This commit is contained in:
LordMZTE 2021-07-20 22:10:18 +02:00
commit 915a7316c7
3 changed files with 153 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

14
Cargo.toml Normal file
View File

@ -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"] }

137
src/main.rs Normal file
View File

@ -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<String> {
Ok(String::from_utf8(
client.get(url).send().await?.bytes().await?.to_vec(),
)?)
}
pub struct Model {
tx: UnboundedSender<RuntimeMsg>,
_channel: Channel<Msg>,
sender: Sender<Msg>,
working: bool,
}
pub struct RuntimeMsg {
url: String,
sender: Sender<Msg>,
}
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<Self>, tx: UnboundedSender<RuntimeMsg>) -> 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)),
}
}
}