Skip to content

Commit c2dd5e9

Browse files
committed
Redesign SearchBar into a single shared RoomFilterInputBar
The new `RoomFilterInputBar` is shared across both the narrow "Mobile"-oriented UI and the wider "Desktop"-oriented UI, and is now shown in different places on each. We place the filter bar inside of a `CachedWidget` to ensure that there is only a singleton instance of the `RoomFilterInputBar` globally across the whole app. This means that the text is now shared and that there is no need to filter its actions across multiple different SearchBar actions. Thus, it now automatically works when transitioning between the mobile and desktop views.
1 parent d2c175f commit c2dd5e9

5 files changed

Lines changed: 99 additions & 115 deletions

File tree

src/home/home_screen.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ live_design! {
99
use crate::home::rooms_sidebar::RoomsSideBar;
1010
use crate::home::spaces_dock::SpacesDock;
1111
use crate::shared::styles::*;
12-
use crate::shared::search_bar::SearchBar;
12+
use crate::shared::room_filter_input_bar::RoomFilterInputBar;
1313
use crate::home::main_desktop_ui::MainDesktopUI;
1414

1515
NavigationWrapper = {{NavigationWrapper}} {
@@ -31,6 +31,14 @@ live_design! {
3131
<View> {
3232
flow: Down
3333
width: Fill, height: Fill
34+
35+
<CachedWidget> {
36+
<RoomFilterInputBar> {
37+
input = {
38+
empty_message: "Filter rooms..."
39+
}
40+
}
41+
}
3442
<MainDesktopUI> {}
3543
}
3644
}
@@ -45,10 +53,12 @@ live_design! {
4553

4654
<NavigationWrapper> {
4755
view_stack = <StackNavigation> {
56+
4857
root_view = {
4958
padding: {top: 40.}
5059
flow: Down
5160
width: Fill, height: Fill
61+
5262
sidebar = <RoomsSideBar> {}
5363
spaces = <SpacesDock> {}
5464
}

src/home/rooms_list.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ use crate::{
66
app::{AppState, SelectedRoom},
77
room::room_display_filter::{FilterableRoom, RoomDisplayFilter, RoomDisplayFilterBuilder, RoomFilterCriteria, SortFn},
88
shared::{collapsible_header::{CollapsibleHeaderAction, CollapsibleHeaderWidgetRefExt, HeaderCategory},
9-
jump_to_bottom_button::UnreadMessageCount},
9+
jump_to_bottom_button::UnreadMessageCount, room_filter_input_bar::RoomFilterAction},
1010
sliding_sync::{submit_async_request, MatrixRequest, PaginationDirection},
1111
};
12-
13-
use super::{room_preview::RoomPreviewAction, rooms_sidebar::RoomsViewAction};
12+
use super::room_preview::RoomPreviewAction;
1413

1514
/// Whether to pre-paginate visible rooms at least once in order to
1615
/// be able to display the latest message in the room preview,
@@ -625,8 +624,8 @@ impl Widget for RoomsList {
625624

626625
if let Event::Actions(actions) = event {
627626
for action in actions {
628-
if let RoomsViewAction::Search(search_text) = action.as_widget_action().cast() {
629-
self.update_displayed_rooms(cx, &search_text);
627+
if let RoomFilterAction::Changed(keywords) = action.as_widget_action().cast() {
628+
self.update_displayed_rooms(cx, &keywords);
630629
}
631630
}
632631
}

src/home/rooms_sidebar.rs

Lines changed: 55 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
use makepad_widgets::*;
1+
//! The RoomsSideBar is the widget that contains the RoomsList and other items.
2+
//!
3+
//! It differs in what content it includes based on the adaptive view:
4+
//! * On a narrow mobile view, it acts as the root_view of StackNavigation
5+
//! * It includes a title label, a search bar, and the RoomsList.
6+
//! * On a wide desktop view, it acts as a permanent tab that is on the left side of the dock.
7+
//! * It only includes a title label and the RoomsList, because the SearcBar
8+
//! is at the top of the HomeScreen in Desktop view.
29
3-
use crate::shared::search_bar::SearchBarAction;
10+
use makepad_widgets::*;
411

512
live_design! {
613
use link::theme::*;
@@ -9,94 +16,66 @@ live_design! {
916

1017
use crate::shared::styles::*;
1118
use crate::shared::helpers::*;
12-
use crate::shared::search_bar::SearchBar;
19+
use crate::shared::room_filter_input_bar::RoomFilterInputBar;
1320

1421
use crate::home::rooms_list::RoomsList;
1522

16-
RoomsView = {{RoomsView}} {
17-
show_bg: true,
18-
draw_bg: {
19-
instance bg_color: (COLOR_PRIMARY)
20-
instance border_color: #f2f2f2
21-
instance border_size: 0.003
23+
pub RoomsSideBar = <AdaptiveView> {
24+
Desktop = <View> {
25+
padding: {top: 20, left: 10, right: 10}
26+
flow: Down, spacing: 10
27+
width: Fill, height: Fill
28+
29+
show_bg: true,
30+
draw_bg: {
31+
instance bg_color: (COLOR_PRIMARY)
32+
instance border_color: #f2f2f2
33+
instance border_size: 0.003
2234

23-
// Draws a right-side border
24-
fn pixel(self) -> vec4 {
25-
if self.pos.x > 1.0 - self.border_size {
26-
return self.border_color;
27-
} else {
28-
return self.bg_color;
35+
// Draws a right-side border
36+
fn pixel(self) -> vec4 {
37+
if self.pos.x > 1.0 - self.border_size {
38+
return self.border_color;
39+
} else {
40+
return self.bg_color;
41+
}
2942
}
3043
}
31-
}
32-
<Label> {
33-
text: "All Rooms"
34-
draw_text: {
35-
color: #x0
36-
text_style: <TITLE_TEXT>{}
44+
45+
sidebar_title = <Label> {
46+
text: "All Rooms"
47+
draw_text: {
48+
color: #x0
49+
text_style: <TITLE_TEXT>{}
50+
}
3751
}
38-
}
39-
search_bar = <SearchBar> {
40-
input = {
41-
empty_message: "Filter rooms..."
52+
<CachedWidget> {
53+
rooms_list = <RoomsList> {}
4254
}
43-
}
44-
<CachedWidget> {
45-
rooms_list = <RoomsList> {}
46-
}
47-
}
48-
49-
pub RoomsSideBar = <AdaptiveView> {
50-
Desktop = <RoomsView> {
51-
padding: {top: 20., left: 10., right: 10.}
52-
flow: Down, spacing: 10
53-
width: Fill, height: Fill
5455
},
55-
Mobile = <RoomsView> {
56-
padding: {top: 17., left: 17., right: 17.}
56+
57+
Mobile = <View> {
58+
padding: {top: 17, left: 17, right: 17}
5759
flow: Down, spacing: 7
5860
width: Fill, height: Fill
59-
}
60-
}
61-
}
62-
63-
#[derive(Clone, Debug, DefaultNone)]
64-
pub enum RoomsViewAction {
65-
/// Search for rooms
66-
Search(String),
67-
None,
68-
}
69-
70-
#[derive(Widget, Live, LiveHook)]
71-
pub struct RoomsView {
72-
#[deref]
73-
view: View,
74-
}
7561

76-
impl Widget for RoomsView {
77-
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
78-
self.view.handle_event(cx, event, scope);
79-
self.widget_match_event(cx, event, scope);
80-
}
81-
82-
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
83-
self.view.draw_walk(cx, scope, walk)
84-
}
85-
}
86-
87-
impl WidgetMatchEvent for RoomsView {
88-
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) {
89-
let widget_uid = self.widget_uid();
90-
for action in actions {
91-
match action.as_widget_action().cast() {
92-
SearchBarAction::Search(keywords) => {
93-
cx.widget_action(widget_uid, &scope.path, RoomsViewAction::Search(keywords.clone()));
62+
sidebar_title = <Label> {
63+
text: "All Rooms"
64+
draw_text: {
65+
color: #x0
66+
text_style: <TITLE_TEXT>{}
9467
}
95-
SearchBarAction::ResetSearch => {
96-
cx.widget_action(widget_uid, &scope.path, RoomsViewAction::Search("".to_string()));
68+
}
69+
<CachedWidget> {
70+
<RoomFilterInputBar> {
71+
input = {
72+
empty_message: "Filter rooms..."
73+
}
9774
}
98-
_ => {}
75+
}
76+
<CachedWidget> {
77+
rooms_list = <RoomsList> {}
9978
}
10079
}
10180
}
102-
}
81+
}

src/shared/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub mod icon_button;
99
pub mod jump_to_bottom_button;
1010
pub mod mentionable_text_input;
1111
pub mod popup_list;
12-
pub mod search_bar;
12+
pub mod room_filter_input_bar;
1313
pub mod styles;
1414
pub mod text_or_image;
1515
pub mod typing_animation;
@@ -24,7 +24,7 @@ pub fn live_design(cx: &mut Cx) {
2424
icon_button::live_design(cx);
2525
unread_badge::live_design(cx);
2626
collapsible_header::live_design(cx);
27-
search_bar::live_design(cx);
27+
room_filter_input_bar::live_design(cx);
2828
avatar::live_design(cx);
2929
text_or_image::live_design(cx);
3030
html_or_plaintext::live_design(cx);
Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//! A text input used to filter the rooms list
2+
//! with a search icon and a button to clear the input.
3+
//!
4+
//! This is a dedicated widget instead of a general "SearchBar"
5+
//! in order for us to be able to place it inside of a `CachedWidget`
6+
//! and have a single instance be shared across the Mobile and Desktop app views.
7+
18
use makepad_widgets::*;
29

310
live_design! {
@@ -10,7 +17,7 @@ live_design! {
1017

1118
ICON_SEARCH = dep("crate://self/resources/icons/search.svg")
1219

13-
pub SearchBar = {{SearchBar}}<RoundedView> {
20+
pub RoomFilterInputBar = {{RoomFilterInputBar}}<RoundedView> {
1421
width: Fill,
1522
height: Fit,
1623

@@ -43,7 +50,7 @@ live_design! {
4350
width: Fill,
4451
height: Fit,
4552

46-
empty_message: "Search..."
53+
empty_message: "Filter rooms..."
4754

4855
draw_text: {
4956
text_style: { font_size: 10 },
@@ -63,23 +70,23 @@ live_design! {
6370
}
6471
}
6572

73+
/// A text input (with a search icon and cancel button) used to filter the rooms list.
74+
///
75+
/// See the module-level docs for more detail.
6676
#[derive(Live, LiveHook, Widget)]
67-
pub struct SearchBar {
68-
#[deref]
69-
view: View,
77+
pub struct RoomFilterInputBar {
78+
#[deref] view: View,
7079
}
7180

72-
/// Actions emitted by the search bar based on user interaction with it.
81+
/// Actions emitted by the `RoomFilterInputBar` based on user interaction with it.
7382
#[derive(Clone, Debug, DefaultNone)]
74-
pub enum SearchBarAction {
75-
/// The user has entered a search query.
76-
Search(String),
77-
/// The user has cleared the search query.
78-
ResetSearch,
79-
None
83+
pub enum RoomFilterAction {
84+
/// The user has changed the text entered into the filter bar.
85+
Changed(String),
86+
None,
8087
}
8188

82-
impl Widget for SearchBar {
89+
impl Widget for RoomFilterInputBar {
8390
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
8491
self.view.handle_event(cx, event, scope);
8592
self.widget_match_event(cx, event, scope);
@@ -90,40 +97,29 @@ impl Widget for SearchBar {
9097
}
9198
}
9299

93-
impl WidgetMatchEvent for SearchBar {
100+
impl WidgetMatchEvent for RoomFilterInputBar {
94101
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) {
95102
let input = self.text_input(id!(input));
96103
let clear_button = self.button(id!(clear_button));
97104

98105
// Handle user changing the input text
99106
if let Some(keywords) = input.changed(actions) {
100107
clear_button.set_visible(cx, !keywords.is_empty());
101-
let widget_uid = self.widget_uid();
102-
if keywords.is_empty() {
103-
cx.widget_action(
104-
widget_uid,
105-
&scope.path,
106-
SearchBarAction::ResetSearch
107-
);
108-
} else {
109-
cx.widget_action(
110-
widget_uid,
111-
&scope.path,
112-
SearchBarAction::Search(keywords)
113-
);
114-
}
108+
cx.widget_action(
109+
self.widget_uid(),
110+
&scope.path,
111+
RoomFilterAction::Changed(keywords)
112+
);
115113
}
116114

117-
// Handle user clicked the clear button
118115
if clear_button.clicked(actions) {
119116
input.set_text(cx, "");
120117
clear_button.set_visible(cx, false);
121118
input.set_key_focus(cx);
122-
123119
cx.widget_action(
124120
self.widget_uid(),
125121
&scope.path,
126-
SearchBarAction::ResetSearch,
122+
RoomFilterAction::Changed(String::new())
127123
);
128124
}
129125
}

0 commit comments

Comments
 (0)