parent
e4191a744d
commit
fa53f0ec76
|
@ -44,14 +44,14 @@ impl RequestContext {
|
|||
|
||||
pub fn get<S: AsRef<str>>(&self, url: S) -> reqwest::RequestBuilder {
|
||||
self.client
|
||||
.get(&format!("https://{}{}", self.instance, url.as_ref()))
|
||||
.get(&format!("{}{}", self.instance, url.as_ref()))
|
||||
.header(reqwest::header::AUTHORIZATION, format!("JWT {}", self.token))
|
||||
}
|
||||
|
||||
/// Warning: no authentication, since it is only used for login
|
||||
pub fn post<S: AsRef<str>>(&self, url: S) -> reqwest::RequestBuilder {
|
||||
self.client
|
||||
.post(&format!("https://{}{}", self.instance, url.as_ref()))
|
||||
.post(&format!("{}{}", self.instance, url.as_ref()))
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> serde_json::Value {
|
||||
|
|
67
src/main.rs
67
src/main.rs
|
@ -70,6 +70,7 @@ mod ui;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct AppState {
|
||||
window: Rc<RefCell<Window>>,
|
||||
stack: Stack,
|
||||
error: InfoBar,
|
||||
header: HeaderBar,
|
||||
|
@ -156,6 +157,24 @@ fn main() {
|
|||
window.set_title("Mobydick");
|
||||
window.set_default_size(1080, 720);
|
||||
|
||||
window.connect_delete_event(move |_, _| {
|
||||
gtk::main_quit();
|
||||
|
||||
fs::create_dir_all(dirs::config_dir().unwrap().join("mobydick")).unwrap();
|
||||
fs::write(
|
||||
dirs::config_dir().unwrap().join("mobydick").join("data.json"),
|
||||
serde_json::to_string(&client!().to_json()).unwrap()
|
||||
).unwrap();
|
||||
|
||||
Inhibit(false)
|
||||
});
|
||||
|
||||
init(Rc::new(RefCell::new(window)));
|
||||
|
||||
gtk::main();
|
||||
}
|
||||
|
||||
fn init(window: Rc<RefCell<Window>>) {
|
||||
let connected = fs::read(dirs::config_dir().unwrap().join("mobydick").join("data.json")).ok().and_then(|f| {
|
||||
let json: serde_json::Value = serde_json::from_slice(&f).ok()?;
|
||||
let mut api_ctx = crate::api::API.lock().ok()?;
|
||||
|
@ -167,6 +186,7 @@ fn main() {
|
|||
}).is_some();
|
||||
|
||||
let state = Rc::new(RefCell::new(AppState {
|
||||
window: window.clone(),
|
||||
stack: {
|
||||
let s = Stack::new();
|
||||
s.set_vexpand(true);
|
||||
|
@ -196,16 +216,20 @@ fn main() {
|
|||
|
||||
let scrolled = ScrolledWindow::new(None, None);
|
||||
scrolled.add(&main_box);
|
||||
window.add(&scrolled);
|
||||
window.set_titlebar(&state.borrow().header);
|
||||
window.show_all();
|
||||
window.borrow().add(&scrolled);
|
||||
window.borrow().set_titlebar(&state.borrow().header);
|
||||
window.borrow().show_all();
|
||||
|
||||
if connected {
|
||||
let main_page = ui::main_page::render(&state.borrow().header, &{
|
||||
let s = StackSwitcher::new();
|
||||
s.set_stack(&state.borrow().stack);
|
||||
s
|
||||
});
|
||||
let main_page = ui::main_page::render(
|
||||
state.borrow().window.clone(),
|
||||
&state.borrow().header,
|
||||
&{
|
||||
let s = StackSwitcher::new();
|
||||
s.set_stack(&state.borrow().stack);
|
||||
s
|
||||
}
|
||||
);
|
||||
state.borrow().stack.add_titled(&main_page, "main", "Search Music");
|
||||
state.borrow().stack.add_titled(&*ui::dl_list::render().borrow(), "downloads", "Downloads");
|
||||
state.borrow().stack.set_visible_child_name("main");
|
||||
|
@ -213,20 +237,6 @@ fn main() {
|
|||
let login_page = ui::login_page::render(state.clone());
|
||||
state.borrow().stack.add_named(&login_page, "login");
|
||||
}
|
||||
|
||||
window.connect_delete_event(move |_, _| {
|
||||
gtk::main_quit();
|
||||
|
||||
fs::create_dir_all(dirs::config_dir().unwrap().join("mobydick")).unwrap();
|
||||
fs::write(
|
||||
dirs::config_dir().unwrap().join("mobydick").join("data.json"),
|
||||
serde_json::to_string(&client!().to_json()).unwrap()
|
||||
).unwrap();
|
||||
|
||||
Inhibit(false)
|
||||
});
|
||||
|
||||
gtk::main();
|
||||
}
|
||||
|
||||
fn show_error(state: State, msg: &str) {
|
||||
|
@ -238,3 +248,16 @@ fn show_error(state: State, msg: &str) {
|
|||
state.borrow().error.show_all();
|
||||
state.borrow().error.set_revealed(true);
|
||||
}
|
||||
|
||||
fn logout(window: Rc<RefCell<Window>>) {
|
||||
fs::remove_file(dirs::config_dir().unwrap().join("mobydick").join("data.json")).ok();
|
||||
*api::API.lock().unwrap() = None;
|
||||
*DOWNLOADS.lock().unwrap() = HashMap::new();
|
||||
{
|
||||
let window = window.borrow();
|
||||
for ch in window.get_children() {
|
||||
window.remove(&ch);
|
||||
}
|
||||
}
|
||||
init(window)
|
||||
}
|
|
@ -25,8 +25,12 @@ pub fn render(state: State) -> gtk::Box {
|
|||
)));
|
||||
login_bt.connect_clicked(clone!(state, widgets => move |_| {
|
||||
let mut api_ctx = crate::api::API.lock().unwrap();
|
||||
let mut instance_url = widgets.borrow().0.get_text().unwrap().trim_end_matches('/').to_string();
|
||||
if !(instance_url.starts_with("http://") || instance_url.starts_with("https://")) {
|
||||
instance_url = format!("https://{}", instance_url)
|
||||
}
|
||||
*api_ctx = Some(RequestContext::new(
|
||||
widgets.borrow().0.get_text().unwrap()
|
||||
instance_url
|
||||
));
|
||||
|
||||
let state = state.clone();
|
||||
|
@ -45,11 +49,16 @@ pub fn render(state: State) -> gtk::Box {
|
|||
|
||||
let state = state.borrow();
|
||||
state.error.set_revealed(false);
|
||||
state.stack.add_titled(&crate::ui::main_page::render(&state.header, &{
|
||||
let s = StackSwitcher::new();
|
||||
s.set_stack(&state.stack);
|
||||
s
|
||||
}), "main", "Search Music");
|
||||
state.stack.add_titled(&crate::ui::main_page::render(
|
||||
state.window.clone(),
|
||||
&state.header,
|
||||
&{
|
||||
let s = StackSwitcher::new();
|
||||
s.set_stack(&state.stack);
|
||||
s
|
||||
}
|
||||
),
|
||||
"main", "Search Music");
|
||||
state.stack.set_visible_child_name("main");
|
||||
state.stack.add_titled(&*crate::ui::dl_list::render().borrow(), "downloads", "Downloads");
|
||||
state.stack.remove(&state.stack.get_child_by_name("login").unwrap()); // To avoid having a "Login" tab in the header
|
||||
|
@ -59,11 +68,25 @@ pub fn render(state: State) -> gtk::Box {
|
|||
});
|
||||
}));
|
||||
|
||||
cont.add(&title);
|
||||
cont.add(&widgets.borrow().0.render());
|
||||
cont.add(&widgets.borrow().1.render());
|
||||
cont.add(&widgets.borrow().2.render());
|
||||
cont.add(&login_bt);
|
||||
{
|
||||
|
||||
let (ref instance, ref username, ref password) = *widgets.borrow();
|
||||
cont.add(&title);
|
||||
cont.add(&instance.render());
|
||||
cont.add(&username.render());
|
||||
cont.add(&password.render());
|
||||
cont.add(&login_bt);
|
||||
}
|
||||
|
||||
widgets.borrow().0.entry.connect_activate(clone!(widgets => move |_| {
|
||||
widgets.borrow().1.entry.grab_focus();
|
||||
}));
|
||||
widgets.borrow().1.entry.connect_activate(clone!(widgets => move |_| {
|
||||
widgets.borrow().2.entry.grab_focus();
|
||||
}));
|
||||
widgets.borrow().2.entry.connect_activate(move |_| {
|
||||
login_bt.clicked();
|
||||
});
|
||||
|
||||
cont.show_all();
|
||||
cont
|
||||
|
|
|
@ -2,11 +2,13 @@ use gdk::ContextExt;
|
|||
use gdk_pixbuf::PixbufExt;
|
||||
use gtk::*;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
fs,
|
||||
rc::Rc,
|
||||
};
|
||||
use crate::{api::{self, execute}, ui::{title, card}};
|
||||
|
||||
pub fn render(header: &HeaderBar, switcher: &StackSwitcher) -> gtk::Box {
|
||||
pub fn render(window: Rc<RefCell<Window>>, header: &HeaderBar, switcher: &StackSwitcher) -> gtk::Box {
|
||||
let cont = gtk::Box::new(Orientation::Vertical, 12);
|
||||
cont.set_margin_top(48);
|
||||
cont.set_margin_bottom(48);
|
||||
|
@ -50,6 +52,12 @@ pub fn render(header: &HeaderBar, switcher: &StackSwitcher) -> gtk::Box {
|
|||
}));
|
||||
header.pack_start(&avatar);
|
||||
header.set_custom_title(&*switcher);
|
||||
|
||||
let logout_bt = Button::new_from_icon_name("system-log-out", IconSize::LargeToolbar.into());
|
||||
logout_bt.connect_clicked(clone!(window => move |_| {
|
||||
crate::logout(window.clone());
|
||||
}));
|
||||
header.pack_end(&logout_bt);
|
||||
header.show_all();
|
||||
|
||||
let search = SearchEntry::new();
|
||||
|
@ -63,17 +71,23 @@ pub fn render(header: &HeaderBar, switcher: &StackSwitcher) -> gtk::Box {
|
|||
rc!(avatar, results);
|
||||
clone!(avatar, results, avatar_path);
|
||||
wait!(execute(client!().get("/api/v1/users/users/me")) => |res| {
|
||||
let res: api::UserInfo = res.json().unwrap();
|
||||
let res: Result<api::UserInfo, _> = res.json();
|
||||
match res {
|
||||
Ok(res) => {
|
||||
avatar.borrow().set_tooltip_text(format!("Connected as {}.", res.username).as_ref());
|
||||
|
||||
avatar.borrow().set_tooltip_text(format!("Connected as {}.", res.username).as_ref());
|
||||
|
||||
clone!(avatar_path, avatar);
|
||||
wait!(execute(client!().get(&res.avatar.medium_square_crop.unwrap_or_default())) => |avatar_dl| {
|
||||
fs::create_dir_all(avatar_path.parent().unwrap()).unwrap();
|
||||
let mut avatar_file = fs::File::create(avatar_path.clone()).unwrap();
|
||||
avatar_dl.copy_to(&mut avatar_file).unwrap();
|
||||
avatar.borrow().queue_draw();
|
||||
});
|
||||
clone!(avatar_path, avatar);
|
||||
wait!(execute(client!().get(&res.avatar.medium_square_crop.unwrap_or_default())) => |avatar_dl| {
|
||||
fs::create_dir_all(avatar_path.parent().unwrap()).unwrap();
|
||||
let mut avatar_file = fs::File::create(avatar_path.clone()).unwrap();
|
||||
avatar_dl.copy_to(&mut avatar_file).unwrap();
|
||||
avatar.borrow().queue_draw();
|
||||
});
|
||||
},
|
||||
Err(_) => {
|
||||
crate::logout(window.clone());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
search.connect_activate(move |s| {
|
||||
|
|
Loading…
Reference in New Issue