Handle resolved conflicts

This commit is contained in:
Silvano Cerza 2025-02-23 17:30:57 +01:00
parent cef814f702
commit 4745f91bdc
2 changed files with 100 additions and 19 deletions

View file

@ -28,6 +28,7 @@ interface DiffViewProps {
newText: string;
onOldTextChange: (content: string) => void;
onNewTextChange: (content: string) => void;
onConflictResolved: () => void;
}
const DiffView: React.FC<DiffViewProps> = ({
@ -35,6 +36,7 @@ const DiffView: React.FC<DiffViewProps> = ({
newText,
onOldTextChange,
onNewTextChange,
onConflictResolved,
}) => {
// We need to know the line height to correctly draw the ribbon between the left
// and right editor in the actions gutter
@ -72,6 +74,23 @@ const DiffView: React.FC<DiffViewProps> = ({
/>
</div>
<div style={{ minWidth: "160px", width: "auto" }}>
{diffs.length === 0 && (
<button
style={{
position: "absolute",
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
zIndex: 1,
backgroundColor: "var(--interactive-accent)",
color: "var(--text-on-accent)",
}}
onClick={onConflictResolved}
>
Resolve conflict
</button>
)}
<ActionsGutter
diffChunks={diffs}
lineHeight={lineHeight}

View file

@ -125,8 +125,35 @@ export class ConflictsResolutionView extends ItemView {
const root: Root = createRoot(container);
const App = ({ initialFiles }: { initialFiles: ConflictFile[] }) => {
const [files, setFiles] = React.useState(initialFiles);
const [resolvedConflicts, setResolvedConflicts] = React.useState<
ConflictResolution[]
>([]);
const [currentFileIndex, setCurrentFileIndex] = React.useState(0);
const currentFile = files.at(currentFileIndex);
const onConflictResolved = () => {
// Remove the file from the conflicts to resolve
setFiles(files.filter((_, index) => index !== currentFileIndex));
// Keep track of the resolved conflicts
setResolvedConflicts([
...resolvedConflicts,
{
filename: currentFile!.filename,
// We could get either the local or remote content at this point since
// they're identical
content: currentFile!.localContent,
},
]);
// Select the previous file only if we're not already at the start
if (currentFileIndex > 0) {
setCurrentFileIndex(currentFileIndex - 1);
}
if (files.length === 0) {
// We solved all conflicts, we can resume syncing
this.onResolve(resolvedConflicts);
}
};
return (
<React.StrictMode>
<div
@ -134,27 +161,62 @@ export class ConflictsResolutionView extends ItemView {
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "center",
}}
>
<FilesTabBar
files={files.map((f) => f.filename)}
currentFile={currentFile?.filename || ""}
setCurrentFileIndex={setCurrentFileIndex}
/>
<DiffView
oldText={currentFile?.remoteContent || ""}
newText={currentFile?.localContent || ""}
onOldTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].remoteContent = content;
setFiles(tempFiles);
}}
onNewTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].localContent = content;
setFiles(tempFiles);
}}
/>
{files.length === 0 ? (
<div
style={{
position: "relative",
textAlign: "center",
alignSelf: "center",
}}
>
<div
style={{
margin: "20px 0",
fontWeight: "var(--h2-weight)",
fontSize: "var(--h2-size)",
lineHeight: "var(--line-height-tight)",
}}
>
No conflicts to resolve
</div>
<div
style={{
margin: "20px 0",
fontSize: "var(--font-text-size)",
color: "var(--text-muted)",
lineHeight: "var(--line-height-tight)",
}}
>
That's good, keep going
</div>
</div>
) : (
<>
<FilesTabBar
files={files.map((f) => f.filename)}
currentFile={currentFile?.filename || ""}
setCurrentFileIndex={setCurrentFileIndex}
/>
<DiffView
oldText={currentFile?.remoteContent || ""}
newText={currentFile?.localContent || ""}
onOldTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].remoteContent = content;
setFiles(tempFiles);
}}
onNewTextChange={(content: string) => {
const tempFiles = [...files];
tempFiles[currentFileIndex].localContent = content;
setFiles(tempFiles);
}}
onConflictResolved={onConflictResolved}
/>
</>
)}
</div>
</React.StrictMode>
);