mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-04 00:47:00 +01:00
feat(ios): port the Android client to SwiftUI
The iOS client is now a screen-for-screen port of the Android app over the same pstr-android UniFFI surface, with no Rust changes: Library, title page, History, Shares (public links and Drive folders), Downloads and Settings, with the same strings, undo snackbars and two-pane layout on wide screens. - Theme from the engine's palette (Material role names, Inter, the same type ramp and corners), repainted live from the appearance settings. - Account sign-in with two-factor code, mailbox password and the Proton CAPTCHA in a non-persistent WKWebView, the Drive folder browser, and watch-history sync every five minutes, after sign-in, on player close and when the app leaves the screen. - Player over libmpv: resume, progress saved every 5 s, autoplay with the up-next card, skip and auto-skip from the chapter plan, track, speed, volume and episode pickers, landscape lock, mini transport, and lock-screen controls with interruption and route-change handling. - Offline downloads with the Android record format, free-space floor, retries, transfer rate and the Wi-Fi-only policy; interrupted transfers resume at next launch. - Config, data and download state are excluded from backup, as Android's allowBackup=false: a restore would bring shares back without their Keychain secrets and give two devices one sync identity. Picture-in-picture, the share sheet and background downloads are not possible the same way on iOS; docs/IOS.md lists why and what replaces them. Adds XCTest ports of the Android unit tests, a `test` command to scripts/build-ios.sh, the app icon and its render script, and an iOS workflow on macos-15 that runs the tests and builds the unsigned .ipa.
This commit is contained in:
1 parent
da16ab0575
commit
ed05a1e723
38 files changed
+7546
-208
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import Foundation
|
||||
|
||||
/// The settings that are this front end's alone.
|
||||
///
|
||||
/// Playback preferences — volume, languages, autoplay, auto-skip — deliberately
|
||||
/// do *not* live here: they are `pstr_core::prefs`, reached over the bridge, so
|
||||
/// there is one definition of them rather than one per front end. Keys and
|
||||
/// defaults are Android's `SettingsStore`.
|
||||
struct SettingsStore {
|
||||
private let defaults = UserDefaults.standard
|
||||
|
||||
var wifiOnly: Bool {
|
||||
get { bool(Key.wifiOnly, default: true) }
|
||||
nonmutating set { defaults.set(newValue, forKey: Key.wifiOnly) }
|
||||
}
|
||||
|
||||
var backgroundAudio: Bool {
|
||||
get { bool(Key.backgroundAudio, default: true) }
|
||||
nonmutating set { defaults.set(newValue, forKey: Key.backgroundAudio) }
|
||||
}
|
||||
|
||||
/// Whether mpv may decode in hardware. Off is the way out for a file
|
||||
/// VideoToolbox shows green or torn frames for; it costs battery, so it is
|
||||
/// on unless the viewer turns it off. Read at each load, so a change applies
|
||||
/// from the next file.
|
||||
var hardwareDecoding: Bool {
|
||||
get { bool(Key.hardwareDecoding, default: true) }
|
||||
nonmutating set { defaults.set(newValue, forKey: Key.hardwareDecoding) }
|
||||
}
|
||||
|
||||
/// The streaming cache's budget, in GiB. See `cacheBudgetChoices`.
|
||||
var cacheBudgetGib: Int {
|
||||
get { defaults.object(forKey: Key.cacheBudgetGib) as? Int ?? Self.defaultCacheBudgetGib }
|
||||
nonmutating set { defaults.set(newValue, forKey: Key.cacheBudgetGib) }
|
||||
}
|
||||
|
||||
/// The desktop's range, in the steps a phone's storage is bought in.
|
||||
static let cacheBudgetChoices = [1, 2, 4, 8, 16]
|
||||
|
||||
/// `DiskCacheConfig::DEFAULT_BUDGET_BYTES`, so an unset choice changes nothing.
|
||||
static let defaultCacheBudgetGib = 4
|
||||
|
||||
static func gibToBytes(_ gib: Int) -> UInt64 { UInt64(gib) * 1024 * 1024 * 1024 }
|
||||
|
||||
private func bool(_ key: String, default value: Bool) -> Bool {
|
||||
defaults.object(forKey: key) as? Bool ?? value
|
||||
}
|
||||
|
||||
private enum Key {
|
||||
static let wifiOnly = "wifi_only"
|
||||
static let backgroundAudio = "background_audio"
|
||||
static let hardwareDecoding = "hardware_decoding"
|
||||
static let cacheBudgetGib = "cache_budget_gib"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user