smoothie/src/routes/+page.svelte
2026-04-29 13:57:44 +02:00

234 lines
5.9 KiB
Svelte

<script>
// LIBS
import { getVersion } from '@tauri-apps/api/app';
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
import '@webtui/css/components/spinner.css';
// MODULES
import { setupTrayIcon } from '$lib/trayicon';
import { getSettings, currentSettings } from '$lib/settings';
import { getBlenderReleases, blenderReleases } from '$lib/blenderfetch';
import { getInstalledVersions, installedVersionsStore } from '$lib/library.js';
import { downloadTasksStore } from '$lib/download.js';
import Library from '$lib/components/Library.svelte';
import Download from '$lib/components/Download.svelte';
import Settings from '$lib/components/Settings.svelte';
import Popup from '$lib/components/Popup.svelte';
import Dialog from '$lib/components/Dialog.svelte';
import Splash from '$lib/components/Splash.svelte';
// states
let fadeInSettings = { duration: 100 };
let fadeOutSettings = { duration: 100, delay: fadeInSettings.duration };
let activeTab = $state('library');
let blenderVersions = $state([]);
let installedVersions = $state([]);
let downloadTasks = $state([]);
let settings = $state();
let initialized = $state(false);
let version = $state('');
let loadingState = $state('loading'); // load, update, initialized
async function initStoresListeners() {
currentSettings.subscribe((value) => {
settings = value;
console.log('Loaded settings:', settings);
});
installedVersionsStore.subscribe((value) => {
installedVersions = value;
console.log('Loaded installed versions:', installedVersions);
});
blenderReleases.subscribe((value) => {
blenderVersions = value;
console.log('Loaded Blender releases:', blenderVersions);
});
downloadTasksStore.subscribe((value) => {
downloadTasks = value;
//console.log('Loaded download tasks:', downloadTasks);
});
}
onMount(async () => {
loadingState = 'Checking for Updates';
version = await getVersion();
loadingState = 'Loading Settings';
await getSettings();
loadingState = 'Fetching Blender Releases';
await getBlenderReleases();
loadingState = 'Loading your installs';
await getInstalledVersions();
loadingState = 'Setting up Tray';
await setupTrayIcon();
loadingState = 'initializing';
await initStoresListeners();
await setTimeout(() => {}, 1000);
loadingState = 'initialized';
});
</script>
<Popup content="Are you sure you want to delete this file?" type="confirm" />
<Dialog />
<div id="main">
{#if loadingState == 'initialized'}
<div class="tablist" role="tablist">
<div
role="tab"
tabindex="0"
class="tabitem"
class:selected={activeTab === 'library'}
aria-selected={activeTab === 'library'}
on:click={() => (activeTab = 'library')}
on:keydown={(e) => (e.key === 'Enter' || e.key === ' ' ? (activeTab = 'library') : null)}
>
Library
</div>
<div
role="tab"
tabindex="0"
class="tabitem"
class:selected={activeTab === 'download'}
aria-selected={activeTab === 'download'}
on:click={() => (activeTab = 'download')}
on:keydown={(e) => (e.key === 'Enter' || e.key === ' ' ? (activeTab = 'download') : null)}
>
Download
</div>
<div
role="tab"
tabindex="0"
class="tabitem"
class:selected={activeTab === 'settings'}
aria-selected={activeTab === 'settings'}
on:click={() => (activeTab = 'settings')}
on:keydown={(e) => (e.key === 'Enter' || e.key === ' ' ? (activeTab = 'settings') : null)}
>
Settings
</div>
</div>
<div id="tabcontent">
<div class="frame">
{#if activeTab === 'library'}
<div class="page" in:fade={fadeOutSettings} out:fade={fadeInSettings}>
<Library {installedVersions} />
</div>
{:else if activeTab === 'download'}
<div class="page" in:fade={fadeOutSettings} out:fade={fadeInSettings}>
<Download {downloadTasks} {installedVersions} {blenderVersions} />
</div>
{:else if activeTab === 'settings'}
<div class="page" in:fade={fadeOutSettings} out:fade={fadeInSettings}>
<Settings {settings} />
</div>
{/if}
</div>
</div>
<div class="version">v{version}</div>
{:else}
<div class="splash-wrapper" in:fade={{ duration: 100 }} out:fade={{ delay: 50, duration: 200 }}>
<Splash {loadingState} />
</div>
{/if}
</div>
<style>
:global(:root) {
--white: #f5f5f5;
--light-accent: #d4cdf2;
--light: #eaebed;
--black: #171a21;
--accent: #7d70ba;
--error: #ed1c24;
--warning: #f1d302;
--font: font-family: 'Europa Mono', monospace;
}
:global(*) {
color: var(--black);
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
:global(.svelte-tabs) {
box-sizing: border-box;
padding: 0;
margin: 0;
gap: 0;
}
:global(body) {
box-sizing: border-box;
padding: 0;
margin: 0;
background-color: var(--white);
}
.tablist {
width: 100%;
height: 3rem;
display: flex;
flex-direction: row;
}
.tabitem {
text-align: center;
line-height: 3rem;
color: var(--black);
width: 8rem;
cursor: pointer;
padding: 0 1.5rem;
}
.tabitem:hover {
background-color: var(--light-accent);
}
.tabitem.selected {
background-color: var(--light-accent);
border-bottom: 2px solid var(--accent);
}
#main {
display: flex;
flex-direction: column;
}
#tabcontent {
background-color: var(--light);
box-sizing: border-box;
height: calc(100vh - 3rem);
padding: 1rem;
max-height: 100%;
}
.frame {
background-color: var(--white);
padding: 1rem;
height: 100%;
border-radius: 0.5rem;
max-height: 100%;
overflow-y: scroll;
}
.page {
display: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.version {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 2;
text-align: right;
color: var(--light-accent);
}
.splash-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--white);
z-index: 1;
}
</style>