Actualise la liste des sujets sur Onche. Intègre une icône d'engrenage discrète pour les réglages.
// ==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();
}
})();