/* * tonalmine: per-user appearance (mode + color palette). * * Redmine loads this file in
, so the saved choice is applied before the page renders * (no flash of the default colors). The picker is added to the profile menu and the mobile * flyout. The choice is stored per browser in localStorage. */ (function () { // Ids must match PALETTES in tools/palettes/build_palettes.mjs (the build checks this). var PALETTES = [ ['purple', 'Purple', '#6750A4'], ['blue', 'Blue', '#0061A4'], ['teal', 'Teal', '#006A6A'], ['green', 'Green', '#386A20'], ['orange', 'Orange', '#8B5000'] ]; var MODES = [['auto', 'Auto'], ['light', 'Light'], ['dark', 'Dark']]; var KEY = 'tonalmine'; var root = document.documentElement; function load() { try { return JSON.parse(localStorage.getItem(KEY)) || {}; } catch (e) { return {}; } } function save(prefs) { try { localStorage.setItem(KEY, JSON.stringify(prefs)); } catch (e) { /* private mode: applies to this page only */ } } function apply(prefs) { if (prefs.palette && prefs.palette !== PALETTES[0][0]) root.setAttribute('data-palette', prefs.palette); else root.removeAttribute('data-palette'); if (prefs.mode === 'light' || prefs.mode === 'dark') root.setAttribute('data-mode', prefs.mode); else root.removeAttribute('data-mode'); } var prefs = load(); apply(prefs); function button(attr, value, label, pressed, extra) { return ''; } function pickerHtml() { var mode = prefs.mode || 'auto'; var palette = prefs.palette || PALETTES[0][0]; return '