From ce68053a035c4130d649cc7bf57a9c39e204d337 Mon Sep 17 00:00:00 2001 From: Facundo Mendizabal Date: Fri, 11 Oct 2024 16:31:40 -0300 Subject: [PATCH 1/5] Add login screen. --- src/app.rs | 32 ++++- src/lib.rs | 2 + src/login/login_screen.rs | 238 ++++++++++++++++++++++++++++++++++++++ src/login/mod.rs | 7 ++ 4 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 src/login/login_screen.rs create mode 100644 src/login/mod.rs diff --git a/src/app.rs b/src/app.rs index 04fae7b9..1c9685f9 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,9 +2,7 @@ use makepad_widgets::*; use matrix_sdk::ruma::OwnedRoomId; use crate::{ - home::rooms_list::RoomListAction, - verification::VerificationAction, - verification_modal::{VerificationModalAction, VerificationModalWidgetRefExt}, + home::rooms_list::RoomListAction, login::login_screen::LoginAction, verification::VerificationAction, verification_modal::{VerificationModalAction, VerificationModalWidgetRefExt} }; live_design! { @@ -18,6 +16,7 @@ live_design! { import crate::home::room_screen::RoomScreen; import crate::profile::my_profile_screen::MyProfileScreen; import crate::verification_modal::VerificationModal; + import crate::login::login_screen::LoginScreen; ICON_CHAT = dep("crate://self/resources/icons/chat.svg") ICON_CONTACTS = dep("crate://self/resources/icons/contacts.svg") @@ -102,6 +101,12 @@ live_design! { } } + // StackNavigationView without header + SimpleStackNavigationView = { + header = {width: 0, height: 0} + margin: 0 + } + App = {{App}} { ui: { window: {inner_size: vec2(1280, 800)}, @@ -113,7 +118,16 @@ live_design! { width: Fill, height: Fill, flow: Overlay, - home_screen = {} + navigation = { + root_view = { + login_screen = {} + } + stack_navigation_view_home_screen = { + body = { + home_screen = {} + } + } + } verification_modal = { content: { @@ -148,6 +162,7 @@ impl LiveRegister for App { crate::verification_modal::live_design(cx); crate::home::live_design(cx); crate::profile::live_design(cx); + crate::login::live_design(cx); } } @@ -166,6 +181,14 @@ impl MatchEvent for App { fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) { for action in actions { + match action.as_widget_action().cast() { + LoginAction::LoginSuccess => { + let mut navigation = self.ui.stack_navigation(id!(navigation)); + navigation.show_stack_view_by_id(live_id!(stack_navigation_view_home_screen), cx) + } + LoginAction::None => { } + } + match action.as_widget_action().cast() { // A room has been selected, update the app state and navigate to the main content view. RoomListAction::Selected { @@ -244,6 +267,7 @@ impl AppMain for App { #[derive(Default, Debug)] pub struct AppState { pub rooms_panel: RoomsPanelState, + pub login_state: bool, } #[derive(Default, Debug)] diff --git a/src/lib.rs b/src/lib.rs index 1b4ecf74..14917b4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ pub use makepad_widgets; pub mod app; pub mod persistent_state; +/// Login screen +pub mod login; /// Core UI content: the main home screen (rooms list), room screen. pub mod home; /// User profile info and a user profile sliding pane. diff --git a/src/login/login_screen.rs b/src/login/login_screen.rs new file mode 100644 index 00000000..eaca6c12 --- /dev/null +++ b/src/login/login_screen.rs @@ -0,0 +1,238 @@ +use makepad_widgets::*; + +live_design! { + import makepad_widgets::base::*; + import makepad_widgets::theme_desktop_dark::*; + import makepad_draw::shader::std::*; + + import crate::shared::styles::*; + import crate::shared::icon_button::*; + + IMG_APP_LOGO = dep("crate://self/packaging/robrix_logo_alpha.png") + + LoginTextInput = { + width: Fill, height: Fit, margin: 0 + align: {y: 0.5} + draw_bg: { + color: (COLOR_PRIMARY) + instance radius: 2.0 + instance border_width: 0.8 + instance border_color: #D0D5DD + instance inset: vec4(0.0, 0.0, 0.0, 0.0) + + 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; + } + } + + draw_text: { + color: (MESSAGE_TEXT_COLOR), + text_style: {}, + + fn get_color(self) -> vec4 { + return mix( + self.color, + #B, + self.is_empty + ) + } + } + + + // TODO find a way to override colors + draw_cursor: { + instance focus: 0.0 + uniform border_radius: 0.5 + fn pixel(self) -> vec4 { + let sdf = Sdf2d::viewport(self.pos * self.rect_size); + sdf.box( + 0., + 0., + self.rect_size.x, + self.rect_size.y, + self.border_radius + ) + sdf.fill(mix(#fff, #bbb, self.focus)); + return sdf.result + } + } + + // TODO find a way to override colors + draw_selection: { + instance hover: 0.0 + instance focus: 0.0 + uniform border_radius: 2.0 + fn pixel(self) -> vec4 { + let sdf = Sdf2d::viewport(self.pos * self.rect_size); + sdf.box( + 0., + 0., + self.rect_size.x, + self.rect_size.y, + self.border_radius + ) + sdf.fill(mix(#eee, #ddd, self.focus)); // Pad color + return sdf.result + } + } + } + + LoginScreen = {{LoginScreen}} { + show_bg: true, + draw_bg: { + color: (COLOR_PRIMARY) + } + align: {x: 0.5, y: 0.5} + + { + width: Fit, height: Fit + flow: Down + align: {x: 0.5, y: 0.5} + padding: 50 + spacing: 20.0 + + show_bg: true, + draw_bg: { + color: (COLOR_SECONDARY) + } + + logo_image = { + fit: Smallest, + width: 80 + source: (IMG_APP_LOGO), + } + + title =