A copy into a picked folder says where it went, and Show takes you there

The last acceptance criterion M16 had left open. After Copy to..., the snackbar reads 'Copied to AADst' with a Show button; after a move to a picked folder it keeps the undoable message instead, because the sources are gone and Show would lead nowhere.

Two things needed care rather than a string. The action button was hard-wired to undo() - the label was a parameter beside it, which let the two disagree - so UiMessage now carries a MessageAction, and the label follows from it: Undo for an undo, Show for a jump. And a message cannot name a folder from the path alone: a volume root has no name of its own, and internal storage's is 0. The message carries the picked PickerFolder, and the screen resolves its label the way breadcrumbs do - so copying into the root reads 'Copied to Internal storage', which is the case a plain path.name would have got wrong.

Four tests: the message names the destination and offers Show; Show opens it; a paste into the folder on screen still names nothing and offers nothing (its destination is the screen); a move to a picked folder offers Undo. All four driven through the view model, and both snackbar variants checked on the phone, including the volume-root one.

detekt's SpreadOperator baseline entries moved with the expression, so the message building is now a small helper with a deliberate suppression and a reason, and the baseline was regenerated: three obsolete entries removed, none added.
This commit is contained in:
2026-10-17 23:17:03 +02:00
parent 747a6f7784
commit 17078bf613
10 changed files with 219 additions and 26 deletions
-3
View File
@@ -22,7 +22,6 @@
<ID>LongParameterList:BrowserContent.kt$( state: BrowserUiState, contentPadding: PaddingValues, crumbLabel: (StoragePath) -&gt; String, onOpenEntry: (FileEntry) -&gt; Unit, onFocusEntry: (FileEntry) -&gt; Unit, onFocusRoot: (RootItem) -&gt; Unit, onToggleSelection: (StoragePath) -&gt; Unit, onOpenRoot: (StoragePath) -&gt; Unit, onNavigate: (StoragePath) -&gt; Unit, onOpenCategory: (FileCategory) -&gt; Unit, onOpenBookmark: (StoragePath) -&gt; Unit, onRemoveBookmark: (StoragePath) -&gt; Unit, onGrantAllFiles: () -&gt; Unit, onPickFolder: () -&gt; Unit, onRebuildIndex: () -&gt; Unit, /** Hoisted by the screen so the scroll position outlives a viewer taking over. */ listState: LazyListState = rememberLazyListState(), gridState: LazyGridState = rememberLazyGridState(), )</ID>
<ID>LongParameterList:BrowserContent.kt$( state: BrowserUiState, crumbLabel: (StoragePath) -&gt; String, wide: Boolean, listState: LazyListState, gridState: LazyGridState, onOpenEntry: (FileEntry) -&gt; Unit, onFocusEntry: (FileEntry) -&gt; Unit, onToggleSelection: (StoragePath) -&gt; Unit, onNavigate: (StoragePath) -&gt; Unit, onGrantAllFiles: () -&gt; Unit, onRebuildIndex: () -&gt; Unit, modifier: Modifier = Modifier, )</ID>
<ID>LongParameterList:BrowserTopBar.kt$( title: String, canNavigateUp: Boolean, /** Whether this view is a folder, and so can be starred at all. */ canBookmark: Boolean, bookmarked: Boolean, query: String, searchOpen: Boolean, searchScope: SearchScope, /** Whether the scope is the user's to choose at all; see the note beside the toggle. */ scopeChoosable: Boolean, canPaste: Boolean, onUp: () -&gt; Unit, onQuery: (String) -&gt; Unit, onSearchOpen: (Boolean) -&gt; Unit, onSearchScope: () -&gt; Unit, onSort: () -&gt; Unit, onPaste: () -&gt; Unit, onToggleBookmark: () -&gt; Unit, onRefresh: () -&gt; Unit, onUsage: () -&gt; Unit, onDuplicates: () -&gt; Unit, onTrash: () -&gt; Unit, )</ID>
<ID>LongParameterList:SelectionBar.kt$( state: BrowserUiState, onCopy: () -&gt; Unit, onCut: () -&gt; Unit, onDelete: () -&gt; Unit, onDetails: () -&gt; Unit, onRename: () -&gt; Unit, onOpenWith: () -&gt; Unit, onShare: () -&gt; Unit, onCompress: () -&gt; Unit, onExtract: () -&gt; Unit, onSelectAll: () -&gt; Unit, onClear: () -&gt; Unit, )</ID>
<ID>LoopWithTooManyJumpStatements:ArchiveEngine.kt$ArchiveEngine$while</ID>
<ID>LoopWithTooManyJumpStatements:BatchRename.kt$BatchRename$for</ID>
<ID>LoopWithTooManyJumpStatements:DuplicateFinder.kt$DuplicateFinder$while</ID>
@@ -68,8 +67,6 @@
<ID>RethrowCaughtException:BrowserViewModel.kt$BrowserViewModel$throw cancellation</ID>
<ID>ReturnCount:ArchiveEngine.kt$ArchiveEngine$private suspend fun withEntry( archive: StoragePath, name: String, sink: suspend (InputStream) -&gt; Unit, ): Boolean</ID>
<ID>ReturnCount:BrowserScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun BrowserScreen( incoming: IncomingRequest? = null, onDeliver: (FileEntry) -&gt; Unit = {}, onDone: () -&gt; Unit = {}, viewModel: BrowserViewModel = viewModel(factory = BrowserViewModel.Factory), )</ID>
<ID>SpreadOperator:BrowserScreen.kt$(it.textRes, *it.args.toTypedArray())</ID>
<ID>SpreadOperator:BrowserScreen.kt$(it.textRes, quantity, *it.args.toTypedArray())</ID>
<ID>TooGenericExceptionCaught:ArchiveEngine.kt$ArchiveEngine$failure: Exception</ID>
<ID>TooGenericExceptionCaught:BrowserViewModel.kt$BrowserViewModel$failure: Exception</ID>
<ID>TooGenericExceptionCaught:FileOperations.kt$FileOperations$failure: Exception</ID>