mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(app): show cached auth splash art without a fade-in flash (#1907)
This commit is contained in:
1 parent
79cf57abe4
commit
5eb7822691
4 files changed
+29
-52
No files matched your search
@@ -41,7 +41,7 @@ const AuthLayoutContent = observer(function AuthLayoutContent({children}: {child
|
||||
const registerFormDraftsRef = useRef<Map<string, AuthRegisterFormDraft>>(new Map());
|
||||
const scrollerRef = useRef<ScrollerHandle>(null);
|
||||
const location = useLocation();
|
||||
const {patternReady, splashLoaded, splashDimensions} = useAuthBackground(splashUrl, foodPatternUrl);
|
||||
const {patternReady, splashDimensions} = useAuthBackground(splashUrl, foodPatternUrl);
|
||||
const handleSetSplashUrl = useCallback(
|
||||
(url: string | null) => {
|
||||
if (splashUrlRef.current === url) return;
|
||||
@@ -196,7 +196,6 @@ const AuthLayoutContent = observer(function AuthLayoutContent({children}: {child
|
||||
>
|
||||
<AuthBackground
|
||||
splashUrl={splashUrl}
|
||||
splashLoaded={splashLoaded}
|
||||
splashDimensions={splashDimensions}
|
||||
splashScale={splashScale}
|
||||
patternReady={patternReady}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import Accessibility from '@app/features/accessibility/state/Accessibility';
|
||||
import styles from '@app/features/app/components/layout/AuthLayout.module.css';
|
||||
import {GuildSplashCardAlignment} from '@fluxer/constants/src/GuildConstants';
|
||||
import type {ValueOf} from '@fluxer/constants/src/ValueOf';
|
||||
import {motion} from 'framer-motion';
|
||||
import type React from 'react';
|
||||
|
||||
const getSplashAlignmentStyles = (alignment: ValueOf<typeof GuildSplashCardAlignment>) => {
|
||||
@@ -20,7 +18,6 @@ const getSplashAlignmentStyles = (alignment: ValueOf<typeof GuildSplashCardAlign
|
||||
|
||||
export interface AuthBackgroundProps {
|
||||
splashUrl: string | null;
|
||||
splashLoaded: boolean;
|
||||
splashDimensions?: {width: number; height: number} | null;
|
||||
splashScale?: number | null;
|
||||
patternReady: boolean;
|
||||
@@ -32,7 +29,6 @@ export interface AuthBackgroundProps {
|
||||
|
||||
export const AuthBackground: React.FC<AuthBackgroundProps> = ({
|
||||
splashUrl,
|
||||
splashLoaded,
|
||||
splashDimensions,
|
||||
splashScale,
|
||||
patternReady,
|
||||
@@ -47,13 +43,7 @@ export const AuthBackground: React.FC<AuthBackgroundProps> = ({
|
||||
if (useFullCover) {
|
||||
return (
|
||||
<div className={className} data-flx="auth.flow.auth-background.div">
|
||||
<motion.div
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: splashLoaded ? 1 : 0}}
|
||||
transition={{duration: Accessibility.useReducedMotion ? 0 : 0.5, ease: 'easeInOut'}}
|
||||
style={{position: 'absolute', inset: 0}}
|
||||
data-flx="auth.flow.auth-background.div--2"
|
||||
>
|
||||
<div style={{position: 'absolute', inset: 0}} data-flx="auth.flow.auth-background.div--2">
|
||||
<img
|
||||
src={splashUrl}
|
||||
alt=""
|
||||
@@ -68,17 +58,14 @@ export const AuthBackground: React.FC<AuthBackgroundProps> = ({
|
||||
data-flx="auth.flow.auth-background.img"
|
||||
/>
|
||||
<div className={styles.splashOverlay} data-flx="auth.flow.auth-background.splash-overlay" />
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={styles.rightSplit} data-flx="auth.flow.auth-background.right-split">
|
||||
<motion.div
|
||||
<div
|
||||
className={styles.splashImage}
|
||||
initial={{opacity: 0}}
|
||||
animate={{opacity: splashLoaded ? 1 : 0}}
|
||||
transition={{duration: Accessibility.useReducedMotion ? 0 : 0.5, ease: 'easeInOut'}}
|
||||
style={{
|
||||
width: splashDimensions.width,
|
||||
height: splashDimensions.height,
|
||||
@@ -104,7 +91,7 @@ export const AuthBackground: React.FC<AuthBackgroundProps> = ({
|
||||
data-flx="auth.flow.auth-background.img--2"
|
||||
/>
|
||||
<div className={styles.splashOverlay} data-flx="auth.flow.auth-background.splash-overlay--2" />
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import * as ImageCacheUtils from '@app/features/messaging/utils/ImageCacheUtils';
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
interface ImageDimensions {
|
||||
@@ -12,62 +13,53 @@ interface PatternImageLoaderResult {
|
||||
}
|
||||
|
||||
interface SplashImageLoaderResult {
|
||||
loaded: boolean;
|
||||
dimensions: ImageDimensions | null;
|
||||
}
|
||||
|
||||
interface AuthBackgroundResult {
|
||||
patternReady: boolean;
|
||||
splashLoaded: boolean;
|
||||
splashDimensions: ImageDimensions | null;
|
||||
}
|
||||
|
||||
export function usePatternImageLoader(patternUrl: string): PatternImageLoaderResult {
|
||||
const [patternReady, setPatternReady] = useState(false);
|
||||
const [patternReady, setPatternReady] = useState(() => ImageCacheUtils.hasImage(patternUrl));
|
||||
useEffect(() => {
|
||||
const img = new Image();
|
||||
const handleLoad = () => setPatternReady(true);
|
||||
img.addEventListener('load', handleLoad, {once: true});
|
||||
img.src = patternUrl;
|
||||
return () => img.removeEventListener('load', handleLoad);
|
||||
if (ImageCacheUtils.hasImage(patternUrl)) {
|
||||
setPatternReady(true);
|
||||
return;
|
||||
}
|
||||
setPatternReady(false);
|
||||
return ImageCacheUtils.loadImage(patternUrl, () => setPatternReady(true));
|
||||
}, [patternUrl]);
|
||||
return {patternReady};
|
||||
}
|
||||
|
||||
export function useSplashImageLoader(imageUrl: string | null): SplashImageLoaderResult {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [dimensions, setDimensions] = useState<ImageDimensions | null>(null);
|
||||
const [dimensions, setDimensions] = useState<ImageDimensions | null>(
|
||||
() => ImageCacheUtils.getImageSize(imageUrl) ?? null,
|
||||
);
|
||||
useEffect(() => {
|
||||
if (!imageUrl) {
|
||||
setLoaded(false);
|
||||
setDimensions(null);
|
||||
const cached = ImageCacheUtils.getImageSize(imageUrl);
|
||||
if (cached) {
|
||||
setDimensions(cached);
|
||||
return;
|
||||
}
|
||||
let isMounted = true;
|
||||
const img = new Image();
|
||||
const handleLoad = () => {
|
||||
if (!isMounted) return;
|
||||
setLoaded(true);
|
||||
setDimensions({
|
||||
width: img.naturalWidth,
|
||||
height: img.naturalHeight,
|
||||
});
|
||||
};
|
||||
img.addEventListener('load', handleLoad, {once: true});
|
||||
img.src = imageUrl;
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
setDimensions(null);
|
||||
if (!imageUrl) {
|
||||
return;
|
||||
}
|
||||
return ImageCacheUtils.loadImage(imageUrl, () => {
|
||||
setDimensions(ImageCacheUtils.getImageSize(imageUrl) ?? null);
|
||||
});
|
||||
}, [imageUrl]);
|
||||
return {loaded, dimensions};
|
||||
return {dimensions};
|
||||
}
|
||||
|
||||
export function useAuthBackground(splashUrl: string | null, patternUrl: string): AuthBackgroundResult {
|
||||
const {patternReady} = usePatternImageLoader(patternUrl);
|
||||
const {loaded: splashLoaded, dimensions: splashDimensions} = useSplashImageLoader(splashUrl);
|
||||
const {dimensions: splashDimensions} = useSplashImageLoader(splashUrl);
|
||||
return {
|
||||
patternReady,
|
||||
splashLoaded,
|
||||
splashDimensions,
|
||||
};
|
||||
}
|
||||
@@ -61,7 +61,7 @@ export const InvitePagePreviewModal: React.FC<InvitePagePreviewModalProps> = obs
|
||||
}
|
||||
return null;
|
||||
}, [previewSplashUrl, guild?.id, guild?.splash]);
|
||||
const {patternReady, splashLoaded, splashDimensions} = useAuthBackground(splashUrl, foodPatternUrl);
|
||||
const {patternReady, splashDimensions} = useAuthBackground(splashUrl, foodPatternUrl);
|
||||
const shouldShowSplash = Boolean(splashUrl && splashDimensions);
|
||||
const handleClose = useCallback(() => {
|
||||
ModalCommands.pop();
|
||||
@@ -122,7 +122,6 @@ export const InvitePagePreviewModal: React.FC<InvitePagePreviewModalProps> = obs
|
||||
<AuthBackground
|
||||
className={clsx(styles.background, !shouldShowSplash && authLayoutStyles.patternHost)}
|
||||
splashUrl={splashUrl}
|
||||
splashLoaded={splashLoaded}
|
||||
splashDimensions={splashDimensions}
|
||||
patternReady={patternReady}
|
||||
patternImageUrl={foodPatternUrl}
|
||||
|
||||
Reference in new issue
Block a user