feat: improved splash text loading for better UI

This commit is contained in:
Maxim Grigorev 2025-05-20 16:56:38 +07:00
commit b4df2e1837
3 changed files with 52 additions and 69 deletions

View file

@ -26,8 +26,8 @@
}
],
"rightSideText": "A Minecraft client clone in the browser!",
"splashText": "GEN is cooking",
"splashTextFallback": "Welcome!",
"splashText": "https://jsonplaceholder.typicode.com/posts/1",
"pauseLinks": [
[
{

View file

@ -7,9 +7,8 @@ import { miscUiState } from '../globalState'
import {
isRemoteSplashText,
loadRemoteSplashText,
getDisplayText,
getCachedSplashText,
cacheSplashText,
hasSourceUrlChanged,
cacheSourceUrl,
clearSplashCache
} from '../utils/splashText'
@ -56,46 +55,65 @@ export default ({
singleplayerAvailable = true
}: Props) => {
const { appConfig } = useSnapshot(miscUiState)
const [splashText, setSplashText] = useState<string | undefined>(undefined)
useEffect(() => {
if (hasSourceUrlChanged(appConfig?.splashText)) {
clearSplashCache()
if (appConfig?.splashText && isRemoteSplashText(appConfig.splashText)) {
cacheSourceUrl(appConfig.splashText)
const determineAndSetSplashTextForSession = async () => {
const configSplashFromApp = appConfig?.splashText
const configFallbackFromApp = appConfig?.splashTextFallback
const isRemote = configSplashFromApp && isRemoteSplashText(configSplashFromApp)
let currentSourceKey: string
if (isRemote) {
currentSourceKey = configSplashFromApp!
} else {
currentSourceKey = configSplashFromApp || ''
}
}
}, [appConfig?.splashText])
const initialSplashText = getDisplayText(appConfig?.splashText, appConfig?.splashTextFallback)
const [splashText, setSplashText] = useState(initialSplashText)
const [showSplash, setShowSplash] = useState(false)
const storedSourceKey = localStorage.getItem('minecraft_splash_url')
useEffect(() => {
const timer = setTimeout(() => {
setShowSplash(true)
}, 100)
return () => clearTimeout(timer)
}, [])
if (storedSourceKey !== currentSourceKey) {
clearSplashCache()
cacheSourceUrl(currentSourceKey)
}
useEffect(() => {
const loadSplashText = async () => {
try {
if (appConfig?.splashText && isRemoteSplashText(appConfig.splashText)) {
const text = await loadRemoteSplashText(appConfig.splashText)
const cachedText = getCachedSplashText()
if (cachedText) {
setSplashText(cachedText)
return
}
if (text && text.trim() !== '') {
setSplashText(text)
cacheSplashText(text)
if (isRemote && configSplashFromApp) {
try {
const fetchedText = await loadRemoteSplashText(configSplashFromApp)
if (fetchedText && fetchedText.trim() !== '' && !fetchedText.includes('Failed to load')) {
cacheSplashText(fetchedText)
setSplashText(fetchedText)
} else {
const finalText = configFallbackFromApp || ''
setSplashText(finalText)
cacheSplashText(finalText)
}
} else if (appConfig?.splashText && !isRemoteSplashText(appConfig.splashText)) {
setSplashText(appConfig.splashText)
} catch (error) {
console.error('Session splash load error:', error)
const finalText = configFallbackFromApp || ''
setSplashText(finalText)
cacheSplashText(finalText)
}
} catch (error) {
console.error('Failed to load splash text:', error)
} else if (configSplashFromApp && typeof configSplashFromApp === 'string' && configSplashFromApp.trim() !== '') {
setSplashText(configSplashFromApp)
cacheSplashText(configSplashFromApp)
} else {
const finalText = configFallbackFromApp || ''
setSplashText(finalText)
cacheSplashText(finalText)
}
}
void loadSplashText()
}, [appConfig?.splashText, appConfig?.splashTextFallback])
if (appConfig) {
void determineAndSetSplashTextForSession()
}
}, [appConfig])
if (!bottomRightLinks?.trim()) bottomRightLinks = undefined
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
@ -142,7 +160,7 @@ export default ({
<div className={styles['game-title']}>
<div className={styles.minecraft}>
<div className={styles.edition} />
{showSplash && <span className={styles.splash}>{splashText}</span>}
<span className={styles.splash}>{splashText === undefined ? '' : splashText}</span>
</div>
</div>

View file

@ -54,20 +54,6 @@ export const cacheSourceUrl = (url: string): void => {
localStorage.setItem(SPLASH_URL_KEY, url)
}
export const hasSourceUrlChanged = (newUrl?: string): boolean => {
const cachedUrl = localStorage.getItem(SPLASH_URL_KEY)
if (!cachedUrl && !newUrl) {
return false
}
if ((!cachedUrl && newUrl) || (cachedUrl && !newUrl)) {
return true
}
return cachedUrl !== newUrl
}
export const clearSplashCache = (): void => {
localStorage.removeItem(SPLASH_CACHE_KEY)
}
@ -79,24 +65,3 @@ export const getCachedSplashText = (): string | null => {
export const cacheSplashText = (text: string): void => {
localStorage.setItem(SPLASH_CACHE_KEY, text)
}
export const getDisplayText = (splashText?: string, fallbackText?: string): string => {
const cachedText = getCachedSplashText()
if (cachedText) return cachedText
if (fallbackText) return fallbackText
if (splashText && isRemoteSplashText(splashText)) return ''
return splashText || ''
}
export const getDirectDisplayText = (splashText?: string, fallbackText?: string): string => {
if (splashText && !isRemoteSplashText(splashText)) return splashText
if (fallbackText) return fallbackText
return ''
}