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.
Phase 1 shipped a fixed 6-button toolbar. Phase 2 moves visibility to
the config so users pick which buttons appear.
Config (config.rs):
- new ToolbarItems struct (CosmicConfigEntry) with one bool per button
- Config.toolbar: ToolbarItems, default = 'minimal 6' set from phase 1
(new_folder, rename, delete, cut, copy, paste) + 5 extras off
(new_file, reload, toggle_show_hidden, open_terminal, location_up)
Rendering (view()):
- iterate through self.config.toolbar fields in fixed logical order
(location → create/edit → clipboard → view toggles)
- dividers inserted only between non-empty groups
- whole toolbar hidden if every button is off (no empty container)
Settings page (settings()):
- new 'Toolbar' section with one toggler per button, wired through
Message::SetToolbar(ToolbarItems) which persists via config_set!
i18n (en + fr):
- added 'toolbar' + 'parent-directory' strings
- reused existing new-folder / new-file / rename / delete / cut / copy /
paste / reload-folder / show-hidden-files / open-in-terminal
All actions dispatch through Action::message so keybindings and toolbar
share one code path.
Since we already depend on `rustc-hash` transiently, this doesn't add
any more dependencies. As long as DOS attacks aren't a concern (which I
don't think they are?), this should be free performance.
In my (admittedly naive) testing, this really improved CPU usage in some
cases, which is pretty nice to get for free.
Icon sizes are stored as a zoom percentage. This may need to be updated
by a programmer with better ideas, but it seems a bit nicer than storing
the size in pixels and presenting that to the user.
A tab config is useful for allowing users to show hidden files, sorting
by different metrics such as size or MIME type, as well as providing a
way to implement some of the todos such as configurable icon sizes for
views.