mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-19 19:20:49 +08:00
feat(PageTransition): enhance layer management to prevent blank flashes during transitions
This commit is contained in:
@@ -29,6 +29,18 @@
|
|||||||
|
|
||||||
&--stacked {
|
&--stacked {
|
||||||
display: none;
|
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;
|
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;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,16 +331,30 @@ export function PageTransition({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`page-transition${isAnimating ? ' page-transition--animating' : ''}`}>
|
<div className={`page-transition${isAnimating ? ' page-transition--animating' : ''}`}>
|
||||||
{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 (
|
||||||
<div
|
<div
|
||||||
key={layer.key}
|
key={layer.key}
|
||||||
className={[
|
className={[
|
||||||
'page-transition__layer',
|
'page-transition__layer',
|
||||||
layer.status === 'exiting' ? 'page-transition__layer--exit' : '',
|
layer.status === 'exiting' ? 'page-transition__layer--exit' : '',
|
||||||
layer.status === 'stacked' ? 'page-transition__layer--stacked' : '',
|
layer.status === 'stacked' ? 'page-transition__layer--stacked' : '',
|
||||||
|
shouldKeepStacked ? 'page-transition__layer--stacked-keep' : '',
|
||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(' ')}
|
.join(' ')}
|
||||||
|
aria-hidden={layer.status !== 'current'}
|
||||||
|
inert={layer.status !== 'current'}
|
||||||
ref={
|
ref={
|
||||||
layer.status === 'exiting'
|
layer.status === 'exiting'
|
||||||
? exitingLayerRef
|
? exitingLayerRef
|
||||||
@@ -351,7 +365,9 @@ export function PageTransition({
|
|||||||
>
|
>
|
||||||
{render(layer.location)}
|
{render(layer.location)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
);
|
||||||
|
});
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,12 +71,18 @@ export function AiProvidersOpenAIEditLayout() {
|
|||||||
const connectionStatus = useAuthStore((state) => state.connectionStatus);
|
const connectionStatus = useAuthStore((state) => state.connectionStatus);
|
||||||
const disableControls = connectionStatus !== 'connected';
|
const disableControls = connectionStatus !== 'connected';
|
||||||
|
|
||||||
|
const config = useConfigStore((state) => state.config);
|
||||||
const fetchConfig = useConfigStore((state) => state.fetchConfig);
|
const fetchConfig = useConfigStore((state) => state.fetchConfig);
|
||||||
const updateConfigValue = useConfigStore((state) => state.updateConfigValue);
|
const updateConfigValue = useConfigStore((state) => state.updateConfigValue);
|
||||||
const clearCache = useConfigStore((state) => state.clearCache);
|
const clearCache = useConfigStore((state) => state.clearCache);
|
||||||
|
const isCacheValid = useConfigStore((state) => state.isCacheValid);
|
||||||
|
|
||||||
const [providers, setProviders] = useState<OpenAIProviderConfig[]>([]);
|
const [providers, setProviders] = useState<OpenAIProviderConfig[]>(
|
||||||
const [loading, setLoading] = useState(true);
|
() => config?.openaiCompatibility ?? []
|
||||||
|
);
|
||||||
|
const [loading, setLoading] = useState(
|
||||||
|
() => !isCacheValid('openai-compatibility')
|
||||||
|
);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
|
|
||||||
const draftKey = useMemo(() => {
|
const draftKey = useMemo(() => {
|
||||||
@@ -156,7 +162,10 @@ export function AiProvidersOpenAIEditLayout() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
setLoading(true);
|
const hasValidCache = isCacheValid('openai-compatibility');
|
||||||
|
if (!hasValidCache) {
|
||||||
|
setLoading(true);
|
||||||
|
}
|
||||||
|
|
||||||
fetchConfig('openai-compatibility')
|
fetchConfig('openai-compatibility')
|
||||||
.then((value) => {
|
.then((value) => {
|
||||||
@@ -176,7 +185,7 @@ export function AiProvidersOpenAIEditLayout() {
|
|||||||
return () => {
|
return () => {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
};
|
};
|
||||||
}, [fetchConfig, showNotification, t]);
|
}, [fetchConfig, isCacheValid, showNotification, t]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
@@ -322,6 +331,8 @@ export function AiProvidersOpenAIEditLayout() {
|
|||||||
updateConfigValue,
|
updateConfigValue,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const resolvedLoading = !draft?.initialized;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Outlet
|
<Outlet
|
||||||
context={{
|
context={{
|
||||||
@@ -330,7 +341,7 @@ export function AiProvidersOpenAIEditLayout() {
|
|||||||
invalidIndexParam,
|
invalidIndexParam,
|
||||||
invalidIndex,
|
invalidIndex,
|
||||||
disableControls,
|
disableControls,
|
||||||
loading,
|
loading: resolvedLoading,
|
||||||
saving,
|
saving,
|
||||||
form,
|
form,
|
||||||
setForm,
|
setForm,
|
||||||
|
|||||||
Reference in New Issue
Block a user