Skip to content

CI + shared scheme + docs, and implement background location & emergency-contact escalation#2

Merged
billdmar merged 2 commits into
mainfrom
chore/ci-docs-and-features
Jun 10, 2026
Merged

CI + shared scheme + docs, and implement background location & emergency-contact escalation#2
billdmar merged 2 commits into
mainfrom
chore/ci-docs-and-features

Conversation

@billdmar

Copy link
Copy Markdown
Owner

Summary

Brings SafeWalk to parity with the flagship repos (CI, shared scheme, architecture doc, screenshot wiring) and implements the two features the README previously only described — so the README is now accurate.

Features implemented (make README true)

  • Background location. LocationManager now requests requestWhenInUseAuthorization() then escalates to requestAlwaysAuthorization() via the authorization callback, and sets allowsBackgroundLocationUpdates = true / pausesLocationUpdatesAutomatically = false — guarded so it is only enabled once Always authorization is granted (otherwise it crashes at runtime). Added the required declarations through INFOPLIST_KEY_* build settings (the project uses GENERATE_INFOPLIST_FILE = YES, so there is no checked-in Info.plist): NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, and UIBackgroundModes = location, in both Debug and Release of the app target.
  • Emergency-contact escalation. Stored EmergencyContacts were saved to UserDefaults but never used. Now, on escalation, if a contact exists the notification names them and adds a "Text " action that opens an sms: deep link prefilled with a help message and a Maps link to the last known location, alongside the existing "Call UT Police" tel: action. No contact → UTPD-only fallback (prior behavior). NotificationDelegate is now a shared singleton so the action handler is retained and can place the call/SMS.

Infra / docs

  • Shared scheme Party Watcher.xcscheme (none existed; xcodebuild failed on clean checkout). Build action → app target, test action → Party WatcherTests.
  • CI (.github/workflows/ci.yml): builds + runs Party WatcherTests on the iOS Simulator (macos-15, iPhone 16 Pro).
  • docs/ARCHITECTURE.md (component diagram + runtime flow + verified-vs-device notes) and docs/SCREENSHOTS.md (placeholder slots + capture guide).
  • README: CI badge, reconciled feature wording, ARCHITECTURE link, Screenshots section.

Incidental fix

Secrets.example.swift lives in the synchronized source group, so Xcode compiles it; its enum Secrets collided with the real Secrets.swift (invalid redeclaration of 'Secrets') — this broke the build for anyone following the README's copy step. Its body is now commented out.

Honesty / verification notes

  • CI uses a stub Secrets.swift with an empty key (real key stays gitignored). No Gemini network call is exercised in a build/test run.
  • Verified locally: xcodebuild build and xcodebuild test both succeed on the iOS Simulator (iPhone 17, Xcode 26.5) using the new shared scheme — ** TEST SUCCEEDED **. The test target only contains the Xcode-generated placeholder, so 0 tests execute; the step proves the project compiles and the scheme's test action resolves.
  • Needs user verification on device/simulator: runtime background-GPS delivery + lock-screen wakeups, the "Always" authorization prompt flow, notification delivery, and the tel:/sms: deep links. CI does not exercise these.
  • Screenshots are placeholders — see docs/SCREENSHOTS.md.

Do not merge until you've reviewed.

William Mar added 2 commits June 10, 2026 14:29
- LocationManager now requests Always authorization (escalating from
  when-in-use) and enables allowsBackgroundLocationUpdates once granted,
  guarded so it is only set with Always auth. Adds the location usage
  descriptions and UIBackgroundModes=location via INFOPLIST_KEY_* build
  settings (the project uses GENERATE_INFOPLIST_FILE).
- Escalation now uses saved emergency contacts: when a contact exists the
  notification names them and offers a 'Text <name>' action opening an sms:
  deep link prefilled with a help message + a Maps link to the last known
  location, alongside the existing 'Call UT Police' tel: action. Falls back
  to UTPD-only when no contact is saved. NotificationDelegate is now a shared
  singleton so the action handler is retained.
- Fix pre-existing redeclaration: Secrets.example.swift is compiled by the
  synchronized source group, so its 'enum Secrets' collided with the real
  Secrets.swift. Commented out the template body.
- Add GitHub Actions CI (.github/workflows/ci.yml) that builds and runs the
  Party WatcherTests target on the iOS Simulator (macos-15, iPhone 16 Pro).
  Writes a stub Secrets.swift (empty key) before building since the real one
  is gitignored; no network calls are exercised.
- Add shared scheme 'Party Watcher.xcscheme' (none existed, so xcodebuild
  failed on a clean checkout). Build action -> app target; test action ->
  Party WatcherTests.
- Add docs/ARCHITECTURE.md (component diagram + runtime flow + verified-vs-
  device notes) and docs/SCREENSHOTS.md (placeholder slots + capture guide).
- README: add CI badge, reconcile feature claims with the now-real background
  tracking + contact escalation, link ARCHITECTURE.md, add Screenshots section.
@billdmar
billdmar merged commit 6598c2b into main Jun 10, 2026
1 check passed
@billdmar
billdmar deleted the chore/ci-docs-and-features branch June 10, 2026 21:48
billdmar added a commit that referenced this pull request Jun 10, 2026
)

The app aborted on launch (SIGABRT) once 'Always' location authorization
was granted. Root cause: LocationManager set
`allowsBackgroundLocationUpdates = true`, but the built Info.plist was
missing `UIBackgroundModes = location`. CoreLocation throws an exception
when that setter runs without the background mode declared.

Why the plist was missing it: the project uses GENERATE_INFOPLIST_FILE=YES
and declared `INFOPLIST_KEY_UIBackgroundModes = location`, but
UIBackgroundModes is NOT one of the INFOPLIST_KEY_* names Xcode synthesizes
into the generated plist, so it was silently dropped (the usage strings,
which ARE synthesized keys, made it through). This is pre-existing code
from the background-location feature (#2) that had only been
compile-verified, never run.

Fix (two layers):
- Add BuildConfig/Info.plist declaring UIBackgroundModes=[location] and
  point INFOPLIST_FILE at it in both Debug/Release. Kept outside the
  'Party Watcher/' synchronized folder so it isn't also copied as a
  bundle resource (which would cause 'Multiple commands produce Info.plist').
  GENERATE_INFOPLIST_FILE stays YES and merges this on top.
- Harden enableBackgroundUpdatesIfPermitted(): only enable background
  updates if Bundle.main's UIBackgroundModes actually contains 'location',
  so any future plist regression degrades to foreground-only instead of
  crashing.

Verified: built plist now contains UIBackgroundModes=[location] (usage
strings retained); app launches and stays running in the Simulator with
always-location granted (the exact condition that crashed before); no new
crash reports.

Co-authored-by: William Mar <billdmar@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant