init
This commit is contained in:
commit
915a7316c7
3 changed files with 153 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
Cargo.lock
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal 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
137
src/main.rs
Normal 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)),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue