LINUX.ORG.RU
ФорумTalks

LOR и скролл

 ,


0

1

Достало меня, что при переходе к сообщениям, реакциям скролл смещался в конец страницы и наклепал я вот такой вот скриптик:

// ==UserScript==
// @name         LOR FIX
// @namespace    lorf
// @match        *://www.linux.org.ru/*
// @grant        none
// @inject-into  content
// @run-at       document-start
// ==/UserScript==

(function() {
    const origScrollTo = window.scrollTo.bind(window);
    const origScrollIntoView = Element.prototype.scrollIntoView;

    let blocked = false;
    let targetId = null;

    const initialCid = new URL(location.href).searchParams.get('cid');

    if (initialCid) {
        targetId = 'comment-' + initialCid;
        blocked = true;
    }

    window.scrollTo = function(...args) {
        if (blocked) return;
        origScrollTo(...args);
    };

    Element.prototype.scrollIntoView = function(...args) {
        if (blocked) return;
        origScrollIntoView.apply(this, args);
    };

    if (!targetId) {
        let attempts = 0;
        const cidInterval = setInterval(function() {
            attempts++;
            const c = new URL(location.href).searchParams.get('cid');
            if (c) {
                clearInterval(cidInterval);
                targetId = 'comment-' + c;
                blocked = true;
                setTimeout(function() {
                    blocked = false;
                    const el = document.getElementById(targetId);
                    if (el) {
                        el.style.outline = '3px solid #4a90d9';
                        origScrollIntoView.call(el, { behavior: 'smooth', block: 'start' });
                        setTimeout(function() { el.style.outline = ''; }, 3000);
                    }
                }, 2000);
            } else if (attempts >= 10) {
                clearInterval(cidInterval);
            }
        }, 500);
    } else {
        window.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                blocked = false;
                const el = document.getElementById(targetId);
                if (el) {
                    el.style.outline = '3px solid #4a90d9';
                    origScrollIntoView.call(el, { behavior: 'smooth', block: 'start' });
                    setTimeout(function() { el.style.outline = ''; }, 3000);
                }
            }, 2000);
        });
    }
})();

Оно конечно работает, но может есть тут специалисты, где я дурак? Может можно сделать как то правильнее? Может как то проще можно перехватить этот скролл и без таймеров? Или понять что мне этот скролл изначально ломает?

★★★★★

при переходе к сообщениям, реакциям скролл смещался в конец страницы

Ну это явно какой-то баг. Воспроизвести его у себя не могу.

Ты пробовал в браузере с чистым конфигом зайти? Там воспроизводится?

Если нет, то понятно, что проблема с текущим сетапом. В нём для начала я бы попробовал отключить ВСЕ экстеншены. Если тоже починилось — включать половину, и так бинарным поиском найти, какое приводит к проблеме. Ну и уже обладая этой информацией — чинить.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Непонятно в чем разница. И да, в новом профиле все работает как надо. В старом профиле я отключил все что мог, но нет - скролл сломан. Короче, непонятно. Я пока профиль сбрасывать не буду - очень уж много на него завязано.

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от LightDiver

Полностью все экстеншены отключал? Особенно всякие ViolentMonkey. Но для теста лучше прям все.

Если и с отключенными экстеншенами баг есть, а на чистом профиле нет, значит где-то в конфиге проблема. about:config, там включить галочку «Only show modified» — получишь список настроек, отличающихся от дефолта. Ну вот можно их по одной в дефолт сбрасывать и смотреть, не починилось ли. Но да, это долго и нудно. Хотя можно среди них попробовать угадать, что может таки к проблеме относиться, а что явно нет.

Как вариант: в новый профиль скопировать из старого perfs.js. Если проблема воспроизведётся — удалить из этого perfs.js половину строк. Если снова воспроизводится — ещё половину. Ну и так бинарным поиском найти, будет быстрее, чем перебирать по одной. И потом уже зная, что к этому ведёт, починить в основном профиле.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 2)
Ответ на: комментарий от CrX

https://github.com/unreg/lorpa

Все, нашел. Это оно все ломало. Я уже и забыл про него. Лучше перепишу сам вручную и доведу до ума. Спасибо за подсказку

LightDiver ★★★★★
() автор топика
Ответ на: комментарий от CrX

Ух, я этот аддончик добавил много лет назад, кода у меня был сломан скролл мыши. Он добавлял стрелки прокрутки вверх вниз, что мне тогда было очень удобно. В итоге стрелки сломались и давно не наботали, параллельно он сломал прокрутку к комментарию. А все эти годы мучился.

// ==UserScript==
// @name         LOR Navigation Panel
// @namespace    lorf
// @match        *://www.linux.org.ru/*
// @grant        none
// @inject-into  content
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    function addPanel() {
        if (document.querySelector('.lor-panel-container')) return;

        function goToMyLastComment() {
            const profileLink = document.querySelector('a[href*="/people/"][href*="/profile"]');
            let myNick = null;

            if (profileLink) {
                myNick = profileLink.textContent.trim();
            } else {
                const myComments = document.querySelectorAll('article.msg.comments-owner, article.msg.own');
                if (myComments.length > 0) {
                    const link = myComments[0].querySelector('a[href*="/people/"]');
                    if (link) myNick = link.textContent.trim();
                }
            }

            if (!myNick) {
                alert('Не удалось определить ваш ник.');
                return;
            }

            const allComments = document.querySelectorAll('article.msg');
            let lastMyComment = null;

            allComments.forEach(function(comment) {
                const authorLink = comment.querySelector('a[href*="/people/"]');
                if (authorLink && authorLink.textContent.trim() === myNick) {
                    lastMyComment = comment;
                }
            });

            if (lastMyComment) {
                lastMyComment.scrollIntoView({ behavior: 'smooth', block: 'start' });
                lastMyComment.style.outline = '3px solid #4a90d9';
                setTimeout(function() { lastMyComment.style.outline = ''; }, 3000);
            } else {
                alert('Ваших комментариев на этой странице нет.');
            }
        }

        function getProfileUrl() {
            const profileLink = document.querySelector('a[href*="/people/"][href*="/profile"]');
            if (profileLink) return profileLink.href;
            return 'https://www.linux.org.ru/people/';
        }

        function updateNotificationBadge(badge) {
            const countEl = document.getElementById('main_events_count');
            if (countEl) {
                const count = parseInt(countEl.textContent) || 0;
                if (count > 0) {
                    badge.textContent = count;
                    badge.style.display = 'flex';
                } else {
                    badge.style.display = 'none';
                }
            } else {
                badge.style.display = 'none';
            }
        }

        const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
        const size = 54;

        const container = document.createElement('div');
        container.className = 'lor-panel-container';
        container.style.cssText = 'position:fixed !important;top:90px !important;z-index:9999 !important;display:flex !important;flex-direction:column !important;gap:8px !important;right:' + (scrollbarWidth + 20) + 'px !important;';

        function createButton(text, title, callback, marginBottom) {
            const btn = document.createElement('div');
            btn.textContent = text;
            btn.title = title;
            btn.style.cssText = 'width:' + size + 'px !important;height:' + size + 'px !important;background:#000080 !important;color:#ffffff !important;border-radius:50% !important;display:flex !important;align-items:center !important;justify-content:center !important;cursor:pointer !important;font-size:24px !important;user-select:none !important;opacity:0.6 !important;position:relative !important;' + (marginBottom ? 'margin-bottom:30px !important;' : '');
            btn.onmouseenter = function() { this.style.opacity = '1'; this.style.background = '#0000a0'; };
            btn.onmouseleave = function() { this.style.opacity = '0.6'; this.style.background = '#000080'; };
            btn.onclick = callback;
            return btn;
        }

        function createBadge() {
            const badge = document.createElement('span');
            badge.style.cssText = 'position:absolute !important;top:-4px !important;right:-4px !important;background:#ff0000 !important;color:#ffffff !important;border-radius:10px !important;min-width:18px !important;height:18px !important;font-size:11px !important;display:none !important;align-items:center !important;justify-content:center !important;padding:0 4px !important;font-weight:bold !important;';
            return badge;
        }

        // Кнопка "Профиль" (самая верхняя, с отступом 30px)
        container.appendChild(createButton('👤', 'Профиль', function() { location.href = getProfileUrl(); }, true));

        // Кнопка "Наверх"
        container.appendChild(createButton('▲', 'Наверх', function() { window.scrollTo({ top: 0, behavior: 'smooth' }); }));

        // Кнопка "Форум"
        container.appendChild(createButton('📋', 'Форум', function() { location.href = 'https://www.linux.org.ru/forum/'; }));

        // Кнопка "Трекер"
        container.appendChild(createButton('☰', 'Трекер', function() { location.href = 'https://www.linux.org.ru/tracker/'; }));

        // Кнопка "Уведомления" с бейджем
        const notifBtn = createButton('🔔', 'Уведомления', function() { location.href = 'https://www.linux.org.ru/notifications'; });
        const notifBadge = createBadge();
        notifBtn.appendChild(notifBadge);
        container.appendChild(notifBtn);
        updateNotificationBadge(notifBadge);
        setInterval(function() { updateNotificationBadge(notifBadge); }, 5000);

        // Кнопка "К моему сообщению"
        container.appendChild(createButton('💬', 'К моему последнему сообщению', goToMyLastComment));

        // Кнопка "Вниз"
        container.appendChild(createButton('▼', 'Вниз', function() { window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); }));

        document.body.appendChild(container);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() { setTimeout(addPanel, 500); });
    } else {
        setTimeout(addPanel, 500);
    }

    let attempts = 0;
    const interval = setInterval(function() {
        if (document.body && document.querySelector('article.msg')) {
            clearInterval(interval);
            addPanel();
        }
        if (++attempts > 20) clearInterval(interval);
    }, 250);

})();

Вот, наклепал себе быстренько. Дарю. Три новые кнопки - вверх, вниз и к последнему комментарию со своим ником.

LightDiver ★★★★★
() автор топика
Последнее исправление: LightDiver (всего исправлений: 3)
Ответ на: комментарий от LightDiver

Даже так:

// ==UserScript==
// @name         LOR Navigation Panel
// @namespace    lorf
// @match        *://www.linux.org.ru/*
// @grant        none
// @inject-into  content
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    function addPanel() {
        if (document.querySelector('.lor-panel-container')) return;

        function goToMyLastComment() {
            const profileLink = document.querySelector('a[href*="/people/"][href*="/profile"]');
            let myNick = null;

            if (profileLink) {
                myNick = profileLink.textContent.trim();
            } else {
                const myComments = document.querySelectorAll('article.msg.comments-owner, article.msg.own');
                if (myComments.length > 0) {
                    const link = myComments[0].querySelector('a[href*="/people/"]');
                    if (link) myNick = link.textContent.trim();
                }
            }

            if (!myNick) {
                alert('Не удалось определить ваш ник.');
                return;
            }

            const allComments = document.querySelectorAll('article.msg');
            let lastMyComment = null;

            allComments.forEach(function(comment) {
                const authorLink = comment.querySelector('a[href*="/people/"]');
                if (authorLink && authorLink.textContent.trim() === myNick) {
                    lastMyComment = comment;
                }
            });

            if (lastMyComment) {
                lastMyComment.scrollIntoView({ behavior: 'smooth', block: 'start' });
                lastMyComment.style.outline = '3px solid #4a90d9';
                setTimeout(function() { lastMyComment.style.outline = ''; }, 3000);
            } else {
                alert('Ваших комментариев на этой странице нет.');
            }
        }

        function scrollToLastMod() {
            const lastmod = new URL(location.href).searchParams.get('lastmod');
            if (!lastmod) return;
            const el = document.getElementById('comment-' + lastmod);
            if (el) {
                el.scrollIntoView({ behavior: 'smooth', block: 'start' });
                el.style.outline = '3px solid #4a90d9';
                setTimeout(function() { el.style.outline = ''; }, 3000);
            }
        }

        function getProfileUrl() {
            const profileLink = document.querySelector('a[href*="/people/"][href*="/profile"]');
            if (profileLink) return profileLink.href;
            return 'https://www.linux.org.ru/people/';
        }

        function updateNotificationBadge(btn) {
            const countEl = document.getElementById('main_events_count');
            const raw = countEl ? countEl.textContent : '(0)';
            const count = parseInt(raw.replace(/[^0-9]/g, '')) || 0;
            btn.textContent = count > 0 ? count : '🔔';
            btn.style.background = count > 0 ? '#cc0000' : '#000080';
            btn.onmouseenter = function() { this.style.opacity = '1'; this.style.background = count > 0 ? '#ff0000' : '#0000a0'; };
            btn.onmouseleave = function() { this.style.opacity = '0.6'; this.style.background = count > 0 ? '#cc0000' : '#000080'; };
        }

        const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
        const size = 54;

        const container = document.createElement('div');
        container.className = 'lor-panel-container';
        container.style.cssText = 'position:fixed !important;top:100px !important;z-index:9999 !important;display:flex !important;flex-direction:column !important;gap:8px !important;right:' + (scrollbarWidth + 20) + 'px !important;';

        function createButton(text, title, callback, marginBottom) {
            const btn = document.createElement('div');
            btn.textContent = text;
            btn.title = title;
            btn.style.cssText = 'width:' + size + 'px !important;height:' + size + 'px !important;background:#000080 !important;color:#ffffff !important;border-radius:50% !important;display:flex !important;align-items:center !important;justify-content:center !important;cursor:pointer !important;font-size:24px !important;user-select:none !important;opacity:0.6 !important;position:relative !important;' + (marginBottom ? 'margin-bottom:30px !important;' : '');
            btn.onmouseenter = function() { this.style.opacity = '1'; this.style.background = '#0000a0'; };
            btn.onmouseleave = function() { this.style.opacity = '0.6'; this.style.background = '#000080'; };
            btn.onclick = callback;
            return btn;
        }

        container.appendChild(createButton('👤', 'Профиль', function() { location.href = getProfileUrl(); }, true));
        container.appendChild(createButton('▲', 'Наверх', function() { window.scrollTo({ top: 0, behavior: 'smooth' }); }));
        container.appendChild(createButton('📋', 'Форум', function() { location.href = 'https://www.linux.org.ru/forum/'; }));
        container.appendChild(createButton('☰', 'Трекер', function() { location.href = 'https://www.linux.org.ru/tracker/'; }));

        const notifBtn = createButton('🔔', 'Уведомления', function() { location.href = 'https://www.linux.org.ru/notifications'; });
        container.appendChild(notifBtn);
        updateNotificationBadge(notifBtn);
        setInterval(function() { updateNotificationBadge(notifBtn); }, 5000);

        container.appendChild(createButton('💬', 'К моему последнему сообщению', goToMyLastComment));
        container.appendChild(createButton('▼', 'Вниз', function() { window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); }));

        document.body.appendChild(container);
    }

    function scrollToLastMod() {
        const lastmod = new URL(location.href).searchParams.get('lastmod');
        if (!lastmod) return;
        const el = document.getElementById('comment-' + lastmod);
        if (el) {
            el.scrollIntoView({ behavior: 'smooth', block: 'start' });
            el.style.outline = '3px solid #4a90d9';
            setTimeout(function() { el.style.outline = ''; }, 3000);
        }
    }

    window.addEventListener('load', function() {
        setTimeout(scrollToLastMod, 1000);
    });

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() { setTimeout(addPanel, 500); });
    } else {
        setTimeout(addPanel, 500);
    }

    let attempts = 0;
    const interval = setInterval(function() {
        if (document.body && document.querySelector('article.msg')) {
            clearInterval(interval);
            addPanel();
        }
        if (++attempts > 20) clearInterval(interval);
    }, 250);

})();
LightDiver ★★★★★
() автор топика
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)