Migrates the config model from the phase-2 bag-of-bools (ToolbarItems)
to an ordered Vec<ToolbarAction> so the user can pick BOTH the set of
buttons AND their order in the toolbar.
Config (config.rs):
- new ToolbarAction enum with 11 variants (LocationUp, Reload,
NewFolder, NewFile, Rename, Delete, Cut, Copy, Paste,
ToggleShowHidden, OpenTerminal) + to_u8/from_u8 for DnD payload
- Config.toolbar: Vec<ToolbarAction>, default = default_toolbar()
(NewFolder, Rename, Delete, Cut, Copy, Paste — same 6 as phase 2)
Rendering (view()):
- iterate self.config.toolbar in order and emit a tooltip'd icon button
per entry via the new toolbar_action_ui(action) helper shared with
the Settings page. Paste stays disabled when clipboard empty.
- No hardcoded groups or auto-dividers anymore — order is 100% user.
Settings page (toolbar_settings_section):
- two stacked lists:
* 'Toolbar': currently-enabled actions in their Vec order. Each row
is wrapped in dnd_source (drags a ToolbarActionPayload carrying
the enum discriminant) + dnd_destination (accepts drops from other
rows, fires Message::ToolbarReorder { src, target } to move src
before target in the Vec). A list-drag-handle icon + a minus button
(ToolbarRemove) per row.
* 'Available': actions not yet enabled, each with a plus button
(ToolbarAdd) that pushes to the end of the Vec.
- 'Reset to defaults' button at the bottom (ToolbarReset).
DnD infra (app.rs top):
- TOOLBAR_MIME constant: 'application/x-cosmic-files-toolbar-action'
- ToolbarActionPayload(u8) with AsMimeTypes + AllowedMimeTypes +
TryFrom<(Vec<u8>, String)> impls — single-byte wire format matching
the enum discriminant.
Messages:
- ToolbarAdd(ToolbarAction) — append to toolbar vec if absent
- ToolbarRemove(ToolbarAction)
- ToolbarReorder { src, target } — remove src, reinsert before target
- ToolbarReset — restore default_toolbar()
i18n (en + fr):
- new keys: toolbar-available, toolbar-empty-hint, toolbar-reset
Migration: existing installs with a phase-2 ToolbarItems struct in
their config will error at load time (different shape); cosmic_config
falls back to Self::default() which gives the phase-2 minimal-6 set —
a safe reset rather than a broken partial read.