use adw::prelude::*; use relm4::{gtk, prelude::{AsyncComponent, AsyncComponentParts}, AsyncComponentSender}; #[derive(Debug, Default)] pub(crate) struct SmartSummaryButton { content_buffer: gtk::TextBuffer, busy: bool, } #[derive(Debug, thiserror::Error)] pub(crate) enum Error { } #[derive(Debug)] pub(crate) enum Output { Start, Chunk(String), Done, Error(Error) } #[relm4::component(pub(crate) async)] impl AsyncComponent for SmartSummaryButton { type Input = (); type Output = Output; type Init = gtk::TextBuffer; type CommandOutput = (); view! { #[root] #[name = "button"] gtk::Button { connect_clicked => (), #[watch] set_sensitive: !model.busy, set_tooltip_markup: Some("Smart Summary\nAsk a language model for a single-sentence summary."), if model.busy { gtk::Spinner { set_spinning: true } } else { gtk::Label { set_markup: "✨" } } } } async fn init(init: Self::Init, root: Self::Root, sender: AsyncComponentSender) -> AsyncComponentParts { let model = SmartSummaryButton { content_buffer: init, ..Default::default() }; let widgets = view_output!(); AsyncComponentParts { model, widgets } } async fn update_with_view(&mut self, widgets: &mut Self::Widgets, _msg: Self::Input, sender: AsyncComponentSender, _root: &Self::Root) { log::debug!("Starting Smart Summary generation"); self.busy = true; let _ = sender.output(Output::Start); self.update_view(widgets, sender.clone()); let text = self.content_buffer.text( &self.content_buffer.start_iter(), &self.content_buffer.end_iter(), false ); log::debug!("Would generate summary for the following text:\n{}", text); tokio::time::sleep(std::time::Duration::from_millis(450)).await; for i in ["I'", "m ", "sorry,", " I", " am ", "unable", " to", " ", "write", " you ", "a summary.", " I", " am", " not ", "really ", "an ", "LLM."] { tokio::time::sleep(std::time::Duration::from_millis(100)).await; let _ = sender.output(Output::Chunk(i.to_string())); } log::debug!("Done with the summary."); self.busy = false; let _ = sender.output(Output::Done); self.update_view(widgets, sender.clone()); } }