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> <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 { RouterView, useRoute, useRouter } from 'vue-router'
import { import {
ArrowBigUpDashIcon, ArrowBigUpDashIcon,
@ -72,6 +81,7 @@ import UpdateModal from '@/components/ui/UpdateModal.vue'
import { get_available_capes, get_available_skins } from './helpers/skins' import { get_available_capes, get_available_skins } from './helpers/skins'
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer' import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
import { defineMessages, useVIntl } from '@vintl/vintl' import { defineMessages, useVIntl } from '@vintl/vintl'
import { createTooltip, destroyTooltip } from 'floating-vue'
const themeStore = useTheming() const themeStore = useTheming()
@ -450,6 +460,20 @@ async function forceOpenUpdateModal() {
updateModal.value.show(availableUpdate.value) 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) { function handleClick(e) {
let target = e.target let target = e.target
while (target != null) { while (target != null) {
@ -495,6 +519,7 @@ function handleAuxClick(e) {
ref="updateModal" ref="updateModal"
@update-skipped="skipUpdate" @update-skipped="skipUpdate"
@update-enqueued-for-later="updateEnqueuedForLater" @update-enqueued-for-later="updateEnqueuedForLater"
@modal-hidden="showUpdateButtonTooltip"
/> />
</Suspense> </Suspense>
<Suspense> <Suspense>
@ -549,6 +574,7 @@ function handleAuxClick(e) {
<div class="flex flex-grow"></div> <div class="flex flex-grow"></div>
<NavButton <NavButton
v-if="!!availableUpdate" v-if="!!availableUpdate"
ref="updateButton"
v-tooltip.right=" v-tooltip.right="
enqueuedUpdate === availableUpdate?.version enqueuedUpdate === availableUpdate?.version
? 'Update installation queued for next restart' ? 'Update installation queued for next restart'

View File

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

View File

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

View File

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