Fix 5 TestFlight crash types from builds 250-254

- Fix BGTaskScheduler assertion crash on Mac Catalyst by guarding all
  iOS background task APIs with isMacCatalystApp check
- Fix iPad popover crash in UIPopoverPresentationController by adding
  .presentationCompactAdaptation(.sheet) to all 27 confirmationDialogs
- Fix SwiftData assertion crash when accessing deleted Bookmark model
  properties during SwiftUI hit testing in BookmarkRowView
- Fix UICollectionView invalid item count crash on queue swipe-to-delete
  by using ID-based removal with withAnimation instead of stale index
- Fix Range crash in storyboard download when storyboardCount is zero
This commit is contained in:
Arkadiusz Fal
2026-03-27 17:52:08 +01:00
parent 2db78c429e
commit 3c04b8540f
22 changed files with 59 additions and 3 deletions

View File

@@ -43,6 +43,7 @@ final class BackgroundRefreshManager {
func registerBackgroundTasks() {
#if os(iOS)
guard !ProcessInfo.processInfo.isMacCatalystApp else { return }
registerIOSBackgroundTask()
#elseif os(macOS)
registerMacOSBackgroundActivity()
@@ -64,6 +65,7 @@ final class BackgroundRefreshManager {
}
func scheduleIOSBackgroundRefresh() {
guard !ProcessInfo.processInfo.isMacCatalystApp else { return }
let request = BGAppRefreshTaskRequest(identifier: Self.backgroundTaskIdentifier)
// Request to run in ~15 minutes (system decides actual timing)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
@@ -77,6 +79,7 @@ final class BackgroundRefreshManager {
}
func cancelIOSBackgroundRefresh() {
guard !ProcessInfo.processInfo.isMacCatalystApp else { return }
BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: Self.backgroundTaskIdentifier)
LoggingService.shared.debug("Cancelled iOS background refresh", category: .notifications)
}
@@ -156,6 +159,7 @@ final class BackgroundRefreshManager {
func handleNotificationsEnabledChanged(_ enabled: Bool) {
#if os(iOS)
guard !ProcessInfo.processInfo.isMacCatalystApp else { return }
if enabled {
scheduleIOSBackgroundRefresh()
} else {

View File

@@ -74,7 +74,7 @@ extension DownloadManager {
}
// If VTT parsing failed, fall back to direct URLs (may not work if blocked)
if imageURLs.isEmpty {
if imageURLs.isEmpty, storyboard.storyboardCount > 0 {
for sheetIndex in 0..<storyboard.storyboardCount {
if let url = storyboard.directSheetURL(for: sheetIndex) {
imageURLs.append(url)

View File

@@ -539,6 +539,11 @@ final class PlayerState {
queue.remove(at: index)
}
/// Removes a video from the queue by its ID.
func removeFromQueue(id: QueuedVideo.ID) {
queue.removeAll { $0.id == id }
}
/// Updates a queue item with preloaded video details and streams.
/// Preserves the item's ID for stable SwiftUI identity.
func updateQueueItemWithPreload(at index: Int, video: Video, stream: Stream?, audioStream: Stream?) {

View File

@@ -122,6 +122,11 @@ final class QueueManager {
playerState?.removeFromQueue(at: index)
}
/// Removes a video from the queue by its ID.
func removeFromQueue(id: QueuedVideo.ID) {
playerState?.removeFromQueue(id: id)
}
/// Moves a queue item from one position to another.
func moveQueueItem(from sourceIndex: Int, to destinationIndex: Int) {
playerState?.moveQueueItem(from: sourceIndex, to: destinationIndex)