fix(app): restore file tree layout

Restore the established tree rails while retaining file actions. Keep Escape local to generic editable fields so cancelling a file draft cannot interrupt an agent.
This commit is contained in:
Mohamed Boudra
2026-08-12 15:54:11 +02:00
parent 124e512b58
commit 474b4e70b4
9 changed files with 101 additions and 68 deletions
@@ -27,15 +27,7 @@ import { StyleSheet, useUnistyles, withUnistyles } from "react-native-unistyles"
import { useIsCompactFormFactor, WORKSPACE_SECONDARY_HEADER_HEIGHT } from "@/constants/layout";
import { isWeb } from "@/constants/platform";
import * as Clipboard from "expo-clipboard";
import {
ChevronDown,
Eye,
EyeOff,
FilePlus,
Folder,
FolderPlus,
RotateCw,
} from "lucide-react-native";
import { ChevronDown, Eye, EyeOff, FilePlus, FolderPlus, RotateCw } from "lucide-react-native";
import { MaterialFileIcon } from "@/components/material-file-icon";
import {
TreeChevron,
@@ -89,7 +81,6 @@ const SORT_OPTIONS: { value: SortOption }[] = [
];
const ThemedLoadingSpinner = withUnistyles(LoadingSpinner);
const ThemedFolder = withUnistyles(Folder);
const foregroundMutedColorMapping = (theme: Theme) => ({
color: theme.colors.foregroundMuted,
});
@@ -213,12 +204,9 @@ function EntryNameInputRow({
<View style={[styles.entryRow, { paddingLeft: treeRowPaddingLeft(depth) }]}>
<TreeIndentGuides depth={depth} />
<View style={styles.entryInfo}>
<View style={styles.entryChevron}>
{kind === "directory" ? <TreeChevron expanded={false} /> : null}
</View>
<View style={styles.entryIcon}>
{kind === "directory" ? (
<ThemedFolder size={WORKSPACE_TREE_ICON_SIZE} uniProps={foregroundMutedColorMapping} />
<TreeChevron expanded={false} />
) : (
<MaterialFileIcon fileName={name || "untitled"} size={WORKSPACE_TREE_ICON_SIZE} />
)}
@@ -237,6 +225,7 @@ function EntryNameInputRow({
}
autoCapitalize="none"
autoCorrect={false}
placeholderTextColor={styles.draftPlaceholder.color}
style={styles.draftInput}
selectTextOnFocus={Boolean(initialName)}
testID="file-explorer-name-input"
@@ -381,15 +370,9 @@ function TreeRowItem({
>
<TreeIndentGuides depth={depth} />
<View ref={dragSourceRef} style={styles.entryInfo}>
<View style={styles.entryChevron}>
{isDirectory ? <DirectoryChevronIcon loading={loading} expanded={isExpanded} /> : null}
</View>
<View style={styles.entryIcon}>
{isDirectory ? (
<ThemedFolder
size={WORKSPACE_TREE_ICON_SIZE}
uniProps={foregroundMutedColorMapping}
/>
<DirectoryChevronIcon loading={loading} expanded={isExpanded} />
) : (
<MaterialFileIcon fileName={entry.name} size={WORKSPACE_TREE_ICON_SIZE} />
)}
@@ -1772,13 +1755,6 @@ const styles = StyleSheet.create((theme) => ({
gap: WORKSPACE_TREE_ICON_LABEL_GAP,
minWidth: 0,
},
entryChevron: {
width: WORKSPACE_TREE_ICON_SIZE,
height: WORKSPACE_TREE_ICON_SIZE,
alignItems: "center",
justifyContent: "center",
flexShrink: 0,
},
entryIcon: {
width: WORKSPACE_TREE_ICON_SIZE,
height: WORKSPACE_TREE_ICON_SIZE,
@@ -1799,6 +1775,9 @@ const styles = StyleSheet.create((theme) => ({
paddingVertical: 0,
paddingHorizontal: 0,
},
draftPlaceholder: {
color: theme.colors.foregroundExtraMuted,
},
contextMetaBlock: {
paddingVertical: theme.spacing[1],
},
@@ -10,22 +10,22 @@ import { inlineUnistylesStyle } from "@/styles/unistyles-inline-style";
// paths) render different data, but their ROWS should look identical — same
// indentation, guide lines, and chevron. Keep those here so the two trees can't
// drift apart.
export const TREE_INDENT_PER_LEVEL = 14;
export const WORKSPACE_FILE_ROW_VERTICAL_PADDING = SPACING[1];
export const WORKSPACE_TREE_ICON_SIZE = 14;
export const WORKSPACE_TREE_LOADING_ICON_SIZE = 12;
export const WORKSPACE_TREE_ICON_LABEL_GAP = SPACING[1];
export const TREE_INDENT_PER_LEVEL = 16;
export const WORKSPACE_FILE_ROW_VERTICAL_PADDING = SPACING[1.5];
export const WORKSPACE_TREE_ICON_SIZE = 16;
export const WORKSPACE_TREE_LOADING_ICON_SIZE = 14;
export const WORKSPACE_TREE_ICON_LABEL_GAP = SPACING[2];
/**
* Trailing glyph rail shared with the explorer X and Changes options chevron.
* The extra 2px is optical: text ink ends inside its layout box, while the
* header icons' strokes extend to theirs.
*/
export const WORKSPACE_FILE_ROW_TRAILING_PADDING = SPACING[3] + 2;
export const WORKSPACE_FILE_ROW_TRAILING_PADDING = SPACING[4] + 2;
/** Left padding for a tree row at `depth`. Shared by folder rows and file headers
* in the Changes tree so their indentation can't drift apart. */
export function treeRowPaddingLeft(depth: number): number {
return SPACING[2] + depth * TREE_INDENT_PER_LEVEL;
return SPACING[3] + depth * TREE_INDENT_PER_LEVEL;
}
const foregroundExtraMutedIconColorMapping = (theme: Theme) => ({
@@ -46,7 +46,7 @@ export function TreeIndentGuides({ depth }: { depth: number }) {
key: index,
style: [
styles.indentGuide,
inlineUnistylesStyle({ left: SPACING[2] + index * TREE_INDENT_PER_LEVEL + 3 }),
inlineUnistylesStyle({ left: SPACING[3] + index * TREE_INDENT_PER_LEVEL + 4 }),
],
})),
[depth],