fix: hide modal header & add "Hide update reminder" button w/ tooltip

This commit is contained in:
IMB11 2025-07-17 11:37:17 +01:00
parent 071e2b58b3
commit 0310cc52d0
4 changed files with 60 additions and 17 deletions

View File

@ -1,5 +1,14 @@
<script setup>
import { computed, onMounted, onUnmounted, ref, watch, useTemplateRef, provide } from 'vue'
import {
computed,
onMounted,
onUnmounted,
ref,
watch,
useTemplateRef,
provide,
nextTick,
} from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import {
ArrowBigUpDashIcon,
@ -72,6 +81,7 @@ import UpdateModal from '@/components/ui/UpdateModal.vue'
import { get_available_capes, get_available_skins } from './helpers/skins'
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { createTooltip, destroyTooltip } from 'floating-vue'
const themeStore = useTheming()
@ -450,6 +460,20 @@ async function forceOpenUpdateModal() {
updateModal.value.show(availableUpdate.value)
}
const updateButton = useTemplateRef('updateButton')
async function showUpdateButtonTooltip() {
await nextTick()
const tooltip = createTooltip(updateButton.value.$el, {
placement: 'right',
content: 'Click here to view the update again.',
})
tooltip.show()
setTimeout(() => {
tooltip.hide()
destroyTooltip(updateButton.value.$el)
}, 3500)
}
function handleClick(e) {
let target = e.target
while (target != null) {
@ -495,6 +519,7 @@ function handleAuxClick(e) {
ref="updateModal"
@update-skipped="skipUpdate"
@update-enqueued-for-later="updateEnqueuedForLater"
@modal-hidden="showUpdateButtonTooltip"
/>
</Suspense>
<Suspense>
@ -549,6 +574,7 @@ function handleAuxClick(e) {
<div class="flex flex-grow"></div>
<NavButton
v-if="!!availableUpdate"
ref="updateButton"
v-tooltip.right="
enqueuedUpdate === availableUpdate?.version
? 'Update installation queued for next restart'

View File

@ -1,18 +1,13 @@
<template>
<ModalWrapper
ref="modal"
:header="formatMessage(messages.header)"
:on-hide="onHide"
:closable="!updatingImmediately && !downloadInProgress"
>
<ModalWrapper ref="modal" hide-header :closable="false" :on-hide="onHide">
<div class="flex flex-col gap-4">
<div class="max-w-[500px]">
<div class="font-extrabold text-contrast text-xl mb-1">
Modrinth App v{{ update!.version }}
<div class="w-[500px]">
<div class="font-extrabold text-contrast text-xl">
{{ formatMessage(messages.header) }} Modrinth App v{{ update!.version }}
</div>
<template v-if="!downloadInProgress && !downloadError">
<div class="mb-4 leading-tight">{{ formatMessage(messages.bodyVersion) }}</div>
<div class="text-sm text-secondary mb-3">
<div class="mb-1 leading-tight">{{ formatMessage(messages.bodyVersion) }}</div>
<div class="text-sm text-secondary mb-2">
{{ formatMessage(messages.downloadSize, { size: formatBytes(updateSize) }) }}
</div>
</template>
@ -49,7 +44,7 @@
</ButtonStyled>
</div>
</div>
<div v-if="!downloadError" class="flex flex-wrap gap-2 w-full mb-2">
<div v-if="!downloadError" class="flex flex-wrap gap-2 w-full">
<JoinedButtons
:actions="installActions"
:disabled="updatingImmediately || downloadInProgress"
@ -74,7 +69,7 @@ import { defineMessages, useVIntl } from '@vintl/vintl'
import { useTemplateRef, ref, computed } from 'vue'
import { AppearingProgressBar, ButtonStyled, JoinedButtons } from '@modrinth/ui'
import type { JoinedButtonAction } from '@modrinth/ui'
import { ExternalIcon, DownloadIcon, RedoIcon, ClipboardCopyIcon } from '@modrinth/assets'
import { ExternalIcon, DownloadIcon, RedoIcon, ClipboardCopyIcon, XIcon } from '@modrinth/assets'
import { enqueueUpdateForInstallation, getUpdateSize } from '@/helpers/utils'
import { formatBytes } from '@modrinth/utils'
import { handleError } from '@/store/notifications'
@ -85,13 +80,14 @@ import { ChatIcon } from '@/assets/icons'
const emit = defineEmits<{
(e: 'updateEnqueuedForLater', version: string | null): Promise<void>
(e: 'modalHidden'): void
}>()
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'app.update.modal-header',
defaultMessage: 'An update is available!',
defaultMessage: 'Update available - ',
},
copiedError: {
id: 'app.update.copied-error',
@ -131,6 +127,10 @@ const messages = defineMessages({
id: 'app.update.try-again',
defaultMessage: 'Try again',
},
hide: {
id: 'app.update.hide',
defaultMessage: 'Hide update reminder',
},
})
type UpdateData = {
@ -146,7 +146,7 @@ const update = ref<UpdateData>()
const updateSize = ref<number>()
const updatingImmediately = ref(false)
const downloadInProgress = ref(true)
const downloadInProgress = ref(false)
const downloadProgress = ref(0)
const copiedError = ref(false)
const downloadError = ref<Error | null>(null)
@ -167,6 +167,15 @@ const installActions = computed<JoinedButtonAction[]>(() => [
icon: RedoIcon,
action: updateAtNextExit,
},
{
id: 'hide',
label: formatMessage(messages.hide),
action: () => {
hide()
emit('modalHidden')
},
icon: XIcon,
},
])
const downloadedBytes = computed(() => {

View File

@ -11,6 +11,10 @@ const props = defineProps({
type: String,
default: null,
},
hideHeader: {
type: Boolean,
default: false,
},
closable: {
type: Boolean,
default: true,
@ -53,6 +57,7 @@ function onModalHide() {
:header="header"
:noblur="!themeStore.advancedRendering"
:closable="closable"
:hide-header="hideHeader"
@hide="onModalHide"
>
<template #title>

View File

@ -22,6 +22,7 @@
<div class="modal-body flex flex-col bg-bg-raised rounded-2xl">
<div
data-tauri-drag-region
v-if="!hideHeader"
class="grid grid-cols-[auto_min-content] items-center gap-12 p-6 border-solid border-0 border-b-[1px] border-divider max-w-full"
>
<div class="flex text-wrap break-words items-center gap-3 min-w-0">
@ -60,6 +61,7 @@ const props = withDefaults(
closeOnClickOutside?: boolean
warnOnClose?: boolean
header?: string
hideHeader?: boolean
onHide?: () => void
onShow?: () => void
}>(),
@ -71,6 +73,7 @@ const props = withDefaults(
closeOnEsc: true,
warnOnClose: false,
header: undefined,
hideHeader: false,
onHide: () => {},
onShow: () => {},
},
@ -134,7 +137,7 @@ function updateMousePosition(event: { clientX: number; clientY: number }) {
}
function handleKeyDown(event: KeyboardEvent) {
if (props.closeOnEsc && event.key === 'Escape') {
if (props.closeOnEsc && event.key === 'Escape' && props.closable) {
hide()
mouseX.value = window.innerWidth / 2
mouseY.value = window.innerHeight / 2