Onche Auto-Refresh

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

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

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