feat: Refactor API interactions and enhance user settings management
- Updated ezpp API to include user info retrieval and improved error handling. - Introduced new writable stores for current user info and loading states. - Added gamemode enums and utility functions for better gamemode handling. - Refactored global state management to use consistent naming conventions. - Enhanced loading and login components to provide better user feedback. - Updated user settings to include preferred mode and type. - Improved layout and page components for better state management and user experience.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import Badge from '@/components/ui/badge/badge.svelte';
|
||||
import Button from '@/components/ui/button/button.svelte';
|
||||
import * as Select from '@/components/ui/select';
|
||||
import { beatmap_sets, current_view, server_connection_fails, server_ping } from '@/global';
|
||||
import { beatmapSets, currentView, serverConnectionFails, serverPing } from '@/global';
|
||||
import {
|
||||
LoaderCircle,
|
||||
Logs,
|
||||
@@ -14,19 +14,26 @@
|
||||
Gamepad2,
|
||||
WifiOff,
|
||||
Settings2,
|
||||
Drum,
|
||||
Cherry,
|
||||
Piano,
|
||||
Circle,
|
||||
LogOut,
|
||||
LogIn,
|
||||
} from 'lucide-svelte';
|
||||
import { Circle } from 'radix-icons-svelte';
|
||||
import NumberFlow from '@number-flow/svelte';
|
||||
import * as AlertDialog from '@/components/ui/alert-dialog';
|
||||
import Progress from '@/components/ui/progress/progress.svelte';
|
||||
import { numberHumanReadable } from '@/utils';
|
||||
import { scale } from 'svelte/transition';
|
||||
import { formatTimeReadable, numberHumanReadable } from '@/utils';
|
||||
import { fade, scale } from 'svelte/transition';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import Label from '@/components/ui/label/label.svelte';
|
||||
import {
|
||||
cursorSmoothening,
|
||||
customCursor,
|
||||
osuInstallationPath,
|
||||
preferredMode,
|
||||
preferredType,
|
||||
reduceAnimations,
|
||||
userSettings,
|
||||
} from '@/userSettings';
|
||||
@@ -35,11 +42,30 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import Login from './Login.svelte';
|
||||
import { currentUser } from '@/userAuthentication';
|
||||
import { currentUser, userAuth } from '@/userAuthentication';
|
||||
import {
|
||||
getGamemodeInt,
|
||||
getGamemodeName,
|
||||
getModeAndTypeFromGamemode,
|
||||
modeIntToStr,
|
||||
typeIntToStr,
|
||||
validModeTypeCombinationsSorted,
|
||||
} from '@/gamemode';
|
||||
import { currentUserInfo } from '@/data';
|
||||
|
||||
let selectedTab = $state('home');
|
||||
let launching = $state(false);
|
||||
|
||||
let selectedGamemode = $derived(
|
||||
getGamemodeInt(modeIntToStr($preferredMode), typeIntToStr($preferredType))
|
||||
);
|
||||
let selectedMode = $derived(getModeAndTypeFromGamemode(selectedGamemode).mode);
|
||||
let selectedType = $derived(getModeAndTypeFromGamemode(selectedGamemode).type);
|
||||
|
||||
const updateGamemode = (newGamemode: string) => {
|
||||
selectedGamemode = Number(newGamemode);
|
||||
};
|
||||
|
||||
const browse_osu_installation = async () => {
|
||||
const selectedPath = await open({
|
||||
directory: true,
|
||||
@@ -48,9 +74,9 @@
|
||||
});
|
||||
|
||||
if (typeof selectedPath === 'string') {
|
||||
/* if (selectedPath === $osuInstallationPath) {
|
||||
if (selectedPath === $osuInstallationPath) {
|
||||
return;
|
||||
} */
|
||||
}
|
||||
const validFolder: boolean = await invoke('valid_osu_folder', { folder: selectedPath });
|
||||
if (!validFolder) {
|
||||
toast.error(
|
||||
@@ -62,6 +88,13 @@
|
||||
$userSettings.value('osu_installation_path').set(selectedPath);
|
||||
$userSettings.save();
|
||||
toast.success('osu! installation path set successfully.');
|
||||
|
||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
||||
folder: selectedPath,
|
||||
});
|
||||
if (beatmapSetCount) {
|
||||
beatmapSets.set(beatmapSetCount);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -94,53 +127,184 @@
|
||||
<div class="flex flex-row gap-2">
|
||||
<!-- <Badge variant="destructive">Owner</Badge> -->
|
||||
{#if !$currentUser}
|
||||
<Button variant="outline" size="sm" onclick={() => current_view.set(Login)}>Login</Button>
|
||||
<Button variant="outline" size="sm" onclick={() => currentView.set(Login)}>
|
||||
<LogIn size={16} />
|
||||
Login
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onclick={async () => {
|
||||
$userAuth.value('username').del();
|
||||
$userAuth.value('password').del();
|
||||
await $userAuth.save();
|
||||
toast.success('Logout successful!', {
|
||||
description: 'See you soon!',
|
||||
});
|
||||
currentUser.set(undefined);
|
||||
currentUserInfo.set(undefined);
|
||||
}}
|
||||
>
|
||||
<LogOut size={16} />
|
||||
Logout
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-6 h-full px-3">
|
||||
<Select.Root type="single">
|
||||
<Select.Trigger
|
||||
class="border-theme-800/90 bg-theme-900/90 !text-muted-foreground font-semibold"
|
||||
{#if $currentUser}
|
||||
<div class="flex flex-col gap-6 h-full px-3">
|
||||
<div
|
||||
in:scale={{ duration: $reduceAnimations ? 0 : 400, start: 0.98 }}
|
||||
out:scale={{ duration: $reduceAnimations ? 0 : 400, start: 0.98 }}
|
||||
>
|
||||
<Select.Root
|
||||
type="single"
|
||||
value={selectedGamemode.toFixed()}
|
||||
onValueChange={updateGamemode}
|
||||
>
|
||||
<Select.Trigger
|
||||
class="border-theme-800/90 bg-theme-900/90 !text-muted-foreground font-semibold"
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
{#if selectedMode === 0}
|
||||
<Circle size={16} class="text-theme-200" />
|
||||
{:else if selectedMode === 1}
|
||||
<Drum size={16} class="text-theme-200" />
|
||||
{:else if selectedMode === 2}
|
||||
<Cherry size={16} class="text-theme-200" />
|
||||
{:else if selectedMode === 3}
|
||||
<Piano size={16} class="text-theme-200" />
|
||||
{/if}
|
||||
{getGamemodeName(modeIntToStr(selectedMode), typeIntToStr(selectedType))}
|
||||
</div>
|
||||
</Select.Trigger>
|
||||
<Select.Content class="bg-theme-950 border border-theme-900 rounded-lg">
|
||||
{#each validModeTypeCombinationsSorted as gamemode}
|
||||
{@const gamemod = getModeAndTypeFromGamemode(gamemode)}
|
||||
<Select.Item value={gamemode.toFixed()}>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
{#if gamemod.mode === 0}
|
||||
<Circle size={16} class="text-theme-200" />
|
||||
{:else if gamemod.mode === 1}
|
||||
<Drum size={16} class="text-theme-200" />
|
||||
{:else if gamemod.mode === 2}
|
||||
<Cherry size={16} class="text-theme-200" />
|
||||
{:else if gamemod.mode === 3}
|
||||
<Piano size={16} class="text-theme-200" />
|
||||
{/if}
|
||||
{getGamemodeName(modeIntToStr(gamemod.mode), typeIntToStr(gamemod.type))}
|
||||
</div>
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</div>
|
||||
<div
|
||||
class="bg-theme-900/90 border border-theme-800/90 rounded-lg p-2"
|
||||
in:scale={{
|
||||
duration: $reduceAnimations ? 0 : 400,
|
||||
delay: $reduceAnimations ? 0 : 50,
|
||||
start: 0.98,
|
||||
}}
|
||||
out:scale={{
|
||||
duration: $reduceAnimations ? 0 : 400,
|
||||
delay: $reduceAnimations ? 0 : 50,
|
||||
start: 0.98,
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Circle class="text-muted-foreground" />
|
||||
osu!vn
|
||||
<Logs class="text-muted-foreground" size="16" />
|
||||
<span class="font-semibold text-muted-foreground text-sm">Mode Stats</span>
|
||||
</div>
|
||||
</Select.Trigger>
|
||||
<Select.Content class="bg-theme-950 border border-theme-900 rounded-lg">
|
||||
<Select.Item value="light">osu!vn</Select.Item>
|
||||
<Select.Item value="dark">osu!rx</Select.Item>
|
||||
<Select.Item value="system">osu!ap</Select.Item>
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
<div class="bg-theme-900/90 border border-theme-800/90 rounded-lg p-2">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Logs class="text-muted-foreground" size="16" />
|
||||
<span class="font-semibold text-muted-foreground text-sm">Mode Stats</span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 mt-2 border-t border-theme-800 pt-2 pb-2">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span class="text-sm text-muted-foreground font-semibold">Rank</span>
|
||||
<span class="text-lg font-semibold text-theme-50">#727</span>
|
||||
<div class="grid grid-cols-2 mt-2 border-t border-theme-800 pt-2 pb-2">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span class="text-sm text-muted-foreground font-semibold">Rank</span>
|
||||
<div class="flex items-center h-full text-lg font-semibold text-theme-50">
|
||||
{#if $currentUserInfo}
|
||||
<div in:fade>
|
||||
<NumberFlow
|
||||
trend={0}
|
||||
prefix="#"
|
||||
value={$currentUserInfo.stats[selectedGamemode].rank ?? 0}
|
||||
></NumberFlow>
|
||||
</div>
|
||||
{:else}
|
||||
<div in:fade>
|
||||
<LoaderCircle class="animate-spin" size={21} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span class="text-sm text-muted-foreground font-semibold">PP</span>
|
||||
<div class="flex items-center h-full text-lg font-semibold text-theme-50">
|
||||
{#if $currentUserInfo}
|
||||
<div in:fade>
|
||||
<NumberFlow trend={0} value={$currentUserInfo.stats[selectedGamemode].pp ?? 0}
|
||||
></NumberFlow>
|
||||
</div>
|
||||
{:else}
|
||||
<div in:fade>
|
||||
<LoaderCircle class="animate-spin" size={21} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<span class="text-sm text-muted-foreground font-semibold">PP</span>
|
||||
<span class="text-lg font-semibold text-theme-50">727</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-[1fr_auto] border-t border-theme-800 pt-2">
|
||||
<span class="text-sm text-muted-foreground font-semibold">Accuracy</span>
|
||||
<span class="text-sm font-semibold text-end text-theme-50">72.72%</span>
|
||||
<div class="grid grid-cols-[1fr_auto] border-t border-theme-800 pt-2">
|
||||
<span class="text-sm text-muted-foreground font-semibold">Accuracy</span>
|
||||
<div
|
||||
class="flex items-center flex-row-reverse h-full text-sm text-end font-semibold text-theme-50"
|
||||
>
|
||||
{#if $currentUserInfo}
|
||||
<div in:fade>
|
||||
<NumberFlow
|
||||
trend={0}
|
||||
suffix="%"
|
||||
value={$currentUserInfo.stats[selectedGamemode].acc.toFixed(2) ?? 0}
|
||||
></NumberFlow>
|
||||
</div>
|
||||
{:else}
|
||||
<div in:fade>
|
||||
<LoaderCircle class="animate-spin" size={21} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<span class="text-sm text-muted-foreground font-semibold">Play Count</span>
|
||||
<span class="text-sm font-semibold text-end text-theme-50">727</span>
|
||||
<span class="text-sm text-muted-foreground font-semibold">Play Count</span>
|
||||
<div
|
||||
class="flex items-center flex-row-reverse h-full text-sm text-end font-semibold text-theme-50"
|
||||
>
|
||||
{#if $currentUserInfo}
|
||||
<div in:fade>
|
||||
<NumberFlow trend={0} value={$currentUserInfo.stats[selectedGamemode].plays ?? 0}
|
||||
></NumberFlow>
|
||||
</div>
|
||||
{:else}
|
||||
<div in:fade>
|
||||
<LoaderCircle class="animate-spin" size={21} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<span class="text-sm text-muted-foreground font-semibold">Play Time</span>
|
||||
<span class="text-sm font-semibold text-end text-theme-50">727h</span>
|
||||
<span class="text-sm text-muted-foreground font-semibold">Play Time</span>
|
||||
<div
|
||||
class="flex items-center flex-row-reverse h-full text-sm text-end font-semibold text-theme-50"
|
||||
>
|
||||
{#if $currentUserInfo}
|
||||
<div in:fade>
|
||||
{formatTimeReadable($currentUserInfo.stats[selectedGamemode].playtime ?? 0)}
|
||||
</div>
|
||||
{:else}
|
||||
<div in:fade>
|
||||
<LoaderCircle class="animate-spin" size={21} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="mt-auto bg-theme-900/90 border border-theme-800/90 rounded-lg p-2">
|
||||
<!-- <div class="mt-auto bg-theme-900/90 border border-theme-800/90 rounded-lg p-2">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<Users class="text-muted-foreground" size="16" />
|
||||
@@ -149,7 +313,8 @@
|
||||
<Badge class="h-5 bg-green-500/20 hover:bg-green-500/20 text-green-500">3 online</Badge>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex flex-col gap-6 w-full h-full bg-theme-900/40 p-6">
|
||||
<div
|
||||
@@ -188,21 +353,21 @@
|
||||
</div>
|
||||
<div class="relative font-bold text-xl text-blue-400">
|
||||
<div
|
||||
class="absolute top-1 left-1/2 -translate-x-1/2 {!$beatmap_sets
|
||||
class="absolute top-1 left-1/2 -translate-x-1/2 {!$beatmapSets
|
||||
? 'opacity-100'
|
||||
: 'opacity-0'} transition-opacity duration-1000"
|
||||
>
|
||||
<LoaderCircle class="animate-spin" />
|
||||
</div>
|
||||
<div
|
||||
class="{!$beatmap_sets
|
||||
class="{!$beatmapSets
|
||||
? 'opacity-0'
|
||||
: 'opacity-100'} transition-opacity duration-1000"
|
||||
>
|
||||
{#if $reduceAnimations}
|
||||
<span>{numberHumanReadable($beatmap_sets ?? 0)}</span>
|
||||
<span>{numberHumanReadable($beatmapSets ?? 0)}</span>
|
||||
{:else}
|
||||
<NumberFlow value={$beatmap_sets ?? 0} trend={0} />
|
||||
<NumberFlow value={$beatmapSets ?? 0} trend={0} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -249,38 +414,38 @@
|
||||
class="bg-theme-800/90 border border-theme-700/90 rounded-lg px-2 py-4 w-full flex flex-col gap-1 items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="flex items-center justify-center p-2 rounded-lg {$server_connection_fails > 1
|
||||
class="flex items-center justify-center p-2 rounded-lg {$serverConnectionFails > 1
|
||||
? 'bg-red-500/20'
|
||||
: 'bg-green-500/20'}"
|
||||
>
|
||||
{#if $server_connection_fails > 1}
|
||||
{#if $serverConnectionFails > 1}
|
||||
<WifiOff class="text-red-500" size="26" />
|
||||
{:else}
|
||||
<Wifi class="text-green-500" size="26" />
|
||||
{/if}
|
||||
</div>
|
||||
<div
|
||||
class="relative font-bold text-xl {$server_connection_fails > 1
|
||||
class="relative font-bold text-xl {$serverConnectionFails > 1
|
||||
? 'text-red-400'
|
||||
: 'text-green-400'}"
|
||||
>
|
||||
<div
|
||||
class="absolute top-1 left-1/2 -translate-x-1/2 {!$server_ping ||
|
||||
$server_connection_fails > 1
|
||||
class="absolute top-1 left-1/2 -translate-x-1/2 {!$serverPing ||
|
||||
$serverConnectionFails > 1
|
||||
? 'opacity-100'
|
||||
: 'opacity-0'} transition-opacity duration-1000"
|
||||
>
|
||||
<LoaderCircle class="animate-spin" />
|
||||
</div>
|
||||
<div
|
||||
class="{!$server_ping || $server_connection_fails > 1
|
||||
class="{!$serverPing || $serverConnectionFails > 1
|
||||
? 'opacity-0'
|
||||
: 'opacity-100'} transition-opacity duration-1000"
|
||||
>
|
||||
{#if $reduceAnimations}
|
||||
<span>{$server_ping}ms</span>
|
||||
<span>{$serverPing}ms</span>
|
||||
{:else}
|
||||
<NumberFlow value={$server_ping ?? 0} trend={0} suffix="ms" />
|
||||
<NumberFlow value={$serverPing ?? 0} trend={0} suffix="ms" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -289,6 +454,7 @@
|
||||
</div>
|
||||
<Button
|
||||
size="lg"
|
||||
disabled={launching || $osuInstallationPath === ''}
|
||||
onclick={() => {
|
||||
launching = true;
|
||||
setTimeout(() => {
|
||||
@@ -297,7 +463,7 @@
|
||||
}}
|
||||
>
|
||||
<Play />
|
||||
Launch {$server_connection_fails > 1 ? 'offline' : ''}
|
||||
Launch {$serverConnectionFails > 1 ? 'offline' : ''}
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
@@ -320,7 +486,7 @@
|
||||
|
||||
<span class="text-sm text-muted-foreground font-semibold">Beatmap Sets</span>
|
||||
<span class="text-sm font-semibold text-end text-theme-50"
|
||||
>{numberHumanReadable($beatmap_sets ?? 0)}</span
|
||||
>{numberHumanReadable($beatmapSets ?? 0)}</span
|
||||
>
|
||||
|
||||
<span class="text-sm text-muted-foreground font-semibold">Skins</span>
|
||||
|
@@ -1,8 +1,14 @@
|
||||
<script lang="ts">
|
||||
import Logo from '$assets/logo.png';
|
||||
import { estimateRefreshRate } from '@/displayUtils';
|
||||
import { current_view, first_startup } from '@/global';
|
||||
import { cursorSmoothness } from '@/userSettings';
|
||||
import { beatmapSets, currentLoadingInfo, currentView, firstStartup } from '@/global';
|
||||
import {
|
||||
cursorSmoothness,
|
||||
osuInstallationPath,
|
||||
preferredMode,
|
||||
preferredType,
|
||||
userSettings,
|
||||
} from '@/userSettings';
|
||||
import { animate, utils } from 'animejs';
|
||||
import { onMount } from 'svelte';
|
||||
import SetupWizard from './SetupWizard.svelte';
|
||||
@@ -10,6 +16,8 @@
|
||||
import { currentUser, userAuth } from '@/userAuthentication';
|
||||
import { ezppfarm } from '@/api/ezpp';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { currentUserInfo } from '@/data';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
|
||||
let ezppLogo: HTMLImageElement;
|
||||
let spinnerCircle: SVGCircleElement;
|
||||
@@ -54,24 +62,59 @@
|
||||
|
||||
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}!`,
|
||||
});
|
||||
|
||||
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.',
|
||||
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.',
|
||||
});
|
||||
}
|
||||
} 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: boolean = await invoke('valid_osu_folder', {
|
||||
folder: $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('Counting beatmapsets...');
|
||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
||||
folder: $osuInstallationPath,
|
||||
});
|
||||
if (beatmapSetCount) {
|
||||
beatmapSets.set(beatmapSetCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animate(ezppLogo, {
|
||||
@@ -88,8 +131,8 @@
|
||||
onComplete: () => {},
|
||||
});
|
||||
setTimeout(() => {
|
||||
if ($first_startup) current_view.set(SetupWizard);
|
||||
else current_view.set(Launch);
|
||||
if ($firstStartup) currentView.set(SetupWizard);
|
||||
else currentView.set(Launch);
|
||||
}, 250);
|
||||
};
|
||||
|
||||
@@ -144,4 +187,5 @@
|
||||
bind:this={ezppLogo}
|
||||
/>
|
||||
</div>
|
||||
<span class="text-theme-200 font-semibold">{$currentLoadingInfo}</span>
|
||||
</div>
|
||||
|
@@ -4,12 +4,14 @@
|
||||
import Button from '@/components/ui/button/button.svelte';
|
||||
import Input from '@/components/ui/input/input.svelte';
|
||||
import Label from '@/components/ui/label/label.svelte';
|
||||
import { current_view } from '@/global';
|
||||
import { currentView } from '@/global';
|
||||
import { currentUser, userAuth } from '@/userAuthentication';
|
||||
import { animate } from 'animejs';
|
||||
import { LoaderCircle } from 'lucide-svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import Launch from './Launch.svelte';
|
||||
import { currentUserInfo } from '@/data';
|
||||
import { preferredMode, preferredType } from '@/userSettings';
|
||||
|
||||
let username = $state('');
|
||||
let password = $state('');
|
||||
@@ -52,7 +54,7 @@
|
||||
await $userAuth.save();
|
||||
|
||||
currentUser.set(loginResult.user);
|
||||
current_view.set(Launch);
|
||||
currentView.set(Launch);
|
||||
} else {
|
||||
toast.error('Login failed!', {
|
||||
description: 'Please check your username and password.',
|
||||
@@ -65,6 +67,16 @@
|
||||
});
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
if ($currentUser) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
import Checkbox from '@/components/ui/checkbox/checkbox.svelte';
|
||||
import { cursorSmoothening, customCursor, reduceAnimations, userSettings } from '@/userSettings';
|
||||
import Label from '@/components/ui/label/label.svelte';
|
||||
import { current_view } from '@/global';
|
||||
import { beatmapSets, currentView } from '@/global';
|
||||
import Launch from './Launch.svelte';
|
||||
import Confetti from 'svelte-confetti';
|
||||
|
||||
@@ -65,6 +65,13 @@
|
||||
autoDetectedOsuPath = false;
|
||||
manualSelectValid = true;
|
||||
$userSettings.value('osu_installation_path').set(osuInstallationPath);
|
||||
|
||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
||||
folder: osuInstallationPath,
|
||||
});
|
||||
if (beatmapSetCount) {
|
||||
beatmapSets.set(beatmapSetCount);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -90,7 +97,7 @@
|
||||
class="mt-4"
|
||||
onclick={async () => {
|
||||
await $userSettings.save();
|
||||
current_view.set(Launch);
|
||||
currentView.set(Launch);
|
||||
}}
|
||||
>
|
||||
Finish
|
||||
|
Reference in New Issue
Block a user