document.addEventListener('DOMContentLoaded', function () { document.addEventListener('click', function (event) { if (event.target.classList.contains('native-datetime-picker--input')) { const inputElement = event.target; inputElement.classList.add('is-set-value'); } }); }); // Выпадающее меню /* document.addEventListener('DOMContentLoaded', function () { const userMenuLink = document.getElementById('user-menu-f7mail'); const dropdownMenu = document.getElementById('header-menu-user-menu-f7mail'); if (userMenuLink && dropdownMenu) { userMenuLink.addEventListener('click', function (e) { e.preventDefault(); dropdownMenu.style.display = dropdownMenu.style.display === 'none' ? 'block' : 'none'; }); document.addEventListener('click', function (e) { if (!dropdownMenu.contains(e.target) && e.target !== userMenuLink) { dropdownMenu.style.display = 'none'; } }); } //уведомления иконка setTimeout(function () { const newNotifications = document.getElementsByClassName('notification__dot'); if (newNotifications.length > 0) { const spanAlert = document.createElement('span'); spanAlert.className = 'alert-icon'; newNotifications[0].parentNode.parentNode.appendChild(spanAlert); } }, 2000); });*/ document.addEventListener('DOMContentLoaded', () => { const moveElements = () => { console.log('moveElements вызван'); const content_wrap = document.getElementById('content-vue'); const searchBox = document.querySelector('.app-files .app-navigation__search .app-navigation-search'); const targetContainer = document.querySelector('.app-files .files-list__header'); const targetContainerFirstElement = document.querySelector('.app-files .files-list__breadcrumbs'); const searchBoxActual = document.querySelector('.app-files .app-navigation__search'); if (content_wrap) { let mask_button = document.querySelector('.mask-button-load'); if (!mask_button) { mask_button = document.createElement('div'); mask_button.classList.add('mask-button-load'); content_wrap.append(mask_button); } else { console.log('⚠️ mask-button-load уже существует'); } } let magnifier = document.querySelector('.app-files .magnifier-icon'); if (!magnifier && searchBox) { magnifier = document.createElement('div'); magnifier.className = 'magnifier-icon'; magnifier.innerHTML = ` `; magnifier.style.cssText = 'cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 4px;'; magnifier.style.cursor = 'pointer'; targetContainerFirstElement.after(magnifier); magnifier.addEventListener('click', () => { console.log('click', searchBox); if (searchBox) { searchBox.style.display = 'flex'; magnifier.style.display = 'none'; searchBox.querySelector('input')?.focus(); } }); if (searchBox && targetContainer) { targetContainer.insertBefore(searchBox, magnifier); searchBox.style.display = 'none'; } if (searchBox) { const input = searchBox.querySelector('input'); if (input) { input.addEventListener('focus', () => { if (magnifier) { magnifier.style.display = 'none'; } }); input.addEventListener('blur', () => { if (magnifier) { magnifier.style.display = 'flex'; searchBox.style.display = 'none'; } }); } } } }; const observer = new MutationObserver((mutations) => { const appFiles = document.querySelector('.app-files'); if (appFiles) { moveElements(); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); document.addEventListener('DOMContentLoaded', function () { const toggleButton = document.querySelector('[href="#profile-visibility"]'); const profileWrapper = document.querySelector('.settings-visible-profile'); if (toggleButton && profileWrapper) { toggleButton.addEventListener('click', function () { if (profileWrapper.style.display === 'none' || profileWrapper.style.display === '') { profileWrapper.style.display = 'block'; } else { profileWrapper.style.display = 'none'; } }); } }); function initSnappyMailPasswordToggle() { if (!window.location.pathname.includes('/apps/snappymail/')) { return; } const setupPasswordToggle = () => { const passwordControl = document.querySelector('#password-control'); if (passwordControl) { const passwordToggleIcon = passwordControl.querySelector('.password-toggle-icon'); const inputField = passwordControl.querySelector('input[name="Password"]'); const eyeOpenIcon = passwordControl.querySelector('.eye-icon.eye-open'); const eyeClosedIcon = passwordControl.querySelector('.eye-icon.eye-closed'); if (passwordToggleIcon && inputField && eyeOpenIcon && eyeClosedIcon) { passwordToggleIcon.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); passwordControl.classList.toggle('show-password'); if (inputField.type === 'password') { inputField.type = 'text'; } else { inputField.type = 'password'; } eyeOpenIcon.classList.toggle('active'); eyeClosedIcon.classList.toggle('active'); }); return true; } } return false; }; if (setupPasswordToggle()) { return; } const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { if (setupPasswordToggle()) { observer.disconnect(); return; } } } }); observer.observe(document.body, { childList: true, subtree: true }); } if (document.readyState === 'complete') { initSnappyMailPasswordToggle(); } else { document.addEventListener('DOMContentLoaded', initSnappyMailPasswordToggle); } //hamburger document.addEventListener('DOMContentLoaded', function () { const burgerButton = document.querySelector('#header .is-header__burger'); const appMenu = document.querySelector('#header .app-menu'); const html = document.querySelector('html'); if (burgerButton && appMenu) { burgerButton.addEventListener('click', function () { this.classList.toggle('is-show-mobile-menu'); appMenu.classList.toggle('show'); html.classList.toggle('no-scroll'); }); } }); // logic for correct print dots icon (close-open right sidebar) document.addEventListener('DOMContentLoaded', function () { let currentObserver = null; let headerObserver = null; function cleanupObservers() { if (currentObserver) { currentObserver.disconnect(); currentObserver = null; } if (headerObserver) { headerObserver.disconnect(); headerObserver = null; } } function initializeFeature() { const divMain = document.querySelector('#content.app-spreed'); const buttonDotsCheck = document.querySelector('.action-item.action-item--default-popover.action-item--tertiary'); if (!divMain || !buttonDotsCheck) { cleanupObservers(); return; } try { const appContentDiv = document.getElementById('app-content-vue'); if (!appContentDiv) { cleanupObservers(); return; } const topHeaderWrapper = appContentDiv.querySelector('.top-bar.top-bar--authorised'); if (!topHeaderWrapper) { cleanupObservers(); return; } const buttonDots = topHeaderWrapper.querySelector('.action-item.action-item--default-popover.action-item--tertiary'); if (!buttonDots) { cleanupObservers(); return; } const buttonDotsSpan = buttonDots.querySelector('.material-design-icon.dots-horizontal-icon'); if (!buttonDotsSpan) { cleanupObservers(); return; } const appRightSidebar = document.getElementById('app-sidebar-vue'); if (!appRightSidebar) { cleanupObservers(); return; } const headerConf = appContentDiv.querySelector('.conversation-header'); if (!headerConf) { cleanupObservers(); return; } const headerConfText = headerConf.querySelector('.title'); if (!headerConfText) { cleanupObservers(); return; } function updateIconVisibility() { const headerConfTextContent = headerConfText.textContent.trim(); const shouldHideIcon = headerConfTextContent === "Личные заметки" || headerConfTextContent === "Обновления приложения «Конференции» ✅"; if (shouldHideIcon) { if (getComputedStyle(appRightSidebar).display === 'none') { buttonDotsSpan.style.display = 'none'; } else { buttonDotsSpan.style.display = 'flex'; } } else { buttonDotsSpan.style.display = 'flex'; } } cleanupObservers(); currentObserver = new MutationObserver(() => { updateIconVisibility(); }); headerObserver = new MutationObserver(() => { updateIconVisibility(); }); currentObserver.observe(appRightSidebar, { attributes: true, attributeFilter: ['style'] }); headerObserver.observe(headerConfText, { characterData: true, childList: true, subtree: true }); updateIconVisibility(); } catch (e) { cleanupObservers(); } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializeFeature); } else { initializeFeature(); } const handleNavigation = () => { requestAnimationFrame(() => { initializeFeature(); }); }; const documentObserver = new MutationObserver(handleNavigation); documentObserver.observe(document.body, { childList: true, subtree: true }); setInterval(handleNavigation, 1000); }); // ------------------------------------------------------------ document.addEventListener('DOMContentLoaded', function () { const divMain = document.querySelector('#content.app-spreed'); if (!divMain) return; const HIDDEN_BODY_CLASS = 'my-in-call-hidden-header'; let currentInCall = null; let createdPanels = null; let placing = false; const style = document.createElement('style'); style.textContent = ` body.${HIDDEN_BODY_CLASS} .top-bar.top-bar--in-call { display: none !important; } `; document.head.appendChild(style); function waitFor(selector, scope = document, timeout = 2000) { return new Promise(resolve => { let el = scope.querySelector(selector); if (el) return resolve(el); let time = 0; const iv = setInterval(() => { el = scope.querySelector(selector); if (el) { clearInterval(iv); resolve(el); } time += 50; if (time >= timeout) { clearInterval(iv); resolve(null); } }, 50); }); } async function collectElements(inCallEl) { const header = await waitFor('.main-view .top-bar.top-bar--in-call', inCallEl); const callContainer = await waitFor('.main-view #call-container', inCallEl); if (!header || !callContainer) return null; let bottomMenu = null; const bottomMenuSearch = callContainer.children[2]; if (bottomMenuSearch) { if (bottomMenuSearch.classList.contains('bottom-bar')) { bottomMenu = bottomMenuSearch; } } else if (callContainer.children[1].classList.contains('bottom-bar')) { bottomMenu = callContainer.children[1]; } console.log('bottomMenu', bottomMenu) if (!bottomMenu) return null; const icon = header.querySelector('a.top-bar__icon-wrapper'); const title = header.querySelector('.conversation-header'); const time = header.querySelector('.v-popper.call-time'); const participants = header.querySelector('.button-vue--tertiary.top-bar__participants-button'); const dots = header.querySelector('.top-bar-menu'); const sections = [...bottomMenu.children]; return { header, bottomMenu, icon, title, time, participants, dots, sections }; } function move(el, to) { if (!el || !to) return; if (!to.contains(el)) { try { to.appendChild(el); } catch (e) { console.warn(e); } } } function buildPanels(parts) { if (createdPanels) return; const { bottomMenu, icon, title, time, participants, dots, sections } = parts; const wrapper = document.createElement('div'); wrapper.className = 'my-call-toolbar-wrapper'; wrapper.dataset.ourPanel = 'true'; const left = document.createElement('div'); left.className = 'left-panel'; const middle = document.createElement('div'); middle.className = 'middle-panel'; const right = document.createElement('div'); right.className = 'right-panel'; wrapper.append(left, middle, right); move(icon, left); move(title, left); const [sec1, sec2, sec3] = sections; move(sec1, middle); move(sec2, middle); move(sec3, middle); move(time, right); move(participants, right); move(dots, right); bottomMenu.appendChild(wrapper); createdPanels = { wrapper, parts }; document.body.classList.add(HIDDEN_BODY_CLASS); console.log('✔ Created call panels'); } function removePanels() { if (!createdPanels) return; const { wrapper, parts } = createdPanels; wrapper.remove(); const { header, icon, title, time, participants, dots, sections } = parts; if (icon) header.prepend(icon); if (title) { const after = header.querySelector('a.top-bar__icon-wrapper'); if (after?.nextSibling) header.insertBefore(title, after.nextSibling); else header.appendChild(title); } move(time, header); move(participants, header); if (dots) { const wrap = header.querySelector('.top-bar__wrapper'); if (wrap) { const join = wrap.querySelector('.button-vue.join-call'); if (join) wrap.insertBefore(dots, join); else wrap.appendChild(dots); } else { header.appendChild(dots); } } const bottomMenu = parts.bottomMenu; if (bottomMenu) { sections.forEach(sec => { if (sec) bottomMenu.appendChild(sec); }); } createdPanels = null; document.body.classList.remove(HIDDEN_BODY_CLASS); console.log('🧹 Panels restored'); } async function onEnterInCall(inCallEl) { if (placing) return; placing = true; if (currentInCall === inCallEl) { placing = false; return; } currentInCall = inCallEl; const parts = await collectElements(inCallEl); if (!parts) { placing = false; return; } buildPanels(parts); placing = false; } function onExitCall() { currentInCall = null; removePanels(); } function initialCheck() { const inCall = divMain.querySelector('.content.app-talk.in-call'); if (inCall) onEnterInCall(inCall); } initialCheck(); const observer = new MutationObserver(() => { clearTimeout(observer._t); observer._t = setTimeout(() => { const inCall = divMain.querySelector('.content.app-talk.in-call'); if (inCall) { onEnterInCall(inCall); } else { onExitCall(); } }, 120); }); observer.observe(divMain, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); window.addEventListener('beforeunload', () => { observer.disconnect(); removePanels(); }); }); //settings - sharing document.addEventListener('DOMContentLoaded', function () { const divMain = document.querySelector('#app-content'); if (divMain && divMain.dataset.activeSectionId === "sharing") { const filesSettings = divMain.querySelector('#files-personal-settings'); const filesSharingSettings = divMain.querySelector('#files-sharing-personal-settings'); const transferSelectRow = filesSettings.querySelector('.transfer-select-row'); const buttonText = transferSelectRow.querySelector('.button-vue__text'); const titleSharingContent = document.createElement('h2'); titleSharingContent.textContent = "Настройки доступа"; titleSharingContent.classList.add('sharing-content-title'); const titleDisSharingContent = document.createElement('p'); titleDisSharingContent.textContent = "Настройки доступа к вашей информации в сервисах Forbion"; titleDisSharingContent.classList.add('sharing-content-title-discription'); const contentWrapperSharingContent = document.createElement('div'); contentWrapperSharingContent.classList.add('sharing-settings-box'); divMain.appendChild(titleSharingContent); divMain.appendChild(titleDisSharingContent); divMain.appendChild(contentWrapperSharingContent); contentWrapperSharingContent.appendChild(filesSettings); contentWrapperSharingContent.appendChild(filesSharingSettings); buttonText.textContent = "Выбрать"; } }) //settings - persons document.addEventListener('DOMContentLoaded', function () { const divMain = document.querySelector('#app-content'); if (divMain && divMain.dataset.activeSectionId === "personal-info") { const divContent = document.getElementById('personal-settings'); const titlePersonContent = document.createElement('h2'); titlePersonContent.textContent = "Личная информация"; titlePersonContent.classList.add('person-content-title'); const titleDisPersonContent = document.createElement('p'); titleDisPersonContent.textContent = "Сведения о вас и ваших настройках в сервисах Forbion"; titleDisPersonContent.classList.add('person-content-title-discription'); const divAvatar = document.getElementById('vue-avatar-section'); const divProfile = divContent.querySelector('.personal-settings-setting-box.personal-settings-setting-box-profile'); const divDetails = divContent.querySelector('.personal-settings-setting-box.personal-settings-setting-box-detail'); const divName = divContent.querySelectorAll('.personal-settings-setting-box')[2]; const divEmail = divContent.querySelectorAll('.personal-settings-setting-box')[4]; const divNumber = divContent.querySelectorAll('.personal-settings-setting-box')[5]; const divPlace = divContent.querySelectorAll('.personal-settings-setting-box')[6]; const divDate = divContent.querySelectorAll('.personal-settings-setting-box')[7]; const divLang = divContent.querySelector('.personal-settings-language-box'); const divMestoim = divContent.querySelectorAll('.personal-settings-setting-box')[3]; const divLocate = divContent.querySelector('.personal-settings-locale-box'); const divWeek = divContent.querySelectorAll('.personal-settings-setting-box')[10]; const divTime = divContent.querySelectorAll('.personal-settings-setting-box')[11]; const divUrlSite = divContent.querySelectorAll('.personal-settings-setting-box')[12]; const divTW = divContent.querySelectorAll('.personal-settings-setting-box')[13]; const divBluesky = divContent.querySelectorAll('.personal-settings-setting-box')[14]; const divFederate = divContent.querySelectorAll('.personal-settings-setting-box')[15]; const divOrg = divContent.querySelectorAll('.personal-settings-setting-box')[16]; const divRole = divContent.querySelectorAll('.personal-settings-setting-box')[17]; const divTitle = divContent.querySelectorAll('.personal-settings-setting-box')[18]; const divAbout = divContent.querySelectorAll('.personal-settings-setting-box')[19]; divMestoim.style.display = "none"; divLocate.style.display = "none"; divWeek.style.display = "none"; divTime.style.display = "none"; divUrlSite.style.display = "none"; divTW.style.display = "none"; divBluesky.style.display = "none"; divFederate.style.display = "none"; divOrg.style.display = "none"; divRole.style.display = "none"; divTitle.style.display = "none"; divAbout.style.display = "none"; const divAboutF7cloud = divMain.querySelector('.development-notice'); divAboutF7cloud.style.display = "none"; const wrapperBoxAvatarInfo = document.createElement('div'); wrapperBoxAvatarInfo.classList.add('wrapper-content-box'); wrapperBoxAvatarInfo.id = 'wrapper-content-box-avater-and-info'; const wrapperBoxContent = document.createElement('div'); wrapperBoxContent.classList.add('content-box'); const titleBoxAvatarInfo = document.createElement('p'); titleBoxAvatarInfo.classList.add('title-box'); titleBoxAvatarInfo.textContent = 'Основная иформация профиля'; const divGridPersonInfo = document.createElement('div'); divGridPersonInfo.classList.add('person-grid'); const wrapperBoxProfile = document.createElement('div'); wrapperBoxProfile.classList.add('wrapper-content-box'); wrapperBoxProfile.id = 'wrapper-content-box-profile-info'; const wrapperBoxContent2 = document.createElement('div'); wrapperBoxContent2.classList.add('content-box'); const titleBoxProfile = document.createElement('p'); titleBoxProfile.classList.add('title-box'); titleBoxProfile.textContent = 'Подробные сведения'; divContent.append(titlePersonContent); divContent.append(titleDisPersonContent); divContent.append(wrapperBoxAvatarInfo); divContent.append(wrapperBoxProfile); // section 1 wrapperBoxAvatarInfo.append(titleBoxAvatarInfo); wrapperBoxAvatarInfo.append(wrapperBoxContent); wrapperBoxContent.append(divAvatar); wrapperBoxContent.append(divGridPersonInfo); divGridPersonInfo.append(divName); divGridPersonInfo.append(divNumber); divGridPersonInfo.append(divDate); divGridPersonInfo.append(divPlace); divGridPersonInfo.append(divEmail); divGridPersonInfo.append(divLang); // divGridPersonInfo.append(divMestoim); divGridPersonInfo.append(divLocate); divGridPersonInfo.append(divWeek); divGridPersonInfo.append(divTime); divGridPersonInfo.append(divUrlSite); divGridPersonInfo.append(divTW); divGridPersonInfo.append(divBluesky); divGridPersonInfo.append(divFederate); divGridPersonInfo.append(divOrg); divGridPersonInfo.append(divRole); divGridPersonInfo.append(divTitle); divGridPersonInfo.append(divAbout); // section 2 wrapperBoxProfile.append(titleBoxProfile); wrapperBoxProfile.append(wrapperBoxContent2); wrapperBoxContent2.append(divProfile); wrapperBoxContent2.append(divDetails); } }) // Анимация сайдбара-хеддера document.addEventListener('DOMContentLoaded', function () { const userMenuLink = document.getElementById('user-menu-f7mail'); const dropdownMenu = document.getElementById('header-menu-user-menu-f7mail'); if (userMenuLink && dropdownMenu) { userMenuLink.addEventListener('click', function (e) { e.preventDefault(); dropdownMenu.style.display = dropdownMenu.style.display === 'none' ? 'block' : 'none'; }); document.addEventListener('click', function (e) { if (!dropdownMenu.contains(e.target) && e.target !== userMenuLink) { dropdownMenu.style.display = 'none'; } }); } setTimeout(function () { const newNotifications = document.getElementsByClassName('notification__dot'); if (newNotifications.length > 0) { const spanAlert = document.createElement('span'); spanAlert.className = 'alert-icon'; newNotifications[0].parentNode.parentNode.appendChild(spanAlert); } }, 2000); const moreBtn = document.getElementById('app-menu-toggle--more'); const hiddenMenu = document.getElementById('hidden-menu'); const appList = document.querySelector('.app-menu__list'); moreBtn.addEventListener('click', e => { e.preventDefault(); e.stopPropagation(); if (hiddenMenu.classList.contains('is-active')) { hiddenMenu.style.maxHeight = hiddenMenu.scrollHeight + 'px'; requestAnimationFrame(() => { hiddenMenu.style.maxHeight = '0'; hiddenMenu.style.opacity = '0'; hiddenMenu.style.transform = 'translateY(20px)'; }); hiddenMenu.addEventListener('transitionend', function handler() { hiddenMenu.classList.remove('is-active'); hiddenMenu.style.maxHeight = ''; hiddenMenu.removeEventListener('transitionend', handler); }); appList.scrollTop = 0; } else { hiddenMenu.classList.add('is-active'); hiddenMenu.style.maxHeight = '0'; hiddenMenu.style.opacity = '0'; hiddenMenu.style.transform = 'translateY(20px)'; requestAnimationFrame(() => { hiddenMenu.style.maxHeight = hiddenMenu.scrollHeight + 'px'; hiddenMenu.style.opacity = '1'; hiddenMenu.style.transform = 'translateY(0)'; }); } }); document.addEventListener('click', e => { if (!hiddenMenu.contains(e.target) && !e.target.closest('#app-menu-toggle--more')) { if (hiddenMenu.classList.contains('is-active')) { moreBtn.click(); } } }); document.addEventListener('keydown', e => { if (e.key === 'Escape' && hiddenMenu.classList.contains('is-active')) { moreBtn.click(); } }); }); document.addEventListener('DOMContentLoaded', () => { const tooltip = document.createElement('div'); tooltip.className = 'global-tooltip'; document.body.appendChild(tooltip); const entries = document.querySelectorAll('.app-menu-entry'); function findScrollParent(el) { let p = el.parentElement; while (p) { const overflowY = window.getComputedStyle(p).overflowY; if (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') return p; p = p.parentElement; } return window; } let activeEntry = null; let scrollParent = null; function showTooltipFor(entry) { const labelEl = entry.querySelector('.tooltip-header-hide'); if (!labelEl) return; const text = labelEl.textContent.trim(); tooltip.textContent = text; tooltip.classList.add('visible'); requestAnimationFrame(() => positionTooltip(entry)); activeEntry = entry; scrollParent = findScrollParent(entry); if (scrollParent && scrollParent !== window) { scrollParent.addEventListener('scroll', onScrollOrResize, { passive: true }); } window.addEventListener('scroll', onScrollOrResize, { passive: true }); window.addEventListener('resize', onScrollOrResize); } function hideTooltip() { tooltip.classList.remove('visible'); if (scrollParent && scrollParent !== window) { scrollParent.removeEventListener('scroll', onScrollOrResize); } window.removeEventListener('scroll', onScrollOrResize); window.removeEventListener('resize', onScrollOrResize); activeEntry = null; scrollParent = null; } function onScrollOrResize() { if (activeEntry) positionTooltip(activeEntry); } function positionTooltip(entry) { const rect = entry.getBoundingClientRect(); const gap = 8; const preferLeft = false; const tooltipRect = tooltip.getBoundingClientRect(); let top = rect.top + rect.height / 2; let left = rect.right + gap; const viewportWidth = document.documentElement.clientWidth; if (left + tooltipRect.width > viewportWidth - 8) { left = rect.left - gap - tooltipRect.width; } left = Math.max(8, Math.min(left, viewportWidth - tooltipRect.width - 8)); const viewportHeight = document.documentElement.clientHeight; const halfTooltipHeight = tooltipRect.height / 2; top = Math.max(8 + halfTooltipHeight, Math.min(top, viewportHeight - 8 - halfTooltipHeight)); tooltip.style.left = Math.round(left) + 'px'; tooltip.style.top = Math.round(top) + 'px'; } entries.forEach(entry => { const target = entry.querySelector('.app-menu-entry__link') || entry; // mouseenter / mouseleave entry.addEventListener('mouseenter', () => showTooltipFor(entry)); entry.addEventListener('mouseleave', hideTooltip); if (target) { target.addEventListener('focus', () => showTooltipFor(entry)); target.addEventListener('blur', hideTooltip); } }); }); document.addEventListener('DOMContentLoaded', () => { const divFile = document.querySelector('.content.app-files') if (!divFile) return function waitForElement(selector, timeout = 5000) { return new Promise((resolve, reject) => { const el = document.querySelector(selector) if (el) return resolve(el) const obs = new MutationObserver(() => { const el2 = document.querySelector(selector) if (el2) { obs.disconnect() resolve(el2) } }) obs.observe(document.body, { childList: true, subtree: true }) setTimeout(() => { obs.disconnect() reject(new Error(`Элемент ${selector} не найден за ${timeout}ms`)) }, timeout) }) } async function moveFiltersOnce() { try { const filtersRoot = await waitForElement('.files-list__filters') const nameSortButton = await waitForElement('.files-list__column-sort-button[title="Имя"]') if (filtersRoot.dataset.moved === '1') return const thead = nameSortButton.closest('thead') if (!thead) return const nameTh = nameSortButton.closest('th') if (!nameTh) return // Оборачиваем в div для выравнивания let wrapper = thead.querySelector('.files-list__filters-moved') if (!wrapper) { wrapper = document.createElement('div') wrapper.className = 'files-list__filters-moved' wrapper.style.display = 'flex' wrapper.style.gap = '8px' wrapper.style.marginLeft = '12px' wrapper.style.alignItems = 'center' nameTh.appendChild(wrapper) } wrapper.appendChild(filtersRoot) filtersRoot.style.display = '' filtersRoot.dataset.moved = '1' } catch (e) { console.error('moveFiltersOnce error', e) } } moveFiltersOnce() const observer = new MutationObserver(mutations => { for (const m of mutations) { if (m.type === 'childList' && m.addedNodes.length) { if ([...m.addedNodes].some( n => n.nodeType === 1 && (n.matches?.('.files-list__filters') || n.querySelector?.('.files-list__filters')) )) { setTimeout(moveFiltersOnce, 50) break } } } }) observer.observe(divFile, { childList: true, subtree: true }) }) document.addEventListener('DOMContentLoaded', () => { const divFile = document.getElementById('body-public')?.querySelector('.content.app-files'); if (!divFile) return; const setupHeader = () => { const header = document.getElementById('header'); if (!header || header.querySelector('#header-controls')) return; const headerRight = document.querySelector('.header-right'); const talkTrigger = document.getElementById('talk-sidebar-trigger'); console.log(headerRight) if (headerRight && talkTrigger) { const controls = document.createElement('div'); controls.id = 'header-controls'; controls.className = 'header-controls'; console.log(controls) if (headerRight.parentNode) headerRight.parentNode.removeChild(headerRight); if (talkTrigger.parentNode) talkTrigger.parentNode.removeChild(talkTrigger); controls.appendChild(headerRight); controls.appendChild(talkTrigger); const headerLeft = header.querySelector('.header-left'); if (headerLeft) { headerLeft.insertAdjacentElement('afterend', controls); } } }; const initWithRetry = () => { setupHeader(); setTimeout(setupHeader, 200); setTimeout(setupHeader, 800); }; initWithRetry(); const observer = new MutationObserver(() => { if (document.getElementById('talk-sidebar-trigger')) { setTimeout(setupHeader, 50); } }); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); }); //add dop field for contact document.addEventListener('DOMContentLoaded', () => { const bodyUser = document.getElementById('body-user'); if (!bodyUser) return; const contactsApp = bodyUser.querySelector('.app-contacts'); if (!contactsApp) return; const processedButtons = new WeakSet(); const buttonObserver = new MutationObserver(() => { const addButton = [...contactsApp.querySelectorAll( 'button.action-item__menutoggle' )].find(btn => btn.querySelector('.button-vue__text') ?.textContent.includes('Добавить больше информации') ); if (!addButton) return; if (processedButtons.has(addButton)) return; processedButtons.add(addButton); handleAddButton(addButton); }); buttonObserver.observe(contactsApp, { childList: true, subtree: true }); async function handleAddButton(addButton) { addButton.click(); let menu; try { menu = await waitForPopperMenu(); } catch (e) { console.error(e); return; } clickByIcon(menu, '.cake-variant-outline-icon', 'День рождения'); const moreBtn = menu.querySelector( 'span[aria-label="Дополнительные поля"]' )?.closest('button'); if (moreBtn) { moreBtn.click(); } setTimeout(() => { document.body.click(); }, 300); } function clickByIcon(menu, iconSelector, label) { const btn = menu.querySelector(iconSelector)?.closest('button'); if (btn) { btn.click(); } else { console.warn(`⚠️ Поле не найдено: ${label}`); } } function waitForPopperMenu(timeout = 3000) { return new Promise((resolve, reject) => { const start = performance.now(); let rafId; function check() { const poppers = [...document.querySelectorAll( '.v-popper__popper[aria-hidden="false"]' )]; if (poppers.length) { const popper = poppers[poppers.length - 1]; const menu = popper.querySelector('ul[role="menu"]'); if (menu) { cancelAnimationFrame(rafId); observer.disconnect(); resolve(menu); return; } } if (performance.now() - start > timeout) { cancelAnimationFrame(rafId); observer.disconnect(); reject('❌ Popper-меню не найдено'); return; } rafId = requestAnimationFrame(check); } const observer = new MutationObserver(check); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['aria-hidden', 'class'] }); check(); }); } }); document.addEventListener('DOMContentLoaded', function () { const observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { mutation.addedNodes.forEach(function (node) { if (node.nodeType === 1) { if (node.id === 'notifications' && node.hasAttribute('title')) { node.removeAttribute('title'); observer.disconnect(); return; } const notificationsContainer = node.id === 'notifications' || node.closest?.('#notifications'); if (notificationsContainer && notificationsContainer.hasAttribute('title')) { notificationsContainer.removeAttribute('title'); observer.disconnect(); } } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); const existingContainer = document.querySelector('#notifications[title]'); if (existingContainer) { existingContainer.removeAttribute('title'); observer.disconnect(); } });