Skip to content

File browser: honor mobile access settings and load directories on demand #759

Open

Description

@DodgyBadger

Problem

The file browser has three related usability issues:

  1. Mobile access: enabling File Viewer in header settings does not expose its button on phones. Opening it requires returning to Settings.
  2. Incomplete listings: larger repositories lose files and folders when the recursive listing reaches its shared entry or depth limit. There is no way to retrieve omitted entries.
  3. Hidden-file behavior: enabling Show hidden files can make ordinary entries disappear, giving the impression that it switches to a hidden-files-only view.

Investigation

Phone CSS explicitly hides the File Viewer header button regardless of the enabled setting. An existing policy test enforces this behavior.

The browser currently requests a recursive tree with a depth of five levels and a shared budget of approximately 5,000 files and directories. The server stops scanning when it reaches that budget. Expanding a folder only reveals prefetched children; it does not request missing entries.

Show hidden files already includes both ordinary and hidden entries. However, hidden directories can exhaust the shared budget before ordinary entries are visited.

For example:

.aaa/           # Contains 5,000 files
src/visible.ts
README.md

With hidden files disabled, src/ and README.md appear. Enabling hidden files returns only .aaa/, with the listing marked truncated. Searching for visible.ts also returns no matches and reports truncation.

Proposed behavior

Mobile access

Honor the existing File Viewer header setting on phones. Keep it disabled by default, but allow users who explicitly enable it to open and close the browser directly from the header.

Ensure the browser and its essential controls remain usable within a phone viewport.

Load directories on demand

Replace the recursive preload with lazy directory loading:

  • Opening the browser loads the workspace root’s immediate files and folders.
  • Expanding a folder requests that folder’s immediate children.
  • Each directory request has an independent budget. The size of a subtree cannot consume the budget for root entries or sibling folders.
  • If an individual directory exceeds its request limit, pagination or “Load more” allows users to retrieve its remaining entries.
  • Folders with children that have not been loaded must remain distinguishable from empty folders.

This is a functional change involving both the frontend tree and listing API, proposed for maintainer agreement before implementation. Existing directory exclusions remain unchanged.

Hidden files

Show hidden files should add eligible hidden entries to the current view while preserving access to ordinary entries.

Toggling it should retain applicable expanded folders and the active search query. Directory results must be refreshed or invalidated consistently with the new visibility setting.

Search

Repository-wide search must continue to search folders that have not been expanded.

Search currently shares the recursive scan’s entry and depth limits. Its incomplete results must be clearly identified, with an agreed way to continue or narrow the search. The directory-loading change alone does not resolve search truncation.

Acceptance criteria

Mobile

  • Explicitly enabling File Viewer exposes a usable header button on phones after saving and reloading.
  • The button opens and closes the active session’s file browser without visiting Settings.
  • Disabling the setting hides the button; the phone default remains disabled.
  • Essential browser controls remain visible and usable within the phone viewport.

Directory browsing

  • Opening the browser lists the workspace root’s immediate eligible files and folders.
  • Root entries remain reachable regardless of the size or depth of their descendants.
  • Expanding a folder loads its immediate children on demand.
  • Loading a large folder does not remove or prevent access to root entries or sibling folders.
  • Files deeper than the current five-level preload remain reachable through navigation.
  • An individual directory exceeding its request limit provides a way to retrieve all remaining eligible entries.
  • An unloaded or partially loaded folder is not presented as empty.
  • Requests and responses remain bounded.

Hidden files and request state

  • Enabling hidden files adds eligible hidden entries without making ordinary entries unreachable.
  • The 5,000-file hidden-directory fixture above preserves access to src/visible.ts and README.md.
  • Toggling preserves applicable expanded folders and the active search query.
  • Session changes, refreshes, and rapid toggles cannot display stale results from an earlier request.

Search and compatibility

  • Search includes eligible files in folders that have not been expanded.
  • Incomplete search results are clearly distinguished from a completed search with no matches.
  • The search continuation or narrowing behavior is agreed before implementation.
  • Existing ownership checks, filesystem restrictions, and directory exclusions remain intact.
  • Existing preview and download actions continue to work.

Integration points

Area Existing integration points
Mobile access mobile.css, header markup, settings-ui.js, mobile header policy tests
Directory listing /api/sessions/:id/files in file-routes.ts
Expansion, caching, and request state panels-ui.js
Search Existing q handling and compileFileQuery()
Validation Route tests, hidden-file/search tests, real mobile browser tests

