diff --git a/frontend.html b/frontend.html index 2375a3d..9d2b1d1 100644 --- a/frontend.html +++ b/frontend.html @@ -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'); } }); diff --git a/main.py b/main.py index a9f8275..69516fc 100644 --- a/main.py +++ b/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'{part}') lines.append("") - 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'
' + f'📁 {folder}' + f"
" + ) - for folder in sorted(folders): - folder_path = f"{prefix}{folder}/" if prefix else f"{folder}/" - result.append( - f'
' - f'{indent}📁 {folder}' - f"
" - ) - 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'
' + f'📄 {file}' + f"
" + ) - 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'
' - f'{indent}📄 {file}' - f"
" - ) - - 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, ) diff --git a/tests/test_navigate.py b/tests/test_navigate.py index 167f43b..4449534 100644 --- a/tests/test_navigate.py +++ b/tests/test_navigate.py @@ -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