fix: hide Draw.io loading flash with placeholder (#481)

* fix: hide Draw.io loading flash with placeholder

* style: auto-format with Biome

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Dayuan Jiang
2026-01-01 15:20:00 +09:00
committed by GitHub
parent 493ee168b1
commit 77a2f6f6fa
2 changed files with 39 additions and 23 deletions

View File

@@ -35,6 +35,7 @@ export default function Home() {
const [drawioUi, setDrawioUi] = useState<"min" | "sketch">("min") const [drawioUi, setDrawioUi] = useState<"min" | "sketch">("min")
const [darkMode, setDarkMode] = useState(false) const [darkMode, setDarkMode] = useState(false)
const [isLoaded, setIsLoaded] = useState(false) const [isLoaded, setIsLoaded] = useState(false)
const [isDrawioReady, setIsDrawioReady] = useState(false)
const [closeProtection, setCloseProtection] = useState(false) const [closeProtection, setCloseProtection] = useState(false)
const chatPanelRef = useRef<ImperativePanelHandle>(null) const chatPanelRef = useRef<ImperativePanelHandle>(null)
@@ -104,12 +105,18 @@ export default function Home() {
setIsLoaded(true) setIsLoaded(true)
}, [pathname, router]) }, [pathname, router])
const handleDrawioLoad = useCallback(() => {
setIsDrawioReady(true)
onDrawioLoad()
}, [onDrawioLoad])
const handleDarkModeChange = async () => { const handleDarkModeChange = async () => {
await saveDiagramToStorage() await saveDiagramToStorage()
const newValue = !darkMode const newValue = !darkMode
setDarkMode(newValue) setDarkMode(newValue)
localStorage.setItem("next-ai-draw-io-dark-mode", String(newValue)) localStorage.setItem("next-ai-draw-io-dark-mode", String(newValue))
document.documentElement.classList.toggle("dark", newValue) document.documentElement.classList.toggle("dark", newValue)
setIsDrawioReady(false)
resetDrawioReady() resetDrawioReady()
} }
@@ -118,6 +125,7 @@ export default function Home() {
const newUi = drawioUi === "min" ? "sketch" : "min" const newUi = drawioUi === "min" ? "sketch" : "min"
localStorage.setItem("drawio-theme", newUi) localStorage.setItem("drawio-theme", newUi)
setDrawioUi(newUi) setDrawioUi(newUi)
setIsDrawioReady(false)
resetDrawioReady() resetDrawioReady()
} }
@@ -131,6 +139,7 @@ export default function Home() {
newIsMobile !== isMobileRef.current newIsMobile !== isMobileRef.current
) { ) {
saveDiagramToStorage().catch(() => {}) saveDiagramToStorage().catch(() => {})
setIsDrawioReady(false)
resetDrawioReady() resetDrawioReady()
} }
isMobileRef.current = newIsMobile isMobileRef.current = newIsMobile
@@ -206,18 +215,21 @@ export default function Home() {
mouseOverDrawioRef.current = false mouseOverDrawioRef.current = false
}} }}
> >
<div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30"> <div className="h-full rounded-xl overflow-hidden shadow-soft-lg border border-border/30 relative">
{isLoaded ? ( {isLoaded && (
<div
className={`h-full w-full ${isDrawioReady ? "" : "invisible absolute inset-0"}`}
>
<DrawIoEmbed <DrawIoEmbed
key={`${drawioUi}-${darkMode}-${currentLang}`} key={`${drawioUi}-${darkMode}-${currentLang}`}
ref={drawioRef} ref={drawioRef}
onExport={handleDiagramExport} onExport={handleDiagramExport}
onLoad={onDrawioLoad} onLoad={handleDrawioLoad}
onSave={handleDrawioSave} onSave={handleDrawioSave}
baseUrl={drawioBaseUrl} baseUrl={drawioBaseUrl}
urlParameters={{ urlParameters={{
ui: drawioUi, ui: drawioUi,
spin: true, spin: false,
libraries: false, libraries: false,
saveAndExit: false, saveAndExit: false,
noExitBtn: true, noExitBtn: true,
@@ -225,9 +237,13 @@ export default function Home() {
lang: currentLang, lang: currentLang,
}} }}
/> />
) : ( </div>
<div className="h-full w-full flex items-center justify-center bg-background"> )}
<div className="animate-spin h-8 w-8 border-4 border-primary border-t-transparent rounded-full" /> {(!isLoaded || !isDrawioReady) && (
<div className="h-full w-full bg-background flex items-center justify-center">
<span className="text-muted-foreground">
Draw.io panel is loading...
</span>
</div> </div>
)} )}
</div> </div>

View File

@@ -32,7 +32,7 @@ const DRAWIO_ORIGIN = getOrigin(DRAWIO_BASE_URL)
// Normalize URL for iframe src - ensure no double slashes // Normalize URL for iframe src - ensure no double slashes
function normalizeUrl(url: string): string { function normalizeUrl(url: string): string {
// Remove trailing slash to avoid double slashes // Remove trailing slash to avoid double slashes
return url.replace(/\/$/, '') return url.replace(/\/$/, "")
} }
interface SessionState { interface SessionState {