You've already forked AstralRinth
refactor(app-frontend): move launcher update flow to AstralRinth helper and modal
This commit is contained in:
@@ -85,7 +85,7 @@ import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
|
||||
import { config } from '@/config'
|
||||
import { check_reachable } from '@/helpers/auth.js'
|
||||
import { get_user, get_version } from '@/helpers/cache.js'
|
||||
import { command_listener, notification_listener, warning_listener, log_listener } from '@/helpers/events.js'
|
||||
import { command_listener, notification_listener, warning_listener } from '@/helpers/events.js'
|
||||
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.ts'
|
||||
import { create_profile_and_install_from_file } from '@/helpers/pack'
|
||||
import { list } from '@/helpers/profile.js'
|
||||
@@ -109,7 +109,7 @@ import { AppNotificationManager } from './providers/app-notifications'
|
||||
import { AppPopupNotificationManager } from './providers/app-popup-notifications'
|
||||
|
||||
// This code line modified by AstralRinth
|
||||
import { getRemote, updateState } from '@/helpers/update.js'
|
||||
import { fetchRemote, isUpdateAvailable } from '@/helpers/astralrinth/update'
|
||||
|
||||
const themeStore = useTheming()
|
||||
const router = useRouter()
|
||||
@@ -119,23 +119,23 @@ const APP_SIDEBAR_WIDTH = 300
|
||||
const INTERCOM_BUBBLE_DEFAULT_PADDING = 20
|
||||
// This code line modified by AstralRinth
|
||||
const filteredNewsPhrases = [
|
||||
"LGBT",
|
||||
"LGBTQ",
|
||||
"LGBTQ+",
|
||||
"LGBTQIA+",
|
||||
"gay",
|
||||
"lesbian",
|
||||
"bisexual",
|
||||
"pansexual",
|
||||
"asexual",
|
||||
"aromantic",
|
||||
"transgender",
|
||||
"nonbinary",
|
||||
"intersex",
|
||||
"homosexual",
|
||||
"homosexuality",
|
||||
"pride",
|
||||
];
|
||||
'LGBT',
|
||||
'LGBTQ',
|
||||
'LGBTQ+',
|
||||
'LGBTQIA+',
|
||||
'gay',
|
||||
'lesbian',
|
||||
'bisexual',
|
||||
'pansexual',
|
||||
'asexual',
|
||||
'aromantic',
|
||||
'transgender',
|
||||
'nonbinary',
|
||||
'intersex',
|
||||
'homosexual',
|
||||
'homosexuality',
|
||||
'pride',
|
||||
]
|
||||
const credentials = ref()
|
||||
const sidebarToggled = ref(true)
|
||||
const unsubscribeSidebarToggle = themeStore.$subscribe(() => {
|
||||
@@ -172,6 +172,8 @@ const popupNotificationManager = new AppPopupNotificationManager()
|
||||
providePopupNotificationManager(popupNotificationManager)
|
||||
const { addPopupNotification } = popupNotificationManager
|
||||
|
||||
const settingsModal = ref(null)
|
||||
|
||||
const appVersion = getVersion()
|
||||
const tauriApiClient = new TauriModrinthClient({
|
||||
userAgent: async () => `modrinth/theseus/${await appVersion} (support@modrinth.com)`,
|
||||
@@ -281,7 +283,22 @@ const authUnreachable = computed(() => {
|
||||
onMounted(async () => {
|
||||
await useCheckDisableMouseover()
|
||||
// This code line modified by AstralRinth
|
||||
await getRemote(false)
|
||||
await fetchRemote()
|
||||
if (isUpdateAvailable.value) {
|
||||
addPopupNotification({
|
||||
title: formatMessage(messages.launcherUpdateAvailableTitle),
|
||||
text: formatMessage(messages.launcherUpdateAvailableText),
|
||||
type: 'info',
|
||||
autoCloseMs: 12000,
|
||||
buttons: [
|
||||
{
|
||||
label: formatMessage(messages.launcherUpdateAvailableAction),
|
||||
action: () => settingsModal.value?.showUpdateModal?.(),
|
||||
color: 'brand',
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
document.querySelector('body').addEventListener('click', handleClick)
|
||||
document.querySelector('body').addEventListener('auxclick', handleAuxClick)
|
||||
@@ -305,6 +322,18 @@ const messages = defineMessages({
|
||||
defaultMessage:
|
||||
'Minecraft authentication servers may be down right now. Check your internet connection and try again later.',
|
||||
},
|
||||
launcherUpdateAvailableTitle: {
|
||||
id: 'astralrinth.app.launcher-update.available.title',
|
||||
defaultMessage: 'Launcher update available',
|
||||
},
|
||||
launcherUpdateAvailableText: {
|
||||
id: 'astralrinth.app.launcher-update.available.text',
|
||||
defaultMessage: 'New version of AstralRinth is available for download.',
|
||||
},
|
||||
launcherUpdateAvailableAction: {
|
||||
id: 'astralrinth.app.launcher-update.available.action',
|
||||
defaultMessage: 'View update',
|
||||
},
|
||||
})
|
||||
|
||||
// This code line modified by AstralRinth
|
||||
@@ -705,10 +734,7 @@ async function logOut() {
|
||||
}
|
||||
|
||||
// This code line modified by AstralRinth
|
||||
const hasPlus = computed(
|
||||
() =>
|
||||
!!credentials.value?.user,
|
||||
)
|
||||
const hasPlus = computed(() => !!credentials.value?.user)
|
||||
|
||||
async function fetchIntercomToken() {
|
||||
const creds = await getCreds()
|
||||
@@ -1121,18 +1147,20 @@ provideAppUpdateDownloadProgress(appUpdateDownload) // [AR Note] If delete this
|
||||
</NavButton>
|
||||
<div class="flex flex-grow"></div>
|
||||
<!-- This code line modified by AstralRinth -->
|
||||
<template v-if="updateState">
|
||||
<template v-if="isUpdateAvailable">
|
||||
<NavButton
|
||||
class="neon-icon pulse"
|
||||
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
|
||||
:to="() => $refs.settingsModal.show()">
|
||||
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
|
||||
:to="() => $refs.settingsModal.show()"
|
||||
>
|
||||
<SettingsIcon />
|
||||
</NavButton>
|
||||
</template>
|
||||
<template v-else>
|
||||
<NavButton
|
||||
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
|
||||
:to="() => $refs.settingsModal.show()">
|
||||
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
|
||||
:to="() => $refs.settingsModal.show()"
|
||||
>
|
||||
<SettingsIcon />
|
||||
</NavButton>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
<script setup lang="ts">
|
||||
import { Button, defineMessages, useVIntl } from '@modrinth/ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||
import {
|
||||
downloadLatestRelease,
|
||||
isUpdateInstalling,
|
||||
LAUNCHER_RELEASES_URL,
|
||||
LAUNCHER_REPOSITORY_URL,
|
||||
latestLauncherRelease,
|
||||
} from '@/helpers/astralrinth/update'
|
||||
|
||||
type ModalHandle = {
|
||||
hide: () => void
|
||||
show: () => void
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
version: string
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const updateModalView = ref<ModalHandle | null>(null)
|
||||
const updateRequestFailView = ref<ModalHandle | null>(null)
|
||||
|
||||
const releaseTag = computed(() => latestLauncherRelease.value?.tag_name ?? '')
|
||||
const releaseTitle = computed(() => latestLauncherRelease.value?.name ?? '')
|
||||
|
||||
const messages = defineMessages({
|
||||
updateHeader: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.header',
|
||||
defaultMessage: 'AstralRinth launcher update',
|
||||
},
|
||||
updateTitle: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.title',
|
||||
defaultMessage: 'A new version of the AstralRinth launcher is available.',
|
||||
},
|
||||
updateDescription: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.description',
|
||||
defaultMessage:
|
||||
'You are using an older version. We recommend updating now for the latest fixes and improvements.',
|
||||
},
|
||||
updateNoticeTitle: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.notice-title',
|
||||
defaultMessage: '⚠️ Before you continue',
|
||||
},
|
||||
updateNoticeLead: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.notice-lead',
|
||||
defaultMessage:
|
||||
'Save your work, close all running launcher instances, and back up your launcher data before installing the update.',
|
||||
},
|
||||
updateNoticeWindows: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.notice-windows',
|
||||
defaultMessage: 'On Windows, important data may be stored in',
|
||||
},
|
||||
updateNoticeMacos: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.notice-macos',
|
||||
defaultMessage: 'On macOS, important data may be stored in',
|
||||
},
|
||||
updateNoticeOutro: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.notice-outro',
|
||||
defaultMessage: 'To avoid data loss, keep a backup copy in a safe place before continuing.',
|
||||
},
|
||||
latestReleaseTag: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.latest-release-tag',
|
||||
defaultMessage: '☁️ Latest release tag:',
|
||||
},
|
||||
latestReleaseTitle: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.latest-release-title',
|
||||
defaultMessage: '☁️ Latest release title:',
|
||||
},
|
||||
installedVersion: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.installed-version',
|
||||
defaultMessage: '💾 Installed & Running version:',
|
||||
},
|
||||
repositoryLink: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.repository-link',
|
||||
defaultMessage: 'Open the project repository',
|
||||
},
|
||||
cancelAction: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.cancel-action',
|
||||
defaultMessage: 'Cancel',
|
||||
},
|
||||
downloadAction: {
|
||||
id: 'astralrinth.app.launcher-update-modal.update.download-action',
|
||||
defaultMessage: 'Download update and close',
|
||||
},
|
||||
errorHeader: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.header',
|
||||
defaultMessage: 'Could not download the update',
|
||||
},
|
||||
errorTitle: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.title',
|
||||
defaultMessage: 'Download failed',
|
||||
},
|
||||
errorDescription: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.description',
|
||||
defaultMessage: 'AstralRinth could not download the update file from the server.',
|
||||
},
|
||||
errorHelpText: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.help-text',
|
||||
defaultMessage: 'You can try downloading it manually from',
|
||||
},
|
||||
errorHelpLink: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.help-link',
|
||||
defaultMessage: 'AstralRinth repository releases',
|
||||
},
|
||||
errorHelpSuffix: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.help-suffix',
|
||||
defaultMessage: 'if a newer release is available there.',
|
||||
},
|
||||
localVersion: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.local-version',
|
||||
defaultMessage: 'Local AstralRinth:',
|
||||
},
|
||||
closeAction: {
|
||||
id: 'astralrinth.app.launcher-update-modal.error.close-action',
|
||||
defaultMessage: 'Close',
|
||||
},
|
||||
})
|
||||
|
||||
async function show() {
|
||||
updateModalView.value?.show()
|
||||
}
|
||||
|
||||
async function initDownload() {
|
||||
updateModalView.value?.hide()
|
||||
const result = await downloadLatestRelease()
|
||||
|
||||
if (!result) {
|
||||
updateRequestFailView.value?.show()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
hide: () => updateModalView.value?.hide(),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ModalWrapper
|
||||
ref="updateModalView"
|
||||
:has-to-type="false"
|
||||
:header="formatMessage(messages.updateHeader)"
|
||||
>
|
||||
<div class="space-y-3 pb-16">
|
||||
<div class="space-y-1 rounded-2xl border border-solid border-[rgba(255,255,255,0.12)] p-3">
|
||||
<p class="m-0 text-base">
|
||||
<strong>{{ formatMessage(messages.updateTitle) }}</strong>
|
||||
</p>
|
||||
<p class="m-0 text-secondary">{{ formatMessage(messages.updateDescription) }}</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="space-y-2 rounded-2xl border border-solid border-[rgba(255,255,255,0.12)] bg-[rgba(255,255,255,0.03)] p-3"
|
||||
>
|
||||
<div class="space-y-2">
|
||||
<p class="m-0">
|
||||
<strong class="neon-text">{{ formatMessage(messages.updateNoticeTitle) }}</strong>
|
||||
</p>
|
||||
<p class="m-0 text-secondary text-sm">{{ formatMessage(messages.updateNoticeLead) }}</p>
|
||||
<p class="m-0 text-sm">
|
||||
{{ formatMessage(messages.updateNoticeWindows) }}
|
||||
<code class="neon-text">%appdata%\Roaming\AstralRinthApp</code>
|
||||
</p>
|
||||
<p class="m-0 text-sm">
|
||||
{{ formatMessage(messages.updateNoticeMacos) }}
|
||||
<code class="neon-text">~/Library/Application Support/AstralRinthApp</code>
|
||||
</p>
|
||||
<p class="m-0 text-sm">{{ formatMessage(messages.updateNoticeOutro) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="space-y-2 rounded-2xl border border-solid border-[rgba(255,255,255,0.12)] p-3 text-sm text-secondary"
|
||||
>
|
||||
<p class="m-0">
|
||||
<strong>{{ formatMessage(messages.latestReleaseTag) }}</strong>
|
||||
<span class="neon-text">{{ releaseTag }}</span>
|
||||
<br />
|
||||
<strong>{{ formatMessage(messages.latestReleaseTitle) }}</strong>
|
||||
<span class="neon-text">{{ releaseTitle }}</span>
|
||||
<br />
|
||||
<strong>{{ formatMessage(messages.installedVersion) }}</strong>
|
||||
<span class="neon-text">v{{ props.version }}</span>
|
||||
</p>
|
||||
<a
|
||||
class="inline-flex neon-text"
|
||||
:href="LAUNCHER_REPOSITORY_URL"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{{ formatMessage(messages.repositoryLink) }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-4 right-4 flex items-center gap-4 neon-button neon">
|
||||
<Button class="bordered" @click="updateModalView?.hide()">
|
||||
{{ formatMessage(messages.cancelAction) }}
|
||||
</Button>
|
||||
<Button class="bordered" :disabled="isUpdateInstalling" @click="initDownload()">
|
||||
{{ formatMessage(messages.downloadAction) }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
|
||||
<ModalWrapper
|
||||
ref="updateRequestFailView"
|
||||
:has-to-type="false"
|
||||
:header="formatMessage(messages.errorHeader)"
|
||||
>
|
||||
<div class="space-y-3 pb-16">
|
||||
<div class="space-y-2 rounded-2xl border border-solid border-[rgba(255,255,255,0.12)] p-3">
|
||||
<p><strong>{{ formatMessage(messages.errorTitle) }}</strong></p>
|
||||
<p class="m-0 text-secondary">{{ formatMessage(messages.errorDescription) }}</p>
|
||||
<p class="m-0 text-sm">
|
||||
{{ formatMessage(messages.errorHelpText) }}
|
||||
<a
|
||||
class="neon-text"
|
||||
:href="LAUNCHER_RELEASES_URL"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{{ formatMessage(messages.errorHelpLink) }}
|
||||
</a>
|
||||
{{ formatMessage(messages.errorHelpSuffix) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="rounded-2xl border border-solid border-[rgba(255,255,255,0.12)] p-3 text-sm text-secondary">
|
||||
<p class="m-0">
|
||||
<strong>{{ formatMessage(messages.localVersion) }}</strong>
|
||||
<span class="neon-text">v{{ props.version }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-4 right-4 flex items-center gap-4 neon-button neon">
|
||||
<Button class="bordered" @click="updateRequestFailView?.hide()">
|
||||
{{ formatMessage(messages.closeAction) }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../../../../packages/assets/styles/astralrinth/neon-button.scss';
|
||||
@import '../../../../../../packages/assets/styles/astralrinth/neon-text.scss';
|
||||
</style>
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
ToggleRightIcon,
|
||||
} from '@modrinth/assets'
|
||||
import {
|
||||
Button,
|
||||
commonMessages,
|
||||
commonSettingsMessages,
|
||||
defineMessage,
|
||||
@@ -26,7 +25,7 @@ import { getVersion } from '@tauri-apps/api/app'
|
||||
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||
import LauncherUpdateModal from '@/components/ui/astralrinth/LauncherUpdateModal.vue'
|
||||
import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
|
||||
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
|
||||
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
|
||||
@@ -35,22 +34,16 @@ import LanguageSettings from '@/components/ui/settings/LanguageSettings.vue'
|
||||
import PrivacySettings from '@/components/ui/settings/PrivacySettings.vue'
|
||||
import ResourceManagementSettings from '@/components/ui/settings/ResourceManagementSettings.vue'
|
||||
import { get, set } from '@/helpers/settings.ts'
|
||||
import { getRemote, installState, updateState } from '@/helpers/update.js'
|
||||
import { isUpdateInstalling, isUpdateAvailable } from '@/helpers/astralrinth/update'
|
||||
import { injectAppUpdateDownloadProgress } from '@/providers/download-progress.ts'
|
||||
import { useTheming } from '@/store/state'
|
||||
|
||||
type ModalHandle = {
|
||||
hide: () => void
|
||||
show: () => void
|
||||
}
|
||||
|
||||
const themeStore = useTheming()
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const devModeCounter = ref(0)
|
||||
const modal = ref<InstanceType<typeof TabbedModal> | null>(null)
|
||||
const updateModalView = ref<ModalHandle | null>(null)
|
||||
const updateRequestFailView = ref<ModalHandle | null>(null)
|
||||
const launcherUpdateModal = ref<InstanceType<typeof LauncherUpdateModal> | null>(null)
|
||||
|
||||
const developerModeEnabled = defineMessage({
|
||||
id: 'app.settings.developer-mode-enabled',
|
||||
@@ -120,20 +113,11 @@ function show() {
|
||||
}
|
||||
|
||||
function showUpdateModal() {
|
||||
updateModalView.value?.show()
|
||||
void getRemote(false)
|
||||
modal.value?.show()
|
||||
void launcherUpdateModal.value?.show()
|
||||
}
|
||||
|
||||
async function initDownload() {
|
||||
updateModalView.value?.hide()
|
||||
const result = await getRemote(true)
|
||||
|
||||
if (!result) {
|
||||
updateRequestFailView.value?.show()
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ show })
|
||||
defineExpose({ show, showUpdateModal })
|
||||
|
||||
const { progress, version: downloadingVersion } = injectAppUpdateDownloadProgress()
|
||||
|
||||
@@ -168,6 +152,14 @@ const messages = defineMessages({
|
||||
id: 'app.settings.downloading',
|
||||
defaultMessage: 'Downloading v{version}',
|
||||
},
|
||||
updateInstalling: {
|
||||
id: 'astralrinth.app.settings.update-installing',
|
||||
defaultMessage: 'Installing update...',
|
||||
},
|
||||
viewUpdateInfo: {
|
||||
id: 'astralrinth.app.settings.view-update-info',
|
||||
defaultMessage: 'View update info',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -211,19 +203,19 @@ const messages = defineMessages({
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="updateState"
|
||||
v-if="isUpdateAvailable"
|
||||
class="w-8 h-8 cursor-pointer hover:brightness-75 neon-icon pulse shrink-0"
|
||||
>
|
||||
<template v-if="installState">
|
||||
<template v-if="isUpdateInstalling">
|
||||
<SpinnerIcon
|
||||
class="size-6 animate-spin"
|
||||
v-tooltip.bottom="'Installing in process...'"
|
||||
v-tooltip.bottom="formatMessage(messages.updateInstalling)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<DownloadIcon
|
||||
class="size-6"
|
||||
v-tooltip.bottom="'View update info'"
|
||||
v-tooltip.bottom="formatMessage(messages.viewUpdateInfo)"
|
||||
@click="showUpdateModal()"
|
||||
/>
|
||||
</template>
|
||||
@@ -233,100 +225,9 @@ const messages = defineMessages({
|
||||
</template>
|
||||
</TabbedModal>
|
||||
|
||||
<ModalWrapper
|
||||
ref="updateModalView"
|
||||
:has-to-type="false"
|
||||
header="Request to update the AstralRinth launcher"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<strong>The new version of the AstralRinth launcher is available!</strong>
|
||||
<p>Your version is outdated. We recommend that you update to the latest version.</p>
|
||||
<br />
|
||||
<br />
|
||||
<p><strong>⚠️ Please, read this notice before initialize update process</strong></p>
|
||||
<p>
|
||||
Before updating, make sure that you have saved and closed all running instances and
|
||||
made a backup copy of the launcher data such as
|
||||
<code>%appdata%\Roaming\AstralRinthApp</code> on Windows or
|
||||
<code>~/Library/Application Support/AstralRinthApp</code> on macOS. Remember that
|
||||
the authors of the product are not responsible for the breakdown of your files, so
|
||||
you should always make back up copies of them and keep them in a safe place.
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-sm text-secondary space-y-1">
|
||||
<p>
|
||||
<strong>☁️ Latest release tag:</strong>
|
||||
<span id="releaseTag" class="neon-text"></span>
|
||||
<br />
|
||||
<strong>☁️ Latest release title:</strong>
|
||||
<span id="releaseTitle" class="neon-text"></span>
|
||||
<br />
|
||||
<strong>💾 Installed & Running version:</strong>
|
||||
<span class="neon-text">v{{ version }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
class="neon-text"
|
||||
href="https://me.astralium.su/get/ar"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Checkout our git repository
|
||||
</a>
|
||||
<div class="absolute bottom-4 right-4 flex items-center gap-4 neon-button neon">
|
||||
<Button class="bordered" @click="updateModalView?.hide()">Cancel</Button>
|
||||
<Button class="bordered" @click="initDownload()">Download file</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
|
||||
<ModalWrapper
|
||||
ref="updateRequestFailView"
|
||||
:has-to-type="false"
|
||||
header="Failed to request a file from the server :("
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<p><strong>Error occurred</strong></p>
|
||||
<p>Unfortunately, the program was unable to download the file from our servers.</p>
|
||||
<p>
|
||||
Please try downloading it yourself from
|
||||
<a
|
||||
class="neon-text"
|
||||
href="https://astralium.su/product/astralrinth/source"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
AstralRinth repository
|
||||
</a>
|
||||
if there are any updates available.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="text-sm text-secondary">
|
||||
<p>
|
||||
<strong>Local AstralRinth:</strong>
|
||||
<span class="neon-text">v{{ version }}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute bottom-4 right-4 flex items-center gap-4 neon-button neon">
|
||||
<Button class="bordered" @click="updateRequestFailView?.hide()">Close</Button>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
<LauncherUpdateModal ref="launcherUpdateModal" :version="version" />
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../../../../packages/assets/styles/astralrinth/neon-icon.scss';
|
||||
@import '../../../../../../packages/assets/styles/astralrinth/neon-button.scss';
|
||||
@import '../../../../../../packages/assets/styles/astralrinth/neon-text.scss';
|
||||
|
||||
code {
|
||||
background: linear-gradient(90deg, #005eff, #00cfff);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
import { getVersion } from '@tauri-apps/api/app'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { getOS, initUpdateLauncher, isDev } from '@/helpers/utils.js'
|
||||
|
||||
export type LauncherReleaseAsset = {
|
||||
name: string
|
||||
browser_download_url: string
|
||||
}
|
||||
|
||||
export type LauncherRelease = {
|
||||
tag_name: string
|
||||
name: string
|
||||
assets: LauncherReleaseAsset[]
|
||||
}
|
||||
|
||||
// import.meta.env uses `vite.config.ts`
|
||||
// Environments can be configured in `packages/app-lib/` directory.
|
||||
export const LAUNCHER_REPOSITORY_URL = `${import.meta.env.GIT_ASTRALIUM_URL}didirus/AstralRinth/`
|
||||
export const LAUNCHER_RELEASES_URL = `${LAUNCHER_REPOSITORY_URL}releases`
|
||||
const LAUNCHER_LATEST_RELEASE_API = `${import.meta.env.GIT_ASTRALIUM_API_URL}repos/didirus/AstralRinth/releases/latest`
|
||||
|
||||
export const isUpdateInstalling = ref(false)
|
||||
export const isUpdateAvailable = ref(false)
|
||||
export const latestLauncherRelease = ref<LauncherRelease | null>(null)
|
||||
|
||||
const currentOS = ref('')
|
||||
|
||||
const systems = ['macos', 'windows', 'linux'] as const
|
||||
const osExtensions = {
|
||||
"linux": ['.deb'],
|
||||
"macos": ['.dmg', '.pkg', '.app'],
|
||||
"windows": ['.exe', '.msi']
|
||||
}
|
||||
|
||||
const isDeveloper = await isDev()
|
||||
|
||||
const blacklistBeginPrefixes = [
|
||||
'dev',
|
||||
'nightly',
|
||||
'dirty',
|
||||
'dirty-dev',
|
||||
'dirty-nightly',
|
||||
'dirty_dev',
|
||||
'dirty_nightly',
|
||||
]
|
||||
|
||||
export async function fetchRemote(): Promise<void> {
|
||||
currentOS.value = (await getOS()).toLowerCase()
|
||||
|
||||
try {
|
||||
const response = await fetch(LAUNCHER_LATEST_RELEASE_API)
|
||||
if (!response.ok) {
|
||||
throw new Error(String(response.status))
|
||||
}
|
||||
|
||||
const remoteData = (await response.json()) as LauncherRelease
|
||||
latestLauncherRelease.value = remoteData
|
||||
|
||||
if (systems.includes(currentOS.value as (typeof systems)[number])) {
|
||||
const localVersion = normalizeVersion(await getVersion())
|
||||
const remoteVersion = normalizeVersion(remoteData.tag_name)
|
||||
isUpdateAvailable.value = remoteVersion !== localVersion
|
||||
} else {
|
||||
isUpdateAvailable.value = false
|
||||
}
|
||||
|
||||
if (isDeveloper) {
|
||||
console.debug('Update available state is', isUpdateAvailable.value)
|
||||
console.debug('Remote version is', remoteData.tag_name)
|
||||
console.debug('Remote title is', remoteData.name)
|
||||
console.debug('Local version is', await getVersion())
|
||||
console.debug('Operating System is', currentOS.value)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch remote releases:', error)
|
||||
latestLauncherRelease.value = null
|
||||
isUpdateAvailable.value = false
|
||||
isUpdateInstalling.value = false
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadLatestRelease(): Promise<boolean> {
|
||||
if (!latestLauncherRelease.value) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!currentOS.value) {
|
||||
currentOS.value = (await getOS()).toLowerCase()
|
||||
}
|
||||
|
||||
const installer = getInstaller(resolveOperationalSystemExtension(), latestLauncherRelease.value.assets)
|
||||
if (isDeveloper) {
|
||||
console.debug(installer)
|
||||
}
|
||||
if (!installer) {
|
||||
isUpdateInstalling.value = false
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
isUpdateInstalling.value = true
|
||||
return await initUpdateLauncher(
|
||||
installer.browser_download_url,
|
||||
installer.name,
|
||||
currentOS.value,
|
||||
true,
|
||||
)
|
||||
} finally {
|
||||
isUpdateInstalling.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function getInstaller(
|
||||
osExtensions: string[],
|
||||
builds: LauncherReleaseAsset[],
|
||||
): LauncherReleaseAsset | null {
|
||||
for (const build of builds) {
|
||||
if (blacklistBeginPrefixes.some((prefix) => build.name.startsWith(prefix))) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (osExtensions.some((extension) => build.name.endsWith(extension))) {
|
||||
if (isDeveloper) {
|
||||
console.debug(build.name, build.browser_download_url)
|
||||
}
|
||||
return build
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function resolveOperationalSystemExtension(): string[] {
|
||||
if (currentOS.value === 'macos') {
|
||||
return osExtensions["macos"]
|
||||
}
|
||||
|
||||
if (currentOS.value === 'linux') {
|
||||
return osExtensions["linux"]
|
||||
}
|
||||
|
||||
return osExtensions["windows"]
|
||||
}
|
||||
|
||||
function normalizeVersion(version: string): string {
|
||||
return version.trim().replace(/^v/i, '')
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import { getVersion } from '@tauri-apps/api/app'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { getOS, initUpdateLauncher } from '@/helpers/utils.js'
|
||||
|
||||
export const allowState = ref(false)
|
||||
export const installState = ref(false)
|
||||
export const updateState = ref(false)
|
||||
|
||||
const currentOS = ref('')
|
||||
const api = `https://git.astralium.su/api/v1/repos/didirus/AstralRinth/releases/latest`
|
||||
|
||||
const systems = ['macos', 'windows', 'linux']
|
||||
const macosExtensions = ['.dmg', '.pkg', '.app']
|
||||
const windowsExtensions = ['.exe', '.msi']
|
||||
|
||||
const blacklistBeginPrefixes = [
|
||||
`dev`,
|
||||
`nightly`,
|
||||
`dirty`,
|
||||
`dirty-dev`,
|
||||
`dirty-nightly`,
|
||||
`dirty_dev`,
|
||||
`dirty_nightly`,
|
||||
] // This is blacklisted builds for download. For example, file.startsWith('dev') is not allowed.
|
||||
|
||||
export async function getRemote(isDownloadState) {
|
||||
var releaseTag = null;
|
||||
var releaseTitle = null;
|
||||
var result = false;
|
||||
currentOS.value = await getOS();
|
||||
try {
|
||||
const response = await fetch(api);
|
||||
if (!response.ok) {
|
||||
throw new Error(response.status);
|
||||
}
|
||||
const remoteData = await response.json();
|
||||
releaseTag = document.getElementById('releaseTag');
|
||||
releaseTitle = document.getElementById('releaseTitle');
|
||||
if (releaseTag && releaseTitle) {
|
||||
releaseTag.textContent = remoteData.tag_name;
|
||||
releaseTitle.textContent = remoteData.name;
|
||||
}
|
||||
if (systems.includes(currentOS.value.toLowerCase())) {
|
||||
const localVersion = await getVersion();
|
||||
const isUpdateAvailable = !remoteData.tag_name.includes(localVersion);
|
||||
updateState.value = isUpdateAvailable;
|
||||
allowState.value = isUpdateAvailable;
|
||||
} else {
|
||||
updateState.value = false;
|
||||
allowState.value = false;
|
||||
}
|
||||
if (isDownloadState) {
|
||||
try {
|
||||
installState.value = true;
|
||||
const builds = remoteData.assets;
|
||||
const fileName = getInstaller(getExtension(), builds);
|
||||
result = fileName ? await initUpdateLauncher(fileName[1], fileName[0], currentOS.value, true) : false;
|
||||
installState.value = false;
|
||||
} catch (err) {
|
||||
installState.value = false;
|
||||
}
|
||||
}
|
||||
console.log('Update available state is', updateState.value);
|
||||
console.log('Remote version is', remoteData.tag_name);
|
||||
console.log('Remote title is', remoteData.name);
|
||||
console.log('Local version is', await getVersion());
|
||||
console.log('Operating System is', currentOS.value);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch remote releases:", error);
|
||||
if (!releaseTag) {
|
||||
updateState.value = false;
|
||||
allowState.value = false;
|
||||
installState.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getInstaller(osExtension, builds) {
|
||||
console.log(osExtension, builds)
|
||||
for (const build of builds) {
|
||||
if (blacklistBeginPrefixes.some(prefix => build.name.startsWith(prefix))) {
|
||||
continue;
|
||||
}
|
||||
if (osExtension.some(ext => build.name.endsWith(ext))) {
|
||||
console.log(build.name, build.browser_download_url);
|
||||
return [build.name, build.browser_download_url];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getExtension() {
|
||||
return systems.find(osName => osName === currentOS.value.toLowerCase())?.endsWith('macos')
|
||||
? macosExtensions
|
||||
: windowsExtensions;
|
||||
}
|
||||
@@ -119,6 +119,87 @@
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Cannot reach authentication servers"
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.action": {
|
||||
"message": "View update"
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.text": {
|
||||
"message": "New version of AstralRinth is available for download."
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.title": {
|
||||
"message": "Launcher update available"
|
||||
},
|
||||
"astralrinth.app.settings.update-installing": {
|
||||
"message": "Installing update..."
|
||||
},
|
||||
"astralrinth.app.settings.view-update-info": {
|
||||
"message": "View update info"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.close-action": {
|
||||
"message": "Close"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.description": {
|
||||
"message": "AstralRinth could not download the update file from the server."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.header": {
|
||||
"message": "Could not download the update"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-link": {
|
||||
"message": "AstralRinth repository releases"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-suffix": {
|
||||
"message": "if a newer release is available there."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-text": {
|
||||
"message": "You can try downloading it manually from"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.local-version": {
|
||||
"message": "Local AstralRinth:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.title": {
|
||||
"message": "Download failed"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.cancel-action": {
|
||||
"message": "Cancel"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.description": {
|
||||
"message": "You are using an older version. We recommend updating now for the latest fixes and improvements."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.download-action": {
|
||||
"message": "Download update and close"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.header": {
|
||||
"message": "AstralRinth launcher update"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.installed-version": {
|
||||
"message": "💾 Installed & Running version:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.latest-release-tag": {
|
||||
"message": "☁️ Latest release tag:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.latest-release-title": {
|
||||
"message": "☁️ Latest release title:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-lead": {
|
||||
"message": "Save your work, close all running launcher instances, and back up your launcher data before installing the update."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-macos": {
|
||||
"message": "On macOS, important data may be stored in"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-outro": {
|
||||
"message": "To avoid data loss, keep a backup copy in a safe place before continuing."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-windows": {
|
||||
"message": "On Windows, important data may be stored in"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-title": {
|
||||
"message": "⚠️ Before you continue"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.repository-link": {
|
||||
"message": "Open the project repository"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.title": {
|
||||
"message": "A new version of the AstralRinth launcher is available."
|
||||
},
|
||||
"astralrinth.app.minecraft-account.add-elyby-account": {
|
||||
"message": "Add Ely.by account"
|
||||
},
|
||||
|
||||
@@ -110,6 +110,87 @@
|
||||
"app.auth-servers.unreachable.header": {
|
||||
"message": "Нет связи с серверами аутентификации"
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.action": {
|
||||
"message": "Посмотреть обновление"
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.text": {
|
||||
"message": "Новая версия AstralRinth уже доступна для загрузки."
|
||||
},
|
||||
"astralrinth.app.launcher-update.available.title": {
|
||||
"message": "Доступно обновление лаунчера"
|
||||
},
|
||||
"astralrinth.app.settings.update-installing": {
|
||||
"message": "Установка обновления..."
|
||||
},
|
||||
"astralrinth.app.settings.view-update-info": {
|
||||
"message": "Посмотреть информацию об обновлении"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.close-action": {
|
||||
"message": "Закрыть"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.description": {
|
||||
"message": "AstralRinth не удалось скачать файл обновления с сервера."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.header": {
|
||||
"message": "Не удалось скачать обновление"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-link": {
|
||||
"message": "релизы репозитория AstralRinth"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-suffix": {
|
||||
"message": "если там доступен более новый релиз."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.help-text": {
|
||||
"message": "Вы можете скачать его вручную из"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.local-version": {
|
||||
"message": "Локальная версия AstralRinth:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.error.title": {
|
||||
"message": "Не удалось скачать файл"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.cancel-action": {
|
||||
"message": "Отмена"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.description": {
|
||||
"message": "Вы используете более старую версию. Рекомендуем обновиться сейчас, чтобы получить последние исправления и улучшения."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.download-action": {
|
||||
"message": "Скачать обновление и закрыть"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.header": {
|
||||
"message": "Обновление лаунчера AstralRinth"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.installed-version": {
|
||||
"message": "💾 Установленная и запущенная версия:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.latest-release-tag": {
|
||||
"message": "☁️ Тег последнего релиза:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.latest-release-title": {
|
||||
"message": "☁️ Название последнего релиза:"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-lead": {
|
||||
"message": "Перед установкой обновления сохраните работу, закройте все запущенные экземпляры лаунчера и сделайте резервную копию его данных."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-macos": {
|
||||
"message": "На macOS важные данные могут находиться в"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-outro": {
|
||||
"message": "Чтобы избежать потери данных, сохраните резервную копию в безопасном месте перед продолжением."
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-windows": {
|
||||
"message": "На Windows важные данные могут находиться в"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.notice-title": {
|
||||
"message": "⚠️ Перед продолжением"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.repository-link": {
|
||||
"message": "Открыть репозиторий проекта"
|
||||
},
|
||||
"astralrinth.app.launcher-update-modal.update.title": {
|
||||
"message": "Доступна новая версия лаунчера AstralRinth."
|
||||
},
|
||||
"astralrinth.app.minecraft-account.add-elyby-account": {
|
||||
"message": "Добавить Ely.by аккаунт"
|
||||
},
|
||||
|
||||
@@ -101,7 +101,7 @@ export default defineConfig({
|
||||
},
|
||||
// to make use of `TAURI_ENV_DEBUG` and other env variables
|
||||
// https://v2.tauri.app/reference/environment-variables/#tauri-cli-hook-commands
|
||||
envPrefix: ['VITE_', 'TAURI_', 'MODRINTH_'],
|
||||
envPrefix: ['VITE_', 'TAURI_', 'MODRINTH_', 'GIT_ASTRALIUM_'],
|
||||
build: {
|
||||
rolldownOptions: {
|
||||
onwarn(warning, defaultHandler) {
|
||||
|
||||
@@ -5,8 +5,10 @@ MODRINTH_API_URL=https://api.modrinth.com/v2/
|
||||
MODRINTH_API_URL_V3=https://api.modrinth.com/v3/
|
||||
MODRINTH_SOCKET_URL=wss://api.modrinth.com/
|
||||
MODRINTH_LAUNCHER_META_URL=https://launcher-meta.modrinth.com/
|
||||
GIT_ASTRALIUM_URL=https://git.astralium.su/
|
||||
GIT_ASTRALIUM_API_URL=https://git.astralium.su/api/v1/
|
||||
|
||||
# SQLite database file used by sqlx for type checking. Uncomment this to a valid path
|
||||
# in your system and run `cargo sqlx database setup` to generate an empty database that
|
||||
# can be used for developing the app DB schema
|
||||
#DATABASE_URL=sqlite:///tmp/Modrinth/code/packages/app-lib/.sqlx/generated/state.db
|
||||
#DATABASE_URL=sqlite:///tmp/AstralRinth/code/packages/app-lib/.sqlx/generated/state.db
|
||||
|
||||
@@ -24,3 +24,10 @@
|
||||
0 0 2px rgba(16, 250, 229, 0.4),
|
||||
0 0 4px rgba(16, 250, 229, 0.25);
|
||||
}
|
||||
|
||||
code {
|
||||
background: linear-gradient(90deg, #005eff, #00cfff);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user