Skip to content
Open
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
11 changes: 8 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ use makepad_widgets::{makepad_micro_serde::*, *};
use matrix_sdk::ruma::{OwnedRoomId, RoomId};
use crate::{
avatar_cache::clear_avatar_cache, home::{
main_desktop_ui::MainDesktopUiAction, new_message_context_menu::NewMessageContextMenuWidgetRefExt, room_screen::{clear_timeline_states, MessageAction}, rooms_list::{clear_all_invited_rooms, enqueue_rooms_list_update, RoomsListAction, RoomsListRef, RoomsListUpdate}
main_desktop_ui::MainDesktopUiAction, new_message_context_menu::NewMessageContextMenuWidgetRefExt, room_screen::{MessageAction, clear_timeline_states}, rooms_list::{RoomsListAction, RoomsListRef, RoomsListUpdate, clear_all_invited_rooms, enqueue_rooms_list_update}
}, join_leave_room_modal::{
JoinLeaveModalKind, JoinLeaveRoomModalAction, JoinLeaveRoomModalWidgetRefExt
}, login::login_screen::LoginAction, logout::logout_confirm_modal::{LogoutAction, LogoutConfirmModalAction, LogoutConfirmModalWidgetRefExt}, persistence, profile::user_profile_cache::clear_user_profile_cache, room::BasicRoomDetails, shared::callout_tooltip::{
CalloutTooltipOptions,
CalloutTooltipWidgetRefExt,
TooltipAction,
}, sliding_sync::current_user_id, utils::{
room_name_or_id,
OwnedRoomIdRon,
OwnedRoomIdRon, OwnedRoomOrAliasIdRon, OwnedServerNameRon, room_name_or_id
}, verification::VerificationAction, verification_modal::{
VerificationModalAction,
VerificationModalWidgetRefExt,
Expand Down Expand Up @@ -630,20 +629,26 @@ pub enum SelectedRoom {
room_id: OwnedRoomIdRon,
room_name: Option<String>,
},
PreviewedRoom {
room_id: OwnedRoomIdRon,
room_name: Option<String>,
},
}

impl SelectedRoom {
pub fn room_id(&self) -> &OwnedRoomId {
match self {
SelectedRoom::JoinedRoom { room_id, .. } => room_id,
SelectedRoom::InvitedRoom { room_id, .. } => room_id,
SelectedRoom::PreviewedRoom { room_id, .. } => room_id,
}
}

pub fn room_name(&self) -> Option<&String> {
match self {
SelectedRoom::JoinedRoom { room_name, .. } => room_name.as_ref(),
SelectedRoom::InvitedRoom { room_name, .. } => room_name.as_ref(),
SelectedRoom::PreviewedRoom { room_name, .. } => room_name.as_ref(),
}
}

Expand Down
178 changes: 177 additions & 1 deletion src/home/main_desktop_ui.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use makepad_widgets::*;
use matrix_sdk::ruma::OwnedRoomId;
use ruma::{OwnedRoomAliasId, OwnedRoomOrAliasId};
use tokio::sync::Notify;
use std::{collections::HashMap, sync::Arc};

use crate::{app::{AppState, AppStateAction, SelectedRoom}, utils::room_name_or_id};
use crate::{app::{AppState, AppStateAction, SelectedRoom}, home::room_screen::handle_switch_to_known_room, room::{self, BasicRoomDetails, RoomAliasResolutionAction, preview_screen::{PreviewDetails, PreviewScreenWidgetRefExt, RoomPreviewAction}}, sliding_sync::{MatrixRequest, submit_async_request}, utils::room_name_or_id};
use super::{invite_screen::InviteScreenWidgetRefExt, room_screen::RoomScreenWidgetRefExt, rooms_list::RoomsListAction};

live_design! {
Expand All @@ -17,6 +18,7 @@ live_design! {
use crate::home::welcome_screen::WelcomeScreen;
use crate::home::room_screen::RoomScreen;
use crate::home::invite_screen::InviteScreen;
use crate::room::preview_screen::PreviewScreen;

pub MainDesktopUI = {{MainDesktopUI}} {
dock = <Dock> {
Expand Down Expand Up @@ -54,6 +56,7 @@ live_design! {
welcome_screen = <WelcomeScreen> {}
room_screen = <RoomScreen> {}
invite_screen = <InviteScreen> {}
preview_screen = <PreviewScreen> {}
}
}
}
Expand Down Expand Up @@ -88,6 +91,9 @@ pub struct MainDesktopUI {
/// If true, this widget proceeds to draw the desktop UI as normal.
#[rust]
drawn_previously: bool,

#[rust]
already_resolved_aliases: HashMap<OwnedRoomAliasId, OwnedRoomId>,
}

impl Widget for MainDesktopUI {
Expand Down Expand Up @@ -138,6 +144,7 @@ impl MainDesktopUI {
id!(invite_screen),
room_name_or_id(room_name.as_ref(), room_id),
),
_ => return
};
let new_tab_widget = dock.create_and_select_tab(
cx,
Expand Down Expand Up @@ -168,6 +175,7 @@ impl MainDesktopUI {
room.room_name().cloned()
);
}
_ => {}
}
cx.action(MainDesktopUiAction::SaveDockIntoAppState);
} else {
Expand All @@ -178,6 +186,70 @@ impl MainDesktopUI {
self.most_recently_selected_room = Some(room);
}

fn focus_or_create_preview_tab(&mut self, cx: &mut Cx, room: SelectedRoom, preview_details: PreviewDetails) {
let dock = self.view.dock(ids!(dock));

if self.most_recently_selected_room.as_ref().is_some_and(|r| r == &room) {
return;
}

let room_id_as_live_id = LiveId::from_str(room.room_id().as_str());
if self.open_rooms.contains_key(&room_id_as_live_id) {
dock.select_tab(cx, room_id_as_live_id);
self.most_recently_selected_room = Some(room);
return;
}

let (tab_bar, _pos) = match dock.find_tab_bar_of_tab(id!(home_tab)) {
Some(found) => found,
None => {
error!("BUG: unable to find home_tab tab bar when creating preview tab");
return;
}
};

let (kind, name) = match &room {
SelectedRoom::PreviewedRoom { room_id, room_name } => (
id!(preview_screen),
room_name_or_id(room_name.as_ref(), room_id),
),
_ => {
error!("BUG: focus_or_create_preview_tab called with non-preview room: {:?}", room);
return;
}
};

log!("Creating preview tab for room {:?}", name);

let new_tab_widget = dock.create_and_select_tab(
cx,
tab_bar,
room_id_as_live_id,
kind,
name.clone(),
id!(CloseableTab),
None,
);

if let Some(new_widget) = new_tab_widget {
self.room_order.push(room.clone());
new_widget.as_preview_screen().set_displayed_preview(
cx,
room.room_id().clone(),
room.room_name().cloned(),
preview_details.clone(),
);

cx.action(MainDesktopUiAction::SaveDockIntoAppState);
} else {
error!("BUG: failed to create preview tab for {room:?}");
return;
}

self.open_rooms.insert(room_id_as_live_id, room.clone());
self.most_recently_selected_room = Some(room);
}

/// Closes a tab in the dock and focuses on the latest open room.
fn close_tab(&mut self, cx: &mut Cx, tab_id: LiveId) {
let dock = self.view.dock(ids!(dock));
Expand Down Expand Up @@ -272,6 +344,7 @@ impl MainDesktopUI {

impl WidgetMatchEvent for MainDesktopUI {
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) {
let uid = self.widget_uid();
let mut should_save_dock_action: bool = false;
for action in actions {
let widget_action = action.as_widget_action();
Expand All @@ -282,6 +355,79 @@ impl WidgetMatchEvent for MainDesktopUI {
continue;
}

if let Some(RoomAliasResolutionAction::Resolved(room_alias, result)) = action.downcast_ref() {
match result {
Ok(data) => {
let room_id = &data.room_id;
let server_names = &data.servers;

// Skip if we've already resolved this alias
if self.already_resolved_aliases.contains_key(room_alias) {
log!("Alias {} already resolved, skipping.", room_alias);
return;
}

self.already_resolved_aliases
.insert(room_alias.clone(), room_id.clone());

// Try to switch to the known room
if !handle_switch_to_known_room(cx, uid, room_id.clone()) {
cx.widget_action(
uid,
&Scope::empty().path,
RoomPreviewAction::Selected {
room_or_alias_id: OwnedRoomOrAliasId::from(room_id.clone()),
via: server_names.to_vec(),
}
);
}
}
Err(e) => {
error!("Failed to resolve alias {}: {}", room_alias, e);
}
}
}

if let Some(room::RoomPreviewAction::Fetched(res)) = action.downcast_ref() {
match res {
Ok(data) => {
let BasicRoomDetails {
room_id,
room_name,
room_avatar,
} = BasicRoomDetails {
room_id: data.room_id.clone(),
room_name: data.name.clone(),
room_avatar: data.room_avatar.clone(),
};

let preview_details = PreviewDetails {
room_basic_details: BasicRoomDetails {
room_id: room_id.clone(),
room_name: room_name.clone(),
room_avatar,
},
is_world_readable: data.is_world_readable.unwrap_or(false),
join_rule: data.join_rule.clone(),
};

log!("Opening room preview for {} (name: {:?})", room_id, room_name);

self.focus_or_create_preview_tab(
cx,
SelectedRoom::PreviewedRoom {
room_id: room_id.into(),
room_name: room_name.clone(),
},
preview_details,
);
}
Err(e) => {
error!("Failed to fetch room preview: {e}");
}
}
}

// Handle actions emitted by the dock within the MainDesktopUI
match widget_action.cast() { // TODO: don't we need to call `widget_uid_eq(dock.widget_uid())` here?
// Whenever a tab (except for the home_tab) is pressed, notify the app state.
Expand Down Expand Up @@ -333,6 +479,36 @@ impl WidgetMatchEvent for MainDesktopUI {
_ => (),
}

match widget_action.cast() {
RoomPreviewAction::Selected { room_or_alias_id, via } => {
match OwnedRoomAliasId::try_from(room_or_alias_id) {
// We have a room alias ID to resolve it to a room ID, and then switch to it.
Ok(alias_id) => {
if let Some(room_id) = self.already_resolved_aliases.get(&alias_id) {
if handle_switch_to_known_room(cx, uid, room_id.clone()) {
return;
}
// If we couldn't switch to the known room, we need to fetch the preview info.
submit_async_request(MatrixRequest::GetRoomPreview {
room_or_alias_id: OwnedRoomOrAliasId::from(room_id.clone()),
via: via.clone(),
});
} else {
submit_async_request(MatrixRequest::ResolveRoomAlias(alias_id));
}
}
// This Err returns means we have a room ID, so we can directly fetch the preview info.
Err(room_id) => {
submit_async_request(MatrixRequest::GetRoomPreview {
room_or_alias_id: OwnedRoomOrAliasId::from(room_id.clone()),
via: via.clone()
});
}
}
}
RoomPreviewAction::None => { }
}

// Handle RoomsList actions, which are updates from the rooms list.
match widget_action.cast() {
RoomsListAction::Selected(selected_room) => {
Expand Down
5 changes: 5 additions & 0 deletions src/home/main_mobile_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ impl Widget for MainMobileUI {
show_room = false;
show_invite = false;
}
_ => {
show_welcome = false;
show_room = false;
show_invite = false;
}
}

self.view.view(ids!(welcome)).set_visible(cx, show_welcome);
Expand Down
Loading
Loading