From 3f0b234cc4c61f8361eab8bd0dd112c55f63d723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Thu, 4 Apr 2024 12:28:18 +0200 Subject: [PATCH] feat(ui): add max. file size check before upload attachment (#2709) Co-authored-by: TAKAHASHI Shuuji --- composables/i18n.ts | 29 +++++++++++++++++++++++++++++ composables/masto/publish.ts | 25 +++++++++++++++++++++++++ locales/en.json | 4 ++++ locales/es-419.json | 3 +++ locales/es.json | 6 +++++- 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/composables/i18n.ts b/composables/i18n.ts index 1d612266..ecd76550 100644 --- a/composables/i18n.ts +++ b/composables/i18n.ts @@ -77,3 +77,32 @@ export function useTimeAgoOptions(short = false): UseTimeAgoOptions { }, } } + +export function useFileSizeFormatter() { + const { locale } = useI18n() + + const formatters = computed(() => ([ + Intl.NumberFormat(locale.value, { + style: 'unit', + unit: 'megabyte', + unitDisplay: 'narrow', + maximumFractionDigits: 0, + }), + Intl.NumberFormat(locale.value, { + style: 'unit', + unit: 'kilobyte', + unitDisplay: 'narrow', + maximumFractionDigits: 0, + }), + ])) + + const megaByte = 1024 * 1024 + + function formatFileSize(size: number) { + return size >= megaByte + ? formatters.value[0].format(size / megaByte) + : formatters.value[1].format(size / 1024) + } + + return { formatFileSize } +} diff --git a/composables/masto/publish.ts b/composables/masto/publish.ts index ae1f6020..31c2218b 100644 --- a/composables/masto/publish.ts +++ b/composables/masto/publish.ts @@ -155,6 +155,7 @@ export type MediaAttachmentUploadError = [filename: string, message: string] export function useUploadMediaAttachment(draft: Ref) { const { client } = useMasto() const { t } = useI18n() + const { formatFileSize } = useFileSizeFormatter() const isUploading = ref(false) const isExceedingAttachmentLimit = ref(false) @@ -224,8 +225,32 @@ export function useUploadMediaAttachment(draft: Ref) { // TODO: display some kind of message if too many media are selected // DONE const limit = currentInstance.value!.configuration?.statuses.maxMediaAttachments || 4 + const maxVideoSize = currentInstance.value!.configuration?.mediaAttachments.videoSizeLimit || 0 + const maxImageSize = currentInstance.value!.configuration?.mediaAttachments.imageSizeLimit || 0 for (const file of files.slice(0, limit)) { if (draft.value.attachments.length < limit) { + if (file.type.startsWith('image/')) { + if (maxImageSize > 0 && file.size > maxImageSize) { + failedAttachments.value = [...failedAttachments.value, [file.name, t('state.attachments_limit_image_error', [formatFileSize(maxImageSize)])]] + continue + } + } + else { + if (maxVideoSize > 0 && file.size > maxVideoSize) { + const key + = file.type.startsWith('audio/') + ? 'state.attachments_limit_audio_error' + : file.type.startsWith('video/') + ? 'state.attachments_limit_video_error' + : 'state.attachments_limit_unknown_error' + const errorMessage = t(key, [formatFileSize(maxVideoSize)]) + failedAttachments.value = [ + ...failedAttachments.value, + [file.name, errorMessage], + ] + continue + } + } isExceedingAttachmentLimit.value = false try { const attachment = await client.value.v1.media.create({ diff --git a/locales/en.json b/locales/en.json index 74e124a4..645eab0c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -594,7 +594,11 @@ }, "state": { "attachments_exceed_server_limit": "The number of attachments exceeded the limit per post.", + "attachments_limit_audio_error": "Maximum audio size exceeded: {0}", "attachments_limit_error": "Limit per post exceeded", + "attachments_limit_image_error": "Maximum image size exceeded: {0}", + "attachments_limit_unknown_error": "Maximum file size exceeded: {0}", + "attachments_limit_video_error": "Maximum video size exceeded: {0}", "edited": "(Edited)", "editing": "Editing", "loading": "Loading...", diff --git a/locales/es-419.json b/locales/es-419.json index 51b8ce24..ee90c93c 100644 --- a/locales/es-419.json +++ b/locales/es-419.json @@ -184,6 +184,9 @@ "label": "Usuarios en línea" } }, + "state": { + "attachments_limit_video_error": "Tamaño máximo de video excedido: {0}" + }, "status": { "spoiler_show_less": "Menos" }, diff --git a/locales/es.json b/locales/es.json index 810d8842..90e74ba1 100644 --- a/locales/es.json +++ b/locales/es.json @@ -591,7 +591,11 @@ }, "state": { "attachments_exceed_server_limit": "Número máximo de archivos adjuntos por publicación excedido.", + "attachments_limit_audio_error": "Tamaño máximo de audio excedido: {0}", "attachments_limit_error": "Límite por publicación excedido", + "attachments_limit_image_error": "Tamaño máximo de imagen excedido: {0}", + "attachments_limit_unknown_error": "Tamaño máximo de archivo excedido: {0}", + "attachments_limit_video_error": "Tamaño máximo de vídeo excedido: {0}", "edited": "(Editado)", "editing": "Editando", "loading": "Cargando...", @@ -708,7 +712,7 @@ "tooltip": { "add_content_warning": "Añadir advertencia de contenido", "add_emojis": "Agregar emojis", - "add_media": "Añadir imágenes, video o audio", + "add_media": "Añadir imágenes, vídeo o audio", "add_publishable_content": "Publicar contenido", "change_content_visibility": "Cambiar visibilidad de contenido", "change_language": "Cambiar idioma",