A bunch of changes
This commit is contained in:
parent
8754520d10
commit
dbdf66012d
@ -6,6 +6,16 @@
|
||||
<summary>Api key</summary>
|
||||
<description>The api key for the current user</description>
|
||||
</key>
|
||||
<key name="profile-url" type="ms">
|
||||
<default>nothing</default>
|
||||
<summary>Profile picture url</summary>
|
||||
<description>The url for the users profile picture</description>
|
||||
</key>
|
||||
<key name="profile-data" type="may">
|
||||
<default>nothing</default>
|
||||
<summary>Profile picture data</summary>
|
||||
<description>The data for the users profile picture</description>
|
||||
</key>
|
||||
<key name="window-size" type="(ii)">
|
||||
<default>(-1,-1)</default>
|
||||
</key>
|
||||
|
@ -14,9 +14,6 @@ template $SettingsPanel : Box {
|
||||
row-homogeneous: true;
|
||||
valign: start;
|
||||
|
||||
Button profile_image_button {
|
||||
has-frame: false;
|
||||
|
||||
Image profile_image {
|
||||
halign: center;
|
||||
icon-name: "user-info-symbolic";
|
||||
@ -24,7 +21,6 @@ template $SettingsPanel : Box {
|
||||
margin-end: 5;
|
||||
valign: center;
|
||||
vexpand: true;
|
||||
}
|
||||
|
||||
layout {
|
||||
column: "0";
|
||||
@ -34,14 +30,6 @@ template $SettingsPanel : Box {
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
Button remove_picture_button {
|
||||
halign: start;
|
||||
valign: center;
|
||||
icon-name: "window-close-symbolic";
|
||||
visible: false;
|
||||
}
|
||||
|
||||
Entry name_label {
|
||||
editable: false;
|
||||
can-focus: false;
|
||||
@ -53,8 +41,6 @@ template $SettingsPanel : Box {
|
||||
styles [
|
||||
"login-title-label",
|
||||
]
|
||||
}
|
||||
|
||||
layout {
|
||||
column: "1";
|
||||
column-span: "1";
|
||||
|
@ -17,6 +17,7 @@ mod imp {
|
||||
pub struct Application {
|
||||
#[property(name = "api-key", type = Option<String>,
|
||||
get = Self::api_key, set = Self::set_api_key, nullable)]
|
||||
#[property(get)]
|
||||
pub settings: RefCell<gio::Settings>,
|
||||
pub context: RefCell<sl::Context>,
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::application;
|
||||
use gtk4 as gtk;
|
||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
||||
use gtk::{glib, gio, gdk, prelude::*, subclass::prelude::*};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
@ -8,6 +8,7 @@ mod imp {
|
||||
use std::cell::RefCell;
|
||||
use glib::subclass::Signal;
|
||||
use once_cell::sync::Lazy;
|
||||
use simplelogin::reqwest;
|
||||
|
||||
#[derive(Debug, Default, glib::Properties, gtk::CompositeTemplate)]
|
||||
#[template(file = "data/settings_panel.blp")]
|
||||
@ -20,12 +21,8 @@ mod imp {
|
||||
#[template_child]
|
||||
pub content: TemplateChild<gtk::Grid>,
|
||||
#[template_child]
|
||||
pub profile_image_button: TemplateChild<gtk::Button>,
|
||||
#[template_child]
|
||||
pub profile_image: TemplateChild<gtk::Image>,
|
||||
#[template_child]
|
||||
pub remove_picture_button: TemplateChild<gtk::Button>,
|
||||
#[template_child]
|
||||
pub name_label: TemplateChild<gtk::Entry>,
|
||||
#[template_child]
|
||||
pub edit_button: TemplateChild<gtk::Button>,
|
||||
@ -149,6 +146,79 @@ mod imp {
|
||||
}
|
||||
}
|
||||
|
||||
fn did_profile_picture_change(
|
||||
new_url: &Option<String>, settings: &gio::Settings
|
||||
) -> bool {
|
||||
let old_url: Option<String> = settings.value("profile-url")
|
||||
.get::<Option<String>>().unwrap();
|
||||
*new_url != old_url
|
||||
}
|
||||
|
||||
fn has_valid_content_type(resp: &reqwest::Response) -> bool {
|
||||
match resp.headers().get("Content-Type") {
|
||||
Some(ct) => match ct.to_str() {
|
||||
Ok("image/png") => true,
|
||||
Ok("image/jpeg") => true,
|
||||
_ => false,
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_profile_picture_response_body(
|
||||
&self, url: &str, resp: reqwest::Response,
|
||||
settings: &gio::Settings
|
||||
) {
|
||||
if let Ok(body) = resp.bytes().await {
|
||||
let tex_res = gdk::Texture::from_bytes(&glib::Bytes::from(body.as_ref()));
|
||||
if let Ok(tex) = tex_res {
|
||||
self.profile_image.get().set_from_paintable(Some(&tex));
|
||||
_ = settings.set("profile-url", Some(url));
|
||||
_ = settings.set("profile-data", Some(body.as_ref()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn download_and_set_profile_picture(
|
||||
&self, url: &str, app: &application::Application
|
||||
) -> bool {
|
||||
let ctx = app.context().borrow();
|
||||
let client = ctx.client();
|
||||
match client.get(url).send().await {
|
||||
Ok(resp) if Self::has_valid_content_type(&resp) => {
|
||||
self.process_profile_picture_response_body(
|
||||
url, resp, &app.settings()).await;
|
||||
false
|
||||
},
|
||||
Ok(_) => false,
|
||||
Err(e) => {
|
||||
self.set_error(Some(&e.to_string()));
|
||||
true
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_user_profile_picture(
|
||||
&self, user_info: &simplelogin::UserInfo,
|
||||
) -> bool {
|
||||
let app = self.application.borrow();
|
||||
let settings = &app.settings();
|
||||
if Self::did_profile_picture_change(&user_info.profile_picture_url,
|
||||
&settings) {
|
||||
self.profile_image.get()
|
||||
.set_from_icon_name(Some("user-info-symbolic"));
|
||||
_ = settings.set("profile-url", Option::<&str>::None);
|
||||
_ = settings.set("profile-data", Option::<&[u8]>::None);
|
||||
match &user_info.profile_picture_url {
|
||||
Some(new_url) => self.download_and_set_profile_picture(
|
||||
&new_url, &app).await,
|
||||
None => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
async fn refresh_user_info(&self) -> bool {
|
||||
let app = self.application.borrow();
|
||||
let mut ctx = app.context().borrow_mut();
|
||||
@ -170,6 +240,8 @@ mod imp {
|
||||
} else {
|
||||
"Free"
|
||||
});
|
||||
drop(ctx);
|
||||
self.refresh_user_profile_picture(&user_info).await;
|
||||
false
|
||||
},
|
||||
Err(e) => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
pub use reqwest;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
@ -63,6 +64,7 @@ struct MfaResponse {
|
||||
struct UserInfoRequest<'a> {
|
||||
api_key: &'a str,
|
||||
profile_picture: Option<&'a str>,
|
||||
name: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@ -148,6 +150,10 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client(&self) -> &reqwest::Client {
|
||||
&self.client
|
||||
}
|
||||
|
||||
pub fn api_key(&self) -> &Option<String> {
|
||||
&self.api_key
|
||||
}
|
||||
@ -304,12 +310,12 @@ impl Context {
|
||||
}
|
||||
|
||||
pub async fn update_user_info(
|
||||
&mut self, profile_picture: Option<&str>
|
||||
&mut self, profile_picture: Option<&str>, name: Option<&str>
|
||||
) -> Result<UserInfo, Error> {
|
||||
match self.api_key.as_ref() {
|
||||
Some(api_key) => {
|
||||
let req_json = Self::obj_to_json(
|
||||
&UserInfoRequest {api_key, profile_picture})?;
|
||||
&UserInfoRequest {api_key, profile_picture, name})?;
|
||||
let res = self.patch_request("api/user_info",
|
||||
Some(&req_json), None).await?;
|
||||
Ok(Self::json_to_obj(&res)?)
|
||||
|
Loading…
Reference in New Issue
Block a user