feat: hide dotfiles in file explorer (#1516)

* feat: hide dotfiles in file explorer

* refactor: rename to "hidden files" and read flag from store

Rename the explorer dotfile toggle to show-semantics "hidden files"
so copy and code share one cross-platform vocabulary, and stop
prop-drilling the flag now that it lives in the panel store.

- explorerShowHiddenFiles (default true) replaces explorerHideDotFiles;
  i18n keys + translations switched from "dotfiles" to "hidden files"
- imperative helpers read usePanelStore.getState() instead of taking
  the flag as a parameter; flag stays threaded only through the
  reactive tree-row render path
- drop dead usePanelState exposure; collapse migration double-guard

* fix: address Greptile review on hidden-file path matching

- isHiddenExplorerPath no longer treats ".." segments as hidden
  (only "." was exempt before); add tests for ".." and "../sibling"
- assert the showHiddenFiles i18n key alongside hideHiddenFiles

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
Yurui Zhou
2026-06-15 12:28:17 +08:00
committed by GitHub
co-authored by Mohamed Boudra
parent f4450cda51
commit eb94b70848
13 changed files with 230 additions and 51 deletions
+7 -1
View File
@@ -75,6 +75,7 @@ export interface PanelState {
sidebarWidth: number;
explorerWidth: number;
explorerSortOption: SortOption;
explorerShowHiddenFiles: boolean;
explorerFilesSplitRatio: number;
// Actions
@@ -101,6 +102,7 @@ export interface PanelState {
setSidebarWidth: (width: number) => void;
setExplorerWidth: (width: number) => void;
setExplorerSortOption: (option: SortOption) => void;
toggleExplorerShowHiddenFiles: () => void;
setExplorerFilesSplitRatio: (ratio: number) => void;
}
@@ -127,6 +129,7 @@ export const usePanelStore = create<PanelState>()(
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
explorerWidth: DEFAULT_EXPLORER_SIDEBAR_WIDTH,
explorerSortOption: "name",
explorerShowHiddenFiles: true,
explorerFilesSplitRatio: DEFAULT_EXPLORER_FILES_SPLIT_RATIO,
toggleFocusMode: () =>
@@ -262,6 +265,8 @@ export const usePanelStore = create<PanelState>()(
setSidebarWidth: (width) => set({ sidebarWidth: clampSidebarWidth(width) }),
setExplorerWidth: (width) => set({ explorerWidth: clampExplorerWidth(width) }),
setExplorerSortOption: (option) => set({ explorerSortOption: option }),
toggleExplorerShowHiddenFiles: () =>
set((state) => ({ explorerShowHiddenFiles: !state.explorerShowHiddenFiles })),
setExplorerFilesSplitRatio: (ratio) =>
set({
explorerFilesSplitRatio: Number.isFinite(ratio)
@@ -271,7 +276,7 @@ export const usePanelStore = create<PanelState>()(
}),
{
name: "panel-state",
version: 10,
version: 11,
storage: createJSONStorage(() => AsyncStorage),
migrate: (persistedState, version) =>
migratePanelState(persistedState, version, { isWeb }) as unknown as PanelState,
@@ -285,6 +290,7 @@ export const usePanelStore = create<PanelState>()(
sidebarWidth: state.sidebarWidth,
explorerWidth: state.explorerWidth,
explorerSortOption: state.explorerSortOption,
explorerShowHiddenFiles: state.explorerShowHiddenFiles,
explorerFilesSplitRatio: state.explorerFilesSplitRatio,
}),
},
@@ -7,6 +7,7 @@ import {
import {
buildOpenFileExplorerPatch,
buildToggleFileExplorerPatch,
migratePanelState,
selectIsAgentListOpen,
selectIsFileExplorerOpen,
selectPanelVisibility,
@@ -96,6 +97,14 @@ describe("panel-store explorer tab resolution", () => {
});
});
describe("panel-store migration", () => {
it("defaults hidden-file visibility to showing hidden files", () => {
const state = migratePanelState({}, 10, { isWeb: false });
expect(state.explorerShowHiddenFiles).toBe(true);
});
});
describe("panel-store visibility selectors", () => {
it("uses mobileView for compact layout visibility", () => {
const state = makePanelState({
@@ -245,6 +245,9 @@ export function migratePanelState(
) {
state.diffExpandedPathsByWorkspace = {};
}
if (typeof state.explorerShowHiddenFiles !== "boolean") {
state.explorerShowHiddenFiles = true;
}
return state;
}