7 Commits
3.0.5 ... 3.0.7

12 changed files with 140 additions and 31 deletions

View File

@@ -14,6 +14,7 @@
"@tauri-apps/plugin-dialog": "^2.4.0", "@tauri-apps/plugin-dialog": "^2.4.0",
"@tauri-apps/plugin-fs": "^2.4.2", "@tauri-apps/plugin-fs": "^2.4.2",
"@tauri-apps/plugin-shell": "^2.3.1", "@tauri-apps/plugin-shell": "^2.3.1",
"@types/umami": "^2.10.1",
"animejs": "^4.1.3", "animejs": "^4.1.3",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
@@ -347,6 +348,8 @@
"@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="], "@types/semver": ["@types/semver@7.7.1", "", {}, "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA=="],
"@types/umami": ["@types/umami@2.10.1", "", {}, "sha512-CvOEMq+BFOUXj8yciq4hPsdOt0o9KBg5jQXnF1FrdOMKZMxJiwryyZNLa9Ud2NVO6nXSwU22YMKR3E+Xhbo+DA=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="],
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="],

View File

@@ -1,11 +1,11 @@
{ {
"name": "ezpplauncher", "name": "ezpplauncher",
"version": "3.0.5", "version": "3.0.7",
"description": "", "description": "",
"type": "module", "type": "module",
"scripts": { "scripts": {
"debug": "bun run tauri dev", "debug": "bun run tauri dev",
"build": "bun ./scripts/sync-version.ts && bun run tauri:build", "build": "bun ./scripts/sync-version.ts && bun run vite:build && bun run tauri:build",
"vite:dev": "vite dev", "vite:dev": "vite dev",
"vite:build": "vite build", "vite:build": "vite build",
"tauri:build": "tauri build", "tauri:build": "tauri build",
@@ -28,13 +28,14 @@
"@tauri-apps/plugin-dialog": "^2.4.0", "@tauri-apps/plugin-dialog": "^2.4.0",
"@tauri-apps/plugin-fs": "^2.4.2", "@tauri-apps/plugin-fs": "^2.4.2",
"@tauri-apps/plugin-shell": "^2.3.1", "@tauri-apps/plugin-shell": "^2.3.1",
"@types/umami": "^2.10.1",
"animejs": "^4.1.3", "animejs": "^4.1.3",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"lucide-svelte": "^0.542.0", "lucide-svelte": "^0.542.0",
"semver": "^7.7.2", "semver": "^7.7.2",
"tw-animate-css": "^1.3.8", "svelte-confetti": "^2.3.2",
"svelte-confetti": "^2.3.2" "tw-animate-css": "^1.3.8"
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^1.3.2", "@eslint/compat": "^1.3.2",

2
src-tauri/Cargo.lock generated
View File

@@ -1012,7 +1012,7 @@ dependencies = [
[[package]] [[package]]
name = "ezpplauncher" name = "ezpplauncher"
version = "3.0.5" version = "3.0.7"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"discord-rich-presence", "discord-rich-presence",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ezpplauncher" name = "ezpplauncher"
version = "3.0.5" version = "3.0.7"
description = "EZPPLauncher redefined." description = "EZPPLauncher redefined."
authors = ["HorizonCode"] authors = ["HorizonCode"]
edition = "2024" edition = "2024"

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "EZPPLauncher", "productName": "EZPPLauncher",
"version": "3.0.5", "version": "3.0.7",
"identifier": "farm.EZPPFarm.Launcher", "identifier": "farm.EZPPFarm.Launcher",
"mainBinaryName": "ezpplauncher", "mainBinaryName": "ezpplauncher",
"build": { "build": {
@@ -15,7 +15,7 @@
{ {
"title": "EZPPLauncher", "title": "EZPPLauncher",
"width": 1000, "width": 1000,
"height": 700, "height": 737,
"decorations": false, "decorations": false,
"resizable": false, "resizable": false,
"maximizable": false "maximizable": false

View File

@@ -1,13 +1,15 @@
<!doctype html> <!doctype html>
<html lang="en" class="dark"> <html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>EZPPLauncher</title>
%sveltekit.head%
</head>
<body class="bg-theme-950" data-sveltekit-preload-data="hover"> <head>
<div style="display: contents">%sveltekit.body%</div> <meta charset="utf-8" />
</body> <meta name="viewport" content="width=device-width, initial-scale=1" />
</html> <title>EZPPLauncher</title>
%sveltekit.head%
</head>
<body class="bg-theme-950" data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -65,10 +65,15 @@ export class Config {
} }
value(key: string) { value(key: string) {
console.log('Accessing config key:', key, this.config[key]);
return { return {
set: <T>(val: T) => { set: <T>(val: T) => {
this.config[key] = val; this.config[key] = val;
}, },
exists: () => {
console.log('Checking existence of key:', key, this.config[key] !== undefined);
return this.config[key] !== undefined;
},
get: <T>(fallback: T): T => { get: <T>(fallback: T): T => {
return (this.config[key] as T) ?? fallback; return (this.config[key] as T) ?? fallback;
}, },

View File

@@ -9,7 +9,7 @@ export function estimateRefreshRate(): Promise<number> {
if (now - last >= 1000) { if (now - last >= 1000) {
console.log(`Estimated Refresh Rate: ${frames - 2} FPS`); console.log(`Estimated Refresh Rate: ${frames - 2} FPS`);
resolve(frames - 2); // estimated Hz resolve(frames - 2);
} else { } else {
requestAnimationFrame(loop); requestAnimationFrame(loop);
} }

View File

@@ -14,6 +14,8 @@ export const newVersion = writable<Release | undefined>(undefined);
export const launcherStreams = writable<string[]>(['stable']); export const launcherStreams = writable<string[]>(['stable']);
export const launcherStream = writable<string>('stable'); export const launcherStream = writable<string>('stable');
export const trackingEnabled = writable<boolean>(false);
export const discordPresence = writable<boolean>(false); export const discordPresence = writable<boolean>(false);
export const presenceLoading = writable<boolean>(false); export const presenceLoading = writable<boolean>(false);

View File

@@ -12,6 +12,7 @@
platform, platform,
presenceLoading, presenceLoading,
setupValues, setupValues,
trackingEnabled,
} from '@/global'; } from '@/global';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import OsuCursor from '@/components/ui/osu-cursor/OsuCursor.svelte'; import OsuCursor from '@/components/ui/osu-cursor/OsuCursor.svelte';
@@ -103,6 +104,7 @@
const config_reduce_animations = $userSettings.value('reduce_animations'); const config_reduce_animations = $userSettings.value('reduce_animations');
const config_osu_installation_path = $userSettings.value('osu_installation_path'); const config_osu_installation_path = $userSettings.value('osu_installation_path');
const config_discord_presence = $userSettings.value('discord_presence'); const config_discord_presence = $userSettings.value('discord_presence');
const config_tracking_enabled = $userSettings.value('tracking_consent');
patch.set(config_patching.get(true)); patch.set(config_patching.get(true));
customCursor.set(config_custom_cursor.get(true)); customCursor.set(config_custom_cursor.get(true));
@@ -110,6 +112,9 @@
reduceAnimations.set(config_reduce_animations.get(false)); reduceAnimations.set(config_reduce_animations.get(false));
osuInstallationPath.set(config_osu_installation_path.get('')); osuInstallationPath.set(config_osu_installation_path.get(''));
discordPresence.set(config_discord_presence.get(true)); discordPresence.set(config_discord_presence.get(true));
if (config_tracking_enabled.exists()) {
trackingEnabled.set(config_tracking_enabled.get(false));
}
patch.subscribe((val) => config_patching.set(val)); patch.subscribe((val) => config_patching.set(val));
customCursor.subscribe((val) => config_custom_cursor.set(val)); customCursor.subscribe((val) => config_custom_cursor.set(val));

View File

@@ -1,10 +1,21 @@
<script lang="ts"> <script lang="ts">
import { currentView } from '@/global'; import { currentView, launcherVersion, trackingEnabled } from '@/global';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
const View = $derived($currentView); const View = $derived($currentView);
</script> </script>
<svelte:head>
{#if $launcherVersion !== '' && $trackingEnabled}
<script
defer
src="https://analytics.ez-pp.farm/script.js"
data-website-id="b03f0013-64f0-42ce-85c0-abd56e8b3c64"
data-tag={$launcherVersion}
></script>
{/if}
</svelte:head>
{#key View} {#key View}
<div in:fade={{ duration: 300 }}> <div in:fade={{ duration: 300 }}>
<View /> <View />

View File

@@ -21,6 +21,7 @@
serverConnectionFails, serverConnectionFails,
serverPing, serverPing,
skins, skins,
trackingEnabled,
} from '@/global'; } from '@/global';
import { import {
LoaderCircle, LoaderCircle,
@@ -111,14 +112,10 @@
import { EZPPActionStatus } from '@/types'; import { EZPPActionStatus } from '@/types';
import * as presence from '@/presence'; import * as presence from '@/presence';
import { expoOut } from 'svelte/easing'; import { expoOut } from 'svelte/easing';
import { onMount } from 'svelte';
const tabs = [ const tabs = [
{ name: 'Home', key: 'home', show: true }, { name: 'Home', key: 'home', show: true },
{
name: 'Skins',
key: 'skins',
show: false,
},
{ {
name: 'Settings', name: 'Settings',
key: 'settings', key: 'settings',
@@ -134,6 +131,8 @@
let launchInfo = $state(''); let launchInfo = $state('');
let launchError = $state<Error | undefined>(undefined); let launchError = $state<Error | undefined>(undefined);
let askForTrackingPermission = $state(false);
let downloadingUpdate = $state(false); let downloadingUpdate = $state(false);
let selectedGamemode = $derived( let selectedGamemode = $derived(
@@ -182,6 +181,7 @@
}; };
const launch = async () => { const launch = async () => {
umami.track('app_launch_osu');
const osuRunning = await isOsuRunning(); const osuRunning = await isOsuRunning();
if (osuRunning) { if (osuRunning) {
toast.error('Hold on a second!', { toast.error('Hold on a second!', {
@@ -485,7 +485,7 @@
} }
await runOsu(osuPath, true); await runOsu(osuPath, true);
umami.track('app_exit_osu');
launchInfo = 'Cleaning up...'; launchInfo = 'Cleaning up...';
await getCurrentWindow().show(); await getCurrentWindow().show();
if (presenceUpdater) { if (presenceUpdater) {
@@ -536,8 +536,19 @@
description: 'Failed to launch.', description: 'Failed to launch.',
}); });
launching.set(false); launching.set(false);
umami.track('app_launch_fail', { error: err });
} }
}; };
onMount(() => {
const config = $userSettings;
const trackingConsent = config.value('tracking_consent');
if (trackingConsent.exists()) {
trackingEnabled.set(trackingConsent.get(false));
} else {
askForTrackingPermission = true;
}
});
</script> </script>
<AlertDialog.Root open={launchError !== undefined}> <AlertDialog.Root open={launchError !== undefined}>
@@ -642,6 +653,59 @@
</AlertDialog.Content> </AlertDialog.Content>
</AlertDialog.Root> </AlertDialog.Root>
<AlertDialog.Root open={$newVersion === undefined && askForTrackingPermission}>
<AlertDialog.Content
class="bg-theme-950 border-theme-800 p-0"
escapeKeydownBehavior="ignore"
interactOutsideBehavior="ignore"
>
<div
class="flex flex-col items-center justify-center border-b border-theme-800 bg-black/40 rounded-t-lg p-3"
>
<img class="h-20 w-20" src={Logo} alt="logo" />
<span class="font-semibold text-xl">App Tracking Consent</span>
</div>
<div
class="flex flex-col items-center text-sm text-center bg-theme-900 border border-theme-800 rounded-lg mx-3 p-3"
>
<p class="mb-4">
We value your privacy. To enhance your experience and improve our services, we would like to
collect anonymous usage data. This data helps us understand how the application is used and
identify areas for improvement.
</p>
<p class="mb-4">
No personal information is collected, and all data is anonymized. You can choose to enable
or disable this tracking at any time in the application settings.
</p>
<p>
Do you consent to the collection of anonymous usage data to help us improve the application?
</p>
</div>
<div class="flex items-center justify-center mb-3 gap-4 mt-4">
<Button
onclick={async () => {
trackingEnabled.set(true);
const config = $userSettings;
config.value('tracking_consent').set(true);
await config.save();
askForTrackingPermission = false;
}}>Yes, I consent</Button
>
<Button
variant="outline"
onclick={async () => {
trackingEnabled.set(false);
const config = $userSettings;
config.value('tracking_consent').set(false);
await config.save();
askForTrackingPermission = false;
}}>No, I do not consent</Button
>
</div>
</AlertDialog.Content>
</AlertDialog.Root>
<AlertDialog.Root bind:open={$launching}> <AlertDialog.Root bind:open={$launching}>
<AlertDialog.Content <AlertDialog.Content
class="bg-theme-950 border-theme-800 p-0" class="bg-theme-950 border-theme-800 p-0"
@@ -1035,11 +1099,12 @@
</div> </div>
<Button <Button
size="lg" size="lg"
class="text-xl h-16 px-16 border-2 border-violet-500/40"
disabled={$launching || $osuInstallationPath === '' || $serverConnectionFails > 1} disabled={$launching || $osuInstallationPath === '' || $serverConnectionFails > 1}
onclick={launch} onclick={launch}
> >
<Play /> <Play class="!size-5" />
{$serverConnectionFails > 1 ? 'No connection' : 'Launch'} {$launching ? 'Launching...' : $serverConnectionFails > 1 ? 'No connection' : 'Launch'}
</Button> </Button>
</div> </div>
<div <div
@@ -1087,8 +1152,6 @@
</span> </span>
</div> </div>
</div> </div>
{:else if selectedTab === 'skins'}
<p>list of skins here, option to set current skin (also a subpage to download new skins?)</p>
{:else if selectedTab === 'settings'} {:else if selectedTab === 'settings'}
<div <div
class="bg-theme-900/90 flex flex-col justify-center gap-3 border border-theme-800/90 rounded-lg" class="bg-theme-900/90 flex flex-col justify-center gap-3 border border-theme-800/90 rounded-lg"
@@ -1195,6 +1258,23 @@
class="flex items-center justify-center w-5 h-5" class="flex items-center justify-center w-5 h-5"
></Checkbox> ></Checkbox>
</div> </div>
<div class="flex flex-col">
<Label class="text-sm" for="setting-reduce-animations">App Tracking</Label>
<div class="text-muted-foreground text-xs">
Allow anonymous usage data to be collected to help improve the application.
</div>
</div>
<Checkbox
id="setting-reduce-animations"
checked={$trackingEnabled}
onCheckedChange={async (e) => {
trackingEnabled.set(e);
$userSettings.value('tracking_consent').set(e);
await $userSettings.save();
}}
class="flex items-center justify-center w-5 h-5"
></Checkbox>
</div> </div>
<div <div
class="grid grid-cols-[0.7fr_auto] gap-y-1 items-center border-theme-800 pl-6 pr-5 pb-4" class="grid grid-cols-[0.7fr_auto] gap-y-1 items-center border-theme-800 pl-6 pr-5 pb-4"
@@ -1237,7 +1317,7 @@
label: 'Download .NET 8.0', label: 'Download .NET 8.0',
onClick: async () => onClick: async () =>
await openURL( await openURL(
'https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-8.0.18-windows-x64-installer' 'https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-8.0.22-windows-x64-installer'
), ),
}, },
}); });