Migrate to the latest version of Factory (#1097)
This commit is contained in:
parent
439cd85c77
commit
29b917ead0
|
@ -21,9 +21,12 @@ import SwiftUI
|
||||||
|
|
||||||
final class MainCoordinator: NavigationCoordinatable {
|
final class MainCoordinator: NavigationCoordinatable {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
|
@Injected(\.currentUserSession)
|
||||||
|
private var userSession
|
||||||
|
|
||||||
var stack: Stinsen.NavigationStack<MainCoordinator>
|
var stack: Stinsen.NavigationStack<MainCoordinator>
|
||||||
|
|
||||||
@Root
|
@Root
|
||||||
|
@ -50,7 +53,7 @@ final class MainCoordinator: NavigationCoordinatable {
|
||||||
do {
|
do {
|
||||||
try await SwiftfinStore.setupDataStack()
|
try await SwiftfinStore.setupDataStack()
|
||||||
|
|
||||||
if UserSession.current() != nil, !Defaults[.signOutOnClose] {
|
if userSession != nil, !Defaults[.signOutOnClose] {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
withAnimation(.linear(duration: 0.1)) {
|
withAnimation(.linear(duration: 0.1)) {
|
||||||
let _ = root(\.serverCheck)
|
let _ = root(\.serverCheck)
|
||||||
|
@ -118,9 +121,9 @@ final class MainCoordinator: NavigationCoordinatable {
|
||||||
@objc
|
@objc
|
||||||
func didChangeCurrentServerURL(_ notification: Notification) {
|
func didChangeCurrentServerURL(_ notification: Notification) {
|
||||||
|
|
||||||
guard UserSession.current() != nil else { return }
|
guard userSession != nil else { return }
|
||||||
|
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignIn].post()
|
Notifications[.didSignIn].post()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import SwiftUI
|
||||||
|
|
||||||
final class MainCoordinator: NavigationCoordinatable {
|
final class MainCoordinator: NavigationCoordinatable {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
var stack: Stinsen.NavigationStack<MainCoordinator>
|
var stack: Stinsen.NavigationStack<MainCoordinator>
|
||||||
|
@ -38,7 +38,7 @@ final class MainCoordinator: NavigationCoordinatable {
|
||||||
do {
|
do {
|
||||||
try await SwiftfinStore.setupDataStack()
|
try await SwiftfinStore.setupDataStack()
|
||||||
|
|
||||||
if UserSession.current() != nil {
|
if Container.shared.currentUserSession() != nil {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
withAnimation(.linear(duration: 0.1)) {
|
withAnimation(.linear(duration: 0.1)) {
|
||||||
let _ = root(\.mainTab)
|
let _ = root(\.mainTab)
|
||||||
|
|
|
@ -98,7 +98,7 @@ extension BaseItemDto {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: client passing for widget/shared group views?
|
// TODO: client passing for widget/shared group views?
|
||||||
guard let client = UserSession.current()?.client else { return nil }
|
guard let client = Container.shared.currentUserSession()?.client else { return nil }
|
||||||
|
|
||||||
let parameters = Paths.GetItemImageParameters(
|
let parameters = Paths.GetItemImageParameters(
|
||||||
maxWidth: scaleWidth,
|
maxWidth: scaleWidth,
|
||||||
|
|
|
@ -21,7 +21,7 @@ extension BaseItemDto {
|
||||||
let tempOverkillBitrate = 360_000_000
|
let tempOverkillBitrate = 360_000_000
|
||||||
let profile = DeviceProfile.build(for: currentVideoPlayerType, maxBitrate: tempOverkillBitrate)
|
let profile = DeviceProfile.build(for: currentVideoPlayerType, maxBitrate: tempOverkillBitrate)
|
||||||
|
|
||||||
let userSession = UserSession.current()!
|
let userSession = Container.shared.currentUserSession()!
|
||||||
|
|
||||||
let playbackInfo = PlaybackInfoDto(deviceProfile: profile)
|
let playbackInfo = PlaybackInfoDto(deviceProfile: profile)
|
||||||
let playbackInfoParameters = Paths.GetPostedPlaybackInfoParameters(
|
let playbackInfoParameters = Paths.GetPostedPlaybackInfoParameters(
|
||||||
|
@ -56,7 +56,7 @@ extension BaseItemDto {
|
||||||
profile.directPlayProfiles = [DirectPlayProfile(type: .video)]
|
profile.directPlayProfiles = [DirectPlayProfile(type: .video)]
|
||||||
}
|
}
|
||||||
|
|
||||||
let userSession = UserSession.current()!
|
let userSession = Container.shared.currentUserSession()!
|
||||||
|
|
||||||
let playbackInfo = PlaybackInfoDto(deviceProfile: profile)
|
let playbackInfo = PlaybackInfoDto(deviceProfile: profile)
|
||||||
let playbackInfoParameters = Paths.GetPostedPlaybackInfoParameters(
|
let playbackInfoParameters = Paths.GetPostedPlaybackInfoParameters(
|
||||||
|
|
|
@ -193,8 +193,7 @@ extension BaseItemDto {
|
||||||
parameters: parameters
|
parameters: parameters
|
||||||
)
|
)
|
||||||
|
|
||||||
let imageURL = UserSession
|
let imageURL = Container.shared.currentUserSession()!
|
||||||
.current()!
|
|
||||||
.client
|
.client
|
||||||
.fullURL(with: request)
|
.fullURL(with: request)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ extension BaseItemPerson: Poster {
|
||||||
|
|
||||||
func portraitImageSources(maxWidth: CGFloat? = nil) -> [ImageSource] {
|
func portraitImageSources(maxWidth: CGFloat? = nil) -> [ImageSource] {
|
||||||
|
|
||||||
guard let client = UserSession.current()?.client else { return [] }
|
guard let client = Container.shared.currentUserSession()?.client else { return [] }
|
||||||
|
|
||||||
// TODO: figure out what to do about screen scaling with .main being deprecated
|
// TODO: figure out what to do about screen scaling with .main being deprecated
|
||||||
// - maxWidth assume already scaled?
|
// - maxWidth assume already scaled?
|
||||||
|
|
|
@ -18,7 +18,7 @@ extension MediaSourceInfo {
|
||||||
|
|
||||||
func videoPlayerViewModel(with item: BaseItemDto, playSessionID: String) throws -> VideoPlayerViewModel {
|
func videoPlayerViewModel(with item: BaseItemDto, playSessionID: String) throws -> VideoPlayerViewModel {
|
||||||
|
|
||||||
let userSession: UserSession! = UserSession.current()
|
let userSession: UserSession! = Container.shared.currentUserSession()
|
||||||
let playbackURL: URL
|
let playbackURL: URL
|
||||||
let streamType: StreamType
|
let streamType: StreamType
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ extension MediaSourceInfo {
|
||||||
|
|
||||||
func liveVideoPlayerViewModel(with item: BaseItemDto, playSessionID: String) throws -> VideoPlayerViewModel {
|
func liveVideoPlayerViewModel(with item: BaseItemDto, playSessionID: String) throws -> VideoPlayerViewModel {
|
||||||
|
|
||||||
let userSession: UserSession! = UserSession.current()
|
let userSession: UserSession! = Container.shared.currentUserSession()
|
||||||
let playbackURL: URL
|
let playbackURL: URL
|
||||||
let streamType: StreamType
|
let streamType: StreamType
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ extension MediaStream {
|
||||||
static var none: MediaStream = .init(displayTitle: L10n.none, index: -1)
|
static var none: MediaStream = .init(displayTitle: L10n.none, index: -1)
|
||||||
|
|
||||||
var asPlaybackChild: VLCVideoPlayer.PlaybackChild? {
|
var asPlaybackChild: VLCVideoPlayer.PlaybackChild? {
|
||||||
guard let deliveryURL, let client = UserSession.current()?.client else { return nil }
|
guard let deliveryURL, let client = Container.shared.currentUserSession()?.client else { return nil }
|
||||||
|
|
||||||
let deliveryPath = deliveryURL.removingFirst(if: client.configuration.url.absoluteString.last == "/")
|
let deliveryPath = deliveryURL.removingFirst(if: client.configuration.url.absoluteString.last == "/")
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import UDPBroadcast
|
||||||
|
|
||||||
class ServerDiscovery {
|
class ServerDiscovery {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
private var connection: UDPBroadcastConnection?
|
private var connection: UDPBroadcastConnection?
|
||||||
|
|
|
@ -12,17 +12,12 @@ import Foundation
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
|
|
||||||
extension Container {
|
extension Container {
|
||||||
|
var downloadManager: Factory<DownloadManager> { self { DownloadManager() }.shared }
|
||||||
static let downloadManager = Factory(scope: .singleton) {
|
|
||||||
let manager = DownloadManager()
|
|
||||||
manager.clearTmp()
|
|
||||||
return manager
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DownloadManager: ObservableObject {
|
class DownloadManager: ObservableObject {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
|
|
|
@ -38,9 +38,9 @@ class DownloadTask: NSObject, ObservableObject {
|
||||||
case ready
|
case ready
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
@Injected(UserSession.current)
|
@Injected(\.currentUserSession)
|
||||||
private var userSession: UserSession!
|
private var userSession: UserSession!
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
|
@ -80,8 +80,7 @@ class DownloadTask: NSObject, ObservableObject {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
self.state = .error(error)
|
self.state = .error(error)
|
||||||
|
|
||||||
Container.downloadManager()
|
Container.shared.downloadManager.reset()
|
||||||
.remove(task: self)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -284,8 +283,7 @@ extension DownloadTask: URLSessionDownloadDelegate {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.state = .error(error)
|
self.state = .error(error)
|
||||||
|
|
||||||
Container.downloadManager()
|
Container.shared.downloadManager.reset()
|
||||||
.remove(task: self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +293,7 @@ extension DownloadTask: URLSessionDownloadDelegate {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.state = .error(error)
|
self.state = .error(error)
|
||||||
|
|
||||||
Container.downloadManager()
|
Container.shared.downloadManager.reset()
|
||||||
.remove(task: self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,8 @@ import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import KeychainSwift
|
import KeychainSwift
|
||||||
|
|
||||||
enum Keychain {
|
extension Container {
|
||||||
|
|
||||||
// TODO: take a look at all security options
|
// TODO: take a look at all security options
|
||||||
static let service = Factory<KeychainSwift>(scope: .singleton) {
|
var keychainService: Factory<KeychainSwift> { self { KeychainSwift() }.singleton }
|
||||||
KeychainSwift()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,22 +13,28 @@ import Logging
|
||||||
import Pulse
|
import Pulse
|
||||||
|
|
||||||
// TODO: cleanup
|
// TODO: cleanup
|
||||||
|
extension Container {
|
||||||
|
var logService: Factory<Logger> { self { Logger(label: "org.jellyfin.swiftfin") }.singleton }
|
||||||
|
|
||||||
enum LogManager {
|
var pulseNetworkLogger: Factory<NetworkLogger> {
|
||||||
|
self {
|
||||||
static let service = Factory<Logger>(scope: .singleton) {
|
let configuration = NetworkLogger.Configuration()
|
||||||
Logger(label: "org.jellyfin.swiftfin")
|
return NetworkLogger(configuration: configuration)
|
||||||
|
}
|
||||||
|
.singleton
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LogManager {
|
||||||
// TODO: make rules for logging sessions and redacting
|
// TODO: make rules for logging sessions and redacting
|
||||||
|
|
||||||
static let pulseNetworkLogger = Factory<NetworkLogger>(scope: .singleton) {
|
// static let pulseNetworkLogger = Factory<NetworkLogger>(scope: .singleton) {
|
||||||
var configuration = NetworkLogger.Configuration()
|
// var configuration = NetworkLogger.Configuration()
|
||||||
|
|
||||||
// TODO: this used to be necessary to stop the mass of image requests
|
// TODO: this used to be necessary to stop the mass of image requests
|
||||||
// clogging the logs, however don't seem necessary anymore?
|
// clogging the logs, however don't seem necessary anymore?
|
||||||
// Find out how to get images to be logged and have an option to
|
// Find out how to get images to be logged and have an option to
|
||||||
// turn it on, via SuperUser.
|
// turn it on, via SuperUser.
|
||||||
|
|
||||||
// configuration.willHandleEvent = { event -> LoggerStore.Event? in
|
// configuration.willHandleEvent = { event -> LoggerStore.Event? in
|
||||||
// switch event {
|
// switch event {
|
||||||
|
@ -46,8 +52,8 @@ enum LogManager {
|
||||||
// return event
|
// return event
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return NetworkLogger(configuration: configuration)
|
// return NetworkLogger(configuration: configuration)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SwiftfinConsoleLogger: LogHandler {
|
struct SwiftfinConsoleLogger: LogHandler {
|
||||||
|
@ -79,7 +85,7 @@ struct SwiftfinConsoleLogger: LogHandler {
|
||||||
|
|
||||||
struct SwiftfinCorestoreLogger: CoreStoreLogger {
|
struct SwiftfinCorestoreLogger: CoreStoreLogger {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
func log(
|
func log(
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Foundation
|
||||||
|
|
||||||
class SwiftfinNotification {
|
class SwiftfinNotification {
|
||||||
|
|
||||||
@Injected(Notifications.service)
|
@Injected(\.notificationCenter)
|
||||||
private var notificationService
|
private var notificationService
|
||||||
|
|
||||||
let name: Notification.Name
|
let name: Notification.Name
|
||||||
|
@ -37,9 +37,11 @@ class SwiftfinNotification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Notifications {
|
extension Container {
|
||||||
|
var notificationCenter: Factory<NotificationCenter> { self { NotificationCenter.default }.singleton }
|
||||||
|
}
|
||||||
|
|
||||||
static let service = Factory(scope: .singleton) { NotificationCenter.default }
|
enum Notifications {
|
||||||
|
|
||||||
struct Key: Hashable {
|
struct Key: Hashable {
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ final class UserSession {
|
||||||
let client = JellyfinClient(
|
let client = JellyfinClient(
|
||||||
configuration: .swiftfinConfiguration(url: server.currentURL),
|
configuration: .swiftfinConfiguration(url: server.currentURL),
|
||||||
sessionConfiguration: .swiftfin,
|
sessionConfiguration: .swiftfin,
|
||||||
sessionDelegate: URLSessionProxyDelegate(logger: LogManager.pulseNetworkLogger()),
|
sessionDelegate: URLSessionProxyDelegate(logger: Container.shared.pulseNetworkLogger()),
|
||||||
accessToken: user.accessToken
|
accessToken: user.accessToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,32 +39,27 @@ final class UserSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate extension Container.Scope {
|
extension Container {
|
||||||
|
var currentUserSession: Factory<UserSession?> {
|
||||||
|
self {
|
||||||
|
if let lastUserID = Defaults[.lastSignedInUserID],
|
||||||
|
let user = try? SwiftfinStore.dataStack.fetchOne(
|
||||||
|
From<UserModel>().where(\.$id == lastUserID)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
guard let server = user.server,
|
||||||
|
let _ = SwiftfinStore.dataStack.fetchExisting(server)
|
||||||
|
else {
|
||||||
|
fatalError("No associated server for last user")
|
||||||
|
}
|
||||||
|
|
||||||
// static let userSessionScope = .
|
return .init(
|
||||||
}
|
server: server.state,
|
||||||
|
user: user.state
|
||||||
extension UserSession {
|
)
|
||||||
|
|
||||||
static let current = Factory<UserSession?>(scope: .cached) {
|
|
||||||
|
|
||||||
if let lastUserID = Defaults[.lastSignedInUserID],
|
|
||||||
let user = try? SwiftfinStore.dataStack.fetchOne(
|
|
||||||
From<UserModel>().where(\.$id == lastUserID)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
guard let server = user.server,
|
|
||||||
let existingServer = SwiftfinStore.dataStack.fetchExisting(server)
|
|
||||||
else {
|
|
||||||
fatalError("No associated server for last user")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .init(
|
return nil
|
||||||
server: server.state,
|
}.cached
|
||||||
user: user.state
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import Combine
|
import Combine
|
||||||
import CoreStore
|
import CoreStore
|
||||||
|
import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
@ -125,7 +126,7 @@ extension StoredValue {
|
||||||
domain: key.domain
|
domain: key.domain
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
LogManager.service().error("Unable to store and create publisher for: \(key)")
|
Container.shared.logService().error("Unable to store and create publisher for: \(key)")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ extension StoredValues.Keys {
|
||||||
domain: String,
|
domain: String,
|
||||||
default defaultValue: Value
|
default defaultValue: Value
|
||||||
) -> Key<Value> {
|
) -> Key<Value> {
|
||||||
guard let name, let currentUser = UserSession.current()?.user else {
|
guard let name, let currentUser = Container.shared.currentUserSession()?.user else {
|
||||||
return Key(always: defaultValue)
|
return Key(always: defaultValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import CoreStore
|
import CoreStore
|
||||||
|
import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import KeychainSwift
|
import KeychainSwift
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ extension SwiftfinStore.Mappings {
|
||||||
|
|
||||||
// move access token to Keychain
|
// move access token to Keychain
|
||||||
if let id = sourceObject["id"] as? String, let accessToken = sourceObject["accessToken"] as? String {
|
if let id = sourceObject["id"] as? String, let accessToken = sourceObject["accessToken"] as? String {
|
||||||
Keychain.service().set(accessToken, forKey: "\(id)-accessToken")
|
Container.shared.keychainService().set(accessToken, forKey: "\(id)-accessToken")
|
||||||
} else {
|
} else {
|
||||||
fatalError("wtf")
|
fatalError("wtf")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import CoreStore
|
import CoreStore
|
||||||
|
import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
import Pulse
|
import Pulse
|
||||||
|
@ -41,7 +42,7 @@ extension SwiftfinStore.State {
|
||||||
JellyfinClient(
|
JellyfinClient(
|
||||||
configuration: .swiftfinConfiguration(url: currentURL),
|
configuration: .swiftfinConfiguration(url: currentURL),
|
||||||
sessionConfiguration: .swiftfin,
|
sessionConfiguration: .swiftfin,
|
||||||
sessionDelegate: URLSessionProxyDelegate(logger: LogManager.pulseNetworkLogger())
|
sessionDelegate: URLSessionProxyDelegate(logger: Container.shared.pulseNetworkLogger())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ typealias UserState = SwiftfinStore.State.User
|
||||||
|
|
||||||
// MARK: Namespaces
|
// MARK: Namespaces
|
||||||
|
|
||||||
|
extension Container {
|
||||||
|
var dataStore: Factory<DataStack> { self { SwiftfinStore.dataStack }.singleton }
|
||||||
|
}
|
||||||
|
|
||||||
enum SwiftfinStore {
|
enum SwiftfinStore {
|
||||||
|
|
||||||
/// Namespace for V1 objects
|
/// Namespace for V1 objects
|
||||||
|
@ -64,14 +68,10 @@ extension SwiftfinStore {
|
||||||
case .success:
|
case .success:
|
||||||
continuation.resume()
|
continuation.resume()
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
LogManager.service().error("Failed creating datastack with: \(error.localizedDescription)")
|
Container.shared.logService().error("Failed creating datastack with: \(error.localizedDescription)")
|
||||||
continuation.resume(throwing: JellyfinAPIError("Failed creating datastack with: \(error.localizedDescription)"))
|
continuation.resume(throwing: JellyfinAPIError("Failed creating datastack with: \(error.localizedDescription)"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static let service = Factory<DataStack>(scope: .singleton) {
|
|
||||||
SwiftfinStore.dataStack
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import CoreStore
|
import CoreStore
|
||||||
|
import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
import KeychainSwift
|
import KeychainSwift
|
||||||
|
@ -42,7 +43,7 @@ extension UserState {
|
||||||
|
|
||||||
var accessToken: String {
|
var accessToken: String {
|
||||||
get {
|
get {
|
||||||
guard let accessToken = Keychain.service().get("\(id)-accessToken") else {
|
guard let accessToken = Container.shared.keychainService().get("\(id)-accessToken") else {
|
||||||
assertionFailure("access token missing in keychain")
|
assertionFailure("access token missing in keychain")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -50,7 +51,7 @@ extension UserState {
|
||||||
return accessToken
|
return accessToken
|
||||||
}
|
}
|
||||||
nonmutating set {
|
nonmutating set {
|
||||||
Keychain.service().set(newValue, forKey: "\(id)-accessToken")
|
Container.shared.keychainService().set(newValue, forKey: "\(id)-accessToken")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ extension UserState {
|
||||||
|
|
||||||
UserDefaults.userSuite(id: id).removeAll()
|
UserDefaults.userSuite(id: id).removeAll()
|
||||||
|
|
||||||
let keychain = Keychain.service()
|
let keychain = Container.shared.keychainService()
|
||||||
keychain.delete("\(id)-pin")
|
keychain.delete("\(id)-pin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ extension UserState {
|
||||||
let client = JellyfinClient(
|
let client = JellyfinClient(
|
||||||
configuration: .swiftfinConfiguration(url: server.currentURL),
|
configuration: .swiftfinConfiguration(url: server.currentURL),
|
||||||
sessionConfiguration: .swiftfin,
|
sessionConfiguration: .swiftfin,
|
||||||
sessionDelegate: URLSessionProxyDelegate(logger: LogManager.pulseNetworkLogger()),
|
sessionDelegate: URLSessionProxyDelegate(logger: Container.shared.pulseNetworkLogger()),
|
||||||
accessToken: accessToken
|
accessToken: accessToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import Combine
|
import Combine
|
||||||
import CoreStore
|
import CoreStore
|
||||||
|
import Factory
|
||||||
import Foundation
|
import Foundation
|
||||||
import Get
|
import Get
|
||||||
import JellyfinAPI
|
import JellyfinAPI
|
||||||
|
@ -146,7 +147,7 @@ final class ConnectToServerViewModel: ViewModel, Eventful, Stateful {
|
||||||
|
|
||||||
let client = JellyfinClient(
|
let client = JellyfinClient(
|
||||||
configuration: .swiftfinConfiguration(url: url),
|
configuration: .swiftfinConfiguration(url: url),
|
||||||
sessionDelegate: URLSessionProxyDelegate(logger: LogManager.pulseNetworkLogger())
|
sessionDelegate: URLSessionProxyDelegate(logger: Container.shared.pulseNetworkLogger())
|
||||||
)
|
)
|
||||||
|
|
||||||
let response = try await client.send(Paths.getPublicSystemInfo)
|
let response = try await client.send(Paths.getPublicSystemInfo)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import SwiftUI
|
||||||
|
|
||||||
class DownloadListViewModel: ViewModel {
|
class DownloadListViewModel: ViewModel {
|
||||||
|
|
||||||
@Injected(Container.downloadManager)
|
@Injected(\.downloadManager)
|
||||||
private var downloadManager
|
private var downloadManager
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
|
|
|
@ -110,7 +110,7 @@ final class SettingsViewModel: ViewModel {
|
||||||
|
|
||||||
func signOut() {
|
func signOut() {
|
||||||
Defaults[.lastSignedInUserID] = nil
|
Defaults[.lastSignedInUserID] = nil
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignOut].post()
|
Notifications[.didSignOut].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,17 +13,17 @@ import KeychainSwift
|
||||||
|
|
||||||
class ViewModel: ObservableObject {
|
class ViewModel: ObservableObject {
|
||||||
|
|
||||||
@Injected(SwiftfinStore.service)
|
@Injected(\.dataStore)
|
||||||
var dataStack
|
var dataStack
|
||||||
|
|
||||||
@Injected(Keychain.service)
|
@Injected(\.keychainService)
|
||||||
var keychain
|
var keychain
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
var logger
|
var logger
|
||||||
|
|
||||||
/// The current *signed in* user session
|
/// The current *signed in* user session
|
||||||
@Injected(UserSession.current)
|
@Injected(\.currentUserSession)
|
||||||
var userSession: UserSession!
|
var userSession: UserSession!
|
||||||
|
|
||||||
var cancellables = Set<AnyCancellable>()
|
var cancellables = Set<AnyCancellable>()
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct SwiftfinApp: App {
|
||||||
|
|
||||||
if Defaults[.signOutOnBackground], backgroundedInterval > Defaults[.backgroundSignOutInterval] {
|
if Defaults[.signOutOnBackground], backgroundedInterval > Defaults[.backgroundSignOutInterval] {
|
||||||
Defaults[.lastSignedInUserID] = nil
|
Defaults[.lastSignedInUserID] = nil
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignOut].post()
|
Notifications[.didSignOut].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ extension ItemView {
|
||||||
|
|
||||||
struct PlayButton: View {
|
struct PlayButton: View {
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
|
|
|
@ -306,7 +306,7 @@ struct SelectUserView: View {
|
||||||
self.isPresentingError = true
|
self.isPresentingError = true
|
||||||
case let .signedIn(user):
|
case let .signedIn(user):
|
||||||
Defaults[.lastSignedInUserID] = user.id
|
Defaults[.lastSignedInUserID] = user.id
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignIn].post()
|
Notifications[.didSignIn].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ struct UserSignInView: View {
|
||||||
router.dismissCoordinator()
|
router.dismissCoordinator()
|
||||||
|
|
||||||
Defaults[.lastSignedInUserID] = user.id
|
Defaults[.lastSignedInUserID] = user.id
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignIn].post()
|
Notifications[.didSignIn].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5172,7 +5172,7 @@
|
||||||
repositoryURL = "https://github.com/sindresorhus/Defaults";
|
repositoryURL = "https://github.com/sindresorhus/Defaults";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = 7.0.0;
|
minimumVersion = 8.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E145EB492BE16849003BF6F3 /* XCRemoteSwiftPackageReference "keychain-swift" */ = {
|
E145EB492BE16849003BF6F3 /* XCRemoteSwiftPackageReference "keychain-swift" */ = {
|
||||||
|
@ -5228,7 +5228,7 @@
|
||||||
repositoryURL = "https://github.com/hmlongco/Factory";
|
repositoryURL = "https://github.com/hmlongco/Factory";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = 1.0.0;
|
minimumVersion = 2.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E19DDEC52948EF9900954E10 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
|
E19DDEC52948EF9900954E10 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"originHash" : "323b2ad9aaa9c000faf264d68272f0e9fab1349d9f910a0b95ee6aea10460f31",
|
"originHash" : "651194fc1966b57201a0de2cba27dc40798bbdf515febdc83f00d634d916fea4",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "blurhashkit",
|
"identity" : "blurhashkit",
|
||||||
|
@ -51,8 +51,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/sindresorhus/Defaults",
|
"location" : "https://github.com/sindresorhus/Defaults",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "3efef5a28ebdbbe922d4a2049493733ed14475a6",
|
"revision" : "38925e3cfacf3fb89a81a35b1cd44fd5a5b7e0fa",
|
||||||
"version" : "7.3.1"
|
"version" : "8.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -69,8 +69,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/hmlongco/Factory",
|
"location" : "https://github.com/hmlongco/Factory",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "39ff6a675cd0272d833d184d35add0f8fddd63de",
|
"revision" : "587995f7d5cc667951d635fbf6b4252324ba0439",
|
||||||
"version" : "1.3.7"
|
"version" : "2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct SwiftfinApp: App {
|
||||||
|
|
||||||
if backgroundedInterval > Defaults[.backgroundSignOutInterval] {
|
if backgroundedInterval > Defaults[.backgroundSignOutInterval] {
|
||||||
Defaults[.lastSignedInUserID] = nil
|
Defaults[.lastSignedInUserID] = nil
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignOut].post()
|
Notifications[.didSignOut].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ extension DownloadTaskView {
|
||||||
@Default(.accentColor)
|
@Default(.accentColor)
|
||||||
private var accentColor
|
private var accentColor
|
||||||
|
|
||||||
@Injected(Container.downloadManager)
|
@Injected(\.downloadManager)
|
||||||
private var downloadManager
|
private var downloadManager
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
|
|
|
@ -18,7 +18,7 @@ extension ItemView {
|
||||||
@Default(.accentColor)
|
@Default(.accentColor)
|
||||||
private var accentColor
|
private var accentColor
|
||||||
|
|
||||||
@Injected(Container.downloadManager)
|
@Injected(\.downloadManager)
|
||||||
private var downloadManager: DownloadManager
|
private var downloadManager: DownloadManager
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct DownloadTaskButton: View {
|
||||||
extension DownloadTaskButton {
|
extension DownloadTaskButton {
|
||||||
|
|
||||||
init(item: BaseItemDto) {
|
init(item: BaseItemDto) {
|
||||||
let downloadManager = Container.downloadManager()
|
let downloadManager = Container.shared.downloadManager()
|
||||||
|
|
||||||
self.downloadTask = downloadManager.task(for: item) ?? .init(item: item)
|
self.downloadTask = downloadManager.task(for: item) ?? .init(item: item)
|
||||||
self.onSelect = { _ in }
|
self.onSelect = { _ in }
|
||||||
|
|
|
@ -19,7 +19,7 @@ extension ItemView {
|
||||||
@Default(.accentColor)
|
@Default(.accentColor)
|
||||||
private var accentColor
|
private var accentColor
|
||||||
|
|
||||||
@Injected(LogManager.service)
|
@Injected(\.logService)
|
||||||
private var logger
|
private var logger
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
|
|
|
@ -562,7 +562,7 @@ struct SelectUserView: View {
|
||||||
UIDevice.feedback(.success)
|
UIDevice.feedback(.success)
|
||||||
|
|
||||||
Defaults[.lastSignedInUserID] = user.id
|
Defaults[.lastSignedInUserID] = user.id
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignIn].post()
|
Notifications[.didSignIn].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ extension SettingsView {
|
||||||
|
|
||||||
struct UserProfileRow: View {
|
struct UserProfileRow: View {
|
||||||
|
|
||||||
@Injected(UserSession.current)
|
@Injected(\.currentUserSession)
|
||||||
private var userSession: UserSession!
|
private var userSession: UserSession!
|
||||||
|
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
|
@ -74,7 +74,7 @@ struct UserSignInView: View {
|
||||||
UIDevice.feedback(.success)
|
UIDevice.feedback(.success)
|
||||||
|
|
||||||
Defaults[.lastSignedInUserID] = user.id
|
Defaults[.lastSignedInUserID] = user.id
|
||||||
UserSession.current.reset()
|
Container.shared.currentUserSession.reset()
|
||||||
Notifications[.didSignIn].post()
|
Notifications[.didSignIn].post()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue