From a5ff746085dd381459844025ff06150664dd323e Mon Sep 17 00:00:00 2001 From: Kevin Boos <1139460+kevinaboos@users.noreply.github.com> Date: Mon, 15 Jul 2024 10:39:28 -0700 Subject: [PATCH] Properly handle events when the user profile pane is shown (#80) Events that flow into the RoomScreen either get forwarded to the underlying timeline view or the user profile sliding pane. If the pane is currently shown, mouse/touch/tap events are now forwarded to the pane *ONLY*, and not the underlying timeline. This prevents the underlying timeline from being scrolled or clicked when it is partially "hidden" underneath the sliding pane view, which would be confusing to most users. Other events (e.g., draw events) are always forwarded to the underlying timeline. If the pane is not shown, events are also forwarded to the timeline view, as normal. Solution suggested by @jmbejar. --- src/home/room_screen.rs | 17 ++++++++++++++--- src/profile/user_profile.rs | 12 +++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/home/room_screen.rs b/src/home/room_screen.rs index 002f4c80..43dd62b9 100644 --- a/src/home/room_screen.rs +++ b/src/home/room_screen.rs @@ -557,6 +557,8 @@ impl Widget for RoomScreen { // Handle events and actions at the RoomScreen level. fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope){ + let pane = self.user_profile_sliding_pane(id!(user_profile_sliding_pane)); + if let Event::Actions(actions) = event { // Handle the send message button being clicked. if self.button(id!(send_message_button)).clicked(&actions) { @@ -584,7 +586,6 @@ impl Widget for RoomScreen { for action in actions { // Handle the action that requests to show the user profile sliding pane. if let ShowUserProfileAction::ShowUserProfile(avatar_info) = action.as_widget_action().cast() { - let pane = self.user_profile_sliding_pane(id!(user_profile_sliding_pane)); pane.set_info(UserProfileInfo { avatar_info, room_name: self.room_name.clone(), @@ -596,10 +597,20 @@ impl Widget for RoomScreen { } } } - // Forward the event to the inner view, and thus, the inner timeline. - self.view.handle_event(cx, event, scope) + + // Only forward visibility-related events (touch/tap/scroll) to the inner timeline view + // if the user profile sliding pane is not visible. + if event.requires_visibility() && pane.is_currently_shown(cx) { + // Forward the event to the user profile sliding pane, + // preventing the underlying timeline view from receiving it. + pane.handle_event(cx, event, scope); + } else { + // Forward the event to the inner timeline view. + self.view.handle_event(cx, event, scope); + } } } + impl RoomScreenRef { /// Sets this `RoomScreen` widget to display the timeline for the given room. pub fn set_displayed_room(&self, room_name: String, room_id: OwnedRoomId) { diff --git a/src/profile/user_profile.rs b/src/profile/user_profile.rs index 9b2ecdd6..2a7044d3 100644 --- a/src/profile/user_profile.rs +++ b/src/profile/user_profile.rs @@ -180,7 +180,7 @@ live_design! { width: Fill, height: Fit padding: {left: 15} draw_text: { - wrap: Line, + wrap: Word, text_style: {}, color: #000 } @@ -427,6 +427,14 @@ impl Widget for UserProfileSlidingPane { } impl UserProfileSlidingPaneRef { + /// Returns `true` if the pane is both currently visible *and* + /// animator is in the `show` state. + pub fn is_currently_shown(&self, cx: &mut Cx) -> bool { + self.borrow().map_or(false, |inner| + inner.visible && inner.animator_in_state(cx, id!(panel.show)) + ) + } + pub fn set_info(&self, info: UserProfileInfo) { if let Some(mut inner) = self.borrow_mut() { inner.info = Some(info); @@ -441,4 +449,6 @@ impl UserProfileSlidingPaneRef { inner.redraw(cx); } } + + }