Fix navigation to not display the whole structure, just the current root.
This commit is contained in:
parent
b8947af2db
commit
eaf574231c
@ -51,7 +51,7 @@
|
||||
padding: 10px;
|
||||
}
|
||||
.play-btn:hover { color: rgba(255, 255, 255, 1); transform: scale(1.1); }
|
||||
/q .hidden { display: none; }
|
||||
.hidden { display: none; }
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@ -72,6 +72,7 @@
|
||||
display: block;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
text-wrap-mode: nowrap;
|
||||
}
|
||||
#sidebar a:hover {
|
||||
background: #3a3a3a;
|
||||
@ -185,6 +186,7 @@
|
||||
}
|
||||
} else if (e.key.toLowerCase() === 'i') {
|
||||
document.getElementById('sidebar').classList.toggle('hidden');
|
||||
document.getElementById('sidebar-toggle').classList.toggle('collapsed');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
97
main.py
97
main.py
@ -705,7 +705,7 @@ def _render_folder_index_html(
|
||||
current_order: str | None = None,
|
||||
current_delay: int | None = None,
|
||||
) -> str:
|
||||
"""Render a folder index sidebar showing the full tree from root.
|
||||
"""Render a folder index sidebar showing only the current folder's contents.
|
||||
|
||||
Args:
|
||||
current_path: The currently viewed file path (for highlighting).
|
||||
@ -716,6 +716,30 @@ def _render_folder_index_html(
|
||||
HTML string for the folder index sidebar.
|
||||
"""
|
||||
all_paths = _collect_zip_paths()
|
||||
|
||||
# Determine the folder to display:
|
||||
# - None/"" → root
|
||||
# - ends with "/" → that folder
|
||||
# - file path → parent folder
|
||||
if not current_path:
|
||||
folder_prefix = ""
|
||||
elif current_path.endswith("/"):
|
||||
folder_prefix = current_path
|
||||
else:
|
||||
# current_path is a file — show its parent folder
|
||||
slash_idx = current_path.rfind("/")
|
||||
folder_prefix = current_path[: slash_idx + 1] if slash_idx >= 0 else ""
|
||||
|
||||
folders: set[str] = set()
|
||||
files: set[str] = set()
|
||||
for p in all_paths:
|
||||
if p.startswith(folder_prefix):
|
||||
remainder = p[len(folder_prefix) :]
|
||||
if "/" in remainder:
|
||||
folders.add(remainder.split("/", 1)[0])
|
||||
else:
|
||||
files.add(remainder)
|
||||
|
||||
lines: list[str] = []
|
||||
|
||||
# Breadcrumb
|
||||
@ -729,63 +753,40 @@ def _render_folder_index_html(
|
||||
lines.append(f'<a href="{root_path}/navigate/{accumulated}">{part}</a>')
|
||||
lines.append("</nav>")
|
||||
|
||||
def _render_folder(folder_prefix: str, depth: int = 0) -> list[str]:
|
||||
"""Recursively render a folder's contents."""
|
||||
result: list[str] = []
|
||||
indent = " " * depth
|
||||
prefix = folder_prefix or ""
|
||||
href_params = ""
|
||||
if current_order is not None and current_delay is not None:
|
||||
href_params = f"?order={current_order}&delay={current_delay}"
|
||||
|
||||
folders: set[str] = set()
|
||||
files: set[str] = set()
|
||||
for p in all_paths:
|
||||
if p.startswith(prefix):
|
||||
remainder = p[len(prefix) :]
|
||||
if "/" in remainder:
|
||||
folders.add(remainder.split("/", 1)[0])
|
||||
else:
|
||||
files.add(remainder)
|
||||
for folder in sorted(folders):
|
||||
folder_path = f"{folder_prefix}{folder}/" if folder_prefix else f"{folder}/"
|
||||
lines.append(
|
||||
f'<div class="index-item folder">'
|
||||
f'<a href="{root_path}/navigate/{folder_path}">📁 {folder}</a>'
|
||||
f"</div>"
|
||||
)
|
||||
|
||||
for folder in sorted(folders):
|
||||
folder_path = f"{prefix}{folder}/" if prefix else f"{folder}/"
|
||||
result.append(
|
||||
f'<div class="index-item folder">'
|
||||
f'{indent}<a href="{root_path}/navigate/{folder_path}">📁 {folder}</a>'
|
||||
f"</div>"
|
||||
)
|
||||
result.extend(_render_folder(folder_path, depth + 1))
|
||||
for file in sorted(files):
|
||||
file_path = f"{folder_prefix}{file}" if folder_prefix else file
|
||||
is_current = file_path == current_path
|
||||
cls = "index-item file current" if is_current else "index-item file"
|
||||
lines.append(
|
||||
f'<div class="{cls}">'
|
||||
f'<a href="{root_path}/navigate/{file_path}{href_params}">📄 {file}</a>'
|
||||
f"</div>"
|
||||
)
|
||||
|
||||
for file in sorted(files):
|
||||
file_path = f"{prefix}{file}" if prefix else file
|
||||
is_current = file_path == current_path
|
||||
cls = "index-item file current" if is_current else "index-item file"
|
||||
href_params = ""
|
||||
if current_order is not None and current_delay is not None:
|
||||
href_params = f"?order={current_order}&delay={current_delay}"
|
||||
result.append(
|
||||
f'<div class="{cls}">'
|
||||
f'{indent}<a href="{root_path}/navigate/{file_path}{href_params}">📄 {file}</a>'
|
||||
f"</div>"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
lines.extend(_render_folder(""))
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _render_folder_index_page(
|
||||
path: str,
|
||||
folders: list[str],
|
||||
files: list[str],
|
||||
current_order: str | None = None,
|
||||
current_delay: int | None = None,
|
||||
) -> HTMLResponse:
|
||||
"""Render a folder index page showing subfolders and files.
|
||||
"""Render a folder index page showing the current folder's contents.
|
||||
|
||||
Args:
|
||||
path: The folder path (e.g., 'folder/').
|
||||
folders: List of subfolder names.
|
||||
files: List of file names.
|
||||
current_order: Current navigation order.
|
||||
current_delay: Current navigation delay.
|
||||
|
||||
@ -797,8 +798,10 @@ def _render_folder_index_page(
|
||||
|
||||
template = string.Template(content)
|
||||
|
||||
# Build folder index sidebar HTML using recursive tree renderer
|
||||
folder_path = path.rstrip("/") or None
|
||||
# Build folder index sidebar HTML showing current folder contents
|
||||
folder_path = path.rstrip("/")
|
||||
if folder_path:
|
||||
folder_path += "/"
|
||||
folder_index_html = _render_folder_index_html(
|
||||
current_path=folder_path,
|
||||
current_order=current_order,
|
||||
@ -856,8 +859,6 @@ async def navigate_page(
|
||||
raise HTTPException(status_code=404, detail="File not found")
|
||||
return _render_folder_index_page(
|
||||
path if path else "/",
|
||||
folders,
|
||||
files,
|
||||
current_order=order,
|
||||
current_delay=delay,
|
||||
)
|
||||
|
||||
@ -115,14 +115,17 @@ class TestNavigatePage:
|
||||
assert "/navigate/folder/deep.txt" in response.text
|
||||
assert "/navigate/folder/image.png" in response.text
|
||||
|
||||
async def test_subfolder_index_shows_full_tree(
|
||||
async def test_subfolder_index_shows_only_current_folder(
|
||||
self, client_zip_navigate: AsyncClient
|
||||
) -> None:
|
||||
"""Subfolder index sidebar shows full tree from root."""
|
||||
"""Subfolder index shows only that folder's contents, not the full tree."""
|
||||
response = await client_zip_navigate.get("/navigate/folder/")
|
||||
assert response.status_code == 200
|
||||
# Should still show root-level items in the tree
|
||||
assert "/navigate/top.txt" in response.text
|
||||
# Should show folder's own files
|
||||
assert "/navigate/folder/deep.txt" in response.text
|
||||
assert "/navigate/folder/image.png" in response.text
|
||||
# Should NOT show root-level items
|
||||
assert "/navigate/top.txt" not in response.text
|
||||
|
||||
async def test_file_page_has_sidebar(
|
||||
self, client_zip_navigate: AsyncClient
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user