Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fine-aliens-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@1git/gpuix": minor
---

Add consistent List and Tree file navigation across Changes, History, Stashes, Graph, and comparisons, with folder inclusion and a remembered layout preference. Use a compact icon toggle beside Search and Refresh in Changes and in each saved-file pane header. Reveal truncated file and folder labels on hover or keyboard focus with the same sliding text as workspace tabs, without text tooltips.
Binary file added .github/assets/tree-view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 20 additions & 6 deletions apps/gpuix/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ import {
import { useWorkspaceSession } from "./feature/workspace-tabs/hooks/use-workspace-session";

import { RepositoryNavigation } from "./feature/repository-workspace/components/repository-navigation";
import {
RepositoryFileViewProvider,
useRepositoryFileLayout,
} from "./feature/repository-workspace/components/repository-file-view";
import { RepositoryFileActions } from "./feature/repository-workspace/lib/repository-file-actions";
import { RepositoryDiffEmpty } from "./feature/repository-workspace/components/repository-diff-empty";
import { RepositoryDiff } from "./feature/repository-workspace/components/repository-diff";
Expand Down Expand Up @@ -213,11 +217,15 @@ export function App({

return (
<AppThemeContext value={theme}>
<AiProvider service={ai}>
<MachineContext value={props.machines ?? Machines.shared}>
<AppContent {...props} />
</MachineContext>
</AiProvider>
<RepositoryFileViewProvider
initialLayout={props.initialSession?.fileListLayout}
>
<AiProvider service={ai}>
<MachineContext value={props.machines ?? Machines.shared}>
<AppContent {...props} />
</MachineContext>
</AiProvider>
</RepositoryFileViewProvider>
</AppThemeContext>
);
}
Expand Down Expand Up @@ -663,6 +671,8 @@ function AppContent({
(tab) => tab.id === onboardingId
)?.workspace;

const { layout: fileListLayout } = useRepositoryFileLayout();

const session = useWorkspaceSession(
state,
saveSession,
Expand All @@ -678,7 +688,8 @@ function AppContent({
theme.smoothTransitions,
theme.showScrollbars,
theme.typography,
tips
tips,
fileListLayout
);

useEffect(() => {
Expand Down Expand Up @@ -2188,6 +2199,7 @@ function AppContent({
/>
) : activeTab?.comparison?.intent === "pull-request" && workspace ? (
<RepositoryPullRequestView
fileTreeScope={activeTab.id}
key={`${activeTab.id}:pull-request`}
root={activeTab.comparison.root}
state={workspace}
Expand All @@ -2207,6 +2219,7 @@ function AppContent({
/>
) : activeTab?.comparison ? (
<RepositoryComparison
fileTreeScope={activeTab.id}
key={activeTab.id}
request={activeTab.comparison}
readComparison={readComparison}
Expand Down Expand Up @@ -2277,6 +2290,7 @@ function AppContent({
workspace?.repository &&
workspace.view === "graph" ? (
<RepositoryGraph
fileTreeScope={activeTab.id}
key={`graph:${activeTab.id}:${workspace.repository.root}`}
root={workspace.repository.root}
head={workspace.repository.head}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import type { RepositoryPreviewCache } from "../repository-workspace/lib/repository-preview-cache";
import { RepositoryDiff } from "../repository-workspace/components/repository-diff";
import { RepositoryList } from "../repository-workspace/components/repository-list";
import { RepositoryFileLayoutToggle } from "../repository-workspace/components/repository-file-view";
import type { WorkspaceEntry } from "../repository-workspace/types";
import { ComparisonArtwork } from "../../fixture/comparison-artwork";
import { StateMessage } from "../../fixture/state-message";
Expand Down Expand Up @@ -133,6 +134,7 @@ const themedStyles = createThemedStyles(({ tokens: appTokens }) => {
});

type Readers = {
fileTreeScope?: string;
readComparison?: typeof Reader.read;
readHistory?: typeof RepositoryHistory.read;
readCommitFiles?: typeof RepositoryHistory.readFiles;
Expand Down Expand Up @@ -386,6 +388,7 @@ function ComparisonResults({
previewCache,
diffSettings,
onDiffSettingsChange,
fileTreeScope,
}: { request: ComparisonRequest; base: string; head: string } & Readers) {
const theme = useAppTheme();
const { tokens: appTokens } = theme;
Expand Down Expand Up @@ -589,12 +592,37 @@ function ComparisonResults({
}}
/>
</div>
<Text tokens={appTokens} style={styles.label}>
{commit ? "Commit files" : "Changed files"} · {files.length}
</Text>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: spacing[3.5],
paddingRight: spacing[3],
height: 28,
flexShrink: 0,
}}
>
<Text
tokens={appTokens}
style={{ ...typography.xs, color: appTokens.colors.textMuted }}
>
{commit ? "Commit files" : "Changed files"} · {files.length}
</Text>
<RepositoryFileLayoutToggle testId="comparison-file-layout" />
</div>
<RepositoryList
key={commit ?? "all"}
testId="comparison-files"
fileTree={{
owner: JSON.stringify([base, head, commit]),
scope: JSON.stringify([
fileTreeScope,
request.root,
"comparison",
]),
}}
entries={files}
label="Comparison files"
emptyMessage={
Expand Down
22 changes: 18 additions & 4 deletions apps/gpuix/src/feature/repository-graph/repository-graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
import { useAppTheme } from "../../styles/theme";
import { StateMessage } from "../../fixture/state-message";
import { RepositoryList } from "../repository-workspace/components/repository-list";
import { RepositoryFileLayoutToggle } from "../repository-workspace/components/repository-file-view";
import { RepositoryHistory } from "../repository-workspace/lib/repository-history";
import { RepositoryCommitDetails } from "../repository-workspace/components/repository-commit-details";
import { RepositoryDiff } from "../repository-workspace/components/repository-diff";
Expand Down Expand Up @@ -52,6 +53,7 @@ const row = {
} as const;

type Readers = {
fileTreeScope?: string;
readReferences?: typeof RepositoryGraphReader.references;
readPage?: typeof RepositoryGraphReader.page;
readCommitFiles?: typeof RepositoryHistory.readFiles;
Expand Down Expand Up @@ -658,6 +660,7 @@ function GraphCommitFiles({
previewCache,
diffSettings,
onDiffSettingsChange,
fileTreeScope,
}: { root: string; commit: CommitInfo } & Readers) {
const { colors, tokens } = useAppTheme();
const window = useWindowSize();
Expand Down Expand Up @@ -720,16 +723,27 @@ function GraphCommitFiles({
borderColor: colors.editorHairline,
}}
>
<text
<div
style={{
...typography.xs,
color: colors.editorMuted,
...row,
alignItems: "center",
flexWrap: "wrap",
justifyContent: "space-between",
padding: spacing[2],
flexShrink: 0,
}}
>{`Changed files · ${files.length}`}</text>
>
<text
style={{ ...typography.xs, color: colors.editorMuted }}
>{`Changed files · ${files.length}`}</text>
<RepositoryFileLayoutToggle testId="graph-file-layout" />
</div>
<RepositoryList
testId="graph-files"
fileTree={{
scope: JSON.stringify([fileTreeScope, root, "graph"]),
owner: commit.oid,
}}
label="Commit files"
entries={files}
emptyMessage={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
type ComparisonProps = Pick<
Parameters<typeof RepositoryComparison>[0],
| "readComparison"
| "fileTreeScope"
| "readHistory"
| "readCommitFiles"
| "readDiff"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createThemedStyles, useAppTheme } from "../../../styles/theme";
import { spacing, typography, fontWeight, iconSize } from "@1git/design-tokens";
import { StyleSheet } from "@1git/gpuix-stylesheet";
import { OverflowingLabel } from "../../../fixture/overflowing-label";

import type { WorkspaceEntry } from "../types";

Expand Down Expand Up @@ -39,26 +40,29 @@ const themedStyles = createThemedStyles(({ colors: appColors }) => {
fontWeight: fontWeight.regular,
color: appColors.editorInk,
flexShrink: 0,
maxWidth: "100%",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflowX: "hidden",
},
path: {
...typography.xs,
color: appColors.editorFaint,
minWidth: 0,
flexShrink: 0,
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflowX: "hidden",
},
});

return { styles };
});

/** Filename-first identity for changed files; the full path remains in the row's accessible label. */
export function RepositoryChangeLabel({ entry }: { entry: WorkspaceEntry }) {
export function RepositoryChangeLabel({
entry,
showDirectory = true,
reveal = false,
}: {
entry: WorkspaceEntry;
showDirectory?: boolean;
reveal?: boolean;
}) {
const theme = useAppTheme();
const { tokens: appTokens, colors: appColors } = theme;
const { styles } = themedStyles.get(theme);
Expand Down Expand Up @@ -87,7 +91,13 @@ export function RepositoryChangeLabel({ entry }: { entry: WorkspaceEntry }) {
: appColors.brand,
}}
/>
<div testId={`identity-${entry.id}`} style={styles.nameAndPath}>
<OverflowingLabel
testId={`identity-${entry.id}`}
reveal={reveal}
contentKey={JSON.stringify([entry.title, showDirectory])}
style={styles.nameAndPath}
gap={spacing[1.5]}
>
<text
testId={`filename-${entry.id}`}
style={StyleSheet.compose(
Expand All @@ -105,12 +115,12 @@ export function RepositoryChangeLabel({ entry }: { entry: WorkspaceEntry }) {
Conflict
</text>
) : null}
{directory ? (
{showDirectory && directory ? (
<text testId={`directory-${entry.id}`} style={styles.path}>
{directory}
</text>
) : null}
</div>
</OverflowingLabel>
{status === "U" ? (
<text style={{ ...typography.xs, color: appTokens.colors.danger }}>
Conflict
Expand Down
Loading
Loading