You've already forked AstralRinth
forked from didirus/AstralRinth
This reverts commit b11934054d.
This commit is contained in:
@@ -13,23 +13,14 @@ import {
|
||||
TrashIcon,
|
||||
XIcon,
|
||||
} from '@modrinth/assets'
|
||||
import {
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
injectNotificationManager,
|
||||
OverflowMenu,
|
||||
ProgressBar,
|
||||
} from '@modrinth/ui'
|
||||
import { ButtonStyled, commonMessages, OverflowMenu, ProgressBar } from '@modrinth/ui'
|
||||
import type { Backup } from '@modrinth/utils'
|
||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||
import dayjs from 'dayjs'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const flags = useFeatureFlags()
|
||||
const { formatMessage } = useVIntl()
|
||||
const { addNotification } = injectNotificationManager()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'download' | 'rename' | 'restore' | 'lock' | 'retry'): void
|
||||
@@ -42,13 +33,11 @@ const props = withDefaults(
|
||||
preview?: boolean
|
||||
kyrosUrl?: string
|
||||
jwt?: string
|
||||
server?: ModrinthServer
|
||||
}>(),
|
||||
{
|
||||
preview: false,
|
||||
kyrosUrl: undefined,
|
||||
jwt: undefined,
|
||||
server: undefined,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -135,48 +124,7 @@ const messages = defineMessages({
|
||||
id: 'servers.backups.item.retry',
|
||||
defaultMessage: 'Retry',
|
||||
},
|
||||
downloadingBackup: {
|
||||
id: 'servers.backups.item.downloading-backup',
|
||||
defaultMessage: 'Downloading backup...',
|
||||
},
|
||||
downloading: {
|
||||
id: 'servers.backups.item.downloading',
|
||||
defaultMessage: 'Downloading',
|
||||
},
|
||||
})
|
||||
|
||||
const downloadingState = ref<{ progress: number; state: string } | undefined>(undefined)
|
||||
|
||||
const downloading = computed(() => downloadingState.value)
|
||||
|
||||
const handleDownload = async () => {
|
||||
if (!props.server?.backups || downloading.value) {
|
||||
return
|
||||
}
|
||||
|
||||
downloadingState.value = { progress: 0, state: 'ongoing' }
|
||||
|
||||
try {
|
||||
const download = props.server.backups.downloadBackup(props.backup.id, props.backup.name)
|
||||
|
||||
download.onProgress((p) => {
|
||||
downloadingState.value = { progress: p.progress, state: 'ongoing' }
|
||||
})
|
||||
|
||||
await download.promise
|
||||
|
||||
emit('download')
|
||||
} catch (error) {
|
||||
console.error('Failed to download backup:', error)
|
||||
addNotification({
|
||||
type: 'error',
|
||||
title: 'Download failed',
|
||||
text: error instanceof Error ? error.message : 'Failed to download backup',
|
||||
})
|
||||
} finally {
|
||||
downloadingState.value = undefined
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
@@ -244,15 +192,6 @@ const handleDownload = async () => {
|
||||
class="max-w-full"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="downloading" class="col-span-2 flex flex-col gap-3 text-blue">
|
||||
{{ formatMessage(messages.downloadingBackup) }}
|
||||
<ProgressBar
|
||||
:progress="downloading.progress >= 0 ? downloading.progress : 0"
|
||||
color="blue"
|
||||
:waiting="downloading.progress <= 0"
|
||||
class="max-w-full"
|
||||
/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<div class="col-span-2">
|
||||
{{ dayjs(backup.created_at).format('MMMM D, YYYY [at] h:mm A') }}
|
||||
@@ -284,32 +223,34 @@ const handleDownload = async () => {
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<template v-else>
|
||||
<ButtonStyled v-show="!downloading">
|
||||
<button :disabled="!server?.backups" @click="handleDownload">
|
||||
<ButtonStyled>
|
||||
<a
|
||||
:class="{
|
||||
disabled: !kyrosUrl || !jwt,
|
||||
}"
|
||||
:href="`https://${kyrosUrl}/modrinth/v0/backups/${backup.id}/download?auth=${jwt}`"
|
||||
@click="() => emit('download')"
|
||||
>
|
||||
<DownloadIcon />
|
||||
{{ formatMessage(commonMessages.downloadButton) }}
|
||||
</button>
|
||||
</a>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled circular type="transparent">
|
||||
<OverflowMenu
|
||||
:options="[
|
||||
{
|
||||
id: 'rename',
|
||||
action: () => emit('rename'),
|
||||
disabled: !!restoring || !!downloading,
|
||||
},
|
||||
{ id: 'rename', action: () => emit('rename') },
|
||||
{
|
||||
id: 'restore',
|
||||
action: () => emit('restore'),
|
||||
disabled: !!restoring || !!downloading,
|
||||
disabled: !!restoring,
|
||||
},
|
||||
{ id: 'lock', action: () => emit('lock'), disabled: !!restoring || !!downloading },
|
||||
{ id: 'lock', action: () => emit('lock') },
|
||||
{ divider: true },
|
||||
{
|
||||
id: 'delete',
|
||||
color: 'red',
|
||||
action: () => emit('delete'),
|
||||
disabled: !!restoring || !!downloading,
|
||||
disabled: !!restoring,
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
||||
@@ -106,87 +106,4 @@ export class BackupsModule extends ServerModule {
|
||||
async getAutoBackup(): Promise<AutoBackupSettings> {
|
||||
return await useServersFetch(`servers/${this.serverId}/autobackup`)
|
||||
}
|
||||
|
||||
downloadBackup(
|
||||
backupId: string,
|
||||
backupName: string,
|
||||
): {
|
||||
promise: Promise<void>
|
||||
onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => void
|
||||
cancel: () => void
|
||||
} {
|
||||
const progressSubject = new EventTarget()
|
||||
const abortController = new AbortController()
|
||||
|
||||
const downloadPromise = new Promise<void>((resolve, reject) => {
|
||||
const auth = this.server.general?.node
|
||||
if (!auth?.instance || !auth?.token) {
|
||||
reject(new Error('Missing authentication credentials'))
|
||||
return
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest()
|
||||
|
||||
xhr.addEventListener('progress', (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const progress = e.loaded / e.total
|
||||
progressSubject.dispatchEvent(
|
||||
new CustomEvent('progress', {
|
||||
detail: { loaded: e.loaded, total: e.total, progress },
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
// progress = -1 to indicate indeterminate size
|
||||
progressSubject.dispatchEvent(
|
||||
new CustomEvent('progress', {
|
||||
detail: { loaded: e.loaded, total: 0, progress: -1 },
|
||||
}),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
xhr.onload = () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
const blob = xhr.response
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = `${backupName}.zip`
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
window.URL.revokeObjectURL(url)
|
||||
resolve()
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
} else {
|
||||
reject(new Error(`Download failed with status ${xhr.status}`))
|
||||
}
|
||||
}
|
||||
|
||||
xhr.onerror = () => reject(new Error('Download failed'))
|
||||
xhr.onabort = () => reject(new Error('Download cancelled'))
|
||||
|
||||
xhr.open(
|
||||
'GET',
|
||||
`https://${auth.instance}/modrinth/v0/backups/${backupId}/download?auth=${auth.token}`,
|
||||
)
|
||||
xhr.responseType = 'blob'
|
||||
xhr.send()
|
||||
|
||||
abortController.signal.addEventListener('abort', () => xhr.abort())
|
||||
})
|
||||
|
||||
return {
|
||||
promise: downloadPromise,
|
||||
onProgress: (cb: (p: { loaded: number; total: number; progress: number }) => void) => {
|
||||
progressSubject.addEventListener('progress', ((e: CustomEvent) => {
|
||||
cb(e.detail)
|
||||
}) as EventListener)
|
||||
},
|
||||
cancel: () => abortController.abort(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2570,12 +2570,6 @@
|
||||
"servers.backups.item.creating-backup": {
|
||||
"message": "Creating backup..."
|
||||
},
|
||||
"servers.backups.item.downloading": {
|
||||
"message": "Downloading"
|
||||
},
|
||||
"servers.backups.item.downloading-backup": {
|
||||
"message": "Downloading backup..."
|
||||
},
|
||||
"servers.backups.item.failed-to-create-backup": {
|
||||
"message": "Failed to create backup"
|
||||
},
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
v-for="backup in backups"
|
||||
:key="`backup-${backup.id}`"
|
||||
:backup="backup"
|
||||
:server="props.server"
|
||||
:kyros-url="props.server.general?.node.instance"
|
||||
:jwt="props.server.general?.node.token"
|
||||
@download="() => triggerDownloadAnimation()"
|
||||
|
||||
Reference in New Issue
Block a user