Skip to content
Merged
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
123 changes: 71 additions & 52 deletions src/home/invite_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use std::{ops::Deref, rc::Rc};
use makepad_widgets::*;
use matrix_sdk::{RoomState, ruma::{OwnedRoomId, room::JoinRuleSummary}};
use matrix_sdk::{RoomState, ruma::{OwnedRoomAliasId, OwnedRoomId, room::JoinRuleSummary}};

use crate::{app::AppStateAction, avatar_cache::{self, AvatarCacheEntry}, block_user_modal::{BlockUserModalAction, BlockUserRequest}, home::rooms_list::RoomsListRef, join_leave_room_modal::{JoinLeaveModalKind, JoinLeaveRoomModalAction}, room::{BasicRoomDetails, FetchedRoomAvatar, FetchedRoomPreview}, room_preview_cache::{self, CachedRoomPreview}, shared::{avatar::AvatarWidgetRefExt, restore_status_view::RestoreStatusViewWidgetExt}, sliding_sync::{is_user_blocked, submit_async_request, MatrixRequest}, utils::{self, RoomNameId}};

Expand All @@ -18,6 +18,19 @@ script_mod! {
use mod.widgets.*


// One part of an invite's details row: the join rule or the member count.
mod.widgets.InviteRoomDetailsLabel = Label {
width: Fit, height: Fit
padding: 0
text: ""
draw_text +: {
text_style: REGULAR_TEXT {
font_size: 11,
},
color: (COLOR_TEXT_SUBTLE)
}
}

mod.widgets.InviteScreen = set_type_default() do #(InviteScreen::register_widget(vm)) {
..mod.widgets.SolidView

Expand Down Expand Up @@ -158,46 +171,46 @@ script_mod! {
}
}

