Files
ipx/ios/Sources/App.swift
Ray Slakinski ecc248307e iOS: episodes kept on the phone play with no connection (#425)
A WKWebView runs no service worker, so the page's Keep button (#412)
was not shown in the app and everything played from the server. Now the
page asks the app to keep the file (keep, unkeep, clearKept), and the
app answers with what it holds (kept, keepFailed) whether or not
anything plays. The app fetches with a background URLSession, so a
download goes on with the app closed, into Application Support (not
backed up; the files can be fetched again), and Playback plays from the
file when there is one. The DeadAir copy is kept under its own path, as
the browser keeps it. Places and finishes reached offline wait in an
outbox, newest per address, and go when the network is back.

Checked in the simulator against a local server: kept /media/42 and
/media/42/deadair, then with the server refusing /media, a fresh launch
played each from the phone and asked the server for nothing. The page
itself still needs a connection to open (#435).

Deploy the app (build 6) before the page: a new page in an old app
shows a Keep button nothing answers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 14:40:01 -05:00

51 lines
1.9 KiB
Swift

import UIKit
@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
Badge.registerBackgroundRefresh()
Offline.shared.resume()
Outbox.watch()
return true
}
/// A download kept going while the app was closed has finished (#425): the system launched us
/// to hand it over, and waits on this handler.
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void) {
Offline.shared.backgroundCompletion = completionHandler
Offline.shared.resume()
}
}
/// The one window. iOS will not run an app that has not adopted scenes, and a CarPlay app would
/// be a second scene beside this one.
final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options: UIScene.ConnectionOptions) {
guard let scene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: scene)
window.rootViewController = WebViewController()
window.makeKeyAndVisible()
self.window = window
}
/// iOS wants the request made as the app leaves, with the user's last look at the list; the
/// one made on coming forward stays for a run that was cut short.
func sceneDidEnterBackground(_ scene: UIScene) {
Badge.scheduleBackgroundRefresh()
}
func sceneDidBecomeActive(_ scene: UIScene) {
Badge.requestPermission()
Badge.scheduleBackgroundRefresh()
Task {
await Outbox.flush()
await Badge.refresh()
}
}
}