fix(app): polish workspace navigation surfaces

Use mobile action sheets and long-press file menus while preserving provider context across sheet portals. Keep sidebar and file-pane glyphs on shared visual rails, avoid scrollbar layout shifts, and hide keyboard affordances where shortcuts are unavailable.
This commit is contained in:
Mohamed Boudra
2026-08-03 21:40:21 +02:00
parent ab8151d33f
commit a361d1cb2f
37 changed files with 1153 additions and 208 deletions
@@ -12,7 +12,7 @@ import {
type ViewStyle,
} from "react-native";
import { StyleSheet, useUnistyles, withUnistyles } from "react-native-unistyles";
import { WORKSPACE_SECONDARY_HEADER_HEIGHT } from "@/constants/layout";
import { useIsCompactFormFactor, WORKSPACE_SECONDARY_HEADER_HEIGHT } from "@/constants/layout";
import * as Clipboard from "expo-clipboard";
import { ChevronDown, Eye, EyeOff, RotateCw } from "lucide-react-native";
import { MaterialFileIcon } from "@/components/material-file-icon";
@@ -20,9 +20,14 @@ import {
TreeChevron,
TreeIndentGuides,
treeRowPaddingLeft,
WORKSPACE_FILE_ROW_TRAILING_PADDING,
WORKSPACE_FILE_ROW_VERTICAL_PADDING,
} from "@/components/tree-primitives";
import { LoadingSpinner } from "@/components/ui/loading-spinner";
import {
useOverlayFlatListScrollbar,
type OverlayFlatListScrollbar,
} from "@/components/ui/overlay-scrollbar/use-overlay-flat-list-scrollbar";
import type { Theme } from "@/styles/theme";
import type {
AgentFileExplorerState,
@@ -174,12 +179,7 @@ function TreeRowItem({
return (
<ContextMenu>
<ContextMenuTrigger
enabledOnMobile={false}
onPress={handlePress}
style={pressableStyle}
testID={testID}
>
<ContextMenuTrigger onPress={handlePress} style={pressableStyle} testID={testID}>
<TreeIndentGuides depth={depth} />
<View ref={dragSourceRef} style={styles.entryInfo}>
<View style={styles.entryIcon}>
@@ -226,6 +226,7 @@ export function FileExplorerPane({
onAddToChat,
}: FileExplorerPaneProps) {
const { t } = useTranslation();
const isCompact = useIsCompactFormFactor();
const normalizedWorkspaceRoot = useMemo(() => workspaceRoot.trim(), [workspaceRoot]);
const workspaceStateKey = useMemo(
@@ -278,6 +279,7 @@ export function FileExplorerPane({
);
const treeListRef = useRef<FlatList<ExplorerTreeRow>>(null);
const scrollbar = useOverlayFlatListScrollbar(treeListRef, { enabled: !isCompact });
const hasInitializedRef = useRef(false);
@@ -518,6 +520,7 @@ export function FileExplorerPane({
currentSortLabel={currentSortLabel}
isRefreshFetching={isRefreshFetching}
treeListRef={treeListRef}
scrollbar={scrollbar}
renderTreeRow={renderTreeRow}
handleSortCycle={handleSortCycle}
handleToggleHiddenFiles={handleToggleHiddenFiles}
@@ -539,6 +542,7 @@ interface FileExplorerPaneContentProps {
currentSortLabel: string;
isRefreshFetching: boolean;
treeListRef: RefObject<FlatList<ExplorerTreeRow> | null>;
scrollbar: OverlayFlatListScrollbar;
renderTreeRow: (info: ListRenderItemInfo<ExplorerTreeRow>) => ReactElement;
handleSortCycle: () => void;
handleToggleHiddenFiles: () => void;
@@ -560,6 +564,7 @@ function FileExplorerPaneContent(props: FileExplorerPaneContentProps) {
currentSortLabel,
isRefreshFetching,
treeListRef,
scrollbar,
renderTreeRow,
handleSortCycle,
handleToggleHiddenFiles,
@@ -682,12 +687,17 @@ function FileExplorerPaneContent(props: FileExplorerPaneContentProps) {
keyExtractor={treeRowKeyExtractor}
testID="file-explorer-tree-scroll"
contentContainerStyle={styles.entriesContent}
showsVerticalScrollIndicator
onLayout={scrollbar.onLayout}
onScroll={scrollbar.onScroll}
onContentSizeChange={scrollbar.onContentSizeChange}
scrollEventThrottle={16}
showsVerticalScrollIndicator={!scrollbar.enabled}
initialNumToRender={24}
maxToRenderPerBatch={40}
windowSize={12}
/>
)}
{treeRows.length > 0 ? scrollbar.overlay : null}
</View>
);
}
@@ -1055,7 +1065,7 @@ const styles = StyleSheet.create((theme) => ({
alignItems: "center",
justifyContent: "space-between",
paddingVertical: WORKSPACE_FILE_ROW_VERTICAL_PADDING,
paddingRight: theme.spacing[3],
paddingRight: WORKSPACE_FILE_ROW_TRAILING_PADDING,
},
entryRowActive: {
backgroundColor: theme.colors.surfaceSidebarHover,