From ecd88771cbbcc34f7791053a9d16cdee72fbf197 Mon Sep 17 00:00:00 2001 From: Kensaa <54020933+Kensaa@users.noreply.github.com> Date: Tue, 2 Apr 2024 11:11:31 +0200 Subject: [PATCH] made profile fetching more reliable --- launcher/package.json | 2 +- launcher/src/components/ProfilePicker.tsx | 33 ++++++++++++++--------- launcher/src/stores/profiles.ts | 33 ++++++++++++++++------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/launcher/package.json b/launcher/package.json index 3701739..3696ada 100644 --- a/launcher/package.json +++ b/launcher/package.json @@ -3,7 +3,7 @@ "description": "A Minecraft launcher with auto-update feature to facilitate playing modded minecraft", "author": "Kensa", "private": true, - "version": "3.2.1", + "version": "3.2.2", "license": "MIT", "main": "dist-electron/electron.js", "scripts": { diff --git a/launcher/src/components/ProfilePicker.tsx b/launcher/src/components/ProfilePicker.tsx index bff9097..b98fcb2 100644 --- a/launcher/src/components/ProfilePicker.tsx +++ b/launcher/src/components/ProfilePicker.tsx @@ -9,24 +9,35 @@ import { useSelectedProfile } from '../stores/profiles' import LoadingSpinner from './LoadingSpinner' +import { useEffect, useState } from 'react' export default function ProfilePicker() { const profiles = useProfiles() const fetching = useIsFetching() const { selectedProfile, setSelectedProfile } = useSelectedProfile() + const [profile, setProfile] = useState(undefined) + useEffect(() => { + if (fetching) return + if (Object.keys(profiles).length === 0) return setProfile(undefined) + //this means that there is no server available, so no profile + if (selectedProfile[0] === '') return setProfile(undefined) + + const currentServer = profiles[selectedProfile[0]] + //this could happen, because due to the way that useProfile() is implemented, fetching is set to false before the profiles are set (because it is set in the useEffect of useProfiles(), so it takes one more render to set the profiles) + if (!currentServer) return setProfile(undefined) + + const profile = currentServer.profiles[selectedProfile[1]] + // this should never happen (because useSelectedProfile checks for invalid selected profile), but just in case + if (!profile) return setProfile(undefined) + + setProfile(profile) + }, [profiles, fetching, selectedProfile]) const selectProfile = (profile: [string, number]) => { setSelectedProfile(profile) ipcRenderer.send('set-selected-profile', profile) } - console.log(selectedProfile) - const currentServer = profiles[selectedProfile[0]] ?? { - profiles: [], - address: '' - } - const profile = currentServer.profiles[selectedProfile[1]] ?? undefined - return (
{fetching ? ( diff --git a/launcher/src/stores/profiles.ts b/launcher/src/stores/profiles.ts index ed4ff04..7469d93 100644 --- a/launcher/src/stores/profiles.ts +++ b/launcher/src/stores/profiles.ts @@ -5,6 +5,8 @@ import { useConfig } from './config' import { Profile } from '../types' import { useEffect, useState } from 'react' +const FETCH_TIMEOUT = 1500 + interface ServerProfiles { address: string profiles: Profile[] @@ -37,9 +39,17 @@ const useStore = create(set => { const seenServers = new Set() Promise.all( - servers.map(server => - fetch(server + '/profiles') + servers.map(server => { + const controller = new AbortController() + const timeoutID = setTimeout( + () => controller.abort(), + FETCH_TIMEOUT + ) + return fetch(server + '/profiles', { + signal: controller.signal + }) .then(res => { + clearTimeout(timeoutID) //get the server name from the headers const serverName = res.headers.get('X-Server-Name') if (serverName) { @@ -61,16 +71,16 @@ const useStore = create(set => { }) }) .catch(err => { - console.log(err) + //console.log(err) console.log('unable to fetch profiles from ' + server) return { name: server, data: { address: server, profiles: [] as Profile[] } } }) - ) + }) ).then(responses => { - console.log('resp', responses) + //console.log('resp', responses) for (const response of responses) { if (!response) continue @@ -145,10 +155,15 @@ export const useSelectedProfile = () => { !profiles[selectedProfile[0]] || selectedProfile[1] >= profiles[selectedProfile[0]].profiles.length ) { - const firstServer = Object.entries(profiles)[0] - const newSelectedProfile = [firstServer[0], 0] as [string, number] - ipcRenderer.send('set-selected-profile', newSelectedProfile) - setSelectedProfile(newSelectedProfile) + for (const server of Object.entries(profiles)) { + const [name, serverProfiles] = server + if (serverProfiles.profiles.length > 0) { + setSelectedProfile([name, 0]) + return + } + } + // in case there are no server available + setSelectedProfile(['', 0]) } }, [profiles, servers])