feat: show toast after upload is finished

This commit is contained in:
uku 2025-05-13 00:01:05 +02:00
parent 3b75134572
commit 1d93482209
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
4 changed files with 336 additions and 59 deletions

196
Cargo.lock generated
View file

@ -26,6 +26,22 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "arboard"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70"
dependencies = [
"clipboard-win",
"log",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"parking_lot",
"percent-encoding",
"x11rb",
]
[[package]] [[package]]
name = "ashpd" name = "ashpd"
version = "0.11.0" version = "0.11.0"
@ -192,6 +208,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "clipboard-win"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
dependencies = [
"error-code",
]
[[package]] [[package]]
name = "color-eyre" name = "color-eyre"
version = "0.6.4" version = "0.6.4"
@ -340,6 +365,12 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "error-code"
version = "3.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "5.4.0" version = "5.4.0"
@ -579,6 +610,16 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "gethostname"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
dependencies = [
"libc",
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.16" version = "0.2.16"
@ -1136,6 +1177,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.9.4" version = "0.9.4"
@ -1280,6 +1327,7 @@ dependencies = [
"bitflags", "bitflags",
"block2", "block2",
"objc2", "objc2",
"objc2-core-graphics",
"objc2-foundation", "objc2-foundation",
] ]
@ -1294,6 +1342,19 @@ dependencies = [
"objc2", "objc2",
] ]
[[package]]
name = "objc2-core-graphics"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
dependencies = [
"bitflags",
"dispatch2 0.3.0",
"objc2",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]] [[package]]
name = "objc2-encode" name = "objc2-encode"
version = "4.1.0" version = "4.1.0"
@ -1311,6 +1372,17 @@ dependencies = [
"objc2-core-foundation", "objc2-core-foundation",
] ]
[[package]]
name = "objc2-io-surface"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
dependencies = [
"bitflags",
"objc2",
"objc2-core-foundation",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.36.7" version = "0.36.7"
@ -1384,6 +1456,29 @@ version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -1555,6 +1650,15 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "redox_syscall"
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "redox_users" name = "redox_users"
version = "0.5.0" version = "0.5.0"
@ -1752,6 +1856,19 @@ dependencies = [
"semver", "semver",
] ]
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "1.0.7" version = "1.0.7"
@ -1761,7 +1878,7 @@ dependencies = [
"bitflags", "bitflags",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys 0.9.4",
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
@ -2032,7 +2149,7 @@ dependencies = [
"fastrand", "fastrand",
"getrandom 0.3.3", "getrandom 0.3.3",
"once_cell", "once_cell",
"rustix", "rustix 1.0.7",
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
@ -2280,6 +2397,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
name = "tyrolienne" name = "tyrolienne"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"arboard",
"color-eyre", "color-eyre",
"dirs", "dirs",
"futures", "futures",
@ -2580,6 +2698,21 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"
@ -2612,6 +2745,12 @@ dependencies = [
"windows_x86_64_msvc 0.53.0", "windows_x86_64_msvc 0.53.0",
] ]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.6" version = "0.52.6"
@ -2624,6 +2763,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.6" version = "0.52.6"
@ -2636,6 +2781,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.6" version = "0.52.6"
@ -2660,6 +2811,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.6" version = "0.52.6"
@ -2672,6 +2829,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.6" version = "0.52.6"
@ -2684,6 +2847,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.6" version = "0.52.6"
@ -2696,6 +2865,12 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.6"
@ -2732,6 +2907,23 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
[[package]]
name = "x11rb"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
dependencies = [
"gethostname",
"rustix 0.38.44",
"x11rb-protocol",
]
[[package]]
name = "x11rb-protocol"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
[[package]] [[package]]
name = "yoke" name = "yoke"
version = "0.8.0" version = "0.8.0"

View file

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
arboard = { version = "3.5.0", default-features = false }
color-eyre = "0.6.4" color-eyre = "0.6.4"
dirs = "6.0.0" dirs = "6.0.0"
futures = "0.3.31" futures = "0.3.31"

View file

@ -6,7 +6,7 @@ use std::{borrow::Cow, path::PathBuf, time::Duration};
use color_eyre::eyre::{OptionExt, Result, bail}; use color_eyre::eyre::{OptionExt, Result, bail};
use gobject::GtkZiplineFolder; use gobject::GtkZiplineFolder;
use relm::{Dialog, DialogInput}; use relm::{Dialog, DialogInput, Toast, ToastInput};
use relm4::{ use relm4::{
Component, ComponentController, Controller, RelmApp, Sender, Component, ComponentController, Controller, RelmApp, Sender,
adw::{self, prelude::*}, adw::{self, prelude::*},
@ -51,7 +51,7 @@ enum Message {
enum ProgressMessage { enum ProgressMessage {
SetTotal(usize), SetTotal(usize),
Progress(usize), Progress(usize),
Finish, Finish(String),
Error(String), Error(String),
} }
@ -69,6 +69,7 @@ struct Tyrolienne {
video_path: Option<PathBuf>, video_path: Option<PathBuf>,
folder: Option<ZiplineFolder>, folder: Option<ZiplineFolder>,
dialog: Controller<Dialog>, dialog: Controller<Dialog>,
toast: Controller<Toast>,
} }
impl Tyrolienne { impl Tyrolienne {
@ -100,63 +101,68 @@ impl AsyncComponent for Tyrolienne {
set_title: Some("Tyrolienne"), set_title: Some("Tyrolienne"),
set_default_width: 500, set_default_width: 500,
gtk::Box { gtk::Box {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_spacing: 0, set_spacing: 0,
adw::HeaderBar {}, adw::HeaderBar {},
gtk::Box { #[local_ref]
set_orientation: gtk::Orientation::Vertical, toast_overlay -> adw::ToastOverlay {
set_spacing: 32,
set_margin_top: 32,
set_margin_bottom: 32,
set_margin_start: 32,
set_margin_end: 32,
gtk::ListBox {
set_selection_mode: gtk::SelectionMode::None,
set_css_classes: &["boxed-list"],
adw::ActionRow {
set_activatable: true,
set_css_classes: &["property"],
set_title: "Video file",
#[watch]
set_subtitle: &model.display_video_path(),
connect_activated => Message::OpenFilePicker,
},
adw::ComboRow {
set_title: "Folder",
set_model: Some(&folder_store),
set_expression: Some(&folder_expression),
connect_activated[sender] => move |r| {
if let Some(item) = r
.selected_item()
.and_then(|i| i.downcast::<GtkZiplineFolder>().ok())
{
sender.input(Message::SetFolder(item.as_folder()));
}
},
}
},
gtk::Box { gtk::Box {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_spacing: 10, set_spacing: 32,
set_margin_top: 32,
set_margin_bottom: 32,
set_margin_start: 32,
set_margin_end: 32,
gtk::ProgressBar { gtk::ListBox {
#[watch] set_selection_mode: gtk::SelectionMode::None,
set_fraction: model.progress as f64 / model.total as f64, set_css_classes: &["boxed-list"],
adw::ActionRow {
set_activatable: true,
set_css_classes: &["property"],
set_title: "Video file",
#[watch]
set_subtitle: &model.display_video_path(),
connect_activated => Message::OpenFilePicker,
},
adw::ComboRow {
set_title: "Folder",
set_model: Some(&folder_store),
set_expression: Some(&folder_expression),
connect_activated[sender] => move |r| {
if let Some(item) = r
.selected_item()
.and_then(|i| i.downcast::<GtkZiplineFolder>().ok())
{
sender.input(Message::SetFolder(item.as_folder()));
}
},
}
}, },
gtk::Button {
#[watch] gtk::Box {
set_label: if model.locked { "Uploading..." } else { "Send" }, set_orientation: gtk::Orientation::Vertical,
#[watch] set_spacing: 10,
set_sensitive: !model.locked && model.video_path.is_some(),
connect_clicked => Message::StartTheProcess, gtk::ProgressBar {
#[watch]
set_fraction: model.progress as f64 / model.total as f64,
},
gtk::Button {
#[watch]
set_label: if model.locked { "Uploading..." } else { "Send" },
#[watch]
set_sensitive: !model.locked && model.video_path.is_some(),
connect_clicked => Message::StartTheProcess,
}
} }
} }
} }
@ -169,6 +175,8 @@ impl AsyncComponent for Tyrolienne {
root: Self::Root, root: Self::Root,
sender: relm4::AsyncComponentSender<Self>, sender: relm4::AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> { ) -> AsyncComponentParts<Self> {
let toast_overlay = adw::ToastOverlay::new();
let model = Tyrolienne { let model = Tyrolienne {
config, config,
locked: false, locked: false,
@ -177,7 +185,10 @@ impl AsyncComponent for Tyrolienne {
video_path: None, video_path: None,
folder: None, folder: None,
dialog: Dialog::builder() dialog: Dialog::builder()
.launch(root.clone()) .launch(toast_overlay.clone())
.forward(sender.input_sender(), |_| Message::Nothing),
toast: Toast::builder()
.launch(toast_overlay.clone())
.forward(sender.input_sender(), |_| Message::Nothing), .forward(sender.input_sender(), |_| Message::Nothing),
}; };
@ -242,10 +253,7 @@ impl AsyncComponent for Tyrolienne {
shutdown shutdown
.register(async move { .register(async move {
match the_process(info, &out).await { match the_process(info, &out).await {
Ok(url) => { Ok(url) => out.emit(ProgressMessage::Finish(url)),
tracing::info!("{url}");
out.emit(ProgressMessage::Finish);
}
Err(e) => out.emit(ProgressMessage::Error(e.to_string())), Err(e) => out.emit(ProgressMessage::Error(e.to_string())),
} }
}) })
@ -265,12 +273,14 @@ impl AsyncComponent for Tyrolienne {
match message { match message {
ProgressMessage::SetTotal(total) => self.total = total, ProgressMessage::SetTotal(total) => self.total = total,
ProgressMessage::Progress(prog) => self.progress += prog, ProgressMessage::Progress(prog) => self.progress += prog,
ProgressMessage::Finish | ProgressMessage::Error(_) => { ProgressMessage::Finish(_) | ProgressMessage::Error(_) => {
self.locked = false; self.locked = false;
self.progress = 0; self.progress = 0;
self.total = 1; self.total = 1;
if let ProgressMessage::Error(e) = message { if let ProgressMessage::Finish(url) = message {
self.toast.emit(ToastInput::Show(url));
} else if let ProgressMessage::Error(e) = message {
self.dialog.emit(DialogInput::Show { self.dialog.emit(DialogInput::Show {
heading: "An error occurred".into(), heading: "An error occurred".into(),
body: e.to_string(), body: e.to_string(),

View file

@ -5,7 +5,9 @@ use relm4::{
}; };
pub struct Dialog { pub struct Dialog {
window: adw::ApplicationWindow, // toast overlay looks like an odd choice but i think it's fitting considering it acts as a
// "box" for the main content
window: adw::ToastOverlay,
visible: bool, visible: bool,
heading: String, heading: String,
body: String, body: String,
@ -22,7 +24,7 @@ pub struct DialogWidgets {
} }
impl SimpleComponent for Dialog { impl SimpleComponent for Dialog {
type Init = adw::ApplicationWindow; type Init = adw::ToastOverlay;
type Root = adw::AlertDialog; type Root = adw::AlertDialog;
type Widgets = DialogWidgets; type Widgets = DialogWidgets;
type Input = DialogInput; type Input = DialogInput;
@ -80,3 +82,75 @@ impl SimpleComponent for Dialog {
} }
} }
} }
pub struct Toast {
root: adw::ToastOverlay,
visible: bool,
text: String,
}
#[derive(Debug)]
pub enum ToastInput {
Show(String),
Copy,
Dismiss,
}
#[relm4::component(pub)]
impl SimpleComponent for Toast {
type Input = ToastInput;
type Output = ();
type Init = adw::ToastOverlay;
view! {
#[name = "toast"]
adw::Toast {
#[watch]
set_title: &model.text,
set_button_label: Some("Copy"),
connect_button_clicked => ToastInput::Copy,
connect_dismissed => ToastInput::Dismiss,
}
}
fn init(
init: Self::Init,
root: Self::Root,
_sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> {
let model = Self {
root: init,
visible: false,
text: String::new(),
};
let widgets = view_output!();
relm4::ComponentParts { model, widgets }
}
fn update(&mut self, message: Self::Input, _sender: relm4::ComponentSender<Self>) {
match message {
ToastInput::Show(text) => {
self.visible = true;
self.text = text;
}
ToastInput::Copy => {
if let Err(e) =
arboard::Clipboard::new().and_then(|mut c| c.set_text(self.text.clone()))
{
tracing::error!("could not copy url to clipboard: {e}");
self.text = "Could not copy".into();
} else {
self.visible = false;
}
}
ToastInput::Dismiss => self.visible = false,
}
}
fn post_view() {
if model.visible {
model.root.add_toast(widgets.toast.clone());
}
}
}