diff --git a/apps/app-frontend/src/components/ui/UpdateModal.vue b/apps/app-frontend/src/components/ui/UpdateModal.vue
index 0372d351c..6eb7787bf 100644
--- a/apps/app-frontend/src/components/ui/UpdateModal.vue
+++ b/apps/app-frontend/src/components/ui/UpdateModal.vue
@@ -7,6 +7,7 @@
>
{{ formatMessage(messages.downloadSize, { size: formatBytes(updateSize) }) }}
+
+
+ {{ formatMessage(messages.downloadError) }}
+
+
+
+
+
()
const updatingImmediately = ref(false)
const downloadInProgress = ref(false)
const downloadProgress = ref(0)
-const downloadError = ref(false)
+const copiedError = ref(false)
+const downloadError = ref(null)
const enqueuedUpdate = ref(null)
@@ -185,6 +216,29 @@ function hide() {
defineExpose({ show, hide, isOpen })
+async function copyError() {
+ if (downloadError.value) {
+ copiedError.value = true
+ const errorData = {
+ message: downloadError.value.message,
+ stack: downloadError.value.stack,
+ name: downloadError.value.name,
+ timestamp: new Date().toISOString(),
+ updateVersion: update.value?.version,
+ }
+
+ setTimeout(() => {
+ copiedError.value = false
+ }, 3000)
+
+ try {
+ await navigator.clipboard.writeText(JSON.stringify(errorData, null, 2))
+ } catch (e) {
+ console.error('Failed to copy error to clipboard:', e)
+ }
+ }
+}
+
// TODO: Migrate to common events.ts helper when events/listeners are refactored
interface LoadingListenerEvent {
event: {
@@ -222,7 +276,7 @@ function updateAtNextExit() {
}
async function downloadUpdate() {
- downloadError.value = false
+ downloadError.value = null
downloadProgress.value = 0
const versionToDownload = update.value!.version
@@ -232,7 +286,7 @@ async function downloadUpdate() {
await enqueueUpdateForInstallation(update.value!.rid)
} catch (e) {
downloadInProgress.value = false
- downloadError.value = true
+ downloadError.value = e instanceof Error ? e : new Error(String(e))
handleError(e)