diff --git a/Coder Desktop/Coder Desktop/Coder_DesktopApp.swift b/Coder Desktop/Coder Desktop/Coder_DesktopApp.swift index 7650386..fa3d364 100644 --- a/Coder Desktop/Coder Desktop/Coder_DesktopApp.swift +++ b/Coder Desktop/Coder Desktop/Coder_DesktopApp.swift @@ -11,9 +11,9 @@ struct DesktopApp: App { EmptyView() } Window("Sign In", id: Windows.login.rawValue) { - LoginForm() - }.environmentObject(appDelegate.session) - .windowResizability(.contentSize) + LoginForm().environmentObject(appDelegate.session) + } + .windowResizability(.contentSize) } } diff --git a/Coder Desktop/Coder Desktop/Views/LoginForm.swift b/Coder Desktop/Coder Desktop/Views/LoginForm.swift index a9b2e5f..776cee9 100644 --- a/Coder Desktop/Coder Desktop/Views/LoginForm.swift +++ b/Coder Desktop/Coder Desktop/Views/LoginForm.swift @@ -15,48 +15,46 @@ struct LoginForm: View { let inspection = Inspection() var body: some View { - VStack { - VStack { - switch currentPage { - case .serverURL: - serverURLPage - .transition(.move(edge: .leading)) - .onAppear { - DispatchQueue.main.async { - focusedField = .baseAccessURL - } + Group { + switch currentPage { + case .serverURL: + serverURLPage + .transition(.move(edge: .leading)) + .onAppear { + DispatchQueue.main.async { + focusedField = .baseAccessURL } - case .sessionToken: - sessionTokenPage - .transition(.move(edge: .trailing)) - .onAppear { - DispatchQueue.main.async { - focusedField = .sessionToken - } + } + case .sessionToken: + sessionTokenPage + .transition(.move(edge: .trailing)) + .onAppear { + DispatchQueue.main.async { + focusedField = .sessionToken } - } - } - .animation(.easeInOut, value: currentPage) - .onAppear { - baseAccessURL = session.baseAccessURL?.absoluteString ?? baseAccessURL - sessionToken = "" - }.padding(.vertical, 35) - .alert("Error", isPresented: Binding( - get: { loginError != nil }, - set: { isPresented in - if !isPresented { - loginError = nil } + } + } + .animation(.easeInOut, value: currentPage) + .onAppear { + baseAccessURL = session.baseAccessURL?.absoluteString ?? baseAccessURL + sessionToken = "" + } + .alert("Error", isPresented: Binding( + get: { loginError != nil }, + set: { isPresented in + if !isPresented { + loginError = nil } - )) { - Button("OK", role: .cancel) {}.keyboardShortcut(.defaultAction) - } message: { - Text(loginError?.description ?? "") } - }.padding() - .frame(width: 450, height: 220) - .disabled(loading) - .onReceive(inspection.notice) { self.inspection.visit(self, $0) } // ViewInspector + )) { + Button("OK", role: .cancel) {}.keyboardShortcut(.defaultAction) + } message: { + Text(loginError?.description ?? "") + }.disabled(loading) + .frame(width: 550) + .fixedSize() + .onReceive(inspection.notice) { self.inspection.visit(self, $0) } // ViewInspector } func submit() async { @@ -82,63 +80,70 @@ struct LoginForm: View { } private var serverURLPage: some View { - VStack(spacing: 15) { - Text("Coder Desktop").font(.title).padding(.bottom, 15) - VStack(alignment: .leading) { - HStack(alignment: .firstTextBaseline) { - Text("Server URL") - Spacer() - TextField("https://coder.example.com", text: $baseAccessURL) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .disableAutocorrection(true) - .frame(width: 290, alignment: .leading) + VStack(spacing: 0) { + Spacer() + Text("Coder Desktop").font(.title).padding(.top, 10) + Form { + Section { + TextField( + "Server URL", + text: $baseAccessURL, + prompt: Text("https://coder.example.com") + ).autocorrectionDisabled() .focused($focusedField, equals: .baseAccessURL) } - } + }.formStyle(.grouped).scrollDisabled(true).padding(.horizontal) + Divider() HStack { + Spacer() + Button("Cancel", action: { dismiss() }).keyboardShortcut(.cancelAction) Button("Next", action: next) - .buttonStyle(.borderedProminent) .keyboardShortcut(.defaultAction) } - .padding(.top, 10) - }.padding(.horizontal, 15) + .padding(20) + } + } + + private var cliAuthURL: URL { + URL(string: baseAccessURL)!.appendingPathComponent("cli-auth") } private var sessionTokenPage: some View { - VStack { - VStack(alignment: .leading) { - HStack(alignment: .firstTextBaseline) { - Text("Server URL") - Spacer() - TextField("https://coder.example.com", text: $baseAccessURL) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .disableAutocorrection(true) - .frame(width: 290, alignment: .leading) - .disabled(true) + VStack(alignment: .leading, spacing: 0) { + Form { + Section { + TextField( + "Server URL", + text: $baseAccessURL, + prompt: Text("https://coder.example.com") + ).disabled(true) } - HStack(alignment: .firstTextBaseline) { - Text("Session Token") - Spacer() - SecureField("", text: $sessionToken) - .textFieldStyle(RoundedBorderTextFieldStyle()) - .disableAutocorrection(true) - .frame(width: 290, alignment: .leading) + Section { + SecureField("Session Token", text: $sessionToken, prompt: Text("●●●●●●●●")) + .autocorrectionDisabled() .privacySensitive() .focused($focusedField, equals: .sessionToken) + HStack(spacing: 0) { + Text("Generate a session token at ") + .font(.subheadline) + .foregroundColor(.secondary) + Link(cliAuthURL.absoluteString, destination: cliAuthURL) + .font(.subheadline) + .foregroundColor(.blue) + } } - Link( - "Generate a token via the Web UI", - destination: URL(string: baseAccessURL)!.appendingPathComponent("cli-auth") - ).font(.callout).foregroundColor(.blue).underline() - }.padding() + }.formStyle(.grouped).scrollDisabled(true).padding(.horizontal) + Divider() HStack { - Button("Back", action: back) + Spacer() + Button("Back", action: back).keyboardShortcut(.cancelAction) Button("Sign In") { Task { await submit() } } .buttonStyle(.borderedProminent) .keyboardShortcut(.defaultAction) - }.padding(.top, 5) + } + .padding(20) } }