76 lines
2.8 KiB
Swift
76 lines
2.8 KiB
Swift
import Domain
|
|
import Foundation
|
|
import Synchronization
|
|
|
|
public final class FakeSource: LibrarySource, Starring, LyricsSource {
|
|
public let id: SourceID
|
|
public let name: String
|
|
private let catalog: FakeCatalog
|
|
private let artworkDirectory: URL
|
|
private struct Extras {
|
|
var changes: [Change] = []
|
|
var artwork: [String: URL] = [:]
|
|
var lyrics: [String: URL] = [:]
|
|
}
|
|
|
|
private let extras = Mutex(Extras())
|
|
|
|
public init(id: SourceID = SourceID(), name: String = "Demo Library") {
|
|
self.id = id
|
|
self.name = name
|
|
catalog = FakeCatalog(source: id)
|
|
artworkDirectory = FileManager.default.temporaryDirectory.appending(path: "FakeSourceArtwork", directoryHint: .isDirectory)
|
|
try? FileManager.default.createDirectory(at: artworkDirectory, withIntermediateDirectories: true)
|
|
}
|
|
|
|
public var sampleTracks: [Track] {
|
|
catalog.changes.compactMap {
|
|
if case let .upsert(.track(track)) = $0 {
|
|
return track
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public func add(_ changes: [Change], artworkFiles: [String: URL], lyricsFiles: [String: URL] = [:]) {
|
|
extras.withLock {
|
|
$0.changes += changes
|
|
$0.artwork.merge(artworkFiles) { $1 }
|
|
$0.lyrics.merge(lyricsFiles) { $1 }
|
|
}
|
|
}
|
|
|
|
public func lyrics(for track: EntityID) async throws -> Lyrics? {
|
|
guard let file = extras.withLock({ $0.lyrics[track.remote] }) else { return nil }
|
|
return try Lyrics(lrc: String(contentsOf: file, encoding: .utf8))
|
|
}
|
|
|
|
public func changes(since cursor: Cursor?) -> AsyncThrowingStream<Change, Error> {
|
|
let changes = cursor == nil ? catalog.changes + extras.withLock(\.changes) : []
|
|
return AsyncThrowingStream { continuation in
|
|
changes.forEach { continuation.yield($0) }
|
|
continuation.yield(.checkpoint(Cursor("1")))
|
|
continuation.finish()
|
|
}
|
|
}
|
|
|
|
public func stream(for _: EntityID) async throws -> StreamRequest {
|
|
throw SourceError.notFound
|
|
}
|
|
|
|
public func artwork(_ id: EntityID, pixelSize: Int) async throws -> ResourceRequest {
|
|
if let file = extras.withLock({ $0.artwork[id.remote] }) {
|
|
return ResourceRequest(url: file)
|
|
}
|
|
let side = pixelSize <= 320 ? 320 : 1024
|
|
let file = artworkDirectory.appending(path: "\(id.remote)-\(side).png")
|
|
if !FileManager.default.fileExists(atPath: file.path) {
|
|
guard let data = FakeArtwork.png(seed: id.remote, side: side) else { throw SourceError.notFound }
|
|
try data.write(to: file, options: .atomic)
|
|
}
|
|
return ResourceRequest(url: file)
|
|
}
|
|
|
|
public func setFavorite(_: Bool, for _: EntityID, kind _: EntityKind) async throws {}
|
|
}
|