Onche Auto-Refresh

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

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

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