Add search (Ctrl+F, wildcards, match case/whole word) and sort, both off by default

This commit is contained in:
sarah committed 2026-09-29 19:59:02 +02:00
1 parent 6c48796dde
commit 1c2acf3f16
5 files changed
+249 -5

No files matched your search

+56 -1
View File
@@ -29,10 +29,12 @@ class Sidebar(ft.Container):
OnNavigate: Callable[[Path], None],
Config: AppConfig,
OnFilesMoved: Optional[Callable[[], None]] = None,
OnSortChanged: Optional[Callable[[], None]] = None,
):
self.OnNavigate = OnNavigate
self.Config = Config
self.OnFilesMoved = OnFilesMoved
self.OnSortChanged = OnSortChanged
self.LocationTiles: dict[Path, Callable[[bool], None]] = {}
self.BookmarksListView: Optional[ft.ReorderableListView] = None
self.DevicesView: Optional[DevicesPanel] = None
@@ -46,6 +48,11 @@ class Sidebar(ft.Container):
BookmarksBox: Optional[ft.Container] = None
DevicesBox: Optional[ft.Container] = None
if Config.ShowSort:
Sections.append(self._BuildSortControl())
if Config.ShowBookmarks or Config.ShowDevices or Config.ShowFiletree:
Sections.append(ft.Divider(height=1, color=Palette.Surface1))
if Config.ShowBookmarks:
self.BookmarksListView = ft.ReorderableListView(
controls=self._BuildBookmarkTiles(),
@@ -104,7 +111,55 @@ class Sidebar(ft.Container):
border=Border,
)
DefaultSectionHeight = 150 # starting point for a drag when a section had no explicit height yet
SortFields = ("Name", "Size", "Modified", "Type")
def _BuildSortControl(self) -> ft.Control:
""""[Sort: Name] v" — a dropdown for the field — plus a separate
ascending/descending arrow button to its right that flips on click
(Features/Major: search + sort). Directories always sort before
files regardless of field/direction — see Browser._SortEntries."""
FieldButton = ft.PopupMenuButton(
content=ft.Row(
[
ft.Text(f"Sort: {self.Config.SortField}", size=13),
ft.Icon(ft.Icons.ARROW_DROP_DOWN, size=18, color=Palette.Overlay0),
],
spacing=2,
tight=True,
),
items=[
ft.PopupMenuItem(content=Field, on_click=lambda e, F=Field: self._OnSortFieldChosen(F))
for Field in self.SortFields
],
)
self.SortFieldButton = FieldButton
self.SortDirectionButton = ft.IconButton(
icon=ft.Icons.ARROW_DROP_UP if self.Config.SortAscending else ft.Icons.ARROW_DROP_DOWN,
tooltip="Ascending" if self.Config.SortAscending else "Descending",
icon_size=20,
on_click=self._OnSortDirectionToggled,
)
return ft.Container(
content=ft.Row([FieldButton, self.SortDirectionButton], spacing=0),
padding=ft.Padding.symmetric(horizontal=4, vertical=2),
)
def _OnSortFieldChosen(self, Field: str) -> None:
self.Config.SortField = Field
self.Config.Save()
self.SortFieldButton.content.controls[0].value = f"Sort: {Field}"
self.SortFieldButton.update()
if self.OnSortChanged:
self.OnSortChanged()
def _OnSortDirectionToggled(self, Event: ft.ControlEvent) -> None:
self.Config.SortAscending = not self.Config.SortAscending
self.Config.Save()
self.SortDirectionButton.icon = ft.Icons.ARROW_DROP_UP if self.Config.SortAscending else ft.Icons.ARROW_DROP_DOWN
self.SortDirectionButton.tooltip = "Ascending" if self.Config.SortAscending else "Descending"
self.SortDirectionButton.update()
if self.OnSortChanged:
self.OnSortChanged()
def _BuildSectionDivider(self, Box: ft.Container, MaxHeightAttr: str) -> ft.Control:
"""A resize handle for the section above it (Box) — drags resize that