Onche Auto-Refresh

Actualise la liste des sujets sur Onche. Intègre une icône d'engrenage discrète pour les réglages.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Onche Auto-Refresh
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Actualise la liste des sujets sur Onche. Intègre une icône d'engrenage discrète pour les réglages.
// @author       Bkz1
// @match        https://onche.org/*
// @license MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ==========================================
    // PARAMÈTRES ET VARIABLES GLOBALES
    // ==========================================

    const TOPIC_LIST_SELECTOR = '.topics';
    let intervalTimerId = null;
    let refreshIntervalSeconds = parseInt(localStorage.getItem('onche_refresh_interval')) || 30;

    // ==========================================
    // LOGIQUE DE RAFRAÎCHISSEMENT (AJAX)
    // ==========================================

    function refreshTopics() {
        const currentUrl = window.location.href;

        fetch(currentUrl)
            .then(response => {
                if (!response.ok) throw new Error('Erreur réseau');
                return response.text();
            })
            .then(html => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, 'text/html');
                const newTopicList = doc.querySelector(TOPIC_LIST_SELECTOR);
                const currentTopicList = document.querySelector(TOPIC_LIST_SELECTOR);

                if (newTopicList && currentTopicList) {
                    currentTopicList.innerHTML = newTopicList.innerHTML;
                    console.log(`✅ [Auto-Refresh] Sujets mis à jour (Intervalle : ${refreshIntervalSeconds}s)`);
                }
            })
            .catch(error => console.error('⚠️ [Auto-Refresh] Erreur :', error));
    }

    // ==========================================
    // GESTION DU CHRONOMÈTRE
    // ==========================================

    function startTimer() {
        if (intervalTimerId !== null) {
            clearInterval(intervalTimerId);
        }
        intervalTimerId = setInterval(refreshTopics, refreshIntervalSeconds * 1000);
    }

    // ==========================================
    // INTÉGRATION DE L'ENGRENAGE ET DU MENU
    // ==========================================

    function injectSettingsIntoPage() {
        const topicList = document.querySelector(TOPIC_LIST_SELECTOR);
        if (!topicList) return;

        // 1. Création d'un conteneur "wrapper" qui va englober l'icône et le menu
        // Ce conteneur est en "position: relative" pour que le menu puisse s'afficher juste en dessous de lui
        const wrapper = document.createElement('div');
        wrapper.id = 'onche-refresh-wrapper';
        wrapper.style.position = 'relative';
        wrapper.style.display = 'flex';
        wrapper.style.justifyContent = 'flex-end'; // Aligne l'engrenage tout à droite
        wrapper.style.marginBottom = '8px';
        wrapper.style.paddingRight = '5px';

        // 2. Structure HTML : L'icône ⚙️ et le menu caché par défaut (display: none)
        // Les couleurs sont neutres (rgba) pour s'adapter au mode sombre/clair
        wrapper.innerHTML = `
            <div id="onche-gear-icon" title="Réglages Auto-Refresh"
                 style="cursor: pointer; font-size: 18px; opacity: 0.5; transition: all 0.3s ease; user-select: none;">
                ⚙️
            </div>

            <div id="onche-settings-popup"
                 style="display: none; position: absolute; top: 28px; right: 0; background: rgba(30, 30, 30, 0.95);
                        border: 1px solid rgba(255, 255, 255, 0.1); padding: 12px; border-radius: 8px;
                        box-shadow: 0px 8px 16px rgba(0,0,0,0.5); z-index: 1000; color: #eee; width: max-content; font-family: sans-serif;">

                <div style="margin-bottom: 10px; font-size: 13px; font-weight: bold; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 5px;">
                    🔄 Auto-Refresh
                </div>

                <div style="display: flex; gap: 8px; align-items: center;">
                    <input type="number" id="onche-refresh-input" value="${refreshIntervalSeconds}" min="5" max="600"
                           style="width: 50px; padding: 4px; border-radius: 4px; border: 1px solid #555; background: #111; color: white; text-align: center; font-size: 13px;">
                    <span style="font-size: 12px;">secondes</span>
                    <button id="onche-refresh-save"
                            style="cursor: pointer; padding: 4px 10px; border-radius: 4px; border: 1px solid #555; background: #333; color: white; font-size: 12px; font-weight: bold; transition: background 0.2s;">
                        OK
                    </button>
                </div>

                <div id="onche-refresh-feedback" style="color: #4ade80; display: none; font-size: 12px; margin-top: 8px; text-align: center; font-weight: bold;">
                    ✔ Intervalle enregistré
                </div>
            </div>
        `;

        // 3. Insertion dans la page, juste au-dessus de la liste des sujets
        topicList.parentNode.insertBefore(wrapper, topicList);

        // 4. Ciblage des éléments que l'on vient de créer
        const gear = document.getElementById('onche-gear-icon');
        const popup = document.getElementById('onche-settings-popup');
        const saveBtn = document.getElementById('onche-refresh-save');

        // 5. Animations au survol de l'engrenage (opacité et rotation)
        gear.addEventListener('mouseenter', () => {
            gear.style.opacity = '1';
            gear.style.transform = 'rotate(45deg)';
        });
        gear.addEventListener('mouseleave', () => {
            gear.style.opacity = '0.5';
            gear.style.transform = 'rotate(0deg)';
        });

        // 6. Afficher/Cacher le menu quand on clique sur l'engrenage
        gear.addEventListener('click', (event) => {
            event.stopPropagation(); // Empêche le clic de se propager au reste de la page
            const isHidden = popup.style.display === 'none';
            popup.style.display = isHidden ? 'block' : 'none';
        });

        // 7. Cacher le menu si on clique n'importe où ailleurs sur la page (ergonomie)
        document.addEventListener('click', (event) => {
            if (popup.style.display === 'block' && !wrapper.contains(event.target)) {
                popup.style.display = 'none';
            }
        });

        // 8. Sauvegarder les paramètres
        saveBtn.addEventListener('click', () => {
            const inputVal = parseInt(document.getElementById('onche-refresh-input').value, 10);

            if (inputVal >= 5) {
                refreshIntervalSeconds = inputVal;
                localStorage.setItem('onche_refresh_interval', refreshIntervalSeconds);
                startTimer();

                // Animation de confirmation
                const feedback = document.getElementById('onche-refresh-feedback');
                feedback.style.display = 'block';

                // On cache le message de confirmation ET le menu après 1.5 secondes
                setTimeout(() => {
                    feedback.style.display = 'none';
                    popup.style.display = 'none';
                }, 1500);
            } else {
                alert("Pour ne pas surcharger les serveurs, le minimum est de 5 secondes.");
                document.getElementById('onche-refresh-input').value = 5;
            }
        });

        // Effet de survol sur le bouton OK
        saveBtn.addEventListener('mouseenter', () => saveBtn.style.background = '#444');
        saveBtn.addEventListener('mouseleave', () => saveBtn.style.background = '#333');
    }

    // ==========================================
    // INITIALISATION DU SCRIPT
    // ==========================================

    if (document.querySelector(TOPIC_LIST_SELECTOR)) {
        injectSettingsIntoPage();
        startTimer();
    }
})();