Git commit history (#1534)
* feat(app): add fileView preference for changes panel * feat(app): add buildDiffTree util for changed-files tree * feat(app): add changed-files tree directory row * feat(app): changed-files tree view mode in changes panel (#117) * feat(protocol): add checkout.commits.list RPC + commitsList feature flag * feat(server): list branch commits ahead of base with on-remote flags * feat(server): handle checkout.commits.list RPC and advertise capability * feat(client): checkout.commits.list method + useCommitsQuery hook * feat(app): per-commit inline view with local-vs-remote markers (#117) * feat(protocol,server): per-commit file diff RPC (checkout.commits.file_diff) * feat(app): open per-commit file diff on click (#117) * refactor: surface baseRef + commits loading/error, drop dead depth field * fix(app): flip commit local/remote dot — local hollow, remote filled * feat(app): list/tree view for expanded commit file list (#117) * fix(app): syntax-highlight per-commit file diff to match Changes view * feat(app): draggable resize between commits and diff sections * refactor(app): dedupe wrap-text helpers into diff-highlighted-text * fix(app): clean up commits resize drag on unmount + a11y label * fix(app): collapse commits section by default * fix(app): render per-commit file diff with the shared Changes line renderer * perf(app): memoize shared diff line row; drop redundant DiffLineView wrapper * refactor(app): extract shared DiffFileBody; render commit file diff through it * fix(app): hide inline-comment affordance in per-commit diffs (no reviewActions) * feat(app): move commits to a resizable bottom drawer in the Changes panel * feat(review): commitSha scoping for per-commit review drafts + attachment * feat(app): per-commit inline comments wired through to the composer (#117) * refactor(app): own commit file-diff open state in CommitFileList (drop reset effect) * refactor(app): colocate diff-render cluster under git/diff-file-body/ * feat(app): add diff tab target kind (working/commit diff tabs) * feat(app): useDiffFiles hook unifying working + commit diff targets * feat(app): diff tab panel rendering working/commit diffs * feat(app): open a commit diff tab on commit click; drop per-commit drawer/file list * feat(app): open/scroll working diff tab on changed-file click * fix(app): keep commit diff tabs ephemeral; align working diff whitespace * feat(app): collapsible file sections in the diff tab, collapsed by default * feat(app): make the on-remote commit dot more subtle Dims the filled green remote dot (row + legend) to ~0.55 opacity so the local-only ring stays the state that draws the eye. * Reshape commit diffs around the existing Changes view * Fix diff tab migration complexity after rebase * Address diff tab review findings * Clean up diff tab review interfaces * Collapse commit diffs into the existing view * Load commits when expanded --------- Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import { useMemo } from "react";
|
||||
import { Text, View } from "react-native";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { GitCommitHorizontal } from "lucide-react-native";
|
||||
import { StyleSheet, withUnistyles } from "react-native-unistyles";
|
||||
import invariant from "tiny-invariant";
|
||||
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||
import { isWeb } from "@/constants/platform";
|
||||
import { useChangesPreferences } from "@/hooks/use-changes-preferences";
|
||||
import { useAppSettings } from "@/hooks/use-settings";
|
||||
import { SharedDiffView } from "@/git/diff-pane";
|
||||
import { useCommitDiffFiles } from "@/git/use-diff-files";
|
||||
import { usePaneContext } from "@/panels/pane-context";
|
||||
import type { PanelDescriptor, PanelRegistration } from "@/panels/panel-registry";
|
||||
import { useWorkspaceDirectory } from "@/stores/session-store-hooks";
|
||||
import type { WorkspaceTabTarget } from "@/stores/workspace-tabs-store";
|
||||
|
||||
const ThemedGitCommitHorizontal = withUnistyles(GitCommitHorizontal);
|
||||
|
||||
function CommitDiffPanel() {
|
||||
const { t } = useTranslation();
|
||||
const { serverId, workspaceId, target } = usePaneContext();
|
||||
const cwd = useWorkspaceDirectory(serverId, workspaceId);
|
||||
const { settings } = useAppSettings();
|
||||
const { preferences } = useChangesPreferences();
|
||||
const isCompact = useIsCompactFormFactor();
|
||||
invariant(target.kind === "commit_diff", "CommitDiffPanel requires commit_diff target");
|
||||
|
||||
const { files, isLoading, error, capabilityMissing } = useCommitDiffFiles({
|
||||
serverId,
|
||||
cwd: cwd ?? "",
|
||||
sha: target.sha,
|
||||
enabled: Boolean(cwd),
|
||||
});
|
||||
const effectiveLayout = isWeb && !isCompact ? preferences.layout : "unified";
|
||||
const displayPreferences = useMemo(
|
||||
() => ({
|
||||
layout: effectiveLayout,
|
||||
wrapLines: preferences.wrapLines,
|
||||
codeFontSize: settings.codeFontSize,
|
||||
monoFontFamily: settings.monoFontFamily,
|
||||
}),
|
||||
[effectiveLayout, preferences.wrapLines, settings.codeFontSize, settings.monoFontFamily],
|
||||
);
|
||||
const commitMode = useMemo(() => ({ kind: "commit" as const }), []);
|
||||
|
||||
if (!cwd) {
|
||||
return (
|
||||
<View style={styles.centerState}>
|
||||
<Text style={styles.mutedText}>{t("panels.diff.directoryMissing")}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (capabilityMissing) {
|
||||
return (
|
||||
<View style={styles.centerState} testID="commit-diff-capability-missing">
|
||||
<Text style={styles.mutedText}>{t("panels.diff.capabilityMissing")}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
if (error) {
|
||||
return (
|
||||
<View style={styles.centerState} testID="commit-diff-error">
|
||||
<Text style={styles.errorText}>{t("panels.diff.loadError")}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
if (isLoading && files.length === 0) {
|
||||
return (
|
||||
<View style={styles.centerState} testID="commit-diff-loading">
|
||||
<Text style={styles.mutedText}>{t("workspace.tabs.loading")}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
if (files.length === 0) {
|
||||
return (
|
||||
<View style={styles.centerState} testID="commit-diff-empty">
|
||||
<Text style={styles.mutedText}>{t("panels.diff.empty")}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return <SharedDiffView files={files} displayPreferences={displayPreferences} mode={commitMode} />;
|
||||
}
|
||||
|
||||
function useCommitDiffPanelDescriptor(
|
||||
target: Extract<WorkspaceTabTarget, { kind: "commit_diff" }>,
|
||||
): PanelDescriptor {
|
||||
const { t } = useTranslation();
|
||||
return {
|
||||
label: target.sha.slice(0, 7),
|
||||
subtitle: t("panels.diff.commitSubtitle"),
|
||||
titleState: "ready",
|
||||
icon: ThemedGitCommitHorizontal,
|
||||
statusBucket: null,
|
||||
};
|
||||
}
|
||||
|
||||
export const commitDiffPanelRegistration: PanelRegistration<"commit_diff"> = {
|
||||
kind: "commit_diff",
|
||||
component: CommitDiffPanel,
|
||||
useDescriptor: useCommitDiffPanelDescriptor,
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create((theme) => ({
|
||||
centerState: {
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
paddingHorizontal: theme.spacing[6],
|
||||
paddingTop: theme.spacing[16],
|
||||
},
|
||||
mutedText: {
|
||||
fontSize: theme.fontSize.base,
|
||||
color: theme.colors.foregroundMuted,
|
||||
textAlign: "center",
|
||||
},
|
||||
errorText: {
|
||||
fontSize: theme.fontSize.base,
|
||||
color: theme.colors.destructive,
|
||||
textAlign: "center",
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user