Skip to content

refactor(arca-gui): move view-owned state mutations into AppController - #87

Merged
devin-ai-integration[bot] merged 2 commits into
mainfrom
devin/1792271402-controller-owned-state
Oct 18, 2026
Merged

devin-ai-integration[bot] merged 2 commits into
mainfrom
devin/1792271402-controller-owned-state

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Views in arca-gui/src/ui/ wrote straight into AppState/Settings and called Settings::save() themselves, which silently dropped I/O errors. They also kept two copies of the codec/level picker that had drifted apart. The active pane's state was stored twice: in the legacy AppState fields and in browser.panes[active], kept in sync by snapshot_active_pane/restore_active_pane. Behavior is unchanged, except that a failed settings write now shows an error notice.

Active pane: one copy of its state (commit 1)

  • Removed AppState::{checked, filter, order, current_dir, cursor}. DirectoryPane::selected: HashSet<usize> is now checked: Vec<bool>.
  • AppState::active_pane() / active_pane_mut() return &browser.panes[browser.active]. snapshot_active_pane/restore_active_pane are gone. Switching panes calls pane_switched(), which does what restore did: resizes the pane's checked to entries.len() and clears last_click, renaming and the preview.
  • select_only (added on main in refactor(arca-gui): select a single row through one controller action #72 as AppAction::SelectOnly) now clears active_pane_mut().checked and no longer needs a snapshot.

Settings persistence

Settings::save(&self) -> io::Result<()>           // was (), with `let _ =` on create_dir_all/write
AppController::update_settings(|s| ...) -> R      // mutate, save once, error -> set_notice(settings_not_saved, true)
AppController::set_column_width(slot, w, persist) // live drag updates, saved when the drag ends

Every settings.save() call in ui/ (dialogs including the theme library, header, sidebar, preview, browser, mod) and in the controller, including set_archive_defaults from #68, now goes through this path. New string settings_not_saved (en/es).

Compressor picker

  • AppController::compressor_for(format, codec) -> Compressor::{Fixed("LZMA2"|"RAR"), Codec { codec, editable }} replaces the two copies of the is_lzma2/Format::Rar check. compressor() applies it to the session's state.format/state.codec. CODECS and LEVEL_PRESETS replace the inline arrays.
  • Both dialogs use one codec_combo helper:
    • Settings > Defaults passes settings.new_format/new_codec to compressor_for and saves through set_archive_defaults.
    • The compress dialog uses compressor() and calls set_codec/set_level.
  • Each dialog keeps its own layout: the settings page shows a level combo and a disabled combo for non-ZIP codecs, and the compress dialog shows a slider and a muted label.

Notices: set_notice(text, error) replaces the paired notice/error writes.

Tests

New tests: select_only_replaces_the_active_selection and only_zip_lets_the_codec_be_picked. #72's select_only test now checks panes[0].checked.

Ran locally: cargo fmt --check, cargo clippy --workspace --all-targets -D warnings, cargo test --workspace, both release builds, and bash interop.sh (146 passed).

Not covered:

  • No test for the save-error path. It would need XDG_CONFIG_HOME set for the whole process, and the tests run in parallel.
  • I didn't click through the GUI by hand.

Link to Devin session: https://app.devin.ai/sessions/f6cf7190c78d468b8c00be133c2d3a76
Open in Devin Desktop: https://app.devin.ai/desktop/session/f6cf7190c78d468b8c00be133c2d3a76?variant=devin
Requested by: @Villoh

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1792271402-controller-owned-state branch 3 times, most recently from 58400e5 to 6156812 Compare October 18, 2026 10:40
Villoh and others added 2 commits October 18, 2026 10:47
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…es through the controller

Views mutated AppState and Settings directly and called Settings::save, which dropped I/O errors. Settings::save now returns io::Result and AppController::update_settings saves once and shows a failure as an error notice. Both create dialogs read the compressor from AppController::compressor and share one codec picker.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1792271402-controller-owned-state branch from 6156812 to bc73d44 Compare October 18, 2026 10:48
@devin-ai-integration
devin-ai-integration Bot merged commit c2a099e into main Oct 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant