# Roadmap File Manager is built against a fixed milestone plan (**M0–M10**). This file is the single source of truth for what is done and what remains. Legend: βœ… done Β· 🚧 in progress Β· ⏳ not started Β· πŸ’‘ candidate (proposed, not scheduled) ## Milestones | # | Milestone | Status | Evidence / notes | |---|---|---|---| | M0 | Toolchain & scaffold | βœ… | Gradle 9.3.1 + AGP 9.1.0 wrapper, version catalog, app module, Compose theme, debug APK builds, installs and runs on the `phone` AVD: package `de.softwareapp_hb.filemanager.debug`, `versionCode 1`, `minSdk 26`/`targetSdk 36`, **no `INTERNET` permission**, `lintDebug` clean (one expected `UnusedResources` for the not-yet-used notification icon) | | M1 | Pure-Kotlin core + JVM tests | βœ… | `core/` is **Android-free**: `StoragePath` (normalised absolute paths that cannot escape the root), `FileEntry` + `FileKind` classification, `MimeTypes`, `NaturalOrder` + `SortSpec` (directories first; `file2` before `file10`), `FileSize`, `NameMatcher` (substring + `*`/`?` glob), `NameAllocator` ("name (1)") and `TransferPlanner` (conflict policies, move-into-self). **44 JVM tests** across 10 classes, all green | | M2 | Storage layer | βœ… | `StorageSource` with two backends β€” `AllFilesSource` (`java.io.File` under all-files access) and `SafSource` (`DocumentsContract` over a persisted tree URI), the latter split so the tree↔path mapping (`SafDocumentIds`) is exhaustively testable; `SafGrant` for the picker and its persistence; `VolumeRepository` (`StorageManager`/`StorageVolume` + `StatFs`); `StorageAccess` + `StorageAccessPolicy` for the all-files/SAF decision. **76 JVM tests** total (32 added here) | | M3 | Operations engine + service | βœ… | `domain/FileOperations` composes the backend primitives into copy/move/delete/rename with recursive walking, an honest progress total, cooperative cancellation between entries and per-item failure reporting; conflicts are decided through the M1 `TransferPlanner` (`ASK` is surfaced for the UI to resolve). `service/FileOpService` is a `dataSync` foreground service mirroring progress into a notification (`FileOpNotifications` + `text/TextRes`). **99 JVM tests** total (23 added here) | | M4 | Compose UI | βœ… | `BrowserViewModel` + `BrowserUiState` over `StorageLocation`; browser screen with list/grid, breadcrumbs, in-folder search, a sort/hidden-files/view sheet, multi-select action bar, details sheet, and new-folder/rename/delete/conflict dialogs; a roots view and the "All files access" + SAF-folder prompts; `data/MediaStoreDeleter` routes a delete through the platform's own dialog where it can and falls back to a direct delete; a `FileProvider` backs "open with" and share. **115 JVM tests** total (16 added here) | | M5 | Analysis, archives, viewers | ⏳ | disk-usage analysis, large-file finder, ZIP/TAR/GZ via Commons Compress, image viewer, text editor | | M6 | Release config & Play readiness | ⏳ | R8/minify, optional signing, `.aab`; [PLAY_RELEASE_CHECKLIST](PLAY_RELEASE_CHECKLIST.md) (incl. the **Permissions Declaration Form**), [PRIVACY.md](../PRIVACY.md), README | | M7 | On-device validation & hardening | ⏳ | AVD + real-device checks, per-operation error boundaries, edge-case fixtures | | M8 | Localisation groundwork | ⏳ | every user-visible string in `res/values/strings.xml` with real ``; `text/` mapping | | M9 | Monetisation | ⏳ | **one-time paid** β€” price set only in the Play Console before the first upload; no Billing code and no `BILLING` permission | | M10 | Store assets | ⏳ | icon/feature-graphic generators, per-form-factor screenshots, [STORE_LISTING](STORE_LISTING.md); display name confirmed | ## Key decisions | Decision | Choice | Rationale | |---|---|---| | Language / UI | Kotlin + Jetpack Compose | Mirrors the sibling app's proven, installed toolchain; no NDK | | Storage access | `MANAGE_EXTERNAL_STORAGE` first, SAF fallback | Google Play explicitly permits "All files access" for file managers; SAF keeps the app usable if the user declines | | Connectivity | Local-first (no `INTERNET` in v1) | Preserves the "nothing leaves the device" claim and keeps the Data Safety form trivial | | Monetisation | One-time paid, price in Console | No Billing code; free β†’ paid is impossible after the first upload, so the price must be set beforehand | ## Deliberately deferred (post-1.0) - Dual-pane view; cloud storage (Drive/OneDrive/Dropbox/…); network clients (SMB/FTP/SFTP/WebDAV); FTP/Web server. - App manager (`QUERY_ALL_PACKAGES`), APK installation (`REQUEST_INSTALL_PACKAGES`). - RAR/7z archives; root explorer; encryption vault; themes/icon packs.