Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export function LightDiffViewer({
themeType: "dark",
overflow: "wrap",
disableFileHeader: true,
unsafeCSS: `
* {
user-select: text;
-webkit-user-select: text;
}
`,
}}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,13 @@ export function FileViewerPane({
pinPane(paneId);
};

const switchToMode = (newMode: FileViewerMode) => {
const switchToMode = (
newMode: FileViewerMode,
location?: {
line?: number;
column?: number;
},
) => {
const panes = useTabsStore.getState().panes;
const currentPane = panes[paneId];
if (currentPane?.fileViewer) {
Expand All @@ -185,13 +191,20 @@ export function FileViewerPane({
fileViewer: {
...currentPane.fileViewer,
viewMode: newMode,
initialLine: location?.line ?? currentPane.fileViewer.initialLine,
initialColumn:
location?.column ?? currentPane.fileViewer.initialColumn,
},
},
},
});
}
};

const handleSwitchToRawAtLocation = (line: number, column: number) => {
switchToMode("raw", { line, column });
};

const handleViewModeChange = (value: string) => {
if (!value) return;
const newMode = value as FileViewerMode;
Expand Down Expand Up @@ -300,6 +313,7 @@ export function FileViewerPane({
onSaveRaw={handleSaveRaw}
onEditorChange={handleEditorChange}
setIsDirty={setIsDirty}
onSwitchToRawAtLocation={handleSwitchToRawAtLocation}
// Context menu props
onSplitHorizontal={() => splitPaneHorizontal(tabId, paneId, path)}
onSplitVertical={() => splitPaneVertical(tabId, paneId, path)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { ContextMenuItem } from "@superset/ui/context-menu";
import { toast } from "@superset/ui/sonner";
import { type MutableRefObject, type ReactNode, useCallback } from "react";
import { LuSquarePen } from "react-icons/lu";
import type { Tab } from "renderer/stores/tabs/types";
import {
type CodeEditorAdapter,
EditorContextMenu,
type EditorSelectionLines,
useEditorActions,
} from "../../../../../components";

interface DiffViewerContextMenuProps {
children: ReactNode;
containerRef: MutableRefObject<HTMLDivElement | null>;
filePath: string;
getSelectionLines: () => EditorSelectionLines | null;
onSplitHorizontal: () => void;
onSplitVertical: () => void;
onSplitWithNewChat?: () => void;
onSplitWithNewBrowser?: () => void;
onClosePane: () => void;
currentTabId: string;
availableTabs: Tab[];
onMoveToTab: (tabId: string) => void;
onMoveToNewTab: () => void;
onEditAtLocation: () => void;
}

function isSelectionInsideContainer(
container: HTMLDivElement,
selection: Selection,
): boolean {
if (selection.rangeCount === 0) {
return false;
}

for (let index = 0; index < selection.rangeCount; index += 1) {
const range = selection.getRangeAt(index);
if (!container.contains(range.commonAncestorContainer)) {
return false;
}
}

return true;
}

export function DiffViewerContextMenu({
children,
containerRef,
filePath,
getSelectionLines,
onSplitHorizontal,
onSplitVertical,
onSplitWithNewChat,
onSplitWithNewBrowser,
onClosePane,
currentTabId,
availableTabs,
onMoveToTab,
onMoveToNewTab,
onEditAtLocation,
}: DiffViewerContextMenuProps) {
const getEditor = useCallback((): CodeEditorAdapter | null => {
const container = containerRef.current;
if (!container) {
return null;
}

return {
focus() {
container.focus();
},
getValue() {
return container.innerText;
},
setValue(_value: string) {},
revealPosition(_line: number, _column?: number) {},
getSelectionLines,
selectAll() {
const selection = window.getSelection();
if (!selection) return;
const range = document.createRange();
range.selectNodeContents(container);
selection.removeAllRanges();
selection.addRange(range);
},
cut() {},
copy() {
const selection = window.getSelection();
if (!selection || !isSelectionInsideContainer(container, selection)) {
return;
}

const selectedText = selection.toString();
if (!selectedText) {
return;
}

void navigator.clipboard.writeText(selectedText).catch((error) => {
console.error(
"[DiffViewerContextMenu] Failed to copy selection:",
error,
);
toast.error("Failed to copy selection", {
description: String(error),
});
});
},
paste() {},
openFind() {},
dispose() {},
};
}, [containerRef, getSelectionLines]);

const editorActions = useEditorActions({
getEditor,
filePath,
editable: false,
});

return (
<EditorContextMenu
editorActions={{
...editorActions,
onFind: undefined,
}}
leadingItems={
<ContextMenuItem onSelect={onEditAtLocation}>
<LuSquarePen className="size-4" />
Edit Here
</ContextMenuItem>
}
paneActions={{
onSplitHorizontal,
onSplitVertical,
onSplitWithNewChat,
onSplitWithNewBrowser,
onClosePane,
currentTabId,
availableTabs,
onMoveToTab,
onMoveToNewTab,
}}
>
{children}
</EditorContextMenu>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DiffViewerContextMenu } from "./DiffViewerContextMenu";
Loading
Loading