room_details := Label {
width: Fill, height: Fit,
align: Align{x: 0.5, y: 0},
flow: Flow.Right{wrap: true},
text: ""
draw_text +: {
text_style: REGULAR_TEXT {
font_size: 11,
},
color: (COLOR_TEXT_SUBTLE)
}
room_details := View {
width: Fill, height: Fit
flow: Flow.Right{wrap: true}
align: Align{x: 0.5, y: 0}
padding: 6
spacing: 16
// The same spacing between two regular wrapped lines of text.
wrap_spacing: 3.52

room_join_rule := mod.widgets.InviteRoomDetailsLabel {}
room_member_count := mod.widgets.InviteRoomDetailsLabel {}
}

room_topic := Label {
width: Fill, height: Fit,
align: Align{x: 0.5, y: 0},
margin: Inset{top: 5},
flow: Flow.Right{wrap: true},
max_lines: 3
text_overflow: Ellipsis
text: ""
draw_text +: {
text_style: REGULAR_TEXT {
font_size: 12,
},
color: (COLOR_INVITE_SCREEN_TOPIC_TEXT)
room_topic := CollapsibleLabel {
width: Fill {max: 500}
margin: Inset{top: 16, bottom: 6}
padding: Inset{left: 6, right: 6}
label +: {
align: Align{x: 0.5, y: 0}
draw_text +: {
text_style: REGULAR_TEXT {
font_size: 12,
},
color: (COLOR_INVITE_SCREEN_TOPIC_TEXT)
}
}
}
}

buttons := View {
width: Fill, height: Fit
// We'd like to use RightWrap, but it doesn't work with x-centered alignment
// flow: Flow.Right{wrap: true},
flow: Right,
flow: Flow.Right{wrap: true},
align: Align{x: 0.5, y: 0.5}
margin: Inset{top: 20}
spacing: 40
// matches the gap above reject_and_block_button.
wrap_spacing: 22

cancel_button := RobrixNegativeIconButton {
width: 135
align: Align{x: 0.5, y: 0.5}
padding: 15,
draw_icon.svg: (ICON_FORBIDDEN)
Expand All @@ -206,6 +219,7 @@ script_mod! {
}

accept_button := RobrixPositiveIconButton {
width: 135
align: Align{x: 0.5, y: 0.5}
padding: 15,
draw_icon.svg: (ICON_CHECKMARK)
Expand Down Expand Up @@ -247,6 +261,9 @@ script_mod! {
pub struct InviteDetails {
pub room_info: BasicRoomDetails,
pub inviter: Option<InviterInfo>,
pub canonical_alias: Option<OwnedRoomAliasId>,
pub topic: Option<String>,
pub join_rule: Option<JoinRuleSummary>,
}
impl Deref for InviteDetails {
type Target = BasicRoomDetails;
Expand Down Expand Up @@ -552,38 +569,34 @@ impl Widget for InviteScreen {
let invite_room_label = info.room_name_id().to_string();
room_view.label(cx, ids!(room_name)).set_text(cx, &invite_room_label);

// Third, show extra details about the room/space from the fetched room preview, if we have it
let preview = self.room_preview.as_deref();
let alias = preview.and_then(|p| p.canonical_alias.as_ref());
// Third, show extra details about the room/space.
// These come from the invite itself, except the member count, which only the room preview has.
let room_alias = room_view.label(cx, ids!(room_alias));
room_alias.set_visible(cx, alias.is_some());
room_alias.set_text(cx, alias.map_or("", |a| a.as_str()));
room_alias.set_visible(cx, info.canonical_alias.is_some());
room_alias.set_text(cx, info.canonical_alias.as_ref().map_or("", |a| a.as_str()));

let join_rule = preview.and_then(|p| p.join_rule.as_ref()).map(|rule| match rule {
let join_rule = info.join_rule.as_ref().map(|rule| match rule {
JoinRuleSummary::Public => "🌐 Public",
_ => "🔒 Private",
});
let room_or_space = if self.is_space { "space" } else { "room" };
let room_join_rule = room_view.label(cx, ids!(room_join_rule));
room_join_rule.set_visible(cx, join_rule.is_some());
if let Some(rule) = join_rule {
room_join_rule.set_text(cx, &format!("{rule} {room_or_space}"));
}
// If there are 0 members, that actually means we don't know how many members there are.
let num_members = preview.map(|p| p.num_joined_members).filter(|n| *n > 0);
let num_members = self.room_preview.as_deref().map(|p| p.num_joined_members).filter(|n| *n > 0);
let plural = if num_members == Some(1) { "" } else { "s" };
let details = match (join_rule, num_members) {
(Some(rule), Some(n)) => format!("{rule} {room_or_space} · {n} member{plural}"),
(Some(rule), None) => format!("{rule} {room_or_space}"),
(None, Some(n)) => format!("{n} member{plural}"),
(None, None) => String::new(),
};
let room_details = room_view.label(cx, ids!(room_details));
room_details.set_visible(cx, !details.is_empty());
room_details.set_text(cx, &details);

let topic = preview.and_then(|p| p.topic.as_deref())
.map(str::trim)
.filter(|t| !t.is_empty())
.map(|t| utils::replace_linebreaks_separators(t, false));
let room_topic = room_view.label(cx, ids!(room_topic));
room_topic.set_visible(cx, topic.is_some());
room_topic.set_text(cx, topic.as_deref().unwrap_or_default());
let member_count = num_members.map_or_else(
|| String::from("👥 ?? members"),
|n| format!("👥 {n} member{plural}"),
);
room_view.label(cx, ids!(room_member_count)).set_text(cx, &member_count);

let room_topic = room_view.widget(cx, ids!(room_topic));
room_topic.set_visible(cx, info.topic.is_some());
room_topic.set_text(cx, info.topic.as_deref().unwrap_or_default());

// Fourth, set the buttons' text based on the invite state.
let cancel_button = self.view.button(cx, ids!(cancel_button));
Expand Down Expand Up @@ -652,6 +665,12 @@ impl InviteScreen {
room_avatar: invite.room_avatar.clone(),
},
inviter: invite.inviter_info.clone(),
canonical_alias: invite.canonical_alias.clone(),
topic: invite.topic.as_deref()
.map(str::trim)
.filter(|t| !t.is_empty())
.map(str::to_owned),
join_rule: invite.join_rule.clone(),
});
self.invite_state = invite.invite_state;
self.is_space = invite.is_space;
Expand Down
18 changes: 17 additions & 1 deletion src/home/rooms_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use makepad_widgets::*;
use matrix_sdk_ui::spaces::room_list::SpaceRoomListPaginationState;
use ruma::events::tag::TagName;
use tokio::sync::mpsc::UnboundedSender;
use matrix_sdk::{RoomState, ruma::{events::tag::Tags, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId}};
use matrix_sdk::{RoomState, ruma::{events::tag::Tags, room::JoinRuleSummary, MilliSecondsSinceUnixEpoch, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId}};
use crate::{
app::{AppState, AppStateAction, SelectedRoom},
home::{
Expand Down Expand Up @@ -231,6 +231,12 @@ pub enum RoomsListUpdate {
room_id: OwnedRoomId,
is_space: bool,
},
/// Update the topic and join rule of the given invited room.
UpdateTopicAndJoinRule {
room_id: OwnedRoomId,
topic: Option<String>,
join_rule: Option<JoinRuleSummary>,
},
/// Remove the given room from the rooms list
RemoveRoom {
room_id: OwnedRoomId,
Expand Down Expand Up @@ -396,6 +402,10 @@ pub struct InvitedRoomInfo {
pub canonical_alias: Option<OwnedRoomAliasId>,
/// The alternative aliases for this room, if any.
pub alt_aliases: Vec<OwnedRoomAliasId>,
/// The topic of this room, if any.
pub topic: Option<String>,
/// The join rule of this room, if known.
pub join_rule: Option<JoinRuleSummary>,
/// The avatar for this room: either an array of bytes holding the avatar image
/// or a string holding the first Unicode character of the room name.
pub room_avatar: FetchedRoomAvatar,
Expand Down Expand Up @@ -1016,6 +1026,12 @@ impl RoomsList {
cx.action(InviteScreenAction::IsSpace { room_id, is_space });
}
}
RoomsListUpdate::UpdateTopicAndJoinRule { room_id, topic, join_rule } => {
if let Some(room) = self.invited_rooms.borrow_mut().get_mut(&room_id) {
room.topic = topic;
room.join_rule = join_rule;
}
}
RoomsListUpdate::RemoveRoom { room_id, new_state, is_space } => {
// TODO: once we have a dedicated LoadingScreen widget, we should emit an action
// to replace this room (if it's currently open) with the LoadingScreen widget,
Expand Down
30 changes: 2 additions & 28 deletions src/room/reply_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,32 +99,6 @@ script_mod! {
}
}

// The show more button (to expand) and show less button (to collapse) a tall reply preview.
mod.widgets.ReplyToggleButton = RobrixIconButton {
visible: false
width: Fit, height: Fit
spacing: 4
padding: Inset{ top: 4, bottom: 4, left: 8, right: 8 }
draw_icon +: { color: (COLOR_TEXT_MUTED) }
icon_walk: Walk{ width: 10, height: 10 }
draw_text +: {
text_style: theme.font_regular { font_size: 10.0, line_spacing: 1.2 }
color: (COLOR_TEXT_MUTED)
color_hover: (COLOR_TEXT_MUTED)
color_down: (COLOR_TEXT_MUTED)
}
draw_bg +: {
color: (COLOR_BG_PREVIEW)
color_hover: (COLOR_BG_PREVIEW_HOVER)
color_down: (COLOR_BG_PREVIEW_DOWN)
border_size: 1.0
border_color: (COLOR_PREVIEW_TOGGLE_BUTTON_BORDER)
border_color_hover: (COLOR_PREVIEW_TOGGLE_BUTTON_BORDER)
border_color_down: (COLOR_PREVIEW_TOGGLE_BUTTON_BORDER)
border_radius: 4.0
}
}

// Wraps a reply preview in a collapsible view.
mod.widgets.CollapsiblePreview = set_type_default() do #(CollapsiblePreview::register_widget(vm)) {
visible: false
Expand Down Expand Up @@ -156,12 +130,12 @@ script_mod! {
}
}

reply_expand_button := mod.widgets.ReplyToggleButton {
reply_expand_button := mod.widgets.ShowMoreLessButton {
draw_icon +: { svg: (ICON_TRIANGLE_DOWN) }
text: "Show more…"
}

reply_collapse_button := mod.widgets.ReplyToggleButton {
reply_collapse_button := mod.widgets.ShowMoreLessButton {
draw_icon +: { svg: (ICON_TRIANGLE_UP) }
text: "Show less"
}
Expand Down
Loading
Loading