mirror of
https://git.srhtnin.garden/sarah/SaraFem.git
synced 2026-10-14 18:18:12 +02:00
List view metadata columns and drag-to-resize everywhere
- New optional list-view columns: Description, Size (now includes directories), Modified, Owner, Created (via statx birth time), Content (item/line count or image dimensions), Access (rwx) - Drag-to-resize: list view column headers, sidebar sections (Bookmarks/ Devices/Filetree), Preview/Tags split, and the sidebar/preview side panels themselves — all commit to Config on release, not per drag frame - Column resizing mutates existing row cells live instead of rebuilding, with metadata cached per (file, mtime) — fixes lag in large folders - Fix list view background click (rows were full ListTile width with no empty space to click); bookmark selected-background now covers the triple-dot menu too; batch rename/new-file dialogs pre-select their default text instead of just pre-filling it - Toolbar scrolls instead of clipping when buttons don't fit; toolbar and breadcrumbs are independently toggleable - Add a "Server" bookmark icon Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
a5f5c5ca79
commit
31b6c554e6
6 files changed
+699
-89
No files matched your search
@@ -9,6 +9,7 @@ import shutil
|
||||
import subprocess
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
import flet as ft
|
||||
import toml
|
||||
@@ -170,6 +171,27 @@ class AppConfig:
|
||||
|
||||
ShowDotfiles: bool = True
|
||||
ViewMode: str = "list" # "list" or "grid"
|
||||
# List view: which metadata columns show, beyond the always-present Name.
|
||||
ListShowDescription: bool = False
|
||||
ListShowSize: bool = True
|
||||
ListShowModified: bool = True
|
||||
ListShowOwner: bool = False
|
||||
ListShowCreated: bool = False
|
||||
ListShowContent: bool = False
|
||||
ListShowAccess: bool = False
|
||||
# List view column widths — drag the header dividers to set these, or
|
||||
# type a number in Options; both write here.
|
||||
ListWidthName: int = 220
|
||||
ListWidthDescription: int = 90
|
||||
ListWidthSize: int = 80
|
||||
ListWidthModified: int = 130
|
||||
ListWidthOwner: int = 90
|
||||
ListWidthCreated: int = 130
|
||||
ListWidthContent: int = 90
|
||||
ListWidthAccess: int = 60
|
||||
# Grid view.
|
||||
GridIconSize: int = 64
|
||||
GridNameBelowIcon: bool = True
|
||||
|
||||
# Batch-rename pattern for multi-select rename, syntax modeled on
|
||||
# SaraSortd's own placeholder characters (see ~/Applications/SaraSortd's
|
||||
@@ -403,6 +425,46 @@ def ApplyHeightBounds(Content: ft.Control, MinHeight: int, MaxHeight: int) -> ft
|
||||
return Content
|
||||
|
||||
|
||||
def ResizeHandle(
|
||||
Axis: str,
|
||||
Length: Optional[int],
|
||||
OnDrag: Callable[[float], None],
|
||||
OnDragEnd: Callable[[], None],
|
||||
) -> ft.GestureDetector:
|
||||
"""A thin draggable divider, shared by the file list's column headers,
|
||||
the sidebar/preview section splits, and the sidebar/preview *panel*
|
||||
widths. "horizontal" resizes side-by-side things (drag left/right, e.g.
|
||||
a column or a whole side panel) and needs Length = the row's height, not
|
||||
just 6px wide with an unset (collapses to zero) height; "vertical"
|
||||
resizes stacked things (drag up/down, e.g. Bookmarks vs Devices) and
|
||||
needs Length = the panel's width, for the same reason on the other axis.
|
||||
Pass Length=None instead when the immediate parent Row/Column already
|
||||
stretches its children on that cross axis (confirmed, not assumed —
|
||||
Flet doesn't do this by default) — then an explicit value would fight
|
||||
that stretch instead of matching it. OnDrag fires with the incremental
|
||||
delta on every move — cheap for a single header cell or a sidebar
|
||||
section, but callers with many redraws to do (the file list's rows)
|
||||
should treat it as a live *preview* and do the expensive rebuild in
|
||||
OnDragEnd instead, which fires once on release; that's also where
|
||||
Config gets saved, so a drag isn't disk I/O on every pixel of movement."""
|
||||
IsHorizontal = Axis == "horizontal"
|
||||
Handle = ft.GestureDetector(
|
||||
content=ft.Container(
|
||||
width=6 if IsHorizontal else Length,
|
||||
height=Length if IsHorizontal else 6,
|
||||
bgcolor=Palette.Surface1,
|
||||
),
|
||||
mouse_cursor=ft.MouseCursor.RESIZE_COLUMN if IsHorizontal else ft.MouseCursor.RESIZE_ROW,
|
||||
)
|
||||
if IsHorizontal:
|
||||
Handle.on_horizontal_drag_update = lambda e: OnDrag(e.primary_delta or 0)
|
||||
Handle.on_horizontal_drag_end = lambda e: OnDragEnd()
|
||||
else:
|
||||
Handle.on_vertical_drag_update = lambda e: OnDrag(e.primary_delta or 0)
|
||||
Handle.on_vertical_drag_end = lambda e: OnDragEnd()
|
||||
return Handle
|
||||
|
||||
|
||||
# The group tag shared by every Draggable source and DragTarget in the app,
|
||||
# so bookmarks/filetree only accept drops that actually originate from
|
||||
# SaraFem's own file list (not, say, a Chip or some future draggable widget).
|
||||
|
||||
Reference in new issue
Block a user