import * as i18n from './i18n.js'; const { t, initI18n, bindLanguageSelector, onLanguageChange, getCurrentLanguage, setLanguage, } = i18n; const setLanguageGuard = i18n.setLanguageGuard || (() => {}); import { closeIcon, eyeIcon, trashIcon } from './constants.js'; import { ensureAuthenticated, startAuthWatcher, clearAuthUser, } from './auth.js'; ensureAuthenticated(); startAuthWatcher(); const logoutButton = document.getElementById('btn-logout'); if (logoutButton) { logoutButton.addEventListener('click', () => { clearAuthUser(); window.location.href = 'login.html'; }); } const inputElement = document.getElementById('file-input'); const textInputElement = document.getElementById('text-input-additional'); const socialMediaInputElement = document.getElementById('input-social'); const titleInputElement = document.getElementById('input-title'); const locationInputElement = document.getElementById('input-location'); const categoryInputElement = document.getElementById('input-category'); const violenceLevelInputElement = document.getElementById('input-violence'); const outputElement = document.getElementById('output-area'); const btnClear = document.getElementById('btn-clear-face-check'); const btnSubmit = document.getElementById('btn-submit-face-check'); const btnSave = document.getElementById('btn-save-face-check'); const wrapperFilesElement = document.getElementById('wrapper-files-face-check'); const wrapperUploadElement = document.getElementById( 'wrapper-upload-face-check' ); const wrapperModalElement = document.getElementById( 'wrapper-modal-1760410479496' ); const contentModalElement = document.getElementById('model-1760410479496'); const dropZones = document.getElementsByClassName('drop-zone'); const fileRemoves = document.getElementsByClassName('file-remove'); const statusFaceCheckElement = document.getElementById('status-face-check'); const tabMenuElement = document.getElementById('menu-1762855257376'); const tabItems = tabMenuElement.getElementsByClassName('item'); const livechat = document.getElementById('live-chat-1765253515534'); export let output; initI18n(); bindLanguageSelector('#language-select'); const languageApiMap = { en: 'English', ja: 'Japanese', vi: 'Vietnamese', }; const languageLabelMap = { en: () => t('languageEnglish') || 'English', ja: () => t('languageJapanese') || 'Japanese', vi: () => t('languageVietnamese') || 'Vietnamese', }; const languageDropdown = document.getElementById('language-dropdown'); const languageToggle = document.getElementById('language-toggle'); const languageOptions = document.querySelectorAll('.language-option'); const languageSelectedLabel = document.getElementById( 'language-selected-label' ); const hiddenLanguageSelect = document.getElementById('language-select'); function setLanguageControlsDisabled(disabled) { if (languageToggle) { languageToggle.disabled = disabled; languageToggle.classList.toggle('btn-disabled', disabled); } if (hiddenLanguageSelect) { hiddenLanguageSelect.disabled = disabled; } languageOptions.forEach((option) => { option.classList.toggle('btn-disabled', disabled); option.setAttribute('aria-disabled', disabled.toString()); }); } function setLanguageUI(lang) { const labelFn = languageLabelMap[lang]; if (languageSelectedLabel && labelFn) { languageSelectedLabel.textContent = labelFn(); } languageOptions.forEach((option) => { const isActive = option.dataset.lang === lang; option.classList.toggle('active', isActive); option.setAttribute('aria-selected', isActive.toString()); }); if (hiddenLanguageSelect) { hiddenLanguageSelect.value = lang; } if (languageToggle) { languageToggle.setAttribute('aria-expanded', 'false'); } if (languageDropdown) { languageDropdown.classList.remove('open'); } } function setupLanguageDropdown() { if (!languageDropdown || !languageToggle) return; languageToggle.addEventListener('click', (event) => { event.stopPropagation(); const isOpen = languageDropdown.classList.toggle('open'); languageToggle.setAttribute('aria-expanded', isOpen.toString()); }); languageOptions.forEach((option) => { option.addEventListener('click', (event) => { event.stopPropagation(); const lang = option.dataset.lang; if (lang) { setLanguage(lang); } }); }); document.addEventListener('click', (event) => { if (!languageDropdown.classList.contains('open')) return; if (!languageDropdown.contains(event.target)) { languageDropdown.classList.remove('open'); languageToggle.setAttribute('aria-expanded', 'false'); } }); setLanguageUI(getCurrentLanguage()); } setupLanguageDropdown(); const formInputs = [ textInputElement, socialMediaInputElement, titleInputElement, locationInputElement, categoryInputElement, violenceLevelInputElement, ]; function setDefaultOutputPlaceholder() { outputElement.innerHTML = `

${t('verificationPlaceholder')}

`; } function updateSubmitButtonLabel() { if (!btnSubmit) return; btnSubmit.innerText = isLoading.value ? t('processingLabel') : t('submitButton'); } onLanguageChange((lang) => { setLanguageUI(lang); updateSubmitButtonLabel(); if (!data.value) { setDefaultOutputPlaceholder(); return; } if (selectedTab.value === 'verified_evidence') { const activeChild = selectedTabChildren.value || 'source_details'; const content = data.value.readme_content[selectedTab.value]?.[activeChild]?.content || data.value.readme_content[selectedTab.value]?.content || ''; outputElement.innerHTML = buildVerifiedEvidenceMenu(activeChild) + marked.parse(content); } }); function toggleFormInputs(disabled) { formInputs.forEach((el) => { if (!el) return; el.disabled = disabled; el.classList.toggle('btn-disabled', disabled); }); } export const clientId = Date.now().toString(36) + Math.random().toString(36).substring(2, 8); export const apiBaseUrl = ''; export let estTimeStep1 = 0; export let estTimeStep2 = 0; let currentPreviewURL = null; const mediaPreviewUrls = new Map(); const renderer = new marked.Renderer(); renderer.link = function ({ href, text }) { return `${text}`; }; let isReplaced = true; let isReplacedBlock = true; renderer.text = function ({ text }) { const hiddenTexts = []; const noReplaces = [ //EN '**Tags:**', '**Filename:**', '**Authenticity Assessment:**', '**Verification Methods:**', '**Details:**', '**Verification Tools & Methods:**', '**Synthetic Type (if applicable):**', '**Other Artifacts:**', '**Supporting Sources:**', '**Cross-Checking Information:**', '**Other Info:**', //JA '**タグ:**', '**真正性評価:**', '**検証方法:**', '**詳細:**', '**サポートソース:**', '**クロスチェック情報:**', '**その他の情報:**', //Vi '**Thẻ:**', '**Đánh giá tính xác thực:**', '**Phương pháp xác minh:**', '**Chi tiết:**', '**Nguồn hỗ trợ:**', '**Thông tin đối chiếu chéo:**', '**Thông tin khác:**', ]; isReplaced = !noReplaces.some((item) => text.includes(item)); if (isReplacedBlock) { isReplacedBlock = !text.includes('**Supporting Sources:**'); } const normalizedText = text.trim().replace(/^[-*]\s*/, ''); if (hiddenTexts.some((item) => normalizedText === item)) { return ''; } if (!isReplaced) { const inlineHtml = typeof marked.parseInline === 'function' ? marked.parseInline(text) : marked.Renderer.prototype.text.call(renderer, text); return inlineHtml; } const replaced = text.replace( /(?:\b([\w-]+)\s*)?(?:\[((?:Image\s+[^\]]+|Source\s+[^\]]+|URL\s+[^\]]+|[^,\]]+(?:\s*,\s*[^,\]]+)*))\]|\((Sources?\s+[^)]+)\))/gi, (match, beforeWord, insideSquare, insideSource) => { const beforeWordLower = (beforeWord || '').toLowerCase(); const insideLower = (insideSquare || '').toLowerCase(); const isImages = ['image', 'images', 'photo', 'photos']; if ( isImages.includes(beforeWordLower) || isImages.some((item) => insideLower.includes(item)) ) { const listImage = insideSquare .split(',') .map( (item) => `${item}` ); return `${ beforeWord ? beforeWord + ' ' : '' } [${listImage.join(', ')}]`; } const listUrl = (insideSquare || insideSource) .split(',') .map( (item) => `${item}` ); return `${beforeWord ? beforeWord + ' ' : ''} \n[${listUrl.join( ', ' )}]`; } ); return replaced; }; marked.setOptions({ renderer, breaks: true, }); let files = {}; Object.defineProperty(files, 'value', { set(newValue) { const activeIds = new Set( newValue.map((file) => `${file.name}|${file.size}|${file.lastModified}`) ); mediaPreviewUrls.forEach((url, id) => { if (!activeIds.has(id)) { URL.revokeObjectURL(url); mediaPreviewUrls.delete(id); } }); if (newValue.length > 0) { const displayNames = newValue .map((file) => { const fileId = `${file.name}|${file.size}|${file.lastModified}`; if (!mediaPreviewUrls.has(fileId)) { mediaPreviewUrls.set(fileId, URL.createObjectURL(file)); } const previewUrl = mediaPreviewUrls.get(fileId); const previewMarkup = file.type.startsWith('video/') ? `
` : `${file.name}`; return `
${previewMarkup} ${file.name}
${eyeIcon}
${trashIcon}
`; }) .join(''); wrapperFilesElement.innerHTML = displayNames; wrapperFilesElement.classList.remove('display-none'); // Add tooltips only for truncated text setTimeout(() => { document.querySelectorAll('.file-name').forEach((span) => { const fullName = span.getAttribute('data-full-name'); if (fullName && span.scrollWidth > span.clientWidth) { span.setAttribute('title', fullName); } }); }, 0); } else { wrapperFilesElement.innerHTML = ''; wrapperFilesElement.classList.add('display-none'); } this._value = newValue; }, get() { return this._value; }, }); files.value = []; let data = {}; Object.defineProperty(data, 'value', { set(newValue) { if (newValue) { btnSave.classList.add('active'); console.log(newValue); output = newValue; // livechat.classList.remove('display-none'); } else { btnSave.classList.remove('active'); output = ''; // livechat.classList.add('display-none'); } this._value = newValue; }, get() { return this._value; }, }); // data.value = {} function buildVerifiedEvidenceMenu(activeChild = 'source_details') { const labels = { source_details: t('sourceDetailsTab'), where: t('whereTab'), when: t('whenTab'), who: t('whoTab'), why: t('whyTab'), }; const childTabs = ['source_details', 'where', 'when', 'who', 'why']; const items = childTabs .map( (key) => `
${labels[key]}
` ) .join(''); return ``; } let selectedTab = {}; Object.defineProperty(selectedTab, 'value', { set(newValue) { if (data.value) { const menuItems = newValue === 'verified_evidence' ? buildVerifiedEvidenceMenu( selectedTabChildren.value || 'source_details' ) : ''; outputElement.innerHTML = menuItems + marked.parse( data.value.readme_content[newValue]?.content || data.value.readme_content[newValue]?.source_details?.content || '' ); } isReplacedBlock = true; this._value = newValue; }, get() { return this._value; }, }); selectedTab.value = 'case_summary'; let selectedTabChildren = {}; Object.defineProperty(selectedTabChildren, 'value', { set(newValue) { if (data.value) { const menuItems = buildVerifiedEvidenceMenu(newValue); outputElement.innerHTML = menuItems + marked.parse( data.value.readme_content[selectedTab.value]?.[newValue]?.content || '' ); } isReplacedBlock = true; this._value = newValue; }, get() { return this._value; }, }); selectedTabChildren.value = 'source_details'; let isLoading = {}; Object.defineProperty(isLoading, 'value', { set(newValue) { if (newValue) { btnClear.disabled = true; btnSave.disabled = true; btnSubmit.disabled = true; inputElement.disabled = true; toggleFormInputs(true); Array.from(dropZones).forEach((dropZone) => { dropZone.disabled = true; dropZone.classList.add('btn-disabled'); }); Array.from(fileRemoves).forEach((fileRemove) => { fileRemove.disabled = true; fileRemove.classList.add('btn-disabled'); }); btnClear.classList.add('btn-disabled'); btnSave.classList.add('btn-disabled'); btnSubmit.classList.add('btn-disabled'); Array.from(tabItems).forEach((tabItem) => { tabItem.disabled = true; tabItem.classList.add('btn-disabled', 'no-hover'); }); setLanguageControlsDisabled(true); } else { btnClear.disabled = false; btnSave.disabled = false; btnSubmit.disabled = false; inputElement.disabled = false; toggleFormInputs(false); Array.from(dropZones).forEach((dropZone) => { dropZone.disabled = false; dropZone.classList.remove('btn-disabled'); }); Array.from(fileRemoves).forEach((fileRemove) => { fileRemove.disabled = false; fileRemove.classList.remove('btn-disabled'); }); btnClear.classList.remove('btn-disabled'); btnSave.classList.remove('btn-disabled'); btnSubmit.classList.remove('btn-disabled'); Array.from(tabItems).forEach((tabItem) => { tabItem.disabled = false; tabItem.classList.remove('btn-disabled', 'no-hover'); }); setLanguageControlsDisabled(false); } this._value = newValue; updateSubmitButtonLabel(); }, get() { return this._value; }, }); updateSubmitButtonLabel(); setDefaultOutputPlaceholder(); inputElement.addEventListener('change', (event) => { const allowedExtensions = [ '.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.mov', '.mp4', ]; const selectedFiles = Array.from(event.target.files); const invalidFiles = selectedFiles.filter((file) => { return !allowedExtensions.some((ext) => file.name.toLowerCase().endsWith(ext) ); }); if (invalidFiles.length > 0) { createTemplateModal( `${t('allowedFormats')}${allowedExtensions.join(', ')}` ); inputElement.value = ''; return; } for (const file of selectedFiles) { if ( !files.value.some((f) => f.name === file.name && f.size === file.size) ) { files.value = [...files.value, file]; } } inputElement.value = ''; }); // Drag and drop for media files const mediaDropZone = document.querySelector('label[for="file-input"]'); mediaDropZone.addEventListener('dragover', (e) => { e.preventDefault(); mediaDropZone.classList.add('drag-over'); }); mediaDropZone.addEventListener('dragleave', (e) => { e.preventDefault(); mediaDropZone.classList.remove('drag-over'); }); mediaDropZone.addEventListener('drop', (e) => { e.preventDefault(); mediaDropZone.classList.remove('drag-over'); const droppedFiles = Array.from(e.dataTransfer.files); const allowedExtensions = [ '.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.mov', '.mp4', ]; const invalidFiles = droppedFiles.filter((file) => { return !allowedExtensions.some((ext) => file.name.toLowerCase().endsWith(ext) ); }); if (invalidFiles.length > 0) { createTemplateModal( `${t('allowedFormats')}${allowedExtensions.join(', ')}` ); return; } for (const file of droppedFiles) { if ( !files.value.some((f) => f.name === file.name && f.size === file.size) ) { files.value = [...files.value, file]; } } }); btnSubmit.addEventListener('click', () => handleSubmit()); btnClear.addEventListener('click', () => reset()); btnSave.addEventListener('click', () => handleDownload('report.md')); function reset() { inputElement.value = ''; if (textInputElement) textInputElement.value = ''; if (socialMediaInputElement) socialMediaInputElement.value = ''; if (titleInputElement) titleInputElement.value = ''; if (locationInputElement) locationInputElement.value = ''; if (categoryInputElement) categoryInputElement.value = ''; if (violenceLevelInputElement) violenceLevelInputElement.value = ''; setDefaultOutputPlaceholder(); files.value = []; data.value = null; } function hasExistingData() { return !!data.value; } function showLanguageChangeConfirm(nextLang) { const content = ` `; createTemplateModal(content, t('languageChangeConfirmTitle')); } window.confirmLanguageChange = function (lang) { reset(); setLanguage(lang, { force: true }); closeModal(); }; setLanguageGuard((nextLang, currentLang) => { if (nextLang === currentLang) return true; if (!hasExistingData()) return true; setLanguageUI(currentLang); showLanguageChangeConfirm(nextLang); return false; }); const pollIntervalMs = 5000; const maxPolls = 1000; async function runFaceCheckPolling(formData, clientId) { try { const start = await axios.post( apiBaseUrl + 'v1/face_check/polling', formData, { headers: { 'Content-Type': 'multipart/form-data', 'X-Client-ID': clientId, }, } ); const { job_id, status } = start.data; if (!job_id) return { error: 'Missing job_id from polling start' }; if (status === 'failed') return { error: 'Job failed immediately' }; let attempts = 0; while (attempts < maxPolls) { await new Promise((r) => setTimeout(r, pollIntervalMs)); attempts += 1; const res = await axios.get( apiBaseUrl + `v1/face_check/polling/${job_id}` ); if (res.data.status === 'succeeded') return { result: res.data.result }; if (res.data.status === 'failed') { return { error: res.data.error || 'Job failed' }; } } return { error: 'Polling timeout' }; } catch (error) { console.error('Face check polling failed', error); statusFaceCheckElement.classList.add('display-none'); return { error: error?.message || 'Job failed' }; } } function createDefaultMetadataFile() { const randomSuffix = Math.random().toString(36).slice(2, 10); const fileName = `metadata-${Date.now()}-${randomSuffix}.json`; const meta = { title: (titleInputElement?.value || '').trim(), location: (locationInputElement?.value || '').trim(), category: (categoryInputElement?.value || '').trim(), 'violence level': (violenceLevelInputElement?.value || '').trim(), description: (textInputElement?.value || '').trim(), 'social media link': (socialMediaInputElement?.value || '').trim(), }; const content = JSON.stringify(meta, null, 2); return new File([content], fileName, { type: 'application/json' }); } function sanitizeTextareaValue(raw) { return (raw || '').replace(/\r?\n/g, ' ').trim(); } async function handleSubmit() { if (isLoading.value) return; data.value = null; setDefaultOutputPlaceholder(); if (files.value.length === 0) { createTemplateModal(t('uploadRequirement')); return; } isLoading.value = true; statusFaceCheckElement.classList.remove('display-none'); const metadataFile = createDefaultMetadataFile(); const formData = new FormData(); formData.append('metadata_file', metadataFile); formData.append( 'additional_text', sanitizeTextareaValue(textInputElement?.value) ); const selectedLanguage = getCurrentLanguage(); formData.append('language', languageApiMap[selectedLanguage] || 'English'); const mediainfo = await new Promise((resolve) => { MediaInfo.mediaInfoFactory({ format: 'JSON' }, resolve); }); let isGetTimed = false; for (const [index, file] of files.value.entries()) { const readChunk = async (chunkSize, offset) => new Uint8Array( await file.slice(offset, offset + chunkSize).arrayBuffer() ); try { if (file.type.startsWith('video/') && !isGetTimed) { const result = await mediainfo.analyzeData(file.size, readChunk); const data = JSON.parse(result); const video = data.media.track.find((t) => t['@type'] === 'Video') || {}; const duration = +video.Duration || 0; const frameRate = +video.FrameRate || 0; const heightV = +video.Height || 0; const widthV = +video.Width || 0; const calcEstimatedTimeCode = Math.ceil( (duration * frameRate * heightV * widthV * 3.17e-7) / 60 ); estTimeStep1 = calcEstimatedTimeCode; isGetTimed = true; } formData.append('files', file); } catch (error) { console.error('Error:', error); } } estTimeStep1 = estTimeStep1 + 5; estTimeStep2 = 5; try { const { result, error } = await runFaceCheckPolling(formData, clientId); if (error || !result) { outputElement.innerText = t('processingError'); isLoading.value = false; return; } data.value = result; const menuItems = selectedTab.value === 'verified_evidence' ? buildVerifiedEvidenceMenu( selectedTabChildren.value || 'source_details' ) : ''; outputElement.innerHTML = menuItems + marked.parse( result.readme_content[selectedTab.value]?.content || result.readme_content[selectedTab.value]?.source_details?.content || '' ); estTimeStep1 = 0; estTimeStep2 = 0; isLoading.value = false; } catch (error) { outputElement.innerText = t('processingError'); isLoading.value = false; } } function handleHyperLinkImages(text) { return text.replace(/[\[\(]Image\s+([\d,\s]+)[\]\)]/g, (match, numbers) => { const list = numbers .split(',') .map((n) => n.trim()) .filter((n) => n !== ''); const result = list.map((n) => { return `[![Image ${n}]](./media/image-${n}.png)`; }); return result.join(''); }); } async function handleDownload(filename) { if (!data.value) { createTemplateModal(t('noDataToSave')); return; } const dataReport = handleHyperLinkImages(`${data.value.readme_content.case_summary.title}${data.value.readme_content.case_summary.content}${data.value.readme_content.content_classification.title}${data.value.readme_content.content_classification.content}${data.value.readme_content.verified_evidence.title} ${data.value.readme_content.verified_evidence.source_details.title}${data.value.readme_content.verified_evidence.source_details.content}${data.value.readme_content.verified_evidence.where.title}${data.value.readme_content.verified_evidence.where.content}${data.value.readme_content.verified_evidence.when.title}${data.value.readme_content.verified_evidence.when.content}${data.value.readme_content.verified_evidence.who.title}${data.value.readme_content.verified_evidence.who.content}${data.value.readme_content.verified_evidence.why.title}${data.value.readme_content.verified_evidence.why.content}${data.value.readme_content.forensic_analysis.title}${data.value.readme_content.forensic_analysis.content}${data.value.readme_content.other_evidence.title}${data.value.readme_content.other_evidence.content} `); const mediaItems = Array.isArray(data.value.readme_content.media) ? data.value.readme_content.media : []; if (mediaItems.length === 0) { const blob = new Blob([dataReport], { type: 'text/markdown', }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); return; } if (typeof JSZip === 'undefined') { createTemplateModal(t('downloadPrepareFailedNetwork')); return; } const zip = new JSZip(); zip.file(filename, dataReport); // Package each available media asset alongside the markdown report mediaItems.forEach((raw, index) => { if (typeof raw !== 'string' || !raw.trim()) { return; } const base64Data = raw.replace(/\s+/g, ''); zip.file(`media/image-${index + 1}.png`, base64Data, { base64: true }); }); try { const archiveBlob = await zip.generateAsync({ type: 'blob' }); const baseName = filename ? filename.replace(/\.[^/.]+$/, '') : 'report'; const archiveName = `${baseName || 'report'}-assets.zip`; const url = URL.createObjectURL(archiveBlob); const a = document.createElement('a'); a.href = url; a.download = archiveName; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch (error) { console.error('Failed to generate download archive', error); createTemplateModal(t('downloadPrepareFailed')); } } window.goToEvidence = function () { if (selectedTab.value === 'other_evidence') return; document.querySelectorAll('.menu .item').forEach((item) => { item.classList.remove('active'); }); document .getElementById('other_evidence-1763023210526') .classList.add('active'); selectedTab.value = 'other_evidence'; }; window.previewImage = function (imageRaw) { const match = imageRaw.match(/\d+/); if (!match) return; const index = Number(match[0]) - 1; const image = data.value.readme_content.media[index]; if (!image) return; createTemplateModal( `Image Preview`, `${t('imageLabel')} ${index + 1}` ); }; window.changeTabChildren = function (tab, element) { if (isLoading.value) return; document.querySelectorAll('.menu-children .item').forEach((item) => { item.classList.remove('active'); }); element.classList.add('active'); selectedTabChildren.value = tab; }; window.changeTab = function (tab, element) { if (isLoading.value) return; document.querySelectorAll('.menu .item').forEach((item) => { item.classList.remove('active'); }); element.classList.add('active'); selectedTab.value = tab; }; window.removeFile = function (event, fileId, fileType) { event.preventDefault(); event.stopPropagation(); if (isLoading.value) return; const [fileName, fileSize, fileLastModified] = fileId.split('|'); files.value = files.value.filter( (file) => !( file.name === fileName && file.size.toString() === fileSize && file.lastModified.toString() === fileLastModified ) ); }; function createTemplateModal(content, title = t('notificationTitle')) { const modal = `
${title}
${closeIcon}
${content}
`; openModal(modal); } window.previewFile = function (event, fileId) { event.preventDefault(); event.stopPropagation(); const [fileName, fileSize, fileLastModified] = fileId.split('|'); const file = files.value.find( (f) => f.name === fileName && f.size.toString() === fileSize && f.lastModified.toString() === fileLastModified ); if (!file) return; const fileURL = URL.createObjectURL(file); currentPreviewURL = fileURL; let content = ''; if (file.type === 'video/quicktime') { content = t('movNotSupported'); } else if (file.type.startsWith('image/')) { content = `${file.name}`; } else if (file.type.startsWith('video/')) { content = ``; } else { content = t('previewUnavailable'); } createTemplateModal(content, file.name); }; function openModal(content) { contentModalElement.innerHTML = content; wrapperModalElement.style.display = 'flex'; } window.closeModal = function () { wrapperModalElement.style.display = 'none'; const video = contentModalElement.querySelector('video'); if (video) { video.pause(); video.currentTime = 0; } if (currentPreviewURL) { URL.revokeObjectURL(currentPreviewURL); currentPreviewURL = null; } };