From 6302a3815fa830b82d3ded28b05ad7cef7538754 Mon Sep 17 00:00:00 2001 From: Maxim Grigorev Date: Fri, 16 May 2025 20:19:23 +0700 Subject: [PATCH] feat: Add remote splash text loading via URLs --- config.json | 4 ++-- src/react/MainMenu.tsx | 20 ++++++++++++++++--- src/utils/splashText.ts | 43 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 src/utils/splashText.ts diff --git a/config.json b/config.json index ea27ca5a..0515aa40 100644 --- a/config.json +++ b/config.json @@ -26,7 +26,7 @@ } ], "rightSideText": "A Minecraft client clone in the browser!", - "splashText": "Gen is cooking!", + "splashText": "https://jsonplaceholder.typicode.com/posts/1", "pauseLinks": [ [ { @@ -37,4 +37,4 @@ } ] ] -} +} \ No newline at end of file diff --git a/src/react/MainMenu.tsx b/src/react/MainMenu.tsx index 7ed257c0..e706a3a8 100644 --- a/src/react/MainMenu.tsx +++ b/src/react/MainMenu.tsx @@ -1,9 +1,10 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { openURL } from 'renderer/viewer/lib/simpleUtils' import { useSnapshot } from 'valtio' import { haveDirectoryPicker } from '../utils' import { ConnectOptions } from '../connect' import { miscUiState } from '../globalState' +import { isRemoteSplashText, loadRemoteSplashText } from '../utils/splashText' import styles from './mainMenu.module.css' import Button from './Button' import ButtonWithTooltip from './ButtonWithTooltip' @@ -47,6 +48,19 @@ export default ({ singleplayerAvailable = true }: Props) => { const { appConfig } = useSnapshot(miscUiState) + const [splashText, setSplashText] = useState(appConfig?.splashText || '') + + useEffect(() => { + const loadSplashText = async () => { + if (appConfig?.splashText && isRemoteSplashText(appConfig.splashText)) { + const text = await loadRemoteSplashText(appConfig.splashText) + setSplashText(text) + } else { + setSplashText(appConfig?.splashText || '') + } + } + void loadSplashText() + }, [appConfig?.splashText]) if (!bottomRightLinks?.trim()) bottomRightLinks = undefined // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion @@ -75,7 +89,7 @@ export default ({ const connectToServerLongPress = useLongPress( () => { if (process.env.NODE_ENV === 'development') { - // Connect to :25565 + // Connect to :25565 const origin = window.location.hostname const connectOptions: ConnectOptions = { server: `${origin}:25565`, @@ -93,7 +107,7 @@ export default ({
- {appConfig?.splashText} + {splashText}
diff --git a/src/utils/splashText.ts b/src/utils/splashText.ts new file mode 100644 index 00000000..a46da218 --- /dev/null +++ b/src/utils/splashText.ts @@ -0,0 +1,43 @@ +const MAX_WORDS = 5 +const HTTPS_REGEX = /^https?:\/\// + +const limitWords = (text: string): string => { + const words = text.split(/\s+/) + if (words.length <= MAX_WORDS) { + return text + } + return words.slice(0, MAX_WORDS).join(' ') + '...' +} + +export const isRemoteSplashText = (text: string): boolean => { + return HTTPS_REGEX.test(text) +} + +export const loadRemoteSplashText = async (url: string): Promise => { + try { + const response = await fetch(url) + if (!response.ok) { + throw new Error(`Failed to fetch splash text: ${response.statusText}`) + } + try { + const json = await response.json() + + if (typeof json === 'object' && json !== null) { + if (json.title) return limitWords(json.title) + if (json.text) return limitWords(json.text) + if (json.message) return limitWords(json.message) + + return limitWords(JSON.stringify(json)) + } + + return limitWords(String(json)) + } catch (jsonError) { + + const text = await response.text() + return limitWords(text.trim()) + } + } catch (error) { + console.error('Error loading remote splash text:', error) + return 'Failed to load splash text!' + } +}