Files
share/apps/ios/README.md
T
TZGyn bf5d19900c Add a relay ping and backend status to the iOS app
The relay now answers a stateless ping with pong. The Relay card auto-checks on appear and address changes, showing latency or the connection error; this verifies the endpoint speaks the share protocol, not just that a TCP port is open.
2026-10-27 21:59:27 +08:00

112 lines
4.0 KiB
Markdown

# Share for iOS
A native SwiftUI client for the `share` swarm. It uses the same Go engine as
the CLI, compiled for iOS with gomobile, so the phone is a real peer: it can
seed files, receive files, verify chunks, and fall back to the relay pipe when
a direct connection is blocked.
```
apps/ios/
project.yml XcodeGen project (source of truth)
Share/ SwiftUI sources, assets, Info.plist
GoBridge/ nested Go module exposing swarm to Swift
build-go.sh builds Share.xcframework with gomobile
build.sh simulator or signed device build
run-device.sh install + launch on a paired iPhone
Branding/make-icon.swift regenerates the app icon
```
## Build
Requirements: Xcode, `xcodegen`, Go 1.26+ for the gomobile bridge, and
network access the first time `gomobile` is installed. (The CLI itself still
builds with the repo's Go 1.25 requirement.)
```sh
cd apps/ios
# Simulator (Apple Silicon)
./build.sh simulator
# Signed device build (team RX6767S6BW)
./build.sh device
# Install on the paired iPhone over Wi-Fi
./run-device.sh FeelsCringeMan
```
`build.sh` regenerates `Share.xcframework` before running `xcodegen generate`;
the XCFramework and the generated `.xcodeproj` are build artifacts and are
ignored by git.
## Smoke tests
The app has two launch-argument driven tests that write
`Documents/share-selftest.txt`; console output is unreliable on a simulator
and unavailable on a device.
Receive (the app is the peer that downloads):
```sh
# 1. Start a relay on the Mac (all interfaces, so a phone can reach it).
go run . relay --host 0.0.0.0 --port 9009
# 2. Launch the test. Use 127.0.0.1 for the simulator, or the Mac's LAN
# address for a physical phone.
xcrun simctl launch <udid> dev.tzgyn.share \
-shareSelfTest -shareSelfTestRelay 127.0.0.1:9009 \
-shareSelfTestCode 1234-selftest-share-apple
# 3. Seed a file from the CLI.
go run . send --relay 127.0.0.1:9009 --code 1234-selftest-share-apple /tmp/test.bin
# 4. Read the report from the simulator container.
DATA=$(xcrun simctl get_app_container <udid> dev.tzgyn.share data)
cat "$DATA/Documents/share-selftest.txt"
```
Send (the app seeds a generated 2 MiB file):
```sh
xcrun simctl launch <udid> dev.tzgyn.share \
-shareSelfTestSend -shareSelfTestRelay 127.0.0.1:9009 \
-shareSelfTestCode 1234-selftest-send-apple
go run . --relay 127.0.0.1:9009 --out /tmp/received --one-time \
1234-selftest-send-apple
```
On a physical phone, read the report with:
```sh
xcrun devicectl device copy from --device <device> \
--domain-type appDataContainer --domain-identifier dev.tzgyn.share \
--source Documents/share-selftest.txt --destination /tmp/share-selftest.txt
```
## How it works
- `GoBridge/share.go` keeps one `swarm.Client` per room and exposes
`Start`, `StatusJSON`, and `Stop`. Progress crosses the gomobile boundary as
JSON so Swift only decodes plain value types.
- The app copies picked files into `Documents/Seeds/` before starting a room:
the document picker's security-scoped URL is only valid while the picker
callback is on the stack, not for the lifetime of a transfer.
- Received files are written to `Documents/Received/`. `UIFileSharingEnabled`
makes that folder visible in Files → On My iPhone → Share.
- The default relay is the project's own `share.tzgyn.dev:9009`; the CLI and
the iOS app both use it. For local transfers, run `share relay` on a Mac and
enter its LAN address (`192.168.x.x:9009`) under Relay in the app.
- The Relay card probes the backend with a stateless protocol ping/pong and
shows the latency or the connection error; it re-checks when the address
changes and can be refreshed manually.
## Notes
- The app runs one room at a time; starting another requires stopping the
current one.
- Receiving uses `oneTime: true`, so the room stops after every file known at
that moment is complete. Sending keeps seeding until Stop.
- iOS can suspend the app when it leaves the foreground; if the relay
connection dies, the room card shows the error and a new room can be started.