Compare commits

..

No commits in common. "dc4fb77a660086be1ab0abd47e674e356839349e" and "22213037ca032002e889738f435f029db60e5e3e" have entirely different histories.

14 changed files with 55 additions and 138 deletions

View file

@ -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"),
],

View file

@ -1,7 +1,6 @@
import Adwaita
import Foundation
import LuminateCore
import LuminateDI
import LuminateHome
import LuminateLibrary
import LuminatePlayer

View file

@ -1,7 +1,6 @@
import Adwaita
import Foundation
import LuminateCore
import LuminateDI
public struct ServerSetupView: View {

View file

@ -1 +0,0 @@
public enum LuminateAPI {}

View 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()
}
}

View 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
}
}

View file

@ -1,5 +1,4 @@
import Foundation
import LuminateCore
public struct InjectionValues {
@ -10,4 +9,5 @@ public struct InjectionValues {
public var persistence: PersistenceService?
public init() {}
}

View file

@ -1,4 +1,3 @@
@_exported import LuminateAPI
@_exported import OpenAPIRuntime
@_exported import OpenAPIURLSession

View file

@ -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()
}
}
}

View file

@ -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) }
}

View file

@ -1,7 +1,6 @@
import Adwaita
import Foundation
import LuminateCore
import LuminateDI
struct HomePosterCell: View {

View file

@ -1,6 +1,5 @@
import Adwaita
import LuminateCore
import LuminateDI
public struct HomeView: View {