feat(widgets): add native Android and iOS home screen players

Publish artwork, metadata, and transport state through a shared Dart bridge. Add configurable Android RemoteViews and iOS WidgetKit players with controls and links into the full player.

Serialize widget commands and session restoration, and share one headless-capable iOS Flutter engine with the foreground scene. Include native integration tests, Dart bridge tests, and widget setup documentation.
This commit is contained in:
zarzet committed 2026-09-25 01:22:58 +07:00
1 parent 64445a09fc
commit 040c328479
34 files changed
+1601 -16

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
import Foundation
struct PlayerWidgetState: Codable {
var id = ""
var title = ""
var artist = ""
var album = ""
var playing = false
var canPlay = false
var canPrevious = false
var canNext = false
var background: UInt32 = 0xff292433
var artworkKey = ""
var artworkName = ""
static let kind = "SpotiFLACPlayer"
static var container: URL? {
let group = Bundle.main.object(forInfoDictionaryKey: "PlayerWidgetAppGroup") as? String
?? "group.com.zarz.spotiflac"
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: group)
}
static func read() -> PlayerWidgetState {
guard let url = container?.appendingPathComponent("player.json"),
let data = try? Data(contentsOf: url),
let state = try? JSONDecoder().decode(Self.self, from: data) else { return Self() }
return state
}
var artworkURL: URL? {
guard !artworkName.isEmpty, !artworkName.contains("/") else { return nil }
return Self.container?.appendingPathComponent(artworkName)
}
static var preview: PlayerWidgetState {
var value = Self()
value.title = "Your favorite music"
value.artist = "SpotiFLAC"
value.album = "Now Playing"
value.canPlay = true
value.canPrevious = true
value.canNext = true
return value
}
}