UNPKG

@nextcloud/vue

Version:
270 lines (269 loc) 12.2 kB
import '../assets/NcUploadPicker.css'; import { defineComponent, useTemplateRef, onBeforeMount, onUnmounted, watch, ref, computed, openBlock, createBlock, unref, withCtx, withDirectives, createElementVNode, normalizeClass, createVNode, createElementBlock, toDisplayString, createTextVNode, createCommentVNode, vShow } from "vue"; import { b as mdiClose, C as mdiPlus } from "./mdi.mjs"; import { openConflictPicker } from "@nextcloud/dialogs"; import { getUniqueName } from "@nextcloud/files"; import { getUploader, UploaderStatus, UploadStatus } from "@nextcloud/files/upload"; import { N as NcButton } from "./NcButton.mjs"; import { N as NcFilePicker } from "./NcFilePicker.mjs"; import { N as NcIconSvgWrapper } from "./NcIconSvgWrapper.mjs"; import { N as NcProgressBar } from "./NcProgressBar.mjs"; import { useFormatRelativeTime } from "../composables/useFormatDateTime/index.mjs"; import "../composables/useHotKey/index.mjs"; import "../composables/useIsDarkTheme/index.mjs"; import "../composables/useIsFullscreen/index.mjs"; import "../composables/useIsMobile/index.mjs"; import { r as register, E as t10, a as t } from "./_l10n.mjs"; import { c as createElementId } from "./createElementId.mjs"; import { l as logger } from "./logger.mjs"; import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs"; function basename(path, extname2) { path = path.replace(/\\/g, "/").replace(/\/+$/g, "").replace(/.*\//, ""); return path; } register(t10); const _hoisted_1 = ["id"]; const _hoisted_2 = { key: 0 }; const _hoisted_3 = { key: 1 }; const _hoisted_4 = ["title"]; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "NcUploadPicker", props: { actions: { default: () => [] }, destination: {}, content: {}, accept: { default: () => [] }, disabled: { type: Boolean }, label: { default: () => t("New") }, multiple: { type: Boolean }, iconOnly: { type: Boolean }, variant: { default: "secondary" }, directory: { type: Boolean } }, emits: ["upload:started", "upload:finished", "paused", "resumed", "finished"], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emit = __emit; __expose({ reset }); const filePickerElement = useTemplateRef("filePicker"); const progressTimeId = createElementId(); const uploadManager = getUploader(); onBeforeMount(() => { window.addEventListener("beforeunload", onBeforePageUnload); uploadManager.addEventListener("uploadFinished", onUploadFinished); uploadManager.addEventListener("uploadStarted", onUploadStarted); uploadManager.addEventListener("uploadProgress", updateEta); uploadManager.addEventListener("finished", onUploaderFinished); uploadManager.addEventListener("paused", onUploaderPaused); uploadManager.addEventListener("reset", updateUploadStatus); uploadManager.addEventListener("resumed", onUploaderResumed); updateUploadStatus(); }); onUnmounted(() => { window.removeEventListener("beforeunload", onBeforePageUnload); uploadManager.removeEventListener("uploadFinished", onUploadFinished); uploadManager.removeEventListener("uploadStarted", onUploadStarted); uploadManager.removeEventListener("uploadProgress", updateEta); uploadManager.removeEventListener("finished", onUploaderFinished); uploadManager.removeEventListener("paused", onUploaderPaused); uploadManager.removeEventListener("reset", updateUploadStatus); uploadManager.removeEventListener("resumed", onUploaderResumed); }); watch(() => props.destination, () => setDestination(props.destination), { immediate: true }); const isPaused = ref(uploadManager.status === UploaderStatus.PAUSED); function onUploaderPaused() { updateUploadStatus(); emit("paused", [...uploadManager.queue]); } function onUploaderResumed() { updateUploadStatus(); emit("resumed", [...uploadManager.queue]); } const hasFailure = ref(false); const isUploading = ref(false); const isAssembling = ref(false); const isOnlyAssembling = ref(false); function updateUploadStatus() { isPaused.value = uploadManager.status === UploaderStatus.PAUSED; isUploading.value = uploadManager.status === UploaderStatus.UPLOADING || isPaused.value && uploadManager.queue.length > 0; hasFailure.value = uploadManager.queue.some((upload) => upload.status === UploadStatus.FAILED); isAssembling.value = uploadManager.queue.some((upload) => upload.status === UploadStatus.ASSEMBLING); isOnlyAssembling.value = isAssembling.value && uploadManager.queue.every((upload) => upload.status >= UploadStatus.ASSEMBLING); } function reset() { filePickerElement.value?.reset(); } function setDestination(destination) { if (!destination) { logger.debug("Invalid destination"); return; } uploadManager.destination = destination; } const etaProgress = ref(0); const etaSpeed = ref(""); const etaRaw = ref(Infinity); const etaTimeRaw = computed(() => etaRaw.value === Infinity ? Infinity : new Date(Date.now() + etaRaw.value)); const etaTimeFormatted = useFormatRelativeTime(etaTimeRaw, { ignoreSeconds: true }); const etaTime = computed(() => etaTimeRaw.value === Infinity ? t("Estimating …") : etaTimeFormatted.value); function updateEta() { etaRaw.value = uploadManager.statistics.eta === Infinity ? Infinity : uploadManager.statistics.eta * 1e3; etaSpeed.value = uploadManager.statistics.speedReadable; etaProgress.value = uploadManager.statistics.progress; } function onUploaderFinished() { updateUploadStatus(); emit("finished"); } function onUploadFinished(event) { updateUploadStatus(); emit("upload:finished", event.detail); } function onUploadStarted(event) { updateUploadStatus(); emit("upload:started", event.detail); } async function onPick(files) { try { await uploadManager.batchUpload("", files, { callback: handleConflicts }); } catch (error) { logger.debug("Error while uploading", { error }); } finally { reset(); } } async function handleConflicts(nodes, currentPath) { try { const content = await props.content(currentPath); const conflicts = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename)); const uploadMapping = Object.fromEntries(nodes.map((name) => [name, name])); if (conflicts.length === 0) { return uploadMapping; } const existingNodes = content.filter((node) => nodes.includes(node.displayname) || nodes.includes(node.basename)); const result = await openConflictPicker(basename(currentPath), conflicts, existingNodes, { recursive: props.directory }); if (result) { const usedNames = content.map((node) => node.basename); for (const node of conflicts) { if (result.skipped.some((skipped) => skipped.basename === node.basename)) { delete uploadMapping[node.basename]; } else if (result.renamed.some((renamed) => renamed.basename === node.basename)) { const newName = getUniqueName(basename(node.basename), usedNames); uploadMapping[node.basename] = newName; usedNames.push(newName); } } return uploadMapping; } } catch (error) { logger.error("Error during conflict resolution - skipping upload", { error }); } return false; } function onCancel() { uploadManager.reset(); reset(); } function onBeforePageUnload(event) { if (uploadManager.queue.length > 0) { event.preventDefault(); event.returnValue = ""; } } return (_ctx, _cache) => { return openBlock(), createBlock(NcFilePicker, { ref: "filePicker", accept: __props.accept, actionCaption: __props.actions.length > 0 || __props.directory ? unref(t)("Upload from device") : void 0, actions: __props.actions, directory: __props.directory, disabled: __props.disabled, iconOnly: __props.iconOnly, label: __props.label, multiple: __props.multiple, variant: __props.variant, onPick }, { icon: withCtx(() => [ createVNode(NcIconSvgWrapper, { path: unref(mdiPlus) }, null, 8, ["path"]) ]), default: withCtx(() => [ withDirectives(createElementVNode("div", { class: normalizeClass([_ctx.$style.uploadPicker_progress, { [_ctx.$style.uploadPicker_progress__uploading]: isUploading.value, [_ctx.$style.uploadPicker_progress__paused]: isPaused.value }]) }, [ createVNode(NcProgressBar, { ariaLabel: unref(t)("Upload progress"), ariaDescribedby: unref(progressTimeId), error: hasFailure.value, value: etaProgress.value, size: "medium" }, null, 8, ["ariaLabel", "ariaDescribedby", "error", "value"]), createElementVNode("p", { id: unref(progressTimeId), class: normalizeClass(_ctx.$style.uploadPicker_progressLabel) }, [ isPaused.value ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString( unref(t)("paused") /* TRANSLATORS: State of the current upload - it is paused */ ), 1)) : isOnlyAssembling.value ? (openBlock(), createElementBlock("span", _hoisted_3, toDisplayString( unref(t)("assembling") /* TRANSLATORS: State of the current upload - chunks of the uploaded files are being assembled into the final file */ ), 1)) : (openBlock(), createElementBlock("span", { key: 2, title: `${etaTime.value} (${etaSpeed.value})` }, [ createTextVNode(toDisplayString(etaTime.value) + " ", 1), etaSpeed.value && etaRaw.value > 31e3 ? (openBlock(), createElementBlock("span", { key: 0, class: normalizeClass(_ctx.$style.uploadPicker_progressLabelSpeed) }, " (" + toDisplayString(etaSpeed.value) + ") ", 3)) : createCommentVNode("", true) ], 8, _hoisted_4)) ], 10, _hoisted_1) ], 2), [ [vShow, isUploading.value] ]), isUploading.value && !isOnlyAssembling.value ? (openBlock(), createBlock(NcButton, { key: 0, class: normalizeClass(_ctx.$style.uploadPicker_cancelButton), "aria-label": unref(t)("Cancel uploads"), variant: "tertiary", onClick: onCancel }, { icon: withCtx(() => [ createVNode(NcIconSvgWrapper, { path: unref(mdiClose) }, null, 8, ["path"]) ]), _: 1 }, 8, ["class", "aria-label"])) : createCommentVNode("", true) ]), _: 1 }, 8, ["accept", "actionCaption", "actions", "directory", "disabled", "iconOnly", "label", "multiple", "variant"]); }; } }); const uploadPicker_progress = "_uploadPicker_progress_LchrN"; const uploadPicker_progress__uploading = "_uploadPicker_progress__uploading_RBQWf"; const uploadPicker_progress__paused = "_uploadPicker_progress__paused_t4TGj"; const breathing = "_breathing_B9q41"; const uploadPicker_progressLabel = "_uploadPicker_progressLabel_iEywW"; const uploadPicker_progressLabelSpeed = "_uploadPicker_progressLabelSpeed_dIEb3"; const style0 = { uploadPicker_progress, uploadPicker_progress__uploading, uploadPicker_progress__paused, breathing, uploadPicker_progressLabel, uploadPicker_progressLabelSpeed }; const cssModules = { "$style": style0 }; const NcUploadPicker = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]); export { NcUploadPicker as N }; //# sourceMappingURL=NcUploadPicker.mjs.map