-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbrowser.py
More file actions
164 lines (133 loc) · 4.82 KB
/
browser.py
File metadata and controls
164 lines (133 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""Deck A browser — pure path logic, returns data for JS rendering."""
from pathlib import Path
import state
import constants
import preview
def navigate_to(path_str: str) -> dict[str, any]:
"""Navigate to path and return directory listing for Deck A.
Returns:
{
"current_path": str,
"parent_path": str | None,
"entries": [
{"name": str, "path": str, "type": "up|folder|file",
"checked": bool, "icon": str, "is_audio": bool}
],
"audio_count": int,
}
"""
p = Path(path_str)
if not p.is_dir():
return {"error": "Not a directory", "current_path": path_str, "entries": []}
state.set("active_dir", str(p), push=False)
# Clear name overrides on folder navigation
preview._name_overrides.clear()
# Clear previous selection tracking for this view
# (Keep existing selections — they persist across navigation)
entries = []
audio_count = 0
# Parent entry (up button)
parent = p.parent
if parent != p:
entries.append({
"name": "..",
"path": str(parent),
"type": "up",
"checked": False,
"icon": "↑",
"is_audio": False,
})
# Subdirectories
try:
subdirs = sorted(d for d in p.iterdir()
if d.is_dir() and not d.name.startswith("."))
for d in subdirs:
path_str_d = str(d)
# Auto-select all subdirs on every navigation (matching original behavior)
state._selected_folders.add(path_str_d)
is_checked = True
entries.append({
"name": d.name,
"path": path_str_d,
"type": "folder",
"checked": is_checked,
"icon": "▶",
"is_audio": False,
})
# Leaf directory — no subdirs, include the dir itself
if not subdirs:
state._selected_folders.add(str(p))
except PermissionError:
pass
# Audio files
try:
audio = sorted(f for f in p.iterdir()
if f.is_file() and f.suffix.lower() in constants.AUDIO_EXTS)
for f in audio:
state._selected_folders.add(str(f)) # Add files to selection
entries.append({
"name": f.name,
"path": str(f),
"type": "file",
"checked": True, # Default checked
"icon": "♪",
"is_audio": True,
})
audio_count += 1
except PermissionError:
pass
# Update state
state._state["dir_entries"] = entries
state._state["src_count"] = audio_count
state._sync_selected_folders()
state.push_keys(["dir_entries", "src_count", "selected_folders", "active_dir"])
# Trigger preview refresh
preview.refresh()
return {
"current_path": str(p),
"parent_path": str(parent) if parent != p else None,
"entries": entries,
"audio_count": audio_count,
}
def toggle_folder(path: str, checked: bool) -> None:
"""Toggle folder selection state."""
if checked:
state._selected_folders.add(path)
else:
state._selected_folders.discard(path)
# Update the dir_entries checked state
for entry in state._state.get("dir_entries", []):
if entry.get("path") == path:
entry["checked"] = checked
break
state._sync_selected_folders()
state.push_keys(["selected_folders", "dir_entries"])
preview.refresh()
def select_all_visible() -> None:
"""Select all visible folders and files."""
for entry in state._state.get("dir_entries", []):
if entry.get("type") in ("folder", "file"):
entry["checked"] = True
state._selected_folders.add(entry["path"])
state._sync_selected_folders()
state.push_keys(["selected_folders", "dir_entries"])
preview.refresh()
def deselect_all_visible() -> None:
"""Deselect all visible folders and files."""
for entry in state._state.get("dir_entries", []):
if entry.get("type") in ("folder", "file"):
entry["checked"] = False
state._selected_folders.discard(entry["path"])
state._sync_selected_folders()
state.push_keys(["selected_folders", "dir_entries"])
preview.refresh()
def get_selected_folders() -> list[str]:
"""Return list of selected folder paths."""
return list(state._selected_folders)
def clear_selection() -> None:
"""Clear all folder selections."""
state._selected_folders.clear()
for entry in state._state.get("dir_entries", []):
entry["checked"] = False
state._sync_selected_folders()
state.push_keys(["selected_folders", "dir_entries"])