fix(ios): keep NWC Live Activity on playing track during in-app pick
This commit is contained in:
@@ -10,6 +10,7 @@ enum NWCLiveActivityShared {
|
||||
private static let keyIsMuted = "nwc.isMuted"
|
||||
private static let keyRevision = "nwc.contentRevision"
|
||||
private static let keyActivityId = "nwc.activityId"
|
||||
private static let keyPreferredTrackIndex = "nwc.preferredTrackIndex"
|
||||
|
||||
private static var defaults: UserDefaults? {
|
||||
UserDefaults(suiteName: appGroupID)
|
||||
@@ -36,6 +37,19 @@ enum NWCLiveActivityShared {
|
||||
d?.set(Int(revision), forKey: keyRevision)
|
||||
}
|
||||
|
||||
/// Track the user prefers next start to play. Distinct from the display state
|
||||
/// (`keyTrackIndex`) so picking in settings during an active session doesn't
|
||||
/// race the refresh timer into showing a track the audio isn't actually playing.
|
||||
static func readPreferredTrackIndex() -> Int? {
|
||||
guard let d = defaults, d.object(forKey: keyPreferredTrackIndex) != nil
|
||||
else { return nil }
|
||||
return d.integer(forKey: keyPreferredTrackIndex)
|
||||
}
|
||||
|
||||
static func writePreferredTrackIndex(_ index: Int) {
|
||||
defaults?.set(index, forKey: keyPreferredTrackIndex)
|
||||
}
|
||||
|
||||
static func setPreferredActivityId(_ id: String?) {
|
||||
let d = defaults
|
||||
if let id {
|
||||
@@ -125,6 +139,7 @@ enum NWCLiveActivityShared {
|
||||
static func applyNextTrack() async {
|
||||
var (index, muted, _) = readDisplay()
|
||||
index = (index + 1) % max(tracks.count, 1)
|
||||
writePreferredTrackIndex(index)
|
||||
await pushLiveActivity(trackIndex: index, isMuted: muted)
|
||||
}
|
||||
|
||||
@@ -133,6 +148,7 @@ enum NWCLiveActivityShared {
|
||||
var (index, muted, _) = readDisplay()
|
||||
let count = max(tracks.count, 1)
|
||||
index = (index - 1 + count) % count
|
||||
writePreferredTrackIndex(index)
|
||||
await pushLiveActivity(trackIndex: index, isMuted: muted)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,10 +118,11 @@ RCT_EXPORT_MODULE();
|
||||
_disconnectCount = 0;
|
||||
_trackNames = [NWCAmbientTracks trackNames];
|
||||
|
||||
// Restore last-selected track from the app group (written by
|
||||
// switchToTrackAtIndex: via NWCLiveActivityBridge). UserDefaults
|
||||
// returns 0 if the key was never written, which matches the default.
|
||||
NSInteger persisted = [NWCLiveActivityBridge appGroupTrackIndex];
|
||||
// Restore the user's preferred track. Preference key wins; fall back
|
||||
// to the display-state index (which reflects in-session changes made
|
||||
// from the Dynamic Island) if the user never picked in settings.
|
||||
NSInteger fallback = [NWCLiveActivityBridge appGroupTrackIndex];
|
||||
NSInteger persisted = [NWCLiveActivityBridge preferredTrackIndexWithFallback:fallback];
|
||||
NSInteger count = (NSInteger)_trackNames.count;
|
||||
_currentTrackIndex = (count > 0 && persisted >= 0 && persisted < count)
|
||||
? persisted
|
||||
@@ -258,8 +259,10 @@ RCT_EXPORT_METHOD(setTrack:(NSInteger)index
|
||||
|
||||
// Updates the preferred track without restarting playback. Used when the
|
||||
// settings UI changes selection during an active NWC session — the user's
|
||||
// pick should persist (app group, in-memory) so the next start uses it,
|
||||
// but the currently playing ambient track must not be interrupted.
|
||||
// pick should persist so the next start uses it, but the currently playing
|
||||
// ambient track and the Dynamic Island must not be interrupted. Writes only
|
||||
// the preference key in the app group; the display-state index (which the
|
||||
// Live Activity refresh timer reads every 15s) is intentionally left alone.
|
||||
RCT_EXPORT_METHOD(setTrackPreference:(NSInteger)index
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject) {
|
||||
@@ -268,9 +271,7 @@ RCT_EXPORT_METHOD(setTrackPreference:(NSInteger)index
|
||||
return;
|
||||
}
|
||||
|
||||
self.currentTrackIndex = index;
|
||||
[NWCLiveActivityBridge syncAppGroupFromAudioWithTrackIndex:index
|
||||
isMuted:self.isMuted];
|
||||
[NWCLiveActivityBridge setPreferredTrackIndex:index];
|
||||
|
||||
resolve([self currentStatusDict]);
|
||||
}
|
||||
@@ -345,6 +346,7 @@ RCT_EXPORT_METHOD(disarmNWCAudio:(RCTPromiseResolveBlock)resolve
|
||||
|
||||
[NWCLiveActivityBridge syncAppGroupFromAudioWithTrackIndex:index
|
||||
isMuted:self.isMuted];
|
||||
[NWCLiveActivityBridge setPreferredTrackIndex:index];
|
||||
|
||||
if (@available(iOS 16.1, *)) {
|
||||
NSString *trackName = self.trackNames[index];
|
||||
|
||||
@@ -19,4 +19,18 @@ import Foundation
|
||||
revision: revision
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the persisted preferred track index, or `fallback` if unset.
|
||||
/// Distinct from the display-state track index so the Live Activity
|
||||
/// refresh timer doesn't surface the preference while a different track
|
||||
/// is actually playing.
|
||||
@objc(preferredTrackIndexWithFallback:)
|
||||
static func preferredTrackIndex(fallback: Int) -> Int {
|
||||
NWCLiveActivityShared.readPreferredTrackIndex() ?? fallback
|
||||
}
|
||||
|
||||
@objc(setPreferredTrackIndex:)
|
||||
static func setPreferredTrackIndex(_ index: Int) {
|
||||
NWCLiveActivityShared.writePreferredTrackIndex(index)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user