fix(desktop): replace dialog blur with theme-aware mask

This commit is contained in:
t8y2 2026-07-30 17:41:29 +08:00
parent 343c81f305
commit 45d7db7a10
No known key found for this signature in database
5 changed files with 6 additions and 42 deletions

View File

@ -34,7 +34,6 @@ import { useVisibilityChange } from "@/composables/useVisibilityChange";
import { useWebDavAutoUpload } from "@/composables/useWebDavAutoUpload";
import { useScheduledDatabaseBackups } from "@/composables/useScheduledDatabaseBackups";
import { shouldDrawDesktopWindowFrame } from "@/composables/useWindowControls";
import { startDialogBackdropSync, stopDialogBackdropSync } from "@/lib/app/dialogBackdrop";
import { useSaveSqlFolderSelection } from "@/composables/useSaveSqlFolderSelection";
import "@/i18n";
import { translateBackendError } from "@/i18n/backend-errors";
@ -2093,7 +2092,6 @@ onMounted(async () => {
});
applyTheme();
void applyUiScale(settingsStore.editorSettings.uiScale);
startDialogBackdropSync();
window.addEventListener("keydown", handleKeydown);
window.addEventListener("dbx-open-driver-store", openDriverStoreFromEvent);
if (isDesktop) {
@ -2154,7 +2152,6 @@ onMounted(async () => {
});
onUnmounted(() => {
stopDialogBackdropSync();
cleanupTauriListeners();
cleanupCloseActionPromptListener();
if (updateCheckTimer) {

View File

@ -26,7 +26,7 @@ async function startWindowDrag(event: PointerEvent) {
</script>
<template>
<DialogOverlay data-slot="dialog-overlay" v-bind="delegatedProps" :class="cn('data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 fixed inset-0 isolate z-50', props.class)">
<DialogOverlay data-slot="dialog-overlay" v-bind="delegatedProps" :class="cn('data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/25 dark:bg-background/70 duration-100 fixed inset-0 isolate z-50', props.class)">
<div v-if="isDesktop" aria-hidden="true" class="fixed inset-x-0 top-0 h-10 pointer-events-auto" data-tauri-drag-region @pointerdown="startWindowDrag" />
<slot />
</DialogOverlay>

View File

@ -1,24 +0,0 @@
const DIALOG_BACKDROP_CLASS = "dbx-dialog-backdrop-active";
let dialogBackdropObserver: MutationObserver | undefined;
function hasDialogOverlay(): boolean {
return Array.from(document.body.children).some((child) => child.matches('[data-slot="dialog-overlay"]') || child.querySelector('[data-slot="dialog-overlay"]'));
}
function syncDialogBackdrop() {
document.documentElement.classList.toggle(DIALOG_BACKDROP_CLASS, hasDialogOverlay());
}
export function startDialogBackdropSync() {
if (typeof document === "undefined" || dialogBackdropObserver) return;
dialogBackdropObserver = new MutationObserver(syncDialogBackdrop);
dialogBackdropObserver.observe(document.body, { childList: true });
syncDialogBackdrop();
}
export function stopDialogBackdropSync() {
dialogBackdropObserver?.disconnect();
dialogBackdropObserver = undefined;
document.documentElement.classList.remove(DIALOG_BACKDROP_CLASS);
}

View File

@ -6,8 +6,6 @@ const dialogContentSource = readFileSync(new URL("../../components/ui/dialog/Dia
const dialogScrollContentSource = readFileSync(new URL("../../components/ui/dialog/DialogScrollContent.vue", import.meta.url), "utf8");
const dialogOverlaySource = readFileSync(new URL("../../components/ui/dialog/DialogOverlay.vue", import.meta.url), "utf8");
const connectionDialogSource = readFileSync(new URL("../../components/connection/ConnectionDialog.vue", import.meta.url), "utf8");
const dialogBackdropSource = readFileSync(new URL("../../lib/app/dialogBackdrop.ts", import.meta.url), "utf8");
const appSource = readFileSync(new URL("../../App.vue", import.meta.url), "utf8");
const desktopIndexSource = readFileSync(new URL("../../../index.html", import.meta.url), "utf8");
const connectionDialogLegacyCss = readFileSync(new URL("../../../public/connection-dialog-legacy.css", import.meta.url), "utf8");
@ -46,15 +44,12 @@ describe("legacy WebView CSS fallbacks", () => {
expect(connectionDialogSource).toContain("max-height: calc(var(--dbx-viewport-height) - 2rem);");
});
it("blurs the stable app root instead of the transient dialog overlay", () => {
it("uses a lightweight theme-aware mask without full-window filters", () => {
expect(dialogOverlaySource).not.toContain("backdrop-filter");
expect(dialogOverlaySource).toContain("bg-black/10");
expect(globalsCss).toContain("html.dbx-dialog-backdrop-active #root");
expect(globalsCss).toContain("filter: blur(4px);");
expect(dialogBackdropSource).toContain("dialogBackdropObserver.observe(document.body, { childList: true })");
expect(dialogBackdropSource).not.toContain("subtree: true");
expect(appSource).toContain("startDialogBackdropSync();");
expect(appSource).toContain("stopDialogBackdropSync();");
expect(dialogOverlaySource).toContain("bg-black/25");
expect(dialogOverlaySource).toContain("dark:bg-background/70");
expect(globalsCss).not.toContain("dbx-dialog-backdrop");
expect(globalsCss).not.toContain("filter: blur(4px);");
});
it("keeps legacy tab triggers connected to the configured corner style", () => {

View File

@ -270,10 +270,6 @@
}
}
html.dbx-dialog-backdrop-active #root {
filter: blur(4px);
}
.dark {
--background: rgb(19 20 22);
--foreground: rgb(215 215 219);