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
82 changes: 68 additions & 14 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::{cell::RefCell, collections::HashMap};
use makepad_widgets::*;
use matrix_sdk::{RoomState, ruma::{OwnedRoomId, RoomId}};
use matrix_sdk::{RoomState, ruma::{OwnedEventId, OwnedRoomId, RoomId}};
use serde::{Deserialize, Serialize};
use crate::{
avatar_cache::clear_avatar_cache, home::{
Expand Down Expand Up @@ -374,18 +374,14 @@ impl MatchEvent for App {
continue;
}

// A new room has been selected, update the app state and navigate to the main content view.
if let RoomsListAction::Selected(selected_room) = action.as_widget_action().cast() {
// A room has been selected, update the app state and navigate to the main content view.
let display_name = match &selected_room {
SelectedRoom::JoinedRoom { room_name_id } => room_name_id.to_string(),
SelectedRoom::InvitedRoom { room_name_id } => room_name_id.to_string(),
SelectedRoom::Space { space_name_id } => format!("[Space] {}", space_name_id),
};
self.app_state.selected_room = Some(selected_room);
// Set the Stack Navigation header to show the name of the newly-selected room.
self.ui
.label(ids!(main_content_view.header.content.title_container.title))
.set_text(cx, &display_name);
.set_text(cx, &selected_room.display_name());

self.app_state.selected_room = Some(selected_room);

// Navigate to the main content view
cx.widget_action(
Expand Down Expand Up @@ -852,12 +848,29 @@ pub struct SavedDockState {

/// Represents a room currently or previously selected by the user.
///
/// One `SelectedRoom` is considered equal to another if their `room_id`s are equal.
/// ## PartialEq/Eq equality comparison behavior
/// Room/Space names are ignored for the purpose of equality comparison.
/// Two `SelectedRoom`s are considered equal if their `room_id`s are equal,
/// unless they are `Thread`s,` in which case their `thread_root_event_id`s
/// are also compared for equality.
/// A `Thread` is never considered equal to a non-`Thread`, even if their `room_id`s are equal.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum SelectedRoom {
JoinedRoom { room_name_id: RoomNameId },
InvitedRoom { room_name_id: RoomNameId },
Space { space_name_id: RoomNameId },
JoinedRoom {
room_name_id: RoomNameId,
},
Thread {
room_name_id: RoomNameId,
/// The event ID of the root message of this thread,
/// which is used to distinguish this thread from the main room timeline.
thread_root_event_id: OwnedEventId,
},
InvitedRoom {
room_name_id: RoomNameId,
},
Space {
space_name_id: RoomNameId,
},
}

impl SelectedRoom {
Expand All @@ -866,6 +879,7 @@ impl SelectedRoom {
SelectedRoom::JoinedRoom { room_name_id } => room_name_id.room_id(),
SelectedRoom::InvitedRoom { room_name_id } => room_name_id.room_id(),
SelectedRoom::Space { space_name_id } => space_name_id.room_id(),
SelectedRoom::Thread { room_name_id, .. } => room_name_id.room_id(),
}
}

Expand All @@ -874,6 +888,7 @@ impl SelectedRoom {
SelectedRoom::JoinedRoom { room_name_id } => room_name_id,
SelectedRoom::InvitedRoom { room_name_id } => room_name_id,
SelectedRoom::Space { space_name_id } => space_name_id,
SelectedRoom::Thread { room_name_id, .. } => room_name_id,
}
}

Expand All @@ -895,10 +910,49 @@ impl SelectedRoom {
_ => false,
}
}

/// Returns the `LiveId` of the room tab corresponding to this `SelectedRoom`.
pub fn tab_id(&self) -> LiveId {
match self {
SelectedRoom::Thread { room_name_id, thread_root_event_id } => {
LiveId::from_str(
&format!("{}##{}", room_name_id.room_id(), thread_root_event_id)
)
}
other => LiveId::from_str(other.room_id().as_str()),
}
}

/// Returns the display name to be shown for this room in the UI.
pub fn display_name(&self) -> String {
match self {
SelectedRoom::JoinedRoom { room_name_id } => room_name_id.to_string(),
SelectedRoom::InvitedRoom { room_name_id } => room_name_id.to_string(),
SelectedRoom::Space { space_name_id } => format!("[Space] {space_name_id}"),
SelectedRoom::Thread { room_name_id, .. } => format!("[Thread] {room_name_id}"),
}
}
}

impl PartialEq for SelectedRoom {
fn eq(&self, other: &Self) -> bool {
self.room_id() == other.room_id()
match (self, other) {
(
SelectedRoom::Thread {
room_name_id: lhs_room_name_id,
thread_root_event_id: lhs_thread_root_event_id,
},
SelectedRoom::Thread {
room_name_id: rhs_room_name_id,
thread_root_event_id: rhs_thread_root_event_id,
},
) => {
lhs_room_name_id.room_id() == rhs_room_name_id.room_id()
&& lhs_thread_root_event_id == rhs_thread_root_event_id
}
(SelectedRoom::Thread { .. }, _) | (_, SelectedRoom::Thread { .. }) => false,
_ => self.room_id() == other.room_id(),
}
}
}
impl Eq for SelectedRoom {}
Expand Down
40 changes: 35 additions & 5 deletions src/event_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use std::borrow::Cow;

use matrix_sdk::{ruma::{events::{room::{guest_access::GuestAccess, history_visibility::HistoryVisibility, join_rules::JoinRule, message::{MessageFormat, MessageType}}, AnySyncMessageLikeEvent, AnySyncTimelineEvent, FullStateEventContent, SyncMessageLikeEvent}, serde::Raw, UserId}};
use matrix_sdk::{ruma::{OwnedUserId, events::{room::{guest_access::GuestAccess, history_visibility::HistoryVisibility, join_rules::JoinRule, message::{MessageFormat, MessageType}}, AnySyncMessageLikeEvent, AnySyncTimelineEvent, FullStateEventContent, SyncMessageLikeEvent}, serde::Raw, UserId}};
use matrix_sdk_base::crypto::types::events::UtdCause;
use matrix_sdk_ui::timeline::{self, AnyOtherFullStateEventContent, EncryptedMessage, EventTimelineItem, MemberProfileChange, MembershipChange, MsgLikeKind, OtherMessageLike, RoomMembershipChange, TimelineItemContent};

Expand Down Expand Up @@ -69,7 +69,7 @@ pub fn text_preview_of_timeline_item(
match content {
TimelineItemContent::MsgLike(msg_like_content) => {
match &msg_like_content.kind {
MsgLikeKind::Message(msg) => text_preview_of_message(msg, sender_username),
MsgLikeKind::Message(msg) => text_preview_of_message(msg.msgtype(), sender_username),
MsgLikeKind::Sticker(sticker) => TextPreview::from((
format!("[Sticker]: <i>{}</i>", htmlize::escape_text(&sticker.content().body)),
BeforeText::UsernameWithColon,
Expand Down Expand Up @@ -206,11 +206,11 @@ pub fn plaintext_body_of_timeline_item(


/// Returns a text preview of the given message as an Html-formatted string.
pub fn text_preview_of_message(
message: &timeline::Message,
fn text_preview_of_message(
msg: &MessageType,
sender_username: &str,
) -> TextPreview {
let text = match message.msgtype() {
let text = match msg {
MessageType::Audio(audio) => format!(
"[Audio]: <i>{}</i>",
if let Some(formatted_body) = audio.formatted.as_ref() {
Expand Down Expand Up @@ -300,6 +300,36 @@ pub fn text_preview_of_message(
TextPreview::from((text, BeforeText::UsernameWithColon))
}

/// Returns a preview of the given raw timeline event.
pub fn text_preview_of_raw_timeline_event(
raw_event: &Raw<AnySyncTimelineEvent>,
sender_username: &str,
) -> Option<TextPreview> {
match raw_event.deserialize().ok()? {
AnySyncTimelineEvent::MessageLike(
AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Original(ev)
)
) => Some(text_preview_of_message(
&ev.content.msgtype,
sender_username,
)),
AnySyncTimelineEvent::MessageLike(
AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Redacted(_)
)
) => {
let sender_user_id = raw_event.get_field::<OwnedUserId>("sender").ok().flatten()?;
Some(text_preview_of_redacted_message(
Some(raw_event),
sender_user_id.as_ref(),
sender_username,
))
}
_ => None,
}
}


/// Returns a plaintext preview of the given redacted message.
///
Expand Down
40 changes: 28 additions & 12 deletions src/home/editing_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use makepad_widgets::{text::selection::Cursor, *};
use matrix_sdk::{
room::edit::EditedContent,
ruma::{
OwnedRoomId,
events::{
poll::unstable_start::{UnstablePollAnswer, UnstablePollStartContentBlock},
room::message::{FormattedBody, MessageType, RoomMessageEventContentWithoutRelation},
Expand All @@ -13,7 +12,8 @@ use matrix_sdk_ui::timeline::{EventTimelineItem, MsgLikeKind, TimelineEventItemI

use crate::shared::mentionable_text_input::MentionableTextInputWidgetExt;
use crate::{
shared::popup_list::{enqueue_popup_notification, PopupKind}, sliding_sync::{submit_async_request, MatrixRequest}
shared::popup_list::{enqueue_popup_notification, PopupKind},
sliding_sync::{submit_async_request, MatrixRequest, TimelineKind},
};

live_design! {
Expand Down Expand Up @@ -150,7 +150,7 @@ pub enum EditingPaneAction {
/// The information maintained by the EditingPane widget.
struct EditingPaneInfo {
event_tl_item: EventTimelineItem,
room_id: OwnedRoomId,
timeline_kind: TimelineKind,
}

/// A view that slides in from the bottom of the screen to allow editing a message.
Expand Down Expand Up @@ -369,7 +369,7 @@ impl Widget for EditingPane {
};

submit_async_request(MatrixRequest::EditMessage {
room_id: info.room_id.clone(),
timeline_kind: info.timeline_kind.clone(),
timeline_event_item_id: info.event_tl_item.identifier(),
edited_content,
});
Expand Down Expand Up @@ -426,7 +426,12 @@ impl EditingPane {
}

/// Shows the editing pane and sets it up to edit the given `event`'s content.
pub fn show(&mut self, cx: &mut Cx, event_tl_item: EventTimelineItem, room_id: OwnedRoomId) {
pub fn show(
&mut self,
cx: &mut Cx,
event_tl_item: EventTimelineItem,
timeline_kind: TimelineKind,
) {
if !event_tl_item.is_editable() {
enqueue_popup_notification(
"That message cannot be edited.",
Expand All @@ -452,7 +457,10 @@ impl EditingPane {
}


self.info = Some(EditingPaneInfo { event_tl_item, room_id: room_id.clone() });
self.info = Some(EditingPaneInfo {
event_tl_item,
timeline_kind,
});

self.visible = true;
self.button(ids!(accept_button)).reset_hover(cx);
Expand Down Expand Up @@ -487,13 +495,16 @@ impl EditingPane {
&mut self,
cx: &mut Cx,
editing_pane_state: EditingPaneState,
room_id: OwnedRoomId,
timeline_kind: TimelineKind,
) {
let EditingPaneState { event_tl_item, text_input_state } = editing_pane_state;
self.mentionable_text_input(ids!(editing_content.edit_text_input))
.text_input_ref()
.restore_state(cx, text_input_state);
self.info = Some(EditingPaneInfo { event_tl_item, room_id: room_id.clone() });
self.info = Some(EditingPaneInfo {
event_tl_item,
timeline_kind,
});
self.visible = true;
self.button(ids!(accept_button)).reset_hover(cx);
self.button(ids!(cancel_button)).reset_hover(cx);
Expand Down Expand Up @@ -537,11 +548,16 @@ impl EditingPaneRef {
}

/// See [`EditingPane::show()`].
pub fn show(&self, cx: &mut Cx, event_tl_item: EventTimelineItem, room_id: OwnedRoomId) {
pub fn show(
&self,
cx: &mut Cx,
event_tl_item: EventTimelineItem,
timeline_kind: TimelineKind,
) {
let Some(mut inner) = self.borrow_mut() else {
return;
};
inner.show(cx, event_tl_item, room_id);
inner.show(cx, event_tl_item, timeline_kind);
}

/// See [`EditingPane::save_state()`].
Expand All @@ -556,10 +572,10 @@ impl EditingPaneRef {
&self,
cx: &mut Cx,
editing_pane_state: EditingPaneState,
room_id: OwnedRoomId,
timeline_kind: TimelineKind,
) {
let Some(mut inner) = self.borrow_mut() else { return };
inner.restore_state(cx, editing_pane_state, room_id);
inner.restore_state(cx, editing_pane_state, timeline_kind);
}

/// Hides the editing pane immediately and clears its state without animating it out.
Expand Down
Loading