Skip to content

File browser: extract useSftpTransfers and useElevation hooks from FileBrowserPanel #825

Open

Description

@smart-ssh-planner

Goal

Uploads/downloads with progress and conflicts, and the elevated (sudo) browsing mode, each live in one hook, so their state transitions can be read and tested in isolation.

Context

apps/smart-ssh-community/frontend/src/components/FileBrowserPanel.tsx has 3,634 lines. The component function FileBrowserPanel alone spans lines 206–2845 (logic 206–1646, JSX 1646–2845) with 51 useState, 29 useRef and 23 useEffect. Eight sub-components follow in the same file: FileEntryMenu (:2864), FilePropertiesDialog (:2991), ColumnsMenu (:3050), ChmodDialog (:3114), ChownDialog (:3292), RenamePrompt (:3390, with isValidEntryName :3456), DirectoryMenu (:3463), ColumnResizeHandle (:3552), ElevationFailureDialog (:3577); helpers findMenuTrigger/focusMenuTrigger (:2845–2863), formatMb, localDirName, revealLabelKey (:120–140). Tests: FileBrowserPanel.test.tsx (3,371 lines, 144 tests), FileBrowserPanel.android.test.tsx, FileBrowserPanel.startDirectory.test.tsx. Line numbers are from develop before the colour-token migration and may shift slightly.

Responsibilities to extract (state names as on develop):

  1. Transfers: transfers, uploadConflict, folderConfirm, folderSummary, dragOver, the onSftpTransfer* event subscriptions, cancel, drop and folder upload.
  2. Elevation: elevation, enablingElevation, elevationTargetUser, otherUser*, elevationFailure, elevationWarning, stopPrompt and the calls that enable/disable the elevated channel (about 84 occurrences of "elevat" in the file).

End state of the series: no file over 800 lines, no function component over 400 lines, at most 12 useState per component, sub-components and hooks under src/components/fileBrowser/.

Requirements

  • src/components/fileBrowser/useSftpTransfers.ts: useSftpTransfers(sessionId, …) owns the transfer list, conflicts and event subscriptions; it exposes start/cancel/resolve-conflict functions.
  • src/components/fileBrowser/useElevation.ts: useElevation(sessionId) owns the elevation state, the enable/disable flow, the failure and warning state and the stop prompt for running elevated operations.
  • Event subscriptions keep their exact filter by session id and are cleaned up on unmount; the subscription effect of each hook depends only on the values it really needs.
  • Hook unit tests with renderHook: transfer progress event updates the matching transfer only, cancel, conflict resolution; elevation enable success, enable failure shows the failure state, disable with running operations asks first.

Acceptance Criteria

  • useSftpTransfers and useElevation exist with unit tests (at least the cases listed above).
  • FileBrowserPanel has at most 20 useState calls left.
  • Elevated mode still never applies to a different session than the one it was enabled for (existing tests pass unchanged).
  • The test count of FileBrowserPanel*.test.tsx is not lower than before; all pass.
  • npm run lint, npx vitest run, npm run build and npm run test:e2e pass.

Technical Notes

  • Pure refactoring: no change to behaviour, visible text, i18n keys, CSS classes, data-testids, ARIA attributes, keyboard handling, invoked Tauri commands or listened events. Behaviour changes, if you find a bug, go into a separate issue (mention it in the PR).

  • Colour classes in these files are being migrated to theme tokens in a separate issue that must be merged first; keep exactly the classes that are on develop when you start.

  • Exports that other files or tests import from the original file keep working: either update the importers or re-export from the original path. The extension API (src/extensions/*, src/api.ts, src/components/ui) does not change.

  • Tests: count it(/test( in the listed test files before and after; the number must not decrease. Tests may move next to an extracted unit, but their assertions stay the same. Tests drive the user-visible behaviour through FileBrowserPanel/ChatPanel/ServerForm as today.

  • New code comments in English; existing German comments may move unchanged.

  • No filter, risk, redaction or credential logic is touched (frontend only).

  • Gate: npm run lint, npx vitest run, npm run build in apps/smart-ssh-community/frontend, plus npm run test:e2e if a browser test covers the component.

  • The elevated channel is enforced in the backend; the frontend only requests it. Do not change which commands are invoked with an elevated user or when.

Spec impact: none

Related Work

Activity

  1. added this to the 0.8.0 milestone on Oct 26, 2026
  2. 21 remaining items

  3. marked this as blocking 15 issues on Oct 26, 2026
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

    frontendFrontend (React/TypeScript)

    Type

    Fields

    Priority

    P2 - Normal

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions