@@ -50,24 +50,27 @@ let installLoading = ref(false);
5050const isDesktopReleaseMode = ref (
5151 typeof window !== ' undefined' && !! window .astrbotDesktop ?.isDesktop
5252);
53- const redirectConfirmDialog = ref (false );
54- const pendingRedirectUrl = ref (' ' );
55- const resolvingReleaseTarget = ref (false );
56- const DEFAULT_ASTRBOT_RELEASE_BASE_URL = ' https://github.com/AstrBotDevs/AstrBot/releases' ;
57- const resolveReleaseBaseUrl = () => {
58- const raw = import .meta .env .VITE_ASTRBOT_RELEASE_BASE_URL ;
59- // Keep upstream default on AstrBot releases; desktop distributors can override via env injection.
60- const normalized = raw ?.trim ()?.replace (/ \/ + $ / , ' ' ) || ' ' ;
61- const withoutLatestSuffix = normalized .replace (/ \/ latest$ / i , ' ' );
62- return withoutLatestSuffix || DEFAULT_ASTRBOT_RELEASE_BASE_URL ;
63- };
64- const releaseBaseUrl = resolveReleaseBaseUrl ();
65- const getReleaseUrlByTag = (tag : string | null | undefined ) => {
66- const normalizedTag = (tag || ' ' ).trim ();
67- if (! normalizedTag || normalizedTag .toLowerCase () === ' latest' ) {
68- return ` ${releaseBaseUrl }/latest ` ;
53+ const desktopUpdateDialog = ref (false );
54+ const desktopUpdateChecking = ref (false );
55+ const desktopUpdateInstalling = ref (false );
56+ const desktopUpdateHasNewVersion = ref (false );
57+ const desktopUpdateCurrentVersion = ref (' -' );
58+ const desktopUpdateLatestVersion = ref (' -' );
59+ const desktopUpdateStatus = ref (' ' );
60+
61+ const getAppUpdaterBridge = (): AstrBotAppUpdaterBridge | null => {
62+ if (typeof window === ' undefined' ) {
63+ return null ;
64+ }
65+ const bridge = window .astrbotAppUpdater ;
66+ if (
67+ bridge &&
68+ typeof bridge .checkForAppUpdate === ' function' &&
69+ typeof bridge .installAppUpdate === ' function'
70+ ) {
71+ return bridge ;
6972 }
70- return ` ${ releaseBaseUrl }/tag/${ normalizedTag } ` ;
73+ return null ;
7174};
7275
7376const getSelectedGitHubProxy = () => {
@@ -89,16 +92,6 @@ const releasesHeader = computed(() => [
8992 { title: t (' core.header.updateDialog.table.sourceUrl' ), key: ' zipball_url' },
9093 { title: t (' core.header.updateDialog.table.actions' ), key: ' switch' }
9194]);
92- const latestReleaseTag = computed (() => {
93- const firstRelease = (releases .value as any [])?.[0 ];
94- if (firstRelease ?.tag_name ) {
95- return firstRelease .tag_name as string ;
96- }
97- return hasNewVersion .value
98- ? t (' core.header.updateDialog.redirectConfirm.latestLabel' )
99- : (botCurrVersion .value || ' -' );
100- });
101-
10295// Form validation
10396const formValid = ref (true );
10497const passwordRules = computed (() => [
@@ -126,47 +119,88 @@ const accountEditStatus = ref({
126119 message: ' '
127120});
128121
129- const open = (link : string ) => {
130- window .open (link , ' _blank' );
131- };
122+ function cancelDesktopUpdate() {
123+ if (desktopUpdateInstalling .value ) {
124+ return ;
125+ }
126+ desktopUpdateDialog .value = false ;
127+ }
128+
129+ async function openDesktopUpdateDialog() {
130+ desktopUpdateDialog .value = true ;
131+ desktopUpdateChecking .value = true ;
132+ desktopUpdateInstalling .value = false ;
133+ desktopUpdateHasNewVersion .value = false ;
134+ desktopUpdateCurrentVersion .value = ' -' ;
135+ desktopUpdateLatestVersion .value = ' -' ;
136+ desktopUpdateStatus .value = t (' core.header.updateDialog.desktopApp.checking' );
137+
138+ const bridge = getAppUpdaterBridge ();
139+ if (! bridge ) {
140+ desktopUpdateChecking .value = false ;
141+ desktopUpdateStatus .value = t (' core.header.updateDialog.desktopApp.checkFailed' );
142+ return ;
143+ }
132144
133- function requestExternalRedirect(link : string ) {
134- pendingRedirectUrl .value = link ;
135- redirectConfirmDialog .value = true ;
136- }
145+ try {
146+ const result = await bridge .checkForAppUpdate ();
147+ if (! result ?.ok ) {
148+ desktopUpdateCurrentVersion .value = result ?.currentVersion || ' -' ;
149+ desktopUpdateLatestVersion .value =
150+ result ?.latestVersion || result ?.currentVersion || ' -' ;
151+ desktopUpdateStatus .value =
152+ result ?.reason || t (' core.header.updateDialog.desktopApp.checkFailed' );
153+ return ;
154+ }
137155
138- function cancelExternalRedirect() {
139- redirectConfirmDialog .value = false ;
140- pendingRedirectUrl .value = ' ' ;
156+ desktopUpdateCurrentVersion .value = result .currentVersion || ' -' ;
157+ desktopUpdateLatestVersion .value =
158+ result .latestVersion || result .currentVersion || ' -' ;
159+ desktopUpdateHasNewVersion .value = !! result .hasUpdate ;
160+ desktopUpdateStatus .value = result .hasUpdate
161+ ? t (' core.header.updateDialog.desktopApp.hasNewVersion' )
162+ : t (' core.header.updateDialog.desktopApp.isLatest' );
163+ } catch (error ) {
164+ console .error (error );
165+ desktopUpdateStatus .value = t (' core.header.updateDialog.desktopApp.checkFailed' );
166+ } finally {
167+ desktopUpdateChecking .value = false ;
168+ }
141169}
142170
143- function confirmExternalRedirect() {
144- const targetUrl = pendingRedirectUrl .value ;
145- cancelExternalRedirect ();
146- if (targetUrl ) {
147- open (targetUrl );
171+ async function confirmDesktopUpdate() {
172+ if (! desktopUpdateHasNewVersion .value || desktopUpdateInstalling .value ) {
173+ return ;
148174 }
149- }
150175
151- const getReleaseUrlForDesktop = () => {
152- const firstRelease = ( releases . value as any [])?.[ 0 ];
153- if ( firstRelease ?. tag_name ) {
154- return getReleaseUrlByTag ( firstRelease . tag_name as string ) ;
176+ const bridge = getAppUpdaterBridge ();
177+ if ( ! bridge ) {
178+ desktopUpdateStatus . value = t ( ' core.header.updateDialog.desktopApp.installFailed ' );
179+ return ;
155180 }
156- if (hasNewVersion .value ) return getReleaseUrlByTag (' latest' );
157- const tag = botCurrVersion .value ?.startsWith (' v' ) ? botCurrVersion .value : ' latest' ;
158- return getReleaseUrlByTag (tag );
159- };
181+
182+ desktopUpdateInstalling .value = true ;
183+ desktopUpdateStatus .value = t (' core.header.updateDialog.desktopApp.installing' );
184+
185+ try {
186+ const result = await bridge .installAppUpdate ();
187+ if (result ?.ok ) {
188+ desktopUpdateDialog .value = false ;
189+ return ;
190+ }
191+ desktopUpdateStatus .value =
192+ result ?.reason || t (' core.header.updateDialog.desktopApp.installFailed' );
193+ } catch (error ) {
194+ console .error (error );
195+ desktopUpdateStatus .value = t (' core.header.updateDialog.desktopApp.installFailed' );
196+ } finally {
197+ desktopUpdateInstalling .value = false ;
198+ }
199+ }
160200
161201function handleUpdateClick() {
162202 if (isDesktopReleaseMode .value ) {
163- requestExternalRedirect (' ' );
164- resolvingReleaseTarget .value = true ;
165- checkUpdate ();
166- void getReleases ().finally (() => {
167- pendingRedirectUrl .value = getReleaseUrlForDesktop () || getReleaseUrlByTag (' latest' );
168- resolvingReleaseTarget .value = false ;
169- });
203+ void openDesktopUpdateDialog ();
170204 return ;
171205 }
172206 checkUpdate ();
@@ -680,40 +714,38 @@ onMounted(async () => {
680714 </v-card >
681715 </v-dialog >
682716
683- <v-dialog v-model =" redirectConfirmDialog " max-width =" 460" >
717+ <v-dialog v-model =" desktopUpdateDialog " max-width =" 460" >
684718 <v-card >
685719 <v-card-title class =" text-h3 pa-4 pl-6 pb-0" >
686- {{ t('core.header.updateDialog.redirectConfirm .title') }}
720+ {{ t('core.header.updateDialog.desktopApp .title') }}
687721 </v-card-title >
688722 <v-card-text >
689723 <div class =" mb-3" >
690- {{ t('core.header.updateDialog.redirectConfirm .message') }}
724+ {{ t('core.header.updateDialog.desktopApp .message') }}
691725 </div >
692726 <v-alert type =" info" variant =" tonal" density =" compact" >
693727 <div >
694- {{ t('core.header.updateDialog.redirectConfirm.targetVersion') }}
695- <strong v-if =" !resolvingReleaseTarget" >{{ latestReleaseTag }}</strong >
696- <v-progress-circular v-else indeterminate size =" 16" width =" 2" class =" ml-1" />
728+ {{ t('core.header.updateDialog.desktopApp.currentVersion') }}
729+ <strong >{{ desktopUpdateCurrentVersion }}</strong >
697730 </div >
698- <div class =" text-caption" >
699- {{ t('core.header.updateDialog.redirectConfirm.currentVersion') }}
700- {{ botCurrVersion || '-' }}
731+ <div >
732+ {{ t('core.header.updateDialog.desktopApp.latestVersion') }}
733+ <strong v-if =" !desktopUpdateChecking" >{{ desktopUpdateLatestVersion }}</strong >
734+ <v-progress-circular v-else indeterminate size =" 16" width =" 2" class =" ml-1" />
701735 </div >
702736 </v-alert >
703737 <div class =" text-caption mt-3" >
704- <div >{{ t('core.header.updateDialog.redirectConfirm.guideTitle') }}</div >
705- <div >1. {{ t('core.header.updateDialog.redirectConfirm.guideStep1') }}</div >
706- <div >2. {{ t('core.header.updateDialog.redirectConfirm.guideStep2') }}</div >
707- <div >3. {{ t('core.header.updateDialog.redirectConfirm.guideStep3') }}</div >
738+ {{ desktopUpdateStatus }}
708739 </div >
709740 </v-card-text >
710741 <v-card-actions >
711742 <v-spacer ></v-spacer >
712- <v-btn color =" grey" variant =" text" @click =" cancelExternalRedirect " >
743+ <v-btn color =" grey" variant =" text" @click =" cancelDesktopUpdate " :disabled = " desktopUpdateInstalling " >
713744 {{ t('core.common.dialog.cancelButton') }}
714745 </v-btn >
715- <v-btn color =" primary" variant =" flat" @click =" confirmExternalRedirect"
716- :loading =" resolvingReleaseTarget" :disabled =" resolvingReleaseTarget || !pendingRedirectUrl" >
746+ <v-btn color =" primary" variant =" flat" @click =" confirmDesktopUpdate"
747+ :loading =" desktopUpdateInstalling"
748+ :disabled =" desktopUpdateChecking || desktopUpdateInstalling || !desktopUpdateHasNewVersion" >
717749 {{ t('core.common.dialog.confirmButton') }}
718750 </v-btn >
719751 </v-card-actions >
0 commit comments