Add settings view + fix signin flow

This commit is contained in:
Shav Kinderlehrer 2023-12-15 10:41:00 -05:00
parent 3994a6f408
commit 2e3c12fed3
13 changed files with 307 additions and 88 deletions

View File

@ -11,6 +11,7 @@
3D1015DC2B27F5D300F5C29A /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015DA2B27F5D300F5C29A /* Model.xcdatamodeld */; }; 3D1015DC2B27F5D300F5C29A /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015DA2B27F5D300F5C29A /* Model.xcdatamodeld */; };
3D1015DE2B27F79900F5C29A /* DatamodelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015DD2B27F79900F5C29A /* DatamodelController.swift */; }; 3D1015DE2B27F79900F5C29A /* DatamodelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015DD2B27F79900F5C29A /* DatamodelController.swift */; };
3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015E32B28000E00F5C29A /* AuthStateController.swift */; }; 3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1015E32B28000E00F5C29A /* AuthStateController.swift */; };
3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D41D1F42B2C962500E58234 /* AppearancePicker.swift */; };
3D7709392B29139700199889 /* Pulse in Frameworks */ = {isa = PBXBuildFile; productRef = 3D7709382B29139700199889 /* Pulse */; }; 3D7709392B29139700199889 /* Pulse in Frameworks */ = {isa = PBXBuildFile; productRef = 3D7709382B29139700199889 /* Pulse */; };
3D77093B2B29139700199889 /* PulseUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3D77093A2B29139700199889 /* PulseUI */; }; 3D77093B2B29139700199889 /* PulseUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3D77093A2B29139700199889 /* PulseUI */; };
3D77093D2B29350700199889 /* ConsoleSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D77093C2B29350700199889 /* ConsoleSheetView.swift */; }; 3D77093D2B29350700199889 /* ConsoleSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D77093C2B29350700199889 /* ConsoleSheetView.swift */; };
@ -25,6 +26,9 @@
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; }; 3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; };
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; }; 3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; };
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; }; 3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; };
3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC6BA2C2B2A422300416B9F /* SettingsController.swift */; };
3DDD67932B293BC40026781E /* DashBoardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67922B293BC40026781E /* DashBoardView.swift */; };
3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67952B29E28B0026781E /* SettingsView.swift */; };
3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */; }; 3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -64,6 +68,7 @@
3D1015DB2B27F5D300F5C29A /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; }; 3D1015DB2B27F5D300F5C29A /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
3D1015DD2B27F79900F5C29A /* DatamodelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatamodelController.swift; sourceTree = "<group>"; }; 3D1015DD2B27F79900F5C29A /* DatamodelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatamodelController.swift; sourceTree = "<group>"; };
3D1015E32B28000E00F5C29A /* AuthStateController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthStateController.swift; sourceTree = "<group>"; }; 3D1015E32B28000E00F5C29A /* AuthStateController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthStateController.swift; sourceTree = "<group>"; };
3D41D1F42B2C962500E58234 /* AppearancePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePicker.swift; sourceTree = "<group>"; };
3D77093C2B29350700199889 /* ConsoleSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleSheetView.swift; sourceTree = "<group>"; }; 3D77093C2B29350700199889 /* ConsoleSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleSheetView.swift; sourceTree = "<group>"; };
3D9063C72B279A310063DD2A /* Jel.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Jel.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3D9063C72B279A310063DD2A /* Jel.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Jel.app; sourceTree = BUILT_PRODUCTS_DIR; };
3D9063CA2B279A310063DD2A /* JelApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JelApp.swift; sourceTree = "<group>"; }; 3D9063CA2B279A310063DD2A /* JelApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JelApp.swift; sourceTree = "<group>"; };
@ -80,6 +85,9 @@
3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; }; 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; };
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; }; 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; };
3DC0E5802B2832B9001CCE96 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 3DC0E5802B2832B9001CCE96 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3DC6BA2C2B2A422300416B9F /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
3DDD67922B293BC40026781E /* DashBoardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashBoardView.swift; sourceTree = "<group>"; };
3DDD67952B29E28B0026781E /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinClientController.swift; sourceTree = "<group>"; }; 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinClientController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -115,8 +123,10 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3D9063CC2B279A310063DD2A /* ContentView.swift */, 3D9063CC2B279A310063DD2A /* ContentView.swift */,
3DDD67902B293B780026781E /* Dashboard */,
3DDD67942B29E27A0026781E /* Settings */,
3D91FDC52B28C28900919017 /* SignIn */, 3D91FDC52B28C28900919017 /* SignIn */,
3D77093C2B29350700199889 /* ConsoleSheetView.swift */, 3DDD67912B293B9E0026781E /* Utility */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -127,6 +137,7 @@
3D1015DD2B27F79900F5C29A /* DatamodelController.swift */, 3D1015DD2B27F79900F5C29A /* DatamodelController.swift */,
3D1015E32B28000E00F5C29A /* AuthStateController.swift */, 3D1015E32B28000E00F5C29A /* AuthStateController.swift */,
3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */, 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */,
3DC6BA2C2B2A422300416B9F /* SettingsController.swift */,
); );
path = Controllers; path = Controllers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -211,6 +222,31 @@
path = SignIn; path = SignIn;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
3DDD67902B293B780026781E /* Dashboard */ = {
isa = PBXGroup;
children = (
3DDD67922B293BC40026781E /* DashBoardView.swift */,
);
path = Dashboard;
sourceTree = "<group>";
};
3DDD67912B293B9E0026781E /* Utility */ = {
isa = PBXGroup;
children = (
3D77093C2B29350700199889 /* ConsoleSheetView.swift */,
);
path = Utility;
sourceTree = "<group>";
};
3DDD67942B29E27A0026781E /* Settings */ = {
isa = PBXGroup;
children = (
3DDD67952B29E28B0026781E /* SettingsView.swift */,
3D41D1F42B2C962500E58234 /* AppearancePicker.swift */,
);
path = Settings;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -359,8 +395,12 @@
3D77093D2B29350700199889 /* ConsoleSheetView.swift in Sources */, 3D77093D2B29350700199889 /* ConsoleSheetView.swift in Sources */,
3D1015DC2B27F5D300F5C29A /* Model.xcdatamodeld in Sources */, 3D1015DC2B27F5D300F5C29A /* Model.xcdatamodeld in Sources */,
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */, 3D91FDC92B28C62800919017 /* SignInView.swift in Sources */,
3DDD67932B293BC40026781E /* DashBoardView.swift in Sources */,
3DC6BA2D2B2A422300416B9F /* SettingsController.swift in Sources */,
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */, 3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */,
3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */, 3D1015E42B28000E00F5C29A /* AuthStateController.swift in Sources */,
3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */,
3D41D1F52B2C962500E58234 /* AppearancePicker.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -546,7 +586,7 @@
PRODUCT_BUNDLE_IDENTIFIER = icu.trinket.apps.Jel; PRODUCT_BUNDLE_IDENTIFIER = icu.trinket.apps.Jel;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto; SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
@ -586,7 +626,7 @@
PRODUCT_BUNDLE_IDENTIFIER = icu.trinket.apps.Jel; PRODUCT_BUNDLE_IDENTIFIER = icu.trinket.apps.Jel;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto; SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";

View File

@ -62,24 +62,27 @@ class JellyfinClientController: ObservableObject {
}) })
} }
func isJellyfinServer() async -> Bool { func getPublicServerInfo() async -> PublicSystemInfo? {
let request = Paths.getPublicSystemInfo let request = Paths.getPublicSystemInfo
do { do {
let res = try await api.send(request) let res = try await api.send(request)
if res.statusCode != 200 { if res.statusCode != 200 {
throw JellyfinClientError.badResponseCode throw JellyfinClientError.badResponseCode
} }
return res.value
} catch { } catch {
return false return nil
} }
return true
} }
func signIn(username: String, pw: String) async throws { func signIn(username: String, pw: String) async throws {
let request = Paths.authenticateUserByName(AuthenticateUserByName(pw: pw, username: username)) let request = Paths.authenticateUserByName(AuthenticateUserByName(pw: pw, username: username))
let res = try await self.api.send(request) let res = try await self.api.send(request)
DispatchQueue.main.async {
self.authState.loggedIn = true self.authState.loggedIn = true
self.authState.authToken = res.value.accessToken self.authState.authToken = res.value.accessToken
self.authState.save() self.authState.save()
} }
}
} }

View File

@ -0,0 +1,44 @@
//
// SettingsController.swift
// Jel
//
// Created by zerocool on 12/13/23.
//
import Foundation
enum AppearanceState: Int, CaseIterable, Identifiable, CustomStringConvertible {
case automatic
case light
case dark
var id: Self { self }
var description: String {
switch self {
case .light:
return "Light"
case .dark:
return "Dark"
case .automatic:
return "Automatic"
}
}
}
class SettingsController: ObservableObject {
static let shared: SettingsController = SettingsController()
@Published var appearance: AppearanceState = .automatic
private let defaults = UserDefaults.standard
func save() {
defaults.set(self.appearance.rawValue, forKey: "Settings_appearance")
}
func load() {
let oldAppearance = defaults.integer(forKey: "Settings_appearance")
self.appearance = AppearanceState(rawValue: oldAppearance) ?? .automatic
}
}

View File

@ -10,8 +10,6 @@ import SwiftUI
@main @main
struct JelApp: App { struct JelApp: App {
let datamodelController = DatamodelController.shared let datamodelController = DatamodelController.shared
let authStateController = AuthStateController.shared
let jellyfinClientController = JellyfinClientController(authHeaders: AuthHeaders( let jellyfinClientController = JellyfinClientController(authHeaders: AuthHeaders(
Client: "Jel", Client: "Jel",
Device: UIDevice.current.systemName, Device: UIDevice.current.systemName,
@ -21,15 +19,13 @@ struct JelApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView(authState: authStateController) ContentView()
.environment(\.managedObjectContext, .environment(\.managedObjectContext,
datamodelController.container.viewContext) datamodelController.container.viewContext)
.environmentObject(jellyfinClientController) .environmentObject(jellyfinClientController)
.task { .task {
authStateController.load() AuthStateController.shared.load()
if authStateController.serverUrl != nil { SettingsController.shared.load()
jellyfinClientController.setUrl(url: authStateController.serverUrl!)
}
} }
} }
} }

View File

@ -1,43 +0,0 @@
//
// ConsoleSheetView.swift
// Jel
//
// Created by zerocool on 12/12/23.
//
import SwiftUI
import PulseUI
struct ConsoleSheetView: View {
@Binding var showingConsoleSheet: Bool
var body: some View {
NavigationStack {
List {
NavigationLink {
ConsoleView(mode: .network)
.closeButtonHidden()
} label: {
Text("Network Console")
}
NavigationLink {
ConsoleView(mode: .logs)
.closeButtonHidden()
} label: {
Text("Logs Console")
}
}
.toolbar {
Button {
showingConsoleSheet.toggle()
} label: {
Text("Done")
}
}
}
}
}
#Preview {
ConsoleSheetView(showingConsoleSheet: .constant(true))
}

View File

@ -9,34 +9,36 @@ import SwiftUI
import PulseUI import PulseUI
struct ContentView: View { struct ContentView: View {
@ObservedObject var authState: AuthStateController @EnvironmentObject var jellyfinClient: JellyfinClientController
@StateObject var settingsController: SettingsController = SettingsController.shared
@StateObject var authState: AuthStateController = AuthStateController.shared
@State var showingConsoleSheet: Bool = false @State var showingConsoleSheet: Bool = false
var body: some View { var body: some View {
VStack { VStack {
Button {
showingConsoleSheet.toggle()
} label: {
Label("Console", systemImage: "network")
}
.sheet(isPresented: $showingConsoleSheet) {
ConsoleSheetView(showingConsoleSheet: $showingConsoleSheet)
}
if !authState.loggedIn { if !authState.loggedIn {
SignInView(authState: authState) SignInView()
} else { } else {
Text("Logged in") NavigationStack {
Button("Log out") { DashBoardView()
authState.loggedIn = false
authState.save()
} }
} }
} }
.padding() .padding()
.preferredColorScheme({
switch settingsController.appearance {
case .dark:
return ColorScheme.dark
case .light:
return ColorScheme.light
case .automatic:
return .none
}
}())
} }
} }
#Preview { #Preview {
ContentView(authState: AuthStateController()) ContentView()
} }

View File

@ -0,0 +1,36 @@
//
// DashBoardView.swift
// Jel
//
// Created by zerocool on 12/12/23.
//
import SwiftUI
struct DashBoardView: View {
@State var showingSettingsSheet: Bool = false
var body: some View {
NavigationStack {
VStack {
}
.toolbar {
ToolbarItem {
Button {
showingSettingsSheet.toggle()
} label: {
Label("Settings", systemImage: "gear")
}
}
}
.sheet(isPresented: $showingSettingsSheet) {
SettingsView(showingSettingsView: $showingSettingsSheet)
}
}
}
}
#Preview {
DashBoardView()
}

View File

@ -0,0 +1,25 @@
//
// AppearancePicker.swift
// Jel
//
// Created by zerocool on 12/15/23.
//
import SwiftUI
struct AppearancePicker: View {
@ObservedObject var settingsController: SettingsController = SettingsController.shared
var body: some View {
Picker("Appearance", selection: $settingsController.appearance) {
ForEach(AppearanceState.allCases) { option in
Text(String(describing: option))
}
}
.pickerStyle(.menu)
}
}
#Preview {
AppearancePicker()
}

View File

@ -0,0 +1,68 @@
//
// SettingsView.swift
// Jel
//
// Created by zerocool on 12/13/23.
//
import SwiftUI
import PulseUI
struct SettingsView: View {
@Binding var showingSettingsView: Bool
@StateObject var authState: AuthStateController = AuthStateController.shared
@ObservedObject var settingsController: SettingsController = SettingsController.shared
var body: some View {
NavigationStack {
Form {
Section {
AppearancePicker()
}
Section {
NavigationLink {
ConsoleView()
.closeButtonHidden()
} label: {
Text("Logs")
}
Button(role: .destructive) {
authState.loggedIn = false
authState.save()
} label: {
Text("Sign out")
}
}
}
.navigationTitle("Settings")
.toolbar {
ToolbarItem {
Button {
showingSettingsView.toggle()
settingsController.save()
} label: {
Text("Done")
.bold()
}
}
}
.preferredColorScheme({
switch settingsController.appearance {
case .dark:
return ColorScheme.dark
case .light:
return ColorScheme.light
case .automatic:
return .none
}
}())
}
}
}
#Preview {
SettingsView(showingSettingsView: .constant(true))
}

View File

@ -9,7 +9,7 @@ import SwiftUI
struct AddServerView: View { struct AddServerView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController @EnvironmentObject var jellyfinClient: JellyfinClientController
@ObservedObject var authState: AuthStateController @ObservedObject var authState: AuthStateController = AuthStateController.shared
@Binding var serverUrlIsValid: Bool @Binding var serverUrlIsValid: Bool
@State var serverUrlString: String = "http://" @State var serverUrlString: String = "http://"
@ -73,7 +73,7 @@ struct AddServerView: View {
if isValidUrl(data: serverUrlString) { if isValidUrl(data: serverUrlString) {
let url = URL(string: serverUrlString)! let url = URL(string: serverUrlString)!
jellyfinClient.setUrl(url: url) jellyfinClient.setUrl(url: url)
if await jellyfinClient.isJellyfinServer() { if await jellyfinClient.getPublicServerInfo() != nil {
authState.serverUrl = url authState.serverUrl = url
authState.save() authState.save()
urlHasError = false urlHasError = false
@ -103,6 +103,6 @@ struct AddServerView: View {
} }
#Preview { #Preview {
AddServerView(authState: AuthStateController(), serverUrlIsValid: .constant(false)) AddServerView(serverUrlIsValid: .constant(false))
} }

View File

@ -9,17 +9,19 @@ import SwiftUI
struct SignInToServerView: View { struct SignInToServerView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController @EnvironmentObject var jellyfinClient: JellyfinClientController
@ObservedObject var authState: AuthStateController
@StateObject var authState: AuthStateController = AuthStateController.shared
@State var username: String = "" @State var username: String = ""
@State var password: String = "" @State var password: String = ""
@State var isLoading: Bool = false @State var isLoading: Bool = false
@State var hasError: Bool = false @State var hasError: Bool = false
@State var serverName: String = ""
var body: some View { var body: some View {
VStack { VStack {
Text("Sign in") Text("Sign in to \(serverName)")
.font(.title) .font(.title)
TextField(text: $username) { TextField(text: $username) {
Text("Username") Text("Username")
@ -60,6 +62,13 @@ struct SignInToServerView: View {
.textFieldStyle(.roundedBorder) .textFieldStyle(.roundedBorder)
.textInputAutocapitalization(.never) .textInputAutocapitalization(.never)
.disabled(isLoading) .disabled(isLoading)
.onAppear {
Task {
if let serverInfo = await jellyfinClient.getPublicServerInfo() {
serverName = serverInfo.serverName ?? "Unknown"
}
}
}
} }
func logInToServer() async { func logInToServer() async {
@ -74,6 +83,7 @@ struct SignInToServerView: View {
} }
} }
#Preview { // FIXME: Preview broken for this view
SignInToServerView(authState: AuthStateController()) //#Preview {
} // SignInToServerView()
//}

View File

@ -6,17 +6,20 @@
// //
import SwiftUI import SwiftUI
import PulseUI
struct SignInView: View { struct SignInView: View {
@EnvironmentObject var jellyfinClient: JellyfinClientController @EnvironmentObject var jellyfinClient: JellyfinClientController
@ObservedObject var authState: AuthStateController
@StateObject var authState: AuthStateController = AuthStateController.shared
@State var serverUrlIsValid: Bool = false @State var serverUrlIsValid: Bool = false
@State var showingConsoleSheet: Bool = false
var body: some View { var body: some View {
NavigationStack { NavigationStack {
AddServerView(authState: authState, serverUrlIsValid: $serverUrlIsValid) AddServerView(serverUrlIsValid: $serverUrlIsValid)
.navigationDestination(isPresented: $serverUrlIsValid) { .navigationDestination(isPresented: $serverUrlIsValid) {
SignInToServerView(authState: authState) SignInToServerView()
} }
} }
.onAppear { .onAppear {
@ -31,12 +34,12 @@ struct SignInView: View {
return return
} }
if await jellyfinClient.isJellyfinServer() { if await jellyfinClient.getPublicServerInfo() != nil {
serverUrlIsValid = true serverUrlIsValid = true
} }
} }
} }
#Preview { #Preview {
SignInView(authState: AuthStateController()) SignInView()
} }

View File

@ -0,0 +1,35 @@
//
// ConsoleSheetView.swift
// Jel
//
// Created by zerocool on 12/12/23.
//
import SwiftUI
import PulseUI
struct ConsoleSheetView: View {
@Binding var showingConsoleSheet: Bool
var body: some View {
NavigationStack {
ConsoleView()
.closeButtonHidden()
.navigationTitle("Debug consoles")
.toolbar {
ToolbarItem {
Button {
showingConsoleSheet.toggle()
} label: {
Text("Done")
.bold()
}
}
}
}
}
}
#Preview {
ConsoleSheetView(showingConsoleSheet: .constant(true))
}