77 lines
5.0 KiB
Markdown
77 lines
5.0 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to File Manager are documented in this file.
|
|
|
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the
|
|
project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
`versionCode` and `versionName` are defined in `app/build.gradle.kts`. Each Play
|
|
upload needs a **higher `versionCode`** than every previous upload.
|
|
|
|
## [Unreleased]
|
|
|
|
### Added
|
|
|
|
- **M5 — analysis, archives and viewers.** `domain/UsageAnalysis` rolls up recursive folder
|
|
sizes and finds the largest files below a folder, which the new storage-usage screen
|
|
shows as a size and a share bar per row. `domain/ArchiveEngine` creates ZIP archives and
|
|
extracts ZIP, TAR, TAR.GZ, GZ, BZ2 and XZ using `java.util.zip` and Commons Compress —
|
|
all pure Java, so the app still ships no native code; RAR and 7z are recognised and
|
|
refused with a clear message rather than half-supported. Every archive entry name is
|
|
passed through `core/ArchivePath` before it becomes a path, so a crafted `../` entry
|
|
cannot write outside the destination. The browser gains Coil thumbnails in the list and
|
|
grid, a built-in image viewer and text editor, and compress/extract actions. 26 new JVM
|
|
tests (141 total), including a zip-slip archive that is refused while the same archive's
|
|
safe entry still extracts.
|
|
|
|
- **M4 — the browser UI.** The app is now usable end to end. `StorageLocation` (with a
|
|
real `StorageProvider` and a fake for tests) decides which backend is in effect;
|
|
`BrowserViewModel` owns navigation, sorting, hidden files, list/grid, search, selection
|
|
and the clipboard, and turns an `ASK` conflict into a prompt rather than a guess. The
|
|
screen offers roots and folder lists with breadcrumbs, a details sheet, new-folder /
|
|
rename / delete / conflict dialogs, and the "All files access" and SAF-folder prompts —
|
|
including an upgrade banner so declining full access never blocks browsing. Deletes go
|
|
through the platform's own confirmation when `MediaStore` can build one and fall back to
|
|
a direct delete otherwise; a `FileProvider` lets other apps open and receive files
|
|
without a `file://` URI ever leaving the process. 16 new JVM tests (115 total).
|
|
|
|
- **M3 — operations engine and foreground service.** `domain/FileOperations` turns the
|
|
backend primitives into copy, move, delete and rename: it walks folders, counts the
|
|
work up front so the progress bar has an honest denominator, checks for cancellation
|
|
between entries (never swallowing `CancellationException`), and reports per-item
|
|
failures instead of abandoning a batch because one file was unreadable. Conflicts are
|
|
resolved through the M1 `TransferPlanner` — `ASK` is deliberately surfaced to the
|
|
caller so the UI can prompt. A move tries the backend's atomic rename first and only
|
|
falls back to copy-then-delete when the backend cannot do it (the SAF path across
|
|
directories); the source is never deleted when its copy failed. `service/FileOpService`
|
|
is a `dataSync` foreground service that mirrors the engine's progress into an ongoing
|
|
notification, so a long operation survives the app being backgrounded. 23 new JVM
|
|
tests (99 total), including Robolectric coverage of the notification and the service
|
|
entering the foreground.
|
|
|
|
- **M2 — storage layer.** The two storage backends behind one interface. `AllFilesSource`
|
|
is `java.io.File` over every mounted volume (the "All files access" path);
|
|
`SafSource` is the Storage Access Framework fallback, reading a persisted tree URI
|
|
through `DocumentsContract` with `SafDocumentIds` doing the tree↔path mapping and
|
|
`SafGrant` owning the folder picker and its persistence. `VolumeRepository` enumerates
|
|
volumes via `StorageManager`/`StorageVolume` and reports free/total space through
|
|
`StatFs`; `StorageAccess` and `StorageAccessPolicy` decide between the two backends.
|
|
Both sources confine their blocking I/O to `Dispatchers.IO` and expose a `suspend`
|
|
contract. 32 new JVM tests (76 total), including a Robolectric run of `SafSource`
|
|
against a stand-in `DocumentsProvider`.
|
|
|
|
- **M1 — pure-Kotlin core engine.** An Android-free `core/` package holding the logic
|
|
every other layer builds on: `StoragePath` (normalised absolute paths that can never
|
|
escape the root), `FileEntry` with extension-based `FileKind` classification and a
|
|
`MimeTypes` lookup for "open with", natural-order `SortSpec` (directories always
|
|
first, `file2` before `file10`), human-readable `FileSize`, `NameMatcher`
|
|
(case-insensitive substring plus `*`/`?` globs), `NameAllocator` ("name (1)") and
|
|
`TransferPlanner` (conflict policies and move-into-self detection). Covered by
|
|
**44 JVM unit tests** across 10 classes.
|
|
|
|
- **M0 — project scaffold.** Gradle 9.3.1 / AGP 9.1.0 build with a version catalog,
|
|
`de.softwareapp_hb.filemanager` app module, a Compose Material 3 shell with the
|
|
branded blue theme (dynamic colour on Android 12+), an adaptive launcher icon, and
|
|
the storage-access permission set (all files access + SAF fallback). Debug APK
|
|
builds, installs and runs on an AOSP Android 12 AVD.
|