From 355f92037aedd63951adcba33e67e453b23abab7 Mon Sep 17 00:00:00 2001 From: Sythos Date: Thu, 8 Oct 2026 10:13:30 +0200 Subject: [PATCH] Open chat media links in a popup over the chat --- crates/cordiale-ui/src/main.rs | 4 +-- crates/cordiale-ui/ui/appwindow.slint | 44 +++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/crates/cordiale-ui/src/main.rs b/crates/cordiale-ui/src/main.rs index 8a63284..743ed52 100644 --- a/crates/cordiale-ui/src/main.rs +++ b/crates/cordiale-ui/src/main.rs @@ -8204,7 +8204,7 @@ fn link_refused(ui: &slint::Weak, refusal: cordiale_core::media::Link ui.set_media_error(reason.into()); ui.set_media_kind("failed".into()); ui.set_media_zoom(false); - ui.set_screen("media".into()); + ui.set_media_open(true); }); } @@ -8237,7 +8237,7 @@ fn open_link(state: &WorkerState, ui: &slint::Weak, href: String) { ui.set_media_title(title.into()); ui.set_media_kind("loading".into()); ui.set_media_zoom(false); - ui.set_screen("media".into()); + ui.set_media_open(true); }); let ui = ui.clone(); tokio::spawn(async move { diff --git a/crates/cordiale-ui/ui/appwindow.slint b/crates/cordiale-ui/ui/appwindow.slint index 407e908..c1fe76d 100644 --- a/crates/cordiale-ui/ui/appwindow.slint +++ b/crates/cordiale-ui/ui/appwindow.slint @@ -925,7 +925,8 @@ export component AppWindow inherits Window { chat-resume = false; } } else { - chat-resume = screen == "media" || screen == "settings" || screen == "links" || screen == "archive" || screen == "reply" || screen == "umodes" || screen == "radio" || screen == "debug"; + media-open = false; + chat-resume = screen == "settings" || screen == "links" || screen == "archive" || screen == "reply" || screen == "umodes" || screen == "radio" || screen == "debug"; } } // Set once by Rust before the window is shown: where the splash @@ -1579,6 +1580,8 @@ export component AppWindow inherits Window { in property media-text: ""; in property media-truncated: false; in-out property media-zoom: false; + // The viewer is a popup over the connected screen, not a screen of its own. + in-out property media-open: false; // The integrated radio. `radio-status` is "", "connecting", "playing", // "failed" or "ended"; the custom stations live in Settings > Radio. in property <[RadioRow]> radio-stations: []; @@ -7274,7 +7277,39 @@ export component AppWindow inherits Window { } } - if screen == "media" : VerticalBox { + // The media viewer: a popup over the chat, which stays where it is + // behind it. Escape or Close dismisses it. + if media-open : Rectangle { + width: parent.width; + height: parent.height; + background: #00000099; + + TouchArea { + width: parent.width; + height: parent.height; + } + + Rectangle { + width: min(900px, parent.width - 32px); + height: parent.height - 32px; + x: (parent.width - self.width) / 2; + y: 16px; + border-width: 1px; + border-radius: 8px; + border-color: #8080806a; + background: theme == "dark" ? #242424 : white; + + FocusScope { + init => { self.focus(); } + key-pressed(event) => { + if event.text == Key.Escape { + media-open = false; + return accept; + } + return reject; + } + + VerticalBox { padding: 16px; spacing: 8px; @@ -7299,7 +7334,7 @@ export component AppWindow inherits Window { } CompactButton { text: "✕ " + @tr("Close"); - clicked => { screen = "connected"; } + clicked => { media-open = false; } } } @@ -7360,6 +7395,9 @@ export component AppWindow inherits Window { } } } + } + } + } if screen == "archive" : VerticalBox { padding: 16px;