Skip to content

Commit 4ced188

Browse files
fix: Fix register modal button click handling and add mask state
1 parent 0ef2b32 commit 4ced188

File tree

3 files changed

+77
-26
lines changed

3 files changed

+77
-26
lines changed

src/register/register_screen.rs

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ live_design! {
5050
use crate::register::register_status_modal::RegisterStatusModal;
5151

5252
IMG_APP_LOGO = dep("crate://self/resources/robrix_logo_alpha.png")
53+
54+
MaskableButton = <RobrixIconButton> {
55+
draw_bg: {
56+
instance mask: 0.0
57+
fn pixel(self) -> vec4 {
58+
let base_color = mix(self.color, mix(self.color, self.color_hover, 0.2), self.hover);
59+
let gray = dot(base_color.rgb, vec3(0.299, 0.587, 0.114));
60+
return mix(base_color, vec4(gray, gray, gray, base_color.a), self.mask);
61+
}
62+
}
63+
}
5364

5465
pub RegisterScreen = {{RegisterScreen}} {
5566
width: Fill, height: Fill,
@@ -235,13 +246,14 @@ live_design! {
235246
spacing: 10
236247
visible: true
237248

238-
sso_button = <RobrixIconButton> {
249+
sso_button = <MaskableButton> {
239250
width: Fill, height: 40
240251
padding: 10
241252
margin: {top: 10}
242253
align: {x: 0.5, y: 0.5}
243254
draw_bg: {
244255
color: (COLOR_ACTIVE_PRIMARY)
256+
mask: 0.0
245257
}
246258
draw_text: {
247259
color: (COLOR_PRIMARY)
@@ -280,13 +292,14 @@ live_design! {
280292
is_password: true,
281293
}
282294

283-
register_button = <RobrixIconButton> {
295+
register_button = <MaskableButton> {
284296
width: Fill, height: 40
285297
padding: 10
286298
margin: {top: 5, bottom: 10}
287299
align: {x: 0.5, y: 0.5}
288300
draw_bg: {
289301
color: (COLOR_ACTIVE_PRIMARY)
302+
mask: 0.0
290303
}
291304
draw_text: {
292305
color: (COLOR_PRIMARY)
@@ -337,12 +350,13 @@ live_design! {
337350
text: "Back to Login"
338351
}
339352
}
340-
}
341-
}
342-
343-
status_modal = <Modal> {
344-
content: {
345-
status_modal_inner = <RegisterStatusModal> {}
353+
354+
// Modal for registration status (both password and SSO)
355+
status_modal = <Modal> {
356+
content: {
357+
status_modal_inner = <RegisterStatusModal> {}
358+
}
359+
}
346360
}
347361
}
348362
}
@@ -372,6 +386,20 @@ impl RegisterScreen {
372386
});
373387
}
374388

389+
fn update_button_mask(&self, button: &ButtonRef, cx: &mut Cx, mask: f32) {
390+
button.apply_over(cx, live! {
391+
draw_bg: { mask: (mask) }
392+
});
393+
}
394+
395+
fn reset_modal_state(&mut self, cx: &mut Cx) {
396+
let register_button = self.view.button(id!(register_button));
397+
register_button.set_enabled(cx, true);
398+
register_button.reset_hover(cx);
399+
self.update_button_mask(&register_button, cx, 0.0);
400+
self.redraw(cx);
401+
}
402+
375403
fn update_registration_mode(&mut self, cx: &mut Cx) {
376404
let is_matrix_org = self.selected_homeserver == "matrix.org" || self.selected_homeserver.is_empty();
377405

@@ -421,9 +449,13 @@ impl MatchEvent for RegisterScreen {
421449
if edit_button.clicked(actions) {
422450
self.toggle_homeserver_options(cx);
423451
}
424-
452+
425453
// Handle SSO button click for matrix.org
426454
if sso_button.clicked(actions) && !self.sso_pending {
455+
// Mark SSO as pending for this screen
456+
self.sso_pending = true;
457+
self.update_button_mask(&sso_button, cx, 1.0);
458+
427459
// Use the same SSO flow as login screen - spawn SSO server with Google provider
428460
// This follows Element's implementation where SSO login and registration share the same OAuth flow
429461
// The Matrix server will handle whether to create a new account or login existing user
@@ -520,6 +552,7 @@ impl MatchEvent for RegisterScreen {
520552

521553
// Disable register button to prevent duplicate submissions
522554
register_button.set_enabled(cx, false);
555+
self.update_button_mask(&register_button, cx, 1.0);
523556

524557
// Show registration status modal
525558
self.view.modal(id!(status_modal)).open(cx);
@@ -539,20 +572,24 @@ impl MatchEvent for RegisterScreen {
539572
// Handle modal closing for both success and failure in one place
540573
for action in actions {
541574
// Handle RegisterStatusModal close action
542-
if let Some(RegisterStatusModalAction::Close) = action.as_widget_action().cast() {
543-
self.view.modal(id!(status_modal)).close(cx);
544-
// Re-enable register button when modal is closed manually
545-
let register_button = self.view.button(id!(register_button));
546-
register_button.set_enabled(cx, true);
547-
self.redraw(cx);
575+
if let Some(RegisterStatusModalAction::Close { was_internal }) = action.downcast_ref::<RegisterStatusModalAction>() {
576+
if *was_internal {
577+
self.view.modal(id!(status_modal)).close(cx);
578+
}
579+
self.reset_modal_state(cx);
580+
// Reset SSO button state if it was SSO registration
581+
if self.sso_pending {
582+
self.sso_pending = false;
583+
self.update_button_mask(&sso_button, cx, 0.0);
584+
}
548585
}
549-
586+
550587
// Handle SSO login actions
551588
match action.downcast_ref::<LoginAction>() {
552589
Some(LoginAction::SsoPending(pending)) => {
553590
self.sso_pending = *pending;
554-
// Update SSO button state
555-
sso_button.set_enabled(cx, !pending);
591+
// Update SSO button state with mask
592+
self.update_button_mask(&sso_button, cx, if *pending { 1.0 } else { 0.0 });
556593
self.redraw(cx);
557594
}
558595
Some(LoginAction::Status { .. }) => {
@@ -569,7 +606,7 @@ impl MatchEvent for RegisterScreen {
569606
}
570607
self.view.modal(id!(status_modal)).close(cx);
571608
self.sso_pending = false;
572-
sso_button.set_enabled(cx, true);
609+
self.update_button_mask(&sso_button, cx, 0.0);
573610
self.redraw(cx);
574611
}
575612
_ => {}

src/register/register_status_modal.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,13 @@ live_design! {
3838
},
3939
text: "Registering account, please wait..."
4040
}
41-
41+
4242
<View> {
4343
width: Fill,
4444
height: Fit,
4545
flow: Right,
4646
align: {x: 1.0},
4747
margin: {top: 10}
48-
4948
cancel_button = <RobrixIconButton> {
5049
width: Fit, height: Fit,
5150
padding: 10,
@@ -81,16 +80,31 @@ impl Widget for RegisterStatusModal {
8180

8281
impl MatchEvent for RegisterStatusModal {
8382
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
84-
if self.view.button(id!(cancel_button)).clicked(actions) {
85-
// Send action to close the modal
83+
// Check if modal was dismissed (ESC key or click outside)
84+
let modal_dismissed = actions
85+
.iter()
86+
.any(|a| matches!(a.downcast_ref(), Some(ModalAction::Dismissed)));
87+
88+
// Check if Abort button was clicked
89+
let abort_clicked = self.view.button(id!(cancel_button)).clicked(actions);
90+
91+
if abort_clicked || modal_dismissed {
92+
// Send action to close the modal with appropriate was_internal flag
8693
// Note: This doesn't actually cancel the registration request (still running in background)
87-
cx.action(RegisterStatusModalAction::Close);
94+
cx.action(RegisterStatusModalAction::Close {
95+
was_internal: abort_clicked
96+
});
8897
}
8998
}
9099
}
91100

92101
#[derive(Clone, DefaultNone, Debug)]
93102
pub enum RegisterStatusModalAction {
94-
Close,
103+
/// The modal requested to be closed
104+
Close {
105+
/// Whether the modal was closed by clicking an internal button (Abort)
106+
/// or being dismissed externally (ESC or click outside)
107+
was_internal: bool,
108+
},
95109
None,
96110
}

src/sliding_sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ async fn async_worker(
626626
enqueue_popup_notification(PopupItem {
627627
message: error_msg.clone(),
628628
kind: PopupKind::Error,
629-
auto_dismissal_duration: Some(5.0),
629+
auto_dismissal_duration: None,
630630
});
631631
Cx::post_action(RegisterAction::RegistrationFailure(error_msg));
632632
}

0 commit comments

Comments
 (0)