From 9868b644c8b70396417a81c23e028e9212934444 Mon Sep 17 00:00:00 2001 From: Vika Date: Thu, 22 Aug 2024 17:49:30 +0300 Subject: Factor out the smart summary button This is a little bit janky in my opinion, because it takes a reference to the buffer which contents its gonna be summarizing. In a perfect world, it would ask the parent component for the text. --- src/components/smart_summary.rs | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/components/smart_summary.rs (limited to 'src/components/smart_summary.rs') diff --git a/src/components/smart_summary.rs b/src/components/smart_summary.rs new file mode 100644 index 0000000..37bbd74 --- /dev/null +++ b/src/components/smart_summary.rs @@ -0,0 +1,84 @@ +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()); + } +} -- cgit 1.4.1