From 066af677c335e3dce82488b156281e150c00d19c Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Fri, 6 Sep 2024 14:51:20 -0300 Subject: [PATCH 1/6] Implement smooth scroll --- src/home/room_screen.rs | 154 +++++++++++++++++++++++++++++++++------- 1 file changed, 128 insertions(+), 26 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index ad80beb9..3ca1c8d6 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -204,6 +204,7 @@ live_design! { width: Fill height: Fit flow: Down + padding: {top: 0.0, right: 12.0, bottom: 0.0, left: 12.0} // A reply preview with a vertical bar drawn in the background. @@ -302,6 +303,54 @@ live_design! { padding: 0.0, spacing: 0.0 + show_bg: true + draw_bg: { + instance highlight: 0.0 + instance hover: 0.0 + fn pixel(self) -> vec4 { + return mix( + mix( + #ffffff, + #f3f3f3, + self.hover + ), + #f3f3f3, + self.highlight + ) + } + } + + animator: { + highlight = { + default: off + off = { + redraw: true, + from: { all: Forward {duration: 2.0} } + ease: ExpDecay {d1: 0.80, d2: 0.97} + apply: { draw_bg: {highlight: 0.0} } + } + on = { + redraw: true, + from: { all: Forward {duration: 0.5} } + ease: ExpDecay {d1: 0.80, d2: 0.97} + apply: { draw_bg: {highlight: 1.0} } + } + } + hover = { + default: off + off = { + redraw: true, + from: { all: Snap } + apply: { draw_bg: {hover: 0.0} } + } + on = { + redraw: true, + from: { all: Snap } + apply: { draw_bg: {hover: 1.0} } + } + } + } + // A preview of the earlier message that this message was in reply to. replied_to_message = { flow: Right @@ -1002,7 +1051,7 @@ impl Widget for RoomScreen { } } MessageAction::ReplyPreviewClicked(item_id) => { - let portal_list = self.portal_list(id!(list)); + let mut portal_list = self.portal_list(id!(list)); let Some(tl) = self.tl_state.as_mut() else { continue; }; @@ -1022,7 +1071,17 @@ impl Widget for RoomScreen { }) }); if let Some(index) = message_replied_to_tl_index { - portal_list.set_first_id(index); + let distance = (index as isize - portal_list.first_id() as isize).abs() as f64; + let base_speed = 5.0; + // apply a scaling based on the distance + let scaled_speed = base_speed * (distance * distance); + + portal_list.smooth_scroll_to(cx, index , scaled_speed); + // start highlight animation. + tl.message_highlight_animation_state = MessageHighlightAnimationState::Pending { + item_id: index + 1 + }; + self.redraw(cx); } } @@ -1030,7 +1089,23 @@ impl Widget for RoomScreen { } } } - MessageAction::None => {} + _ => {} + } + + // Handle the highlight animation. + let portal_list = self.portal_list(id!(list)); + let Some(tl) = self.tl_state.as_mut() else { + return; + }; + if let MessageHighlightAnimationState::Pending { item_id } = tl.message_highlight_animation_state { + if portal_list.smooth_scroll_reached(actions) { + cx.widget_action( + widget_uid, + &scope.path, + MessageAction::MessageHighlight(item_id), + ); + tl.message_highlight_animation_state = MessageHighlightAnimationState::Off; + } } // Handle message reply action @@ -1215,7 +1290,6 @@ impl Widget for RoomScreen { } - fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { while let Some(subview) = self.view.draw_walk(cx, scope, walk).step() { // We only care about drawing the portal list. @@ -1437,6 +1511,7 @@ impl RoomScreen { media_cache: MediaCache::new(MediaFormatConst::File, Some(update_sender)), replying_to: None, saved_state: SavedState::default(), + message_highlight_animation_state: MessageHighlightAnimationState::default(), }; (new_tl_state, true) }; @@ -1653,6 +1728,15 @@ struct TimelineUiState { /// The states relevant to the UI display of this timeline that are saved upon /// a `Hide` action and restored upon a `Show` action. saved_state: SavedState, + + /// The state of the message highlight animation. + /// + /// We need to run the animation once the scrolling, triggered by the click of of a + /// a reply preview, ends. so we keep a small state for it. + /// By default, it starts in Off. + /// Once the scrolling is started, the state becomes Pending. + /// If the animation was trigged, the state goes back to Off. + message_highlight_animation_state: MessageHighlightAnimationState, } /// The item index, scroll position, and optional unique IDs of the first `N` events @@ -1678,6 +1762,14 @@ struct ItemIndexScroll { scroll: f64, } + +#[derive(Default, Debug)] +enum MessageHighlightAnimationState { + Pending { item_id: usize, }, + #[default] + Off, +} + /// States that are necessary to save in order to maintain a consistent UI display for a timeline. /// /// These are saved when navigating away from a timeline (upon `Hide`) @@ -2482,6 +2574,7 @@ fn get_profile_display_name(event_tl_item: &EventTimelineItem) -> Option pub enum MessageAction { MessageReply(usize), ReplyPreviewClicked(usize), + MessageHighlight(usize), None, } @@ -2495,10 +2588,22 @@ pub struct Message { can_be_replied_to: bool, #[rust] item_id: usize, + #[animator] + animator: Animator, } impl Widget for Message { fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { + if self.animator_handle_event(cx, event).must_redraw() { + self.redraw(cx); + } + + if !self.animator.is_track_animating(cx, id!(highlight)) + && self.animator_in_state(cx, id!(highlight.on)) + { + self.animator_play(cx, id!(highlight.off)); + } + let widget_uid = self.widget_uid(); if let Event::Actions(actions) = event { @@ -2521,15 +2626,31 @@ impl Widget for Message { } } + if let Event::Actions(actions) = event { + for action in actions { + match action.as_widget_action().cast() { + MessageAction::MessageHighlight(id) if id == self.item_id => { + self.animator_play(cx, id!(highlight.on)); + self.redraw(cx); + } + _ => {} + } + } + } + if let Event::MouseMove(e) = event { let hovered = self.view.area().rect(cx).contains(e.abs); - if self.hovered != hovered { + if (self.hovered != hovered) || (!hovered && self.animator_in_state(cx, id!(hover.on))){ self.hovered = hovered; // TODO: Once we have a context menu, the messageMenu can be displayed on hover or push only // self.view.view(id!(message_menu)).set_visible(hovered); - - self.redraw(cx); + let hover_animator = if self.hovered { + id!(hover.on) + } else { + id!(hover.off) + }; + self.animator_play(cx, hover_animator); } } @@ -2537,25 +2658,6 @@ impl Widget for Message { } fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { - // TODO: need vecs for apply_over(), maybe use an animator so we just set the state here - // and the animator handles the color changes from inside the dsl. - let default_color = vec3(1.0, 1.0, 1.0); // #ffffff - let hover_color = vec3(0.98, 0.98, 0.98); // #fafafa (very light gray) - - let bg_color = if self.hovered { - hover_color - } else { - default_color - }; - - self.view.apply_over( - cx, - live! { - show_bg: true, - draw_bg: {color: (bg_color)} - }, - ); - self.view .button(id!(reply_button)) .set_visible(self.can_be_replied_to); From 882b6118fc574c2b222be87932b62052a720755f Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Thu, 19 Sep 2024 07:40:53 -0300 Subject: [PATCH 2/6] Fix reply preview view id. Leave space for target item --- src/home/room_screen.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 3ca1c8d6..f7fb4eae 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -1072,14 +1072,15 @@ impl Widget for RoomScreen { }); if let Some(index) = message_replied_to_tl_index { let distance = (index as isize - portal_list.first_id() as isize).abs() as f64; - let base_speed = 5.0; + let base_speed = 10.0; // apply a scaling based on the distance let scaled_speed = base_speed * (distance * distance); - portal_list.smooth_scroll_to(cx, index , scaled_speed); + // substract to leave some space. + portal_list.smooth_scroll_to(cx, index - 2, scaled_speed); // start highlight animation. tl.message_highlight_animation_state = MessageHighlightAnimationState::Pending { - item_id: index + 1 + item_id: index }; self.redraw(cx); @@ -2616,7 +2617,7 @@ impl Widget for Message { } } - if let Hit::FingerUp(fe) = event.hits(cx, self.view(id!(reply_preview)).area()) { + if let Hit::FingerUp(fe) = event.hits(cx, self.view(id!(replied_to_message)).area()) { if fe.was_tap() { cx.widget_action( widget_uid, From 7ce7480db94e7ed40d08c4aa85e75b9dd3127b72 Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Thu, 19 Sep 2024 08:15:24 -0300 Subject: [PATCH 3/6] Update bg colors --- src/home/room_screen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index f7fb4eae..ca1bf945 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -311,10 +311,10 @@ live_design! { return mix( mix( #ffffff, - #f3f3f3, + #fafafa, self.hover ), - #f3f3f3, + #fafafa, self.highlight ) } From 615f09f4755e57315632b0c67bfa498de71b1c34 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Mon, 23 Sep 2024 01:00:57 +0200 Subject: [PATCH 4/6] Update makepad for `PortalList::smooth_scroll_to()`, which we now use for scrolling up to replies. Highlight a replied-to message upon click (after auto-scroll to it) in a light blue color, which makes it much more obvious. Explicitly specify the default font color of Html widgets. --- Cargo.lock | 63 +++++++++++++++--------------- src/home/room_screen.rs | 69 ++++++++++++++++++--------------- src/home/welcome_screen.rs | 34 ++-------------- src/shared/html_or_plaintext.rs | 1 + src/shared/search_bar.rs | 2 +- 5 files changed, 74 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f41a8ac0..0f2af4d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1731,7 +1731,7 @@ dependencies = [ [[package]] name = "makepad-derive-live" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -1740,7 +1740,7 @@ dependencies = [ [[package]] name = "makepad-derive-wasm-bridge" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-micro-proc-macro", ] @@ -1748,7 +1748,7 @@ dependencies = [ [[package]] name = "makepad-derive-widget" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id", "makepad-micro-proc-macro", @@ -1757,7 +1757,7 @@ dependencies = [ [[package]] name = "makepad-draw" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "ab_glyph_rasterizer", "fxhash", @@ -1774,17 +1774,17 @@ dependencies = [ [[package]] name = "makepad-futures" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-futures-legacy" version = "0.7.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-html" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id", ] @@ -1792,7 +1792,7 @@ dependencies = [ [[package]] name = "makepad-http" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-jni-sys" @@ -1803,7 +1803,7 @@ checksum = "9775cbec5fa0647500c3e5de7c850280a88335d1d2d770e5aa2332b801ba7064" [[package]] name = "makepad-live-compiler" version = "0.5.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-derive-live", "makepad-live-tokenizer", @@ -1813,7 +1813,7 @@ dependencies = [ [[package]] name = "makepad-live-id" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id-macros", ] @@ -1821,7 +1821,7 @@ dependencies = [ [[package]] name = "makepad-live-id-macros" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-micro-proc-macro", ] @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "makepad-live-tokenizer" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id", "makepad-math", @@ -1839,7 +1839,7 @@ dependencies = [ [[package]] name = "makepad-markdown" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-id", ] @@ -1847,25 +1847,26 @@ dependencies = [ [[package]] name = "makepad-math" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-micro-proc-macro" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-micro-serde" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ + "makepad-live-id", "makepad-micro-serde-derive", ] [[package]] name = "makepad-micro-serde-derive" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-micro-proc-macro", ] @@ -1873,12 +1874,12 @@ dependencies = [ [[package]] name = "makepad-objc-sys" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "makepad-platform" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "hilog-sys", "makepad-android-state", @@ -1900,7 +1901,7 @@ dependencies = [ [[package]] name = "makepad-rustybuzz" version = "0.8.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "bitflags 1.3.2", "bytemuck", @@ -1915,7 +1916,7 @@ dependencies = [ [[package]] name = "makepad-shader-compiler" version = "0.5.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-live-compiler", ] @@ -1923,7 +1924,7 @@ dependencies = [ [[package]] name = "makepad-vector" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "resvg", "ttf-parser", @@ -1932,7 +1933,7 @@ dependencies = [ [[package]] name = "makepad-wasm-bridge" version = "0.4.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-derive-wasm-bridge", "makepad-live-id", @@ -1941,7 +1942,7 @@ dependencies = [ [[package]] name = "makepad-widgets" version = "0.6.0" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-derive-widget", "makepad-draw", @@ -1955,7 +1956,7 @@ dependencies = [ [[package]] name = "makepad-windows" version = "0.51.1" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "windows-core 0.51.1 (git+https://github.com/makepad/makepad?branch=rik)", "windows-targets 0.48.5", @@ -1964,7 +1965,7 @@ dependencies = [ [[package]] name = "makepad-zune-core" version = "0.2.14" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "bitflags 2.4.1", ] @@ -1972,7 +1973,7 @@ dependencies = [ [[package]] name = "makepad-zune-inflate" version = "0.2.54" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "simd-adler32", ] @@ -1980,7 +1981,7 @@ dependencies = [ [[package]] name = "makepad-zune-jpeg" version = "0.3.17" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-zune-core", ] @@ -1988,7 +1989,7 @@ dependencies = [ [[package]] name = "makepad-zune-png" version = "0.2.1" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "makepad-zune-core", "makepad-zune-inflate", @@ -3941,7 +3942,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "ttf-parser" version = "0.21.1" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" [[package]] name = "typenum" @@ -4348,7 +4349,7 @@ dependencies = [ [[package]] name = "windows-core" version = "0.51.1" -source = "git+https://github.com/makepad/makepad?branch=rik#fdcb02233b5fde78e8acdcec1f6f7ccce541a8e5" +source = "git+https://github.com/makepad/makepad?branch=rik#98cc605647409a95c60405837ff1fbeb35100a4b" dependencies = [ "windows-targets 0.48.5", ] diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 19abf0b9..27ca5f90 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -314,7 +314,7 @@ live_design! { #fafafa, self.hover ), - #fafafa, + #c5d6fa, // light blue self.highlight ) } @@ -840,7 +840,7 @@ live_design! { return sdf.result; } } - draw_label: { + draw_text: { color: (MESSAGE_TEXT_COLOR), text_style: {}, @@ -1104,36 +1104,39 @@ impl Widget for RoomScreen { }; let tl_idx = item_id as usize; - if let Some(tl_item) = tl.items.get(tl_idx) { - if let Some(tl_event_item) = tl_item.as_event() { - if let Some(message) = tl_event_item.content().as_message() { - if let Some(details) = message.in_reply_to() { - // Find the replyed message on timeline so we use the id for scrolling portal list - let message_replied_to_tl_index = - tl.items.iter().position(|i| { - i.as_event() - .and_then(|e| e.event_id()) - .map_or(false, |event_id| { - details.event_id == event_id - }) - }); - if let Some(index) = message_replied_to_tl_index { - let distance = (index as isize - portal_list.first_id() as isize).abs() as f64; - let base_speed = 10.0; - // apply a scaling based on the distance - let scaled_speed = base_speed * (distance * distance); - - // substract to leave some space. - portal_list.smooth_scroll_to(cx, index - 2, scaled_speed); - // start highlight animation. - tl.message_highlight_animation_state = MessageHighlightAnimationState::Pending { - item_id: index - }; - - self.redraw(cx); - } - } - } + if let Some(details) = tl.items.get(tl_idx) + .and_then(|item| item.as_event()) + .and_then(|event| event.content().as_message()) + .and_then(|message| message.in_reply_to()) + { + // Attempt to find the index of replied-to message on the timeline. + // Start from the current item's index (`tl_idx`)and search backwards, + // since we know the replied-to message must come before the current item. + let replied_to_msg_tl_index = tl.items + .focus() + .narrow(..tl_idx) + .into_iter() + .rposition(|i| i.as_event() + .and_then(|e| e.event_id()) + .map_or(false, |ev_id| ev_id == details.event_id) + ); + + if let Some(index) = replied_to_msg_tl_index { + let distance = (index as isize - portal_list.first_id() as isize).abs() as f64; + let base_speed = 10.0; + // apply a scaling based on the distance + let scaled_speed = base_speed * (distance * distance); + // Scroll to the message right before the replied-to message. + // FIXME: `smooth_scroll_to` should accept a scroll offset parameter too, + // so that we can scroll to the replied-to message and have it + // appear beneath the top of the viewport. + portal_list.smooth_scroll_to(cx, index - 1, scaled_speed); + // start highlight animation. + tl.message_highlight_animation_state = MessageHighlightAnimationState::Pending { + item_id: index + }; + + self.redraw(cx); } } } @@ -1153,6 +1156,8 @@ impl Widget for RoomScreen { MessageAction::MessageHighlight(item_id), ); tl.message_highlight_animation_state = MessageHighlightAnimationState::Off; + // Adjust the scrolled-to item's position to be slightly beneath the top of the viewport. + // portal_list.set_first_id_and_scroll(portal_list.first_id(), 15.0); } } diff --git a/src/home/welcome_screen.rs b/src/home/welcome_screen.rs index d4f68023..ba6aca3c 100644 --- a/src/home/welcome_screen.rs +++ b/src/home/welcome_screen.rs @@ -6,6 +6,7 @@ live_design! { import makepad_draw::shader::std::*; import crate::shared::styles::*; + import crate::shared::html_or_plaintext::*; WELCOME_TEXT_COLOR: #x4 @@ -41,9 +42,10 @@ live_design! { } // Using the HTML widget to taking advantage of embedding a link within text with proper vertical alignment - { + { padding: {top: 12, left: 0.} font_size: 14. + font_color: (WELCOME_TEXT_COLOR) draw_normal: { color: (WELCOME_TEXT_COLOR) } @@ -55,36 +57,6 @@ live_design! { // color_pressed: #f00, // color_hover: #0f0, // } - draw_bg: { - instance border_width: 0.0 - instance border_color: #0000 - instance inset: vec4(0.0, 0.0, 0.0, 0.0) - instance radius: 2. - instance color: #x0 - fn get_color(self) -> vec4 { - return self.color - } - - fn get_border_color(self) -> vec4 { - return self.border_color - } - - fn pixel(self) -> vec4 { - let sdf = Sdf2d::viewport(self.pos * self.rect_size) - sdf.box( - self.inset.x + self.border_width, - self.inset.y + self.border_width, - self.rect_size.x - (self.inset.x + self.inset.z + self.border_width * 2.0), - self.rect_size.y - (self.inset.y + self.inset.w + self.border_width * 2.0), - max(1.0, self.radius) - ) - sdf.fill_keep(self.get_color()) - if self.border_width > 0.0 { - sdf.stroke(self.get_border_color(), self.border_width) - } - return sdf.result; - } - } } body:" Look out for the latest announcements in our Matrix channel: [m] Robrix
diff --git a/src/shared/html_or_plaintext.rs b/src/shared/html_or_plaintext.rs index 3241c78a..dc2bcc86 100644 --- a/src/shared/html_or_plaintext.rs +++ b/src/shared/html_or_plaintext.rs @@ -38,6 +38,7 @@ live_design! { line_spacing: (HTML_LINE_SPACING), width: Fill, height: Fit, // see comment in `HtmlOrPlaintext` font_size: (MESSAGE_FONT_SIZE), + font_color: (MESSAGE_TEXT_COLOR), draw_normal: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } } draw_italic: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } } draw_bold: { color: (MESSAGE_TEXT_COLOR), text_style: { height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING) } } diff --git a/src/shared/search_bar.rs b/src/shared/search_bar.rs index 79402e64..c7ab961f 100644 --- a/src/shared/search_bar.rs +++ b/src/shared/search_bar.rs @@ -45,7 +45,7 @@ live_design! { empty_message: "Search" - draw_label: { + draw_text: { text_style: { font_size: 10 }, fn get_color(self) -> vec4 { return (COLOR_TEXT_INPUT_IDLE); From d98b40d70982b8823fabb313b8e085a99ba78183 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Mon, 23 Sep 2024 01:06:26 +0200 Subject: [PATCH 5/6] clarify to-do about unimplemented ability to scroll up to events that have not yet been fetched in the timeline --- src/home/room_screen.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 27ca5f90..47da37a2 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -1137,6 +1137,8 @@ impl Widget for RoomScreen { }; self.redraw(cx); + } else { + log!("TODO: the replied-to message was not yet available in the timeline."); } } } From 7388dba319ace0132f232aa9fc0db0a1d23e2e94 Mon Sep 17 00:00:00 2001 From: Kevin Boos Date: Mon, 23 Sep 2024 01:19:32 +0200 Subject: [PATCH 6/6] Speed up searching for the timeline index of the replied-to message Use `Vector::focus()` with reverse iteration from the current reply message, searching backwards since the replied-to message must come before the reply message --- src/home/room_screen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 47da37a2..3e885a4d 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -1118,7 +1118,7 @@ impl Widget for RoomScreen { .into_iter() .rposition(|i| i.as_event() .and_then(|e| e.event_id()) - .map_or(false, |ev_id| ev_id == details.event_id) + .is_some_and(|ev_id| ev_id == details.event_id) ); if let Some(index) = replied_to_msg_tl_index {