@@ -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 _ => { }
0 commit comments