Files
EZPPLauncher/src/screens/Loading.svelte

234 lines
6.9 KiB
Svelte

<script lang="ts">
import Logo from '$assets/logo.png';
import { estimateRefreshRate } from '@/displayUtils';
import {
beatmapSets,
currentLoadingInfo,
currentSkin,
currentView,
firstStartup,
launcherStream,
launcherStreams,
launcherVersion,
newVersion,
osuBuild,
osuStream,
skins,
} from '@/global';
import {
cursorSmoothness,
osuInstallationPath,
preferredMode,
preferredType,
userSettings,
} from '@/userSettings';
import { animate, utils } from 'animejs';
import { onMount } from 'svelte';
import SetupWizard from './SetupWizard.svelte';
import Launch from './Launch.svelte';
import { currentUser, userAuth } from '@/userAuthentication';
import { ezppfarm } from '@/api/ezpp';
import { toast } from 'svelte-sonner';
import { currentUserInfo } from '@/data';
import {
getBeatmapSetsCount,
getEZPPLauncherStreams,
getReleaseStream,
getSkin,
getSkinsCount,
getVersion,
isValidOsuFolder,
} from '@/osuUtil';
import { git } from '@/api/git';
let ezppLogo: HTMLImageElement;
let spinnerCircle: SVGCircleElement;
let animateInterval: number | undefined;
//TODO: use this to check for updates upon launch
const doBPMAnimation = () => {
if (animateInterval) return;
animateInterval = window.setInterval(async () => {
animate(ezppLogo, {
scale: 1.1,
duration: 900,
ease: (t: number) => Math.pow(2, -5 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
onComplete: () => {},
});
await new Promise((resolve) => setTimeout(resolve, 200));
animate(ezppLogo, {
scale: 1,
duration: 900,
ease: (t: number) => (t - 1) ** 7 + 1,
onComplete: () => {},
});
}, 450);
};
const calculateCursorSmoothness = async () => {
const refreshRate = await estimateRefreshRate();
const hzMin = 60;
const hzMax = 144;
const durationMin = 70;
const durationMax = 180;
const duration =
durationMin + ((refreshRate - hzMin) / (hzMax - hzMin)) * (durationMax - durationMin);
cursorSmoothness.set(Math.round(duration));
};
const prepare = async () => {
await calculateCursorSmoothness();
const username = $userAuth.value('username').get('');
const password = $userAuth.value('password').get('');
if (username.length > 0 && password.length > 0) {
currentLoadingInfo.set('Logging in...');
try {
const loginResult = await ezppfarm.login(username, password);
if (loginResult && loginResult.user) {
toast.success('Login successful!', {
description: `Welcome back, ${loginResult.user.name}!`,
});
currentUser.set(loginResult.user);
} else {
toast.error('Login failed!', {
description: 'Please check your username and password.',
});
}
} catch {
toast.error('Server error occurred during login.', {
description: 'There was an issue connecting to the server. Please try again later.',
});
}
}
if ($currentUser) {
currentLoadingInfo.set('Loading user info...');
const userInfo = await ezppfarm.getUserInfo($currentUser.id);
if (userInfo) {
currentUserInfo.set(userInfo.player);
preferredMode.set(userInfo.player.info.preferred_mode);
preferredType.set(userInfo.player.info.preferred_type);
}
}
if (!$firstStartup) {
currentLoadingInfo.set('Checking osu installation path...');
const validFolder = await isValidOsuFolder($osuInstallationPath);
if (!validFolder) {
osuInstallationPath.set('');
$userSettings.value('osu_installation_path').del();
await $userSettings.save();
toast.error('Oops...', {
description: 'Your previously set osu! installation path seems to be invalid.',
});
} else {
currentLoadingInfo.set('Getting osu version...');
const osuReleaseStream = await getReleaseStream($osuInstallationPath);
osuStream.set(osuReleaseStream);
const osuVersion = await getVersion($osuInstallationPath);
osuBuild.set(osuVersion);
currentLoadingInfo.set('Counting beatmapsets...');
const beatmapSetCount = await getBeatmapSetsCount($osuInstallationPath);
if (beatmapSetCount !== null) beatmapSets.set(beatmapSetCount);
currentLoadingInfo.set('Counting skins...');
const skinCount = await getSkinsCount($osuInstallationPath);
if (skinCount !== null) skins.set(skinCount);
const skin: string = await getSkin($osuInstallationPath);
currentSkin.set(skin);
}
}
currentLoadingInfo.set('Checking for EZPPLauncher updates...');
const launcherUpdate = await git.hasUpdate($launcherVersion);
if (launcherUpdate) {
newVersion.set(launcherUpdate);
}
const ezpplauncherStreams = await getEZPPLauncherStreams();
if (ezpplauncherStreams) launcherStreams.set(ezpplauncherStreams);
const selectedLauncherStream = $userSettings.value('patcherStream').get('stable');
if ($launcherStreams.includes(selectedLauncherStream)) {
launcherStream.set(selectedLauncherStream);
}
animate(ezppLogo, {
opacity: [1, 0],
scale: [1, 1.05],
duration: 1000,
ease: (t: number) => (t - 1) ** 7 + 1,
onComplete: () => {},
});
animate(spinnerCircle, {
opacity: 0,
duration: 1000,
ease: (t: number) => (t - 1) ** 7 + 1,
onComplete: () => {},
});
setTimeout(() => {
if ($firstStartup) currentView.set(SetupWizard);
else currentView.set(Launch);
}, 250);
};
onMount(() => {
animate(ezppLogo, {
opacity: [0, 1],
scale: [0.95, 1],
duration: 900,
ease: (t: number) => (t - 1) ** 7 + 1,
onComplete: doBPMAnimation,
});
animate(spinnerCircle, {
strokeDashoffset: [0, -565],
duration: 1800,
easing: 'linear',
loop: true,
});
prepare();
return () => {
window.clearInterval(animateInterval);
utils.remove(spinnerCircle);
};
});
</script>
<div class="flex flex-col items-center justify-center mt-[50px] h-[calc(100vh-50px)] w-full">
<div class="relative w-80 h-80 flex items-center justify-center">
<svg
class="absolute top-0 left-0 w-full h-full animate-spin"
style="animation-duration: 5s;"
viewBox="0 0 208 208"
>
<circle
cx="104"
cy="104"
r="90"
fill="none"
stroke="#ff0098"
stroke-width="8"
stroke-linecap="round"
stroke-dasharray="180 385"
stroke-dashoffset="0"
bind:this={spinnerCircle}
/>
</svg>
<img
src={Logo}
alt="EZPPLauncher Logo"
class="w-52 h-52 mb-2 relative z-10"
bind:this={ezppLogo}
/>
</div>
<span class="text-theme-200 text-sm mt-5">{$currentLoadingInfo}</span>
</div>