This commit is contained in:
2026-06-04 16:36:27 +02:00
3 changed files with 160 additions and 128 deletions
+10 -3
View File
@@ -24,10 +24,13 @@ pub fn get_osu_user_config<P: AsRef<Path>>(
return None; return None;
} }
let current_user = std::env::var("USERNAME").unwrap_or_else(|_| "Admin".to_string()); let current_user = std::env::var("USERNAME")
.or_else(|_| std::env::var("USER"))
.unwrap_or_else(|_| "Admin".to_string());
let osu_config_path = osu_folder_path let osu_config_path = osu_folder_path
.as_ref() .as_ref()
.join(format!("osu!.{}.cfg", current_user)); .join(format!("osu!.{}.cfg", current_user));
println!("Looking for user config at: {:?}", osu_config_path);
if !osu_config_path.exists() { if !osu_config_path.exists() {
return None; return None;
} }
@@ -48,7 +51,9 @@ pub fn set_osu_user_config_vals(
osu_folder_path: &str, osu_folder_path: &str,
key_values: &[(&str, Option<&str>)], key_values: &[(&str, Option<&str>)],
) -> Result<bool, String> { ) -> Result<bool, String> {
let current_user = std::env::var("USERNAME").unwrap_or_else(|_| "Admin".to_string()); let current_user = std::env::var("USERNAME")
.or_else(|_| std::env::var("USER"))
.unwrap_or_else(|_| "Admin".to_string());
let osu_config_path = Path::new(osu_folder_path).join(format!("osu!.{}.cfg", current_user)); let osu_config_path = Path::new(osu_folder_path).join(format!("osu!.{}.cfg", current_user));
if !osu_config_path.exists() { if !osu_config_path.exists() {
@@ -310,7 +315,9 @@ pub async fn is_net8_installed() -> bool {
} }
let stdout_str = String::from_utf8_lossy(&output.stdout); let stdout_str = String::from_utf8_lossy(&output.stdout);
stdout_str.lines().any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8.")) stdout_str
.lines()
.any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8."))
} }
Err(_) => false, Err(_) => false,
} }
+1 -1
View File
@@ -135,7 +135,7 @@
const localThemes = await getThemes(); const localThemes = await getThemes();
const lastThemeName = await config_theme.get('Default'); const lastThemeName = await config_theme.get('Default');
const last_theme = localThemes.find((t) => t.name === lastThemeName); const last_theme = localThemes.find((t) => t.name === lastThemeName);
if (!last_theme) { if (!last_theme || $platform === 'linux') {
await config.value<string>('theme').set('Default'); await config.value<string>('theme').set('Default');
loadTheme(localThemes[0], $custom_theme_container!, await config_theme_volume.get(0.15)); loadTheme(localThemes[0], $custom_theme_container!, await config_theme_volume.get(0.15));
} else { } else {
+148 -123
View File
@@ -1827,148 +1827,173 @@
}} }}
out:fly={{ duration: $reduceAnimations ? 0 : 400, y: -5, opacity: 0 }} out:fly={{ duration: $reduceAnimations ? 0 : 400, y: -5, opacity: 0 }}
> >
<ScrollContainer class="pt-8" topOffset={45}> {#if $platform === 'linux'}
<div class="grid w-full gap-1 grid-cols-3 p-3 pr-5"> <div
{#each $custom_themes as theme (theme.folder_name)} class="flex flex-col items-center gap-4 mt-12 px-6 text-center h-full justify-center"
<div >
class="group overflow-hidden rounded-3xl border {$active_custom_theme && <!-- currently there is a bug when applying themes on Linux, the Launcher freezes, also when trying to load assets via the assetProtocol it fails because it says the asset was loaded insecurely -->
$active_custom_theme.folder_name === theme.folder_name <span class="text-2xl font-bold drop-shadow-lg"
? 'border-primary' >Custom themes are not supported on Linux yet(we are working on it!)</span
: 'border-theme-800'} bg-theme-950 transition hover:border-white/20 h-73.75" >
> <span class="text-muted-foreground font-semibold drop-shadow-lg"
<img >Due to technical limitations on Linux, custom themes are currently not supported.
src={theme.preview || DefaultThemePreview} </span>
alt="Preview of {theme.name}" <span class="text-muted-foreground font-semibold drop-shadow-lg"
class="mb-2 h-40 w-full rounded-t-3xl object-cover object-center pointer-events-none select-none" >We are working on a solution to bring custom themes to Linux in a future update, but
/> we don't have an ETA yet. Stay tuned!</span
<div class="flex flex-col gap-1 p-3"> >
<div class="mb-4 flex items-center justify-between gap-2"> </div>
<div class="flex flex-col items-start"> {:else}
<span class="text-sm font-semibold">{theme.name}</span> <ScrollContainer class="pt-8" topOffset={45}>
<span class="text-xs text-muted-foreground">by {theme.author}</span> <div class="grid w-full gap-1 grid-cols-3 p-3 pr-5">
{#each $custom_themes as theme (theme.folder_name)}
<div
class="group overflow-hidden rounded-3xl border {$active_custom_theme &&
$active_custom_theme.folder_name === theme.folder_name
? 'border-primary'
: 'border-theme-800'} bg-theme-950 transition hover:border-white/20 h-73.75"
>
<img
src={theme.preview || DefaultThemePreview}
alt="Preview of {theme.name}"
class="mb-2 h-40 w-full rounded-t-3xl object-cover object-center pointer-events-none select-none"
/>
<div class="flex flex-col gap-1 p-3">
<div class="mb-4 flex items-center justify-between gap-2">
<div class="flex flex-col items-start">
<span class="text-sm font-semibold">{theme.name}</span>
<span class="text-xs text-muted-foreground">by {theme.author}</span>
</div>
<span class="text-xs text-muted-foreground">v{theme.version}</span>
</div> </div>
<span class="text-xs text-muted-foreground">v{theme.version}</span> <div class="flex items-center gap-1">
</div> <Button
<div class="flex items-center gap-1"> class="w-full"
<Button disabled={($active_custom_theme &&
class="w-full" $active_custom_theme.folder_name === theme.folder_name) ||
disabled={($active_custom_theme && theme.status === 'downloading' ||
$active_custom_theme.folder_name === theme.folder_name) || theme.status === 'extracting' ||
theme.status === 'downloading' || theme.status === 'deleting'}
theme.status === 'extracting' || onclick={async () => {
theme.status === 'deleting'} if (theme.status === 'installed') {
onclick={async () => { if ($custom_theme_container) {
if (theme.status === 'installed') { loadTheme(theme, $custom_theme_container, $custom_theme_volume);
if ($custom_theme_container) { await config.value<string>('theme').set(theme.name);
loadTheme(theme, $custom_theme_container, $custom_theme_volume); } else {
await config.value<string>('theme').set(theme.name);
} else {
sileo.error({
title: 'Uhhm..',
description: 'Failed to apply theme.',
});
}
} else {
const downloadThemeResult = await downloadTheme(theme);
if (!downloadThemeResult.success) {
if (downloadThemeResult.error && downloadThemeResult.error.length > 0) {
sileo.error({ sileo.error({
title: 'Uhhm..', title: 'Uhhm..',
description: downloadThemeResult.error, description: 'Failed to apply theme.',
}); });
} }
} else { } else {
sileo.success({ const downloadThemeResult = await downloadTheme(theme);
title: 'Yaay!', if (!downloadThemeResult.success) {
description: 'Theme installed successfully!', if (
}); downloadThemeResult.error &&
} downloadThemeResult.error.length > 0
} ) {
}} sileo.error({
> title: 'Uhhm..',
{#if $active_custom_theme && $active_custom_theme.folder_name === theme.folder_name} description: downloadThemeResult.error,
Theme in use });
{:else if theme.status !== 'installed'} }
{#if theme.status === 'downloading'} } else {
{theme.updateAvailable ? 'Updating' : 'Downloading'} Theme... ({Math.round( sileo.success({
theme.progress * 100 title: 'Yaay!',
)}%) description: 'Theme installed successfully!',
{:else if theme.status === 'extracting'}
Extracting Theme... ({Math.round(theme.progress * 100)}%)
{:else if theme.status === 'deleting'}
Uninstalling Theme...
{:else}
Download Theme
{/if}
{:else}
Use Theme
{/if}
</Button>
{#if theme.status === 'installed' && theme.updateAvailable}
<Button
class="min-w-10"
size="icon"
variant="secondary"
onclick={async () => {
const defaultTheme = $custom_themes.find((t) => t.name === 'Default');
if (defaultTheme) {
loadTheme(defaultTheme, $custom_theme_container!, $custom_theme_volume);
await config.value<string>('theme').set(defaultTheme.name);
if (!(await downloadTheme(theme, true))) {
sileo.error({
title: 'Uhhm..',
description: 'Failed to update theme.',
}); });
} }
} }
}} }}
> >
<CloudDownload /> {#if $active_custom_theme && $active_custom_theme.folder_name === theme.folder_name}
Theme in use
{:else if theme.status !== 'installed'}
{#if theme.status === 'downloading'}
{theme.updateAvailable ? 'Updating' : 'Downloading'} Theme... ({Math.round(
theme.progress * 100
)}%)
{:else if theme.status === 'extracting'}
Extracting Theme... ({Math.round(theme.progress * 100)}%)
{:else if theme.status === 'deleting'}
Uninstalling Theme...
{:else}
Download Theme
{/if}
{:else}
Use Theme
{/if}
</Button> </Button>
{/if} {#if theme.status === 'installed' && theme.updateAvailable}
{#if (theme.status === 'installed' || theme.status === 'deleting') && $active_custom_theme && $active_custom_theme.folder_name !== theme.folder_name && theme.name !== 'Default'} <Button
<Button class="min-w-10"
class="min-w-10" size="icon"
size="icon" variant="secondary"
variant="destructive" onclick={async () => {
disabled={theme.status !== 'installed'} const defaultTheme = $custom_themes.find((t) => t.name === 'Default');
onclick={async () => { if (defaultTheme) {
try { loadTheme(
const deleteResult = await deleteTheme(theme); defaultTheme,
if (deleteResult) { $custom_theme_container!,
sileo.success({ $custom_theme_volume
title: 'Yaay!', );
description: 'Theme uninstalled successfully!', await config.value<string>('theme').set(defaultTheme.name);
});
} else { if (!(await downloadTheme(theme, true))) {
sileo.error({
title: 'Uhhm..',
description: 'Failed to update theme.',
});
}
}
}}
>
<CloudDownload />
</Button>
{/if}
{#if (theme.status === 'installed' || theme.status === 'deleting') && $active_custom_theme && $active_custom_theme.folder_name !== theme.folder_name && theme.name !== 'Default'}
<Button
class="min-w-10"
size="icon"
variant="destructive"
disabled={theme.status !== 'installed'}
onclick={async () => {
try {
const deleteResult = await deleteTheme(theme);
if (deleteResult) {
sileo.success({
title: 'Yaay!',
description: 'Theme uninstalled successfully!',
});
} else {
sileo.error({
title: 'Uhhm..',
description: 'Failed to uninstall theme.',
});
}
} catch (err) {
console.log(err);
sileo.error({ sileo.error({
title: 'Uhhm..', title: 'Uhhm..',
description: 'Failed to uninstall theme.', description: 'Failed to uninstall theme.',
}); });
} }
} catch (err) { }}
console.log(err); >
sileo.error({ {#if theme.status === 'deleting'}
title: 'Uhhm..', <LoaderCircle class="animate-spin" />
description: 'Failed to uninstall theme.', {:else}
}); <Trash />
} {/if}
}} </Button>
> {/if}
{#if theme.status === 'deleting'} </div>
<LoaderCircle class="animate-spin" />
{:else}
<Trash />
{/if}
</Button>
{/if}
</div> </div>
</div> </div>
</div> {/each}
{/each} </div>
</div> </ScrollContainer>
</ScrollContainer> {/if}
</div> </div>
{/if} {/if}
</div> </div>