Initial commit
This commit is contained in:
commit
9910ba6917
132 files changed
+53909
No files matched your search
@@ -0,0 +1,73 @@
|
||||
<h1 align="center">OneCamera</h1>
|
||||
|
||||
<h4 align="center">Take photos straight into the right folder.</h4>
|
||||
|
||||
<p align="center">
|
||||
<a href="#features">Features</a> •
|
||||
<a href="#capture-and-storage">Capture & storage</a> •
|
||||
<a href="#responsiveness">Responsiveness</a> •
|
||||
<a href="#tech-stack">Tech stack</a> •
|
||||
<a href="#build">Build</a>
|
||||
</p>
|
||||
|
||||
OneCamera is an Android app for taking photos directly into the folder you choose. Pick a folder, tap the camera button, and a camera app takes the shot. The captured photo is saved straight into the selected folder.
|
||||
|
||||
## Features
|
||||
|
||||
- Folder-first shooting — choose a folder before taking a photo.
|
||||
- Camera handoff — fires `MediaStore.ACTION_IMAGE_CAPTURE`; the system resolves it to the default camera app (no camera picker inside OneCamera).
|
||||
- No broad storage permissions — only a user-selected SAF root folder; everything else is off-limits to the app.
|
||||
- Folder management — create, rename, move, and delete folders in the SAF tree.
|
||||
- ZIP archives — one-tap pack a folder as original files or as JPG quality 85, then share via any app.
|
||||
- Gallery — adaptive grid/list view, sort by name, fullscreen viewer with zoom and subsampling of huge photos, multi-select, share via system intents.
|
||||
- Draggable floating camera button with position persisted across restarts.
|
||||
- Material 3 UI with dynamic color, light, dark, and system themes.
|
||||
- No tracking, no ads, fully open source.
|
||||
|
||||
## Capture & Storage
|
||||
|
||||
OneCamera never asks for broad storage access. All file work goes through a single user-picked Storage Access Framework tree.
|
||||
|
||||
Capture flow:
|
||||
|
||||
1. The user grants a folder tree through the system picker; the grant is persisted.
|
||||
2. The app creates a temp file exposed through `FileProvider` and fires `ACTION_IMAGE_CAPTURE` with `EXTRA_OUTPUT`; the system routes the intent to the default camera app.
|
||||
3. The camera app writes the shot into the temp file; the app moves it into the selected SAF folder.
|
||||
4. A photo event bus refreshes the gallery without a restart; thumbnails are decoded subsampled and cached on disk.
|
||||
|
||||
Folder operations — rename, delete, move — go through SAF documents, so the UI and the file system always agree. ZIP packaging runs off the main thread with progress; if a file cannot be read, the partial archive is deleted and the outcome carries an error message. Archive entry names are UTF-8 encoded to preserve non-ASCII names. Revoking tree access is handled explicitly instead of crashing.
|
||||
|
||||
## Responsiveness
|
||||
|
||||
Photo libraries can be large, so heavy work stays off the main thread:
|
||||
|
||||
- SAF queries, folder scanning, and ZIP packaging run on background dispatchers;
|
||||
- gallery content loads incrementally, and folder statistics are computed separately from the photo list;
|
||||
- thumbnails load through Coil with a bounded memory cache and a disk cache capped by LRU eviction, and oversized photos are subsampled in the fullscreen viewer;
|
||||
- grid and list are lazy; sort order and view mode changes reuse loaded state instead of rescanning the tree;
|
||||
- rotation recreates the Activity by design — scroll position, sort order, and the FAB position live in ViewModel state and DataStore, not in composables;
|
||||
- Baseline Profile rules ship in the APK to speed up cold start.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- Kotlin 2.4.21
|
||||
- Jetpack Compose (BOM 2026.09.00), Material 3
|
||||
- Hilt 2.60.1 (dependency injection)
|
||||
- Navigation Compose 2.10.2
|
||||
- DataStore Preferences 1.2.1
|
||||
- Coil 3.6.3 + ZoomImage 1.7.0 (image loading and fullscreen zoom)
|
||||
- kotlinx.serialization 1.11.0
|
||||
- Androidx tracing with a committed Baseline Profile
|
||||
- Android Gradle Plugin 9.4.1, Gradle 9.8.1, JDK 21
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
./gradlew :app:assembleRelease
|
||||
```
|
||||
|
||||
The release APK targets `arm64-v8a`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
Reference in new issue
Block a user