Add UserLoginView
This commit is contained in:
parent
1576d9d6b7
commit
e81b593fa1
|
@ -67,18 +67,17 @@ struct SettingsView: View {
|
|||
Spacer()
|
||||
Button {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
let nc = NotificationCenter.default
|
||||
nc.post(name: Notification.Name("didSignOut"), object: nil)
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||
}
|
||||
} label: {
|
||||
Text("Switch user").font(.callout)
|
||||
}
|
||||
}
|
||||
Button {
|
||||
// TODO: remove delay
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
SessionManager.current.logout()
|
||||
let nc = NotificationCenter.default
|
||||
nc.post(name: Notification.Name("didSignOut"), object: nil)
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||
}
|
||||
} label: {
|
||||
Text("Sign out").font(.callout)
|
||||
|
|
|
@ -276,6 +276,12 @@
|
|||
E13DD3EA27177ED6009D4DAF /* ServerListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3E827177ED6009D4DAF /* ServerListCoordinator.swift */; };
|
||||
E13DD3EC27178A54009D4DAF /* UserLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3EB27178A54009D4DAF /* UserLoginViewModel.swift */; };
|
||||
E13DD3ED27178A54009D4DAF /* UserLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3EB27178A54009D4DAF /* UserLoginViewModel.swift */; };
|
||||
E13DD3EF27178F87009D4DAF /* NotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3EE27178F87009D4DAF /* NotificationCenter.swift */; };
|
||||
E13DD3F027178F87009D4DAF /* NotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3EE27178F87009D4DAF /* NotificationCenter.swift */; };
|
||||
E13DD3F227179378009D4DAF /* UserLoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3F127179378009D4DAF /* UserLoginCoordinator.swift */; };
|
||||
E13DD3F327179378009D4DAF /* UserLoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3F127179378009D4DAF /* UserLoginCoordinator.swift */; };
|
||||
E13DD3F5271793BB009D4DAF /* UserLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3F4271793BB009D4DAF /* UserLoginView.swift */; };
|
||||
E13DD3F6271793BB009D4DAF /* UserLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E13DD3F4271793BB009D4DAF /* UserLoginView.swift */; };
|
||||
E14F7D0726DB36EF007C3AE6 /* ItemPortraitMainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14F7D0626DB36EF007C3AE6 /* ItemPortraitMainView.swift */; };
|
||||
E14F7D0926DB36F7007C3AE6 /* ItemLandscapeMainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14F7D0826DB36F7007C3AE6 /* ItemLandscapeMainView.swift */; };
|
||||
E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */; };
|
||||
|
@ -517,6 +523,9 @@
|
|||
E13DD3E427177D15009D4DAF /* ServerListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerListView.swift; sourceTree = "<group>"; };
|
||||
E13DD3E827177ED6009D4DAF /* ServerListCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerListCoordinator.swift; sourceTree = "<group>"; };
|
||||
E13DD3EB27178A54009D4DAF /* UserLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLoginViewModel.swift; sourceTree = "<group>"; };
|
||||
E13DD3EE27178F87009D4DAF /* NotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCenter.swift; sourceTree = "<group>"; };
|
||||
E13DD3F127179378009D4DAF /* UserLoginCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLoginCoordinator.swift; sourceTree = "<group>"; };
|
||||
E13DD3F4271793BB009D4DAF /* UserLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserLoginView.swift; sourceTree = "<group>"; };
|
||||
E14F7D0626DB36EF007C3AE6 /* ItemPortraitMainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPortraitMainView.swift; sourceTree = "<group>"; };
|
||||
E14F7D0826DB36F7007C3AE6 /* ItemLandscapeMainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemLandscapeMainView.swift; sourceTree = "<group>"; };
|
||||
E173DA4F26D048D600CC4EB7 /* ServerDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailView.swift; sourceTree = "<group>"; };
|
||||
|
@ -1029,6 +1038,7 @@
|
|||
62C29EA026D102A500C1D2E7 /* MainTabCoordinator.swift */,
|
||||
6220D0B626D5EE1100B8E046 /* SearchCoordinator.swift */,
|
||||
E13DD3E827177ED6009D4DAF /* ServerListCoordinator.swift */,
|
||||
E13DD3F127179378009D4DAF /* UserLoginCoordinator.swift */,
|
||||
6220D0B026D5EC9900B8E046 /* SettingsCoordinator.swift */,
|
||||
6220D0C526D62D8700B8E046 /* VideoPlayerCoordinator.swift */,
|
||||
);
|
||||
|
@ -1039,6 +1049,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
536D3D73267BA8170004248C /* BackgroundManager.swift */,
|
||||
E13DD3EE27178F87009D4DAF /* NotificationCenter.swift */,
|
||||
53649AB0269CFB1900A2D8B7 /* LogManager.swift */,
|
||||
62EC352E267666A5000E9F2D /* SessionManager.swift */,
|
||||
);
|
||||
|
@ -1112,6 +1123,7 @@
|
|||
E13DD3E427177D15009D4DAF /* ServerListView.swift */,
|
||||
539B2DA4263BA5B8007FF1A4 /* SettingsView.swift */,
|
||||
625CB5672678B6FB00530A6E /* SplashView.swift */,
|
||||
E13DD3F4271793BB009D4DAF /* UserLoginView.swift */,
|
||||
53F8377C265FF67C00F456B3 /* VideoPlayerSettingsView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
|
@ -1541,11 +1553,13 @@
|
|||
C4E5081D2703F8370045C9AB /* LibrarySearchView.swift in Sources */,
|
||||
53ABFDE9267974EF00886593 /* HomeViewModel.swift in Sources */,
|
||||
53116A17268B919A003024C9 /* SeriesItemView.swift in Sources */,
|
||||
E13DD3F027178F87009D4DAF /* NotificationCenter.swift in Sources */,
|
||||
E13DD3DA27169406009D4DAF /* SwiftfinStoreKeychain.swift in Sources */,
|
||||
531690E7267ABD79005D8AB9 /* HomeView.swift in Sources */,
|
||||
53ABFDDE267974E300886593 /* SplashView.swift in Sources */,
|
||||
53ABFDE8267974EF00886593 /* SplashViewModel.swift in Sources */,
|
||||
62E632DE267D2E170063E547 /* LatestMediaViewModel.swift in Sources */,
|
||||
E13DD3F327179378009D4DAF /* UserLoginCoordinator.swift in Sources */,
|
||||
E1FCD09726C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
E13DD3EA27177ED6009D4DAF /* ServerListCoordinator.swift in Sources */,
|
||||
53116A19268B947A003024C9 /* PlainLinkButton.swift in Sources */,
|
||||
|
@ -1609,6 +1623,7 @@
|
|||
E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */,
|
||||
53ABFDEB2679753200886593 /* ConnectToServerView.swift in Sources */,
|
||||
536D3D76267BA9BB0004248C /* MainTabViewModel.swift in Sources */,
|
||||
E13DD3F6271793BB009D4DAF /* UserLoginView.swift in Sources */,
|
||||
5310695C2684E7EE00CFFDBA /* VideoPlayerViewController.swift in Sources */,
|
||||
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */,
|
||||
536D3D74267BA8170004248C /* BackgroundManager.swift in Sources */,
|
||||
|
@ -1635,6 +1650,7 @@
|
|||
5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */,
|
||||
6220D0B426D5ED8000B8E046 /* LibraryCoordinator.swift in Sources */,
|
||||
6220D0C026D61C5000B8E046 /* ItemCoordinator.swift in Sources */,
|
||||
E13DD3F227179378009D4DAF /* UserLoginCoordinator.swift in Sources */,
|
||||
621338932660107500A81A2A /* StringExtensions.swift in Sources */,
|
||||
53FF7F2A263CF3F500585C35 /* LatestMediaView.swift in Sources */,
|
||||
62E632EC267D410B0063E547 /* SeriesItemViewModel.swift in Sources */,
|
||||
|
@ -1682,6 +1698,7 @@
|
|||
E188460026DECB9E00B0C5B7 /* ItemLandscapeTopBarView.swift in Sources */,
|
||||
091B5A8B2683142E00D78B61 /* UDPBroadCastConnection.swift in Sources */,
|
||||
6267B3D626710B8900A7371D /* CollectionExtensions.swift in Sources */,
|
||||
E13DD3F5271793BB009D4DAF /* UserLoginView.swift in Sources */,
|
||||
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */,
|
||||
53649AB1269CFB1900A2D8B7 /* LogManager.swift in Sources */,
|
||||
E13DD3E127176BD3009D4DAF /* ServerListViewModel.swift in Sources */,
|
||||
|
@ -1725,6 +1742,7 @@
|
|||
5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */,
|
||||
09389CC726819B4600AE350E /* VideoPlayerModel.swift in Sources */,
|
||||
6220D0B726D5EE1100B8E046 /* SearchCoordinator.swift in Sources */,
|
||||
E13DD3EF27178F87009D4DAF /* NotificationCenter.swift in Sources */,
|
||||
5377CBF5263B596A003A4E83 /* JellyfinPlayerApp.swift in Sources */,
|
||||
E1FCD09626C47118007C8DCF /* ErrorMessage.swift in Sources */,
|
||||
53EE24E6265060780068F029 /* LibrarySearchView.swift in Sources */,
|
||||
|
|
|
@ -82,7 +82,7 @@ extension AppURLHandler {
|
|||
// It would be nice if the ItemViewModel could be initialized to id later.
|
||||
getItem(userID: userID, itemID: itemID) { item in
|
||||
guard let item = item else { return }
|
||||
NotificationCenter.default.post(name: Notification.Name("processDeepLink"), object: DeepLink.item(item))
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.processDeepLink, object: DeepLink.item(item))
|
||||
}
|
||||
|
||||
return true
|
||||
|
|
|
@ -15,6 +15,11 @@ final class ConnectToServerCoodinator: NavigationCoordinatable {
|
|||
let stack = NavigationStack(initial: \ConnectToServerCoodinator.start)
|
||||
|
||||
@Root var start = makeStart
|
||||
@Route(.push) var userLogin = makeUserLogin
|
||||
|
||||
func makeUserLogin(server: SwiftfinStore.Models.Server) -> UserLoginCoordinator {
|
||||
return UserLoginCoordinator(viewModel: .init(server: server))
|
||||
}
|
||||
|
||||
@ViewBuilder func makeStart() -> some View {
|
||||
ConnectToServerView()
|
||||
|
|
|
@ -37,10 +37,10 @@ import SwiftUI
|
|||
UIScrollView.appearance().keyboardDismissMode = .onDrag
|
||||
#endif
|
||||
|
||||
let nc = NotificationCenter.default
|
||||
nc.addObserver(self, selector: #selector(didLogIn), name: Notification.Name("didSignIn"), object: nil)
|
||||
nc.addObserver(self, selector: #selector(didLogOut), name: Notification.Name("didSignOut"), object: nil)
|
||||
nc.addObserver(self, selector: #selector(processDeepLink), name: Notification.Name("processDeepLink"), object: nil)
|
||||
let nc = SwiftfinNotificationCenter.main
|
||||
nc.addObserver(self, selector: #selector(didLogIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
|
||||
nc.addObserver(self, selector: #selector(didLogOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||
nc.addObserver(self, selector: #selector(processDeepLink), name: SwiftfinNotificationCenter.Keys.processDeepLink, object: nil)
|
||||
}
|
||||
|
||||
@objc func didLogIn() {
|
||||
|
|
|
@ -16,14 +16,11 @@ final class ServerListCoordinator: NavigationCoordinatable {
|
|||
|
||||
@Root var start = makeStart
|
||||
@Route(.push) var connectToServer = makeConnectToServer
|
||||
// @Route(.push) var loginUser = makeLoginuser
|
||||
|
||||
func makeConnectToServer() -> ConnectToServerCoodinator {
|
||||
ConnectToServerCoodinator()
|
||||
}
|
||||
|
||||
// func makeLoginUser ->
|
||||
|
||||
@ViewBuilder func makeStart() -> some View {
|
||||
ServerListView(viewModel: ServerListViewModel())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Stinsen
|
||||
import SwiftUI
|
||||
|
||||
final class UserLoginCoordinator: NavigationCoordinatable {
|
||||
let stack = NavigationStack(initial: \UserLoginCoordinator.start)
|
||||
|
||||
@Root var start = makeStart
|
||||
|
||||
let viewModel: UserLoginViewModel
|
||||
|
||||
init(viewModel: UserLoginViewModel) {
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
|
||||
@ViewBuilder func makeStart() -> some View {
|
||||
UserLoginView(viewModel: viewModel)
|
||||
}
|
||||
}
|
|
@ -539,7 +539,7 @@ class PlayerViewController: UIViewController, GCKDiscoveryManagerListener, GCKRe
|
|||
self.delegate?.exitPlayer(self)
|
||||
// TODO: todo
|
||||
// SessionManager.current.logout()
|
||||
main?.root(\.connectToServer)
|
||||
main?.root(\.serverList)
|
||||
case .error:
|
||||
self.delegate?.exitPlayer(self)
|
||||
}
|
||||
|
|
|
@ -72,180 +72,3 @@ struct ConnectToServerView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//struct ConnectToServerView: View {
|
||||
// @EnvironmentObject var mainRouter: MainCoordinator.Router
|
||||
// @StateObject var viewModel = ConnectToServerViewModel()
|
||||
// @State var username = ""
|
||||
// @State var password = ""
|
||||
// @State var uri = ""
|
||||
//
|
||||
// var body: some View {
|
||||
// ZStack {
|
||||
// Form {
|
||||
// if viewModel.isConnectedServer {
|
||||
// if viewModel.publicUsers.isEmpty {
|
||||
// Section(header: Text("Login to \(SessionManager.main.currentLogin.server.name)")) {
|
||||
// TextField(NSLocalizedString("Username", comment: ""), text: $username)
|
||||
// .disableAutocorrection(true)
|
||||
// .autocapitalization(.none)
|
||||
// SecureField(NSLocalizedString("Password", comment: ""), text: $password)
|
||||
// .disableAutocorrection(true)
|
||||
// .autocapitalization(.none)
|
||||
// Button {
|
||||
// viewModel.login()
|
||||
// } label: {
|
||||
// HStack {
|
||||
// Text("Login")
|
||||
// Spacer()
|
||||
// if viewModel.isLoading {
|
||||
// ProgressView()
|
||||
// }
|
||||
// }
|
||||
// }.disabled(viewModel.isLoading || username.isEmpty)
|
||||
// }
|
||||
//
|
||||
// Section {
|
||||
// Button {
|
||||
// viewModel.isConnectedServer = false
|
||||
// } label: {
|
||||
// HStack {
|
||||
// HStack {
|
||||
// Image(systemName: "chevron.left")
|
||||
// Text("Change Server")
|
||||
// }
|
||||
// Spacer()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// Section(header: Text("Login to \(SessionManager.main.currentLogin.server.name)")) {
|
||||
// ForEach(viewModel.publicUsers, id: \.id) { publicUser in
|
||||
// HStack {
|
||||
// Button(action: {
|
||||
// // TODO: todo
|
||||
// print("TODO")
|
||||
//// if SessionManager.current.doesUserHaveSavedSession(userID: publicUser.id!) {
|
||||
//// let user = SessionManager.current.getSavedSession(userID: publicUser.id!)
|
||||
//// SessionManager.current.loginWithSavedSession(user: user)
|
||||
//// mainRouter.root(\.mainTab)
|
||||
//// } else {
|
||||
//// username = publicUser.name ?? ""
|
||||
//// viewModel.selectedPublicUser = publicUser
|
||||
//// viewModel.hidePublicUsers()
|
||||
//// if !(publicUser.hasPassword ?? true) {
|
||||
//// password = ""
|
||||
//// DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||
//// viewModel.login()
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
// }) {
|
||||
// HStack {
|
||||
// Text(publicUser.name ?? "").font(.subheadline).fontWeight(.semibold)
|
||||
// Spacer()
|
||||
// if publicUser.primaryImageTag != nil {
|
||||
// ImageView(src: URL(string: "\(SessionManager.main.currentLogin.server.uri)/Users/\(publicUser.id ?? "")/Images/Primary?width=60&quality=80&tag=\(publicUser.primaryImageTag!)")!)
|
||||
// .frame(width: 60, height: 60)
|
||||
// .cornerRadius(30.0)
|
||||
// } else {
|
||||
// Image(systemName: "person.fill")
|
||||
// .foregroundColor(Color(red: 1, green: 1, blue: 1).opacity(0.8))
|
||||
// .font(.system(size: 35))
|
||||
// .frame(width: 60, height: 60)
|
||||
// .background(Color(red: 98 / 255, green: 121 / 255, blue: 205 / 255))
|
||||
// .cornerRadius(30.0)
|
||||
// .shadow(radius: 6)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Section {
|
||||
// Button {
|
||||
// viewModel.publicUsers.removeAll()
|
||||
// username = ""
|
||||
// } label: {
|
||||
// HStack {
|
||||
// Text("Other User").font(.subheadline).fontWeight(.semibold)
|
||||
// Spacer()
|
||||
// Image(systemName: "person.fill.questionmark")
|
||||
// .foregroundColor(Color(red: 1, green: 1, blue: 1).opacity(0.8))
|
||||
// .font(.system(size: 35))
|
||||
// .frame(width: 60, height: 60)
|
||||
// .background(Color(red: 98 / 255, green: 121 / 255, blue: 205 / 255))
|
||||
// .cornerRadius(30.0)
|
||||
// .shadow(radius: 6)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// Section(header: Text("Connect Manually")) {
|
||||
// TextField(NSLocalizedString("Server URL", comment: ""), text: $uri)
|
||||
// .disableAutocorrection(true)
|
||||
// .autocapitalization(.none)
|
||||
// .keyboardType(.URL)
|
||||
// Button {
|
||||
// viewModel.connectToServer()
|
||||
// } label: {
|
||||
// HStack {
|
||||
// Text("Connect")
|
||||
// Spacer()
|
||||
// if viewModel.isLoading {
|
||||
// ProgressView()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .disabled(viewModel.isLoading || uri.isEmpty)
|
||||
// }
|
||||
//
|
||||
// Section(header: Text("Discovered Servers")) {
|
||||
// if self.viewModel.searching {
|
||||
// ProgressView()
|
||||
// }
|
||||
// ForEach(self.viewModel.servers, id: \.id) { server in
|
||||
// Button(action: {
|
||||
// viewModel.connectToServer(at: server.url)
|
||||
// }, label: {
|
||||
// HStack {
|
||||
// Text(server.name)
|
||||
// .font(.headline)
|
||||
// Text("• \(server.host)")
|
||||
// .font(.subheadline)
|
||||
// .foregroundColor(.secondary)
|
||||
// Spacer()
|
||||
// if viewModel.isLoading {
|
||||
// ProgressView()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// .onAppear(perform: self.viewModel.discoverServers)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .onChange(of: uri) { uri in
|
||||
// viewModel.uriSubject.send(uri)
|
||||
// }
|
||||
// .onChange(of: username) { username in
|
||||
// viewModel.usernameSubject.send(username)
|
||||
// }
|
||||
// .onChange(of: password) { password in
|
||||
// viewModel.passwordSubject.send(password)
|
||||
// }
|
||||
// .alert(item: $viewModel.errorMessage) { _ in
|
||||
// Alert(title: Text("\(viewModel.errorMessage?.code ?? -1)\n\(viewModel.errorMessage?.title ?? "Error")"),
|
||||
// message: Text(viewModel.errorMessage?.displayMessage ?? "Error"),
|
||||
// dismissButton: .cancel())
|
||||
// }
|
||||
// .navigationTitle(NSLocalizedString("Connect to Server", comment: ""))
|
||||
// .onAppear {
|
||||
// AppURLHandler.shared.appURLState = .allowedInLogin
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
|
@ -14,6 +14,7 @@ struct HomeView: View {
|
|||
@EnvironmentObject var homeRouter: HomeCoordinator.Router
|
||||
@StateObject var viewModel = HomeViewModel()
|
||||
|
||||
// TODO: Move so that setup has same button
|
||||
init() {
|
||||
let backButtonBackgroundImage = UIImage(systemName: "chevron.backward.circle.fill")
|
||||
let barAppearance = UINavigationBar.appearance()
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import CoreStore
|
||||
import SwiftUI
|
||||
|
||||
struct ServerListView: View {
|
||||
|
@ -22,13 +23,36 @@ struct ServerListView: View {
|
|||
}
|
||||
.navigationTitle("Servers")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
|
||||
ToolbarItemGroup(placement: .navigation) {
|
||||
HStack {
|
||||
Button {
|
||||
serverListRouter.route(to: \.connectToServer)
|
||||
} label: {
|
||||
Text("Connect")
|
||||
}
|
||||
|
||||
Button {
|
||||
SwiftfinStore.dataStack.perform(asynchronous: { transaction in
|
||||
try! transaction.deleteAll(From<SwiftfinStore.Models.Server>())
|
||||
try! transaction.deleteAll(From<SwiftfinStore.Models.User>())
|
||||
try! transaction.deleteAll(From<SwiftfinStore.Models.AccessToken>())
|
||||
}) { _ in
|
||||
viewModel.servers = []
|
||||
}
|
||||
} label: {
|
||||
Text("Purge")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ToolbarItem(placement: .navigationBarTrailing) {
|
||||
// Button {
|
||||
// serverListRouter.route(to: \.connectToServer)
|
||||
// } label: {
|
||||
// Text("Connect")
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,10 +51,9 @@ struct SettingsView: View {
|
|||
Button {
|
||||
settingsRouter.dismissCoordinator()
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
// TODO: todo
|
||||
// TODO: todo and move notification somewhere else
|
||||
// SessionManager.current.logout()
|
||||
let nc = NotificationCenter.default
|
||||
nc.post(name: Notification.Name("didSignOut"), object: nil)
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||
}
|
||||
} label: {
|
||||
Text("Sign out")
|
||||
|
|
|
@ -20,7 +20,7 @@ struct SplashView: View {
|
|||
if flag {
|
||||
mainRouter.root(\.mainTab)
|
||||
} else {
|
||||
mainRouter.root(\.connectToServer)
|
||||
mainRouter.root(\.serverList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
import Stinsen
|
||||
|
||||
struct UserLoginView: View {
|
||||
|
||||
@ObservedObject var viewModel: UserLoginViewModel
|
||||
@State private var username: String = ""
|
||||
@State private var password: String = ""
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
|
||||
Section {
|
||||
TextField("Username", text: $username)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
SecureField("Password", text: $password)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
||||
Button {
|
||||
viewModel.login(username: username, password: password)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Connect")
|
||||
Spacer()
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled(viewModel.isLoading || username.isEmpty)
|
||||
|
||||
} header: {
|
||||
// TODO: Server
|
||||
Text("Login to \(viewModel.server.name)")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Login")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
enum SwiftfinNotificationCenter {
|
||||
|
||||
static let main: NotificationCenter = {
|
||||
return NotificationCenter()
|
||||
}()
|
||||
|
||||
enum Keys {
|
||||
static let didSignIn = Notification.Name("didSignIn")
|
||||
static let didSignOut = Notification.Name("didSignOut")
|
||||
static let processDeepLink = Notification.Name("processDeepLink")
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
import Combine
|
||||
import CoreData
|
||||
import CoreStore
|
||||
import Defaults
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
import KeychainSwift
|
||||
|
@ -17,6 +18,7 @@ import UIKit
|
|||
|
||||
#if os(tvOS)
|
||||
import TVServices
|
||||
import SwiftUIFocusGuide
|
||||
#endif
|
||||
|
||||
typealias CurrentLogin = (server: SwiftfinStore.Models.Server, user: SwiftfinStore.Models.User)
|
||||
|
@ -30,18 +32,18 @@ final class SessionManager {
|
|||
// MARK: main
|
||||
static let main = SessionManager()
|
||||
|
||||
private let JellyfinDefaults = UserDefaults(suiteName: "jellyfin-defaults")!
|
||||
|
||||
private init() {
|
||||
if let lastServerUserID = SwiftfinStore.Defaults.suite[.lastServerUserID],
|
||||
let userID = lastServerUserID.split(separator: "-")[safe: 1],
|
||||
if let lastUserID = SwiftfinStore.Defaults.suite[.lastServerUserID],
|
||||
let user = try? SwiftfinStore.dataStack.fetchOne(From<SwiftfinStore.Models.User>(),
|
||||
[Where<SwiftfinStore.Models.User>("id == %@", userID)]) {
|
||||
[Where<SwiftfinStore.Models.User>("id == %@", lastUserID)]) {
|
||||
|
||||
// TODO: Fetch for right queue
|
||||
// Strongly assuming that we didn't delete the server associate with the user
|
||||
guard let server = user.server, let accessToken = user.accessToken else { return }
|
||||
guard let existingServer = SwiftfinStore.dataStack.fetchExisting(server) else { return }
|
||||
|
||||
setAuthHeader(with: accessToken.value)
|
||||
currentLogin = (server: server, user: user)
|
||||
currentLogin = (server: existingServer, user: user)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +117,14 @@ final class SessionManager {
|
|||
.handleEvents(receiveOutput: { [unowned self] (user, transaction) in
|
||||
setAuthHeader(with: user.accessToken?.value ?? "")
|
||||
try? transaction.commitAndWait()
|
||||
currentLogin = (server: server, user: user)
|
||||
|
||||
// Fetch for the right queue
|
||||
let currentServer = SwiftfinStore.dataStack.fetchExisting(server)!
|
||||
let currentUser = SwiftfinStore.dataStack.fetchExisting(user)!
|
||||
|
||||
SwiftfinStore.Defaults.suite[.lastServerUserID] = user.id
|
||||
|
||||
currentLogin = (server: currentServer, user: currentUser)
|
||||
})
|
||||
.map({ (user, _) in
|
||||
return user
|
||||
|
@ -123,6 +132,10 @@ final class SessionManager {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func logout() {
|
||||
// TODO: todo
|
||||
}
|
||||
|
||||
private func setAuthHeader(with accessToken: String) {
|
||||
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
var deviceName = UIDevice.current.name
|
||||
|
|
|
@ -14,7 +14,7 @@ import Stinsen
|
|||
|
||||
final class ConnectToServerViewModel: ViewModel {
|
||||
|
||||
@RouterObject var main: MainCoordinator.Router?
|
||||
@RouterObject var router: ConnectToServerCoodinator.Router?
|
||||
@Published var discoveredServers: Set<ServerDiscovery.ServerLookupResponse> = []
|
||||
@Published var searching = false
|
||||
private let discovery = ServerDiscovery()
|
||||
|
@ -33,8 +33,9 @@ final class ConnectToServerViewModel: ViewModel {
|
|||
.sink(receiveCompletion: { completion in
|
||||
self.handleAPIRequestError(displayMessage: "Unable to connect to server.", logLevel: .critical, tag: "connectToServer",
|
||||
completion: completion)
|
||||
}, receiveValue: { _ in
|
||||
}, receiveValue: { server in
|
||||
LogManager.shared.log.debug("Connected to server at \"\(uri)\"", tag: "connectToServer")
|
||||
self.router?.route(to: \.userLogin, server)
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
|
|
@ -16,12 +16,13 @@ import UIKit
|
|||
import WidgetKit
|
||||
#endif
|
||||
|
||||
// TODO: Remove SplashViewModel
|
||||
|
||||
final class SplashViewModel: ViewModel {
|
||||
|
||||
@Published var isLoggedIn: Bool = false
|
||||
|
||||
override init() {
|
||||
// TODO: Remove SplashViewModel
|
||||
isLoggedIn = SessionManager.main.currentLogin != nil
|
||||
super.init()
|
||||
|
||||
|
|
|
@ -7,16 +7,19 @@
|
|||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import CoreStore
|
||||
import Foundation
|
||||
import JellyfinAPI
|
||||
import Stinsen
|
||||
|
||||
final class UserLoginViewModel: ViewModel {
|
||||
|
||||
@RouterObject var router: UserLoginCoordinator.Router?
|
||||
let server: SwiftfinStore.Models.Server
|
||||
|
||||
init(server: SwiftfinStore.Models.Server) {
|
||||
self.server = server
|
||||
// Need to fetch for this context
|
||||
self.server = SwiftfinStore.dataStack.fetchExisting(server)!
|
||||
}
|
||||
|
||||
func login(username: String, password: String) {
|
||||
|
@ -29,19 +32,8 @@ final class UserLoginViewModel: ViewModel {
|
|||
self.handleAPIRequestError(displayMessage: "Unable to connect to server.", logLevel: .critical, tag: "login",
|
||||
completion: completion)
|
||||
} receiveValue: { user in
|
||||
print(user)
|
||||
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
//
|
||||
//
|
||||
// SessionManager.current.login(username: username, password: password)
|
||||
// .trackActivity(loading)
|
||||
// .sink(receiveCompletion: { completion in
|
||||
// self.handleAPIRequestError(displayMessage: "Unable to connect to server.", logLevel: .critical, tag: "login",
|
||||
// completion: completion)
|
||||
// }, receiveValue: { [weak self] _ in
|
||||
// self?.main?.root(\.mainTab)
|
||||
// })
|
||||
// .store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue