1228 lines
41 KiB
JavaScript
1228 lines
41 KiB
JavaScript
|
||
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 = `
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<g clip-path="url(#clip0_3504_3055)">
|
||
<circle cx="5.5" cy="5.5" r="4.75" stroke="#808080" stroke-width="1.5"/>
|
||
<path d="M8.73541 9L14.7354 15" stroke="#808080" stroke-width="1.5" stroke-linecap="round"/>
|
||
</g>
|
||
<defs>
|
||
<clipPath id="clip0_3504_3055">
|
||
<rect width="16" height="16" fill="white"/>
|
||
</clipPath>
|
||
</defs>
|
||
</svg>
|
||
`;
|
||
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();
|
||
}
|
||
});
|
||
|
||
|
||
|
||
|