From 237cca56802a07bb57b7a47500635198d2bfb4a8 Mon Sep 17 00:00:00 2001 From: LTbinglingfeng Date: Sun, 1 Feb 2026 02:18:14 +0800 Subject: [PATCH] feat(PageTransition): enhance layer management to prevent blank flashes during transitions --- src/components/common/PageTransition.scss | 14 +++++++++++++- src/components/common/PageTransition.tsx | 20 ++++++++++++++++++-- src/pages/AiProvidersOpenAIEditLayout.tsx | 21 ++++++++++++++++----- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/components/common/PageTransition.scss b/src/components/common/PageTransition.scss index e0d21e8..6ff5600 100644 --- a/src/components/common/PageTransition.scss +++ b/src/components/common/PageTransition.scss @@ -29,6 +29,18 @@ &--stacked { display: none; + + // Keep the previous layer rendered (but invisible) to avoid a blank flash when popping back. + // Older stacked layers remain `display: none` for performance. + &.page-transition__layer--stacked-keep { + display: flex; + position: absolute; + inset: 0; + overflow: hidden; + pointer-events: none; + opacity: 0; + will-change: transform, opacity; + } } } @@ -36,7 +48,7 @@ will-change: transform, opacity; } - &--animating &__layer:not(.page-transition__layer--exit) { + &--animating &__layer:not(.page-transition__layer--exit):not(.page-transition__layer--stacked) { position: relative; } } diff --git a/src/components/common/PageTransition.tsx b/src/components/common/PageTransition.tsx index a89ceac..a91e59a 100644 --- a/src/components/common/PageTransition.tsx +++ b/src/components/common/PageTransition.tsx @@ -331,16 +331,30 @@ export function PageTransition({ return (
- {layers.map((layer) => ( + {(() => { + const currentIndex = layers.findIndex((layer) => layer.status === 'current'); + const resolvedCurrentIndex = currentIndex === -1 ? layers.length - 1 : currentIndex; + const keepStackedIndex = layers + .slice(0, resolvedCurrentIndex) + .map((layer, index) => ({ layer, index })) + .reverse() + .find(({ layer }) => layer.status === 'stacked')?.index; + + return layers.map((layer, index) => { + const shouldKeepStacked = layer.status === 'stacked' && index === keepStackedIndex; + return (
{render(layer.location)}
- ))} + ); + }); + })()}
); } diff --git a/src/pages/AiProvidersOpenAIEditLayout.tsx b/src/pages/AiProvidersOpenAIEditLayout.tsx index 18687a5..321b0c4 100644 --- a/src/pages/AiProvidersOpenAIEditLayout.tsx +++ b/src/pages/AiProvidersOpenAIEditLayout.tsx @@ -71,12 +71,18 @@ export function AiProvidersOpenAIEditLayout() { const connectionStatus = useAuthStore((state) => state.connectionStatus); const disableControls = connectionStatus !== 'connected'; + const config = useConfigStore((state) => state.config); const fetchConfig = useConfigStore((state) => state.fetchConfig); const updateConfigValue = useConfigStore((state) => state.updateConfigValue); const clearCache = useConfigStore((state) => state.clearCache); + const isCacheValid = useConfigStore((state) => state.isCacheValid); - const [providers, setProviders] = useState([]); - const [loading, setLoading] = useState(true); + const [providers, setProviders] = useState( + () => config?.openaiCompatibility ?? [] + ); + const [loading, setLoading] = useState( + () => !isCacheValid('openai-compatibility') + ); const [saving, setSaving] = useState(false); const draftKey = useMemo(() => { @@ -156,7 +162,10 @@ export function AiProvidersOpenAIEditLayout() { useEffect(() => { let cancelled = false; - setLoading(true); + const hasValidCache = isCacheValid('openai-compatibility'); + if (!hasValidCache) { + setLoading(true); + } fetchConfig('openai-compatibility') .then((value) => { @@ -176,7 +185,7 @@ export function AiProvidersOpenAIEditLayout() { return () => { cancelled = true; }; - }, [fetchConfig, showNotification, t]); + }, [fetchConfig, isCacheValid, showNotification, t]); useEffect(() => { if (loading) return; @@ -322,6 +331,8 @@ export function AiProvidersOpenAIEditLayout() { updateConfigValue, ]); + const resolvedLoading = !draft?.initialized; + return (