1
1
use ratatui:: {
2
- prelude:: { Buffer , Constraint , Layout , Rect } ,
2
+ prelude:: { Alignment , Buffer , Constraint , Layout , Rect } ,
3
3
style:: { Modifier , Style } ,
4
4
text:: { Line , Span , Text } ,
5
- widgets:: { Block , Borders , List , ListItem , ListState , Paragraph , StatefulWidget , Widget } ,
5
+ widgets:: {
6
+ Block , Borders , HighlightSpacing , List , ListItem , ListState , Paragraph , StatefulWidget ,
7
+ Widget ,
8
+ } ,
6
9
} ;
7
10
8
11
use crate :: {
9
12
auth:: { device_flow:: DeviceAuthorizationResponse , AuthenticationProvider } ,
10
- ui:: { extension:: RectExt , Context } ,
13
+ ui:: { self , extension:: RectExt , Context } ,
11
14
} ;
12
15
13
16
/// Handle user authentication
@@ -35,46 +38,65 @@ impl Authentication {
35
38
}
36
39
}
37
40
38
- pub fn authenticated ( & mut self ) {
39
- self . state = AuthenticateState :: Authenticated ;
41
+ pub fn state ( & self ) -> & AuthenticateState {
42
+ & self . state
40
43
}
41
44
42
45
pub fn selected_provider ( & self ) -> AuthenticationProvider {
43
46
self . providers [ self . selected_provider_index ]
44
47
}
45
48
49
+ pub fn authenticated ( & mut self ) {
50
+ self . state = AuthenticateState :: Authenticated ;
51
+ }
52
+
53
+ pub fn set_device_authorization_response ( & mut self , response : DeviceAuthorizationResponse ) {
54
+ self . state = AuthenticateState :: DeviceFlow ( response) ;
55
+ }
56
+
46
57
pub ( super ) fn should_render ( & self ) -> bool {
47
- match self . state {
48
- AuthenticateState :: NotAuthenticated | AuthenticateState :: DeviceFlow ( _ ) => true ,
49
- _ => false ,
50
- }
58
+ matches ! (
59
+ self . state ,
60
+ AuthenticateState :: NotAuthenticated | AuthenticateState :: DeviceFlow ( _ )
61
+ )
51
62
}
52
63
}
53
64
54
65
impl Authentication {
55
66
pub ( super ) fn render ( & self , area : Rect , buf : & mut Buffer , cx : & Context < ' _ > ) {
56
67
match self . state {
57
- AuthenticateState :: NotAuthenticated => self . render_login ( area, buf) ,
68
+ AuthenticateState :: NotAuthenticated => self . render_login ( area, buf, cx ) ,
58
69
AuthenticateState :: DeviceFlow ( ref res) => self . render_device_flow ( area, buf, cx, res) ,
59
70
AuthenticateState :: Authenticated => unreachable ! ( ) ,
60
71
}
61
72
}
62
73
63
- fn render_login ( & self , area : Rect , buf : & mut Buffer ) {
64
- let area = area. centered ( 50 , 50 ) ;
74
+ fn render_login ( & self , area : Rect , buf : & mut Buffer , cx : & Context < ' _ > ) {
75
+ let area = area. centered ( 40 , 50 ) ;
65
76
66
77
let vertical = Layout :: vertical ( [ Constraint :: Length ( 2 ) , Constraint :: Min ( 1 ) ] ) ;
67
78
let [ title_area, methods_area] = area. split ( & vertical) ;
68
79
69
- let title = Paragraph :: new ( Text :: styled ( "Login" , Style :: default ( ) ) )
80
+ let title = Paragraph :: new ( Span :: styled ( "Login" , cx. theme . login . title ) )
81
+ . alignment ( Alignment :: Center )
70
82
. block ( Block :: default ( ) . borders ( Borders :: BOTTOM ) ) ;
71
83
72
84
let methods = {
73
- let items = vec ! [ ListItem :: new( Line :: styled( "with Github" , Style :: default ( ) ) ) ] ;
74
-
75
- List :: new ( items) . highlight_symbol ( ">> " )
85
+ let items = self
86
+ . providers
87
+ . iter ( )
88
+ . map ( |provider| match provider {
89
+ AuthenticationProvider :: Github => Text :: from ( "with GitHub" ) ,
90
+ } )
91
+ . map ( ListItem :: new) ;
92
+
93
+ List :: new ( items)
94
+ . highlight_symbol ( ui:: TABLE_HIGHLIGHT_SYMBOL )
95
+ . highlight_style ( cx. theme . login . selected_auth_provider_item )
96
+ . highlight_spacing ( HighlightSpacing :: Always )
76
97
} ;
77
- let mut methods_state = ListState :: default ( ) . with_selected ( Some ( 0 ) ) ;
98
+ let mut methods_state =
99
+ ListState :: default ( ) . with_selected ( Some ( self . selected_provider_index ) ) ;
78
100
79
101
Widget :: render ( title, title_area, buf) ;
80
102
StatefulWidget :: render ( methods, methods_area, buf, & mut methods_state) ;
@@ -87,27 +109,31 @@ impl Authentication {
87
109
cx : & Context < ' _ > ,
88
110
res : & DeviceAuthorizationResponse ,
89
111
) {
90
- let area = area. centered ( 50 , 50 ) ;
112
+ let area = area. centered ( 40 , 50 ) ;
91
113
92
114
let vertical = Layout :: vertical ( [ Constraint :: Length ( 2 ) , Constraint :: Min ( 1 ) ] ) ;
93
115
94
116
let [ title_area, device_flow_area] = area. split ( & vertical) ;
95
117
96
- let title = Paragraph :: new ( Text :: styled ( "Login" , Style :: default ( ) ) )
118
+ let title = Paragraph :: new ( Text :: from ( "Login" ) )
119
+ . alignment ( Alignment :: Center )
120
+ . style ( cx. theme . login . title )
97
121
. block ( Block :: default ( ) . borders ( Borders :: BOTTOM ) ) ;
98
122
99
123
let device_flow = Paragraph :: new ( vec ! [
124
+ Line :: from( "Open the following URL and Enter the code" ) ,
125
+ Line :: from( "" ) ,
100
126
Line :: from( vec![
101
- Span :: styled( "Code: " , Style :: default ( ) ) ,
127
+ Span :: styled( "URL: " , Style :: default ( ) ) ,
102
128
Span :: styled(
103
- & res. user_code ,
129
+ res. verification_uri . to_string ( ) ,
104
130
Style :: default ( ) . add_modifier( Modifier :: BOLD ) ,
105
131
) ,
106
132
] ) ,
107
133
Line :: from( vec![
108
- Span :: styled( "URL : " , Style :: default ( ) ) ,
134
+ Span :: styled( "Code : " , Style :: default ( ) ) ,
109
135
Span :: styled(
110
- res. verification_uri . to_string ( ) ,
136
+ & res. user_code ,
111
137
Style :: default ( ) . add_modifier( Modifier :: BOLD ) ,
112
138
) ,
113
139
] ) ,
0 commit comments