Skip to content

Commit 0a7263e

Browse files
authored
Merge pull request #432 from TigerInYourDream/fix-logout
2 parents 3263638 + b40cada commit 0a7263e

File tree

14 files changed

+1299
-71
lines changed

14 files changed

+1299
-71
lines changed

src/app.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,25 @@ use std::collections::HashMap;
99
use makepad_widgets::{makepad_micro_serde::*, *};
1010
use matrix_sdk::ruma::{OwnedRoomId, RoomId};
1111
use crate::{
12-
home::{
12+
avatar_cache::clear_avatar_cache, home::{
1313
main_desktop_ui::MainDesktopUiAction,
1414
new_message_context_menu::NewMessageContextMenuWidgetRefExt,
15-
room_screen::MessageAction,
16-
rooms_list::RoomsListAction,
17-
},
18-
join_leave_room_modal::{
15+
room_screen::{clear_timeline_states, MessageAction},
16+
rooms_list::{clear_all_invited_rooms, RoomsListAction},
17+
}, join_leave_room_modal::{
1918
JoinLeaveRoomModalAction,
2019
JoinLeaveRoomModalWidgetRefExt,
21-
},
22-
login::login_screen::LoginAction,
23-
persistence,
24-
shared::callout_tooltip::{
20+
}, login::login_screen::LoginAction, logout::logout_confirm_modal::{LogoutAction, LogoutConfirmModalAction, LogoutConfirmModalWidgetRefExt}, persistence, profile::user_profile_cache::clear_user_profile_cache, shared::callout_tooltip::{
2521
CalloutTooltipOptions,
2622
CalloutTooltipWidgetRefExt,
2723
TooltipAction,
28-
},
29-
sliding_sync::current_user_id,
30-
utils::{
24+
}, sliding_sync::current_user_id, utils::{
3125
room_name_or_id,
3226
OwnedRoomIdRon,
33-
},
34-
verification::VerificationAction,
35-
verification_modal::{
27+
}, verification::VerificationAction, verification_modal::{
3628
VerificationModalAction,
3729
VerificationModalWidgetRefExt,
38-
},
30+
}
3931
};
4032

4133
live_design! {
@@ -48,6 +40,7 @@ live_design! {
4840
use crate::verification_modal::VerificationModal;
4941
use crate::join_leave_room_modal::JoinLeaveRoomModal;
5042
use crate::login::login_screen::LoginScreen;
43+
use crate::logout::logout_confirm_modal::LogoutConfirmModal;
5144
use crate::shared::popup_list::*;
5245
use crate::home::new_message_context_menu::*;
5346
use crate::shared::callout_tooltip::CalloutTooltip;
@@ -119,6 +112,13 @@ live_design! {
119112
}
120113
}
121114

115+
// Logout confirmation modal
116+
logout_confirm_modal = <Modal> {
117+
content: {
118+
logout_confirm_modal_inner = <LogoutConfirmModal> {}
119+
}
120+
}
121+
122122
// Tooltips must be shown in front of all other UI elements,
123123
// since they can be shown as a hover atop any other widget.
124124
app_tooltip = <CalloutTooltip> {}
@@ -171,6 +171,7 @@ impl LiveRegister for App {
171171
crate::home::live_design(cx);
172172
crate::profile::live_design(cx);
173173
crate::login::live_design(cx);
174+
crate::logout::live_design(cx);
174175
}
175176
}
176177

