@@ -26,9 +26,10 @@ use matrix_sdk::{
2626use matrix_sdk_ui:: timeline:: {
2727 self , EmbeddedEvent , EncryptedMessage , EventTimelineItem , InReplyToDetails , MemberProfileChange , MsgLikeContent , MsgLikeKind , PollState , RoomMembershipChange , TimelineDetails , TimelineEventItemId , TimelineItem , TimelineItemContent , TimelineItemKind , VirtualTimelineItem
2828} ;
29+ use tokio:: sync:: Notify ;
2930
3031use crate :: {
31- app:: { AppState , AppStateAction , SelectedRoom } , avatar_cache, event_preview:: { plaintext_body_of_timeline_item, text_preview_of_encrypted_message, text_preview_of_member_profile_change, text_preview_of_other_state, text_preview_of_redacted_message, text_preview_of_room_membership_change, text_preview_of_timeline_item} , home:: { edited_indicator:: EditedIndicatorWidgetRefExt , editing_pane:: EditingPaneState , loading_pane:: { LoadingPaneState , LoadingPaneWidgetExt } , rooms_list:: { RoomsListRef , RoomsListAction } } , location:: init_location_subscriber, media_cache:: { MediaCache , MediaCacheEntry } , profile:: {
32+ app:: { AppStateAction , SelectedRoom } , avatar_cache, event_preview:: { plaintext_body_of_timeline_item, text_preview_of_encrypted_message, text_preview_of_member_profile_change, text_preview_of_other_state, text_preview_of_redacted_message, text_preview_of_room_membership_change, text_preview_of_timeline_item} , home:: { edited_indicator:: EditedIndicatorWidgetRefExt , editing_pane:: EditingPaneState , loading_pane:: { LoadingPaneState , LoadingPaneWidgetExt } , rooms_list:: { RoomsListRef , RoomsListAction } } , location:: init_location_subscriber, media_cache:: { MediaCache , MediaCacheEntry } , profile:: {
3233 user_profile:: { AvatarState , ShowUserProfileAction , UserProfile , UserProfileAndRoomId , UserProfilePaneInfo , UserProfileSlidingPaneRef , UserProfileSlidingPaneWidgetExt } ,
3334 user_profile_cache,
3435 } , shared:: {
@@ -1402,6 +1403,7 @@ impl Widget for RoomScreen {
14021403 TimelineItemContent :: MsgLike ( msg_like_content) => match & msg_like_content. kind {
14031404 MsgLikeKind :: Message ( _) | MsgLikeKind :: Sticker ( _) => {
14041405 let prev_event = tl_idx. checked_sub ( 1 ) . and_then ( |i| tl_items. get ( i) ) ;
1406+ println ! ( "msg_like_content {:?}" , msg_like_content. as_message( ) . unwrap( ) . body( ) ) ;
14051407 populate_message_view (
14061408 cx,
14071409 list,
@@ -1531,6 +1533,7 @@ impl RoomScreen {
15311533 fn process_timeline_updates ( & mut self , cx : & mut Cx , portal_list : & PortalListRef ) {
15321534 let top_space = self . view ( id ! ( top_space) ) ;
15331535 let jump_to_bottom = self . jump_to_bottom_button ( id ! ( jump_to_bottom) ) ;
1536+ let loading_pane = self . loading_pane ( id ! ( loading_pane) ) ;
15341537 let curr_first_id = portal_list. first_id ( ) ;
15351538 let ui = self . widget_uid ( ) ;
15361539 let Some ( tl) = self . tl_state . as_mut ( ) else { return } ;
@@ -1799,6 +1802,61 @@ impl RoomScreen {
17991802 TimelineUpdate :: OwnUserReadReceipt ( receipt) => {
18001803 tl. latest_own_user_receipt = Some ( receipt) ;
18011804 }
1805+ TimelineUpdate :: ScrollToMessage { event_id } => {
1806+ // Search through the timeline to find the message with the given event_id
1807+ let mut num_items_searched = 0 ;
1808+ let target_msg_tl_index = tl. items
1809+ . focus ( )
1810+ . into_iter ( )
1811+ . position ( |item| {
1812+ num_items_searched += 1 ;
1813+ item. as_event ( )
1814+ . and_then ( |e| e. event_id ( ) )
1815+ . is_some_and ( |ev_id| ev_id == event_id)
1816+ } ) ;
1817+ if let Some ( index) = target_msg_tl_index {
1818+ let current_first_index = portal_list. first_id ( ) ;
1819+ let speed = index. saturating_sub ( 1 ) . abs_diff ( current_first_index) as f64 / ( SMOOTH_SCROLL_TIME . get ( ) as f64 * 0.001 ) ;
1820+ portal_list. smooth_scroll_to (
1821+ cx,
1822+ index. saturating_sub ( 1 ) ,
1823+ //index.saturating_sub(1).abs_diff(current_first_index) as f64 / (SMOOTH_SCROLL_TIME as f64 * 0.001),
1824+ speed,
1825+ None ,
1826+ ) ;
1827+ // start highlight animation.
1828+ tl. message_highlight_animation_state = MessageHighlightAnimationState :: Pending {
1829+ item_id : index
1830+ } ;
1831+ } else {
1832+ log ! ( "essage not found - trigger backwards pagination to find it" ) ;
1833+ // Message not found - trigger backwards pagination to find it
1834+ loading_pane. set_state (
1835+ cx,
1836+ LoadingPaneState :: BackwardsPaginateUntilEvent {
1837+ target_event_id : event_id. clone ( ) ,
1838+ events_paginated : 0 ,
1839+ request_sender : tl. request_sender . clone ( ) ,
1840+ } ,
1841+ ) ;
1842+ loading_pane. show ( cx) ;
1843+
1844+ tl. request_sender . send_if_modified ( |requests| {
1845+ if let Some ( existing) = requests. iter_mut ( ) . find ( |r| r. room_id == tl. room_id ) {
1846+ // Re-use existing request
1847+ existing. target_event_id = event_id. clone ( ) ;
1848+ } else {
1849+ requests. push ( BackwardsPaginateUntilEventRequest {
1850+ room_id : tl. room_id . clone ( ) ,
1851+ target_event_id : event_id. clone ( ) ,
1852+ starting_index : 0 , // Search from the beginning since we don't know where it is
1853+ current_tl_len : tl. items . len ( ) ,
1854+ } ) ;
1855+ }
1856+ true
1857+ } ) ;
1858+ }
1859+ }
18021860 }
18031861 }
18041862
@@ -2850,7 +2908,10 @@ pub enum TimelineUpdate {
28502908 UserPowerLevels ( UserPowerLevels ) ,
28512909 /// An update to the currently logged-in user's own read receipt for this room.
28522910 OwnUserReadReceipt ( Receipt ) ,
2853-
2911+ /// Scroll the timeline to the given event.
2912+ ScrollToMessage {
2913+ event_id : OwnedEventId ,
2914+ }
28542915}
28552916
28562917thread_local ! {
@@ -3578,6 +3639,7 @@ pub fn populate_text_message_content(
35783639 if let Some ( fb) = formatted_body. as_ref ( )
35793640 . and_then ( |fb| ( fb. format == MessageFormat :: Html ) . then_some ( fb) )
35803641 {
3642+ println ! ( "fb.body {:?}" , fb. body) ;
35813643 message_content_widget. show_html (
35823644 cx,
35833645 utils:: linkify (
@@ -4353,8 +4415,6 @@ pub struct Message {
43534415 /// The jump option required for searched messages.
43544416 /// Contains the room ID, event ID for the message, and whether it's from an all-rooms search.
43554417 #[ rust] jump_option : Option < JumpToMessageRequest > ,
4356- /// Add a small delay to ensure new room tab is opened before jumping to the message.
4357- #[ rust] jump_delay : Timer ,
43584418}
43594419
43604420impl Widget for Message {
@@ -4368,18 +4428,6 @@ impl Widget for Message {
43684428 {
43694429 self . animator_play ( cx, id ! ( highlight. off) ) ;
43704430 }
4371- if let Event :: Timer ( te) = event {
4372- if let ( Some ( _) , Some ( jump_request) ) = ( self . jump_delay . is_timer ( te) , & self . jump_option ) {
4373- cx. widget_action (
4374- self . widget_uid ( ) ,
4375- & scope. path ,
4376- MessageAction :: ScrollToMessage {
4377- room_id : jump_request. room_id . clone ( ) ,
4378- event_id : jump_request. event_id . clone ( ) ,
4379- }
4380- ) ;
4381- }
4382- }
43834431 if let Some ( jump_request) = & self . jump_option {
43844432 if let Event :: Actions ( actions) = event {
43854433 if self . view . button ( id ! ( jump_to_this_message. jump_button) ) . clicked ( actions) {
@@ -4396,58 +4444,16 @@ impl Widget for Message {
43964444 room_id : jump_request. room_id . clone ( ) . into ( ) ,
43974445 room_name,
43984446 } ;
4447+ let notify = Arc :: new ( Notify :: new ( ) ) ;
43994448 cx. widget_action (
44004449 self . widget_uid ( ) ,
44014450 & scope. path ,
4402- RoomsListAction :: Selected ( target_selected_room)
4451+ RoomsListAction :: Selected ( target_selected_room, Some ( notify . clone ( ) ) )
44034452 ) ;
4404- // if let Some(selected_room) = {
4405- // let app_state = scope.data.get::<AppState>().unwrap();
4406- // &app_state.selected_room
4407- // } {
4408- // cx.widget_action(
4409- // self.widget_uid(),
4410- // &Scope::default().path,
4411- // StackNavigationAction::PopToRoot
4412- // );
4413- // println!("selected_room.room_id(){:?}", selected_room.room_id());
4414- // // If room_id is not the selected room, select the room and open its dock tab
4415- // if selected_room.room_id() != &jump_request.room_id {
4416- // let room_name: Option<String> = {
4417- // let rooms_list_ref = cx.get_global::<RoomsListRef>();
4418- // rooms_list_ref.get_room_name(&jump_request.room_id)
4419- // };
4420-
4421- // let target_selected_room = SelectedRoom::JoinedRoom {
4422- // room_id: jump_request.room_id.clone().into(),
4423- // room_name,
4424- // };
4425- // println!("Jumping to message in room: {} StackNavigationAction::PopToRoot", target_selected_room.room_id());
4426-
4427- // // Dispatch action to select the room and open its dock tab
4428- // cx.widget_action(
4429- // self.widget_uid(),
4430- // &scope.path,
4431- // RoomsListAction::Selected(target_selected_room)
4432- // );
4433- // }
4434- // }
4435- // Add a jump delay to ensure new room tab is opened before jumping to the message.
4436- self . jump_delay = cx. start_timeout ( 1.0 ) ;
4453+ submit_async_request ( MatrixRequest :: WaitForRoomOpenToJump { notify, room_id : jump_request. room_id . clone ( ) , event_id : jump_request. event_id . clone ( ) } ) ;
44374454 }
44384455 }
44394456 self . view . handle_event ( cx, event, scope) ;
4440- let message_view_area = self . view . area ( ) ;
4441- match event. hits ( cx, message_view_area) {
4442- Hit :: FingerDown ( fe) => {
4443- cx. set_key_focus ( message_view_area) ;
4444- // A left click to scroll to the message in room screen.
4445- if fe. device . mouse_button ( ) . is_some_and ( |b| b. is_primary ( ) ) {
4446- self . jump_delay = cx. start_timeout ( 0.5 ) ;
4447- }
4448- }
4449- _ => { }
4450- }
44514457 return ;
44524458 }
44534459 let Some ( details) = self . details . clone ( ) else { return } ;
@@ -4579,9 +4585,6 @@ impl Message {
45794585 self . jump_option = Some ( jump_option) ;
45804586 self . view . view ( id ! ( jump_to_this_message) )
45814587 . set_visible ( cx, true ) ;
4582- self . view . apply_over ( cx, live ! {
4583- cursor: Hand
4584- } ) ;
45854588 }
45864589}
45874590
0 commit comments