This commit is contained in:
Robin Appelman 2023-04-08 22:53:21 +02:00
commit 82a82d2aff
7 changed files with 152 additions and 43 deletions

35
src/data/chat.rs Normal file
View file

@ -0,0 +1,35 @@
use crate::data::demo::Duration;
use crate::Result;
use sqlx::{query_as, Executor, Postgres};
use tracing::instrument;
#[derive(Debug)]
pub struct Chat {
pub from: String,
pub text: String,
pub time: i32,
}
impl Chat {
#[instrument(skip(connection))]
pub async fn for_demo(
connection: impl Executor<'_, Database = Postgres>,
id: u32,
) -> Result<Vec<Chat>> {
Ok(query_as!(
Chat,
r#"SELECT
"from", text, time
FROM chat
WHERE demo_id = $1
ORDER BY time ASC"#,
id as i32
)
.fetch_all(connection)
.await?)
}
pub fn time(&self) -> Duration {
Duration(self.time)
}
}

View file

@ -1,3 +1,4 @@
use crate::data::chat::Chat;
use crate::data::player::Player;
use crate::data::steam_id::SteamId;
use crate::Result;
@ -27,6 +28,7 @@ pub struct Demo {
pub nick: String,
pub player_count: i32,
pub players: Vec<Player>,
pub chat: Vec<Chat>,
}
impl Demo {
@ -76,6 +78,7 @@ impl Demo {
};
let players = Player::for_demo(connection, id).await?;
let chat = Chat::for_demo(connection, id).await?;
Ok(Some(Demo {
id: raw.id,
@ -96,6 +99,7 @@ impl Demo {
nick: raw.nick,
player_count: raw.player_count,
players,
chat,
}))
}
@ -117,6 +121,22 @@ impl Demo {
.or(self.uploader_name.as_deref())
.unwrap_or("unknown")
}
pub fn duration(&self) -> Duration {
Duration(self.duration)
}
pub fn viewer_url(&self) -> ViewerUrl {
ViewerUrl(self.id)
}
}
pub struct ViewerUrl(i32);
impl Render for ViewerUrl {
fn render_to(&self, buffer: &mut String) {
write!(buffer, "/viewer/{}", self.0).unwrap()
}
}
#[derive(Debug, FromRow)]
@ -232,7 +252,7 @@ impl Render for DemoFormat {
}
}
pub struct Duration(i32);
pub struct Duration(pub i32);
impl Render for Duration {
fn render_to(&self, buffer: &mut String) {

View file

@ -1,3 +1,4 @@
pub mod chat;
pub mod demo;
pub mod player;
pub mod steam_id;

View file

@ -89,6 +89,28 @@ impl Page for DemoPage {
}
}
}
p.demo-info {
span { (self.demo.map) }
span.time { (self.demo.duration()) }
}
p.demo-download {
a.button.button-primary href = (self.demo.url) download = (self.demo.name) { "Download" }
a.button href = (self.demo.viewer_url()) { "View" }
details.chat {
summary.button.button-tertiary { "Toggle Chat" }
div {
table.chat {
@for chat in &self.demo.chat {
tr {
td.user { (chat.from) }
td.message { (chat.text) }
td.duration { (chat.time()) }
}
}
}
}
}
}
}
}
}

View file

@ -216,3 +216,40 @@ table.players {
background-color: #5b818f66;
}
}
table.chat {
& td {
padding: 0 6px;
}
& td.user {
white-space: nowrap;
vertical-align: top;
width: 20%;
color: var(--text-secondary);
text-align: right;
border-right: 1px solid #ccc;
}
& td.message {
word-break: break-all;
}
& td.duration {
width: 80px;
text-align: right;
color: var(--text-secondary);
}
}
details.chat {
margin-top: -55px;
& > summary {
float: right;
}
& > div {
padding-top: 45px;
}
}

35
style/pure.css Normal file
View file

@ -0,0 +1,35 @@
.button {
border-radius: 0;
min-width: 150px;
display: inline-block;
zoom: 1;
line-height: normal;
white-space: nowrap;
vertical-align: middle;
text-align: center;
cursor: pointer;
border: none;
-webkit-user-drag: none;
font-family: inherit;
font-size: 100%;
padding: .5em 1em;
color: var(--text-primary);
background-color: #E6E6E6;
text-decoration: none;
}
.button:hover {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0.1)), to(rgba(0, 0, 0, 0.1)));
background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0.1));
background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
}
.button-primary {
background-color: var(--button-primary);
}
.button-tertiary, .button-tertiary:hover {
color: var(--text-secondary);
background-color: transparent;
text-decoration: underline;
}

View file

@ -1,5 +1,6 @@
@import 'header.css';
@import 'footer.css';
@import 'pure.css';
@import 'pages/index.css';
@import 'pages/demo.css';
@ -154,48 +155,6 @@ pre {
float: right;
}
.pure-button {
border-radius: 0;
min-width: 150px;
}
.pure-button-primary, .pure-button-selected, a.pure-button-primary, a.pure-button-selected {
background-color: var(--button-primary);
color: var(--text-primary);
}
.pure-button {
display: inline-block;
zoom: 1;
line-height: normal;
white-space: nowrap;
vertical-align: middle;
text-align: center;
cursor: pointer;
border: none;
-webkit-user-drag: none;
font-family: inherit;
font-size: 100%;
padding: .5em 1em;
color: rgba(0, 0, 0, 0.8);
background-color: #E6E6E6;
text-decoration: none;
min-width: 150px;
&.pure-button-tertiary {
background-color: transparent;
text-decoration: underline;
color: var(--text-secondary);
}
}
.pure-button:hover {
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#1a000000', endColorstr='#1a000000', GradientType=0);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(rgba(0, 0, 0, 0.1)), to(rgba(0, 0, 0, 0.1)));
background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0.1));
background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
}
.button-delete {
background: var(--button-critical);
color: var(--primary-color);