Compare commits

..

1 Commits

Author SHA1 Message Date
dayuan.jiang
5fd7d4364f feat: show success toast after diagram download completes
- Add optional successMessage parameter to saveDiagramToFile()
- Show toast after file download is initiated, not when dialog opens
- Add i18n strings for success message (en/ja/zh)

This is the correct implementation for issue #479 - showing feedback
after the actual save completes rather than when the save dialog opens.
2026-01-04 12:56:50 +09:00
2 changed files with 38 additions and 4 deletions

View File

@@ -17,8 +17,14 @@ 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 { drawioRef, handleDiagramExport, onDrawioLoad, resetDrawioReady } = const {
useDiagram() drawioRef,
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")
@@ -32,8 +38,30 @@ 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
@@ -176,6 +204,12 @@ 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 && (
@@ -187,13 +221,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,

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-ai-draw-io", "name": "next-ai-draw-io",
"version": "0.4.9", "version": "0.4.8",
"license": "Apache-2.0", "license": "Apache-2.0",
"private": true, "private": true,
"main": "dist-electron/main/index.js", "main": "dist-electron/main/index.js",