The separate filesystem picker already loads individual directories, but it has different access rules and its own entry cap. Reusing it would require deliberate review.

Scope decisions requested

Before implementation, please confirm:

  1. Approval to honor the explicitly enabled File Viewer header setting on phones.
  2. Agreement with lazy directory loading and per-directory continuation.
  3. The intended repository-wide search behavior when a bounded scan is incomplete.
  4. The expected behavior of the existing Expand all action under lazy loading.

Changing generated-directory exclusions, file editing, preview-content limits, or adding remote filesystem capabilities is outside this proposal.

Investigation evidence

Investigated on v1.47.0 (f1f7eec4). The hidden-directory interaction was reproduced through the actual listing route with a temporary filesystem fixture.

The four focused existing test suites passed: 175 tests. They do not currently cover this large-tree interaction. Mobile visibility was confirmed through CSS and policy tests; a real-browser reproduction remains part of implementation validation.

Activity

  1. Ark0N commented on Nov 5, 2026

    @Ark0N
    Owner

    Thanks for the write-up, this is a good one. Two open PRs already cover a lot of it, so here's where each part stands.

    Hidden entries using up the budget. #614 fixes this. I ran your fixture against it (.aaa/ with 5,000 files, plus src/visible.ts and README.md). With hidden files on, master lists only .aaa/ and a search for visible.ts finds nothing. On the #614 branch the tree shows both files and the search finds it. That PR is waiting on one change, which is also your "not presented as empty" point: folders the scan ran out of budget for get marked instead of looking empty.

    Lazy loading. #633 is a draft that does this. It sits on top of #631, and both need a rebase. It lists one folder per request and fetches a folder when you expand it. It also has a proposal for two of your open questions: typing filters what's already loaded while Enter runs the whole-workspace search, and Expand All only opens folders that are already loaded. I haven't reviewed it yet, so treat those as its proposal rather than a decision. It would be worth checking your acceptance list against it, especially retrieving the rest of a very large folder.

    File Viewer button on phones. mobile.css hides it on phones on purpose, and a test pins that, because the panel was built for desktop. Honoring the setting means changing that policy, so I'll come back to you on this one separately.

    Please hold off on implementing for now, so we don't end up with a third take on the same code.

  2. Ark0N commented on Nov 9, 2026

    @Ark0N
    Owner

    @DodgyBadger, thanks for waiting. Here's where each part stands now, including the two answers I owed you.

    Hidden entries using up the budget: fixed. #614 shipped in 1.49.0. The walk now takes folders in fair rounds, so with your fixture src/visible.ts and README.md stay in the tree with hidden files on and the search finds visible.ts. Folders the scan ran out of budget for are marked incomplete instead of looking empty.

    File Viewer button on phones: yes, as an opt-in. If someone turns File Viewer on in the header settings, the button should show on a phone too. The phone default stays off. The condition is the one in your acceptance list: the panel and its essential controls have to be usable at phone width (around 390px). That means changing the rule in mobile.css and the phone header policy test that pins it, and checking it in a real mobile browser context. Please send it as its own small PR.

    Lazy loading: it's yours if you want it. #633 has been closed (no activity from its author in a month), so you won't be stepping on anyone. Please use it as a reference rather than starting from zero: its lazy=1 listing of one folder per request, the folder path confined through validateSessionFilePath(), folders sent without children meaning "not loaded", and the epoch/owner/showHidden guards that drop a listing landing after a refresh or a session switch.

    On your scope questions 3 and 4, start from #633's answers: typing filters what's already loaded with no request, Enter runs the existing whole-workspace search, and Expand All only opens folders that are already loaded. An incomplete search has to say so plainly, so it never reads as "no matches". If your testing shows a problem with either, say so in the PR and we'll settle it there.

    A few things to carry over from the current walk:

    Two PRs (phone button, then lazy loading) will be quicker to review than one. Thanks again for the write-up, it made all of this easy to decide.

  3. added a commit that references this issue on Nov 12, 2026
  4. Ark0N commented on Nov 12, 2026

    @Ark0N
    Owner

    The phone part shipped today in Codeman 1.51.0 with your #809: the File Viewer header button follows its setting on a phone and stays off until you turn it on. Thanks, @DodgyBadger.

    What is left here is loading directories on demand. That part is still yours if you want it, with the notes above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions