mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-13 04:59:51 +08:00
refactor(canvas): getDrawioSrc takes the editor's source, and CanvasStage can be given one
This commit is contained in:
@@ -3,7 +3,12 @@ import { DrawioFrame } from "@/components/canvas/drawio-frame"
|
|||||||
import { useLocale } from "@/components/canvas/locale-context"
|
import { useLocale } from "@/components/canvas/locale-context"
|
||||||
import { useDiagram } from "@/contexts/diagram-context"
|
import { useDiagram } from "@/contexts/diagram-context"
|
||||||
import { useDictionary } from "@/hooks/use-dictionary"
|
import { useDictionary } from "@/hooks/use-dictionary"
|
||||||
import { DRAWIO_CSS, getDrawioSrc } from "@/lib/drawio/drawio-config"
|
import {
|
||||||
|
DRAWIO_CSS,
|
||||||
|
type DrawioSource,
|
||||||
|
getDrawioSrc,
|
||||||
|
webDrawioSource,
|
||||||
|
} from "@/lib/drawio/drawio-config"
|
||||||
import { keepCenter, refitIfRecent } from "@/lib/drawio/editor-bridge"
|
import { keepCenter, refitIfRecent } from "@/lib/drawio/editor-bridge"
|
||||||
import { i18n, type Locale } from "@/lib/i18n/config"
|
import { i18n, type Locale } from "@/lib/i18n/config"
|
||||||
import { STORAGE_KEYS } from "@/lib/storage"
|
import { STORAGE_KEYS } from "@/lib/storage"
|
||||||
@@ -28,6 +33,7 @@ export function CanvasStage({
|
|||||||
style,
|
style,
|
||||||
hideOverlays = false,
|
hideOverlays = false,
|
||||||
overlay,
|
overlay,
|
||||||
|
drawioSource,
|
||||||
waitForSavedLocale = false,
|
waitForSavedLocale = false,
|
||||||
}: {
|
}: {
|
||||||
className?: string
|
className?: string
|
||||||
@@ -36,6 +42,9 @@ export function CanvasStage({
|
|||||||
hideOverlays?: boolean
|
hideOverlays?: boolean
|
||||||
/** Rendered over the canvas once draw.io is ready */
|
/** Rendered over the canvas once draw.io is ready */
|
||||||
overlay?: (size: CanvasSize) => React.ReactNode
|
overlay?: (size: CanvasSize) => React.ReactNode
|
||||||
|
/** Where the editor comes from; none: the web app's own copy (the MCP
|
||||||
|
* shell passes what its server configured) */
|
||||||
|
drawioSource?: DrawioSource
|
||||||
/** Web app: the page is about to switch to the language picked last
|
/** Web app: the page is about to switch to the language picked last
|
||||||
* time (useSavedLocale in the workspace); do not load draw.io in the
|
* time (useSavedLocale in the workspace); do not load draw.io in the
|
||||||
* URL's language meanwhile */
|
* URL's language meanwhile */
|
||||||
@@ -74,11 +83,10 @@ export function CanvasStage({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isElectron = !!(window as { electronAPI?: unknown }).electronAPI
|
|
||||||
// The theme class is set before the page renders; the settings store
|
// The theme class is set before the page renders; the settings store
|
||||||
// may not have read it yet
|
// may not have read it yet
|
||||||
const dark = document.documentElement.classList.contains("dark")
|
const dark = document.documentElement.classList.contains("dark")
|
||||||
setSrc(getDrawioSrc({ lang, isElectron, dark }))
|
setSrc(getDrawioSrc(drawioSource ?? webDrawioSource(lang), dark))
|
||||||
}, [lang])
|
}, [lang])
|
||||||
|
|
||||||
// A new iframe starts over: draw.io reports load and access again
|
// A new iframe starts over: draw.io reports load and access again
|
||||||
@@ -94,8 +102,7 @@ export function CanvasStage({
|
|||||||
if (editorAccess !== false || !src) return
|
if (editorAccess !== false || !src) return
|
||||||
const startedDark = new URL(src).searchParams.get("dark") === "1"
|
const startedDark = new URL(src).searchParams.get("dark") === "1"
|
||||||
if (startedDark === isDark) return
|
if (startedDark === isDark) return
|
||||||
const isElectron = !!(window as { electronAPI?: unknown }).electronAPI
|
setSrc(getDrawioSrc(drawioSource ?? webDrawioSource(lang), isDark))
|
||||||
setSrc(getDrawioSrc({ lang, isElectron, dark: isDark }))
|
|
||||||
}, [isDark, editorAccess, lang, src])
|
}, [isDark, editorAccess, lang, src])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
+41
-22
@@ -6,28 +6,49 @@ import { BLANK_MXFILE } from "@/packages/mcp-server/src/pages.ts"
|
|||||||
const EXTERNAL_DRAWIO_URL = process.env.NEXT_PUBLIC_DRAWIO_BASE_URL || ""
|
const EXTERNAL_DRAWIO_URL = process.env.NEXT_PUBLIC_DRAWIO_BASE_URL || ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL of the draw.io editor iframe. By default this is the copy bundled in
|
* Where the editor comes from and how it starts. The web app fills it from
|
||||||
* public/drawio, served from our own origin.
|
* its build settings (webDrawioSource); the MCP's canvas shell from the
|
||||||
|
* config its server writes into the page.
|
||||||
*/
|
*/
|
||||||
export function getDrawioSrc({
|
export interface DrawioSource {
|
||||||
lang,
|
/** The editor page: the bundled copy's index.html on this origin, or an
|
||||||
isElectron,
|
* external draw.io (cross-origin, limited features) */
|
||||||
dark,
|
editorUrl: string
|
||||||
}: {
|
/** draw.io theme (its ui parameter); none: draw.io's default and the
|
||||||
lang: Locale
|
* user's own pick */
|
||||||
isElectron: boolean
|
ui?: string
|
||||||
dark: boolean
|
/** Language in draw.io's naming ("zh-tw"); none: draw.io's own pick */
|
||||||
}): string {
|
lang?: string
|
||||||
// index.html: Next.js does not serve directory indexes
|
/** No calls to external services (the desktop app) */
|
||||||
const base =
|
offline?: boolean
|
||||||
EXTERNAL_DRAWIO_URL ||
|
}
|
||||||
`${window.location.origin}${getAssetUrl("/drawio/index.html")}`
|
|
||||||
const url = new URL(base)
|
/**
|
||||||
|
* The web app's editor: the copy in public/drawio, served from our own
|
||||||
|
* origin (index.html, as Next.js serves no directory indexes), or
|
||||||
|
* NEXT_PUBLIC_DRAWIO_BASE_URL; the simple theme in the page's language.
|
||||||
|
*/
|
||||||
|
export function webDrawioSource(lang: Locale): DrawioSource {
|
||||||
|
const isElectron = !!(window as { electronAPI?: unknown }).electronAPI
|
||||||
|
return {
|
||||||
|
editorUrl: EXTERNAL_DRAWIO_URL || getAssetUrl("/drawio/index.html"),
|
||||||
|
ui: "simple",
|
||||||
|
// draw.io names Traditional Chinese "zh-tw"
|
||||||
|
lang: lang === "zh-Hant" ? "zh-tw" : lang,
|
||||||
|
offline: isElectron && !EXTERNAL_DRAWIO_URL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** URL of the draw.io editor iframe */
|
||||||
|
export function getDrawioSrc(source: DrawioSource, dark: boolean): string {
|
||||||
|
const url = new URL(source.editorUrl, window.location.href)
|
||||||
const params: Record<string, string> = {
|
const params: Record<string, string> = {
|
||||||
embed: "1",
|
embed: "1",
|
||||||
proto: "json",
|
proto: "json",
|
||||||
configure: "1",
|
configure: "1",
|
||||||
ui: "simple",
|
}
|
||||||
|
if (source.ui) params.ui = source.ui
|
||||||
|
Object.assign(params, {
|
||||||
spin: "0",
|
spin: "0",
|
||||||
libraries: "0",
|
libraries: "0",
|
||||||
noSaveBtn: "1",
|
noSaveBtn: "1",
|
||||||
@@ -36,11 +57,9 @@ export function getDrawioSrc({
|
|||||||
// draw.io's own dark mode (switched in place later when the editor
|
// draw.io's own dark mode (switched in place later when the editor
|
||||||
// can be driven directly)
|
// can be driven directly)
|
||||||
dark: dark ? "1" : "0",
|
dark: dark ? "1" : "0",
|
||||||
// draw.io names Traditional Chinese "zh-tw"
|
})
|
||||||
lang: lang === "zh-Hant" ? "zh-tw" : lang,
|
if (source.lang) params.lang = source.lang
|
||||||
}
|
if (source.offline) params.offline = "1"
|
||||||
// No calls to external services from the desktop app
|
|
||||||
if (isElectron && !EXTERNAL_DRAWIO_URL) params.offline = "1"
|
|
||||||
for (const [key, value] of Object.entries(params)) {
|
for (const [key, value] of Object.entries(params)) {
|
||||||
url.searchParams.set(key, value)
|
url.searchParams.set(key, value)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user