mirror of
https://github.com/silvanocerza/github-gitless-sync.git
synced 2026-07-22 12:10:28 +00:00
Ditch old/new nomenclature in favour of remote/local to avoid confusion
This commit is contained in:
parent
41642b5174
commit
8732cdc1f0
7 changed files with 90 additions and 80 deletions
|
|
@ -20,18 +20,18 @@ styles.innerHTML = `
|
|||
document.head.appendChild(styles);
|
||||
|
||||
interface DiffViewProps {
|
||||
oldText: string;
|
||||
newText: string;
|
||||
onOldTextChange: (content: string) => void;
|
||||
onNewTextChange: (content: string) => void;
|
||||
remoteText: string;
|
||||
localText: string;
|
||||
onRemoteTextChange: (content: string) => void;
|
||||
onLocalTextChange: (content: string) => void;
|
||||
onConflictResolved: () => void;
|
||||
}
|
||||
|
||||
const DiffView: React.FC<DiffViewProps> = ({
|
||||
oldText,
|
||||
newText,
|
||||
onOldTextChange,
|
||||
onNewTextChange,
|
||||
remoteText,
|
||||
localText,
|
||||
onRemoteTextChange,
|
||||
onLocalTextChange,
|
||||
onConflictResolved,
|
||||
}) => {
|
||||
// We need to know the line height to correctly draw the ribbon between the left
|
||||
|
|
@ -46,7 +46,7 @@ const DiffView: React.FC<DiffViewProps> = ({
|
|||
const [rightEditorTopOffset, setRightEditorTopOffset] =
|
||||
React.useState<number>(0);
|
||||
|
||||
const diffs = diff(oldText, newText);
|
||||
const diffs = diff(remoteText, localText);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -59,13 +59,13 @@ const DiffView: React.FC<DiffViewProps> = ({
|
|||
>
|
||||
<div style={{ flex: 1, overflow: "hidden" }}>
|
||||
<EditorPane
|
||||
content={oldText}
|
||||
content={remoteText}
|
||||
highlightPluginSpec={{
|
||||
diff: diffs,
|
||||
isOriginal: true,
|
||||
}}
|
||||
onEditorUpdate={handleEditorReady}
|
||||
onContentChange={onOldTextChange}
|
||||
onContentChange={onRemoteTextChange}
|
||||
onScrollTopUpdate={setLeftEditorTopOffset}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -94,77 +94,77 @@ const DiffView: React.FC<DiffViewProps> = ({
|
|||
rightEditorTopLineOffset={rightEditorTopOffset}
|
||||
onAcceptLeft={(chunk: DiffChunk) => {
|
||||
if (chunk.type === "add") {
|
||||
const oldLines = oldText.split("\n");
|
||||
oldLines.splice(
|
||||
const remoteLines = remoteText.split("\n");
|
||||
remoteLines.splice(
|
||||
chunk.startLeftLine - 1,
|
||||
0,
|
||||
...newText
|
||||
...localText
|
||||
.split("\n")
|
||||
.slice(chunk.startRightLine - 1, chunk.endRightLine - 1),
|
||||
);
|
||||
onOldTextChange(oldLines.join("\n"));
|
||||
onRemoteTextChange(remoteLines.join("\n"));
|
||||
} else if (chunk.type === "modify") {
|
||||
const oldLines = oldText.split("\n");
|
||||
oldLines.splice(
|
||||
const remoteLines = remoteText.split("\n");
|
||||
remoteLines.splice(
|
||||
chunk.startLeftLine - 1,
|
||||
chunk.endLeftLine - chunk.startLeftLine,
|
||||
...newText
|
||||
...localText
|
||||
.split("\n")
|
||||
.slice(chunk.startRightLine - 1, chunk.endRightLine - 1),
|
||||
);
|
||||
onOldTextChange(oldLines.join("\n"));
|
||||
onRemoteTextChange(remoteLines.join("\n"));
|
||||
}
|
||||
}}
|
||||
onAcceptRight={(chunk: DiffChunk) => {
|
||||
if (chunk.type === "remove") {
|
||||
const newLines = newText.split("\n");
|
||||
newLines.splice(
|
||||
const localLines = localText.split("\n");
|
||||
localLines.splice(
|
||||
chunk.startRightLine - 1,
|
||||
0,
|
||||
...oldText
|
||||
...remoteText
|
||||
.split("\n")
|
||||
.slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1),
|
||||
);
|
||||
onNewTextChange(newLines.join("\n"));
|
||||
onLocalTextChange(localLines.join("\n"));
|
||||
} else if (chunk.type === "modify") {
|
||||
const newLines = newText.split("\n");
|
||||
newLines.splice(
|
||||
const localLines = localText.split("\n");
|
||||
localLines.splice(
|
||||
chunk.startRightLine - 1,
|
||||
chunk.endRightLine - chunk.startRightLine,
|
||||
...oldText
|
||||
...remoteText
|
||||
.split("\n")
|
||||
.slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1),
|
||||
);
|
||||
onNewTextChange(newLines.join("\n"));
|
||||
onLocalTextChange(localLines.join("\n"));
|
||||
}
|
||||
}}
|
||||
onReject={(chunk: DiffChunk) => {
|
||||
if (chunk.type === "add") {
|
||||
const newLines = newText.split("\n");
|
||||
newLines.splice(
|
||||
const localLines = localText.split("\n");
|
||||
localLines.splice(
|
||||
chunk.startRightLine - 1,
|
||||
chunk.endRightLine - chunk.startRightLine,
|
||||
);
|
||||
onNewTextChange(newLines.join("\n"));
|
||||
onLocalTextChange(localLines.join("\n"));
|
||||
} else if (chunk.type === "remove") {
|
||||
const oldLines = oldText.split("\n");
|
||||
oldLines.splice(
|
||||
const remoteLines = remoteText.split("\n");
|
||||
remoteLines.splice(
|
||||
chunk.startLeftLine - 1,
|
||||
chunk.endLeftLine - chunk.startLeftLine,
|
||||
);
|
||||
onOldTextChange(oldLines.join("\n"));
|
||||
onRemoteTextChange(remoteLines.join("\n"));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1, overflow: "hidden" }}>
|
||||
<EditorPane
|
||||
content={newText}
|
||||
content={localText}
|
||||
highlightPluginSpec={{
|
||||
diff: diffs,
|
||||
isOriginal: false,
|
||||
}}
|
||||
onContentChange={onNewTextChange}
|
||||
onContentChange={onLocalTextChange}
|
||||
onScrollTopUpdate={setRightEditorTopOffset}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -89,14 +89,14 @@ const SplitView = ({
|
|||
setCurrentFileIndex={setCurrentFileIndex}
|
||||
/>
|
||||
<DiffView
|
||||
oldText={currentFile?.remoteContent || ""}
|
||||
newText={currentFile?.localContent || ""}
|
||||
onOldTextChange={(content: string) => {
|
||||
remoteText={currentFile?.remoteContent || ""}
|
||||
localText={currentFile?.localContent || ""}
|
||||
onRemoteTextChange={(content: string) => {
|
||||
const tempFiles = [...files];
|
||||
tempFiles[currentFileIndex].remoteContent = content;
|
||||
setFiles(tempFiles);
|
||||
}}
|
||||
onNewTextChange={(content: string) => {
|
||||
onLocalTextChange={(content: string) => {
|
||||
const tempFiles = [...files];
|
||||
tempFiles[currentFileIndex].localContent = content;
|
||||
setFiles(tempFiles);
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@
|
|||
interface ConflictRange {
|
||||
from: number;
|
||||
to: number;
|
||||
source: "old" | "new" | "both";
|
||||
source: "remote" | "local" | "both";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,13 +78,13 @@ export const createLineDecorations = (
|
|||
const endLine = state.doc.lineAt(range.to);
|
||||
for (let i = 0; i <= endLine.number - startLine.number; i += 1) {
|
||||
const line = state.doc.line(startLine.number + i);
|
||||
if (range.source === "old") {
|
||||
if (range.source === "remote") {
|
||||
builder.add(
|
||||
line.from,
|
||||
line.from,
|
||||
Decoration.line({ class: "cm-deletedLine" }),
|
||||
);
|
||||
} else if (range.source === "new") {
|
||||
} else if (range.source === "local") {
|
||||
builder.add(
|
||||
line.from,
|
||||
line.from,
|
||||
|
|
@ -118,8 +118,8 @@ export const createResolutionDecorations = (
|
|||
const previousRange = ranges.at(index - 1);
|
||||
const nextRange = ranges.at(index + 1);
|
||||
|
||||
if (range.source === "old") {
|
||||
const nextRangeIsNew = nextRange?.source === "new";
|
||||
if (range.source === "remote") {
|
||||
const nextRangeIsNew = nextRange?.source === "local";
|
||||
if (nextRangeIsNew) {
|
||||
const deco = Decoration.widget({
|
||||
widget: new ResolutionWidget({
|
||||
|
|
@ -224,7 +224,10 @@ export const createResolutionDecorations = (
|
|||
});
|
||||
widgets.push(deco.range(range.from));
|
||||
}
|
||||
} else if (range.source === "new" && previousRange?.source !== "old") {
|
||||
} else if (
|
||||
range.source === "local" &&
|
||||
previousRange?.source !== "remote"
|
||||
) {
|
||||
// We draw this only in case the previous range doesn't come from the old document
|
||||
// since we handle that above
|
||||
const deco = Decoration.widget({
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import {
|
|||
} from "./decorations";
|
||||
|
||||
interface DiffViewProps {
|
||||
initialOldText: string;
|
||||
initialNewText: string;
|
||||
initialRemoteText: string;
|
||||
initialLocalText: string;
|
||||
onConflictResolved: (content: string) => void;
|
||||
}
|
||||
|
||||
|
|
@ -21,26 +21,26 @@ interface DiffViewProps {
|
|||
/// ranges that specify whether a certain document range comes from
|
||||
/// remote, local or both documents, so we can highlight them.
|
||||
const createUnifiedDocument = (
|
||||
oldText: string,
|
||||
newText: string,
|
||||
remoteText: string,
|
||||
localText: string,
|
||||
diffChunks: DiffChunk[],
|
||||
): { doc: string; lineRanges: ConflictRange[] } => {
|
||||
const sortedChunks = [...diffChunks].sort(
|
||||
(a, b) => a.startLeftLine - b.startLeftLine,
|
||||
);
|
||||
|
||||
const oldLines = oldText.split(/\r?\n/);
|
||||
const newLines = newText.split(/\r?\n/);
|
||||
const remoteLines = remoteText.split(/\r?\n/);
|
||||
const localLines = localText.split(/\r?\n/);
|
||||
|
||||
let result: string[] = [];
|
||||
let lineRanges: ConflictRange[] = [];
|
||||
let linePosition = 0;
|
||||
let currentRange: ConflictRange | null = null;
|
||||
|
||||
let oldTextLine = 1;
|
||||
let newTextLine = 1;
|
||||
let remoteTextLine = 1;
|
||||
let localTextLine = 1;
|
||||
|
||||
const addLine = (line: string, source: "old" | "new" | "both") => {
|
||||
const addLine = (line: string, source: "remote" | "local" | "both") => {
|
||||
result.push(line);
|
||||
|
||||
const startPos = linePosition;
|
||||
|
|
@ -65,35 +65,42 @@ const createUnifiedDocument = (
|
|||
for (const chunk of sortedChunks) {
|
||||
// Add common lines before the chunk
|
||||
while (
|
||||
oldTextLine < chunk.startLeftLine &&
|
||||
newTextLine < chunk.startRightLine
|
||||
remoteTextLine < chunk.startLeftLine &&
|
||||
localTextLine < chunk.startRightLine
|
||||
) {
|
||||
addLine(oldLines[oldTextLine - 1], "both");
|
||||
oldTextLine++;
|
||||
newTextLine++;
|
||||
addLine(remoteLines[remoteTextLine - 1], "both");
|
||||
remoteTextLine++;
|
||||
localTextLine++;
|
||||
}
|
||||
|
||||
// Add removed lines (from old text)
|
||||
for (let i = oldTextLine; i < chunk.endLeftLine; i++) {
|
||||
addLine(oldLines[i - 1], "old");
|
||||
for (let i = remoteTextLine; i < chunk.endLeftLine; i++) {
|
||||
addLine(remoteLines[i - 1], "remote");
|
||||
}
|
||||
|
||||
// Add added lines (from new text)
|
||||
for (let i = newTextLine; i < chunk.endRightLine; i++) {
|
||||
addLine(newLines[i - 1], "new");
|
||||
for (let i = localTextLine; i < chunk.endRightLine; i++) {
|
||||
addLine(localLines[i - 1], "local");
|
||||
}
|
||||
|
||||
// Update line pointers
|
||||
oldTextLine = chunk.endLeftLine;
|
||||
newTextLine = chunk.endRightLine;
|
||||
remoteTextLine = chunk.endLeftLine;
|
||||
localTextLine = chunk.endRightLine;
|
||||
}
|
||||
|
||||
// Add remaining common lines after the last chunk
|
||||
while (oldTextLine <= oldLines.length && newTextLine <= newLines.length) {
|
||||
if (oldTextLine > oldLines.length || newTextLine > newLines.length) break;
|
||||
addLine(oldLines[oldTextLine - 1], "both");
|
||||
oldTextLine++;
|
||||
newTextLine++;
|
||||
while (
|
||||
remoteTextLine <= remoteLines.length &&
|
||||
localTextLine <= localLines.length
|
||||
) {
|
||||
if (
|
||||
remoteTextLine > remoteLines.length ||
|
||||
localTextLine > localLines.length
|
||||
)
|
||||
break;
|
||||
addLine(remoteLines[remoteTextLine - 1], "both");
|
||||
remoteTextLine++;
|
||||
localTextLine++;
|
||||
}
|
||||
|
||||
// Add the final range if there is one
|
||||
|
|
@ -105,16 +112,16 @@ const createUnifiedDocument = (
|
|||
};
|
||||
|
||||
const DiffView: React.FC<DiffViewProps> = ({
|
||||
initialOldText,
|
||||
initialNewText,
|
||||
initialRemoteText,
|
||||
initialLocalText,
|
||||
onConflictResolved,
|
||||
}) => {
|
||||
const editorViewRef = React.useRef<EditorView | null>(null);
|
||||
|
||||
const diffChunks = diff(initialOldText, initialNewText);
|
||||
const diffChunks = diff(initialRemoteText, initialLocalText);
|
||||
const { doc, lineRanges } = createUnifiedDocument(
|
||||
initialOldText,
|
||||
initialNewText,
|
||||
initialRemoteText,
|
||||
initialLocalText,
|
||||
diffChunks,
|
||||
);
|
||||
|
||||
|
|
@ -134,7 +141,7 @@ const DiffView: React.FC<DiffViewProps> = ({
|
|||
if (update.docChanged) {
|
||||
const conflictRanges = update.state.field(conflictRangesField);
|
||||
const allConflictsSolved = conflictRanges.some(
|
||||
(range) => range.source === "old" || range.source === "new",
|
||||
(range) => range.source === "remote" || range.source === "local",
|
||||
);
|
||||
|
||||
if (!allConflictsSolved) {
|
||||
|
|
@ -173,7 +180,7 @@ const DiffView: React.FC<DiffViewProps> = ({
|
|||
},
|
||||
}),
|
||||
];
|
||||
}, [initialOldText, initialNewText]);
|
||||
}, [initialRemoteText, initialLocalText]);
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%", overflow: "hidden" }}>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const UpdateRangesEffect = StateEffect.define<RangeUpdateOperation>();
|
|||
|
||||
export type RangeChangeSourceOperation = {
|
||||
index: number;
|
||||
newSource: "old" | "new" | "both";
|
||||
newSource: "remote" | "local" | "both";
|
||||
};
|
||||
|
||||
export type RangeRemoveOperation = {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ const UnifiedView = ({
|
|||
{file.filePath}
|
||||
</div>
|
||||
<DiffView
|
||||
initialOldText={file.remoteContent || ""}
|
||||
initialNewText={file.localContent || ""}
|
||||
initialRemoteText={file.remoteContent || ""}
|
||||
initialLocalText={file.localContent || ""}
|
||||
onConflictResolved={(content: string) => {
|
||||
onConflictResolved(index, content);
|
||||
}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue