Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
import RunningAppBar from '@/components/ui/RunningAppBar.vue'
import SplashScreen from '@/components/ui/SplashScreen.vue'
import UpdateAvailableToast from '@/components/ui/UpdateAvailableToast.vue'
import UpdateToast from '@/components/ui/UpdateToast.vue'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
Expand Down Expand Up @@ -143,6 +144,7 @@ const showOnboarding = ref(false)
const nativeDecorations = ref(false)

const os = ref('')
const isDevEnvironment = ref(false)

const stateInitialized = ref(false)

Expand Down Expand Up @@ -247,6 +249,7 @@ async function setupApp() {

os.value = await getOS()
const dev = await isDev()
isDevEnvironment.value = dev
const version = await getVersion()
showOnboarding.value = !onboarded

Expand Down Expand Up @@ -513,13 +516,13 @@ async function checkUpdates() {

async function performCheck() {
const update = await invoke('plugin:updater|check')
const isExistingUpdate = update.version === availableUpdate.value?.version

if (!update) {
console.log('No update available')
return
}

const isExistingUpdate = update.version === availableUpdate.value?.version

if (isExistingUpdate) {
console.log('Update is already known')
return
Expand Down Expand Up @@ -769,6 +772,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
@restart="installUpdate"
@download="downloadAvailableUpdate"
/>
<UpdateAvailableToast v-else-if="os === 'Linux' && !isDevEnvironment" />
</Transition>
</Suspense>
<Transition name="fade">
Expand Down
105 changes: 105 additions & 0 deletions apps/app-frontend/src/components/ui/UpdateAvailableToast.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<script setup lang="ts">
import { restartApp } from '@/helpers/utils'
import { RefreshCwIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages, defineMessages, useVIntl } from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { onMounted, onUnmounted, ref } from 'vue'

const { formatMessage } = useVIntl()

const dismissed = ref(false)
const availableUpdate = ref<{ version: string } | null>(null)

let checkInterval: ReturnType<typeof setInterval> | null = null

async function checkForUpdate() {
try {
const [response, currentVersion] = await Promise.all([
fetch('https://launcher-files.modrinth.com/updates.json'),
getVersion(),
])
const updates = await response.json()
const latestVersion = updates?.version

if (latestVersion && latestVersion !== currentVersion) {
if (latestVersion !== availableUpdate.value?.version) {
availableUpdate.value = { version: latestVersion }
dismissed.value = false
}
}
} catch (e) {
console.error('Failed to check for updates:', e)
}
}

function dismiss() {
dismissed.value = true
}

onMounted(() => {
checkForUpdate()
checkInterval = setInterval(checkForUpdate, 5 * 60 * 1000)
})

onUnmounted(() => {
if (checkInterval) {
clearInterval(checkInterval)
}
})

const messages = defineMessages({
title: {
id: 'app.update-toast.title',
defaultMessage: 'Update available',
},
body: {
id: 'app.update-toast.body.linux',
defaultMessage:
'Modrinth App v{version} is ready to install! Restart the app to apply the update once it has been installed by your system.',
},
download: {
id: 'app.update-toast.download-page',
defaultMessage: 'Download',
},
changelog: {
id: 'app.update-toast.changelog',
defaultMessage: 'Changelog',
},
restart: {
id: 'app.update-toast.restart',
defaultMessage: 'Restart app',
},
})
</script>
<template>
<div
v-if="availableUpdate && !dismissed"
class="grid grid-cols-[min-content] fixed card-shadow rounded-2xl top-[--top-bar-height] mt-6 right-6 p-4 z-10 bg-bg-raised border-divider border-solid border-[2px]"
>
<div class="flex min-w-[25rem] gap-4">
<h2 class="whitespace-nowrap text-base text-contrast font-semibold m-0 grow">
{{ formatMessage(messages.title) }}
</h2>
<ButtonStyled size="small" circular>
<button v-tooltip="formatMessage(commonMessages.closeButton)" @click="dismiss">
<XIcon />
</button>
</ButtonStyled>
</div>
<p class="text-sm mt-2 mb-0">
{{ formatMessage(messages.body, { version: availableUpdate.version }) }}
</p>
<div class="flex gap-2 mt-4">
<ButtonStyled color="brand">
<button @click="restartApp()">
<RefreshCwIcon /> {{ formatMessage(messages.restart) }}
</button>
</ButtonStyled>
<ButtonStyled>
<a href="https://modrinth.com/news/changelog?filter=app">
{{ formatMessage(messages.changelog) }} <ExternalIcon />
</a>
</ButtonStyled>
</div>
</div>
</template>
6 changes: 6 additions & 0 deletions apps/app-frontend/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
"app.update-toast.body.download-complete": {
"message": "Modrinth App v{version} has finished downloading. Reload to update now, or automatically when you close Modrinth App."
},
"app.update-toast.body.linux": {
"message": "Modrinth App v{version} is ready to install! Restart the app to apply the update once it has been installed by your system."
},
"app.update-toast.body.metered": {
"message": "Modrinth App v{version} is available now! Since you're on a metered network, we didn't automatically download it."
},
Expand All @@ -47,6 +50,9 @@
"app.update-toast.download": {
"message": "Download ({size})"
},
"app.update-toast.download-page": {
"message": "Download"
},
"app.update-toast.downloading": {
"message": "Downloading..."
},
Expand Down
Loading