FreshRSS Double-Tap and Auto-Scroll

Double-tap to close active articles and auto-scroll to the active article in FreshRSS.

目前為 2025-02-04 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         FreshRSS Double-Tap and Auto-Scroll
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Double-tap to close active articles and auto-scroll to the active article in FreshRSS.
// @author       Your Name
// @homepage     https://greasyfork.org/en/scripts/525817
// @match        http://192.168.1.2:1030/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Double-tap event to close active articles
    document.addEventListener('dblclick', function (event) {
        // Check if the double-tap is on an interactive element
        const interactiveElements = ['A', 'BUTTON', 'INPUT', 'TEXTAREA', 'SELECT', 'LABEL'];
        if (interactiveElements.includes(event.target.tagName)) {
            return; // Ignore double-taps on interactive elements
        }

        // Find the closest element with both 'current' and 'active' classes
        const activeElement = event.target.closest('.current.active');
        if (activeElement) {
            // Remove the 'active' class
            activeElement.classList.remove('active');
            // console.log('Removed "active" class from:', activeElement);

            // Scroll the page to the closed article (activeElement)
            activeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }
    });

    // Automatically scroll to the active article when it gains the 'active' class
    const observeActiveElements = () => {
        // Set up a MutationObserver to watch for changes to the 'active' class
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    const targetElement = mutation.target;
                    if (targetElement.classList.contains('active')) {
                        // Scroll the active element into view
                        targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    }
                }
            });
        });

        // Observe all elements with the 'current' class (potential candidates for 'active')
        const currentElements = document.querySelectorAll('.current');
        currentElements.forEach((element) => {
            observer.observe(element, { attributes: true });
        });
    };

    // Start observing for changes
    observeActiveElements();
})();