Package-level declarations
Types
A single analytics event. Param keys/values self-clamp to Firebase limits (≤ 40-char name/key, ≤ 100-char value, ≤ 25 params) so impls never reject an event.
Analytics sink. gms: FirebaseAnalytics (app-side); noGms + iOS + desktop: LoggingAnalyticsHelper.
Android FilePicker. Calf's rememberFilePickerLauncher/rememberFileSaverLauncher are @Composable (they wrap rememberLauncherForActivityResult), so — mirroring AndroidPermissionsProvider.requestBridge — the host activity's Compose layer registers pickBridge/saveBridge to the real launchers; with no bridge registered this degrades to reporting no file rather than crashing. File bytes are read via Calf's KmpFile I/O, which is plain suspend code, not Compose-bound.
Android ForwardGeocoder via Compass's mobile geocoder, itself android.location.Geocoder underneath — the same OS geocoder AndroidLocationNameResolver wraps for the reverse direction.
Android LocationNameResolver backed by the platform Geocoder (reverse geocoding).
Android LocationTracker backed by the fused location provider.
Android NotificationScheduler backed by NotificationManagerCompat.
Android PermissionsProvider. isGranted is a plain ContextCompat.checkSelfPermission sweep. request needs an Activity to show the system dialog, so the foreground activity registers a requestBridge (ActivityResult-based); with no bridge registered (headless/no UI host) it degrades to reporting the current grant state instead of crashing.
Android PlaceAutocomplete via Compass's mobile autocomplete — under the hood it matches partial input against the same android.location.Geocoder AndroidForwardGeocoder uses, not a separate typeahead service, so it needs no API key. Same context-free construction as AndroidForwardGeocoder.
Runtime permissions the app requests.
In-app review prompt. Android: Play review (gms) / store intent (noGms). iOS: SKStoreReviewController.
Creates an Activity-scoped AppReviewManager.
In-app update. Android: Play-Core AppUpdateManager (gms) / no-op (noGms). iOS: iTunes Lookup API version compare. Typically Activity/UIViewController-scoped on Android via AppUpdateManagerFactory — the gms-specific impl is app-side, not part of this module (see AppUpdateManagerFactory doc).
Creates an Activity-scoped AppUpdateManager.
Document scanning → captured page images as bytes. Android: ML Kit doc scanner; iOS: VisionKit.
File selection for import/export flows (e.g. picking a receipt, saving an export). Android/iOS: Calf's file-picker/file-saver, bridged from the host's Compose layer — Calf's launchers are @Composable (they wrap rememberLauncherForActivityResult/UIDocumentPickerViewController), so like PermissionsProvider.request's ActivityResult dialog, the actual pick/save UI can't be driven from this headless module and is bridged in by whoever hosts the Compose UI.
Resolves free-text address input to coordinates (forward geocoding — the counterpart to LocationNameResolver's reverse direction). Android/iOS: Compass, itself a thin wrapper over the same OS geocoders LocationNameResolver already wraps (android.location.Geocoder / CLGeocoder).
A plain lat/lng pair — the forward-geocoding counterpart of PlaceName's coordinate string.
A place suggestion: a human-readable label plus its resolvable coordinates.
Process-lifetime in-memory token store (default / test double).
Process-lifetime in-memory store (default / test double; resets on cold start).
iOS in-app review (parity with the Android Play-review path). Uses the iOS 14+ window-scene variant of SKStoreReviewController; if no foreground-active window scene is found it simply does nothing (matches the "host may decline" semantics of the Android impl). Never crashes.
iOS in-app update via the public iTunes Lookup API (no backend, parity with the Android Play-Core path). Compares the App Store version to the running CFBundleShortVersionString. startUpdate opens the App Store page. Any network/parse failure → UpdateAvailability.NotAvailable, never a crash.
iOS document scanning.
iOS FilePicker. Calf's file-picker/file-saver launchers are @Composable — like IosDocumentScanner's VisionKit flow, they must be presented from live Compose UI, which this headless module has no hook into. Mirroring AndroidFilePicker, the host's Compose layer wires pickBridge/saveBridge to the real launchers; with no bridge registered this degrades to reporting no file, the same truthful-no-op fallback IosDocumentScanner uses.
iOS ForwardGeocoder via Compass's mobile geocoder, itself CLGeocoder underneath — the same OS geocoder IosLocationNameResolver wraps for the reverse direction. Needs no context, same as IosLocationNameResolver.
iOS LocationNameResolver via CoreLocation's CLGeocoder (the CLGeocoder counterpart to Android's Geocoder). reverseGeocodeLocation is asynchronous and callback-based; it is bridged to a suspend point with suspendCancellableCoroutine.
iOS location via CoreLocation, counterpart to Android's FusedLocationProvider.
iOS local notifications via UNUserNotificationCenter, the counterpart to Android's NotificationManager + channels. ensurePermission bridges requestAuthorization's completion handler into a suspend call; notify posts an immediate (trigger=null) request keyed by the int id.
iOS runtime permissions, queries/requests the per-capability authorization APIs (camera = AVCaptureDevice, location = CLLocationManager, notifications = UNUserNotificationCenter). Storage has no broad user-facing prompt on iOS, so it is always granted. Location grants surface asynchronously through the CLLocationManager delegate, so request for it is fire-and-forget and the result is read back later via isGranted.
iOS PlaceAutocomplete via Compass's mobile autocomplete — under the hood it matches partial input against the same CLGeocoder IosForwardGeocoder uses, not a separate typeahead service, so it needs no API key. Same context-free construction as IosForwardGeocoder.
Offline PushMessaging backed by a PushTokenStore — the commonMain default (and the noGms/ iOS-without-key fallback) for apps with no push backend of their own to register against.
Resolves a coordinate to a short, human-readable place name (reverse geocoding).
Continuous + one-shot location access. Android: FusedLocation; iOS: CoreLocation.
Analytics sink that logs (self-clamped) events via Napier. This is the noGms + iOS + desktop analytics impl (no real backend); a gms-style app binds a Firebase-backed helper of its own instead.
Local notifications. Android: NotificationManager + channels; iOS: UNUserNotificationCenter.
Snapshot of a permission flow.
Sequential permission-request state machine over a PermissionsProvider. Walks a fixed sequence one permission at a time: each step is skipped if already granted, otherwise requestCurrent asks for it, records the PermissionResult, and advances. Pure orchestration over the platform provider, no Android / iOS types, so it is fully covered by JVM unit tests with a fake provider. The UI observes state and calls requestCurrent from a button; runAll auto-walks the whole sequence.
Runtime permission requests. Android: ActivityResult; iOS: the per-capability authorization APIs.
One permission in a PermissionOrchestrator flow and its latest result (null = not yet decided).
Place-name autocomplete for an in-progress address search. Android/iOS: Compass's mobile autocomplete, which matches partial input against the same OS geocoder ForwardGeocoder uses — there is no separate typeahead network call or API key, so availability mirrors ForwardGeocoder.
Push token + topic surface. Android: FCM (gms) / no-op (noGms). iOS: APNs + Firebase.
Local persistence for the push token + subscribed topics. Platform impls push tokens here; topic subscribe/unsubscribe is local bookkeeping — remote registration against a backend is the app's job.
Pure engagement-gating logic for the in-app review prompt.
Tunable thresholds for the review gate (sane defaults; overridable via app config).
Persisted review counters (app-persisted — DataStore/NSUserDefaults/etc. in production).
Persistence for the review counters. Default in-memory; the app can swap a durable-store impl.
Drives the in-app review prompt from engagement signals. Records first-open + interaction counts, and prompts (via the platform AppReviewManager) only when ReviewEligibility is satisfied, then stamps the prompt time to enforce the cooldown.
Result of querying the store for a newer build.
Gate config for the in-app update flow (mirrors a remote splash/config API).
How an available update should be applied.