Compress answers and show upload progress
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { createImageURL } from '#shared/utils/image';
|
||||
import { compressImage, createImageURL } from '#shared/utils/image';
|
||||
import ClickableImage from '~/components/ClickableImage.vue';
|
||||
import MultilineString from '~/components/MultilineString.vue';
|
||||
import { useI18nKey } from '~/composables/useI18nKey';
|
||||
@@ -55,11 +55,24 @@ const textType = {
|
||||
|
||||
const newImage = ref<File>();
|
||||
|
||||
const newImageURL = computed(() =>
|
||||
newImage.value ? createImageURL(newImage.value) : undefined
|
||||
);
|
||||
|
||||
const uploading = ref(false);
|
||||
const uploadingImage = ref(false);
|
||||
const compressing = ref(false);
|
||||
const uploadProgress = ref(1);
|
||||
const submitError = ref('');
|
||||
useEventListener(window, 'beforeunload', (ev) => {
|
||||
if (uploading.value) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
async function submit() {
|
||||
uploading.value = true;
|
||||
submitError.value = '';
|
||||
uploadProgress.value = 0;
|
||||
|
||||
const body = new FormData();
|
||||
body.set('lang', locale.value);
|
||||
@@ -74,27 +87,38 @@ async function submit() {
|
||||
body.set('final', 'true');
|
||||
}
|
||||
if (newImage.value) {
|
||||
body.set('image', newImage.value);
|
||||
uploadingImage.value = true;
|
||||
compressing.value = true;
|
||||
const compressedImage = await compressImage(newImage.value);
|
||||
compressing.value = false;
|
||||
body.set('image', compressedImage);
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
try {
|
||||
await $fetch(`/api/quest/${questSlug?.id}/submit`, {
|
||||
method: 'POST',
|
||||
body
|
||||
await new Promise((resolve) => {
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
uploadProgress.value = event.loaded / event.total;
|
||||
}
|
||||
});
|
||||
xhr.addEventListener('loadend', () => {
|
||||
resolve(xhr.readyState === 4 && xhr.status === 200);
|
||||
uploadProgress.value = 1;
|
||||
});
|
||||
xhr.open('POST', `/api/quest/${questSlug?.id}/submit`, true);
|
||||
xhr.withCredentials = true;
|
||||
xhr.send(body);
|
||||
});
|
||||
|
||||
await refresh();
|
||||
answer.value = data.value?.answer?.text;
|
||||
newImage.value = undefined;
|
||||
} catch (e) {
|
||||
if (e instanceof Error && 'statusCode' in e && e.statusCode === 418) {
|
||||
if (xhr.status === 418) {
|
||||
submitError.value = t('page.quest.already_finalized');
|
||||
await refresh();
|
||||
} else if (
|
||||
e instanceof Error &&
|
||||
'statusCode' in e &&
|
||||
e.statusCode === 409
|
||||
) {
|
||||
} else if (xhr.status === 409) {
|
||||
submitError.value = t('page.quest.conflict');
|
||||
} else {
|
||||
submitError.value = parseError(e);
|
||||
@@ -102,11 +126,31 @@ async function submit() {
|
||||
}
|
||||
|
||||
uploading.value = false;
|
||||
uploadingImage.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<VaModal
|
||||
:model-value="uploadingImage"
|
||||
no-outside-dismiss
|
||||
hide-default-actions
|
||||
no-dismiss
|
||||
>
|
||||
<h2 class="text-2xl font-bold">{{ t('page.quest.upload_title') }}</h2>
|
||||
<p v-if="compressing" class="text-lg">
|
||||
{{ t('page.quest.upload_compress') }}
|
||||
</p>
|
||||
<VaProgressCircle
|
||||
v-else
|
||||
class="mx-auto"
|
||||
:model-value="uploadProgress * 100"
|
||||
size="50dvw"
|
||||
>
|
||||
{{ (uploadProgress * 100).toFixed(0) + '%' }}
|
||||
</VaProgressCircle>
|
||||
</VaModal>
|
||||
<VaButtonGroup>
|
||||
<VaButton
|
||||
icon="arrow_back"
|
||||
@@ -230,8 +274,8 @@ async function submit() {
|
||||
</VaInput>
|
||||
|
||||
<VaImage
|
||||
v-if="newImage"
|
||||
:src="createImageURL(newImage)"
|
||||
v-if="newImageURL"
|
||||
:src="newImageURL"
|
||||
class="max-h-60 w-full"
|
||||
fit="contain"
|
||||
lazy
|
||||
@@ -279,7 +323,7 @@ async function submit() {
|
||||
newImage ||
|
||||
data.answer?.text !== answer ||
|
||||
data.answer?.final !== final
|
||||
)
|
||||
) || uploading
|
||||
"
|
||||
:loading="uploading"
|
||||
@click="submit"
|
||||
|
||||
Reference in New Issue
Block a user