mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-07 16:52:27 +08:00
Compare commits
5 Commits
fix/save-t
...
v0.4.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ce047f794 | ||
|
|
2c2d35940b | ||
|
|
02366cabfb | ||
|
|
3e0c3bcb36 | ||
|
|
ce2237f92e |
@@ -17,14 +17,8 @@ const drawioBaseUrl =
|
|||||||
process.env.NEXT_PUBLIC_DRAWIO_BASE_URL || "https://embed.diagrams.net"
|
process.env.NEXT_PUBLIC_DRAWIO_BASE_URL || "https://embed.diagrams.net"
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const {
|
const { drawioRef, handleDiagramExport, onDrawioLoad, resetDrawioReady } =
|
||||||
drawioRef,
|
useDiagram()
|
||||||
handleDiagramExport,
|
|
||||||
onDrawioLoad,
|
|
||||||
resetDrawioReady,
|
|
||||||
showSaveDialog,
|
|
||||||
setShowSaveDialog,
|
|
||||||
} = useDiagram()
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
// Extract current language from pathname (e.g., "/zh/about" → "zh")
|
// Extract current language from pathname (e.g., "/zh/about" → "zh")
|
||||||
@@ -38,30 +32,8 @@ export default function Home() {
|
|||||||
const [closeProtection, setCloseProtection] = useState(false)
|
const [closeProtection, setCloseProtection] = useState(false)
|
||||||
|
|
||||||
const chatPanelRef = useRef<ImperativePanelHandle>(null)
|
const chatPanelRef = useRef<ImperativePanelHandle>(null)
|
||||||
const isSavingRef = useRef(false)
|
|
||||||
const mouseOverDrawioRef = useRef(false)
|
|
||||||
const isMobileRef = useRef(false)
|
const isMobileRef = useRef(false)
|
||||||
|
|
||||||
// Reset saving flag when dialog closes (with delay to ignore lingering save events from draw.io)
|
|
||||||
useEffect(() => {
|
|
||||||
if (!showSaveDialog) {
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
isSavingRef.current = false
|
|
||||||
}, 1000)
|
|
||||||
return () => clearTimeout(timeout)
|
|
||||||
}
|
|
||||||
}, [showSaveDialog])
|
|
||||||
|
|
||||||
// Handle save from draw.io's built-in save button
|
|
||||||
// Note: draw.io sends save events for various reasons (focus changes, etc.)
|
|
||||||
// We use mouse position to determine if the user is interacting with draw.io
|
|
||||||
const handleDrawioSave = useCallback(() => {
|
|
||||||
if (!mouseOverDrawioRef.current) return
|
|
||||||
if (isSavingRef.current) return
|
|
||||||
isSavingRef.current = true
|
|
||||||
setShowSaveDialog(true)
|
|
||||||
}, [setShowSaveDialog])
|
|
||||||
|
|
||||||
// Load preferences from localStorage after mount
|
// Load preferences from localStorage after mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Restore saved locale and redirect if needed
|
// Restore saved locale and redirect if needed
|
||||||
@@ -204,12 +176,6 @@ export default function Home() {
|
|||||||
className={`h-full relative ${
|
className={`h-full relative ${
|
||||||
isMobile ? "p-1" : "p-2"
|
isMobile ? "p-1" : "p-2"
|
||||||
}`}
|
}`}
|
||||||
onMouseEnter={() => {
|
|
||||||
mouseOverDrawioRef.current = true
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
mouseOverDrawioRef.current = false
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30 relative">
|
<div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30 relative">
|
||||||
{isLoaded && (
|
{isLoaded && (
|
||||||
@@ -221,13 +187,13 @@ export default function Home() {
|
|||||||
ref={drawioRef}
|
ref={drawioRef}
|
||||||
onExport={handleDiagramExport}
|
onExport={handleDiagramExport}
|
||||||
onLoad={handleDrawioLoad}
|
onLoad={handleDrawioLoad}
|
||||||
onSave={handleDrawioSave}
|
|
||||||
baseUrl={drawioBaseUrl}
|
baseUrl={drawioBaseUrl}
|
||||||
urlParameters={{
|
urlParameters={{
|
||||||
ui: drawioUi,
|
ui: drawioUi,
|
||||||
spin: false,
|
spin: false,
|
||||||
libraries: false,
|
libraries: false,
|
||||||
saveAndExit: false,
|
saveAndExit: false,
|
||||||
|
noSaveBtn: true,
|
||||||
noExitBtn: true,
|
noExitBtn: true,
|
||||||
dark: darkMode,
|
dark: darkMode,
|
||||||
lang: currentLang,
|
lang: currentLang,
|
||||||
|
|||||||
@@ -432,7 +432,12 @@ export function ChatInput({
|
|||||||
open={showSaveDialog}
|
open={showSaveDialog}
|
||||||
onOpenChange={setShowSaveDialog}
|
onOpenChange={setShowSaveDialog}
|
||||||
onSave={(filename, format) =>
|
onSave={(filename, format) =>
|
||||||
saveDiagramToFile(filename, format, sessionId)
|
saveDiagramToFile(
|
||||||
|
filename,
|
||||||
|
format,
|
||||||
|
sessionId,
|
||||||
|
dict.save.savedSuccessfully,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
defaultFilename={`diagram-${new Date()
|
defaultFilename={`diagram-${new Date()
|
||||||
.toISOString()
|
.toISOString()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import type React from "react"
|
import type React from "react"
|
||||||
import { createContext, useContext, useEffect, useRef, useState } from "react"
|
import { createContext, useContext, useEffect, useRef, useState } from "react"
|
||||||
import type { DrawIoEmbedRef } from "react-drawio"
|
import type { DrawIoEmbedRef } from "react-drawio"
|
||||||
|
import { toast } from "sonner"
|
||||||
import type { ExportFormat } from "@/components/save-dialog"
|
import type { ExportFormat } from "@/components/save-dialog"
|
||||||
import { getApiEndpoint } from "@/lib/base-path"
|
import { getApiEndpoint } from "@/lib/base-path"
|
||||||
import {
|
import {
|
||||||
@@ -27,6 +28,7 @@ interface DiagramContextType {
|
|||||||
filename: string,
|
filename: string,
|
||||||
format: ExportFormat,
|
format: ExportFormat,
|
||||||
sessionId?: string,
|
sessionId?: string,
|
||||||
|
successMessage?: string,
|
||||||
) => void
|
) => void
|
||||||
getThumbnailSvg: () => Promise<string | null>
|
getThumbnailSvg: () => Promise<string | null>
|
||||||
isDrawioReady: boolean
|
isDrawioReady: boolean
|
||||||
@@ -236,6 +238,7 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
|
|||||||
filename: string,
|
filename: string,
|
||||||
format: ExportFormat,
|
format: ExportFormat,
|
||||||
sessionId?: string,
|
sessionId?: string,
|
||||||
|
successMessage?: string,
|
||||||
) => {
|
) => {
|
||||||
if (!drawioRef.current) {
|
if (!drawioRef.current) {
|
||||||
console.warn("Draw.io editor not ready")
|
console.warn("Draw.io editor not ready")
|
||||||
@@ -297,6 +300,14 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
|
|||||||
a.click()
|
a.click()
|
||||||
document.body.removeChild(a)
|
document.body.removeChild(a)
|
||||||
|
|
||||||
|
// Show success toast after download is initiated
|
||||||
|
if (successMessage) {
|
||||||
|
toast.success(successMessage, {
|
||||||
|
position: "bottom-left",
|
||||||
|
duration: 2500,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Delay URL revocation to ensure download completes
|
// Delay URL revocation to ensure download completes
|
||||||
if (!url.startsWith("data:")) {
|
if (!url.startsWith("data:")) {
|
||||||
setTimeout(() => URL.revokeObjectURL(url), 100)
|
setTimeout(() => URL.revokeObjectURL(url), 100)
|
||||||
|
|||||||
@@ -117,7 +117,8 @@
|
|||||||
"drawio": "Draw.io XML",
|
"drawio": "Draw.io XML",
|
||||||
"png": "PNG Image",
|
"png": "PNG Image",
|
||||||
"svg": "SVG Image"
|
"svg": "SVG Image"
|
||||||
}
|
},
|
||||||
|
"savedSuccessfully": "Saved successfully!"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"title": "Diagram History",
|
"title": "Diagram History",
|
||||||
|
|||||||
@@ -117,7 +117,8 @@
|
|||||||
"drawio": "Draw.io XML",
|
"drawio": "Draw.io XML",
|
||||||
"png": "PNG 画像",
|
"png": "PNG 画像",
|
||||||
"svg": "SVG 画像"
|
"svg": "SVG 画像"
|
||||||
}
|
},
|
||||||
|
"savedSuccessfully": "保存完了!"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"title": "ダイアグラム履歴",
|
"title": "ダイアグラム履歴",
|
||||||
|
|||||||
@@ -117,7 +117,8 @@
|
|||||||
"drawio": "Draw.io XML",
|
"drawio": "Draw.io XML",
|
||||||
"png": "PNG 图片",
|
"png": "PNG 图片",
|
||||||
"svg": "SVG 图片"
|
"svg": "SVG 图片"
|
||||||
}
|
},
|
||||||
|
"savedSuccessfully": "保存成功!"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"title": "图表历史",
|
"title": "图表历史",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-ai-draw-io",
|
"name": "next-ai-draw-io",
|
||||||
"version": "0.4.8",
|
"version": "0.4.9",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist-electron/main/index.js",
|
"main": "dist-electron/main/index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user