MediaWiki:Gadget-DarkModeSwitch.js

From The Fifth City Wiki
Revision as of 13:32, 28 June 2025 by CarrONoir (talk | contribs) (Created page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
;(function () {
  const themeStorageKey = 'fcw-theme';
  const gadgetThemeDark = 'gadget-DarkMode';
  const gadgetThemeLight = 'gadget-LightMode';
  const themeAttribute = 'data-fcw-theme';
  const mwApi = new mw.Api();

  const currentTheme = getCurrentTheme();
  if (currentTheme) {
    document.documentElement.setAttribute(themeAttribute, currentTheme);
  }
  const themeToggleSwitchIsChecked = currentTheme === 'dark';

  const themeToggleSwitch = new OO.ui.ToggleSwitchWidget({
    classes: ['fcw-theme-toggle'],
    title: 'Toggle dark mode',
    value: themeToggleSwitchIsChecked,
  });
  themeToggleSwitch.on('change', switchTheme);

  const brightIcon = document.createElement('span');
  brightIcon.innerHTML =
    '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><title>bright</title><path d="M17.07 7.07V2.93h-4.14L10 0 7.07 2.93H2.93v4.14L0 10l2.93 2.93v4.14h4.14L10 20l2.93-2.93h4.14v-4.14L20 10zM10 16a6 6 0 116-6 6 6 0 01-6 6z"/><circle cx="10" cy="10" r="4.5"/></svg>';
  const brightIconWidget = new OO.ui.Widget({
    classes: ['fcw-theme-icon', 'fcw-theme-icon-bright'],
    content: [brightIcon],
  });

  const darkIcon = document.createElement('span');
  darkIcon.innerHTML =
    '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><title>moon</title><path d="M17.39 15.14A7.33 7.33 0 0111.75 1.6c.23-.11.56-.23.79-.34a8.19 8.19 0 00-5.41.45 9 9 0 107 16.58 8.42 8.42 0 004.29-3.84 5.3 5.3 0 01-1.03.69z"/></svg>';
  const darkIconWidget = new OO.ui.Widget({
    classes: ['fcw-theme-icon', 'fcw-theme-icon-dark'],
    content: [darkIcon],
  });

  const themeWidget = new OO.ui.HorizontalLayout({
    classes: ['fcw-theme-widget-container'],
    items: [brightIconWidget, themeToggleSwitch, darkIconWidget],
  });
  $('#p-navigation').before(themeWidget.$element);

  // ----*----
  function getCurrentTheme() {
    if (!mw.user.isAnon()) {
      return mw.user.options.get(gadgetThemeDark) ? 'dark' : 'light';
    }
    const storedPref = mw.storage.get(themeStorageKey);
    return storedPref ? storedPref : undefined;
  }

  function switchTheme(value) {
    const nextTheme = value ? 'dark' : 'light';
    setTheme(nextTheme);
  }

  function setTheme(theme) {
    document.documentElement.setAttribute(themeAttribute, theme);
    mw.storage.set(themeStorageKey, theme);
    if (!mw.user.isAnon()) {
      const options = {};
      options[gadgetThemeDark] = theme === 'dark' ? 1 : 0;
      options[gadgetThemeLight] = theme === 'light' ? 1 : 0;
      mwApi.saveOptions(options);
    }
  }
})();