diff --git a/labs/multiverse/src/widgets/room_view/input.rs b/labs/multiverse/src/widgets/room_view/input.rs index f4d4631c9..fcb8cf828 100644 --- a/labs/multiverse/src/widgets/room_view/input.rs +++ b/labs/multiverse/src/widgets/room_view/input.rs @@ -16,6 +16,8 @@ struct Cli { pub enum Command { Invite { user_id: String }, Leave, + Subscribe, + Unsubscribe, } pub enum MessageOrCommand { diff --git a/labs/multiverse/src/widgets/room_view/mod.rs b/labs/multiverse/src/widgets/room_view/mod.rs index a22b478ed..bacb16d5b 100644 --- a/labs/multiverse/src/widgets/room_view/mod.rs +++ b/labs/multiverse/src/widgets/room_view/mod.rs @@ -9,7 +9,8 @@ use matrix_sdk::{ Client, Room, RoomState, locks::Mutex, ruma::{ - OwnedRoomId, RoomId, UserId, api::client::receipt::create_receipt::v3::ReceiptType, + OwnedEventId, OwnedRoomId, RoomId, UserId, + api::client::receipt::create_receipt::v3::ReceiptType, events::room::message::RoomMessageEventContent, }, }; @@ -52,6 +53,7 @@ enum TimelineKind { Thread { room: OwnedRoomId, + thread_root: OwnedEventId, /// The threaded-focused timeline for this thread. timeline: Arc>>, /// Items in the thread timeline (to avoid recomputing them every single @@ -145,10 +147,11 @@ impl RoomView { let i = items.clone(); let t = thread_timeline.clone(); let root = root_event_id; + let cloned_root = root.clone(); let r = room.clone(); let task = spawn(async move { let timeline = TimelineBuilder::new(&r) - .with_focus(TimelineFocus::Thread { root_event_id: root.clone() }) + .with_focus(TimelineFocus::Thread { root_event_id: cloned_root }) .track_read_marker_and_receipts() .build() .await @@ -171,6 +174,7 @@ impl RoomView { self.timeline_list.unselect(); self.kind = TimelineKind::Thread { + thread_root: root, room: room.room_id().to_owned(), timeline: thread_timeline, items, @@ -225,6 +229,12 @@ impl RoomView { self.switch_to_room_timeline(None); } + // Pressing 'Alt+s' on a threaded timeline will print the current + // subscription status. + (KeyModifiers::ALT, Char('s')) => { + self.print_thread_subscription_status().await; + } + (KeyModifiers::CONTROL, Char('l')) => { self.toggle_reaction_to_latest_msg().await } @@ -477,10 +487,67 @@ impl RoomView { self.input.clear(); } + async fn subscribe_thread(&mut self) { + if let TimelineKind::Thread { thread_root, .. } = &self.kind { + self.call_with_room(async |room, status_handle| { + if let Err(err) = room.subscribe_thread(thread_root.clone(), false).await { + status_handle.set_message(format!("error when subscribing to a thread: {err}")); + } else { + status_handle.set_message("Subscribed to thread!".to_owned()); + } + }) + .await; + + self.input.clear(); + } + } + + async fn unsubscribe_thread(&mut self) { + if let TimelineKind::Thread { thread_root, .. } = &self.kind { + self.call_with_room(async |room, status_handle| { + if let Err(err) = room.unsubscribe_thread(thread_root.clone()).await { + status_handle + .set_message(format!("error when unsubscribing to a thread: {err}")); + } else { + status_handle.set_message("Unsubscribed from thread!".to_owned()); + } + }) + .await; + + self.input.clear(); + } + } + + async fn print_thread_subscription_status(&mut self) { + if let TimelineKind::Thread { thread_root, .. } = &self.kind { + self.call_with_room(async |room, status_handle| { + match room.fetch_thread_subscription(thread_root.clone()).await { + Ok(Some(subscription)) => { + status_handle.set_message(format!( + "Thread subscription status: {}", + if subscription.automatic { "automatic" } else { "manual" } + )); + } + Ok(None) => { + status_handle + .set_message("Thread is not subscribed or does not exist".to_owned()); + } + Err(err) => { + status_handle + .set_message(format!("Error getting thread subscription: {err}")); + } + } + }) + .await; + } + } + async fn handle_command(&mut self, command: input::Command) { match command { input::Command::Invite { user_id } => self.invite_member(&user_id).await, input::Command::Leave => self.leave_room().await, + input::Command::Subscribe => self.subscribe_thread().await, + input::Command::Unsubscribe => self.unsubscribe_thread().await, } } diff --git a/labs/multiverse/src/widgets/status.rs b/labs/multiverse/src/widgets/status.rs index 362650a2c..d025f90fd 100644 --- a/labs/multiverse/src/widgets/status.rs +++ b/labs/multiverse/src/widgets/status.rs @@ -89,7 +89,7 @@ impl Status { let status_message = status_message.clone(); async move { - // Clear the status message in 4 seconds. + // Clear the status message after the standard duration. sleep(MESSAGE_DURATION).await; status_message.lock().take(); }