fix(electron): prevent beforeunload prompt by using autosave

- Enable draw.io autosave and handle autosave events to update chartXML
- Clear modified state after autosave to avoid beforeunload prompts
- Disable confirmExit in draw.io configuration
- Set modified=false and keepmodified=false URL parameters
- Fix session save condition to also save when only diagram exists
This commit is contained in:
dayuan.jiang
2026-01-25 14:06:21 +09:00
parent 7656b64018
commit 7877b39fa1
3 changed files with 33 additions and 3 deletions

View File

@@ -13,8 +13,13 @@ import { useDiagram } from "@/contexts/diagram-context"
import { i18n, type Locale } from "@/lib/i18n/config"
export default function Home() {
const { drawioRef, handleDiagramExport, onDrawioLoad, resetDrawioReady } =
useDiagram()
const {
drawioRef,
handleDiagramExport,
handleDiagramAutoSave,
onDrawioLoad,
resetDrawioReady,
} = useDiagram()
const router = useRouter()
const pathname = usePathname()
// Extract current language from pathname (e.g., "/zh/about" → "zh")
@@ -84,6 +89,17 @@ export default function Home() {
onDrawioLoad()
}, [onDrawioLoad])
const handleDrawioAutoSave = useCallback(
(data: { xml?: string }) => {
handleDiagramAutoSave(data)
// Clear modified state to avoid beforeunload prompts in embed mode
if (drawioRef && "current" in drawioRef) {
drawioRef.current?.status({ message: "", modified: false })
}
},
[drawioRef, handleDiagramAutoSave],
)
const handleDarkModeChange = () => {
const newValue = !darkMode
setDarkMode(newValue)
@@ -174,13 +190,19 @@ export default function Home() {
<DrawIoEmbed
key={`${drawioUi}-${darkMode}-${currentLang}-${isElectron}`}
ref={drawioRef}
autosave
onAutoSave={handleDrawioAutoSave}
onExport={handleDiagramExport}
onLoad={handleDrawioLoad}
baseUrl={drawioBaseUrl}
configuration={{ confirmExit: false }}
urlParameters={{
ui: drawioUi,
spin: false,
libraries: false,
// Disable draw.io modified state to avoid beforeunload prompts
modified: false,
keepmodified: false,
saveAndExit: false,
noSaveBtn: true,
noExitBtn: true,

View File

@@ -677,7 +677,7 @@ export default function ChatPanel({
// Debounce: save after 1 second of no changes
localStorageDebounceRef.current = setTimeout(async () => {
try {
if (messages.length > 0) {
if (messages.length > 0 || hasDiagramNow) {
const sessionData = await buildSessionData({
// Only capture thumbnail if there was a diagram AND this isn't a no-diagram session
withThumbnail: hasDiagramNow && !isNodiagramSession,
@@ -699,6 +699,7 @@ export default function ChatPanel({
}
}
}, [
chartXML,
messages,
status,
sessionIsAvailable,

View File

@@ -23,6 +23,7 @@ interface DiagramContextType {
resolverRef: React.Ref<((value: string) => void) | null>
drawioRef: React.Ref<DrawIoEmbedRef | null>
handleDiagramExport: (data: any) => void
handleDiagramAutoSave: (data: { xml?: string }) => void
clearDiagram: () => void
saveDiagramToFile: (
filename: string,
@@ -267,6 +268,11 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
}
}
const handleDiagramAutoSave = (data: { xml?: string }) => {
if (!data?.xml) return
setChartXML(data.xml)
}
const clearDiagram = () => {
const emptyDiagram = `<mxfile><diagram name="Page-1" id="page-1"><mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel></diagram></mxfile>`
// Skip validation for trusted internal template (loadDiagram also sets chartXML)
@@ -391,6 +397,7 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
resolverRef,
drawioRef,
handleDiagramExport,
handleDiagramAutoSave,
clearDiagram,
saveDiagramToFile,
getThumbnailSvg,