feat: implement app tracking consent dialog and update tracking state management
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
serverConnectionFails,
|
serverConnectionFails,
|
||||||
serverPing,
|
serverPing,
|
||||||
skins,
|
skins,
|
||||||
|
trackingEnabled,
|
||||||
} from '@/global';
|
} from '@/global';
|
||||||
import {
|
import {
|
||||||
LoaderCircle,
|
LoaderCircle,
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
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 },
|
||||||
@@ -129,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(
|
||||||
@@ -535,6 +539,16 @@
|
|||||||
umami.track('app_launch_fail', { error: err });
|
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}>
|
||||||
@@ -639,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"
|
||||||
@@ -1191,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"
|
||||||
|
|||||||
Reference in New Issue
Block a user