diff --git a/Cargo.lock b/Cargo.lock index 2cd0629..a6e1cd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,7 +1159,7 @@ dependencies = [ [[package]] name = "egui-video" version = "0.8.0" -source = "git+https://github.com/v0l/egui-video.git?rev=7e9f8dbc2c7d69dd2f327b18f6dc3687d65129b4#7e9f8dbc2c7d69dd2f327b18f6dc3687d65129b4" +source = "git+https://github.com/v0l/egui-video.git?rev=396d0041b437d2354f7a5d4e61c8ce33a69eb3b2#396d0041b437d2354f7a5d4e61c8ce33a69eb3b2" dependencies = [ "anyhow", "atomic", @@ -1167,14 +1167,12 @@ dependencies = [ "chrono", "cpal", "egui", + "egui_inbox", "ffmpeg-sys-the-third", - "ffmpeg-the-third", - "itertools 0.13.0", "libc", + "log", "nom", - "parking_lot", "ringbuf", - "timer", ] [[package]] @@ -1412,16 +1410,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "ffmpeg-the-third" -version = "2.0.1+ffmpeg-7.0" -source = "git+https://github.com/shssoichiro/ffmpeg-the-third.git?branch=master#fd44dd339be4971c0e32787b42514883ca934997" -dependencies = [ - "bitflags 2.6.0", - "ffmpeg-sys-the-third", - "libc", -] - [[package]] name = "flatbuffers" version = "23.5.26" @@ -4216,15 +4204,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "timer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" -dependencies = [ - "chrono", -] - [[package]] name = "tiny-skia" version = "0.11.4" diff --git a/Cargo.toml b/Cargo.toml index 1ebf86e..0191cbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,8 @@ sha2 = "0.10.8" reqwest = { version = "0.12.7", default-features = false, features = ["rustls-tls-native-roots"] } itertools = "0.13.0" -egui-video = { git = "https://github.com/v0l/egui-video.git", rev = "7e9f8dbc2c7d69dd2f327b18f6dc3687d65129b4" } +egui-video = { git = "https://github.com/v0l/egui-video.git", rev = "396d0041b437d2354f7a5d4e61c8ce33a69eb3b2" } +#egui-video = { path = "../egui-video" } [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.14.1" diff --git a/src/link.rs b/src/link.rs index 12603d3..8939a66 100644 --- a/src/link.rs +++ b/src/link.rs @@ -59,7 +59,7 @@ impl NostrLink { } pub fn from_note(note: &Note<'_>) -> Self { - if note.kind() >= 30_000 && note.kind() < 40_000 { + if note.kind() >= 30_000 && note.kind() < 40_000 && note.get_tag_value("d").and_then(|v| v.variant().str()).is_some() { Self { hrp: NostrLinkType::Coordinate, id: IdOrStr::Str( diff --git a/src/stream_info.rs b/src/stream_info.rs index ddfae48..0ba07d2 100644 --- a/src/stream_info.rs +++ b/src/stream_info.rs @@ -1,5 +1,23 @@ use crate::note_util::NoteUtil; use nostrdb::{NdbStrVariant, Note}; +use std::fmt::{Display, Formatter}; + +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)] +pub enum StreamStatus { + Live, + Ended, + Planned, +} + +impl Display for StreamStatus { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + StreamStatus::Live => write!(f, "Live"), + StreamStatus::Ended => write!(f, "Ended"), + StreamStatus::Planned => write!(f, "Planned"), + } + } +} pub trait StreamInfo { fn title(&self) -> Option<&str>; @@ -14,7 +32,7 @@ pub trait StreamInfo { fn image(&self) -> Option<&str>; - fn status(&self) -> Option<&str>; + fn status(&self) -> StreamStatus; fn viewers(&self) -> Option; } @@ -74,11 +92,15 @@ impl<'a> StreamInfo for Note<'a> { } } - fn status(&self) -> Option<&str> { + fn status(&self) -> StreamStatus { if let Some(s) = self.get_tag_value("status") { - s.variant().str() + match s.variant().str() { + Some("live") => StreamStatus::Live, + Some("planned") => StreamStatus::Planned, + _ => StreamStatus::Ended, + } } else { - None + StreamStatus::Ended } } diff --git a/src/widgets/chat.rs b/src/widgets/chat.rs index 210494e..71360df 100644 --- a/src/widgets/chat.rs +++ b/src/widgets/chat.rs @@ -67,8 +67,8 @@ impl NostrWidget for Chat { ui.vertical(|ui| { ui.spacing_mut().item_spacing.y = 8.0; for ev in events.iter().sorted_by(|a, b| { - a.starts().cmp(&b.starts()) - }) { + a.created_at().cmp(&b.created_at()) + }).tail(20) { ChatMessage::new(&stream, ev, services).ui(ui); } }) diff --git a/src/widgets/stream_list.rs b/src/widgets/stream_list.rs index 93167d9..f8f4862 100644 --- a/src/widgets/stream_list.rs +++ b/src/widgets/stream_list.rs @@ -25,7 +25,8 @@ impl Widget for StreamList<'_> { ui.style_mut().spacing.item_spacing = egui::vec2(0., 20.0); for event in self.streams.iter() .sorted_by(|a, b| { - a.starts().cmp(&b.starts()) + a.status().cmp(&b.status()) + .then(a.starts().cmp(&b.starts()).reverse()) }) { ui.add(StreamEvent::new(event, self.services)); } diff --git a/src/widgets/stream_player.rs b/src/widgets/stream_player.rs index ea70535..a9fa3ac 100644 --- a/src/widgets/stream_player.rs +++ b/src/widgets/stream_player.rs @@ -1,22 +1,18 @@ use crate::widgets::VideoPlaceholder; use egui::{Context, Response, Ui, Vec2, Widget}; -use egui_video::{AudioDevice, Player}; +use egui_video::{Player, PlayerControls}; pub struct StreamPlayer { player: Option, - audio: AudioDevice, } impl StreamPlayer { pub fn new(ctx: &Context, url: &String) -> Self { - let mut audio = AudioDevice::new().unwrap(); + let mut p = Player::new(ctx, url); + p.set_debug(true); + p.start(); Self { - player: Player::new(ctx, url).map_or(None, |mut f| { - f.add_audio(&mut audio).expect("Failed to add audio"); - f.start(); - Some(f) - }), - audio, + player: Some(p) } } } @@ -28,7 +24,7 @@ impl Widget for &mut StreamPlayer { let size = Vec2::new(w, h); if let Some(p) = self.player.as_mut() { - p.ui(ui, size) + ui.add_sized(size, p) } else { VideoPlaceholder.ui(ui) } diff --git a/src/widgets/stream_tile.rs b/src/widgets/stream_tile.rs index 5dd43f7..a6aa733 100644 --- a/src/widgets/stream_tile.rs +++ b/src/widgets/stream_tile.rs @@ -1,6 +1,6 @@ use crate::link::NostrLink; use crate::route::{RouteServices, Routes}; -use crate::stream_info::StreamInfo; +use crate::stream_info::{StreamInfo, StreamStatus}; use crate::theme::{NEUTRAL_500, NEUTRAL_900, PRIMARY}; use crate::widgets::avatar::Avatar; use eframe::epaint::{Rounding, Vec2}; @@ -62,8 +62,8 @@ impl Widget for StreamEvent<'_> { } let overlay_label_pad = Vec2::new(5., 5.); - let live_label_text = self.event.status().unwrap_or("live").to_string().to_uppercase(); - let live_label_color = if live_label_text == "LIVE" { + let live_label_text = self.event.status().to_string().to_uppercase(); + let live_label_color = if self.event.status() == StreamStatus::Live { PRIMARY } else { NEUTRAL_900