analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
254 lines (245 loc) • 9.14 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var _chunkKTHF7N26js = require('./chunk-KTHF7N26.js');
var _chunkBVUPM6EYjs = require('./chunk-BVUPM6EY.js');
var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js');
// src/components/DownloadButton/DownloadButton.tsx
var _react = require('react');
var _DownloadSimple = require('@phosphor-icons/react/dist/csr/DownloadSimple');
var _jsxruntime = require('react/jsx-runtime');
var supportsDirectoryPicker = () => typeof globalThis.showDirectoryPicker === "function";
var getFileExtension = (url) => {
try {
const u = new URL(url, _optionalChain([globalThis, 'access', _ => _.location, 'optionalAccess', _2 => _2.origin]) || "http://localhost");
url = u.pathname;
} catch (e) {
}
const path = url.split(/[?#]/)[0];
const dot = path.lastIndexOf(".");
return dot > -1 ? path.slice(dot + 1).toLowerCase() : "file";
};
var slugifyTitle = (lessonTitle) => lessonTitle.toLowerCase().replaceAll(/[^a-z0-9\s]/g, "").replaceAll(/\s+/g, "-").substring(0, 50);
var generateFilename = (contentType, url, lessonTitle = "aula") => `${slugifyTitle(lessonTitle)}-${contentType}.${getFileExtension(url)}`;
var getRemoteFileSize = async (url) => {
try {
const response = await fetch(url, { method: "HEAD", mode: "cors" });
if (!response.ok) return 0;
return Number(response.headers.get("content-length")) || 0;
} catch (e2) {
return 0;
}
};
var streamToDisk = async (url, dirHandle, filename, onBytes) => {
const response = await fetch(url, { mode: "cors" });
if (!response.ok) {
throw new Error(
`Failed to fetch file: ${response.status} ${response.statusText}`
);
}
if (!response.body) {
throw new Error("Response has no readable body");
}
const fileHandle = await dirHandle.getFileHandle(filename, { create: true });
const writable = await fileHandle.createWritable();
try {
const reader = response.body.getReader();
for (; ; ) {
const { done, value } = await reader.read();
if (done) break;
await writable.write(value);
onBytes(value.length);
}
await writable.close();
} catch (error) {
await _optionalChain([writable, 'access', _3 => _3.abort, 'optionalCall', _4 => _4()]);
throw error;
}
};
var triggerBrowserDownload = (url, filename) => {
const link = document.createElement("a");
link.href = url;
link.download = filename;
link.rel = "noopener noreferrer";
document.body.appendChild(link);
link.click();
link.remove();
};
var DownloadButton = ({
content,
className,
onDownloadStart,
onDownloadComplete,
onDownloadError,
lessonTitle = "aula",
disabled = false
}) => {
const [isDownloading, setIsDownloading] = _react.useState.call(void 0, false);
const [progress, setProgress] = _react.useState.call(void 0, 0);
const isValidUrl = _react.useCallback.call(void 0, (url) => {
return Boolean(
url && url.trim() !== "" && url !== "undefined" && url !== "null"
);
}, []);
const getAvailableContent = _react.useCallback.call(void 0, () => {
const downloads = [];
if (isValidUrl(content.urlVideo)) {
downloads.push({ type: "video", url: content.urlVideo, label: "V\xEDdeo" });
}
if (isValidUrl(content.urlPodcast)) {
downloads.push({
type: "podcast",
url: content.urlPodcast,
label: "Podcast"
});
}
if (isValidUrl(content.urlInitialFrame)) {
downloads.push({
type: "quadro-inicial",
url: content.urlInitialFrame,
label: "Quadro Inicial"
});
}
if (isValidUrl(content.urlFinalFrame)) {
downloads.push({
type: "quadro-final",
url: content.urlFinalFrame,
label: "Quadro Final"
});
}
return downloads;
}, [content, isValidUrl]);
const downloadToFolder = _react.useCallback.call(void 0,
async (items, dirHandle) => {
const sizes = await Promise.all(
items.map((item) => getRemoteFileSize(item.url))
);
const totalBytes = sizes.reduce((sum, size) => sum + size, 0);
const weighByFile = totalBytes === 0;
let downloadedBytes = 0;
let succeeded = 0;
for (const [index, item] of items.entries()) {
try {
_optionalChain([onDownloadStart, 'optionalCall', _5 => _5(item.type)]);
await streamToDisk(
item.url,
dirHandle,
generateFilename(item.type, item.url, lessonTitle),
(chunkSize) => {
downloadedBytes += chunkSize;
if (!weighByFile) {
setProgress(
Math.min(99, Math.round(downloadedBytes / totalBytes * 100))
);
}
}
);
succeeded++;
_optionalChain([onDownloadComplete, 'optionalCall', _6 => _6(item.type)]);
} catch (error) {
_optionalChain([onDownloadError, 'optionalCall', _7 => _7(
item.type,
error instanceof Error ? error : new Error(`Falha ao baixar ${item.label}`)
)]);
} finally {
if (weighByFile) {
setProgress(
Math.min(99, Math.round((index + 1) / items.length * 100))
);
}
}
}
if (succeeded === 0) {
throw new Error("Nenhum conte\xFAdo da aula p\xF4de ser baixado");
}
setProgress(100);
},
[lessonTitle, onDownloadStart, onDownloadComplete, onDownloadError]
);
const downloadViaBrowser = _react.useCallback.call(void 0,
async (items) => {
for (const [index, item] of items.entries()) {
_optionalChain([onDownloadStart, 'optionalCall', _8 => _8(item.type)]);
triggerBrowserDownload(
item.url,
generateFilename(item.type, item.url, lessonTitle)
);
_optionalChain([onDownloadComplete, 'optionalCall', _9 => _9(item.type)]);
setProgress(Math.round((index + 1) / items.length * 100));
if (index < items.length - 1) {
await new Promise((resolve) => setTimeout(resolve, 800));
}
}
},
[lessonTitle, onDownloadStart, onDownloadComplete]
);
const handleDownload = _react.useCallback.call(void 0, async () => {
if (disabled || isDownloading) return;
const availableContent = getAvailableContent();
if (availableContent.length === 0) return;
let dirHandle = null;
if (supportsDirectoryPicker()) {
try {
const picker = globalThis.showDirectoryPicker;
dirHandle = await picker({ mode: "readwrite", id: "aulas" });
} catch (e3) {
return;
}
}
setIsDownloading(true);
setProgress(0);
try {
if (dirHandle) {
await downloadToFolder(availableContent, dirHandle);
} else {
await downloadViaBrowser(availableContent);
}
} catch (error) {
_optionalChain([onDownloadError, 'optionalCall', _10 => _10(
"aula",
error instanceof Error ? error : new Error("Falha ao baixar o conte\xFAdo da aula")
)]);
} finally {
setIsDownloading(false);
setProgress(0);
}
}, [
disabled,
isDownloading,
getAvailableContent,
downloadToFolder,
downloadViaBrowser,
onDownloadError
]);
const availableCount = getAvailableContent().length;
if (availableCount === 0) {
return null;
}
const suffix = availableCount > 1 ? "s" : "";
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "flex items-center", className), children: [
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
_chunkBVUPM6EYjs.IconButton_default,
{
icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _DownloadSimple.DownloadSimpleIcon, { size: 24 }),
onClick: handleDownload,
disabled: disabled || isDownloading,
"aria-label": isDownloading ? "Baixando conte\xFAdo..." : `Baixar conte\xFAdo da aula (${availableCount} arquivo${suffix})`,
className: _chunkTN3AYOMVjs.cn.call(void 0,
"!bg-transparent hover:!bg-black/10 transition-colors",
isDownloading && "opacity-60 cursor-not-allowed"
)
}
),
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
_chunkKTHF7N26js.ProgressModal_default,
{
isOpen: isDownloading,
onClose: () => {
},
message: "Baixando conte\xFAdo da aula...",
progress
}
)
] });
};
var DownloadButton_default = DownloadButton;
exports.DownloadButton_default = DownloadButton_default;
//# sourceMappingURL=chunk-7CYRHMOF.js.map