let recommendationAppsConfigs = []; const recommendedButtonsApps = document.getElementById('recommended_buttons_apps'); window.onload = function() { const markDownConverter = new showdown.Converter(); const mainBtn = document.getElementById('openai_generator_button'); const additionalOptions = document.getElementById('additional_options'); const formAppFirstQuestion = document.getElementById('form-app-first-question'); const formAppAdditionalQuestions = document.getElementById('form-app-additional-questions'); const template_type_text = document.getElementById('template_type_text'); const eventHandlers = []; const resultBlock = document.getElementById('result'); const resultMediaGalleryBlock = document.getElementById('result-media-gallery'); let formAlreadyCreated = false; let activeAppConfig = null; let initConfigIdOrSlug = '114'; const initConfigIdOrSlugFromParam = getParameterByName('slugOrId'); if (initConfigIdOrSlugFromParam) { initConfigIdOrSlug = initConfigIdOrSlugFromParam; } let authCheck = false; const messageFormForHuman = document.getElementById('messageFormForHuman'); let loadFeedTask = false; if ( !initConfigIdOrSlug || initConfigIdOrSlug === 'null' ) { initConfigIdOrSlug = localStorage.getItem('initConfigIdOrSlug'); } const initPromises = [ getRecommendedApps(), ...(loadFeedTask ? [getFeedTasks()] : []) ]; Promise.all(initPromises) .then(results => {}) .catch(error => {}); async function getRecommendedApps() { try { const response = await fetch('https://aisearch.tech/api/v3/app/recommended' + '?guest=true&limit=400&loc=en'); if (!response.ok) { throw new Error(`Error: ${response.status}`); } const configApps = await response.json(); renderRecommendedAppsButton(configApps); } catch (error) { toastr.error('An error occurred while retrieving data:', error) } } async function getFeedTasks(nextUrl = null) { try { if (nextUrl === null) { nextUrl = 'https://aisearch.tech/api/v3/app/tasks/feed' + '?loc=en'; } const response = await fetch(nextUrl); if (!response.ok) { throw new Error(`Error: ${response.status}`); } const feedTasks = await response.json(); renderFeedTasks(feedTasks); } catch (error) { toastr.error('An error occurred while retrieving data:', error) } } function renderFeedTasks(feedTasks) { if (feedTasks.feed.data && feedTasks.feed.data.length > 0) { authCheck = feedTasks.authCheck; feedTasks.feed.data.forEach(task => { selectorViewTask(task, true) }); const nextFeedResult = document.getElementById('next_feed_result'); nextFeedResult.innerHTML = ''; if ( feedTasks.feed.next_page_url && feedTasks.feed.data.length > 4 ) { const button = document.createElement('button'); button.textContent = 'More'; button.style.margin = '5px'; button.id = 'app_btn_'; button.classList = "max-w-[calc(100%)] app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none w-full"; button.onclick = () => { getFeedTasks(feedTasks.feed.next_page_url) }; nextFeedResult.appendChild(button); } } allImagesPreview(); } function allImagesPreview() { const imageContainers = document.querySelectorAll('.chat-content-container img'); imageContainers.forEach((img) => { img.style.cursor = 'pointer'; img.onclick = () => { event.preventDefault(); openModalWithImage(img.src); return; }; }); } function openModalWithImage(src) { const url = new URL(src); url.searchParams.delete('width'); const updatedSrc = url.toString(); const modal = document.createElement('div'); modal.style.position = 'fixed'; modal.style.top = '0'; modal.style.left = '0'; modal.style.width = '100%'; modal.style.height = '100%'; modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; modal.style.display = 'flex'; modal.style.alignItems = 'center'; modal.style.justifyContent = 'center'; modal.style.zIndex = '1000'; const img = document.createElement('img'); img.src = updatedSrc; img.style.maxWidth = '90%'; img.style.maxHeight = '90%'; img.style.border = '2px solid white'; modal.appendChild(img); modal.onclick = () => { document.body.removeChild(modal); }; document.body.appendChild(modal); } function selectorViewTask(task, append = true, done = true) { const clone = document.importNode(template_type_text.content, true); let resultAnswer = clone.querySelector('.result_answer'); let requestTitle = clone.querySelector('.request_title'); let requestDateTime = clone.querySelector('.request_date_time'); let requestResultSearch = clone.querySelector('.result-search'); try { let realtime_search_result = JSON.parse(task.realtime_search_result); if (realtime_search_result.organic.length > 0) { prepareResultSearchBlock(requestResultSearch, realtime_search_result.organic); } } catch (e) { } if (task.generator === null) { return; } if (done && task.generator.presentation_result == 'file_excel') { resultAnswer.innerHTML = viewExcelProcessingResult(task); } if (done && task.generator.presentation_result == 'file_image') { resultAnswer.innerHTML = viewFileImages(task); } if (done && task.generator.presentation_result == 'text_editor') { resultAnswer.innerHTML = viewResultTaskText(task, clone); highlightCode(resultAnswer); } if (done && task.generator.presentation_result == 'video_editor') { resultAnswer.innerHTML = viewFileVideo(task); } if (done && task.generator.presentation_result == 'text_to_voice_editor') { resultAnswer.innerHTML = viewFileTextToVoice(task); } if (done && task.generator.presentation_result == 'voice_to_text_editor') { resultAnswer.innerHTML = viewFileVoiceToText(task); } if (done && task.generator.presentation_result == 'image_ocr_editor') { resultAnswer.innerHTML = viewOcrImage(task); } if (done && task.generator.presentation_result == 'clone_voice_editor') { resultAnswer.innerHTML = viewVoiceClone(task); } if (task.output_files) { var outputFiles = JSON.parse(task.output_files); let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); outputFiles.forEach(file => { routeDownload = routeDownload.replace('__name__', file.name); let element; switch (file.mimetype) { case 'audio/mpeg': element = ``; break; case 'video/mp4': element = ``; break; case 'image/jpeg': case 'image/png': case 'image/gif': element = `${routeDownload}`; break; case 'image/svg+xml': element = `Your browser does not support SVGs.`; break; default: element = `

Файл: ${file.name} (тип: ${file.mimetype})

`; } resultAnswer.innerHTML += element; }); } requestTitle.innerHTML = '

'+task.title+'

'; requestDateTime.textContent = convertToLocalDateTime(task.created_at); resultBlock.id = task.uuid; if (append) { resultBlock.appendChild(clone); } else { resultBlock.insertBefore(clone, resultBlock.firstChild); } let audioElements = document.querySelectorAll('.data-audio'); audioElements.forEach(generateWaveForm); } function viewExcelProcessingResult(task) { const excelProcessingObject = task.output; let viewResult = 'Result:
'; let urlToDownload = `https://aisearch.tech/api/v3/app/tasks/__uuid__/download/__filename__`; urlToDownload = urlToDownload.replace('__uuid__', task.uuid); urlToDownload = urlToDownload.replace('__filename__', excelProcessingObject.file_processed); return viewResult += `${excelProcessingObject.file_processed}`; } function viewFileImages(task) { const files = task.output; if (files.length > 0) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); let resultInnerHTML = '
'; files.forEach(file => { resultInnerHTML += `
`; }); resultInnerHTML += `
`; return resultInnerHTML; } } function viewOcrImage(task) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); routeDownload = routeDownload.replace('__name__', task.output.input_file) + '?subDir=input'; let resultInnerHTML = '
'; resultInnerHTML += `
${convertMarkdownToHtml(task.output.extracted_text)}
`; resultInnerHTML += `
`; resultInnerHTML += `
`; return resultInnerHTML; } function viewFileVideo(task) { const file = task.output; let routeToFile = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; let routeDownloadPreview = routeToFile; let routeDownloadVideo = routeToFile; if (file.file && file.file.video) { routeDownloadPreview = routeDownloadPreview.replace('__uuid__', task.uuid); routeDownloadPreview = routeDownloadPreview.replace('__name__', file.file.firstFrame); routeDownloadVideo = routeDownloadVideo.replace('__uuid__', task.uuid); routeDownloadVideo = routeDownloadVideo.replace('__name__', file.file.video); return ``; } else { routeDownloadVideo = routeDownloadVideo.replace('__uuid__', task.uuid); routeDownloadVideo = routeDownloadVideo.replace('__name__', file.fileName); return ``; } } function viewFileVoiceToText(task) { let resultVoiceToText = ''; if (task.output.language) { resultVoiceToText += 'Language: ' + task.output.language + '

'; } if (task.output.text) { resultVoiceToText += task.output.text + '

'; } if (task.output.words) { resultVoiceToText += 'By words:
'; task.output.words.forEach(words => { resultVoiceToText += words.word + ' start: ' + words.start + '
'; }); } return resultVoiceToText; } function viewVoiceClone(task) { let resultTextToVoice = ''; let duration = task.output.duration; let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); routeDownload = routeDownload.replace('__name__', task.output.referenceFileName) + '?subDir=input'; resultTextToVoice += `
${duration}

`; return resultTextToVoice; } function viewFileTextToVoice(task) { let resultTextToVoice = ''; let routeDownloadVideo = null; let output = task.output.speechIds; let compile = task.output.compile_voice; if (task.output.compile_voice && compile.name) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); if (task.output.compile_voice_video) { routeDownloadVideo = routeDownload.replace('__name__', task.output.compile_voice_video.name); } routeDownload = routeDownload.replace('__name__', compile.name); let duration = compile.duration; resultTextToVoice += 'Result:
'; if (routeDownloadVideo) { resultTextToVoice += `
`; } resultTextToVoice += `
`; } let firstIteration = true; for (let key in output) { if (firstIteration) { firstIteration = false; } let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; let duration = 0; if (output[key]['file']['name']) { routeDownload = routeDownload.replace('__uuid__', task.uuid); if (output[key]['fileVideo']['name']) { routeDownloadVideo = routeDownload.replace('__name__', output[key]['fileVideo']['name']); } routeDownload = routeDownload.replace('__name__', output[key]['file']['name']); duration = output[key]['file']['duration']; } let textSpeech = truncateString(output[key]['text-to-voice']); resultTextToVoice += `
${textSpeech}`; if (routeDownloadVideo) { resultTextToVoice += `
`; } resultTextToVoice += `
`; } return resultTextToVoice; } function truncateString(str = null, length = 100) { if (str === null) { return ''; } if (str.length <= length) { return str; } return str.slice(0, length) + '...'; } function viewResultTaskText(task, clone) { createChatWndButton(task, clone); reloadTask(task, clone); return convertMarkdownToHtml(task.output); } function createChatWndButton(task, clone) { if (authCheck) { let requestResultAction = clone.querySelector('.open-chat-wnd'); requestResultAction.style.visibility = 'visible'; requestResultAction.addEventListener('click', function() { openChatFrame(task); }); } } function reloadTask(task, clone) { if (authCheck) { let requestResultAction = clone.querySelector('.reload-task'); requestResultAction.style.visibility = 'visible'; requestResultAction.addEventListener('click', function() { let routeInitData = 'https://aisearch.tech/api/v3/user/tasks/__UUID__/initial-data'; if (task.uuid) { routeInitData = routeInitData.replace('__UUID__', task.uuid); } document.getElementById('app_form').scrollIntoView({ behavior: 'smooth' }); fetch(routeInitData) .then(response => { if (!response.ok) { throw new Error('Сеть ошибки: ' + response.status); } return response.json(); }) .then(data => { const url = new URL(window.location.href); url.search = ''; url.searchParams.set('slugOrId', data.data.app_id); for (const [key, value] of Object.entries(data.data.user_params)) { if (typeof value !== 'object' && !Array.isArray(value)) { url.searchParams.set(key, value); } } url.hash = 'main_block_app_form'; window.location.href = url; }) .catch(e => { toastr.error(e.message); }); }); } } function openChatFrame(task = null) { document.body.style.overflow = 'hidden'; const blurBackground = document.createElement('div'); blurBackground.style.position = 'fixed'; blurBackground.style.top = '0'; blurBackground.style.left = '0'; blurBackground.style.width = '100%'; blurBackground.style.height = '100%'; blurBackground.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; blurBackground.style.backdropFilter = 'blur(10px)'; blurBackground.style.zIndex = '999'; const frame = document.createElement('iframe'); frame.src = 'https://aisearch.tech/dashboard/ai/chat-wnd'; if (task) { frame.src += '?taskId='+task.id; } frame.style.position = 'fixed'; frame.style.top = '50%'; frame.style.left = '50%'; frame.style.transform = 'translate(-50%, -50%)'; if (window.innerWidth < 600) { frame.style.width = '100%'; } else { frame.style.width = '80%'; } frame.style.maxWidth = '1000px'; frame.style.height = '100%'; frame.style.maxHeight = '1100px'; frame.style.zIndex = '9999'; frame.style.border = 'none'; document.body.appendChild(blurBackground); document.body.appendChild(frame); const closeButton = document.createElement('button'); closeButton.innerHTML = ``; closeButton.style.position = 'fixed'; closeButton.style.top = '20px'; closeButton.style.left = '10px'; closeButton.style.zIndex = '10000'; closeButton.addEventListener('click', function() { document.body.removeChild(frame); document.body.removeChild(blurBackground); document.body.removeChild(closeButton); document.body.style.overflow = ''; }); document.body.appendChild(closeButton); } function highlightCode( wrapperEl ) { if ( !wrapperEl ) return; wrapperEl.innerHTML = wrapperEl.innerHTML .replace(/>(\s*\r?\n\s*)<') .replace(/\n(?!.*\n)/, ''); wrapperEl.querySelectorAll( 'code[class*=language-]' ).forEach( el => { Prism.highlightElement( el ); } ); } function prepareResultSearchBlock(requestResultSearch, organic) { const resultSearchTitle = document.createElement('h3'); resultSearchTitle.classList = 'lqd-titlebar-title m-0'; resultSearchTitle.textContent = 'Found on the internet:'; requestResultSearch.appendChild(resultSearchTitle); organic.forEach((result, index) => { const resultItem = document.createElement('div'); resultItem.classList.add('result-item'); const titleElement = document.createElement('h4'); titleElement.innerHTML = ``; titleElement.innerHTML += `
${result.title}`; const snippetElement = document.createElement('p'); snippetElement.textContent = result.snippet; resultItem.appendChild(titleElement); resultItem.appendChild(snippetElement); requestResultSearch.appendChild(resultItem); }); requestResultSearch.style.display = 'block'; requestResultSearch.onclick = () => { requestResultSearch.style.maxHeight = '10000px'; }; return requestResultSearch; } function renderRecommendedAppsButton(configApps) { const gridMoreAppsModalForm = document.getElementById('moreAppsModalFormSearch'); const lqdMoreAppsList = document.getElementById('lqd-more-apps-list'); let iter = 0; let appsOnForm = true; recommendationAppsConfigs = configApps; if (!recommendationAppsConfigs) { return; } authCheck = configApps.authCheck; configApps.data.forEach(app => { if (iter > 3 && appsOnForm) { gridMoreAppsModalForm.style.display = 'inline'; recommendedButtonsApps.appendChild(gridMoreAppsModalForm); appsOnForm = false } if (!appsOnForm) { const divMoreAppForLqdMoreAppsList = document.createElement('div'); divMoreAppForLqdMoreAppsList.classList = "relative w-full cursor-pointer rounded-2xl p-4 shadow-[0_2px_5px_rgba(29,39,59,0.05)] transition-all duration-300 hover:-translate-y-1 hover:shadow-lg dark:bg-foreground/[1%] lg:py-6 lg:ps-6"; divMoreAppForLqdMoreAppsList.setAttribute("data-title", app.title.trim().toLowerCase()); divMoreAppForLqdMoreAppsList.setAttribute("data-prompt", app.btn_main_action.trim().toLowerCase()); divMoreAppForLqdMoreAppsList.setAttribute("data-favorite", false); divMoreAppForLqdMoreAppsList.setAttribute("x-init", ""); divMoreAppForLqdMoreAppsList.setAttribute("x-show", "(searchPromptStr === '' && promptFilter === 'all') || ($el.getAttribute('data-title').includes(searchPromptStr) || $el.getAttribute('data-prompt').includes(searchPromptStr)) && ( promptFilter === 'all' || (promptFilter === 'favorite' && $el.getAttribute('data-favorite') === 'true') )"); divMoreAppForLqdMoreAppsList.innerHTML = `

${app.title}

${app.btn_main_action}

Open app `; lqdMoreAppsList.append(divMoreAppForLqdMoreAppsList); return; } const button = document.createElement('button'); button.textContent = app.title; button.style.margin = '5px'; button.id = 'app_btn_' + app.slug; button.classList = "app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none"; button.onclick = () => { selectAppButton(app.slug); createForm(app); }; recommendedButtonsApps.appendChild(button); iter++; if (initConfigIdOrSlug === app.id || initConfigIdOrSlug === app.slug) { selectAppButton(app.slug); createForm(app); formAlreadyCreated = true; } }); if (initConfigIdOrSlug === null) { if (!formAlreadyCreated) { createForm(recommendationAppsConfigs['data'][0]); } if (recommendationAppsConfigs['data'].length === 0) { return; } selectAppButton(recommendationAppsConfigs['data'][0].slug) } else { if (!formAlreadyCreated) { addButtonAppNotUsedYet(initConfigIdOrSlug); } } } function createForm(config) { if (!formAppFirstQuestion) { return false; } activeAppConfig = config; addParamToUrlSilent('slugOrId', config.slug); while (formAppFirstQuestion.firstChild) { formAppFirstQuestion.removeChild(formAppFirstQuestion.firstChild); } while (formAppAdditionalQuestions.firstChild) { formAppAdditionalQuestions.removeChild(formAppAdditionalQuestions.firstChild); } let input; let countElm = 0; const uuid = getParameterByName('formLoadTaskBYUuid'); if (uuid) { document.getElementById('partiallyTaskUuid').value = uuid; } if (!config) { return; } config.questions.forEach((element, index) => { if (config.isStepByStep) { let step = getParameterByName('step'); if (step < 0) { step = 0; } if ((step - 1) >= config.questions.length) { step = 0; addParamToUrlSilent('step', step); } if (index > 0 && (!step || step === '' || step === '0' || isNaN(step))) { return; } if (step > 0 && index !== step - 1) { return; } } if (!inArray(element.type, ['textarea', 'input', 'select', 'file', 'excel-viewer', 'text-to-voice', 'mic'])) { return; } switch(element.type) { case 'excel-viewer': addExcelViewerToForm(); return; case 'text-to-voice': addTextToVoiceToForm(element); return; case 'mic': addMicRecorderToForm(); return; default: break } let label = document.createElement('label'); label.textContent = element.description; label.setAttribute('for', element.name); label.classList = 'lqd-input-label flex cursor-pointer items-center gap-2 text-2xs font-medium leading-none text-label mb-3'; if (element.type === 'textarea') { input = document.createElement('textarea'); input.style.fontSize = '1.1em'; input.classList = 'lqd-input block peer w-full px-4 py-2 border border-input-border bg-input-background text-input-foreground text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring focus:ring-secondary dark:focus:ring-foreground/10 sm:text-2xs lqd-input-size-none rounded-lg' } if (element.type === 'input') { input = document.createElement('input'); input.type = 'text'; input.classList = 'lqd-input block peer w-full px-4 py-2 border border-input-border bg-input-background text-input-foreground text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring focus:ring-secondary dark:focus:ring-foreground/10 sm:text-2xs lqd-input-size-none rounded-lg' } if (element.type === 'select') { input = document.createElement('select'); if (element.selectListValues) { element.selectListValues.forEach(value => { const option = document.createElement('option'); option.value = value; option.textContent = value; input.appendChild(option); }); } input.classList = 'lqd-input block peer w-full px-4 py-2 border border-input-border bg-input-background text-input-foreground text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring focus:ring-secondary dark:focus:ring-foreground/10 sm:text-2xs lqd-input-size-none rounded-lg' } if (element.type === 'file') { input = document.createElement('input'); input.style.display = 'none'; input.name = element.name; } if (element.isRequired && element.type !== 'file') { input.required = true; } if (countElm === 0) { if (!input.name) { input.name = element.name; } input.id = element.name; input.placeholder = element.description; let inputBlock = document.createElement('div'); let br = document.createElement('br'); inputBlock.appendChild(br); inputBlock.classList = 'lqd-input-container relative w-full'; inputBlock.appendChild(input); formAppFirstQuestion.appendChild(inputBlock); } if (countElm > 0) { if (!input.name) { input.name = element.name; } input.name = element.name; input.id = element.name; input.placeholder = element.description; let inputBlock = document.createElement('div'); let br = document.createElement('br'); inputBlock.appendChild(br); inputBlock.classList = 'lqd-input-container relative w-full'; inputBlock.appendChild(label); inputBlock.appendChild(input); formAppAdditionalQuestions.appendChild(inputBlock); } if (element.inputTypeFiles) { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.name = element.name + '_files'; fileInput.accept = element.inputTypeFiles; if (element.type === 'file' && element.isRequired) { fileInput.required = true; } if (element.isMultipleFiles) { fileInput.multiple = true; fileInput.name = element.name + '_files[]'; } fileInput.id = element.name + '_files'; fileInput.style.display = 'none'; const iconLabel = document.createElement('label'); iconLabel.htmlFor = fileInput.id; iconLabel.style.cursor = 'pointer'; iconLabel.classList = 'px-6 py-3 lg:min-w-10 leading-tight rounded-full transition-all hover:bg-background/80 [&.lqd-is-active]:bg-background [&.lqd-is-active]:shadow-[0_2px_12px_hsl(0_0%_0%/10%)] '; iconLabel.title = 'Attach files'; iconLabel.innerHTML = ``; const selectFilesBlock = document.createElement('div'); selectFilesBlock.id = 'select-files-block'; let mazFileSizeKb = element.inputMaxFileSize; if (!mazFileSizeKb) { mazFileSizeKb = 2048 } fileInput.addEventListener('change', function() { const files = Array.from(fileInput.files); selectFilesBlock.innerHTML = ''; files.forEach(file => { if (file.size > mazFileSizeKb * 1024) { errorExecute(`File ${file.name} exceeds the maximum size in ${mazFileSizeKb / 1024} MB.`); fileInput.value = ''; return; } const fileInfo = document.createElement('div'); fileInfo.innerText = `${file.name} (${(file.size / 1024).toFixed(2)} КБ) `; const removeButton = document.createElement('button'); removeButton.innerHTML = ``; removeButton.onclick = function() { const newFiles = Array.from(fileInput.files).filter(f => f.name !== file.name); const dataTransfer = new DataTransfer(); newFiles.forEach(f => dataTransfer.items.add(f)); fileInput.files = dataTransfer.files; fileInfo.remove(); }; fileInfo.appendChild(removeButton); selectFilesBlock.appendChild(fileInfo); }); }); input.parentNode.insertBefore(selectFilesBlock, input); input.parentNode.insertBefore(fileInput, input); const wrapperDiv = document.createElement('ul'); wrapperDiv.classList = 'mb-2 inline-flex justify-between gap-3 rounded-full bg-foreground/10 p-0 text-xs font-medium'; wrapperDiv.appendChild(iconLabel); if ( navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia && /\.(mp4|webm|ogg|avi|mov)$/i.test(element.inputTypeFiles) ) { const screenRecorder = document.createElement('div'); screenRecorder.id = 'screen-recorder-block'; screenRecorder.innerHTML = ``; screenRecorder.style.cursor = 'pointer'; screenRecorder.onclick = () => { startRecordScreen(fileInput.id); }; screenRecorder.classList = 'px-6 py-3 lg:min-w-10 leading-tight rounded-full transition-all hover:bg-background/80 [&.lqd-is-active]:bg-background [&.lqd-is-active]:shadow-[0_2px_12px_hsl(0_0%_0%/10%)] '; wrapperDiv.appendChild(screenRecorder); } input.parentNode.insertBefore(wrapperDiv, fileInput.nextSibling); } countElm++; }); mainBtn.innerHTML = config.btn_main_action; mainBtn.style.visibility = 'visible'; if (additionalOptions) { additionalOptions.style.visibility = 'visible'; } const form = document.getElementById("app_form"); form.style.height = 'auto'; const textareas = form.querySelectorAll("textarea"); const selects = form.querySelectorAll("select"); const textInputs = form.querySelectorAll("input[type='text']"); const textNumber = form.querySelectorAll("input[type='number']"); const textCheckBox = form.querySelectorAll("input[type='checkbox']"); const eventHandlers = []; eventHandlers.forEach(({ textarea, inputHandler, keydownHandler }) => { textarea.removeEventListener("input", inputHandler); textarea.removeEventListener("keydown", keydownHandler); }); textInputs.forEach(input => { let valueFromParamUrl = getParameterByName(input.name); if (valueFromParamUrl) { input.value = valueFromParamUrl; return; } let savedText = localStorage.getItem(input.name); if (savedText) { input.value = savedText; } }); textNumber.forEach(input => { let savedText = localStorage.getItem(input.name); if (savedText) { input.value = savedText; } }); textCheckBox.forEach(input => { let savedText = localStorage.getItem(input.name); if (!savedText) { return; } if (savedText == 'true') { input.checked = true; } if (savedText == 'false') { input.checked = false; } }); textareas.forEach(textarea => { const inputHandler = function() { if (this.scrollHeight < 500) { this.style.height = 'auto'; this.style.height = this.scrollHeight + 'px'; localStorage.setItem(`textarea-height-${this.name}`, this.scrollHeight); } addParamToUrlSilent(this.name, this.value); localStorage.setItem(`textarea-content-${this.name}`, this.value); }; textarea.addEventListener("input", inputHandler); const keydownHandler = function(event) { if (event.ctrlKey && event.key === "Enter") { event.preventDefault(); run(); } }; textarea.addEventListener("keydown", keydownHandler); eventHandlers.push({ textarea, inputHandler, keydownHandler }); let savedHeightTexArea = localStorage.getItem(`textarea-height-${textarea.id}`); if (savedHeightTexArea) { textarea.style.height = savedHeightTexArea + 'px'; } let savedText = localStorage.getItem(`textarea-content-${textarea.name}`); let valueFromParamUrl = getParameterByName(textarea.name); if (valueFromParamUrl) { textarea.value = valueFromParamUrl; return; } if (savedText) { textarea.value = savedText; } }); selects.forEach(select => { const changeHandler = function() { localStorage.setItem(`select-value-${this.name}`, this.value); }; select.addEventListener("change", changeHandler); let valueFromParamUrl = getParameterByName(select.name); if (valueFromParamUrl) { select.value = valueFromParamUrl; return; } let savedSelectValue = localStorage.getItem(`select-value-${select.name}`); if (savedSelectValue) { select.value = savedSelectValue; } }); trackFormChanges('app_form'); calculateData(); } function startRecordScreen(fileAttachInputId) { let mediaRecorder; let chunks = []; if (mediaRecorder && mediaRecorder.state === "recording") { mediaRecorder.stop(); toastr.success('Recording stopped'); return; } if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { navigator.mediaDevices.getDisplayMedia({ video: true }) .then(stream => { mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = event => { chunks.push(event.data); }; mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'screen-recording.webm'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); const fileInput = document.getElementById(fileAttachInputId); const file = new File([blob], 'screen-recording.webm', { type: 'video/webm' }); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; const event = new Event('change', { bubbles: true }); fileInput.dispatchEvent(event); chunks = []; }; mediaRecorder.start(); toastr.success('Recording has started'); }) .catch(err => { toastr.error('Screen Access Error'); console.error("Screen Access Error: ", err); }); } else { toastr.warning("Sorry, your browser does not support screen recording."); } } function addMicRecorderToForm() { const micContainer = document.createElement('div'); micContainer.style.margin = "15px"; const startBtn = document.createElement('button'); startBtn.type = 'button'; startBtn.classList = `mr-2 text-lg float-left app_btn_not_use_yet app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none lqd-btn-primary bg-primary text-primary-foreground`; const stopBtn = document.createElement('button'); stopBtn.type = 'button'; stopBtn.classList = `mr-2 text-lg float-left app_btn_not_use_yet app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none lqd-btn-primary bg-primary text-primary-foreground`; const clearBtn = document.createElement('button'); clearBtn.type = 'button'; clearBtn.style.display = 'none'; clearBtn.classList = `mr-2 text-lg float-left app_btn_not_use_yet app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none lqd-btn-primary bg-primary text-primary-foreground`; const audioWaveForm = document.createElement('span'); audioWaveForm.innerHTML = ``; startBtn.innerHTML = ``; stopBtn.innerHTML = ``; clearBtn.innerHTML = ``; stopBtn.style.display = 'none'; micContainer.appendChild(clearBtn); micContainer.appendChild(startBtn); micContainer.appendChild(stopBtn); micContainer.appendChild(audioWaveForm); formAppFirstQuestion.appendChild(micContainer); let audioElement = document.getElementById('record-data-audio'); let mediaRecorder; let audioChunks = []; const MAX_AUDIO_SIZE = 5 * 1024 * 1024; startBtn.addEventListener('click', async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); mediaRecorder.start(); startBtn.style.display = 'none'; stopBtn.style.display = 'block'; clearBtn.style.display = 'none'; stopBtn.style.animation = 'blinking 1s infinite'; mediaRecorder.addEventListener('dataavailable', event => { audioChunks.push(event.data); }); mediaRecorder.addEventListener('stop', () => { setTimeout(() => { clearBtn.style.display = 'block'; startBtn.style.display = 'block'; stopBtn.style.display = 'none'; const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); const audioUrl = URL.createObjectURL(audioBlob); audioElement.setAttribute('data-audio', audioUrl); audioElement.style.visibility = 'visible'; generateWaveForm(audioElement); const file = new File([audioBlob], "recording.wav", { type: 'audio/wav' }); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); document.getElementById('voice-file').files = dataTransfer.files; audioChunks = []; }, 1000); }); }); stopBtn.addEventListener('click', () => { mediaRecorder.stop(); startBtn.style.display = 'block'; stopBtn.style.display = 'none'; }); clearBtn.addEventListener('click', () => { startBtn.style.display = 'block'; stopBtn.style.display = 'none'; clearBtn.style.display = 'none'; document.getElementById('voice-file').value = ''; audioChunks = []; audioElement.setAttribute('data-audio', ''); audioElement.style.visibility = 'hidden'; generateWaveForm(audioElement); }); } function getParameterByName(name) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(name); } function trackFormChanges(formId) { const form = document.getElementById(formId); const elements = form.elements; for (let element of elements) { element.addEventListener('input', function() { if (element.type === 'checkbox') { localStorage.setItem(element.name, element.checked); } else { localStorage.setItem(element.name, element.value); } addParamToUrlSilent(this.name, this.value); if ( element.tagName !== 'SELECT' && element.type !== 'range' && element.id !== "workbook_title" && element.type !== 'file' ) { calculateCharacters(this) } }); if (element.tagName.toLowerCase() === 'textarea') { const events = ['focus', 'blur']; events.forEach(event => { element.addEventListener(event, function() { localStorage.setItem(element.name + '_height', this.clientHeight); }); }); } if (element.name !== 'excelfile' && element.name === 'range') { if (localStorage.getItem(element.name)) { element.value = localStorage.getItem(element.name); } } if (localStorage.getItem(element.name + '_height')) { element.style.height = localStorage.getItem(element.name + '_height')+'px'; } } } function calculateData() { const inputs = document.querySelectorAll('#app_form input[type="text"], #app_form textarea'); const filteredInputs = Array.from(inputs).filter(input => input.closest('#app_params') ); filteredInputs.forEach(input => { if (input.id === 'workbook_title') { return; } calculateCharacters(input); }); } function calculateCharacters(elm) { if (!elm.closest('#app_params')) { return; } let charCountDiv = elm.nextElementSibling; if (!charCountDiv || !charCountDiv.classList.contains('char-count-group')) { charCountDiv = document.createElement('div'); charCountDiv.classList = 'char-count-group mt-2'; const clearButton = document.createElement('button'); clearButton.type = 'button'; clearButton.innerHTML = ` `; clearButton.addEventListener('click', () => { elm.value = ''; charCountDiv.style.display = 'none'; if (localStorage.getItem(elm.name)) { localStorage.removeItem(elm.name); } if (localStorage.getItem('textarea-content-'+elm.name)) { localStorage.removeItem('textarea-content-'+elm.name); } }); const charCountDisplay = document.createElement('span'); charCountDisplay.classList.add('char-count'); charCountDisplay.classList.add('text-xs'); charCountDisplay.classList.add('text-foreground/70'); charCountDiv.appendChild(clearButton); charCountDiv.appendChild(charCountDisplay); elm.parentNode.insertBefore(charCountDiv, elm.nextSibling); } const charCount = elm.value.length; const charCountGroup = elm.nextElementSibling; if (charCount > 0) { charCountGroup.style.display = 'flex'; charCountGroup.querySelector('.char-count').textContent = `Characters: ${charCount}`; } else { charCountGroup.style.display = 'none'; } } document.getElementById('app_form').addEventListener('submit', async function(event) { event.preventDefault(); run(); }); async function run() { hideHumanMessage(); Alpine.store('appLoadingIndicator').show(); const form = document.getElementById("app_form"); const formData = new FormData(form); let url = 'https://aisearch.tech/api/v3/app/_rewrite_/execute?loc=en'; url = url.replace('_rewrite_', activeAppConfig.slug); const groupTypeCheckTaskStatus = [ 'excel-processing', 'file', 'VOICE_TO_TEXT', 'IMAGE-OCR', 'CLONE-VOICE', 'SCREENSHOT-MAKE', 'SOUND_EFFECT', ]; if (inArray(activeAppConfig.type, groupTypeCheckTaskStatus)) { try { const response = await fetch(url, { method: 'POST', body: formData, }); const result = await response.json(); if (result.result) { const taskUuid = result.uuid; await checkTaskStatus(taskUuid); } else { errorExecute(result.message); } } catch (error) { errorExecute(error.message); } return; } if (activeAppConfig.type === 'TEXT-TO-VOICE') { const validClientData = { speechIds: {}, }; validClientData['speechId'] = null; const speechItems = document.querySelectorAll('.speech-item'); speechItems.forEach(item => { let textToVoice = item.querySelector('textarea[name="text-to-voice[]"]'); let voiceId = item.querySelector('select[name="speakers[]"]'); let lang = item.querySelector('select[name="lang[]"]'); let speechId = item.querySelector('input[name="speechId[]"]'); let fileVideoToVoiceOver = item.querySelector('input[name="fileVideoToVoice[]"]').files[0]; validClientData.speechIds[speechId.value] = { lang: lang.value, speaker: voiceId.value, 'text-to-voice': textToVoice.value, 'fileVideoToVoice': fileVideoToVoiceOver }; }); const partiallyTaskUuid = document.getElementById('partiallyTaskUuid').value; const formData = new FormData(); formData.append('partiallyTaskUuid', partiallyTaskUuid); formData.append('speechId', validClientData.speechId); for (const [key, value] of Object.entries(validClientData.speechIds)) { formData.append(`speechIds[${key}][lang]`, value.lang); formData.append(`speechIds[${key}][speaker]`, value.speaker); formData.append(`speechIds[${key}][text-to-voice]`, value['text-to-voice']); if (value['fileVideoToVoice']) { formData.append(`speechIds[${key}][fileVideoToVoice]`, value['fileVideoToVoice']); } } try { const response = await fetch(url, { method: 'POST', body: formData, }); const result = await response.json(); if (result.result) { const taskUuid = result.uuid; await checkTaskStatus(taskUuid); } else { errorExecute(result.message) } } catch (error) { toastr.error('Error sending POST request:', error); Alpine.store('appLoadingIndicator').hide(); } return; } if (activeAppConfig.type === 'SEARCH-MEDIA') { const template = document.getElementById('template_type_media_gallery'); const templateClone = template.content.cloneNode(true); resultMediaGalleryBlock.innerHTML = ''; resultMediaGalleryBlock.appendChild(templateClone); formData.append('stream', true); fetch(url, { method: 'POST', body: formData, headers: { 'enctype': 'multipart/form-data' } }).then(response => { if (!response.ok) { return response.json().then(errorData => { throw new Error(`${errorData.message}`); }); } const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); const processChunk = async () => { const {done, value } = await reader.read(); if (done) { Alpine.store('appLoadingIndicator').hide(); return; } const chunk = decoder.decode(value, { stream: true }); const messages = chunk.split('\n').filter(line => line); messages.forEach(message => { try { const jsonData = JSON.parse(message.replace(/^data: /, '')); if (jsonData.type === 'start') { } if (jsonData.type === 'image') { addItemToMediaGallery(jsonData); } if (jsonData.type === 'stop') { } } catch (e) { } }); await processChunk(); }; processChunk(); }).catch(error => { errorExecute(error.message) }); } if (activeAppConfig.presentation_result === 'text_editor') { formData.append('stream', true); const clone = document.importNode(template_type_text.content, true); let requestTitle = clone.querySelector('.request_title'); let requestDateTime = clone.querySelector('.request_date_time'); let requestResultSearch = clone.querySelector('.result-search'); let result = "One moment"; let resultAnswer = clone.querySelector('.result_answer'); resultAnswer.textContent = result; fetch(url, { method: 'POST', body: formData, headers: { 'enctype': 'multipart/form-data' } }).then(response => { if (!response.ok) { return response.json().then(errorData => { throw new Error(`${errorData.message}`); }); } const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); resultAnswer.textContent = ""; let accumulateContent = ''; const processChunk = async () => { const {done, value } = await reader.read(); if (done) { toastr.success('Task accomplished'); Alpine.store('appLoadingIndicator').hide(); window.location.hash = 'result'; return; } resultBlock.insertBefore(clone, resultBlock.firstChild); const chunk = decoder.decode(value, { stream: true }); const messages = chunk.split('\n').filter(line => line); messages.forEach(message => { try { const jsonData = JSON.parse(message.replace(/^data: /, '')); if (jsonData.type === 'start') { requestTitle.innerHTML = jsonData.data.title; } if (jsonData.type === 'search_result') { if (jsonData.data.result.organic.length > 0) { prepareResultSearchBlock(requestResultSearch, jsonData.data.result.organic); } } if (jsonData.type === 'data') { accumulateContent += jsonData.data; resultAnswer.innerHTML = convertMarkdownToHtml(accumulateContent); highlightCode(resultAnswer) } if (jsonData.type === 'stop') { requestDateTime.innerHTML = convertToLocalDateTime(jsonData.data.created_at); if (authCheck) { createChatWndButton(jsonData.data, resultBlock); reloadTask(jsonData.data, resultBlock); } } } catch (e) { } }); await processChunk(); }; processChunk(); }).catch(error => { errorExecute(error.message) }); } } function hideHumanMessage(){ messageFormForHuman.style.visibility = 'hidden'; messageFormForHuman.style.height = '1px;'; let humanMessage = messageFormForHuman.querySelector('#humanMessage'); humanMessage.innerHTML = ''; } function errorExecute(error = null) { messageFormForHuman.style.visibility = 'visible'; messageFormForHuman.style.height = 'auto'; messageFormForHuman.classList.add('highlight'); let humanMessage = messageFormForHuman.querySelector('#humanMessage'); if (error && error.startsWith("Error: ")) { error = error.slice(7); } try { const parsedError = JSON.parse(error); let messages = []; for (const key in parsedError) { if (parsedError.hasOwnProperty(key) && Array.isArray(parsedError[key])) { messages.push(...parsedError[key]); toastr.error(parsedError[key]); } } humanMessage.innerHTML = messages.join('
'); } catch (e) { humanMessage.innerHTML = error; toastr.error(error); } Alpine.store('appLoadingIndicator').hide(); } let currentIndexColumnMediaGallery = 0; let routeSrcVendorHash = 'https://aisearch.tech/api/v3/user/download/file/proxy'; function addItemToMediaGallery(item) { const mediaGallery = document.querySelector('.media-galley-source-grid'); const columnCount = getColumnCount(mediaGallery); for (let i = 0; i < columnCount; i++) { if (!mediaGallery.querySelector(`.resultSearch:nth-child(${i + 1})`)) { const resultBlockDiv = document.createElement('div'); resultBlockDiv.classList.add('resultSearch', 'border-card-border'); resultBlockDiv.style.display = 'block'; mediaGallery.appendChild(resultBlockDiv); } } const resultElements = mediaGallery.querySelectorAll('.resultSearch'); if (currentIndexColumnMediaGallery < resultElements.length) { const itemPicSourceDiv = document.createElement('div'); itemPicSourceDiv.classList.add('item-pic-source'); itemPicSourceDiv.style.marginBottom = '4px'; const itemImage = document.createElement('img'); const columnWidth = resultElements[currentIndexColumnMediaGallery].offsetWidth; let newResolutions = calculateProportions(item.width, item.height, columnWidth); itemImage.width = columnWidth; itemImage.height = newResolutions.height; itemImage.src = `${routeSrcVendorHash}?hash=${item.vendor_url_to_file_hash}&width=${columnWidth}`; itemImage.alt = item.name; itemPicSourceDiv.appendChild(itemImage); resultElements[currentIndexColumnMediaGallery].appendChild(itemPicSourceDiv); currentIndexColumnMediaGallery++; } else { currentIndexColumnMediaGallery = 0; } } function getColumnCount(gridElm) { const styles = getComputedStyle(gridElm); const columnCount = styles.gridTemplateColumns.split(' ').length; return columnCount; } function calculateProportions(originalWidth, originalHeight, newWidth = null, newHeight = null) { if (newWidth !== null) { newHeight = (originalHeight / originalWidth) * newWidth; } else if (newHeight !== null) { newWidth = (originalWidth / originalHeight) * newHeight; } return { width: newWidth.toFixed(), height: newHeight.toFixed() }; } async function checkTaskStatus(taskUuid) { let checkUrl = 'https://aisearch.tech/api/v3/app/task/__uuid__/result'; checkUrl = checkUrl.replace('__uuid__', taskUuid); let hasProcessed = false; const intervalId = setInterval(async () => { try { const response = await fetch(checkUrl); const result = await response.json(); if (result.result) { const status = result.data.status; if (!hasProcessed && ( status === 2 || status === 4 ) ) { hasProcessed = true; clearInterval(intervalId); selectorViewTask(result.data, false); allImagesPreview(); toastr.success('Task accomplished'); window.location.hash = 'result'; Alpine.store('appLoadingIndicator').hide(); } if ( status === 3 && !hasProcessed ) { hasProcessed = true; clearInterval(intervalId); toastr.error('The task failed with an error'); Alpine.store('appLoadingIndicator').hide(); } } else { toastr.error('Error checking task status.'); clearInterval(intervalId); Alpine.store('appLoadingIndicator').hide(); } } catch (error) { toastr.error('Error sending GET request to check status:' + error); Alpine.store('appLoadingIndicator').hide(); } }, 500); } function selectAppButton(appSlug) { hideHumanMessage(); let btnId = 'app_btn_' + appSlug; localStorage.setItem('initConfigIdOrSlug', appSlug); const app_buttons = document.querySelectorAll('.app_btn'); app_buttons.forEach(button => { button.style.fontSize = '14px'; button.style.fontWeight = 'normal'; button.classList.remove('lqd-btn-primary', 'bg-primary', 'text-primary-foreground'); }); document.getElementById(btnId).style.fontSize = '22px'; document.getElementById(btnId).style.fontWeight = 'bolder'; document.getElementById(btnId).classList.add('lqd-btn-primary', 'bg-primary', 'text-primary-foreground'); } function inArray(needle, haystack) { return haystack.includes(needle); } function convertToLocalDateTime(isoString) { const date = new Date(isoString); const localDateTime = date.toLocaleString(); return localDateTime; } function convertMarkdownToHtml(markdownString) { let result = markdownString; try { result = markDownConverter.makeHtml(markdownString); const languageMatch = result.match(//); const language = languageMatch ? languageMatch[1] : 'plaintext'; return result.replace(/
/g, `
`); } catch (err) { } return markdownString; } let configThisItem = null; function addTextToVoiceToForm(element) { configThisItem = element; const textToVoiceSpeechesTemplate = document.getElementById('text-to-voice'); const textToVoiceSpeechesTemplateToForm = document.importNode(textToVoiceSpeechesTemplate.content, true); formAppFirstQuestion.appendChild(textToVoiceSpeechesTemplateToForm); const button = document.querySelector('.add-new-speech'); button.addEventListener('click', addNewSpeech); initArrowUpDownSpeaches(); loadSpeechesFromLocalStorage(); } function addNewSpeech() { const textToVoiceSpeechTemplate = document.getElementById('text-to-voice-speeches'); const textToVoiceSpeechTemplateToForm = document.importNode(textToVoiceSpeechTemplate.content, true); const speechesBlock = document.querySelector('#speeches'); const uniqueSpeechId = generateUniqueId(); if (configThisItem.inputTypeFiles) { const speechVideoBlock = textToVoiceSpeechTemplateToForm.querySelector('.video-upload'); speechVideoBlock.style.display = 'block'; const speechVideoInput = speechVideoBlock.querySelector('.video-input'); speechVideoInput.accept = configThisItem.inputTypeFiles; speechVideoInput.addEventListener('change', function(event) { const currentSpeechItem = speechVideoInput.closest('.speech-item'); const videoPreview = currentSpeechItem.querySelector('.video-preview'); const describeVideo = currentSpeechItem.querySelector('.describe-video'); const file = event.target.files[0]; if (file) { videoPreview.src = URL.createObjectURL(file); videoPreview.style.display = 'block'; describeVideo.style.display = 'block'; } const createSpeechFromFile = currentSpeechItem.querySelector('.create-speech-from-file'); const promptSpeechFromFile = currentSpeechItem.querySelector('.describe-file'); const promptSpeechTextToVoice = currentSpeechItem.querySelector('.text-to-voice'); promptSpeechFromFile.focus(); createSpeechFromFile.addEventListener('click', async function (event) { event.preventDefault(); const lang = currentSpeechItem.querySelector('select[name="lang[]"]'); if (!lang.value) { toastr.warning('Lang must be required'); promptSpeechFromFile.focus(); return; } let prompt = promptSpeechFromFile.value; if (!prompt) { toastr.warning('Prompt must be required'); promptSpeechFromFile.focus(); return; } createSpeechFromFile.innerText = 'Please wait.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = true; let url = 'https://aisearch.tech/api/v3/app/any-task/execute'; const formData = new FormData(); formData.append('stream', true); formData.append('user-prompt_files', file); formData.append('user-prompt', prompt); formData.append('opt_select_lang', lang.value); fetch(url, { method: 'POST', body: formData, headers: { 'enctype': 'multipart/form-data' } }).then(response => { if (!response.ok) { return response.json().then(errorData => { throw new Error(`${errorData.message}`); }); } const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); const processChunk = async () => { const {done, value } = await reader.read(); if (done) { toastr.success('Task accomplished'); Alpine.store('appLoadingIndicator').hide(); createSpeechFromFile.innerText = 'Redo it.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = false; return; } const chunk = decoder.decode(value, { stream: true }); const messages = chunk.split('\n').filter(line => line); messages.forEach(message => { try { const jsonData = JSON.parse(message.replace(/^data: /, '')); if (jsonData.type === 'start') { } if (jsonData.type === 'search_result') { if (jsonData.data.result.organic.length > 0) { } } if (jsonData.type === 'data') { promptSpeechTextToVoice.value += jsonData.data; } if (jsonData.type === 'stop') { } } catch (e) { } }); await processChunk(); }; processChunk(); }).catch(error => { toastr.warning(error.message); createSpeechFromFile.innerText = 'Repeat.'; createSpeechFromFile.style.color = 'black'; createSpeechFromFile.disabled = false; }); }); }); if ( navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia ) { const speechVideoScreenRecord = speechVideoBlock.querySelector('.video-screen-record'); speechVideoScreenRecord.style.display = 'block'; speechVideoScreenRecord.addEventListener('click', function(event) { let mediaRecorder; let chunks = []; if (mediaRecorder && mediaRecorder.state === "recording") { mediaRecorder.stop(); toastr.success('Recording stopped'); return; } if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { navigator.mediaDevices.getDisplayMedia({ video: true }) .then(stream => { mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = event => { chunks.push(event.data); }; mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = 'screen-recording.webm'; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); const file = new File([blob], 'screen-recording.webm', { type: 'video/webm' }); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); speechVideoInput.files = dataTransfer.files; const event = new Event('change', { bubbles: true }); speechVideoInput.dispatchEvent(event); chunks = []; }; mediaRecorder.start(); toastr.success('Recording has started'); }) .catch(err => { toastr.error('Screen Access Error'); console.error("Screen Access Error: ", err); }); } else { console.log("Sorry, your browser does not support screen recording."); } }); } } const speechIdInput = textToVoiceSpeechTemplateToForm.querySelector('.speech-id'); if (speechIdInput) { speechIdInput.value = uniqueSpeechId; } const buttonsPreviewSpeech = textToVoiceSpeechTemplateToForm.querySelector('.preview-speech'); const buttonsDeleteSpeech = textToVoiceSpeechTemplateToForm.querySelector('.delete-speech'); const buttonsVoiceExample = textToVoiceSpeechTemplateToForm.querySelector('.voice-example'); loadTextToVoiceDict(textToVoiceSpeechTemplateToForm); speechesBlock.appendChild(textToVoiceSpeechTemplateToForm); initArrowUpDownSpeaches(); saveSpeechesToLocalStorage(); buttonsDeleteSpeech.addEventListener('click', function() { const speechItem = buttonsDeleteSpeech.closest('.speech-item'); if (speechItem) { speechItem.remove(); saveSpeechesToLocalStorage(); } }); buttonsVoiceExample.addEventListener('click', function() { const speechItem = buttonsVoiceExample.closest('.speech-item'); const selectElement = speechItem.querySelector('select[name="speakers[]"]'); const selectedValue = selectElement ? selectElement.value : null; let routeExample = 'https://aisearch.tech/api/v3/app/directory/text-to-voice/examples/download/__voiceId__'; routeExample = routeExample.replace('__voiceId__', selectedValue); if (selectedValue) { fetch(routeExample) .then(response => { if (response.ok) { return response.blob(); } throw new Error('Network error'); }) .then(blob => { const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play(); }) .catch(error => { toastr.error('This speaker's sample file was not found, we are already aware of this and will fix it soon.:', error); }); } else { toastr.warning('Please select speaker'); selectElement.focus(); } }); buttonsPreviewSpeech.addEventListener('click', function() { previewSpeechRun(buttonsPreviewSpeech); }); const textAreas = document.querySelectorAll('textarea[name="text-to-voice[]"]'); textAreas.forEach(textArea => { const uploadButton = document.createElement('button'); uploadButton.innerHTML = ``; uploadButton.style.marginTop = '-40px'; uploadButton.style.position = 'absolute'; uploadButton.style.right = '0'; uploadButton.type = 'button'; uploadButton.addEventListener('click', () => { const inputFile = document.createElement('input'); inputFile.type = 'file'; inputFile.accept = '.txt, .doc, .docx'; inputFile.addEventListener('change', handleFileSelectToTextArea(textArea)); inputFile.click(); return; }); textArea.parentNode.append(uploadButton); }); trackFormChanges('app_form'); return buttonsDeleteSpeech.closest('.speech-item'); } function previewSpeechRun(buttonsPreviewSpeech = null) { if (buttonsPreviewSpeech === null) { return; } let partiallyTaskUuid = document.getElementById('partiallyTaskUuid').value; const currentSpeechItem = buttonsPreviewSpeech.closest('.speech-item'); const speechesBlock = buttonsPreviewSpeech.closest('#speeches'); const speechItems = speechesBlock.querySelectorAll('.speech-item'); const currentSpeechId = currentSpeechItem.querySelector('.speech-id').value; const validClientData = { speechIds: {}, }; if (currentSpeechId) { validClientData['speechId'] = currentSpeechId; } if (partiallyTaskUuid !== '') { validClientData['partiallyTaskUuid'] = partiallyTaskUuid; } speechItems.forEach(item => { let textToVoice = item.querySelector('textarea[name="text-to-voice[]"]'); let voiceId = item.querySelector('select[name="speakers[]"]'); let lang = item.querySelector('select[name="lang[]"]'); let speechId = item.querySelector('input[name="speechId[]"]'); let fileVideoToVoiceOver = item.querySelector('input[name="fileVideoToVoice[]"]').files[0]; validClientData.speechIds[speechId.value] = { lang: lang.value, speaker: voiceId.value, 'text-to-voice': textToVoice.value, 'fileVideoToVoice': fileVideoToVoiceOver }; }); const formData = new FormData(); formData.append('partiallyTaskUuid', validClientData.partiallyTaskUuid); formData.append('speechId', validClientData.speechId); for (const [key, value] of Object.entries(validClientData.speechIds)) { formData.append(`speechIds[${key}][lang]`, value.lang); formData.append(`speechIds[${key}][speaker]`, value.speaker); formData.append(`speechIds[${key}][text-to-voice]`, value['text-to-voice']); if (value['fileVideoToVoice']) { formData.append(`speechIds[${key}][fileVideoToVoice]`, value['fileVideoToVoice']); } } let url = 'https://aisearch.tech/api/v3/app/_rewrite_/execute'; url = url.replace('_rewrite_', activeAppConfig.slug); startPreviewSpeechItem(buttonsPreviewSpeech); fetch(url, { method: 'POST', headers: { 'enctype': 'multipart/form-data' }, body: formData }) .then(response => response.json()) .then(async data => { if (!data.result) { toastr.error(data.message); finishPreviewSpeechItem(buttonsPreviewSpeech); } if (data.result) { const taskUuid = data.uuid; document.getElementById('partiallyTaskUuid').value = taskUuid; addParamToUrlSilent('formLoadTaskBYUuid', taskUuid); await getResultPreviewSpeech(taskUuid, buttonsPreviewSpeech); } finishPreviewSpeechItem(buttonsPreviewSpeech); }) .catch((error) => { toastr.error(error); finishPreviewSpeechItem(buttonsPreviewSpeech); }); } async function getResultPreviewSpeech(taskUuid = null, buttonsPreviewSpeech = null) { let checkUrl = 'https://aisearch.tech/api/v3/app/task/__uuid__/result'; checkUrl = checkUrl.replace('__uuid__', taskUuid); let hasProcessed = false; const intervalId = setInterval(async () => { try { const response = await fetch(checkUrl); const result = await response.json(); if (result.result) { let status = result.data.status; if ( status === 2 || 4 ) { hasProcessed = true; clearInterval(intervalId); loadDataToFormTextToVoice(result, buttonsPreviewSpeech); Alpine.store('appLoadingIndicator').hide(); } if (status === 3) { hasProcessed = true; clearInterval(intervalId); Alpine.store('appLoadingIndicator').hide(); toastr.error('The task failed with an error'); } } else { toastr.error('Error checking task status.'); clearInterval(intervalId); Alpine.store('appLoadingIndicator').hide(); } } catch (error) { toastr.error('Error sending GET request to check status:' + error); Alpine.store('appLoadingIndicator').hide(); } }, 500); } function loadDataToFormTextToVoice(result, buttonsPreviewSpeech = null) { let task = result.data; let out = result.data.output.speechIds; let speechId = null; if (buttonsPreviewSpeech) { const speechItem = buttonsPreviewSpeech.closest('.speech-item'); speechId = speechItem.querySelector('.speech-id').value; let speechIdNewFile = null; if ((speechIdNewFile = out[speechId]['file']['name'])) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); if (out[speechId]['fileVideo']['name']) { let routeDownloadVideo = routeDownload.replace('__name__', out[speechId]['fileVideo']['name']); const speechItemDataVideo = speechItem.querySelector('.video-output'); speechItemDataVideo.style.display = 'block'; const speechItemDataVideoPreviewSpeech = speechItem.querySelector('.video-preview-speech'); speechItemDataVideoPreviewSpeech.src = routeDownloadVideo; } routeDownload = routeDownload.replace('__name__', speechIdNewFile); const speechItemDataAudio = speechItem.querySelector('.data-audio'); speechItemDataAudio.setAttribute('data-audio', routeDownload); speechItemDataAudio.style.visibility = 'visible'; generateWaveForm(speechItemDataAudio) } return; } for (let key in out) { if (out.hasOwnProperty(key)) { let speechItem = addNewSpeech(); const speechItemTextToVoice = speechItem.querySelector('.text-to-voice'); speechItemTextToVoice.value = out[key]['text-to-voice']; const speechItemId = speechItem.querySelector('.speech-id'); speechItemId.value = key; const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (out[key]['voice_id']) { const optionExists = Array.from(selectSpeakers.options).some(option => option.value === out[key]['voice_id']); if (optionExists) { selectSpeakers.value = out[key]['voice_id']; } } if (out[key]['file']['name']) { let routeDownload = 'https://aisearch.tech/api/v3/user/task/__uuid__/file/__name__'; routeDownload = routeDownload.replace('__uuid__', task.uuid); if (out[key]['fileVideo']['name']) { let routeDownloadVideo = routeDownload.replace('__name__', out[key]['fileVideo']['name']); const speechItemDataVideo = speechItem.querySelector('.video-output'); speechItemDataVideo.style.display = 'block'; const speechItemDataVideoPreviewSpeech = speechItem.querySelector('.video-preview-speech'); speechItemDataVideoPreviewSpeech.src = routeDownloadVideo; } routeDownload = routeDownload.replace('__name__', out[key]['file']['name']); const speechItemDataAudio = speechItem.querySelector('.data-audio'); speechItemDataAudio.setAttribute('data-audio', routeDownload); speechItemDataAudio.style.visibility = 'visible'; generateWaveForm(speechItemDataAudio) } } } } function handleFileSelectToTextArea(textArea) { return function(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { const contents = e.target.result; if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || file.type === 'application/msword') { mammoth.convertToHtml({arrayBuffer: contents}) .then(function(result) { if (result.value) { textArea.value = result.value; } else { toastr.error('The file is empty or contains invalid content..'); } }) .catch(function(err) { toastr.error('Error during conversion: ' + err.message); }); } else { try { const textContent = new TextDecoder().decode(contents); textArea.value = textContent; } catch (error) { toastr.error('Error reading text content: ' + error.message); } } calculateData(); }; reader.readAsArrayBuffer(file); }; } function generateWaveForm(el) { let audioUrl = el.getAttribute( 'data-audio' ); let container = el.querySelector( '.audio-preview' ); let playButton = el.querySelector( 'button' ); let timeData = el.querySelector( 'span' ); let volumeControl = el.querySelector( '#volume' ); let downloadButton = el.querySelector( '.download-button' ); if ( !audioUrl || audioUrl === '' ) { return; } if (el.waveform) { el.waveform.destroy(); } while ( container.firstElementChild ) { container.firstElementChild.remove(); } let waveform = WaveSurfer.create( { container: container, waveColor: '#bcbac8', progressColor: '#320580', cursorWidth: 0, barWidth: 1, interact: true, autoCenter: false, hideScrollbar: true, height: 22, }); el.waveform = waveform; waveform.load( audioUrl ); waveform.on( 'ready', function () { let duration = waveform.getDuration(); timeData.textContent = formatTime( duration ); downloadButton.href = audioUrl; } ); waveform.on( 'audioprocess', function () { let currentTime = waveform.getCurrentTime(); timeData.textContent = formatTime( currentTime ); } ); waveform.on( 'play', function () { playButton.classList.add( 'is-playing' ); } ); waveform.on( 'pause', function () { playButton.classList.remove( 'is-playing' ); } ); playButton.addEventListener( 'click', function () { waveform.playPause(); } ); volumeControl.addEventListener('input', function() { waveform.setVolume(this.value / 100); }); } async function loadTextToVoiceDict(speechItem = null) { if (speechItem === null) { return; } const speechItemOptions = speechItem.querySelector('.text-to-voice-options'); const oneHour = 60 * 60 * 1000; const currentTime = Date.now(); let textToVoiceDict = localStorage.getItem('textToVoiceDict'); let lastUpdated = localStorage.getItem('textToVoiceDictLastUpdated'); if (textToVoiceDict) { try { textToVoiceDict = JSON.parse(textToVoiceDict); lastUpdated = JSON.parse(lastUpdated); if (currentTime - lastUpdated > oneHour) { textToVoiceDict = null; localStorage.removeItem('textToVoiceDictLastUpdated'); localStorage.removeItem('textToVoiceDict'); } } catch (error) { localStorage.removeItem('textToVoiceDict'); localStorage.removeItem('textToVoiceDictLastUpdated'); textToVoiceDict = null; } } if (!textToVoiceDict) { try { const url = 'https://aisearch.tech/api/v3/app/directory/text-to-voice'; const response = await fetch(url); if (!response.ok) { throw new Error(`Ошибка: ${response.status}`); } const data = await response.json(); localStorage.setItem('textToVoiceDict', JSON.stringify(data)); localStorage.setItem('textToVoiceDictLastUpdated', JSON.stringify(currentTime)); textToVoiceDict = data; } catch (error) { toastr.error('Error loading data:', error); } } populateLanguageOptions(textToVoiceDict.data.languages, speechItemOptions); populateGenderOptions(textToVoiceDict.data.gender, speechItemOptions); populateSpeechOptions(textToVoiceDict.data.speakers, speechItemOptions); populateEmotionOptions([], speechItemOptions) } function loadSpeechesFromLocalStorage() { const formLoadTaskBYUuid = getParameterByName('formLoadTaskBYUuid'); if (!formLoadTaskBYUuid) { addNewSpeech(); return; } getResultPreviewSpeech(formLoadTaskBYUuid); } function obtainTextToVoiceDict() { let textToVoiceDict = localStorage.getItem('textToVoiceDict'); if (!textToVoiceDict) { fetch('https://aisearch.tech/api/v3/app/directory/text-to-voice') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { textToVoiceDict = JSON.stringify(data); localStorage.setItem('textToVoiceDict', JSON.stringify(data)); }) .catch(error => { toastr.error('There was a problem with the fetch operation:', error); }); } else { textToVoiceDict = JSON.parse(textToVoiceDict); const parsedData = textToVoiceDict; const lastUpdate = new Date(parsedData.last_update); const now = new Date(); const fiveMinutes = 5 * 60 * 1000; if (now - lastUpdate > fiveMinutes) { fetch('https://aisearch.tech/api/v3/app/directory/text-to-voice') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { localStorage.setItem('textToVoiceDict', JSON.stringify(data)); }) .catch(error => { toastr.error('There was a problem with the fetch operation:', error); }); } else { } } return textToVoiceDict; } function filteredSpeakers(speechItem = null) { if (speechItem === null) { return; } const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (!selectSpeakers) { return; } selectSpeakers.innerHTML = ''; selectSpeakers.name = 'speakers[]'; const langSelect = speechItem.querySelector('select[name="lang[]"]'); const genderSelect = speechItem.querySelector('select[name="gender[]"]'); if (!langSelect) { toastr.error('Element named lang not found.'); } if (!genderSelect) { toastr.error('Element named gender not found.'); } const textToVoiceDict = obtainTextToVoiceDict(); const selectGender = genderSelect.value; const selectedLang = langSelect.value; const speakers = textToVoiceDict.data.speakers; let filteredGender = true; if (selectGender === 'all') { filteredGender = false; } for (const speaker of speakers) { if ( inArray(selectedLang, speaker.lang) && (!filteredGender || selectGender === speaker.gender) ) { const option = document.createElement('option'); option.value = speaker.speaker_id; option.textContent = speaker.speaker_name + ' (' + speaker.gender + ')'; if (speaker.accent) { option.textContent += ' (' + speaker.accent + ')'; } selectSpeakers.appendChild(option); } } } function filteredVoiceEmotion(speechItem = null) { if (speechItem === null) { return; } const selectSpeakers = speechItem.querySelector('select[name="speakers[]"]'); if (!selectSpeakers) { return; } const speakerSelect = speechItem.querySelector('select[name="speakers[]"]'); const textToVoiceDict = obtainTextToVoiceDict(); const speakers = textToVoiceDict.data.speakers; const emotionSelect = speechItem.querySelector('select[name="emotion[]"]'); emotionSelect.style.display = 'none'; for (const speaker of speakers) { if (speaker.speaker_id === speakerSelect.value && speaker.emotion.length > 0) { emotionSelect.style.display = 'block'; for (const [code, name] of Object.entries(speaker.emotion)) { const option = document.createElement('option'); option.value = name; option.textContent = name; emotionSelect.appendChild(option); } } } } function populateSpeechOptions(speakers, speechItem) { if (speechItem.querySelector('select[name="speakers"]')) { return; } const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'speakers[]'; for (const [id, data] of Object.entries(speakers)) { const option = document.createElement('option'); option.value = data.speaker_id; option.textContent = data.speaker_name; if (data.gender) { option.textContent += ' (' + data.gender + ')'; } if (data.accent) { option.textContent += ' (' + data.accent + ')'; } select.appendChild(option); } select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredVoiceEmotion(speechItem); }); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function populateLanguageOptions(languages, speechItem) { if (speechItem.querySelector('select[name="lang"]')) { return; } const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'lang[]'; for (const [code, name] of Object.entries(languages)) { const option = document.createElement('option'); option.value = code; option.textContent = name; if (code === 'ru') { option.selected = true; } select.appendChild(option); } const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock); select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredSpeakers(speechItem); }); } function populateGenderOptions(gender, speechItem) { const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'gender[]'; const option = document.createElement('option'); option.value = 'all'; option.selected = true; option.textContent = 'Gender: all'; select.appendChild(option); for (const [code, name] of Object.entries(gender)) { if (name !== 'non-binary') { const option = document.createElement('option'); option.value = name; option.textContent = name; select.appendChild(option); } } select.addEventListener('change', function () { const speechItem = select.closest('.speech-item'); filteredSpeakers(speechItem); }); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function populateEmotionOptions(emotion, speechItem) { const select = document.createElement('select'); select.classList = 'cursor-pointer lqd-input block peer w-full px-4 py-2 border border-input-border text-base ring-offset-0 transition-colors focus:border-secondary focus:outline-0 focus:ring dark:focus:ring-foreground/10 sm:text-2xs lqd-input-lg h-11 rounded-xl bg-background text-heading-foreground focus:ring-heading-foreground/5'; select.name = 'emotion[]'; select.style.display = "none"; const option = document.createElement('option'); option.value = null; option.textContent = 'none'; select.appendChild(option); const spanBlock = document.createElement('span'); spanBlock.classList = 'mr-2 text-lg float-left'; spanBlock.appendChild(select); speechItem.appendChild(spanBlock) } function initArrowUpDownSpeaches() { document.querySelectorAll('.speech-item.mb-3').forEach((speech) => { const existingUpButton = speech.querySelector('.up-btn'); const existingDownButton = speech.querySelector('.down-btn'); if (existingUpButton) speech.removeChild(existingUpButton); if (existingDownButton) speech.removeChild(existingDownButton); const upButton = document.createElement('button'); upButton.className = 'up-btn'; upButton.style.margin = '10px'; upButton.innerHTML = ' '; upButton.type = 'button'; upButton.addEventListener('click', () => { const prev = speech.previousElementSibling; if (prev) { speech.parentNode.insertBefore(speech, prev); } arrowMoveState(); }); const downButton = document.createElement('button'); downButton.className = 'down-btn'; upButton.style.margin = '10px'; downButton.innerHTML = ' '; downButton.type = 'button'; downButton.addEventListener('click', () => { const next = speech.nextElementSibling; if (next) { speech.parentNode.insertBefore(next, speech); } arrowMoveState(); }); speech.appendChild(upButton); speech.appendChild(downButton); }); } function startPreviewSpeechItem(buttonsPreviewSpeech = null) { Alpine.store('appLoadingIndicator').show(); if (buttonsPreviewSpeech === null) { return; } const initPreviewButton = buttonsPreviewSpeech.querySelector('.init-preview-button'); const loadPreviewButton = buttonsPreviewSpeech.querySelector('.load-preview-button'); if (initPreviewButton) { initPreviewButton.classList.add('hidden'); } if (loadPreviewButton) { loadPreviewButton.classList.remove('hidden'); } } function finishPreviewSpeechItem(buttonsPreviewSpeech = null) { Alpine.store('appLoadingIndicator').hide(); if (buttonsPreviewSpeech === null) { return; } const initPreviewButton = buttonsPreviewSpeech.querySelector('.init-preview-button'); const loadPreviewButton = buttonsPreviewSpeech.querySelector('.load-preview-button'); if (initPreviewButton) { initPreviewButton.classList.remove('hidden'); } if (loadPreviewButton) { loadPreviewButton.classList.add('hidden'); } } function saveSpeechesToLocalStorage() { const speechesBlock = document.querySelector('#speeches'); const speeches = Array.from(speechesBlock.children).map(item => { const inputs = item.querySelectorAll('input, textarea, select'); const speechData = {}; inputs.forEach(input => { speechData[input.name] = input.value; }); return speechData; }); localStorage.setItem('speeches', JSON.stringify(speeches)); } function formatTime( time ) { var minutes = Math.floor( time / 60 ); var seconds = Math.floor( time % 60 ); return minutes + ':' + ( seconds < 10 ? '0' : '' ) + seconds; } function addParamToUrlSilent(name, value) { const urlParams = new URLSearchParams(window.location.search); urlParams.set(name, value); let newUrl = window.location.pathname + '?' + urlParams.toString(); if (newUrl.length > 2000) { newUrl = newUrl.substring(0, 2000); } window.history.replaceState({ path: newUrl }, '', newUrl); } function addExcelViewerToForm() { const excelViewerTemplate = document.getElementById('excel-viewer'); const excelViewer = document.importNode(excelViewerTemplate.content, true); formAppFirstQuestion.appendChild(excelViewer); document.querySelector('.excel-viewer').addEventListener('change', handleFileSelect); const storedFile = localStorage.getItem('selectedFile'); if (storedFile) { const fileInput = document.getElementById('file-input'); const blob = new Blob([new Uint8Array(JSON.parse(storedFile))], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const file = new File([blob], localStorage.getItem('savedFileName') ?? 'temp_name.xlsx'); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; excelReader(file); } } window.createForm = createForm; window.selectAppButton = selectAppButton; window.formAlreadyCreated = formAlreadyCreated; function initCodeHighLight(resultBlock) { const codeElement = resultBlock.querySelector('code'); if (codeElement) { if (codeElement.hasAttribute('data-ace-initialized')) { return; } var bodyClass = document.body.className; var theme = bodyClass.includes('theme-light') ? "ace/theme/github_light_default" : "ace/theme/nord_dark"; const codeText = codeElement.textContent; const editorDiv = document.createElement('div'); editorDiv.id = `editor_${resultBlock.id}`; editorDiv.innerHTML = codeText; codeElement.appendChild(editorDiv); ace.edit(`editor_${resultBlock.id}`, { theme: theme, mode: "ace/mode/javascript", maxLines: 100, wrap: true, autoScrollEditorIntoView: true }); } } function updateEditorTheme() { var bodyClass = document.body.className; var theme = bodyClass.includes('theme-light') ? "ace/theme/github_light_default" : "ace/theme/nord_dark"; } document.querySelector('.lqd-light-dark-switch').addEventListener('click', function() { updateEditorTheme(); }); function generateUniqueId() { const existingIds = new Set([...document.querySelectorAll('[id]')].map(element => element.id)); let newId; do { newId = 'id-' + Math.random().toString(36).substr(2, 9); } while (existingIds.has(newId)); return newId; } }; function addButtonAppNotUsedYet(id) { const existingButtons = document.querySelectorAll('.app_btn_not_use_yet'); existingButtons.forEach(button => button.remove()); if (!recommendationAppsConfigs) { return; } recommendationAppsConfigs.data.forEach(app => { if (id == app.id || id == app.slug) { const element = document.getElementById('app_btn_' + app.slug); if (element) { element.remove(); } const button = document.createElement('button'); button.textContent = app.title; button.style.margin = '5px'; button.id = 'app_btn_' + app.slug; button.classList = "app_btn_not_use_yet app_btn lqd-btn group inline-flex items-center justify-center gap-1.5 text-xs font-medium rounded-full transition-all hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 [&[disabled]]:bg-foreground [&[disabled]]:opacity-30 [&[disabled]]:pointer-events-none lqd-btn-ghost-shadow bg-background text-foreground shadow-xs hover:bg-primary hover:text-primary-foreground dark:hover:bg-foreground dark:hover:text-background focus-visible:bg-primary focus-visible:text-primary-foreground dark:bg-foreground/[3%] dark:focus-visible:bg-foreground dark:focus-visible:text-background lqd-btn-md py-2 px-4 lqd-btn-hover-none"; button.onclick = () => { selectAppButton(app.slug); createForm(app); }; recommendedButtonsApps.prepend(button); selectAppButton(app.slug); localStorage.setItem('initConfigIdOrSlug', app.slug); if (!formAlreadyCreated) { createForm(app); } } }); } function handleFileSelect(event) { const file = event.target.files[0]; if (!file) { return; } if (file) { localStorage.setItem('savedFileName', file.name); const reader = new FileReader(); reader.onload = function (e) { const arrayBuffer = new Uint8Array(e.target.result); localStorage.setItem('selectedFile', JSON.stringify([...arrayBuffer])); localStorage.setItem('savedFileName', file.name); }; excelReader(file); } excelReader(file); } function excelReader(file) { if (file) { const reader = new FileReader(); reader.onload = function (e) { const arrayBuffer = new Uint8Array(e.target.result); localStorage.setItem('selectedFile', JSON.stringify([...arrayBuffer])); }; reader.readAsArrayBuffer(file); } const reader = new FileReader(); reader.onload = function(e) { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; const rows = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); const firstRow = rows[0]; const secondRow = rows[1]; displayTable(firstRow, secondRow); }; reader.readAsArrayBuffer(file); } let lastInsertNewPrompt = null; function displayTable(firstRow, secondRow) { const tableContainer = document.getElementById('table-container'); tableContainer.innerHTML = ''; const table = document.createElement('table'); table.style.width = '100%'; table.id = 'excel-structure-table'; const headerRow = document.createElement('tr'); headerRow.innerHTML = '#First contentWhat to do?'; table.appendChild(headerRow); firstRow.forEach((columnName, index) => { if (columnName) { const row = document.createElement('tr'); const letter = String.fromCharCode(65 + index); const secondRowData = secondRow[index] || ''; const truncatedSecondRow = secondRowData.length > 100 ? secondRowData.slice(0, 100) + '...' : secondRowData; row.innerHTML = ` ${index + 1}${columnName} 
${truncatedSecondRow}
`; table.appendChild(row); const addButton = row.querySelector('.add-row'); addButton.addEventListener('click', function() { const newRow = document.createElement('tr'); const newIndex = table.rows.length - 1; const newLetter = String.fromCharCode(65 + newIndex); let storeValue = localStorage.getItem('excel_columns['+(newIndex + 1)+'][new]'); newRow.innerHTML = ` ${newIndex + 1} `; table.insertBefore(newRow, row.nextSibling); updateIndexes(); const deleteButton = newRow.querySelector('.delete-row'); deleteButton.addEventListener('click', function() { newRow.remove(); updateIndexes(); return; }); }); row.id = index + 1; row.addEventListener('click', function() { if (lastInsertNewPrompt) { lastInsertNewPrompt.value += ' **cell:'+row.id+'** '; lastInsertNewPrompt.focus(); } }); } }); function updateIndexes() { for(let i = 1; i < table.rows.length; i++) { table.rows[i].cells[1].innerText = i; table.rows[i].id = i; const currentTextareas = table.rows[i].getElementsByClassName('column_current'); for (let textarea of currentTextareas) { textarea.name = `columns[${i}][current]`; textarea.addEventListener('click', function() { if (lastInsertNewPrompt) { lastInsertNewPrompt = null; } }); } const newTextareas = table.rows[i].getElementsByClassName('column_new'); for (let textarea of newTextareas) { textarea.name = `columns[${i}][new]`; textarea.addEventListener('input', function() { lastInsertNewPrompt = textarea; localStorage.setItem('excel_' + textarea.name, textarea.value); }); textarea.addEventListener('click', function() { lastInsertNewPrompt = textarea; localStorage.setItem('excel_' + textarea.name, textarea.value); }) } const newHeaderInput = table.rows[i].getElementsByClassName('header_new'); for (let input of newHeaderInput) { input.name = `headers[${i}][new]`; } } } tableContainer.appendChild(table); } function exportTaskTo(elm = null, type = 'clipboard') { const getParentBlock = elm.closest('.chat-content-container'); const getResultContent = getParentBlock.querySelector('.result_answer'); let content = getResultContent.innerHTML; let tempElement = ''; switch (type) { case 'clipboard': tempElement = document.createElement('div'); tempElement.innerHTML = content; document.body.appendChild(tempElement); const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(tempElement); selection.removeAllRanges(); selection.addRange(range); const successful = document.execCommand('copy'); if (successful) { toastr.success('Content copied to clipboard'); } else { toastr.error('Could not copy text'); } document.body.removeChild(tempElement); break; case 'pdf': downloadPDF(content); break; case 'html': const htmlBlob = new Blob([content], { type: 'text/html' }); const htmlLink = document.createElement('a'); htmlLink.href = URL.createObjectURL(htmlBlob); htmlLink.download = 'content.html'; htmlLink.click(); break; case 'word': const wordBlob = new Blob(['\ufeff', '', '', '', content, '' ], { type: 'application/msword' }); const wordLink = document.createElement('a'); wordLink.href = URL.createObjectURL(wordBlob); wordLink.download = 'content.doc'; document.body.appendChild(wordLink); wordLink.click(); document.body.removeChild(wordLink); break; case 'txt': content = getResultContent.innerText; const txtBlob = new Blob([content], { type: 'text/plain' }); const txtLink = document.createElement('a'); txtLink.href = URL.createObjectURL(txtBlob); txtLink.download = 'content.txt'; document.body.appendChild(txtLink); txtLink.click(); document.body.removeChild(txtLink); break; default: console.error('Unsupported export type:', type); break; } } function downloadPDF(htmlContent) { const element = document.createElement('div'); element.innerHTML = htmlContent; const options = { margin: 1, filename: 'download.pdf', html2canvas: { scale: 2 }, jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' } }; html2pdf() .from(element) .set(options) .save() .then(() => { document.body.removeChild(element); }) .catch(err => console.error('Error generating PDF:', err)); } function openChatWnd(wnd) { try { wnd.openChatWnd = !wnd.openChatWnd; const iframe = document.getElementById("chat-wnd-frame"); const setIframeHeight = () => { const height = window.innerHeight; iframe.style.height = (height - 50) + 'px'; }; setIframeHeight(); document.body.style.overflow = wnd.openChatWnd ? 'hidden' : ''; window.addEventListener('resize', setIframeHeight); } catch (e) { console.log(e) } }