mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-03 16:41:26 +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
+34
-10
@@ -11,14 +11,16 @@ repo_root="$(cd -- "$script_dir/.." && pwd)"
|
||||
ios_dir="$repo_root/ios"
|
||||
generated="$ios_dir/build/generated"
|
||||
target=aarch64-apple-ios
|
||||
simulator=aarch64-apple-ios-sim
|
||||
|
||||
usage() {
|
||||
echo "usage: $0 {rust|bindings|ipa|all}"
|
||||
echo "usage: $0 {rust|bindings|ipa|all|test}"
|
||||
echo
|
||||
echo " rust static libpstr_android.a for $target"
|
||||
echo " bindings Swift bindings into ios/build/generated"
|
||||
echo " ipa xcodegen + xcodebuild, then dist/ProtonStream-<version>.ipa"
|
||||
echo " ipa xcodegen + xcodebuild, then dist/proton-stream-<version>-ios.ipa"
|
||||
echo " all all three, in that order"
|
||||
echo " test the unit tests on a simulator ($simulator)"
|
||||
}
|
||||
|
||||
die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
@@ -36,11 +38,19 @@ version="$(awk '/^\[workspace.package\]/{found=1; next} found && /^\[/{exit} fou
|
||||
[[ -n "$version" ]] || die "no [workspace.package] version in Cargo.toml"
|
||||
|
||||
build_rust() {
|
||||
log "cargo rustc -p pstr-android --target $target (staticlib)"
|
||||
local triple="${1:-$target}"
|
||||
log "cargo rustc -p pstr-android --target $triple (staticlib)"
|
||||
# The crate stays `cdylib, rlib` for Android; the archive iOS links is asked
|
||||
# for here instead of being built on every other platform too.
|
||||
( cd "$repo_root" && IPHONEOS_DEPLOYMENT_TARGET=17.0 cargo rustc -p pstr-android --lib \
|
||||
--release --locked --target "$target" --crate-type staticlib )
|
||||
--release --locked --target "$triple" --crate-type staticlib )
|
||||
}
|
||||
|
||||
generate_project() {
|
||||
command -v xcodegen >/dev/null || die "xcodegen is required (brew install xcodegen)"
|
||||
[[ -f "$generated/PstrBridge.swift" ]] || die "run '$0 bindings' first"
|
||||
log "xcodegen ($version)"
|
||||
( cd "$ios_dir" && PSTR_VERSION="$version" PSTR_BUILD="${PSTR_BUILD:-1}" xcodegen generate --quiet )
|
||||
}
|
||||
|
||||
build_bindings() {
|
||||
@@ -56,12 +66,8 @@ build_bindings() {
|
||||
}
|
||||
|
||||
build_ipa() {
|
||||
command -v xcodegen >/dev/null || die "xcodegen is required (brew install xcodegen)"
|
||||
[[ -f "$repo_root/target/$target/release/libpstr_android.a" ]] || die "run '$0 rust' first"
|
||||
[[ -f "$generated/PstrBridge.swift" ]] || die "run '$0 bindings' first"
|
||||
|
||||
log "xcodegen ($version)"
|
||||
( cd "$ios_dir" && PSTR_VERSION="$version" PSTR_BUILD="${PSTR_BUILD:-1}" xcodegen generate --quiet )
|
||||
generate_project
|
||||
|
||||
log "xcodebuild (unsigned)"
|
||||
xcodebuild -project "$ios_dir/ProtonStream.xcodeproj" -scheme ProtonStream \
|
||||
@@ -76,16 +82,34 @@ build_ipa() {
|
||||
rm -rf "$stage"
|
||||
mkdir -p "$stage/Payload" "$repo_root/dist"
|
||||
cp -R "$app" "$stage/Payload/"
|
||||
local ipa="$repo_root/dist/ProtonStream-$version.ipa"
|
||||
local ipa="$repo_root/dist/proton-stream-$version-ios.ipa"
|
||||
rm -f "$ipa"
|
||||
( cd "$stage" && zip -qry "$ipa" Payload )
|
||||
log "wrote $ipa"
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
build_rust "$simulator"
|
||||
[[ -f "$generated/PstrBridge.swift" ]] || build_bindings
|
||||
generate_project
|
||||
# Whichever iPhone this Xcode ships a simulator for: the names change with
|
||||
# every release, and the tests do not care which one.
|
||||
local device
|
||||
device="$(xcrun simctl list devices available | grep -m1 -oE 'iPhone [^(]+' | sed 's/ *$//')"
|
||||
[[ -n "$device" ]] || die "no iPhone simulator is installed"
|
||||
log "xcodebuild test ($device)"
|
||||
xcodebuild -project "$ios_dir/ProtonStream.xcodeproj" -scheme ProtonStream \
|
||||
-destination "platform=iOS Simulator,name=$device" \
|
||||
-derivedDataPath "$ios_dir/build/DerivedData" \
|
||||
CODE_SIGNING_ALLOWED=NO \
|
||||
test
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
rust) build_rust ;;
|
||||
bindings) build_bindings ;;
|
||||
ipa) build_ipa ;;
|
||||
all) build_rust; build_bindings; build_ipa ;;
|
||||
test) run_tests ;;
|
||||
*) usage >&2; exit 2 ;;
|
||||
esac
|
||||
Reference in new issue
Block a user