From c315378fb71a4d23c6ce3e4d6ff1ec2bf17bfb0a Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Sat, 22 Feb 2025 16:45:23 +0100 Subject: [PATCH] Add tab bar to select files with conflicts --- src/views/conflicts-resolution/component.tsx | 203 ++++++++++-------- .../conflicts-resolution/files-tab-bar.tsx | 115 ++++++++++ 2 files changed, 223 insertions(+), 95 deletions(-) create mode 100644 src/views/conflicts-resolution/files-tab-bar.tsx diff --git a/src/views/conflicts-resolution/component.tsx b/src/views/conflicts-resolution/component.tsx index fca0198..e34e59a 100644 --- a/src/views/conflicts-resolution/component.tsx +++ b/src/views/conflicts-resolution/component.tsx @@ -7,6 +7,7 @@ import { createDiffHighlightPlugin } from "./diff-highlight-plugin"; import EditorPane from "./editor-pane"; import ActionsGutter from "./actions-gutter"; import * as React from "react"; +import FilesTabBar from "./files-tab-bar"; // Add styles for diff highlighting const styles = document.createElement("style"); @@ -53,105 +54,117 @@ const DiffView: React.FC = ({ return (
-
- -
-
- { - if (chunk.type === "add") { - const oldLines = oldText.split("\n"); - oldLines.splice( - chunk.startLeftLine - 1, - 0, - ...newText - .split("\n") - .slice(chunk.startRightLine - 1, chunk.endRightLine - 1), - ); - onOldTextChange(oldLines.join("\n")); - } else if (chunk.type === "modify") { - const oldLines = oldText.split("\n"); - oldLines.splice( - chunk.startLeftLine - 1, - chunk.endLeftLine - chunk.startLeftLine, - ...newText - .split("\n") - .slice(chunk.startRightLine - 1, chunk.endRightLine - 1), - ); - onOldTextChange(oldLines.join("\n")); - } - }} - onAcceptRight={(chunk: DiffChunk) => { - if (chunk.type === "remove") { - const newLines = newText.split("\n"); - newLines.splice( - chunk.startRightLine - 1, - 0, - ...oldText - .split("\n") - .slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1), - ); - onNewTextChange(newLines.join("\n")); - } else if (chunk.type === "modify") { - const newLines = newText.split("\n"); - newLines.splice( - chunk.startRightLine - 1, - chunk.endRightLine - chunk.startRightLine, - ...oldText - .split("\n") - .slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1), - ); - onNewTextChange(newLines.join("\n")); - } - }} - onReject={(chunk: DiffChunk) => { - if (chunk.type === "add") { - const newLines = newText.split("\n"); - newLines.splice( - chunk.startRightLine - 1, - chunk.endRightLine - chunk.startRightLine, - ); - onNewTextChange(newLines.join("\n")); - } else if (chunk.type === "remove") { - const oldLines = oldText.split("\n"); - oldLines.splice( - chunk.startLeftLine - 1, - chunk.endLeftLine - chunk.startLeftLine, - ); - onOldTextChange(oldLines.join("\n")); - } - }} - /> -
-
- + console.log(`Clicked ${filename}`)} + /> +
+
+ +
+
+ { + if (chunk.type === "add") { + const oldLines = oldText.split("\n"); + oldLines.splice( + chunk.startLeftLine - 1, + 0, + ...newText + .split("\n") + .slice(chunk.startRightLine - 1, chunk.endRightLine - 1), + ); + onOldTextChange(oldLines.join("\n")); + } else if (chunk.type === "modify") { + const oldLines = oldText.split("\n"); + oldLines.splice( + chunk.startLeftLine - 1, + chunk.endLeftLine - chunk.startLeftLine, + ...newText + .split("\n") + .slice(chunk.startRightLine - 1, chunk.endRightLine - 1), + ); + onOldTextChange(oldLines.join("\n")); + } + }} + onAcceptRight={(chunk: DiffChunk) => { + if (chunk.type === "remove") { + const newLines = newText.split("\n"); + newLines.splice( + chunk.startRightLine - 1, + 0, + ...oldText + .split("\n") + .slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1), + ); + onNewTextChange(newLines.join("\n")); + } else if (chunk.type === "modify") { + const newLines = newText.split("\n"); + newLines.splice( + chunk.startRightLine - 1, + chunk.endRightLine - chunk.startRightLine, + ...oldText + .split("\n") + .slice(chunk.startLeftLine - 1, chunk.endLeftLine - 1), + ); + onNewTextChange(newLines.join("\n")); + } + }} + onReject={(chunk: DiffChunk) => { + if (chunk.type === "add") { + const newLines = newText.split("\n"); + newLines.splice( + chunk.startRightLine - 1, + chunk.endRightLine - chunk.startRightLine, + ); + onNewTextChange(newLines.join("\n")); + } else if (chunk.type === "remove") { + const oldLines = oldText.split("\n"); + oldLines.splice( + chunk.startLeftLine - 1, + chunk.endLeftLine - chunk.startLeftLine, + ); + onOldTextChange(oldLines.join("\n")); + } + }} + /> +
+
+ +
); diff --git a/src/views/conflicts-resolution/files-tab-bar.tsx b/src/views/conflicts-resolution/files-tab-bar.tsx new file mode 100644 index 0000000..6f39cff --- /dev/null +++ b/src/views/conflicts-resolution/files-tab-bar.tsx @@ -0,0 +1,115 @@ +import { Menu } from "obsidian"; +import * as React from "react"; + +interface FilesTabBarProps { + files: string[]; + onTabChange: (filename: string) => void; +} + +const FilesTabBar: React.FC = ({ files, onTabChange }) => { + const [currentFile, setCurrentFile] = React.useState( + files.at(0) || "", + ); + + const onTabClick = (filename: string) => { + if (filename === currentFile) { + return; + } + setCurrentFile(filename); + onTabChange(filename); + }; + + const createTab = (filename: string) => { + return ( +
onTabClick(filename)} + > +
+
{filename}
+
+
+ ); + }; + + // Makes it easier to position the tab bar menu + const divRef = React.useRef(null); + + return ( +
+
+ {files.map(createTab)} +
+
+
{ + const menu = new Menu(); + files.forEach((filename: string) => { + menu.addItem((item) => { + item.setTitle(filename).onClick(() => onTabClick(filename)); + }); + }); + // We use the divRef to force the position to be relative to this div. We want the position + // to always be the same so using the click event is not feasible as that depends on the + // coordinates of the user click. + // The event target is not usable either as depending where the user clicks the target + // might be this div or its children thus having different positions. + const rect = divRef.current!.getBoundingClientRect(); + menu.showAtPosition({ x: rect.left, y: rect.bottom }); + }} + > + + + + + +
+
+ ); +}; + +export default FilesTabBar;