An Android-first, offline-first photo gallery concept that makes every backup state understandable.
Private pre-release · v0.1.0-alpha.1 · Local demo only
Synced Moments explores a simple trust promise: people should always know whether a photo is only on their device, waiting, uploading, backed up, failed, or available only from the cloud—and removing a device source must never silently remove its retained cloud copy.
The current pre-release is a deliberately isolated local demo. It uses safe deterministic fixtures and Room persistence so the gallery, detail view, recovery states, and Sync Ribbon can be reviewed before any real media or Supabase integration is authorized.
Adaptive gallery and item detail using privacy-safe geometric fixtures.
The same library adapts to wider layouts without loading real photo content.
Photo backup products often blur the boundary between the device and the cloud or hide why background work stopped. Synced Moments is designed around explicit state, durable offline behavior, and conservative privacy boundaries.
The intended Android MVP combines:
- an offline date-grouped photo library;
- visible per-item local, queue, upload, failure, and cloud states;
- contextual full, partial, denied, settings-only, and revoked photo access;
- Wi-Fi-first, bounded background work;
- private managed-cloud backup with cross-client viewing;
- clear exact-original versus location-removed behavior;
- retained cloud copies after a local source disappears.
The live cloud portion remains planned. This pre-release validates only the local presentation and state model plus separately labeled engineering diagnostics.
- Nine deterministic, metadata-free geometric demo items with fixed IDs and dates.
- Adaptive date-grouped grid and stable-ID item detail navigation.
- Separate
synced-moments-demo.dbRoom database and demo composition root. - Persisted simulated offline, uploading, backed-up, cloud-only, retry, unreadable, and unsupported states.
- Deterministic reconnect, completion, retry, local-source-removal, and reset actions.
- Persistent Demo library · Local simulation labeling.
- Light/dark themes, font scale 1.0/1.3, portrait/landscape layouts, 48 dp actions, and semantic item labels.
- A separately entered engineering diagnostic for Android photo-access, bounded MediaStore paging, exact/location-removed streams, Room queueing, and constrained WorkManager experiments.
- No
INTERNETpermission or network request. - No Supabase client initialization, account, session, bucket, schema, RLS policy, or remote object.
- No real-photo product gallery on the default demo path.
- No cross-client catalog or real upload/download behavior.
- No physical-device closure, release signing, Play distribution, or production backend.
Any Uploading, Backed up, or Cloud only text in the demo is explicitly labeled as simulated and persists only in the isolated local demo database.
- Launch the debug build and confirm Demo library · Local simulation.
- Select Simulate Wi-Fi return to move waiting items into a simulated upload state.
- Restart the app to confirm Room restores that state.
- Select Complete simulated sync.
- Open an item to retry a deterministic failure or simulate local-source removal.
- Select Reset demo library twice to restore the same fixtures and outcomes.
The Diagnostics action opens the separate platform-risk screen. Sensitive Android permissions are never requested at startup.
androidApp
Android lifecycle, Activity, ViewModels, permission launchers,
WorkManager components, production and demo composition roots
|
v
shared
commonMain: Compose screens, immutable state/actions, pure rules,
repository contracts, Room declarations, fixtures
androidMain: Room drivers, MediaStore/exact-stream gateways,
Ktor engine boundary
The default demo graph contains only its dedicated Room database and repository. MediaStore, WorkManager, Ktor, and Supabase are not injected into it. The production/diagnostic graph is created lazily only after Diagnostics is selected.
- Kotlin 2.4.10 and Compose Multiplatform 1.11.1
- Material 3
- Android Gradle Plugin / Android-KMP 9.1.0
- Gradle 9.3.1 and JDK 17
- Android minSdk 26, compileSdk/targetSdk 36
- Room 3.0.0
- WorkManager 2.11.2
- Ktor 3.5.1 and supabase-kt 3.7.0 as compile-verified, uninstantiated future boundaries
Prerequisites:
- JDK 17
- Android SDK Platform 36
- Android SDK Build Tools 36.0.0
ANDROID_HOMEorANDROID_SDK_ROOT, or an untrackedlocal.properties
Clone the private repository with an authenticated GitHub CLI session:
gh repo clone arpitagarwal1301/synced-moments
cd synced-momentsRun the canonical local verification:
./gradlew verifyLocalBuild or install the debug app:
./gradlew :androidApp:assembleDebug
./gradlew :androidApp:installDebugNo backend configuration is required for the local demo.
Recorded on 2026-07-26/27:
./gradlew verifyLocalpassed 72 tasks.- Six Android host tests passed with zero failures.
- Room/KSP schema generation, Android debug lint, and debug APK assembly passed.
- API 36 verified clean seed, restart persistence, retry, completion, simulated local removal, two resets, and diagnostic navigation.
- Light/dark, font scales 1.0/1.3, portrait/landscape, and accessibility-tree labels were inspected.
- Earlier API 34/36 diagnostics recorded permission truth; API 34 additionally recorded bounded paging, identity/originality, idempotent queue, restart, and constrained Worker behavior.
- Packaged-permission inspection found no Internet, video, all-files, camera, microphone, notification, or foreground-service permission.
Fixture and emulator evidence does not substitute for physical-device, backend, RLS, or cross-client proof.
- Repository fixtures and screenshots contain only programmatically drawn, non-personal geometric content.
- No real photo, filename, URI, location-bearing EXIF, account, credential, or private identifier belongs in source, tests, screenshots, or logs.
- Photo and exact-original access are contextual and have useful denial/revocation paths.
- Demo and app databases are excluded from Android backup/device transfer.
- The planned managed-cloud service is private/account-scoped but is not described as end-to-end encrypted.
- No service-role key, release signing key, permanent public object URL, or test password is stored here.
See PRIVACY.md and SECURITY.md for the engineering contracts.
- Two-module Android/CMP scaffold and full dependency compile.
- API 34/36 access diagnostic and bounded local risk slices.
- Isolated Room-backed local gallery demo.
-
v0.1.0-alpha.1private source pre-release. - Owner-authorized disposable Supabase project and two non-personal test accounts.
- Private claim/resumable-upload/finalize path and cross-account denial proof.
- Real gallery merge, account lifecycle, deletion controls, stress/accessibility hardening, and physical-device closure.
- Owner-controlled signed artifact and distribution decision.
- PRODUCT_BRIEF.md — product promise, audience, scope, and risks.
- SPEC.md — observable behavior and acceptance criteria.
- ARCHITECTURE.md — module boundaries, data flow, cloud protocol, and risk spike.
- DECISIONS.md — durable owner and engineering decisions.
- ROADMAP.md — verified work, gates, blockers, and next steps.
- TESTING.md — verification tiers and recorded evidence.
- DEMO_SCRIPT.md — local demo path and future live demo contract.
- CHANGELOG.md — pre-release history.
This is a private alpha and has no external contribution workflow yet. Keep changes within the approved roadmap and privacy boundaries, run ./gradlew verifyLocal, and update the evidence documents whenever verified behavior changes.
v0.1.0-alpha.1 is a private, source-only GitHub pre-release. The debug APK is intentionally not attached: it uses development signing and is not an owner-approved distribution artifact.
No open-source license has been selected. The private repository does not grant redistribution rights.


