From 915a7316c731c04a22ae07e5cef1d4ccf516ab05 Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Tue, 20 Jul 2021 22:10:18 +0200 Subject: [PATCH] init --- .gitignore | 2 + Cargo.toml | 14 ++++++ src/main.rs | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b3e384b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "relmfetch" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.42" +gtk = "0.14.0" +relm = "0.22.0" +relm-derive = "0.22.0" +reqwest = "0.11.4" +tokio = { version = "1.8.2", features = ["macros", "rt-multi-thread", "sync"] } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..9cfdda1 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,137 @@ +use gtk::prelude::*; +use gtk::Inhibit; +use gtk::Orientation; +use relm::{Channel, Relm, Sender, Widget}; +use relm_derive::{widget, Msg}; +use reqwest::Client; +use std::fmt::Debug; +use tokio::sync::mpsc::UnboundedSender; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel(); + let win_handle = tokio::spawn(async { Win::run(tx) }); + let client = Client::new(); + + while let Some(s) = rx.recv().await { + println!("Got msg {:?}", &s); + s.sender.send(Msg::Working(true))?; + match send_request(&client, s.url).await { + Ok(r) => { + s.sender.send(Msg::UpdateText(r))?; + } + Err(e) => { + s.sender.send(Msg::UpdateText(format!("Error!\n{:?}", e)))?; + } + } + s.sender.send(Msg::Working(false))?; + } + + win_handle.await??; + println!("window finished"); + + Ok(()) +} + +async fn send_request(client: &Client, url: String) -> anyhow::Result { + Ok(String::from_utf8( + client.get(url).send().await?.bytes().await?.to_vec(), + )?) +} + +pub struct Model { + tx: UnboundedSender, + _channel: Channel, + sender: Sender, + working: bool, +} + +pub struct RuntimeMsg { + url: String, + sender: Sender, +} + +impl Debug for RuntimeMsg { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("RuntimeMsg") + .field("url", &self.url) + .finish() + } +} + +#[derive(Clone, Msg)] +pub enum Msg { + Quit, + Clicked, + UpdateText(String), + Working(bool), +} + +#[widget] +impl Widget for Win { + fn model(relm: &Relm, tx: UnboundedSender) -> Model { + let stream = relm.stream().clone(); + let (channel, sender) = Channel::new(move |msg| { + stream.emit(msg); + }); + + Model { + _channel: channel, + working: false, + sender, + tx, + } + } + + fn update(&mut self, event: Msg) { + match event { + Msg::Quit => gtk::main_quit(), + Msg::Clicked => { + let msg = RuntimeMsg { + url: self.widgets.input.text().to_string(), + sender: self.model.sender.clone(), + }; + self.model.tx.send(msg).unwrap(); + } + Msg::UpdateText(s) => { + if let Some(buf) = self.widgets.textview.buffer() { + buf.set_text(&s); + } + } + Msg::Working(w) => self.model.working = w, + } + } + + view! { + gtk::Window { + gtk::Box { + orientation: Orientation::Vertical, + + #[name = "input"] + gtk::Entry {}, + + gtk::Box { + orientation: Orientation::Horizontal, + gtk::Button { + label: "Test", + hexpand: true, + clicked => Msg::Clicked, + }, + gtk::Spinner { + active: self.model.working, + }, + }, + gtk::ScrolledWindow { + hexpand: true, + vexpand: true, + + #[name = "textview"] + gtk::TextView { + editable: false, + }, + } + }, + delete_event(_, _) => (Msg::Quit, Inhibit(false)), + } + } +}