@@ -210,6 +211,38 @@ impl MatchEvent for App {
210211

211212
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
212213
for action in actions {
214+
if let Some(logout_modal_action) = action.downcast_ref::<LogoutConfirmModalAction>() {
215+
match logout_modal_action {
216+
LogoutConfirmModalAction::Open => {
217+
self.ui.logout_confirm_modal(id!(logout_confirm_modal_inner)).reset_state(cx);
218+
self.ui.modal(id!(logout_confirm_modal)).open(cx)
219+
},
220+
LogoutConfirmModalAction::Close { was_internal, .. } => {
221+
if *was_internal {
222+
self.ui.modal(id!(logout_confirm_modal)).close(cx);
223+
}
224+
},
225+
_ => {}
226+
}
227+
}
228+
229+
if let Some(LogoutAction::LogoutSuccess) = action.downcast_ref() {
230+
self.app_state.logged_in = false;
231+
self.ui.modal(id!(logout_confirm_modal)).close(cx);
232+
self.update_login_visibility(cx);
233+
self.ui.redraw(cx);
234+
continue;
235+
}
236+
237+
if let Some(LogoutAction::ClearAppState { on_clear_appstate }) = action.downcast_ref() {
238+
// Clear user profile cache, invited_rooms timeline states
239+
clear_all_app_state(cx);
240+
// Reset all app state to its default.
241+
self.app_state = Default::default();
242+
on_clear_appstate.notify_one();
243+
continue;
244+
}
245+
213246
if let Some(LoginAction::LoginSuccess) = action.downcast_ref() {
214247
log!("Received LoginAction::LoginSuccess, hiding login view.");
215248
self.app_state.logged_in = true;
@@ -363,6 +396,15 @@ impl MatchEvent for App {
363396
}
364397
}
365398

399+
/// Clears all thread-local UI caches (user profiles, invited rooms, and timeline states).
400+
/// The `cx` parameter ensures that these thread-local caches are cleared on the main UI thread,
401+
fn clear_all_app_state(cx: &mut Cx) {
402+
clear_user_profile_cache(cx);
403+
clear_all_invited_rooms(cx);
404+
clear_timeline_states(cx);
405+
clear_avatar_cache(cx);
406+
}
407+
366408
impl AppMain for App {
367409
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
368410
// if let Event::WindowGeomChange(geom) = event {

src/avatar_cache.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,12 @@ pub fn get_or_fetch_avatar(
8282
AvatarCacheEntry::Requested
8383
})
8484
}
85+
86+
/// Clears cached avatars.
87+
/// This function requires passing in a reference to `Cx`,
88+
/// which acts as a guarantee that this function must only be called by the main UI thread.
89+
pub fn clear_avatar_cache(_cx: &mut Cx) {
90+
AVATAR_NEW_CACHE.with_borrow_mut(|cache| {
91+
cache.clear();
92+
});
93+
}

src/home/main_desktop_ui.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use makepad_widgets::*;
22
use matrix_sdk::ruma::OwnedRoomId;
3-
use std::collections::HashMap;
3+
use tokio::sync::Notify;
4+
use std::{collections::HashMap, sync::Arc};
45

56
use crate::{app::{AppState, AppStateAction, SelectedRoom}, utils::room_name_or_id};
67
use super::{invite_screen::InviteScreenWidgetRefExt, room_screen::RoomScreenWidgetRefExt, rooms_list::RoomsListAction};
@@ -216,6 +217,27 @@ impl MainDesktopUI {
216217
self.open_rooms.remove(&tab_id);
217218
}
218219

220+
/// Closes all tabs
221+
pub fn close_all_tabs(&mut self, cx: &mut Cx) {
222+
let dock = self.view.dock(id!(dock));
223+
for tab_id in self.open_rooms.keys() {
224+
dock.close_tab(cx, *tab_id);
225+
}
226+
227+
dock.select_tab(cx, live_id!(home_tab));
228+
cx.widget_action(
229+
self.widget_uid(),
230+
&HeapLiveIdPath::default(),
231+
AppStateAction::FocusNone,
232+
);
233+
234+
// Clear tab-related dock UI state.
235+
self.open_rooms.clear();
236+
self.tab_to_close = None;
237+
self.room_order.clear();
238+
self.most_recently_selected_room = None;
239+
}
240+
219241
/// Replaces an invite with a joined room in the dock.
220242
fn replace_invite_with_joined_room(
221243
&mut self,
@@ -268,6 +290,12 @@ impl WidgetMatchEvent for MainDesktopUI {
268290
for action in actions {
269291
let widget_action = action.as_widget_action();
270292

293+
if let Some(MainDesktopUiAction::CloseAllTabs { on_close_all }) = action.downcast_ref() {
294+
self.close_all_tabs(cx);
295+
on_close_all.notify_one();
296+
continue;
297+
}
298+
271299
// Handle actions emitted by the dock within the MainDesktopUI
272300
match widget_action.cast() { // TODO: don't we need to call `widget_uid_eq(dock.widget_uid())` here?
273301
// Whenever a tab (except for the home_tab) is pressed, notify the app state.
@@ -404,11 +432,14 @@ impl WidgetMatchEvent for MainDesktopUI {
404432
}
405433

406434
/// Actions sent to the MainDesktopUI widget for saving/restoring its dock state.
407-
#[derive(Clone, Debug, DefaultNone)]
435+
#[derive(Debug)]
408436
pub enum MainDesktopUiAction {
409437
/// Save the state of the dock into the AppState.
410438
SaveDockIntoAppState,
411439
/// Load the room panel state from the AppState to the dock.
412440
LoadDockFromAppState,
413-
None,
441+
/// Close all tabs; see [`MainDesktopUI::close_all_tabs()`]
442+
CloseAllTabs {
443+
on_close_all: Arc<Notify>,
444+
},
414445
}

src/home/room_screen.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4387,3 +4387,15 @@ impl MessageRef {
43874387
inner.set_data(details);
43884388
}
43894389
}
4390+
4391+
/// Clears all UI-related timeline states for all known rooms.
4392+
///
4393+
/// This function requires passing in a reference to `Cx`,
4394+
/// which isn't used, but acts as a guarantee that this function
4395+
/// must only be called by the main UI thread.
4396+
pub fn clear_timeline_states(_cx: &mut Cx) {
4397+
// Clear timeline states cache
4398+
TIMELINE_STATES.with_borrow_mut(|states| {
4399+
states.clear();
4400+
});
4401+
}

src/home/rooms_list.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ pub fn get_invited_rooms(_cx: &mut Cx) -> Rc<RefCell<HashMap<OwnedRoomId, Invite
3333
ALL_INVITED_ROOMS.with(Rc::clone)
3434
}
3535

36+
/// Clears all invited rooms
37+
///
38+
/// This function requires passing in a reference to `Cx`,
39+
/// which isn't used, but acts as a guarantee that this function
40+
/// must only be called by the main UI thread.
41+
pub fn clear_all_invited_rooms(_cx: &mut Cx) {
42+
ALL_INVITED_ROOMS.with(|rooms| {
43+
rooms.borrow_mut().clear();
44+
});
45+
}
46+
3647

3748
live_design! {
3849
use link::theme::*;

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub mod settings;
1313

1414
/// Login screen
1515
pub mod login;
16+
/// Logout confirmation and state management
17+
pub mod logout;
1618
/// Core UI content: the main home screen (rooms list), room screen.
1719
pub mod home;
1820
/// User profile info and a user profile sliding pane.

0 commit comments

Comments
 (0)