/** * @file manager.js * @brief Основной файл manager, отвечает за управление файлами */ movementMenu("managerDiv"); movementMenu("managerProperties"); /** @brief Элемент менеджера папок */ let managerDiv = document.getElementById('managerDiv'); managerData(currentPath); /** @brief Основные кнопки и редактируемые поля в менеджере */ function managerFun() { document.getElementById('managerCloseFun').onclick = function() { managerDiv.style.visibility = "hidden"; }; document.getElementById('managerHistoryBackFun').onclick = function() { if (managerHistoryIndex > 0) { managerHistoryIndex--; managerData(managerHistoryPaths[managerHistoryIndex]); } }; document.getElementById('managerHistoryForwFun').onclick = function() { if (managerHistoryIndex < managerHistoryPaths.length - 1) { managerHistoryIndex++; managerData(managerHistoryPaths[managerHistoryIndex]); } }; document.getElementById('managerBackFun').onclick = function() { managerData(removeLastSegment(currentPath)); }; document.getElementById('managerSettingsCopy').onclick = function() { managerClipboard("copy", "{{copy}}"); }; document.getElementById('managerSettingsCut').onclick = function() { managerClipboard("cut", "{{cut}}"); }; /** * @brief Выполняет операции с буфером (копирование/вставка/вырезание) * @param action действие: copy/cut * @param messageText текст сообщения */ function managerClipboard(action, messageText) { if (managerTableDivFilePath) { let textToCopy = managerTableDivFilePath + '|' + action; navigator.clipboard.writeText(textToCopy).then(() => { document.getElementById('managerSettings').style.visibility = "hidden"; }).catch(err => { console.error('Ошибка копирования в буфер:', err); }); } else { messageFunction("{{right_click_to_select_file}}"); } } let managerSettingsInsertId = document.getElementById('managerSettingsInsert'); managerSettingsInsertId.onclick = function() { navigator.clipboard.readText().then(clipboardText => { let [clipboardPath, clipboardAction] = clipboardText.split('|'); if (!clipboardPath || !clipboardAction) { messageFunction("{{right_click_to_select_file}}"); return; } jsonrpcRequest("checkNameConflict", { name: clipboardPath, currentPath: currentPath }).then(response => { if (response == "true") { messageFunction("{{file_with_same_name_exists}}"); } else { jsonrpcRequest("insertClipboard", { managerSettingsInsert: currentPath, clipboardPath: clipboardPath, clipboardAction: clipboardAction }).then(response => { if (response === "true") { messageFunction("{{file_pasted_successfully}}"); } else { let errorMessage = response.error ? response.error : "{{file_paste_unknown_error}}"; messageFunction("{{error}}: " + errorMessage); } managerData(currentPath); }); } }); }).catch(err => { console.error('Ошибка чтения из буфера:', err); }); }; let managerSettingsRenameId = document.getElementById('managerSettingsRename'); managerSettingsRenameId.onclick = async function() { if (managerTableDivFilePath) { let invalidCharacters = /[\/\\:*?"<>|]/; let managerTableDivFileName = managerTableDivFilePath.split(/[/\\]/).pop(); messageQueue.push("{{enter_new_name}}"); let title = await messageCreateInput(managerTableDivFileName || ''); let isFolder = !/\./.test(managerTableDivFileName); if (title !== null) { if (title && !invalidCharacters.test(title) && (!isFolder || !title.includes('.'))) { messageQueue.push("{{rename_confirm}} " + title + "?"); if (await messageCreateQuestion()) { let data = await jsonrpcRequest("checkNameConflict", { name: title, currentPath: currentPath }); if (data == "true") { messageFunction("{{file_with_same_name_exists}}"); } else { let res = await jsonrpcRequest("renameFile", { managerSettingsRename: managerTableDivFilePath, managerNamePath: title }); if (res === "true") { messageFunction("{{rename_success}}"); } else { messageFunction("{{rename_error}}"); } managerData(currentPath); } } } else { messageFunction("{{invalid_name_error}}"); } } } else { messageFunction("{{right_click_to_select_file}}"); } }; let managerSettingsDeleteId = document.getElementById('managerSettingsDelete'); managerSettingsDeleteId.onclick = async function() { if (managerTableDivFilePath) { messageQueue.push("{{delete_confirm}}"); if (await messageCreateQuestion()) { let response = await jsonrpcRequest("deleteFile", { managerSettingsDelete: managerTableDivFilePath }); if (response === "true") { messageFunction("{{delete_success}}"); } else { messageFunction("{{delete_error}}"); } managerData(currentPath); } } else { messageFunction("{{right_click_to_select_file}}"); } }; document.getElementById('managerSettingsButtonCreateFolder').onclick = async function() { await createManagerItem("папка", "{{enter_new_folder_name}}", "{{invalid_folder_name}}", "{{folder_created_successfully}}"); }; document.getElementById('managerSettingsButtonCreateFile').onclick = async function() { await createManagerItem("файл", "{{enter_new_file_name}}", "{{invalid_file_name}}", "{{file_created_successfully}}"); }; async function createManagerItem(type, promptMessage, errorMessage, successMessage, nameSuffix = '') { messageQueue.push(promptMessage); let title = await messageCreateInput(); if (title !== null) { let invalidCharacters = /[\/\\:*?"<>|]/; let isValidTitle = title && !invalidCharacters.test(title) && !title.startsWith('.') && !title.endsWith('.'); if (type === "{{folder}}") { isValidTitle = isValidTitle && !title.includes('.'); } if (isValidTitle) { title += nameSuffix; messageQueue.push("{{create}} " + type + " {{with_name}} " + title + "?"); if (await messageCreateQuestion()) { let data = await jsonrpcRequest("checkNameConflict", { name: title, currentPath: currentPath }); if (data == "true") { messageFunction("{{file_with_same_name_exists}}!"); } else { let response = await jsonrpcRequest("createFile", { managerSettingsCreate: title, managerType: type, managerNamePath: currentPath }); if (response === "true") { messageFunction(successMessage); } else if (response === "checkItemExists") { messageFunction(type + " {{item_already_exists}}"); } else { messageFunction("{{create_error}} " + type + "!"); } managerData(currentPath); } } } else { messageFunction(errorMessage); } } } let managerSettingsPropertiesId = document.getElementById('managerSettingsProperties'); managerSettingsPropertiesId.onclick = function() { document.getElementById('managerProperties').style.visibility = 'hidden'; if (managerTableDivFilePath) { jsonrpcRequest("getFileProperties", { managerSettingsProperties: managerTableDivFilePath }).then(data => { let managerPropertiesId = document.getElementById('managerProperties'); let managerPropertiesDivId = document.getElementById('managerPropertiesDiv'); let managerPropertiesTopNameId = document.getElementById('managerPropertiesTopName'); let managerPropertiesWindowPropertiesId = document.getElementById('managerPropertiesWindowProperties'); let managerPropertiesWindowRightsId = document.getElementById('managerPropertiesWindowRights'); let tableProperties = document.createElement('table'); tableProperties.style.width = "100%"; data.forEach(item => { let row = document.createElement('tr'); let labelCell = document.createElement('td'); let valueCell = document.createElement('td'); labelCell.className = 'managerPropertiesDivDivs'; valueCell.className = 'managerPropertiesDivDivs'; labelCell.textContent = item.label; valueCell.textContent = item.value; row.appendChild(labelCell); row.appendChild(valueCell); tableProperties.appendChild(row); }); let tableRights = document.createElement('div'); tableRights.innerHTML = "{{no_rights_yet}}"; managerPropertiesTopNameId.textContent = "{{properties}} " + data[0].value; managerPropertiesDivId.innerHTML = ''; managerPropertiesWindowPropertiesId.onclick = function() { managerPropertiesDivId.innerHTML = ''; managerPropertiesDivId.appendChild(tableProperties); managerPropertiesWindowPropertiesId.style.backgroundColor = "#f3f3f3"; managerPropertiesWindowRightsId.style.backgroundColor = ""; }; managerPropertiesWindowRightsId.onclick = function() { managerPropertiesDivId.innerHTML = ''; managerPropertiesDivId.appendChild(tableRights); managerPropertiesWindowPropertiesId.style.backgroundColor = ""; managerPropertiesWindowRightsId.style.backgroundColor = "#f3f3f3"; }; managerPropertiesWindowPropertiesId.click(); if (managerPropertiesId.style.visibility == 'hidden') { managerPropertiesId.style.visibility = 'visible'; } let managerPropertiesTopCloseId = document.getElementById('managerPropertiesTopClose'); let managerPropertiesDivButtonOkId = document.getElementById('managerPropertiesDivButtonOk'); let managerPropertiesDivButtonCancelId = document.getElementById('managerPropertiesDivButtonCancel'); managerPropertiesTopCloseId.onclick = function() { managerPropertiesId.style.visibility = 'hidden'; }; managerPropertiesDivButtonOkId.onclick = function() { managerPropertiesId.style.visibility = 'hidden'; }; managerPropertiesDivButtonCancelId.onclick = function() { managerPropertiesId.style.visibility = 'hidden'; }; }); } else { messageFunction("{{right_click_to_select_file}}"); } }; //загрузка файла для менеджера let managerSettingsLoadId = document.getElementById('managerSettingsLoad'); managerSettingsLoadId.onclick = function() { let fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.addEventListener('change', function() { jsonrpcRequest("checkNameConflict", { name: fileInput.files[0].name, currentPath: currentPath }).then(data => { if (data == "true") { messageFunction("{{file_with_same_name_exists}}") } else { const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function() { const base64Data = reader.result.split(',')[1]; jsonrpcRequest("uploadFile", { fileName: file.name, fileData: base64Data, pathLoad: currentPath }).then(response => { messageFunction("{{file_uploaded_successfully}}") managerData(currentPath) }).catch(() => { messageFunction("{{file_with_same_name_exists}}") }) }; reader.readAsDataURL(file); } }); }); fileInput.click(); }; } /** @brief Удаляет последний сегмент пути */ function removeLastSegment(str) { const segments = str.split('/'); if (segments.length > 1) { segments.pop(); } return segments.join('/'); } /** @brief Инициализация окна настроек менеджера */ function managerSettings() { let managerDiv = document.getElementById('managerDiv'); let managerSettingsDiv = document.getElementById('managerSettings'); managerDiv.addEventListener('contextmenu', managerSettingsClick); touchLong(managerDiv, managerSettingsClick); } /** * @brief Обрабатывает клик правой кнопкой мыши для показа настроек * @param event событие мыши */ function managerSettingsClick(event) { event.preventDefault(); let managerSettingsDiv = document.getElementById('managerSettings'); if (!isPhone) { managerSettingsDiv.style.left = `${touchX}px`; managerSettingsDiv.style.top = `${touchY}px`; } else { managerSettingsDiv.style.bottom = '15px'; managerSettingsDiv.style.width = 'calc(100vw - 42px)'; managerSettingsDiv.style.height = '42px'; managerSettingsDiv.style.left = '15px'; managerSettingsDiv.style.top = 'auto'; managerSettingsDiv.style.boxShadow = 'none'; } let ids = [ 'managerSettingsCopy', 'managerSettingsCut', 'managerSettingsRename', 'managerSettingsDelete', 'managerSettingsProperties', 'managerSettingsLoad', 'managerSettingsInsert', 'managerSettingsButtonCreateFolder', 'managerSettingsButtonCreateFile' ]; ids.forEach(id => { let el = document.getElementById(id); if (el) { if (el.dataset.oldDisplay === undefined) { el.dataset.oldDisplay = getComputedStyle(el).display; } el.style.display = 'none'; } }); if (event.target.closest('.managerTableDivFile')) { ['managerSettingsCopy','managerSettingsCut','managerSettingsRename','managerSettingsDelete','managerSettingsProperties'] .forEach(id => { let el = document.getElementById(id); el.style.display = el.dataset.oldDisplay; }); } else { document.getElementById('managerSettingsLoad').style.display = document.getElementById('managerSettingsLoad').dataset.oldDisplay; navigator.clipboard.readText().then(text => { if (text) { let parts = text.split('|'); if (parts.length === 2 && parts[0].trim() !== '' && parts[1].trim() !== '') { let el = document.getElementById('managerSettingsInsert'); el.style.display = el.dataset.oldDisplay; } } }).catch(err => { console.error('Ошибка чтения буфера:', err); }); ['managerSettingsButtonCreateFolder','managerSettingsButtonCreateFile'] .forEach(id => { let el = document.getElementById(id); el.style.display = el.dataset.oldDisplay; }); } managerSettingsDiv.style.visibility = 'visible'; document.addEventListener('pointerdown', function hideMenu(e) { if (!managerSettingsDiv.contains(e.target)) { managerSettingsDiv.style.visibility = 'hidden'; document.removeEventListener('pointerdown', hideMenu); } }); } /** * @brief Обрабатывает контекстное меню пути * @param event событие контекстного меню */ function managerPathContext(event){ let targetElement=event.target.closest('[path]') if(targetElement){ let pathValue=targetElement.getAttribute('path') managerTableDivFilePath=pathValue } } document.addEventListener('contextmenu',managerPathContext) touchLong(document, managerPathContext) /** @brief Сохраняет файл через функцию "Сохранить как" */ function saveHow() { let currentPathHow = currentPath; if (currentPathHow.startsWith('/')) { currentPathHow = currentPathHow.slice(1); } if (!currentPathHow.endsWith('/')) { currentPathHow += '/'; } window.saveContentIdHow(currentPathHow); } /** @brief Открывает выбранную страницу */ function openPageBut() { if (openPageButPath != "no/Select") { getPage(openPageButPath); } else { messageFunction('{{select_file_ending_with_page_php}}'); } } /** @brief Обрабатывает выбор страницы через URL */ function propertiesUrlFun() { let saveHowNameValue = document.getElementById('saveHowName').value; if (!saveHowNameValue.includes('.page.php')) return; let newValue = saveHowNameValue.replace(/\.page\.php/, ""); let cp = currentPath; if (cp.charAt(0) === "/") { cp = cp.substring(1); } document.getElementById('treePropertiesDivUrlValue').innerHTML = cp + "/" + newValue; window.managerDataAction = ""; managerDiv.style.visibility = "hidden"; } /** @brief Обрабатывает выбор изображения для вставки */ function selectImgFormButFun() { var rawPath = document.getElementById('managerPath').textContent; var cleanPath = rawPath.trim().replace(/\s*\/\s*/g, '/').replace(/\s+/g, ''); var fileName = document.getElementById('saveHowName').value.trim(); var fullPath = cleanPath + fileName; if (fullPath.startsWith('/')) { fullPath = fullPath.slice(1); } var img = document.createElement("img"); img.src = fullPath; img.setAttribute("style", "float: left; margin: 10px; width: 250px; border: 0px solid rgb(0, 0, 0); overflow: hidden;"); var sel = window.getSelection(); if (sel.rangeCount) { var range = sel.getRangeAt(0); range.deleteContents(); range.insertNode(img); } window.managerDataAction = ""; managerDiv.style.visibility = "hidden"; } /** @brief Обрабатывает выбор изображения для вставки в форму */ function selectImgFormToFormButFun() { var rawPath = document.getElementById('managerPath').textContent; var cleanPath = rawPath.trim().replace(/\s*\/\s*/g, '/').replace(/\s+/g, ''); var fileName = document.getElementById('saveHowName').value.trim(); var fullPath = cleanPath + fileName; if (fullPath.startsWith('/')) fullPath = fullPath.slice(1); window.pendingImageSrc = fullPath; window.managerDataAction = ""; managerDiv.style.visibility = "hidden"; } if (isPhone) document.getElementById('managerDiv').style.paddingBottom = "150px" if (!isPhone) { document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{ btn.style.backgroundColor='rgba(255, 255, 255, 1)' btn.style.borderRadius='5px' btn.style.padding='2px' btn.style.margin='3px' btn.style.cursor='pointer' btn.style.display='block' btn.addEventListener('mouseover',()=>btn.style.color='#787878') btn.addEventListener('mouseout',()=>btn.style.color='') }) } else { document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{ btn.style.backgroundImage='url(../../img/pict/b_iconslyb.svg)' btn.style.height='42px' btn.style.minWidth='42px' btn.style.setProperty('background-size','calc(1122px* 1.5)','important') btn.style.display='inline-block' btn.style.borderRadius='5px' btn.style.cursor='pointer' btn.style.display='flex' btn.style.flexDirection='column' btn.style.alignItems='center' btn.style.fontSize='10px' btn.style.lineHeight='1' btn.style.justifyContent = 'flex-end' btn.style.top='2px' btn.style.position = 'relative' btn.style.width = 'auto' }) let wrap = document.getElementById('managerSettings') wrap.style.display = 'flex' wrap.style.maxWidth = '-webkit-fill-available' wrap.style.overflowX = 'auto' wrap.style.overflowY = 'hidden' wrap.style.justifyContent = 'center' let div = document.getElementById('managerSettingsDiv') div.style.height = '-webkit-fill-available' div.style.display = 'inline-flex' div.style.whiteSpace = 'nowrap' div.style.width = 'max-content' div.style.gap = '7px' div.style.alignItems = 'center' } window.managerSettings = managerSettings; window.managerFun = managerFun; window.saveHow = saveHow; window.openPageBut = openPageBut; window.propertiesUrlFun = propertiesUrlFun; window.selectImgFormButFun = selectImgFormButFun; window.selectImgFormToFormButFun = selectImgFormToFormButFun;