Something went wrong. Try again.
Self-hosted file management and sharing system, supports multiple storage providers. forked from tdvorak.tngl.sh/cloudreve
Something went wrong. Try again.
README.md
Cloudreve Android #
Native Android client for Cloudreve. Kotlin + Jetpack Compose, Material 3.
Status: Phase E — v0.1 implemented. Sign in, browse, download, upload,
rename, mkdir, delete, thumbnails, share-link creation. See ../ROADMAP.md
for the remaining scope.
Build #
cd android
ANDROID_HOME=$HOME/Android/Sdk ./gradlew :app:assembleDebug
# APK: app/build/outputs/apk/debug/app-debug.apk
CI runs assembleDebug on every PR.
Unit tests cover the pure helpers (formatting, grouping, file kinds, upload naming and conflict resolution):
JAVA_HOME=$(/usr/libexec/java_home -v 17) ./gradlew :app:testDebugUnitTest
Gradle 8.11 cannot create the test task under JDK 24 ("Type T not present"); building works on 24, running tests needs 17 or 21.
What's implemented #
api/v4auth: password login → access/refresh tokens, single-flight refresh on 401, server-side revocation on sign-out- File browser: folder navigation, cursor pagination, pull-refresh, mkdir / rename / delete / download (cache + FileProvider open)
- Uploads: SAF document picker or share-sheet target, WorkManager background worker with progress notification, chunked through the upload-session flow (local + presigned remote policies)
- Thumbnails via
/file/thumb(Coil, lazily resolved per row) - Share-link creation (
PUT /share), link copied to clipboard - Search by name as you type (
GET /file?uri=…?name=<q>&case_folding, which works on every server; the full-text endpoint is off unless the admin enabled FTS). Scope chips (this folder / everywhere) and type chips (images, videos, audio, documents); result rows show the file's folder - Photo backup (
work/CameraUploadWorker,data/backup/): every run scans MediaStore, subtracts what the ledger accounts for and uploads the rest newest-first until nothing is left, chaining a continuation after 30 min. Files go to<root>/yyyy/MMby capture date (EXIF, else modification time). While a file is staged its SHA-256 is computed and sent with the upload session; the server links identical bytes it already has. A photo counts as UPLOADED only once the server lists it with the same size. A name collision is settled against the remote file: same size is the same photo (how uploads from earlier builds in the flat root are adopted), otherwise ours goes up asname~<hash8>.ext. The ledger is a SQLite table keyed by (content hash, MediaStore row) with no cap and no date watermark; once a day the run checks every UPLOADED row is still on the server and flags the rest as MISSING for the user to re-upload. Network errors retry the run; only verdicts about one file mark it REJECTED. - Offline favorites: "Keep offline" in a file's menu downloads to
filesDir/offline/and registers the entry (DataStore JSON); star icon in the top bar opens the offline list — open via FileProvider, re-download to refresh, remove to delete - DocumentsProvider: the whole tree appears in the system Files app /
SAF pickers — browse, open (cached download), thumbnails, rename,
delete, and search all proxy to
api/v4 - Task notifications: periodic
GET /workflowpoll posts a notification when a task completes/fails/cancels — toggle in the settings dialog, runtime POST_NOTIFICATIONS permission gated - OAuth sign-in: "Sign in with browser" opens the server's consent
page with PKCE; the
/callback/desktoppage deep-links the code back throughcloudreve://mount, exchanged at/session/oauth/token - Local sync folder: pick a device folder (SAF, persisted permission) and a remote folder — periodic WorkManager worker mirrors new/changed files upstream, subdirectory structure preserved, unchanged files skipped via mtime/size signatures, Wi-Fi-only option
- Quick Settings tile toggling camera backup, with active/inactive state
UX (feat/android-ux) #
Goal: feel like the system Files app.
- Home page like the Files app: search field, Recent strip (newest files
anywhere in the drive), Images / Videos / Audio / Documents tiles (each a
server-side
?category=search listed newest first with the file's folder in the subtitle), My files, Offline files - Material You dynamic colour; folder name as title with parent path below; search, list/grid toggle and an overflow menu (sort, select, refresh, offline files, settings) instead of a row of icons
- Rows without dividers, rounded thumbnail tiles with per-type icons and
tints,
size • datesubtitles; grid view with adaptive tiles - Sort by name / size / date (tap again to flip), persisted, sent to the
server as
order_by; folders always first - Long-press selection (haptic) with select-all, move, copy and batch delete; per-file actions in a bottom sheet headed by the file's thumbnail and details; Move to / Copy to open a full-screen folder picker
- Upload name clashes are resolved before queuing: Replace (new version),
Keep both (
(1)suffix) or Skip - Delete offers Undo (restores from the trash); Offline files is a full screen listing local copies with thumbnails, update and remove
- Trash collection with Restore and Delete forever; share links created on demand from a sheet with expiry and optional password, then Copy or the system share sheet; Details sheet (size, location, dates, dimensions)
- Folder listings cached per path and shown instantly on re-entry while a fresh listing loads behind a thin bar
- Folder and category top bars show the item count ("5 items", "50+ items" while more pages remain); selection reads "3 of 24 selected"
- Photo backup card on the home page and in Settings: safely uploaded / total on the device, waiting, missing on the server, failed, last run, with Back up now and Retry / Re-upload
- Uploads: byte-level progress in a card above the destination folder's files and in a notification with Cancel; the folder refreshes itself when the batch lands. The home page shows an activity card for uploads and for the periodic camera-backup / folder-sync workers while they run. Downloads show a progress ring on the tile; a second tap cancels; cached copies open at once
- Images and Videos categories render as an edge-to-edge photo grid (play badge on videos); the viewer closes on a vertical swipe
- In-app viewer: swipeable image gallery with pinch zoom, video and
audio streamed with media3, PDF pages via
PdfRenderer, plain text and source files; everything else goes to the system viaACTION_VIEW - Settings as a full screen (photo backup, folder sync, notifications, account)
Planned next #
- No iOS. Ever.