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 (