fix(ui): replace native confirm() dialogs with the global in-app modal

window.confirm blocks the JS event loop, which froze companion remote
input while open — the remote user could raise the mesh "Clear" prompt
(or reboot / backup-delete / uninstall confirms) and then never dismiss
it, because the synthetic events that would dismiss it queue behind the
dialog itself.

New promise-based appConfirm() (useAppConfirm.ts) + one AppConfirmModal
mounted globally in App.vue, built on BaseModal (Teleport-to-body,
full-viewport backdrop, glass card — the canonical modal contract). All
six native confirm() call sites migrated: mesh clear-all, mesh message
delete, dashboard reboot, backup delete, backup USB copy, app uninstall.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-16 05:28:53 -04:00
co-authored by Claude Fable 5
parent 458444d700
commit 876ecc4bdf
7 changed files with 124 additions and 7 deletions
+7 -1
View File
@@ -125,6 +125,7 @@ import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { useContainerStore } from '@/stores/container'
import { appConfirm } from '@/composables/useAppConfirm'
import { type ContainerStatus as ContainerStatusData } from '@/api/container-client'
import ContainerStatus from '@/components/ContainerStatus.vue'
import BackButton from '@/components/BackButton.vue'
@@ -325,7 +326,12 @@ onUnmounted(() => {
})
async function handleRemove() {
if (!confirm(t('apps.uninstallConfirm', { name: appName.value }))) {
const ok = await appConfirm({
message: t('apps.uninstallConfirm', { name: appName.value }),
confirmLabel: t('apps.uninstallTitle'),
danger: true,
})
if (!ok) {
return
}