exlab_wizard.ui.components.file_list#

Live file-list component for the rebuilt main window.

GUI/Orchestrator Redesign §4.3, §5. Renders the immediate contents of a folder (name / size / modified / per-file sync status) and exposes a pure diff function that drives the new-file highlight.

The renderer is a pure function kept free of session-store / API deps (matches the existing components pattern). The folder feed (§5) is expected to call render_file_list with the current entry list; the caller decides when to invoke and when to stop the underlying poll.

Right-click context menu (Redesign §4.3 / decision 6A): selecting a row opens a menu with Open in OS, Copy path, and Keep local actions; the right metadata pane is NOT driven by file-list selection.

Operator-free per-file NAS sync design (2026-05-21): a row can be a tombstone – a file present in the run’s sync_state.json but absent on disk (an “On NAS” cleared-run file). A tombstone is not openable. A keep_local file carries a small “kept local” badge.

Functions

diff_file_lists(previous, current)

Return additions / removals / modifications between two snapshots.

render_file_list(*, state[, ...])

Render the centre-pane file list.

row_background(entry, *, is_selected, ...)

Return the CSS background + decoration fragment for one file-list row.

Classes

FileListDiff(added, removed, modified)

Result of comparing two successive folder-list snapshots.

FileListEntry(name, path, is_dir[, ...])

One row in the centre-pane file list.

FileListState([path, entries, new_paths, ...])

Mutable state for the file list, consumed by the renderer.

class exlab_wizard.ui.components.file_list.FileListDiff(added, removed, modified)[source]#

Bases: object

Result of comparing two successive folder-list snapshots.

Parameters:
added: tuple[str, ...]#
modified: tuple[str, ...]#
removed: tuple[str, ...]#
class exlab_wizard.ui.components.file_list.FileListEntry(name, path, is_dir, size_bytes=None, modified_iso=None, sync_status=None, keep_local=False, tombstone=False)[source]#

Bases: object

One row in the centre-pane file list.

keep_local mirrors the file’s sync_state.json keep-local flag (excluded from cleanup deletion). tombstone marks an “On NAS” row – a file recorded in sync_state.json but absent on disk; such a row shows the on_nas icon and is not openable.

Parameters:
is_dir: bool#
keep_local: bool = False#
modified_iso: str | None = None#
name: str#
path: str#
size_bytes: int | None = None#
sync_status: str | None = None#
tombstone: bool = False#
class exlab_wizard.ui.components.file_list.FileListState(path='', entries=<factory>, new_paths=<factory>, selected_path=None)[source]#

Bases: object

Mutable state for the file list, consumed by the renderer.

Parameters:
entries: list[FileListEntry]#
new_paths: frozenset[str]#

Paths that appeared in the most recent diff – briefly highlighted.

path: str = ''#
selected_path: str | None = None#

Path of the row the operator single-clicked (Phase 4 / Option B); the matching row carries the selected fill + accent bar via row_background.

exlab_wizard.ui.components.file_list.diff_file_lists(previous, current)[source]#

Return additions / removals / modifications between two snapshots.

Pure function. An entry is “modified” when its path is present in both lists but its (size, modified_iso, sync_status) tuple differs. Used by the renderer to drive the new-file highlight and is unit- testable without spinning up NiceGUI.

Parameters:
Return type:

FileListDiff

exlab_wizard.ui.components.file_list.render_file_list(*, state, on_double_click=None, on_context_menu=None, on_select=None)[source]#

Render the centre-pane file list. Pure render function.

Double-clicking a folder navigates into it; double-clicking a file asks the OS to open it. Single-click (on_select) selects the row – files and folders – so its metadata appears in the right pane and the row picks up the selected fill + accent bar (Phase 4 / Option B, spec §4.3). The right-click context menu is unchanged.

Parameters:
Return type:

Any

exlab_wizard.ui.components.file_list.row_background(entry, *, is_selected, is_new, index)[source]#

Return the CSS background + decoration fragment for one file-list row.

Pure function (no NiceGUI) so the row-state precedence is testable in isolation. Implements the spec’s row-state stack (Redesign §4.2).

Background – first matching tier wins, top to bottom:

  1. Selected -> --color-row-selected fill + inset left accent bar.

  2. New-file -> --color-highlight (the just-arrived flash).

  3. Tombstone -> no fill (explicitly suppresses the zebra stripe).

  4. Zebra -> --color-zebra on odd index rows.

  5. (otherwise) -> no background.

Decoration – applied additively whenever the row is a tombstone, independent of which background tier won, so a selected tombstone keeps both the selected fill and the dim/italic “On NAS” treatment.

Zebra parity is computed from index (the row’s position in the rendered list), not CSS :nth-child, so interleaved selected / new / tombstone rows never shift the stripe pattern and the server-side re-render stays deterministic. Odd index values (the 2nd, 4th, … rows) are striped, matching the even-row shading in the approved mockup.

The constant border-bottom rule is the caller’s concern; this returns only the state-dependent fragment.

Parameters:
Return type:

str