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();
    }
})();