Quellcode durchsuchen

Auto-restart Live Activity when iOS sends .ended (#659)

When iOS reaches the Live Activity lifetime cap before renewal fires it
delivers .ended, not .dismissed. The state observer only ran restart
logic on .dismissed, so handleForeground saw renewalFailed=false and
renewBy still in the future and returned "no action needed", leaving
the LA dark until manual force-restart.

Mark laRenewalFailed=true on the .ended path (gated on wasCurrent and
!endingForRestart) so the next foreground entry triggers
performForegroundRestart, which sweeps the corpse activity and pushes a
fresh one.
Jonas Björkert vor 2 Monaten
Ursprung
Commit
91f95cf87b
1 geänderte Dateien mit 14 neuen und 0 gelöschten Zeilen
  1. 14 0
      LoopFollow/LiveActivity/LiveActivityManager.swift

+ 14 - 0
LoopFollow/LiveActivity/LiveActivityManager.swift

@@ -1394,6 +1394,20 @@ final class LiveActivityManager {
                         //   • the user disables LA or calls forceRestart
                         LogManager.shared.log(category: .general, message: "[LA] activity cleared id=\(activity.id) state=\(state)", isDebug: true)
                     }
+                    if state == .ended, wasCurrentActivity, !endingForRestart {
+                        // iOS terminated the activity itself — typically the ~8h lifetime
+                        // cap reached before renewal fired. The .dismissed path below
+                        // already handles iOS-initiated dismissals via renewalFailed /
+                        // pastDeadline, but .ended bypasses that branch entirely. Without
+                        // a signal here, handleForeground() sees `renewalFailed=false` and
+                        // `renewBy` still in the future, returns "no action needed", and
+                        // startIfNeeded keeps re-binding the corpse — the LA stays dark
+                        // until the user manually force-restarts. Mark renewalFailed so
+                        // the next foreground entry runs performForegroundRestart, which
+                        // sweeps any leftover ended activity and pushes a fresh one.
+                        Storage.shared.laRenewalFailed.value = true
+                        LogManager.shared.log(category: .general, message: "[LA] ended by iOS (not our restart) — marked renewalFailed=true, auto-restart on next foreground")
+                    }
                     if state == .dismissed {
                         // Three possible sources of .dismissed — only the third blocks restart:
                         //