Compare commits
No commits in common. "dc4fb77a660086be1ab0abd47e674e356839349e" and "22213037ca032002e889738f435f029db60e5e3e" have entirely different histories.
dc4fb77a66
...
22213037ca
14 changed files with 55 additions and 138 deletions
|
|
@ -14,54 +14,27 @@ let package = Package(
|
|||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "LuminateAPI",
|
||||
name: "LuminateCore",
|
||||
dependencies: [
|
||||
.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
|
||||
.product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession"),
|
||||
.product(name: "SQLite", package: "SQLite.swift"),
|
||||
],
|
||||
plugins: [
|
||||
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "LuminateCore",
|
||||
dependencies: [
|
||||
"LuminateAPI",
|
||||
.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
|
||||
.product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession"),
|
||||
.product(name: "SQLite", package: "SQLite.swift"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "LuminateDI",
|
||||
dependencies: [
|
||||
"LuminateCore",
|
||||
.product(name: "Adwaita", package: "adwaita-swift"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "LuminateHome",
|
||||
dependencies: [
|
||||
"LuminateCore",
|
||||
"LuminateDI",
|
||||
.product(name: "Adwaita", package: "adwaita-swift"),
|
||||
]
|
||||
dependencies: ["LuminateCore", .product(name: "Adwaita", package: "adwaita-swift")]
|
||||
),
|
||||
.target(
|
||||
name: "LuminateLibrary",
|
||||
dependencies: [
|
||||
"LuminateCore",
|
||||
"LuminateDI",
|
||||
.product(name: "Adwaita", package: "adwaita-swift"),
|
||||
]
|
||||
dependencies: ["LuminateCore", .product(name: "Adwaita", package: "adwaita-swift")]
|
||||
),
|
||||
.target(
|
||||
name: "LuminatePlayer",
|
||||
dependencies: [
|
||||
"LuminateCore",
|
||||
"LuminateDI",
|
||||
.product(name: "Adwaita", package: "adwaita-swift"),
|
||||
]
|
||||
dependencies: ["LuminateCore", .product(name: "Adwaita", package: "adwaita-swift")]
|
||||
),
|
||||
.executableTarget(
|
||||
name: "Luminate",
|
||||
|
|
@ -69,7 +42,6 @@ let package = Package(
|
|||
"LuminateHome",
|
||||
"LuminateLibrary",
|
||||
"LuminatePlayer",
|
||||
"LuminateDI",
|
||||
.product(name: "Adwaita", package: "adwaita-swift"),
|
||||
.product(name: "Localized", package: "localized"),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import Adwaita
|
||||
import Foundation
|
||||
import LuminateCore
|
||||
import LuminateDI
|
||||
import LuminateHome
|
||||
import LuminateLibrary
|
||||
import LuminatePlayer
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import Adwaita
|
||||
import Foundation
|
||||
import LuminateCore
|
||||
import LuminateDI
|
||||
|
||||
public struct ServerSetupView: View {
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
public enum LuminateAPI {}
|
||||
33
Sources/LuminateCore/DIContainer.swift
Normal file
33
Sources/LuminateCore/DIContainer.swift
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import Foundation
|
||||
|
||||
public final class DIContainer {
|
||||
|
||||
public static let shared = DIContainer()
|
||||
public private(set) var values = InjectionValues()
|
||||
|
||||
private init() {}
|
||||
|
||||
public func register<T>(
|
||||
_ keyPath: WritableKeyPath<InjectionValues, T?>,
|
||||
value: T
|
||||
) {
|
||||
values[keyPath: keyPath] = value
|
||||
}
|
||||
|
||||
public func resolve<T>(
|
||||
_ keyPath: KeyPath<InjectionValues, T?>
|
||||
) -> T {
|
||||
guard let value = values[keyPath: keyPath] else {
|
||||
fatalError(
|
||||
"DIContainer: No value registered for \(keyPath). "
|
||||
+ "Call DIContainer.shared.register(\\.key, value:) during app startup."
|
||||
)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
values = InjectionValues()
|
||||
}
|
||||
|
||||
}
|
||||
16
Sources/LuminateCore/Injected.swift
Normal file
16
Sources/LuminateCore/Injected.swift
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import Foundation
|
||||
|
||||
@propertyWrapper
|
||||
public struct Injected<T> {
|
||||
|
||||
private let keyPath: KeyPath<InjectionValues, T?>
|
||||
|
||||
public var wrappedValue: T {
|
||||
DIContainer.shared.resolve(keyPath)
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath<InjectionValues, T?>) {
|
||||
self.keyPath = keyPath
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import Foundation
|
||||
import LuminateCore
|
||||
|
||||
public struct InjectionValues {
|
||||
|
||||
|
|
@ -10,4 +9,5 @@ public struct InjectionValues {
|
|||
public var persistence: PersistenceService?
|
||||
|
||||
public init() {}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
@_exported import LuminateAPI
|
||||
@_exported import OpenAPIRuntime
|
||||
@_exported import OpenAPIURLSession
|
||||
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
import Adwaita
|
||||
import Foundation
|
||||
|
||||
public final class DIContainer: @unchecked Sendable {
|
||||
|
||||
public static let shared = DIContainer()
|
||||
public private(set) var values = InjectionValues()
|
||||
private var observers: [AnyKeyPath: [UUID: @Sendable () -> Void]] = [:]
|
||||
private let lock = NSLock()
|
||||
|
||||
private init() {}
|
||||
|
||||
public func register<T>(
|
||||
_ keyPath: WritableKeyPath<InjectionValues, T?>,
|
||||
value: T
|
||||
) {
|
||||
lock.withLock {
|
||||
values[keyPath: keyPath] = value
|
||||
}
|
||||
notifyObservers(for: keyPath)
|
||||
}
|
||||
|
||||
public func resolve<T>(
|
||||
_ keyPath: KeyPath<InjectionValues, T?>
|
||||
) -> T {
|
||||
lock.withLock {
|
||||
guard let value = values[keyPath: keyPath] else {
|
||||
fatalError(
|
||||
"DIContainer: No value registered for \(keyPath). "
|
||||
+ "Call DIContainer.shared.register(\\.key, value:) during app startup."
|
||||
)
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func addObserver<T>(
|
||||
for keyPath: KeyPath<InjectionValues, T?>,
|
||||
handler: @escaping @Sendable () -> Void
|
||||
) -> UUID {
|
||||
let id = UUID()
|
||||
lock.withLock {
|
||||
observers[keyPath, default: [:]][id] = handler
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func removeObserver(_ id: UUID) {
|
||||
lock.withLock {
|
||||
for keyPath in observers.keys {
|
||||
observers[keyPath]?.removeValue(forKey: id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func notifyObservers(for keyPath: AnyKeyPath) {
|
||||
let handlers: [@Sendable () -> Void] = lock.withLock {
|
||||
Array((observers[keyPath] ?? [:]).values)
|
||||
}
|
||||
handlers.forEach { $0() }
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
lock.withLock {
|
||||
values = InjectionValues()
|
||||
observers.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
import Adwaita
|
||||
import Foundation
|
||||
|
||||
@propertyWrapper
|
||||
public struct Injected<T> {
|
||||
|
||||
private let keyPath: KeyPath<InjectionValues, T?>
|
||||
private let observerRef: ObserverRef
|
||||
|
||||
public var wrappedValue: T {
|
||||
DIContainer.shared.resolve(keyPath)
|
||||
}
|
||||
|
||||
public init(_ keyPath: KeyPath<InjectionValues, T?>) {
|
||||
self.keyPath = keyPath
|
||||
self.observerRef = ObserverRef(
|
||||
id: DIContainer.shared.addObserver(for: keyPath) {
|
||||
StateManager.updateViews()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private final class ObserverRef {
|
||||
let id: UUID
|
||||
init(id: UUID) { self.id = id }
|
||||
deinit { DIContainer.shared.removeObserver(id) }
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import Adwaita
|
||||
import Foundation
|
||||
import LuminateCore
|
||||
import LuminateDI
|
||||
|
||||
struct HomePosterCell: View {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import Adwaita
|
||||
import LuminateCore
|
||||
import LuminateDI
|
||||
|
||||
public struct HomeView: View {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue