diff --git a/README.md b/README.md index 9bf50dc..e4358f3 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,10 @@ no advertising or tracking SDKs. ## Status -**M10 — store assets: mostly done.** The app is named **Plain Files**, the icon and feature -graphic are generated from the app's own vectors, the screenshot normaliser is written, and -[docs/STORE_LISTING.md](docs/STORE_LISTING.md) holds length-checked listing copy. The -screenshots are still outstanding — the generator is ready but no captures exist yet. +**M10 — store assets: done.** The app is named **Plain Files**, the icon and feature graphic +are generated from the app's own vectors, and [docs/STORE_LISTING.md](docs/STORE_LISTING.md) +holds length-checked listing copy. The screenshots are captured: 5 phone (1080×2160), 4 on a +7-inch tablet (1200×1920) and 4 on a 10-inch tablet (2560×1600). ## Tech stack @@ -141,8 +141,10 @@ UI.** Translated UI text has to be supplied in `values-/`. - **"Open with" and Share only work in the all-files mode.** A SAF path is relative to the granted tree rather than a filesystem path, so it cannot be handed to `FileProvider`. -- **RAR and 7z are refused**, not supported — they need native code, which this project - deliberately does not ship. +- **RAR and 7z are refused**, not supported. The stated reason is only half right: RAR + genuinely needs native code (the Commons Compress jar this app ships contains no RAR + classes at all), but **7z does not** — `SevenZFile`/`SevenZOutputFile` are already inside + that same jar, so 7z read, and AES-256-encrypted 7z write, is an unpack away. - **Archive extraction does not restore original timestamps or permissions**, and there is no archive encryption or password support. - **Cancellation happens between entries**, so a single very large file finishes before a diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index bfac368..2d0cbab 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -19,7 +19,7 @@ Legend: ✅ done · 🚧 in progress · ⏳ not started · 💡 candidate (propo | M7 | On-device validation & hardening | ✅ | Run on a real **Xiaomi M2101K7AG** (Android 12 / MIUI V140) — see [EDGE_CASE_TESTING](EDGE_CASE_TESTING.md). Verified on hardware: the first-run permission prompt, granting "All files access" while the app is alive (picked up on resume), browsing real storage, the text editor's read **and** write path (independently checked with `adb shell cat`), the storage-usage screen, landscape layout, and **graceful degradation when access is revoked mid-use**. Found and fixed two real defects: misleading first-run copy ("Full access was declined" on a device where nothing had been declined), and a usage screen that stayed blank for **~45–60 s** on a 55 GB volume — now one listing per directory instead of a `stat` per node, with rows streamed out as they are measured. **142 JVM tests** | | M8 | Localisation groundwork | ✅ | Every user-visible string is in `res/values/strings.xml` with real ``, and `text/TextRes.kt` maps **both** `OperationKind` and `FileKind` onto resources so the screen, the notification and the details sheet cannot drift. The audit found a genuine miss: the details sheet rendered `FileKind.name`, i.e. untranslatable English — now a resource. `isPseudoLocalesEnabled = true` on the debug build makes "did every string come from resources?" mechanically checkable; verified `en-rXA` is present in the debug APK and the flag is debug-only. Byte units and the timestamp pattern are deliberately unlocalised, and the README says why. **142 JVM tests** | | M9 | Monetisation | ✅ | **Decided: one-time paid — €4.49 base with a 14-day launch price of €2.29**, both set in the Play Console (*Products › App pricing*), so there is **no Billing client, no `com.android.vending.BILLING` permission and no purchase code**. Rationale, market anchors and Console steps: [MONETISATION](MONETISATION.md). Verified against the release APK: zero billing and zero `INTERNET` references. **The price must be set before the first upload** — Play allows paid → free but never free → paid | -| M10 | Store assets | 🚧 | Name decided: **Plain Files** (one string; `applicationId` already locked). `tools/make-store-assets.sh` renders the 512×512 **RGBA** icon and the 1024×500 **RGB** feature graphic from the app's own vectors, so the store icon *is* the launcher icon; `tools/make-store-screenshots.sh` normalises `adb` captures to Play's 2:1 cap per form factor (phone crop default 93/130 px, tablets 0). [STORE_LISTING](STORE_LISTING.md) carries length-checked copy (name 11/30, short 67/80, full 1881/4000), the permissions paragraph the `MANAGE_EXTERNAL_STORAGE` declaration requires, and the graphics table. The feature graphic's copy was verified to survive Play's centre-square crop by cropping the rendered PNG. **Outstanding: screenshots** — the tooling and directories are in place but no captures exist yet | +| M10 | Store assets | ✅ | Name decided: **Plain Files** (one string; `applicationId` already locked). `tools/make-store-assets.sh` renders the 512×512 **RGBA** icon and the 1024×500 **RGB** feature graphic from the app's own vectors, so the store icon *is* the launcher icon; `tools/make-store-screenshots.sh` normalises `adb` captures to Play's 2:1 cap per form factor (phone crop default 93/130 px, tablets 0). [STORE_LISTING](STORE_LISTING.md) carries length-checked copy (name 11/30, short 67/80, full 1881/4000), the permissions paragraph the `MANAGE_EXTERNAL_STORAGE` declaration requires, and the graphics table. The feature graphic's copy was verified to survive Play's centre-square crop by cropping the rendered PNG. **Screenshots captured:** 5 phone (1080×2160), 4 on a 7-inch tablet (1200×1920) and 4 on a 10-inch tablet (2560×1600), all 24-bit RGB, inside the 2:1 cap. The tablet sets came from AOSP AVDs. The normaliser refuses a capture whose app area is blank, which is how a pure-background capture was caught before it reached the listing | ## Key decisions @@ -32,7 +32,9 @@ Legend: ✅ done · 🚧 in progress · ⏳ not started · 💡 candidate (propo ## Deliberately deferred (post-1.0) -- Dual-pane view; cloud storage (Drive/OneDrive/Dropbox/…); network clients - (SMB/FTP/SFTP/WebDAV); FTP/Web server. +- Cloud storage (Drive/OneDrive/Dropbox/…); network clients (SMB/FTP/SFTP/WebDAV); FTP/Web + server. All of these need `INTERNET`, which is the one permission the app deliberately + does not declare — see the connectivity decision above. - App manager (`QUERY_ALL_PACKAGES`), APK installation (`REQUEST_INSTALL_PACKAGES`). -- RAR/7z archives; root explorer; encryption vault; themes/icon packs. +- RAR archives (the format needs native code) and 7z *creation*; root explorer; encryption + vault; themes/icon packs.