Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add logout feature #293

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/icons/logout.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ impl MatchEvent for App {
self.ui.redraw(cx);
}

if let Some(LoginAction::Logout) = action.downcast_ref() {
self.app_state.logged_in = false;
self.update_login_visibility();
self.ui.redraw(cx);
}

match action.as_widget_action().cast() {
// A room has been selected, update the app state and navigate to the main content view.
RoomListAction::Selected {
Expand Down
72 changes: 63 additions & 9 deletions src/home/spaces_dock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use makepad_widgets::*;
use matrix_sdk::encryption::VerificationState;

use crate::shared::adaptive_view::DisplayContext;
use crate::sliding_sync::get_client;
use crate::sliding_sync::{get_client, submit_async_request, MatrixRequest};
use crate::verification::VerificationStateAction;

live_design! {
Expand All @@ -17,6 +17,7 @@ live_design! {

ICON_HOME = dep("crate://self/resources/icons/home.svg")
ICON_SETTINGS = dep("crate://self/resources/icons/settings.svg")
ICON_LOGOUT = dep("crate://self/resources/icons/logout.svg")

Filler = <View> {
height: Fill, width: Fill
Expand Down Expand Up @@ -102,6 +103,30 @@ live_design! {
}
}

Logout = {{Logout}} {
width: Fit, height: Fit
padding: {top: 8, left: 8, right: 12, bottom: 8}
align: {x: 0.5, y: 0.5}
logout_button = <Button> {
draw_bg: {
fn pixel(self) -> vec4 {
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
return sdf.result
}
}

draw_icon: {
svg_file: (ICON_LOGOUT),
fn get_color(self) -> vec4 {
return (COLOR_DANGER_RED);
// return #x566287; // grayed-out #1C274C until enabled
}
}

icon_walk: {width: 25, height: Fit}
}
}

Settings = <View> {
width: Fit, height: Fit
// FIXME: the extra padding on the right is because the icon is not correctly centered
Expand Down Expand Up @@ -146,6 +171,8 @@ live_design! {

<Filler> {}

<Logout> {}

<Settings> {}
}

Expand Down Expand Up @@ -253,7 +280,7 @@ impl Widget for Profile {
}
}

self.match_event(cx, event);
self.widget_match_event(cx, event, scope);
self.view.handle_event(cx, event, scope)
}

Expand All @@ -262,14 +289,17 @@ impl Widget for Profile {
}
}

impl MatchEvent for Profile {
fn handle_action(&mut self, cx: &mut Cx, action:&Action) {
if let Some(VerificationStateAction::Update(state)) = action.downcast_ref() {
if self.verification_state != *state {
self.verification_state = *state;
impl WidgetMatchEvent for Profile {
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) {

self.set_verification_icon_visibility();
self.redraw(cx);
for action in actions {
if let Some(VerificationStateAction::Update(state)) = action.downcast_ref() {
if self.verification_state != *state {
self.verification_state = *state;

self.set_verification_icon_visibility();
self.redraw(cx);
}
}
}
}
Expand All @@ -286,3 +316,27 @@ impl LiveHook for Profile {
}
}
}

#[derive(Live, LiveHook, Widget)]
pub struct Logout {
#[deref] view: View
}

impl Widget for Logout {
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
self.widget_match_event(cx, event, scope);
self.view.handle_event(cx, event, scope)
}

fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
self.view.draw_walk(cx, scope, walk)
}
}

impl WidgetMatchEvent for Logout {
fn handle_actions(&mut self, _cx: &mut Cx, actions:&Actions, _scope: &mut Scope) {
if self.button(id!(logout_button)).clicked(actions) {
submit_async_request(MatrixRequest::Logout);
}
}
}
4 changes: 4 additions & 0 deletions src/login/login_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ impl MatchEvent for LoginScreen {
status_label.set_text("");
self.redraw(cx);
}
Some(LoginAction::Logout) => {
status_label.set_text("");
}
_ => {

}
Expand Down Expand Up @@ -519,4 +522,5 @@ pub enum LoginAction {
/// inform the login screen which SSO identity providers it should display to the user.
IdentityProvider(Vec<IdentityProvider>),
None,
Logout,
}
19 changes: 19 additions & 0 deletions src/persistent_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ async fn save_latest_user_id(user_id: &UserId) -> anyhow::Result<()> {
}


pub async fn delete_session(user_id: Option<OwnedUserId>) -> anyhow::Result<()> {
let Some(user_id) = user_id.or_else(most_recent_user_id) else {
log!("Could not find previous latest User ID");
bail!("Could not find previous latest User ID");
};
let session_file = session_file_path(&user_id);
if !session_file.exists() {
log!("Could not find previous session file for user {user_id}");
bail!("Could not find previous session file");
}
if let Err(err) = fs::remove_file(&session_file).await {
log!("Failed to delete session file {}: {}", session_file.display(), err);
bail!("Failed to delete session file");
} else {
log!("Successfully deleted session file: {}", session_file.display());
}
Ok(())
}

/// Restores the given user's previous session from the filesystem.
///
/// If no User ID is specified, the ID of the most recently-logged in user
Expand Down
31 changes: 31 additions & 0 deletions src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,30 @@ async fn login(
}
}

/// Log out the current user.
async fn logout() {
if let Ok((client, _sync_token)) = persistent_state::restore_session(None).await {
match persistent_state::delete_session(None).await {
Ok(_) => {
match client.matrix_auth().logout().await {
Ok(_) => {
Cx::post_action(LoginAction::Logout);
},
Err(_err) => {
log!("http error")
}
}
},
Err(_) => {
log!("log out failed, fail to delete session_token, please trt again.")
}
}
} else {
let status_err = "Failed to restore previous user session. Please try later.";
log!("{status_err}");
}
}

async fn populate_login_types(
homeserver_url: &str,
login_types: &mut Vec<LoginType>,
Expand Down Expand Up @@ -258,6 +282,10 @@ pub type OnMediaFetchedFn = fn(
pub enum MatrixRequest {
/// Request from the login screen to log in with the given credentials.
Login(LoginRequest),

/// Request to logout.
Logout,

/// Request to paginate the older (or newer) events of a room's timeline.
PaginateRoomTimeline {
room_id: OwnedRoomId,
Expand Down Expand Up @@ -404,6 +432,9 @@ async fn async_worker(
)));
}
}
MatrixRequest::Logout => {
logout().await
}
MatrixRequest::PaginateRoomTimeline { room_id, num_events, direction } => {
let (timeline, sender) = {
let mut all_room_info = ALL_ROOM_INFO.lock().unwrap();
Expand Down