From 5edb8ca742b7d7dc217aa92d6ae35478116d2f77 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Thu, 13 Feb 2025 17:54:59 +0100 Subject: [PATCH] Handle resize --- .../conflicts-resolution/diff-connections.tsx | 145 ++++++++++-------- src/views/conflicts-resolution/view.tsx | 14 +- 2 files changed, 90 insertions(+), 69 deletions(-) diff --git a/src/views/conflicts-resolution/diff-connections.tsx b/src/views/conflicts-resolution/diff-connections.tsx index 1e8c3f6..2ef5848 100644 --- a/src/views/conflicts-resolution/diff-connections.tsx +++ b/src/views/conflicts-resolution/diff-connections.tsx @@ -1,7 +1,8 @@ -import { setIcon } from "obsidian"; +import { App, setIcon } from "obsidian"; import { useEffect, useState } from "react"; import { EditorView } from "@codemirror/view"; import { DiffResult } from "./diff"; +import { usePlugin } from "../hooks"; interface DiffConnectionProps { differences: DiffResult[]; @@ -25,54 +26,81 @@ const DiffConnections: React.FC = ({ modifiedEditor, }) => { const [connections, setConnections] = useState([]); + const plugin = usePlugin(); + if (!plugin) { + // Unlikely to happen, makes TS happy though + throw new Error("Plugin is not initialized"); + } useEffect(() => { if (!originalEditor || !modifiedEditor) return; - requestAnimationFrame(() => { - const originalContainer = - originalEditor.scrollDOM.getBoundingClientRect(); - const modifiedContainer = - modifiedEditor.scrollDOM.getBoundingClientRect(); + const updateConnections = () => { + requestAnimationFrame(() => { + const originalContainer = + originalEditor.scrollDOM.getBoundingClientRect(); + const modifiedContainer = + modifiedEditor.scrollDOM.getBoundingClientRect(); - // Group consecutive diffs into chunks - const chunks: ConnectionChunk[] = []; - let currentChunk: DiffResult[] = []; + // Group consecutive diffs into chunks + const chunks: ConnectionChunk[] = []; + let currentChunk: DiffResult[] = []; - differences.forEach((diff, i) => { - if (diff.type === "equal") { - if (currentChunk.length > 0) { - // Process the chunk - const chunk = processChunk( - currentChunk, - originalEditor, - modifiedEditor, - originalContainer, - modifiedContainer, - ); - if (chunk) chunks.push(chunk); - currentChunk = []; + differences.forEach((diff, i) => { + if (diff.type === "equal") { + if (currentChunk.length > 0) { + // Process the chunk + const chunk = processChunk( + currentChunk, + originalEditor, + modifiedEditor, + originalContainer, + modifiedContainer, + ); + if (chunk) chunks.push(chunk); + currentChunk = []; + } + } else { + currentChunk.push(diff); } - } else { - currentChunk.push(diff); + }); + + // Process last chunk if exists + if (currentChunk.length > 0) { + const chunk = processChunk( + currentChunk, + originalEditor, + modifiedEditor, + originalContainer, + modifiedContainer, + ); + if (chunk) chunks.push(chunk); } + + setConnections(chunks); }); + }; - // Process last chunk if exists - if (currentChunk.length > 0) { - const chunk = processChunk( - currentChunk, - originalEditor, - modifiedEditor, - originalContainer, - modifiedContainer, - ); - if (chunk) chunks.push(chunk); - } + // Initial update + updateConnections(); - setConnections(chunks); - }); - }, [differences, originalEditor, modifiedEditor]); + // Setup resize observer + const resizeObserver = new ResizeObserver(updateConnections); + resizeObserver.observe(originalEditor.scrollDOM); + resizeObserver.observe(modifiedEditor.scrollDOM); + + // Listen to Obsidian layout changes + const layoutChangeHandler = () => { + updateConnections(); + }; + plugin.app.workspace.on("layout-change", layoutChangeHandler); + + // Cleanup + return () => { + resizeObserver.disconnect(); + plugin.app.workspace.off("layout-change", layoutChangeHandler); + }; + }, [differences, originalEditor, modifiedEditor, plugin]); const processChunk = ( chunk: DiffResult[], @@ -229,44 +257,35 @@ const ConnectionButtons: React.FC<{ chunk: ConnectionChunk; onAction: (action: "left" | "right") => void; }> = ({ chunk, onAction }) => { - const centerY = - (chunk.startTop + chunk.startBottom + chunk.endTop + chunk.endBottom) / 4; - const showLeftArrow = chunk.type === "modify" || chunk.type === "add"; const showRightArrow = chunk.type === "modify" || chunk.type === "remove"; return ( - -
- {showRightArrow && ( + <> + {showRightArrow && ( +
onAction("right")} - ref={(node) => node && setIcon(node, "arrow-right")} + ref={(node) => { + if (node) setIcon(node, "arrow-right"); + }} /> - )} + + )} - {showLeftArrow && ( + {showLeftArrow && ( +
onAction("left")} - ref={(node) => node && setIcon(node, "arrow-left")} + ref={(node) => { + if (node) setIcon(node, "arrow-left"); + }} /> - )} -
-
+ + )} + ); }; diff --git a/src/views/conflicts-resolution/view.tsx b/src/views/conflicts-resolution/view.tsx index d994cc7..9c5ed5c 100644 --- a/src/views/conflicts-resolution/view.tsx +++ b/src/views/conflicts-resolution/view.tsx @@ -2,6 +2,7 @@ import { IconName, ItemView, WorkspaceLeaf } from "obsidian"; import { Root, createRoot } from "react-dom/client"; import DiffView from "./component"; import GitHubSyncPlugin from "src/main"; +import { PluginContext } from "../hooks"; export const CONFLICTS_RESOLUTION_VIEW_TYPE = "conflicts-resolution-view"; @@ -59,12 +60,13 @@ export class ConflictsResolutionView extends ItemView { container.empty(); const root: Root = createRoot(container); root.render( - console.log("Resolved:", text)} - // registerExtension={(ext) => this.plugin.registerEditorExtension(ext)} - />, + + console.log("Resolved:", text)} + /> + , ); }