mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-07 14:56:06 +02:00
improve whats new dialog
This commit is contained in:
Generated
+46
-46
@@ -22,11 +22,11 @@
|
|||||||
"@internationalized/date": "^3.12.0",
|
"@internationalized/date": "^3.12.0",
|
||||||
"@pinia/testing": "^1.0.3",
|
"@pinia/testing": "^1.0.3",
|
||||||
"@sentry/vite-plugin": "^4.9.1",
|
"@sentry/vite-plugin": "^4.9.1",
|
||||||
"@sentry/vue": "^10.44.0",
|
"@sentry/vue": "^10.45.0",
|
||||||
"@sigma/edge-curve": "^3.1.0",
|
"@sigma/edge-curve": "^3.1.0",
|
||||||
"@sigma/node-border": "^3.0.0",
|
"@sigma/node-border": "^3.0.0",
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
"@tailwindcss/vite": "^4.2.2",
|
||||||
"@tanstack/vue-query": "^5.92.10",
|
"@tanstack/vue-query": "^5.94.5",
|
||||||
"@tanstack/vue-table": "^8.21.3",
|
"@tanstack/vue-table": "^8.21.3",
|
||||||
"@tanstack/vue-virtual": "^3.13.23",
|
"@tanstack/vue-virtual": "^3.13.23",
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
@@ -3233,54 +3233,54 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/browser-utils": {
|
"node_modules/@sentry-internal/browser-utils": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.45.0.tgz",
|
||||||
"integrity": "sha512-z9xz3T/v+MnfHY6kdUCmOZI8CiAl3LlKYtGH2p3rAsrxhwX+BTnUp01VhMVnEZIDgUXNt3AhJac+4kcDIPu1Hg==",
|
"integrity": "sha512-ZPZpeIarXKScvquGx2AfNKcYiVNDA4wegMmjyGVsTA2JPmP0TrJoO3UybJS6KGDeee8V3I3EfD/ruauMm7jOFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/feedback": {
|
"node_modules/@sentry-internal/feedback": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.45.0.tgz",
|
||||||
"integrity": "sha512-yNS2EGK1bNm8YUI+Orzpa7yr05Da+b1VEe/9x7dl7gTjw/+tfutoXlG6Y+iFZBB3gQ9QU+nxZAhU+KcxiPEURw==",
|
"integrity": "sha512-vCSurazFVq7RUeYiM5X326jA5gOVrWYD6lYX2fbjBOMcyCEhDnveNxMT62zKkZDyNT/jyD194nz/cjntBUkyWA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/replay": {
|
"node_modules/@sentry-internal/replay": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.45.0.tgz",
|
||||||
"integrity": "sha512-KDmoqBsRmkaoc+eKLR2CbScd2eBmLcw+1+D441lLttAO3WWhvYyCaYdu/HIGGUoybuSgt+IcpCJdi7hFuCvYqw==",
|
"integrity": "sha512-vjosRoGA1bzhVAEO1oce+CsRdd70quzBeo7WvYqpcUnoLe/Rv8qpOMqWX3j26z7XfFHMExWQNQeLxmtYOArvlw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/browser-utils": "10.44.0",
|
"@sentry-internal/browser-utils": "10.45.0",
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/replay-canvas": {
|
"node_modules/@sentry-internal/replay-canvas": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.45.0.tgz",
|
||||||
"integrity": "sha512-RA7XgYZWHY7M+vaHvuMxDFT51wCs4puS2smElM5oh+j3YqbFXY7P16fOCwIAGoyI4gVsj8aTeBgVqUmrmzhAXQ==",
|
"integrity": "sha512-nvq/AocdZTuD7y0KSiWi3gVaY0s5HOFy86mC/v1kDZmT/jsBAzN5LDkk/f1FvsWma1peqQmpUqxvhC+YIW294Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/replay": "10.44.0",
|
"@sentry-internal/replay": "10.45.0",
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3297,17 +3297,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/browser": {
|
"node_modules/@sentry/browser": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.45.0.tgz",
|
||||||
"integrity": "sha512-UpMx5forbVKieNULma3gT2SsLYqsYT4nLXa6s1io/Y8BFej9sH2dD5ExA8TrkQThQwAWFI3qKsQzYnF+EX/Bfg==",
|
"integrity": "sha512-e/a8UMiQhqqv706McSIcG6XK+AoQf9INthi2pD+giZfNRTzXTdqHzUT5OIO5hg8Am6eF63nDJc+vrYNPhzs51Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/browser-utils": "10.44.0",
|
"@sentry-internal/browser-utils": "10.45.0",
|
||||||
"@sentry-internal/feedback": "10.44.0",
|
"@sentry-internal/feedback": "10.45.0",
|
||||||
"@sentry-internal/replay": "10.44.0",
|
"@sentry-internal/replay": "10.45.0",
|
||||||
"@sentry-internal/replay-canvas": "10.44.0",
|
"@sentry-internal/replay-canvas": "10.45.0",
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3508,9 +3508,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/core": {
|
"node_modules/@sentry/core": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.45.0.tgz",
|
||||||
"integrity": "sha512-aa7CiDaNFZvHpqd97LJhuskolfJ/4IH5xyuVVLnv7l6B0v9KTwskPUxb0tH1ej3FxuzfH+i8iTiTFuqpfHS3QA==",
|
"integrity": "sha512-s69UXxvefeQxuZ5nY7/THtTrIEvJxNVCp3ns4kwoCw1qMpgpvn/296WCKVmM7MiwnaAdzEKnAvLAwaxZc2nM7Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3532,14 +3532,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/vue": {
|
"node_modules/@sentry/vue": {
|
||||||
"version": "10.44.0",
|
"version": "10.45.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.45.0.tgz",
|
||||||
"integrity": "sha512-XAjvUPhfqkEULt3kly4fSmwQ7fi9XuBWU8Hq9Fme3WN3Ti5q1lTqFBvxlpGeUDKzb2g/J9NVRq9G10m7d438Fg==",
|
"integrity": "sha512-p6ghTgQtiCBZ+Yw0B2xmC69S8AdCRRsYvbTHW7MJYspwNnJDs7rqgCBqOxNhvr3tsKdDuEOEHLtf/5hbKi+8xQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/browser": "10.44.0",
|
"@sentry/browser": "10.45.0",
|
||||||
"@sentry/core": "10.44.0"
|
"@sentry/core": "10.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3953,9 +3953,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/query-core": {
|
"node_modules/@tanstack/query-core": {
|
||||||
"version": "5.91.0",
|
"version": "5.94.5",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.91.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.94.5.tgz",
|
||||||
"integrity": "sha512-FYXN8Kk9Q5VKuV6AIVaNwMThSi0nvAtR4X7HQoigf6ePOtFcavJYVIzgFhOVdtbBQtCJE3KimDIMMJM2DR1hjw==",
|
"integrity": "sha512-Vx1JJiBURW/wdNGP45afjrqn0LfxYwL7K/bSrQvNRtyLGF1bxQPgUXCpzscG29e+UeFOh9hz1KOVala0N+bZiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -3989,14 +3989,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tanstack/vue-query": {
|
"node_modules/@tanstack/vue-query": {
|
||||||
"version": "5.92.10",
|
"version": "5.94.5",
|
||||||
"resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.92.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.94.5.tgz",
|
||||||
"integrity": "sha512-ukRbUTcVZAHksOhZeLDbhysLFTkCQuKYdhfSR6DiDSX8W30z3prTLjCDOpgicO3tV9BMnzGZkQmguy9EOb2aVw==",
|
"integrity": "sha512-xmnOj1fP0JvUqGrkHmdIY/3FyO4L0IjJBCqOFxnnMIJjrsvCvlpjp/XpI1Zv4eLuV0e8l1LIOOuEvN40ckVuOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/match-sorter-utils": "^8.19.4",
|
"@tanstack/match-sorter-utils": "^8.19.4",
|
||||||
"@tanstack/query-core": "5.91.0",
|
"@tanstack/query-core": "5.94.5",
|
||||||
"@vue/devtools-api": "^6.6.3",
|
"@vue/devtools-api": "^6.6.3",
|
||||||
"vue-demi": "^0.14.10"
|
"vue-demi": "^0.14.10"
|
||||||
},
|
},
|
||||||
@@ -7523,9 +7523,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/flatted": {
|
"node_modules/flatted": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
|
||||||
"integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==",
|
"integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-2
@@ -51,11 +51,11 @@
|
|||||||
"@internationalized/date": "^3.12.0",
|
"@internationalized/date": "^3.12.0",
|
||||||
"@pinia/testing": "^1.0.3",
|
"@pinia/testing": "^1.0.3",
|
||||||
"@sentry/vite-plugin": "^4.9.1",
|
"@sentry/vite-plugin": "^4.9.1",
|
||||||
"@sentry/vue": "^10.44.0",
|
"@sentry/vue": "^10.45.0",
|
||||||
"@sigma/edge-curve": "^3.1.0",
|
"@sigma/edge-curve": "^3.1.0",
|
||||||
"@sigma/node-border": "^3.0.0",
|
"@sigma/node-border": "^3.0.0",
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
"@tailwindcss/vite": "^4.2.2",
|
||||||
"@tanstack/vue-query": "^5.92.10",
|
"@tanstack/vue-query": "^5.94.5",
|
||||||
"@tanstack/vue-table": "^8.21.3",
|
"@tanstack/vue-table": "^8.21.3",
|
||||||
"@tanstack/vue-virtual": "^3.13.23",
|
"@tanstack/vue-virtual": "^3.13.23",
|
||||||
"@types/node": "^24.12.0",
|
"@types/node": "^24.12.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="isOpen">
|
<Dialog v-model:open="isOpen">
|
||||||
<DialogContent
|
<DialogContent
|
||||||
class="border-none! bg-background/85 shadow-[0_0_0_1px_hsl(from_var(--border)_h_s_l/0.5),0_24px_48px_hsl(from_var(--background)_h_s_l/0.4)] backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-xl"
|
class="border border-border bg-background/85 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-xl"
|
||||||
:show-close-button="false"
|
:show-close-button="false"
|
||||||
@escape-key-down="handleDismiss"
|
@escape-key-down="handleDismiss"
|
||||||
@pointer-down-outside="handleDismiss"
|
@pointer-down-outside="handleDismiss"
|
||||||
@@ -14,11 +14,11 @@
|
|||||||
<p class="mt-1.5 text-sm text-muted-foreground">{{ t('onboarding.welcome.subtitle') }}</p>
|
<p class="mt-1.5 text-sm text-muted-foreground">{{ t('onboarding.welcome.subtitle') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="my-4 grid grid-cols-4 gap-2.5">
|
<div class="my-4 grid auto-rows-fr grid-cols-4 gap-2.5">
|
||||||
<div
|
<div
|
||||||
v-for="(feature, index) in features"
|
v-for="(feature, index) in features"
|
||||||
:key="feature.key"
|
:key="feature.key"
|
||||||
class="flex animate-[featureAppear_0.4s_ease-out_both] cursor-default flex-col items-center rounded-[10px] border border-transparent bg-muted/50 px-2 py-3.5 pb-3 text-center transition-all duration-250 hover:-translate-y-0.5 hover:border-primary/25 hover:bg-muted/80 hover:shadow-[0_4px_16px_hsl(from_var(--primary)_h_s_l/0.08)]"
|
class="flex h-full animate-[featureAppear_0.4s_ease-out_both] cursor-default flex-col items-center rounded-[10px] border border-transparent bg-muted/50 px-2 py-3.5 pb-3 text-center transition-all duration-250 hover:-translate-y-0.5 hover:border-primary/25 hover:bg-muted/80 hover:shadow-[0_4px_16px_hsl(from_var(--primary)_h_s_l/0.08)]"
|
||||||
:style="{ animationDelay: `${0.1 + index * 0.1}s` }">
|
:style="{ animationDelay: `${0.1 + index * 0.1}s` }">
|
||||||
<div
|
<div
|
||||||
class="mb-2.5 flex size-10 items-center justify-center rounded-[10px] transition-all duration-250"
|
class="mb-2.5 flex size-10 items-center justify-center rounded-[10px] transition-all duration-250"
|
||||||
@@ -28,10 +28,10 @@
|
|||||||
}">
|
}">
|
||||||
<component :is="feature.icon" class="size-5" />
|
<component :is="feature.icon" class="size-5" />
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-1 text-[13px] font-semibold">
|
<div class="mb-1 w-full text-[13px] font-semibold leading-snug">
|
||||||
{{ t(`onboarding.welcome.features.${feature.key}.title`) }}
|
{{ t(`onboarding.welcome.features.${feature.key}.title`) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[11.5px] leading-snug text-muted-foreground">
|
<div class="w-full text-[11.5px] leading-snug text-muted-foreground">
|
||||||
{{ t(`onboarding.welcome.features.${feature.key}.description`) }}
|
{{ t(`onboarding.welcome.features.${feature.key}.description`) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,7 +39,6 @@
|
|||||||
|
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<Button class="w-full text-sm font-semibold" size="lg" @click="handleDismiss">
|
<Button class="w-full text-sm font-semibold" size="lg" @click="handleDismiss">
|
||||||
<Sparkles class="mr-1.5 size-4" />
|
|
||||||
{{ t('onboarding.welcome.cta') }}
|
{{ t('onboarding.welcome.cta') }}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,46 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="whatsNewDialog.visible">
|
<Dialog v-model:open="whatsNewDialog.visible">
|
||||||
<DialogContent
|
<DialogContent
|
||||||
class="border-none! bg-background/88 p-5 shadow-[0_0_0_1px_hsl(from_var(--border)_h_s_l/0.5),0_24px_48px_hsl(from_var(--background)_h_s_l/0.4)] backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-2xl"
|
class="border border-border bg-background/88 p-5 shadow-lg backdrop-blur-xl backdrop-saturate-[1.4] sm:max-w-xl"
|
||||||
:show-close-button="false"
|
:show-close-button="false"
|
||||||
@escape-key-down="handleDismiss"
|
@escape-key-down="handleDismiss"
|
||||||
@pointer-down-outside="handleDismiss"
|
@pointer-down-outside="handleDismiss"
|
||||||
@interact-outside.prevent>
|
@interact-outside.prevent>
|
||||||
|
<!-- Title -->
|
||||||
<div class="pt-1 text-center">
|
<div class="pt-1 text-center">
|
||||||
<div class="mb-2 flex justify-center">
|
<div class="mb-2 flex justify-center">
|
||||||
<img :src="vrcxLogo" alt="VRCX" class="size-12 rounded-xl" />
|
<img :src="vrcxLogo" alt="VRCX" class="size-12 rounded-xl" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col items-center gap-2">
|
|
||||||
<h2 class="m-0 text-[23px] font-bold tracking-tight">
|
<h2 class="m-0 text-[23px] font-bold tracking-tight">
|
||||||
{{ releaseTitle }}
|
{{ t(whatsNewDialog.titleKey || 'onboarding.whatsnew.title') }}
|
||||||
</h2>
|
</h2>
|
||||||
<Badge
|
|
||||||
v-if="releaseLabel"
|
|
||||||
variant="secondary"
|
|
||||||
class="rounded-full px-2.5 py-0.5 text-[11px] tracking-[0.08em]">
|
|
||||||
{{ releaseLabel }}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<!-- Feature Cards -->
|
||||||
variant="link"
|
<div class="my-2 grid auto-rows-fr grid-cols-4 gap-2.5">
|
||||||
size="sm"
|
|
||||||
class="mt-2 h-auto gap-1 px-0 text-muted-foreground hover:text-foreground"
|
|
||||||
@click="handleViewDetails">
|
|
||||||
{{ t('onboarding.whatsnew.common.view_details') }}
|
|
||||||
<ChevronRight class="size-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-2 grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
||||||
<div
|
<div
|
||||||
v-for="(feature, index) in whatsNewDialog.items"
|
v-for="(feature, index) in whatsNewDialog.items"
|
||||||
:key="feature.key"
|
:key="feature.key"
|
||||||
class="group flex animate-[whatsNewAppear_0.45s_ease-out_both] cursor-default flex-col rounded-[12px] border border-transparent bg-muted/55 px-3 py-3.5 text-left transition-all duration-250 hover:-translate-y-0.5 hover:border-primary/20 hover:bg-muted/80 hover:shadow-[0_4px_18px_hsl(from_var(--primary)_h_s_l/0.08)]"
|
class="flex h-full animate-[featureAppear_0.4s_ease-out_both] cursor-default flex-col items-center rounded-[10px] border border-transparent bg-muted/50 px-2 py-3.5 pb-3 text-center transition-all duration-250 hover:-translate-y-0.5 hover:border-primary/25 hover:bg-muted/80 hover:shadow-[0_4px_16px_hsl(from_var(--primary)_h_s_l/0.08)]"
|
||||||
:style="{ animationDelay: `${0.08 + index * 0.06}s` }">
|
:style="{ animationDelay: `${0.1 + index * 0.1}s` }">
|
||||||
<div
|
<div
|
||||||
class="mb-3 flex size-10 items-center justify-center rounded-[10px] transition-all duration-250"
|
class="mb-2.5 flex size-10 items-center justify-center rounded-[10px] transition-all duration-250"
|
||||||
:style="{
|
:style="{
|
||||||
background: `hsl(${resolveHue(feature.icon)} 60% 50% / 0.12)`,
|
background: `hsl(${resolveHue(feature.icon)} 60% 50% / 0.12)`,
|
||||||
color: `hsl(${resolveHue(feature.icon)} 60% 55%)`
|
color: `hsl(${resolveHue(feature.icon)} 60% 55%)`
|
||||||
@@ -48,47 +33,53 @@
|
|||||||
<component :is="resolveIcon(feature.icon)" class="size-5" />
|
<component :is="resolveIcon(feature.icon)" class="size-5" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-1 text-sm font-semibold">
|
<div class="mb-1 w-full text-[13px] font-semibold leading-snug">
|
||||||
{{ t(feature.titleKey) }}
|
{{ t(feature.titleKey) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-[12.5px] leading-snug text-muted-foreground">
|
<div class="w-full text-[11.5px] leading-snug text-muted-foreground">
|
||||||
{{ t(feature.descriptionKey) }}
|
{{ t(feature.descriptionKey) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-1 rounded-[12px] border border-border/60 bg-muted/30 px-3 py-3">
|
<!-- Support (subdued footer-like) -->
|
||||||
<div class="mb-2 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">
|
<div class="mx-auto mt-4 w-fit max-w-[340px]">
|
||||||
<HeartHandshake class="size-4 text-muted-foreground" />
|
<div class="mb-2 text-[11.5px] font-medium tracking-[0.02em] text-muted-foreground/75">
|
||||||
<span>{{ t('onboarding.whatsnew.common.support') }}</span>
|
<span>{{ t('onboarding.whatsnew.common.support') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-1 text-left">
|
||||||
<div
|
<div
|
||||||
v-for="supporter in supporters"
|
v-for="supporter in supporters"
|
||||||
:key="supporter.name"
|
:key="supporter.name"
|
||||||
class="flex flex-wrap items-center gap-2">
|
class="flex flex-wrap items-center gap-1">
|
||||||
<span class="min-w-20 text-sm font-medium text-foreground">
|
<span class="text-[13px] font-semibold text-foreground/90">
|
||||||
{{ supporter.name }}
|
{{ supporter.name }}
|
||||||
</span>
|
</span>
|
||||||
|
<template v-for="link in supporter.links" :key="link.label">
|
||||||
<Button
|
<span class="text-[11px] text-muted-foreground/40">·</span>
|
||||||
v-for="link in supporter.links"
|
<button
|
||||||
:key="link.label"
|
class="cursor-pointer border-0 bg-transparent p-0 text-[12px] font-medium text-muted-foreground/80 transition-colors duration-200 hover:text-foreground"
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
class="h-8 rounded-full px-3 text-xs font-medium"
|
|
||||||
@click="openExternalLink(link.url)">
|
@click="openExternalLink(link.url)">
|
||||||
{{ link.label }}
|
{{ link.label }}
|
||||||
<ExternalLink class="size-3.5" />
|
</button>
|
||||||
</Button>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- View Changelog -->
|
||||||
|
<div class="mt-2 flex justify-center">
|
||||||
|
<button
|
||||||
|
class="cursor-pointer border-0 bg-transparent text-xs text-muted-foreground/70 transition-colors duration-200 hover:text-foreground"
|
||||||
|
@click="handleViewChangelog">
|
||||||
|
{{ t('onboarding.whatsnew.common.view_changelog') }} →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CTA -->
|
||||||
<Button class="mt-1 h-11 w-full text-sm font-semibold" size="lg" @click="handleDismiss">
|
<Button class="mt-1 h-11 w-full text-sm font-semibold" size="lg" @click="handleDismiss">
|
||||||
<Sparkles class="size-4" />
|
|
||||||
{{ t('onboarding.whatsnew.common.got_it') }}
|
{{ t('onboarding.whatsnew.common.got_it') }}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@@ -96,21 +87,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, markRaw } from 'vue';
|
import { markRaw } from 'vue';
|
||||||
import {
|
import { LayoutDashboard, Search, Activity, Images } from 'lucide-vue-next';
|
||||||
ChevronRight,
|
|
||||||
ExternalLink,
|
|
||||||
HeartHandshake,
|
|
||||||
LayoutDashboard,
|
|
||||||
Search,
|
|
||||||
Sparkles,
|
|
||||||
Activity,
|
|
||||||
Images
|
|
||||||
} from 'lucide-vue-next';
|
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Dialog, DialogContent } from '@/components/ui/dialog';
|
import { Dialog, DialogContent } from '@/components/ui/dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { openExternalLink } from '../../shared/utils';
|
import { openExternalLink } from '../../shared/utils';
|
||||||
@@ -122,14 +103,6 @@
|
|||||||
const { whatsNewDialog } = storeToRefs(vrcxUpdaterStore);
|
const { whatsNewDialog } = storeToRefs(vrcxUpdaterStore);
|
||||||
const { closeWhatsNewDialog, openChangeLogDialogOnly } = vrcxUpdaterStore;
|
const { closeWhatsNewDialog, openChangeLogDialogOnly } = vrcxUpdaterStore;
|
||||||
|
|
||||||
const releaseLabel = computed(() => whatsNewDialog.value.version || '');
|
|
||||||
const releaseTitle = computed(() => {
|
|
||||||
const releaseKey = whatsNewDialog.value.releaseKey;
|
|
||||||
return releaseKey
|
|
||||||
? t(`onboarding.whatsnew.releases.${releaseKey}.title`)
|
|
||||||
: t('onboarding.whatsnew.title');
|
|
||||||
});
|
|
||||||
|
|
||||||
const supporters = [
|
const supporters = [
|
||||||
{
|
{
|
||||||
name: 'Map1en',
|
name: 'Map1en',
|
||||||
@@ -169,7 +142,7 @@
|
|||||||
return hueMap[iconName] ?? '210';
|
return hueMap[iconName] ?? '210';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleViewDetails() {
|
async function handleViewChangelog() {
|
||||||
closeWhatsNewDialog();
|
closeWhatsNewDialog();
|
||||||
await openChangeLogDialogOnly();
|
await openChangeLogDialogOnly();
|
||||||
}
|
}
|
||||||
@@ -180,10 +153,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@keyframes whatsNewAppear {
|
@keyframes featureAppear {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(12px) scale(0.97);
|
transform: translateY(12px) scale(0.95);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|||||||
@@ -2986,28 +2986,28 @@
|
|||||||
"cta": "Got It",
|
"cta": "Got It",
|
||||||
"common": {
|
"common": {
|
||||||
"got_it": "Got It",
|
"got_it": "Got It",
|
||||||
"view_details": "View detailed changelog",
|
"view_changelog": "View changelog",
|
||||||
"support": "Support VRCX"
|
"support": "Support VRCX"
|
||||||
},
|
},
|
||||||
"releases": {
|
"releases": {
|
||||||
"v2026_04_a": {
|
"2026_04_05": {
|
||||||
"title": "What's New in VRCX",
|
"title": "What's New in VRCX",
|
||||||
"items": {
|
"items": {
|
||||||
"quick_search": {
|
"quick_search": {
|
||||||
"title": "Quick Search",
|
"title": "Quick Search",
|
||||||
"description": "Find friends, worlds, avatars, and groups from one search."
|
"description": "Find users, worlds, and avatars in seconds."
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard",
|
"title": "Dashboard",
|
||||||
"description": "Build a workspace with widgets that fit how you work."
|
"description": "Build a workspace that fits how you use VRCX."
|
||||||
},
|
},
|
||||||
"activity_insights": {
|
"activity_insights": {
|
||||||
"title": "Activity Insights",
|
"title": "Activity Insights",
|
||||||
"description": "See activity heatmaps, overlap, and the worlds you visit most."
|
"description": "See shared online time, top worlds, and activity trends."
|
||||||
},
|
},
|
||||||
"my_avatars": {
|
"my_avatars": {
|
||||||
"title": "My Avatars",
|
"title": "My Avatars",
|
||||||
"description": "Browse, manage, and edit your avatars in one place."
|
"description": "Browse and manage your avatars with less friction."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,67 @@
|
|||||||
const whatsNewReleases = {
|
const whatsNewReleases = Object.freeze({
|
||||||
v2026_04_a: {
|
'2026.04.05': {
|
||||||
titleKey: 'onboarding.whatsnew.releases.v2026_04_a.title',
|
|
||||||
releaseLabel: '2026.04',
|
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
key: 'quick_search',
|
key: 'quick_search',
|
||||||
icon: 'search',
|
icon: 'search'
|
||||||
titleKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.quick_search.title',
|
|
||||||
descriptionKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.quick_search.description'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'dashboard',
|
key: 'dashboard',
|
||||||
icon: 'layout-dashboard',
|
icon: 'layout-dashboard'
|
||||||
titleKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.dashboard.title',
|
|
||||||
descriptionKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.dashboard.description'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'activity_insights',
|
key: 'activity_insights',
|
||||||
icon: 'activity',
|
icon: 'activity'
|
||||||
titleKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.activity_insights.title',
|
|
||||||
descriptionKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.activity_insights.description'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'my_avatars',
|
key: 'my_avatars',
|
||||||
icon: 'images',
|
icon: 'images'
|
||||||
titleKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.my_avatars.title',
|
|
||||||
descriptionKey:
|
|
||||||
'onboarding.whatsnew.releases.v2026_04_a.items.my_avatars.description'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} version
|
* @param {string} version
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function getWhatsNewReleaseKey(version) {
|
function normalizeReleaseVersion(version) {
|
||||||
const match = String(version || '').match(/(\d{4})\.(\d{2})(?:\.\d{2})?/);
|
const normalizedVersion = String(version || '')
|
||||||
if (!match) {
|
.replace(/^VRCX\s+/, '')
|
||||||
return '';
|
.trim();
|
||||||
}
|
return /^\d{4}\.\d{2}\.\d{2}$/.test(normalizedVersion)
|
||||||
return `v${match[1]}_${match[2]}_a`;
|
? normalizedVersion
|
||||||
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} version
|
* @param {string} version
|
||||||
* @returns {{titleKey: string, releaseLabel?: string, items: Array<{key: string, icon: string, titleKey: string, descriptionKey: string}>} | null}
|
* @returns {{titleKey: string, items: Array<{key: string, icon: string, titleKey: string, descriptionKey: string}>} | null}
|
||||||
*/
|
*/
|
||||||
function getWhatsNewRelease(version) {
|
function getWhatsNewRelease(version) {
|
||||||
const releaseKey = String(version || '');
|
const normalizedVersion = normalizeReleaseVersion(version);
|
||||||
if (!releaseKey) {
|
if (!normalizedVersion) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return whatsNewReleases[releaseKey] ?? null;
|
const release = whatsNewReleases[normalizedVersion];
|
||||||
|
if (!release) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getWhatsNewRelease, getWhatsNewReleaseKey, whatsNewReleases };
|
const i18nKey = normalizedVersion.replaceAll('.', '_');
|
||||||
|
const baseKey = `onboarding.whatsnew.releases.${i18nKey}`;
|
||||||
|
return {
|
||||||
|
titleKey: `${baseKey}.title`,
|
||||||
|
items: release.items.map((item) => ({
|
||||||
|
...item,
|
||||||
|
titleKey: `${baseKey}.items.${item.key}.title`,
|
||||||
|
descriptionKey: `${baseKey}.items.${item.key}.description`
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getWhatsNewRelease,
|
||||||
|
normalizeReleaseVersion,
|
||||||
|
whatsNewReleases
|
||||||
|
};
|
||||||
|
|||||||
+84
-39
@@ -7,7 +7,7 @@ import { logWebRequest } from '../services/appConfig';
|
|||||||
import { branches } from '../shared/constants';
|
import { branches } from '../shared/constants';
|
||||||
import {
|
import {
|
||||||
getWhatsNewRelease,
|
getWhatsNewRelease,
|
||||||
getWhatsNewReleaseKey
|
normalizeReleaseVersion
|
||||||
} from '../shared/constants/whatsNewReleases';
|
} from '../shared/constants/whatsNewReleases';
|
||||||
import { changeLogRemoveLinks } from '../shared/utils';
|
import { changeLogRemoveLinks } from '../shared/utils';
|
||||||
|
|
||||||
@@ -15,6 +15,12 @@ import configRepository from '../services/config';
|
|||||||
|
|
||||||
import * as workerTimers from 'worker-timers';
|
import * as workerTimers from 'worker-timers';
|
||||||
|
|
||||||
|
const emptyWhatsNewDialog = () => ({
|
||||||
|
visible: false,
|
||||||
|
titleKey: '',
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
|
||||||
export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@@ -40,12 +46,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
buildName: '',
|
buildName: '',
|
||||||
changeLog: ''
|
changeLog: ''
|
||||||
});
|
});
|
||||||
const whatsNewDialog = ref({
|
const whatsNewDialog = ref(emptyWhatsNewDialog());
|
||||||
visible: false,
|
|
||||||
version: '',
|
|
||||||
releaseKey: '',
|
|
||||||
items: []
|
|
||||||
});
|
|
||||||
const pendingVRCXUpdate = ref(false);
|
const pendingVRCXUpdate = ref(false);
|
||||||
const pendingVRCXInstall = ref('');
|
const pendingVRCXInstall = ref('');
|
||||||
const updateInProgress = ref(false);
|
const updateInProgress = ref(false);
|
||||||
@@ -82,10 +83,25 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
await initBranch();
|
await initBranch();
|
||||||
await loadVrcxId();
|
await loadVrcxId();
|
||||||
|
|
||||||
if (await compareAppVersion()) {
|
let checkedForUpdatesDuringAnnouncement = false;
|
||||||
await showWhatsNewDialog();
|
if (await shouldAnnounceCurrentVersion()) {
|
||||||
|
const shown = await showWhatsNewDialog();
|
||||||
|
if (shown) {
|
||||||
|
await markCurrentVersionAsSeen();
|
||||||
|
} else if (isRecognizedStableReleaseVersion()) {
|
||||||
|
const result = await showChangeLogDialog({ prefetch: true });
|
||||||
|
checkedForUpdatesDuringAnnouncement = result.checkedForUpdates;
|
||||||
|
if (result.shown) {
|
||||||
|
await markCurrentVersionAsSeen();
|
||||||
}
|
}
|
||||||
if (autoUpdateVRCX.value !== 'Off') {
|
}
|
||||||
|
} else {
|
||||||
|
await syncCurrentVersionState();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
autoUpdateVRCX.value !== 'Off' &&
|
||||||
|
!checkedForUpdatesDuringAnnouncement
|
||||||
|
) {
|
||||||
await checkForVRCXUpdate();
|
await checkForVRCXUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,51 +146,58 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
await configRepository.setString('VRCX_branch', branch.value);
|
await configRepository.setString('VRCX_branch', branch.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function compareAppVersion() {
|
async function hasVersionChanged() {
|
||||||
const lastVersion = await configRepository.getString(
|
const lastVersion = await configRepository.getString(
|
||||||
'VRCX_lastVRCXVersion',
|
'VRCX_lastVRCXVersion',
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
if (lastVersion !== currentVersion.value) {
|
return lastVersion !== currentVersion.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function markCurrentVersionAsSeen() {
|
||||||
await configRepository.setString(
|
await configRepository.setString(
|
||||||
'VRCX_lastVRCXVersion',
|
'VRCX_lastVRCXVersion',
|
||||||
currentVersion.value
|
currentVersion.value
|
||||||
);
|
);
|
||||||
return branch.value === 'Stable' && lastVersion;
|
}
|
||||||
|
|
||||||
|
async function syncCurrentVersionState() {
|
||||||
|
if (await hasVersionChanged()) {
|
||||||
|
await markCurrentVersionAsSeen();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function shouldAnnounceCurrentVersion() {
|
||||||
* @returns {string}
|
if (branch.value !== 'Stable' || !isRecognizedStableReleaseVersion()) {
|
||||||
*/
|
return false;
|
||||||
function getCurrentWhatsNewReleaseKey() {
|
}
|
||||||
return getWhatsNewReleaseKey(currentVersion.value);
|
const lastVersion = await configRepository.getString(
|
||||||
|
'VRCX_lastVRCXVersion',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
return Boolean(lastVersion) && lastVersion !== currentVersion.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRecognizedStableReleaseVersion() {
|
||||||
|
return Boolean(normalizeReleaseVersion(currentVersion.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
async function showWhatsNewDialog() {
|
async function showWhatsNewDialog() {
|
||||||
const releaseKey = getCurrentWhatsNewReleaseKey();
|
const release = getWhatsNewRelease(currentVersion.value);
|
||||||
const release = getWhatsNewRelease(releaseKey);
|
|
||||||
|
|
||||||
if (!release) {
|
if (!release) {
|
||||||
whatsNewDialog.value = {
|
whatsNewDialog.value = emptyWhatsNewDialog();
|
||||||
visible: false,
|
|
||||||
version: '',
|
|
||||||
releaseKey: '',
|
|
||||||
items: []
|
|
||||||
};
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayVersion = currentVersion.value.replace(/^VRCX\s+/, '');
|
|
||||||
|
|
||||||
whatsNewDialog.value = {
|
whatsNewDialog.value = {
|
||||||
visible: true,
|
visible: true,
|
||||||
version: release.releaseLabel || displayVersion,
|
titleKey: release.titleKey,
|
||||||
releaseKey,
|
|
||||||
items: release.items.map((item) => ({ ...item }))
|
items: release.items.map((item) => ({ ...item }))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -242,9 +265,8 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
currentVersion.value === 'VRCX Nightly Build' ||
|
currentVersion.value === 'VRCX Nightly Build' ||
|
||||||
currentVersion.value === 'VRCX Build'
|
currentVersion.value === 'VRCX Build'
|
||||||
) {
|
) {
|
||||||
changeLogDialog.value.changeLog = '-';
|
|
||||||
// ignore custom builds
|
// ignore custom builds
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (branch.value === 'Beta') {
|
if (branch.value === 'Beta') {
|
||||||
// move Beta users to stable
|
// move Beta users to stable
|
||||||
@@ -269,7 +291,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
json = JSON.parse(response.data);
|
json = JSON.parse(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to check for VRCX update', error);
|
console.error('Failed to check for VRCX update', error);
|
||||||
return;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
checkingForVRCXUpdate.value = false;
|
checkingForVRCXUpdate.value = false;
|
||||||
}
|
}
|
||||||
@@ -279,7 +301,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
message: `${response.status} ${response.data}`
|
message: `${response.status} ${response.data}`
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
pendingVRCXUpdate.value = false;
|
pendingVRCXUpdate.value = false;
|
||||||
logWebRequest('[EXTERNAL GET]', url, `(${response.status})`, json);
|
logWebRequest('[EXTERNAL GET]', url, `(${response.status})`, json);
|
||||||
@@ -290,7 +312,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
setLatestAppVersion(releaseName);
|
setLatestAppVersion(releaseName);
|
||||||
VRCXUpdateDialog.value.updatePendingIsLatest = false;
|
VRCXUpdateDialog.value.updatePendingIsLatest = false;
|
||||||
if (autoUpdateVRCX.value === 'Off') {
|
if (autoUpdateVRCX.value === 'Off') {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
if (releaseName === pendingVRCXInstall.value) {
|
if (releaseName === pendingVRCXInstall.value) {
|
||||||
// update already downloaded
|
// update already downloaded
|
||||||
@@ -300,7 +322,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
json.assets
|
json.assets
|
||||||
);
|
);
|
||||||
if (!downloadUrl) {
|
if (!downloadUrl) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
pendingVRCXUpdate.value = true;
|
pendingVRCXUpdate.value = true;
|
||||||
if (updateToastRelease.value !== releaseName) {
|
if (updateToastRelease.value !== releaseName) {
|
||||||
@@ -325,7 +347,9 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
async function showVRCXUpdateDialog() {
|
async function showVRCXUpdateDialog() {
|
||||||
const D = VRCXUpdateDialog.value;
|
const D = VRCXUpdateDialog.value;
|
||||||
@@ -441,9 +465,31 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function showChangeLogDialog() {
|
async function showChangeLogDialog(options = {}) {
|
||||||
|
const { prefetch = false } = options;
|
||||||
|
|
||||||
|
if (prefetch) {
|
||||||
|
const loaded = await ensureChangeLogReady();
|
||||||
|
if (!loaded) {
|
||||||
|
return { shown: false, checkedForUpdates: true };
|
||||||
|
}
|
||||||
changeLogDialog.value.visible = true;
|
changeLogDialog.value.visible = true;
|
||||||
checkForVRCXUpdate();
|
return { shown: true, checkedForUpdates: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
changeLogDialog.value.visible = true;
|
||||||
|
void ensureChangeLogReady();
|
||||||
|
return { shown: true, checkedForUpdates: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureChangeLogReady() {
|
||||||
|
if (
|
||||||
|
changeLogDialog.value.buildName &&
|
||||||
|
changeLogDialog.value.changeLog
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return checkForVRCXUpdate();
|
||||||
}
|
}
|
||||||
function restartVRCX(isUpgrade) {
|
function restartVRCX(isUpgrade) {
|
||||||
if (!LINUX) {
|
if (!LINUX) {
|
||||||
@@ -486,7 +532,6 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
setAutoUpdateVRCX,
|
setAutoUpdateVRCX,
|
||||||
setBranch,
|
setBranch,
|
||||||
|
|
||||||
compareAppVersion,
|
|
||||||
showWhatsNewDialog,
|
showWhatsNewDialog,
|
||||||
closeWhatsNewDialog,
|
closeWhatsNewDialog,
|
||||||
openChangeLogDialogOnly,
|
openChangeLogDialogOnly,
|
||||||
|
|||||||
Reference in New Issue
Block a user