diff --git a/src/home/room_preview.rs b/src/home/room_preview.rs index d1fa5c2..c7b43dd 100644 --- a/src/home/room_preview.rs +++ b/src/home/room_preview.rs @@ -104,6 +104,7 @@ live_design! { } RoomPreview = {{RoomPreview}} { + height: 65. // Wraps the RoomPreviewContent in an AdaptiveView // to change the displayed content (and its layout) based on the available space in the sidebar. adaptive_preview = { diff --git a/src/home/rooms_list.rs b/src/home/rooms_list.rs index bf933ae..625dc51 100644 --- a/src/home/rooms_list.rs +++ b/src/home/rooms_list.rs @@ -5,7 +5,7 @@ use matrix_sdk::ruma::{MilliSecondsSinceUnixEpoch, OwnedRoomId}; use crate::{app::AppState, sliding_sync::{submit_async_request, MatrixRequest, PaginationDirection}}; -use super::room_preview::RoomPreviewAction; +use super::{room_preview::RoomPreviewAction, rooms_sidebar::{RoomsSideBarAction, RoomsSideBarFilter}}; /// Whether to pre-paginate visible rooms at least once in order to /// be able to display the latest message in the room preview, @@ -232,6 +232,25 @@ impl RoomsList { format!("Loaded {} rooms.", self.all_rooms.len()) }; } + fn filter_rooms(&mut self, keywords: &str) { + let keywords = keywords.to_lowercase(); + + if keywords.is_empty() { + self.display_filter = RoomDisplayFilter::default(); + self.displayed_rooms = self.all_rooms.keys().cloned().collect(); + return; + } + + self.display_filter = RoomDisplayFilter(Box::new(move |room| { + let room_name = room.room_name.as_ref().map(|n| n.to_lowercase()); + room_name.as_ref().map_or(false, |n| n.contains(&keywords)) + })); + + self.displayed_rooms = self.all_rooms.iter() + .filter(|(_, room)| (self.display_filter)(&room)) + .map(|(room_id, _)| room_id.clone()) + .collect(); + } } impl Widget for RoomsList { @@ -369,6 +388,7 @@ impl Widget for RoomsList { self.redraw(cx); } } + self.widget_match_event(cx, event, scope); } @@ -397,7 +417,6 @@ impl Widget for RoomsList { while let Some(item_id) = list.next_visible_item(cx) { let mut scope = Scope::empty(); - // Draw the room preview for each room in the `displayed_rooms` list. let room_to_draw = self.displayed_rooms .get(item_id) @@ -443,3 +462,15 @@ impl Widget for RoomsList { } } + +impl WidgetMatchEvent for RoomsList { + fn handle_actions(&mut self, cx: &mut Cx, actions:&Actions, _scope: &mut Scope) { + for action in actions { + if let RoomsSideBarAction::Filter { keywords, filter } = action.as_widget_action().cast() { + if filter == RoomsSideBarFilter::Rooms { + self.filter_rooms(&keywords); + } + } + } + } +} \ No newline at end of file diff --git a/src/home/rooms_sidebar.rs b/src/home/rooms_sidebar.rs index 71e6045..041e2f9 100644 --- a/src/home/rooms_sidebar.rs +++ b/src/home/rooms_sidebar.rs @@ -1,5 +1,7 @@ use makepad_widgets::*; +use crate::shared::search_bar::SearchBarAction; + live_design! { import makepad_widgets::base::*; import makepad_widgets::theme_desktop_dark::*; @@ -10,6 +12,85 @@ live_design! { import crate::shared::adaptive_view::AdaptiveView; import crate::home::rooms_list::RoomsList; + import crate::shared::cached_widget::CachedWidget; + + ICON_COLLAPSE = dep("crate://self/resources/icons/collapse.svg") + ICON_ADD = dep("crate://self/resources/icons/add.svg") + + CollapsableTitle = { + width: Fill, height: Fit + flow: Right, spacing: 10. + align: {x: 0.0, y: 0.5} + collapse_icon = { + draw_icon: { + svg_file: (ICON_COLLAPSE), + uniform rotation_angle: -90.0, + fn get_color(self) -> vec4 { + // return #666; + return (COLOR_TEXT_IDLE); + } + + // Support rotation of the icon + fn clip_and_transform_vertex(self, rect_pos: vec2, rect_size: vec2) -> vec4 { + let clipped: vec2 = clamp( + self.geom_pos * rect_size + rect_pos, + self.draw_clip.xy, + self.draw_clip.zw + ) + self.pos = (clipped - rect_pos) / rect_size + + // Calculate the texture coordinates based on the rotation angle + let angle_rad = self.rotation_angle * 3.14159265359 / 180.0; + let cos_angle = cos(angle_rad); + let sin_angle = sin(angle_rad); + let rot_matrix = mat2( + cos_angle, -sin_angle, + sin_angle, cos_angle + ); + self.tex_coord1 = mix( + self.icon_t1.xy, + self.icon_t2.xy, + (rot_matrix * (self.pos.xy - vec2(0.5))) + vec2(0.5) + ); + + return self.camera_projection * (self.camera_view * (self.view_transform * vec4( + clipped.x, + clipped.y, + self.draw_depth + self.draw_zbias, + 1. + ))) + } + } + icon_walk: {width: 12, height: 12} + } + + title =