mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-28 12:22:12 +02:00
chore: rebuild dev history without streaming-era commits
This commit is contained in:
@@ -5,6 +5,15 @@ import Gobackend // Import Go framework
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
private let CHANNEL = "com.zarz.spotiflac/backend"
|
||||
private let DOWNLOAD_PROGRESS_STREAM_CHANNEL = "com.zarz.spotiflac/download_progress_stream"
|
||||
private let LIBRARY_SCAN_PROGRESS_STREAM_CHANNEL = "com.zarz.spotiflac/library_scan_progress_stream"
|
||||
private let streamQueue = DispatchQueue(label: "com.zarz.spotiflac.progress_stream", qos: .utility)
|
||||
private var downloadProgressTimer: DispatchSourceTimer?
|
||||
private var downloadProgressEventSink: FlutterEventSink?
|
||||
private var lastDownloadProgressPayload: String?
|
||||
private var libraryScanProgressTimer: DispatchSourceTimer?
|
||||
private var libraryScanProgressEventSink: FlutterEventSink?
|
||||
private var lastLibraryScanProgressPayload: String?
|
||||
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
@@ -16,14 +25,111 @@ import Gobackend // Import Go framework
|
||||
name: CHANNEL,
|
||||
binaryMessenger: controller.binaryMessenger
|
||||
)
|
||||
let downloadProgressEvents = FlutterEventChannel(
|
||||
name: DOWNLOAD_PROGRESS_STREAM_CHANNEL,
|
||||
binaryMessenger: controller.binaryMessenger
|
||||
)
|
||||
let libraryScanProgressEvents = FlutterEventChannel(
|
||||
name: LIBRARY_SCAN_PROGRESS_STREAM_CHANNEL,
|
||||
binaryMessenger: controller.binaryMessenger
|
||||
)
|
||||
|
||||
channel.setMethodCallHandler { [weak self] call, result in
|
||||
self?.handleMethodCall(call: call, result: result)
|
||||
}
|
||||
downloadProgressEvents.setStreamHandler(
|
||||
ClosureStreamHandler(
|
||||
onListen: { [weak self] _, events in
|
||||
self?.startDownloadProgressStream(events)
|
||||
return nil
|
||||
},
|
||||
onCancel: { [weak self] _ in
|
||||
self?.stopDownloadProgressStream()
|
||||
return nil
|
||||
}
|
||||
)
|
||||
)
|
||||
libraryScanProgressEvents.setStreamHandler(
|
||||
ClosureStreamHandler(
|
||||
onListen: { [weak self] _, events in
|
||||
self?.startLibraryScanProgressStream(events)
|
||||
return nil
|
||||
},
|
||||
onCancel: { [weak self] _ in
|
||||
self?.stopLibraryScanProgressStream()
|
||||
return nil
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopDownloadProgressStream()
|
||||
stopLibraryScanProgressStream()
|
||||
}
|
||||
|
||||
private func startDownloadProgressStream(_ eventSink: @escaping FlutterEventSink) {
|
||||
stopDownloadProgressStream()
|
||||
downloadProgressEventSink = eventSink
|
||||
lastDownloadProgressPayload = nil
|
||||
|
||||
let timer = DispatchSource.makeTimerSource(queue: streamQueue)
|
||||
timer.schedule(deadline: .now(), repeating: .milliseconds(800))
|
||||
timer.setEventHandler { [weak self] in
|
||||
guard let self else { return }
|
||||
let payload = GobackendGetAllDownloadProgress() as String? ?? "{}"
|
||||
if payload == self.lastDownloadProgressPayload {
|
||||
return
|
||||
}
|
||||
self.lastDownloadProgressPayload = payload
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.downloadProgressEventSink?(payload)
|
||||
}
|
||||
}
|
||||
downloadProgressTimer = timer
|
||||
timer.resume()
|
||||
}
|
||||
|
||||
private func stopDownloadProgressStream() {
|
||||
downloadProgressTimer?.setEventHandler {}
|
||||
downloadProgressTimer?.cancel()
|
||||
downloadProgressTimer = nil
|
||||
downloadProgressEventSink = nil
|
||||
lastDownloadProgressPayload = nil
|
||||
}
|
||||
|
||||
private func startLibraryScanProgressStream(_ eventSink: @escaping FlutterEventSink) {
|
||||
stopLibraryScanProgressStream()
|
||||
libraryScanProgressEventSink = eventSink
|
||||
lastLibraryScanProgressPayload = nil
|
||||
|
||||
let timer = DispatchSource.makeTimerSource(queue: streamQueue)
|
||||
timer.schedule(deadline: .now(), repeating: .milliseconds(800))
|
||||
timer.setEventHandler { [weak self] in
|
||||
guard let self else { return }
|
||||
let payload = GobackendGetLibraryScanProgressJSON() as String? ?? "{}"
|
||||
if payload == self.lastLibraryScanProgressPayload {
|
||||
return
|
||||
}
|
||||
self.lastLibraryScanProgressPayload = payload
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.libraryScanProgressEventSink?(payload)
|
||||
}
|
||||
}
|
||||
libraryScanProgressTimer = timer
|
||||
timer.resume()
|
||||
}
|
||||
|
||||
private func stopLibraryScanProgressStream() {
|
||||
libraryScanProgressTimer?.setEventHandler {}
|
||||
libraryScanProgressTimer?.cancel()
|
||||
libraryScanProgressTimer = nil
|
||||
libraryScanProgressEventSink = nil
|
||||
lastLibraryScanProgressPayload = nil
|
||||
}
|
||||
|
||||
private func handleMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
@@ -74,6 +180,14 @@ import Gobackend // Import Go framework
|
||||
let response = GobackendSearchSpotifyAll(query, Int(trackLimit), Int(artistLimit), &error)
|
||||
if let error = error { throw error }
|
||||
return response
|
||||
|
||||
case "getSpotifyRelatedArtists":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let artistId = args["artist_id"] as! String
|
||||
let limit = args["limit"] as? Int ?? 12
|
||||
let response = GobackendGetSpotifyRelatedArtists(artistId, Int(limit), &error)
|
||||
if let error = error { throw error }
|
||||
return response
|
||||
|
||||
case "checkAvailability":
|
||||
let args = call.arguments as! [String: Any]
|
||||
@@ -282,6 +396,14 @@ import Gobackend // Import Go framework
|
||||
if let error = error { throw error }
|
||||
return response
|
||||
|
||||
case "getDeezerRelatedArtists":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let artistId = args["artist_id"] as! String
|
||||
let limit = args["limit"] as? Int ?? 12
|
||||
let response = GobackendGetDeezerRelatedArtists(artistId, Int(limit), &error)
|
||||
if let error = error { throw error }
|
||||
return response
|
||||
|
||||
case "getDeezerMetadata":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let resourceType = args["resource_type"] as! String
|
||||
@@ -840,3 +962,27 @@ import Gobackend // Import Go framework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class ClosureStreamHandler: NSObject, FlutterStreamHandler {
|
||||
typealias ListenHandler = (_ arguments: Any?, _ events: @escaping FlutterEventSink) -> FlutterError?
|
||||
typealias CancelHandler = (_ arguments: Any?) -> FlutterError?
|
||||
|
||||
private let onListenHandler: ListenHandler
|
||||
private let onCancelHandler: CancelHandler
|
||||
|
||||
init(
|
||||
onListen: @escaping ListenHandler,
|
||||
onCancel: @escaping CancelHandler = { _ in nil }
|
||||
) {
|
||||
self.onListenHandler = onListen
|
||||
self.onCancelHandler = onCancel
|
||||
}
|
||||
|
||||
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
|
||||
onListenHandler(arguments, events)
|
||||
}
|
||||
|
||||
func onCancel(withArguments arguments: Any?) -> FlutterError? {
|
||||
onCancelHandler(arguments)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,5 +105,11 @@
|
||||
<string>tidal</string>
|
||||
<string>youtube-music</string>
|
||||
</array>
|
||||
|
||||
<!-- Background audio playback -->
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
Reference in New Issue
Block a user