Work on logging out

This commit is contained in:
Alexander Rosenberg 2023-10-25 02:55:33 -07:00
parent 6cd5280713
commit 04fbed2c3a
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
4 changed files with 118 additions and 8 deletions

View File

@ -104,6 +104,7 @@ template $SettingsPanel : Box {
halign: start;
label: "Logout";
valign: center;
clicked => $logout_clicked() swapped;
layout {
column: "2";
@ -231,6 +232,7 @@ template $SettingsPanel : Box {
halign: center;
icon-name: "window-close-symbolic";
valign: end;
clicked => $close_error_clicked() swapped;
styles [
"loading-label",

View File

@ -48,25 +48,39 @@ mod imp {
login_window.present();
}
fn close_window_for_widget<P: glib::IsA<gtk::Widget>>(widget: &P) {
if let Some(win) = get_window_ancestor(widget) {
win.close();
}
}
fn activate_has_api_key(&self) {
let obj = &self.obj();
let main_panel = MainPanel::new(obj);
let settings_panel = SettingsPanel::new(obj);
let settings_panel: gtk::Widget = SettingsPanel::new(obj).upcast();
let window = TabbedWindow::new(obj,
&[("Aliases", &main_panel.upcast()),
("Settings", &settings_panel.clone().upcast())]);
let window_closure = window.clone();
("Settings", &settings_panel)]);
settings_panel.connect_closure(
"api-key-cleared", false,
closure_local!(@weak-allow-none self as opt_this
=> move |_: SettingsPanel| {
window_closure.close();
=> move |panel: SettingsPanel| {
Self::close_window_for_widget(&panel);
if let Some(this) = opt_this {
this.context.borrow_mut().set_api_key(None);
this.set_api_key(None);
this.activate_no_api_key();
}
}));
settings_panel.connect_closure(
"logged-out", false,
closure_local!(@weak-allow-none self as opt_this
=> move |panel: SettingsPanel| {
Self::close_window_for_widget(&panel);
if let Some(this) = opt_this {
this.set_api_key(None);
this.activate_no_api_key();
}
}));
window.present();
}
}
@ -130,3 +144,13 @@ impl Default for Application {
Self::new(crate::APP_ID)
}
}
pub fn get_window_ancestor<P: glib::IsA<gtk::Widget>>(
widget: &P
) -> Option<gtk::Window> {
let root_opt = widget.root()?;
match root_opt.downcast::<gtk::Window>() {
Ok(win) => Some(win),
Err(_) => None,
}
}

View File

@ -4,6 +4,7 @@ use gtk::{glib, prelude::*, subclass::prelude::*};
mod imp {
use super::*;
use glib::clone;
use std::cell::RefCell;
use glib::subclass::Signal;
use once_cell::sync::Lazy;
@ -60,8 +61,69 @@ mod imp {
impl SettingsPanel {
#[template_callback]
fn clear_api_key_clicked(&self, _: &gtk::Button) {
// TODO ensure user is prompted before clear
self.obj().emit_by_name::<()>("api-key-cleared", &[]);
let main_loop = glib::MainContext::default();
main_loop.spawn_local(clone!(@weak self as this => async move {
let alert_diag = gtk::AlertDialog::builder()
.message("Are you sure you would like to clear the API key?")
.buttons(["Yes", "No"]).build();
let widget_this = application::get_window_ancestor(
&this.obj().clone().upcast::<gtk::Widget>());
let resp = alert_diag.choose_future(widget_this.as_ref()).await;
if let Ok(resp_num) = resp {
if resp_num == 0 {
let app = this.application.borrow();
app.context().borrow_mut().set_api_key(None);
this.obj().emit_by_name::<()>("api-key-cleared", &[]);
}
}
}));
}
fn set_is_loading(&self, loading: bool) {
if loading {
self.set_error(None);
}
self.loading_overlay.get().set_visible(loading);
self.content_wrapper.get().set_sensitive(!loading);
}
fn set_error(&self, error: Option<&str>) {
if let Some(e) = error {
self.set_is_loading(false);
self.error_label.get().set_text(e);
}
self.content_wrapper.get().set_sensitive(error.is_none());
self.error_overlay.get().set_visible(error.is_some());
}
#[template_callback]
fn logout_clicked(&self, _: &gtk::Button) {
let main_loop = glib::MainContext::default();
main_loop.spawn_local(clone!(@weak self as this => async move {
let alert_diag = gtk::AlertDialog::builder()
.message("Are you sure you would like to log out?")
.buttons(["Yes", "No"]).build();
let widget_this = application::get_window_ancestor(
&this.obj().clone().upcast::<gtk::Widget>());
let resp = alert_diag.choose_future(widget_this.as_ref()).await;
if let Ok(resp_num) = resp {
if resp_num == 0 {
let app = this.application.borrow();
let mut context = app.context().borrow_mut();
let res = context.logout().await;
drop(context);
match res {
Ok(_) => this.obj().emit_by_name::<()>("logged-out", &[]),
Err(err) => this.set_error(Some(err.to_string().as_str())),
}
}
}
}));
}
#[template_callback]
fn close_error_clicked(&self, _: &gtk::Button) {
self.set_error(None);
}
}

View File

@ -161,6 +161,16 @@ impl Context {
}
}
async fn get_request(
&mut self, endpoint: &str, headers: &[(&str, &str)]
) -> Result<String, Error> {
let mut builder = self.client.get(self.url.to_owned() + endpoint);
for header in headers {
builder = builder.header(header.0, header.1);
}
Self::perform_request(builder).await
}
async fn post_request(
&mut self, endpoint: &str, body: &str
) -> Result<String, Error> {
@ -228,4 +238,16 @@ impl Context {
Err(Error::new(ErrorKind::State, "No login operation in progress"))
}
}
pub async fn logout(&mut self) -> Result<(), Error> {
match self.api_key.as_ref() {
Some(api_key) => {
self.get_request("api/logout",
&[("Authentication", api_key.clone().as_str())]).await?;
self.api_key = None;
Ok(())
},
None => Err(Error::new(ErrorKind::State, "Not logged in")),
}
}
}