@@ -15,48 +15,46 @@ struct LoginForm<S: Session>: View {
1515 let inspection = Inspection < Self > ( )
1616
1717 var body : some View {
18- VStack {
19- VStack {
20- switch currentPage {
21- case . serverURL:
22- serverURLPage
23- . transition ( . move( edge: . leading) )
24- . onAppear {
25- DispatchQueue . main. async {
26- focusedField = . baseAccessURL
27- }
18+ Group {
19+ switch currentPage {
20+ case . serverURL:
21+ serverURLPage
22+ . transition ( . move( edge: . leading) )
23+ . onAppear {
24+ DispatchQueue . main. async {
25+ focusedField = . baseAccessURL
2826 }
29- case . sessionToken :
30- sessionTokenPage
31- . transition ( . move ( edge : . trailing ) )
32- . onAppear {
33- DispatchQueue . main . async {
34- focusedField = . sessionToken
35- }
27+ }
28+ case . sessionToken :
29+ sessionTokenPage
30+ . transition ( . move ( edge : . trailing ) )
31+ . onAppear {
32+ DispatchQueue . main . async {
33+ focusedField = . sessionToken
3634 }
37- }
38- }
39- . animation ( . easeInOut, value: currentPage)
40- . onAppear {
41- baseAccessURL = session. baseAccessURL? . absoluteString ?? baseAccessURL
42- sessionToken = " "
43- } . padding ( . vertical, 35 )
44- . alert ( " Error " , isPresented: Binding (
45- get: { loginError != nil } ,
46- set: { isPresented in
47- if !isPresented {
48- loginError = nil
4935 }
36+ }
37+ }
38+ . animation ( . easeInOut, value: currentPage)
39+ . onAppear {
40+ baseAccessURL = session. baseAccessURL? . absoluteString ?? baseAccessURL
41+ sessionToken = " "
42+ }
43+ . alert ( " Error " , isPresented: Binding (
44+ get: { loginError != nil } ,
45+ set: { isPresented in
46+ if !isPresented {
47+ loginError = nil
5048 }
51- ) ) {
52- Button ( " OK " , role: . cancel) { } . keyboardShortcut ( . defaultAction)
53- } message: {
54- Text ( loginError? . description ?? " " )
5549 }
56- } . padding ( )
57- . frame ( width: 450 , height: 220 )
58- . disabled ( loading)
59- . onReceive ( inspection. notice) { self . inspection. visit ( self , $0) } // ViewInspector
50+ ) ) {
51+ Button ( " OK " , role: . cancel) { } . keyboardShortcut ( . defaultAction)
52+ } message: {
53+ Text ( loginError? . description ?? " " )
54+ } . disabled ( loading)
55+ . frame ( width: 550 )
56+ . fixedSize ( )
57+ . onReceive ( inspection. notice) { self . inspection. visit ( self , $0) } // ViewInspector
6058 }
6159
6260 func submit( ) async {
@@ -82,63 +80,70 @@ struct LoginForm<S: Session>: View {
8280 }
8381
8482 private var serverURLPage : some View {
85- VStack ( spacing: 15 ) {
86- Text ( " Coder Desktop " ) . font ( . title ) . padding ( . bottom , 15 )
87- VStack ( alignment : . leading ) {
88- HStack ( alignment : . firstTextBaseline ) {
89- Text ( " Server URL " )
90- Spacer ( )
91- TextField ( " https://coder.example.com " , text : $baseAccessURL )
92- . textFieldStyle ( RoundedBorderTextFieldStyle ( ) )
93- . disableAutocorrection ( true )
94- . frame ( width : 290 , alignment : . leading )
83+ VStack ( spacing: 0 ) {
84+ Spacer ( )
85+ Text ( " Coder Desktop " ) . font ( . title ) . padding ( . top , 10 )
86+ Form {
87+ Section {
88+ TextField (
89+ " Server URL " ,
90+ text : $baseAccessURL ,
91+ prompt : Text ( " https://coder.example.com " )
92+ ) . autocorrectionDisabled ( )
9593 . focused ( $focusedField, equals: . baseAccessURL)
9694 }
97- }
95+ } . formStyle ( . grouped) . scrollDisabled ( true ) . padding ( . horizontal)
96+ Divider ( )
9897 HStack {
98+ Spacer ( )
99+ Button ( " Cancel " , action: { dismiss ( ) } ) . keyboardShortcut ( . cancelAction)
99100 Button ( " Next " , action: next)
100- . buttonStyle ( . borderedProminent)
101101 . keyboardShortcut ( . defaultAction)
102102 }
103- . padding ( . top, 10 )
104- } . padding ( . horizontal, 15 )
103+ . padding ( 20 )
104+ }
105+ }
106+
107+ private var cliAuthURL : URL {
108+ URL ( string: baseAccessURL) !. appendingPathComponent ( " cli-auth " )
105109 }
106110
107111 private var sessionTokenPage : some View {
108- VStack {
109- VStack ( alignment: . leading) {
110- HStack ( alignment: . firstTextBaseline) {
111- Text ( " Server URL " )
112- Spacer ( )
113- TextField ( " https://coder.example.com " , text: $baseAccessURL)
114- . textFieldStyle ( RoundedBorderTextFieldStyle ( ) )
115- . disableAutocorrection ( true )
116- . frame ( width: 290 , alignment: . leading)
117- . disabled ( true )
112+ VStack ( alignment: . leading, spacing: 0 ) {
113+ Form {
114+ Section {
115+ TextField (
116+ " Server URL " ,
117+ text: $baseAccessURL,
118+ prompt: Text ( " https://coder.example.com " )
119+ ) . disabled ( true )
118120 }
119- HStack ( alignment: . firstTextBaseline) {
120- Text ( " Session Token " )
121- Spacer ( )
122- SecureField ( " " , text: $sessionToken)
123- . textFieldStyle ( RoundedBorderTextFieldStyle ( ) )
124- . disableAutocorrection ( true )
125- . frame ( width: 290 , alignment: . leading)
121+ Section {
122+ SecureField ( " Session Token " , text: $sessionToken, prompt: Text ( " ●●●●●●●● " ) )
123+ . autocorrectionDisabled ( )
126124 . privacySensitive ( )
127125 . focused ( $focusedField, equals: . sessionToken)
126+ HStack ( spacing: 0 ) {
127+ Text ( " Generate a session token at " )
128+ . font ( . subheadline)
129+ . foregroundColor ( . secondary)
130+ Link ( cliAuthURL. absoluteString, destination: cliAuthURL)
131+ . font ( . subheadline)
132+ . foregroundColor ( . blue)
133+ }
128134 }
129- Link (
130- " Generate a token via the Web UI " ,
131- destination: URL ( string: baseAccessURL) !. appendingPathComponent ( " cli-auth " )
132- ) . font ( . callout) . foregroundColor ( . blue) . underline ( )
133- } . padding ( )
135+ } . formStyle ( . grouped) . scrollDisabled ( true ) . padding ( . horizontal)
136+ Divider ( )
134137 HStack {
135- Button ( " Back " , action: back)
138+ Spacer ( )
139+ Button ( " Back " , action: back) . keyboardShortcut ( . cancelAction)
136140 Button ( " Sign In " ) {
137141 Task { await submit ( ) }
138142 }
139143 . buttonStyle ( . borderedProminent)
140144 . keyboardShortcut ( . defaultAction)
141- } . padding ( . top, 5 )
145+ }
146+ . padding ( 20 )
142147 }
143148 }
144149
0 commit comments