mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-30 13:19:44 +02:00
feat(player): add Mornye media notification controls
Sync notification favorites with Library, add Mornye transport icons and an output action on legacy Android, and expose the iOS favorite command. Preserve playback position when controls refresh. Vendor audio_service 0.18.19 with a small Android patch for custom notification actions. Modern Android keeps its system output switcher and transport layout.
This commit is contained in:
1 parent
728d179d69
commit
5259c86365
80 files changed
+8973
-13
No files matched your search
@@ -24,6 +24,7 @@ import UniformTypeIdentifiers
|
||||
private var libraryScanProgressGeneration: UInt64 = 0
|
||||
private var backendChannel: FlutterMethodChannel?
|
||||
private var concertCalendar: ConcertCalendarBridge?
|
||||
private var playbackNotification: PlaybackNotificationBridge?
|
||||
private let coreBackend: CoreBackend = createCoreBackend()
|
||||
private var pendingSessionGrantEvents: [[String: Any]] = []
|
||||
|
||||
@@ -110,6 +111,7 @@ import UniformTypeIdentifiers
|
||||
)
|
||||
|
||||
GeneratedPluginRegistrant.register(with: registry)
|
||||
playbackNotification = PlaybackNotificationBridge(messenger: messenger)
|
||||
registry.registrar(forPlugin: "AudioOutputView")?.register(
|
||||
AudioOutputViewFactory(messenger: messenger),
|
||||
withId: "com.zarz.spotiflac/audio_output"
|
||||
|
||||
@@ -1,7 +1,41 @@
|
||||
import AVKit
|
||||
import Flutter
|
||||
import MediaPlayer
|
||||
import UIKit
|
||||
|
||||
/// iOS owns the lock-screen layout, transport glyphs and AirPlay button.
|
||||
/// Supply its favorite command with the same state/action as the Mornye player.
|
||||
final class PlaybackNotificationBridge {
|
||||
private let channel: FlutterMethodChannel
|
||||
private var target: Any?
|
||||
|
||||
init(messenger: FlutterBinaryMessenger) {
|
||||
channel = FlutterMethodChannel(name: "com.zarz.spotiflac/playback_notification", binaryMessenger: messenger)
|
||||
let command = MPRemoteCommandCenter.shared().likeCommand
|
||||
target = command.addTarget { [weak self] _ in
|
||||
guard let self else { return .commandFailed }
|
||||
self.channel.invokeMethod("favorite", arguments: nil)
|
||||
return .success
|
||||
}
|
||||
command.isEnabled = false
|
||||
channel.setMethodCallHandler { call, result in
|
||||
guard call.method == "update", let values = call.arguments as? [String: Any] else {
|
||||
result(FlutterMethodNotImplemented)
|
||||
return
|
||||
}
|
||||
command.isEnabled = values["enabled"] as? Bool ?? false
|
||||
command.isActive = values["loved"] as? Bool ?? false
|
||||
command.localizedTitle = values["label"] as? String ?? "Favorite"
|
||||
result(nil)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
if let target { MPRemoteCommandCenter.shared().likeCommand.removeTarget(target) }
|
||||
channel.setMethodCallHandler(nil)
|
||||
}
|
||||
}
|
||||
|
||||
final class AudioOutputViewFactory: NSObject, FlutterPlatformViewFactory {
|
||||
private let messenger: FlutterBinaryMessenger
|
||||
|
||||
|
||||
Reference in new issue
Block a user