Restructure ui into view structs
This commit is contained in:
		
							parent
							
								
									41b8756ac2
								
							
						
					
					
						commit
						774198933c
					
				
					 1 changed files with 289 additions and 303 deletions
				
			
		
							
								
								
									
										540
									
								
								src/ui.rs
									
										
									
									
									
								
							
							
						
						
									
										540
									
								
								src/ui.rs
									
										
									
									
									
								
							|  | @ -15,9 +15,9 @@ use matrix_sdk::{ | |||
| 
 | ||||
| use crate::matrix; | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Retrix { | ||||
|     Prompt { | ||||
| /// View for the login prompt
 | ||||
| #[derive(Debug, Clone, Default)] | ||||
| pub struct PromptView { | ||||
|     user_input: text_input::State, | ||||
|     password_input: text_input::State, | ||||
|     server_input: text_input::State, | ||||
|  | @ -28,9 +28,92 @@ pub enum Retrix { | |||
|     server: String, | ||||
|     action: PromptAction, | ||||
|     error: Option<String>, | ||||
|     }, | ||||
|     AwaitLogin(std::time::Instant), | ||||
|     LoggedIn { | ||||
| } | ||||
| 
 | ||||
| impl PromptView { | ||||
|     pub fn new() -> Self { | ||||
|         Self::default() | ||||
|     } | ||||
| 
 | ||||
|     pub fn view(&mut self) -> Element<Message> { | ||||
|         let mut content = Column::new() | ||||
|             .width(500.into()) | ||||
|             .push( | ||||
|                 Row::new() | ||||
|                     .spacing(15) | ||||
|                     .push(Radio::new( | ||||
|                         PromptAction::Login, | ||||
|                         "Login", | ||||
|                         Some(self.action), | ||||
|                         Message::SetAction, | ||||
|                     )) | ||||
|                     .push(Radio::new( | ||||
|                         PromptAction::Signup, | ||||
|                         "Sign up", | ||||
|                         Some(self.action), | ||||
|                         Message::SetAction, | ||||
|                     )), | ||||
|             ) | ||||
|             .push(Text::new("Username")) | ||||
|             .push( | ||||
|                 TextInput::new( | ||||
|                     &mut self.user_input, | ||||
|                     "Username", | ||||
|                     &self.user, | ||||
|                     Message::SetUser, | ||||
|                 ) | ||||
|                 .padding(5), | ||||
|             ) | ||||
|             .push(Text::new("Password")) | ||||
|             .push( | ||||
|                 TextInput::new( | ||||
|                     &mut self.password_input, | ||||
|                     "Password", | ||||
|                     &self.password, | ||||
|                     Message::SetPassword, | ||||
|                 ) | ||||
|                 .password() | ||||
|                 .padding(5), | ||||
|             ) | ||||
|             .push(Text::new("Homeserver")) | ||||
|             .push( | ||||
|                 TextInput::new( | ||||
|                     &mut self.server_input, | ||||
|                     "Server", | ||||
|                     &self.server, | ||||
|                     Message::SetServer, | ||||
|                 ) | ||||
|                 .padding(5), | ||||
|             ); | ||||
|         let button = match self.action { | ||||
|             PromptAction::Login => { | ||||
|                 Button::new(&mut self.login_button, Text::new("Login")).on_press(Message::Login) | ||||
|             } | ||||
|             PromptAction::Signup => { | ||||
|                 content = content.push( | ||||
|                     Text::new("NB: Signup is very naively implemented, and prone to breaking") | ||||
|                         .color([0.2, 0.2, 0.0]), | ||||
|                 ); | ||||
|                 Button::new(&mut self.login_button, Text::new("Sign up")).on_press(Message::Signup) | ||||
|             } | ||||
|         }; | ||||
|         content = content.push(button); | ||||
|         if let Some(ref error) = self.error { | ||||
|             content = content.push(Text::new(error).color([1.0, 0.0, 0.0])); | ||||
|         } | ||||
| 
 | ||||
|         Container::new(content) | ||||
|             .center_x() | ||||
|             .center_y() | ||||
|             .width(iced::Length::Fill) | ||||
|             .height(iced::Length::Fill) | ||||
|             .into() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Main view after successful login
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct MainView { | ||||
|     client: matrix_sdk::Client, | ||||
|     session: matrix::Session, | ||||
| 
 | ||||
|  | @ -43,24 +126,147 @@ pub enum Retrix { | |||
|     message_input: iced::text_input::State, | ||||
|     draft: String, | ||||
|     send_button: iced::button::State, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| impl Retrix { | ||||
|     pub fn new_prompt() -> Retrix { | ||||
|         Retrix::Prompt { | ||||
|             user_input: text_input::State::new(), | ||||
|             password_input: text_input::State::new(), | ||||
|             server_input: text_input::State::new(), | ||||
|             login_button: Default::default(), | ||||
| impl MainView { | ||||
|     pub fn new(client: matrix_sdk::Client, session: matrix::Session) -> Self { | ||||
|         Self { | ||||
|             client, | ||||
|             session, | ||||
|             rooms: Default::default(), | ||||
|             selected: None, | ||||
|             room_scroll: Default::default(), | ||||
|             message_scroll: Default::default(), | ||||
|             message_input: Default::default(), | ||||
|             buttons: Default::default(), | ||||
|             messages: Default::default(), | ||||
|             draft: String::new(), | ||||
|             send_button: Default::default(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|             user: String::new(), | ||||
|             password: String::new(), | ||||
|             server: String::new(), | ||||
|             action: PromptAction::Login, | ||||
|             error: None, | ||||
|     pub fn view(&mut self) -> Element<Message> { | ||||
|         let mut root_row = Row::new().width(Length::Fill).height(Length::Fill); | ||||
| 
 | ||||
|         // Room list
 | ||||
|         let joined = self.client.joined_rooms(); | ||||
|         let rooms = futures::executor::block_on(async { joined.read().await }); | ||||
|         let mut room_col = Scrollable::new(&mut self.room_scroll) | ||||
|             .width(400.into()) | ||||
|             .height(Length::Fill) | ||||
|             .scrollbar_width(5); | ||||
|         // We have to iterate the buttons map and not the other way around to make the
 | ||||
|         // borrow checker happy. First we make sure there's a button entry for every room
 | ||||
|         // entry, and clean up button entries from removed rooms.
 | ||||
|         for (id, _) in rooms.iter() { | ||||
|             self.buttons.entry(id.to_owned()).or_default(); | ||||
|         } | ||||
|         self.buttons.retain(|id, _| rooms.contains_key(id)); | ||||
|         // Then we make our buttons
 | ||||
|         let buttons: Vec<Button<_>> = self | ||||
|             .buttons | ||||
|             .iter_mut() | ||||
|             .map(|(id, state)| { | ||||
|                 // Get read lock for the room
 | ||||
|                 let room = | ||||
|                     futures::executor::block_on(async { rooms.get(id).unwrap().read().await }); | ||||
|                 Button::new(state, Text::new(room.display_name())) | ||||
|                     .on_press(Message::SelectRoom(id.to_owned())) | ||||
|                     .width(400.into()) | ||||
|             }) | ||||
|             .collect(); | ||||
|         // Then we add them to our room column. What a mess.
 | ||||
|         for button in buttons { | ||||
|             room_col = room_col.push(button); | ||||
|         } | ||||
|         root_row = root_row.push(room_col); | ||||
| 
 | ||||
|         // Messages.
 | ||||
|         //
 | ||||
|         // Get selected room.
 | ||||
|         let selected_room = self.selected.as_ref().and_then(|selected| { | ||||
|             futures::executor::block_on(async { | ||||
|                 match rooms.get(selected) { | ||||
|                     Some(room) => Some(room.read().await), | ||||
|                     None => None, | ||||
|                 } | ||||
|             }) | ||||
|         }); | ||||
|         if let Some(room) = selected_room { | ||||
|             let mut col = Column::new() | ||||
|                 .spacing(5) | ||||
|                 .padding(5) | ||||
|                 .push(Text::new(room.display_name()).size(25)) | ||||
|                 .push(Rule::horizontal(2)); | ||||
|             let mut scroll = Scrollable::new(&mut self.message_scroll) | ||||
|                 .scrollbar_width(2) | ||||
|                 .height(Length::Fill); | ||||
|             for message in room.messages.iter() { | ||||
|                 if let AnyPossiblyRedactedSyncMessageEvent::Regular(event) = message { | ||||
|                     if let AnySyncMessageEvent::RoomMessage(room_message) = event { | ||||
|                         match &room_message.content { | ||||
|                             MessageEventContent::Text(text) => { | ||||
|                                 let row = Row::new() | ||||
|                                     .spacing(5) | ||||
|                                     .push( | ||||
|                                         // Render senders disambiguated name or fallback to
 | ||||
|                                         // mxid
 | ||||
|                                         Text::new( | ||||
|                                             room.joined_members | ||||
|                                                 .get(&room_message.sender) | ||||
|                                                 .map(|sender| sender.disambiguated_name()) | ||||
|                                                 .unwrap_or(room_message.sender.to_string()), | ||||
|                                         ) | ||||
|                                         .color([0.2, 0.2, 1.0]), | ||||
|                                     ) | ||||
|                                     .push(Text::new(&text.body).width(Length::Fill)) | ||||
|                                     .push(Text::new(format_systime(room_message.origin_server_ts))); | ||||
|                                 scroll = scroll.push(row); | ||||
|                             } | ||||
|                             _ => (), | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             col = col.push(scroll).push( | ||||
|                 Row::new() | ||||
|                     .push( | ||||
|                         TextInput::new( | ||||
|                             &mut self.message_input, | ||||
|                             "Write a message...", | ||||
|                             &self.draft, | ||||
|                             Message::SetMessage, | ||||
|                         ) | ||||
|                         .width(Length::Fill) | ||||
|                         .padding(5) | ||||
|                         .on_submit(Message::SendMessage), | ||||
|                     ) | ||||
|                     .push( | ||||
|                         Button::new(&mut self.send_button, Text::new("Send")) | ||||
|                             .on_press(Message::SendMessage), | ||||
|                     ), | ||||
|             ); | ||||
| 
 | ||||
|             root_row = root_row.push(col); | ||||
|         } else { | ||||
|             root_row = root_row.push( | ||||
|                 Container::new(Text::new("Select a room to start chatting")) | ||||
|                     .center_x() | ||||
|                     .center_y() | ||||
|                     .width(Length::Fill) | ||||
|                     .height(Length::Fill), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         root_row.into() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Retrix { | ||||
|     Prompt(PromptView), | ||||
|     AwaitLogin, | ||||
|     LoggedIn(MainView), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||||
|  | @ -69,6 +275,12 @@ pub enum PromptAction { | |||
|     Signup, | ||||
| } | ||||
| 
 | ||||
| impl Default for PromptAction { | ||||
|     fn default() -> Self { | ||||
|         PromptAction::Login | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Message { | ||||
|     // Login form messages
 | ||||
|  | @ -106,9 +318,9 @@ impl Application for Retrix { | |||
|                         Err(e) => Message::LoginFailed(e.to_string()), | ||||
|                     }, | ||||
|                 ); | ||||
|                 (Retrix::AwaitLogin(std::time::Instant::now()), command) | ||||
|                 (Retrix::AwaitLogin, command) | ||||
|             } | ||||
|             None => (Retrix::new_prompt(), Command::none()), | ||||
|             None => (Retrix::Prompt(PromptView::new()), Command::none()), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -118,8 +330,8 @@ impl Application for Retrix { | |||
| 
 | ||||
|     fn subscription(&self) -> Subscription<Self::Message> { | ||||
|         match self { | ||||
|             Retrix::LoggedIn { client, .. } => { | ||||
|                 matrix::MatrixSync::subscription(client.clone()).map(Message::Sync) | ||||
|             Retrix::LoggedIn(view) => { | ||||
|                 matrix::MatrixSync::subscription(view.client.clone()).map(Message::Sync) | ||||
|             } | ||||
|             _ => Subscription::none(), | ||||
|         } | ||||
|  | @ -127,22 +339,16 @@ impl Application for Retrix { | |||
| 
 | ||||
|     fn update(&mut self, message: Self::Message) -> Command<Self::Message> { | ||||
|         match self { | ||||
|             Retrix::Prompt { | ||||
|                 user, | ||||
|                 password, | ||||
|                 server, | ||||
|                 action, | ||||
|                 .. | ||||
|             } => match message { | ||||
|                 Message::SetUser(u) => *user = u, | ||||
|                 Message::SetPassword(p) => *password = p, | ||||
|                 Message::SetServer(s) => *server = s, | ||||
|                 Message::SetAction(a) => *action = a, | ||||
|             Retrix::Prompt(prompt) => match message { | ||||
|                 Message::SetUser(u) => prompt.user = u, | ||||
|                 Message::SetPassword(p) => prompt.password = p, | ||||
|                 Message::SetServer(s) => prompt.server = s, | ||||
|                 Message::SetAction(a) => prompt.action = a, | ||||
|                 Message::Login => { | ||||
|                     let user = user.clone(); | ||||
|                     let password = password.clone(); | ||||
|                     let server = server.clone(); | ||||
|                     *self = Retrix::AwaitLogin(std::time::Instant::now()); | ||||
|                     let user = prompt.user.clone(); | ||||
|                     let password = prompt.password.clone(); | ||||
|                     let server = prompt.server.clone(); | ||||
|                     *self = Retrix::AwaitLogin; | ||||
|                     return Command::perform( | ||||
|                         async move { matrix::login(&user, &password, &server).await }, | ||||
|                         |result| match result { | ||||
|  | @ -152,10 +358,10 @@ impl Application for Retrix { | |||
|                     ); | ||||
|                 } | ||||
|                 Message::Signup => { | ||||
|                     let user = user.clone(); | ||||
|                     let password = password.clone(); | ||||
|                     let server = server.clone(); | ||||
|                     *self = Retrix::AwaitLogin(std::time::Instant::now()); | ||||
|                     let user = prompt.user.clone(); | ||||
|                     let password = prompt.password.clone(); | ||||
|                     let server = prompt.server.clone(); | ||||
|                     *self = Retrix::AwaitLogin; | ||||
|                     return Command::perform( | ||||
|                         async move { matrix::signup(&user, &password, &server).await }, | ||||
|                         |result| match result { | ||||
|  | @ -166,27 +372,14 @@ impl Application for Retrix { | |||
|                 } | ||||
|                 _ => (), | ||||
|             }, | ||||
|             Retrix::AwaitLogin(_) => match message { | ||||
|             Retrix::AwaitLogin => match message { | ||||
|                 Message::LoginFailed(e) => { | ||||
|                     *self = Retrix::new_prompt(); | ||||
|                     if let Retrix::Prompt { ref mut error, .. } = *self { | ||||
|                         *error = Some(e); | ||||
|                     } | ||||
|                     let mut view = PromptView::default(); | ||||
|                     view.error = Some(e); | ||||
|                     *self = Retrix::Prompt(view); | ||||
|                 } | ||||
|                 Message::LoggedIn(client, session) => { | ||||
|                     *self = Retrix::LoggedIn { | ||||
|                         client: client.clone(), | ||||
|                         session, | ||||
|                         rooms: BTreeMap::new(), | ||||
|                         selected: None, | ||||
|                         room_scroll: Default::default(), | ||||
|                         message_scroll: Default::default(), | ||||
|                         message_input: Default::default(), | ||||
|                         buttons: Default::default(), | ||||
|                         messages: Default::default(), | ||||
|                         draft: String::new(), | ||||
|                         send_button: Default::default(), | ||||
|                     }; | ||||
|                     *self = Retrix::LoggedIn(MainView::new(client, session)); | ||||
|                     /*let client = client.clone();
 | ||||
|                     return Command::perform( | ||||
|                         async move { | ||||
|  | @ -202,26 +395,20 @@ impl Application for Retrix { | |||
|                 } | ||||
|                 _ => (), | ||||
|             }, | ||||
|             Retrix::LoggedIn { | ||||
|                 rooms, | ||||
|                 selected, | ||||
|                 draft, | ||||
|                 client, | ||||
|                 .. | ||||
|             } => match message { | ||||
|                 Message::ResetRooms(r) => *rooms = r, | ||||
|                 Message::SelectRoom(r) => *selected = Some(r), | ||||
|             Retrix::LoggedIn(view) => match message { | ||||
|                 Message::ResetRooms(r) => view.rooms = r, | ||||
|                 Message::SelectRoom(r) => view.selected = Some(r), | ||||
|                 Message::Sync(event) => match event { | ||||
|                     AnyRoomEvent::Message(_message) => (), | ||||
|                     AnyRoomEvent::State(_state) => (), | ||||
|                     AnyRoomEvent::RedactedMessage(_message) => (), | ||||
|                     AnyRoomEvent::RedactedState(_state) => (), | ||||
|                 }, | ||||
|                 Message::SetMessage(m) => *draft = m, | ||||
|                 Message::SetMessage(m) => view.draft = m, | ||||
|                 Message::SendMessage => { | ||||
|                     let selected = selected.to_owned(); | ||||
|                     let draft = draft.clone(); | ||||
|                     let client = client.clone(); | ||||
|                     let selected = view.selected.to_owned(); | ||||
|                     let draft = view.draft.clone(); | ||||
|                     let client = view.client.clone(); | ||||
|                     return Command::perform( | ||||
|                         async move { | ||||
|                             client | ||||
|  | @ -248,215 +435,14 @@ impl Application for Retrix { | |||
| 
 | ||||
|     fn view(&mut self) -> Element<Self::Message> { | ||||
|         match self { | ||||
|             Retrix::Prompt { | ||||
|                 user_input, | ||||
|                 password_input, | ||||
|                 server_input, | ||||
|                 login_button, | ||||
|                 user, | ||||
|                 password, | ||||
|                 server, | ||||
|                 action, | ||||
|                 error, | ||||
|             } => { | ||||
|                 // Login form
 | ||||
|                 let mut content = Column::new() | ||||
|                     .width(500.into()) | ||||
|                     .push( | ||||
|                         Row::new() | ||||
|                             .push(Radio::new( | ||||
|                                 PromptAction::Login, | ||||
|                                 "Login", | ||||
|                                 Some(*action), | ||||
|                                 Message::SetAction, | ||||
|                             )) | ||||
|                             .push(Radio::new( | ||||
|                                 PromptAction::Signup, | ||||
|                                 "Sign up", | ||||
|                                 Some(*action), | ||||
|                                 Message::SetAction, | ||||
|                             )), | ||||
|                     ) | ||||
|                     .push(Text::new("Username")) | ||||
|                     .push(TextInput::new(user_input, "Username", user, Message::SetUser).padding(5)) | ||||
|                     .push(Text::new("Password")) | ||||
|                     .push( | ||||
|                         TextInput::new(password_input, "Password", password, Message::SetPassword) | ||||
|                             .password() | ||||
|                             .padding(5), | ||||
|                     ) | ||||
|                     .push(Text::new("Homeserver")) | ||||
|                     .push( | ||||
|                         TextInput::new(server_input, "Server", server, Message::SetServer) | ||||
|                             .padding(5), | ||||
|                     ); | ||||
|                 let button = match *action { | ||||
|                     PromptAction::Login => { | ||||
|                         Button::new(login_button, Text::new("Login")).on_press(Message::Login) | ||||
|                     } | ||||
|                     PromptAction::Signup => { | ||||
|                         content = content.push( | ||||
|                             Text::new( | ||||
|                                 "NB: Signup is very naively implemented, and prone to breaking", | ||||
|                             ) | ||||
|                             .color([0.2, 0.2, 0.0]), | ||||
|                         ); | ||||
|                         Button::new(login_button, Text::new("Sign up")).on_press(Message::Signup) | ||||
|                     } | ||||
|                 }; | ||||
|                 content = content.push(button); | ||||
|                 if let Some(ref error) = error { | ||||
|                     content = content.push(Text::new(error).color([1.0, 0.0, 0.0])); | ||||
|                 } | ||||
| 
 | ||||
|                 Container::new(content) | ||||
|                     .center_x() | ||||
|                     .center_y() | ||||
|                     .width(iced::Length::Fill) | ||||
|                     .height(iced::Length::Fill) | ||||
|                     .into() | ||||
|             } | ||||
|             Retrix::AwaitLogin(instant) => Container::new(Text::new(format!( | ||||
|                 "Logging in{}", | ||||
|                 match instant.elapsed().subsec_millis() / 333 { | ||||
|                     0 => ".", | ||||
|                     1 => "..", | ||||
|                     2 => "...", | ||||
|                     _ => "....", | ||||
|                 } | ||||
|             ))) | ||||
|             Retrix::Prompt(prompt) => prompt.view(), | ||||
|             Retrix::AwaitLogin => Container::new(Text::new(format!("Logging in..."))) | ||||
|                 .center_x() | ||||
|                 .center_y() | ||||
|                 .width(Length::Fill) | ||||
|                 .height(Length::Fill) | ||||
|                 .into(), | ||||
|             Retrix::LoggedIn { | ||||
|                 client, | ||||
|                 room_scroll, | ||||
|                 message_scroll, | ||||
|                 message_input, | ||||
|                 send_button, | ||||
|                 buttons, | ||||
|                 selected, | ||||
|                 draft, | ||||
|                 .. | ||||
|             } => { | ||||
|                 let mut root_row = Row::new().width(Length::Fill).height(Length::Fill); | ||||
| 
 | ||||
|                 // Room list
 | ||||
|                 let joined = client.joined_rooms(); | ||||
|                 let rooms = futures::executor::block_on(async { joined.read().await }); | ||||
|                 let mut room_col = Scrollable::new(room_scroll) | ||||
|                     .width(400.into()) | ||||
|                     .height(Length::Fill) | ||||
|                     .scrollbar_width(5); | ||||
|                 // We have to iterate the buttons map and not the other way around to make the
 | ||||
|                 // borrow checker happy. First we make sure there's a button entry for every room
 | ||||
|                 // entry, and clean up button entries from removed rooms.
 | ||||
|                 for (id, _) in rooms.iter() { | ||||
|                     buttons.entry(id.to_owned()).or_default(); | ||||
|                 } | ||||
|                 buttons.retain(|id, _| rooms.contains_key(id)); | ||||
|                 // Then we make our buttons
 | ||||
|                 let buttons: Vec<Button<_>> = buttons | ||||
|                     .iter_mut() | ||||
|                     .map(|(id, state)| { | ||||
|                         // Get read lock for the room
 | ||||
|                         let room = futures::executor::block_on(async { | ||||
|                             rooms.get(id).unwrap().read().await | ||||
|                         }); | ||||
|                         Button::new(state, Text::new(room.display_name())) | ||||
|                             .on_press(Message::SelectRoom(id.to_owned())) | ||||
|                             .width(400.into()) | ||||
|                     }) | ||||
|                     .collect(); | ||||
|                 // Then we add them to our room column. What a mess.
 | ||||
|                 for button in buttons { | ||||
|                     room_col = room_col.push(button); | ||||
|                 } | ||||
|                 root_row = root_row.push(room_col); | ||||
| 
 | ||||
|                 // Messages.
 | ||||
|                 //
 | ||||
|                 // Get selected room.
 | ||||
|                 let selected_room = selected.as_ref().and_then(|selected| { | ||||
|                     futures::executor::block_on(async { | ||||
|                         match rooms.get(selected) { | ||||
|                             Some(room) => Some(room.read().await), | ||||
|                             None => None, | ||||
|                         } | ||||
|                     }) | ||||
|                 }); | ||||
|                 if let Some(room) = selected_room { | ||||
|                     let mut col = Column::new() | ||||
|                         .spacing(5) | ||||
|                         .padding(5) | ||||
|                         .push(Text::new(room.display_name()).size(25)) | ||||
|                         .push(Rule::horizontal(2)); | ||||
|                     let mut scroll = Scrollable::new(message_scroll) | ||||
|                         .scrollbar_width(2) | ||||
|                         .height(Length::Fill); | ||||
|                     for message in room.messages.iter() { | ||||
|                         if let AnyPossiblyRedactedSyncMessageEvent::Regular(event) = message { | ||||
|                             if let AnySyncMessageEvent::RoomMessage(room_message) = event { | ||||
|                                 match &room_message.content { | ||||
|                                     MessageEventContent::Text(text) => { | ||||
|                                         let row = Row::new() | ||||
|                                             .spacing(5) | ||||
|                                             .push( | ||||
|                                                 // Render senders disambiguated name or fallback to
 | ||||
|                                                 // mxid
 | ||||
|                                                 Text::new( | ||||
|                                                     room.joined_members | ||||
|                                                         .get(&room_message.sender) | ||||
|                                                         .map(|sender| sender.disambiguated_name()) | ||||
|                                                         .unwrap_or(room_message.sender.to_string()), | ||||
|                                                 ) | ||||
|                                                 .color([0.2, 0.2, 1.0]), | ||||
|                                             ) | ||||
|                                             .push(Text::new(&text.body).width(Length::Fill)) | ||||
|                                             .push(Text::new(format_systime( | ||||
|                                                 room_message.origin_server_ts, | ||||
|                                             ))); | ||||
|                                         scroll = scroll.push(row); | ||||
|                                     } | ||||
|                                     _ => (), | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     col = col.push(scroll).push( | ||||
|                         Row::new() | ||||
|                             .push( | ||||
|                                 TextInput::new( | ||||
|                                     message_input, | ||||
|                                     "Write a message...", | ||||
|                                     draft, | ||||
|                                     Message::SetMessage, | ||||
|                                 ) | ||||
|                                 .width(Length::Fill) | ||||
|                                 .padding(5) | ||||
|                                 .on_submit(Message::SendMessage), | ||||
|                             ) | ||||
|                             .push( | ||||
|                                 Button::new(send_button, Text::new("Send")) | ||||
|                                     .on_press(Message::SendMessage), | ||||
|                             ), | ||||
|                     ); | ||||
| 
 | ||||
|                     root_row = root_row.push(col); | ||||
|                 } else { | ||||
|                     root_row = root_row.push( | ||||
|                         Container::new(Text::new("Select a room to start chatting")) | ||||
|                             .center_x() | ||||
|                             .center_y() | ||||
|                             .width(Length::Fill) | ||||
|                             .height(Length::Fill), | ||||
|                     ); | ||||
|                 } | ||||
| 
 | ||||
|                 root_row.into() | ||||
|             } | ||||
|             Retrix::LoggedIn(view) => view.view(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue