prepare for private demos

This commit is contained in:
Robin Appelman 2025-04-02 20:37:03 +02:00
commit ffb230045c
6 changed files with 58 additions and 14 deletions

View file

@ -40,6 +40,7 @@ pub struct Demo {
pub player_count: i32,
pub players: Vec<Player>,
pub chat: Vec<Chat>,
pub private_until: Option<OffsetDateTime>,
}
impl Debug for Demo {
@ -74,6 +75,7 @@ impl Demo {
pub server: String,
pub nick: String,
pub player_count: i32,
pub private_until: Option<OffsetDateTime>,
}
let Some(raw) = query_as!(
@ -84,7 +86,8 @@ impl Demo {
"playerCount" as player_count,
users_named.name as uploader_name_preferred,
users.steamid as "uploader_steam_id?: SteamId",
users.name as "uploader_name?"
users.name as "uploader_name?",
demos.private_until
FROM demos
LEFT JOIN users_named ON uploader = users_named.id
LEFT JOIN users ON uploader = users.id
@ -120,6 +123,7 @@ impl Demo {
player_count: raw.player_count,
players,
chat,
private_until: raw.private_until,
}))
}
@ -149,6 +153,37 @@ impl Demo {
pub fn viewer_url(&self) -> ViewerUrl {
ViewerUrl(self.id)
}
pub fn is_private(&self) -> bool {
if let Some(private_until) = self.private_until {
let now = OffsetDateTime::now_utc();
now < private_until
} else {
false
}
}
pub fn url(&self) -> &str {
if self.is_private() {
""
} else {
self.url.as_str()
}
}
pub fn private_until_text(&self) -> Cow<'static, str> {
if let Some(private_until) = self.private_until {
let now = OffsetDateTime::now_utc();
let days = (private_until - now).whole_days();
if days <= 1 {
"by tomorrow".into()
} else {
format!("in {days} days").into()
}
} else {
"".into()
}
}
}
pub struct ViewerUrl(i32);

View file

@ -23,7 +23,9 @@ impl Page for DemoPage {
fn render(&self) -> Markup {
let style_url = ClassIconsStyle::url();
html! {
@if self.demo.url.is_empty() {
@if self.demo.is_private() {
h3.warning { "This demo is private, it will be available for download " (self.demo.private_until_text()) }
} @else if self.demo.url.is_empty() {
h3.warning { "This demo has been deleted and is no longer available for download." }
}
h2 { (self.demo.server) " - " (self.demo.red) " vs " (self.demo.blu) }
@ -104,8 +106,8 @@ impl Page for DemoPage {
span.time { (self.demo.duration()) }
}
p.demo-download {
@if !self.demo.url.is_empty() {
a.button.button-primary href = (self.demo.url) download = (self.demo.name) rel = "nofollow" { "Download" }
@if !self.demo.url().is_empty() {
a.button.button-primary href = (self.demo.url()) download = (self.demo.name) rel = "nofollow" { "Download" }
a.button href = (self.demo.viewer_url()) rel = "nofollow" { "View" }
}
@if !self.demo.chat.is_empty() {

View file

@ -53,8 +53,12 @@ impl Page for ViewerPage<'_> {
html! {
.viewer-page data-maps = (maps) data-sync = (sync) {
@if let Some(demo) = self.demo.as_ref() {
input type = "hidden" name = "url" value = (demo.url) {}
progress.download min = "0" max = "100" value = "0" {}
@if demo.is_private() {
h3.warning { "This demo is private, it will be available for download " (demo.private_until_text()) }
} @else {
input type = "hidden" name = "url" value = (demo.url) {}
progress.download min = "0" max = "100" value = "0" {}
}
} @else {
.dropzone role = "button" {
noscript {