Jake Vanderwerf
2026-01-01 0e4b986e81f8132a44e61fa8df18860301cc3468
assets/js/concise/UserSettings.js
@@ -1,38 +1,130 @@
class UserSettings {
   constructor() {
      this.cache = new window.jvbCache('settings');
      this.cache.loadFromCache();
      this.findSettings();
      this.debouncer = window.debouncer;
      this.isLoggedIn = jvbSettings.currentUser !== null;
      this.isLoggedIn = window.auth.getUser() !== null;
      this.initListeners();
      this.loadSettings();
      this.subscribers = new Set();
   }
   findSettings() {
      this.settings = document.querySelectorAll('[data-setting]')??[];
   }
   addSetting(element, name = '', value = null) {
      name = name === '' ? element.name : name;
      element.dataset.setting = name;
      let cached = this.cache.get(name);
      if (cached) {
         if (element.tagName === 'INPUT' && ['checkbox', 'radio'].includes(element.type)) {
            element.checked = (cached === element.value);
         } else if (element.tagName === 'DETAILS') {
            element.open = (cached === 'on');
         }
      }
      this.debouncer.schedule(
         'add-setting',
         () => {
            this.findSettings.bind(this);
         },
         300
      );
   }
   loadSettings()
   {
      for (const input of this.settings) {
         let setting = input.name;
         if (Object.hasOwn(input.dataset, 'theme')) {
            this.checkTheme(input);
         } else {
            let stored = this.cache.get(setting);
            if (stored) {
               if (input.value === 'on') {
                  input.checked = stored === 'on';
               } else if (['checkbox', 'radio'].includes(input.tagName)) {
                  input.checked = input.value === stored;
               } else {
                  input.value = stored;
               }
            }
         }
      }
   }
   checkTheme(themeSwitch)
   {
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
      let stored = this.cache.get('dark-mode');
      if (prefersDark && (!stored || stored !== 'off')) {
         themeSwitch.checked = true;
      } else if (stored === 'on') {
         themeSwitch.checked = true;
      }
   }
   initListeners() {
      this.changeHandler = this.handleChange.bind(this);
      document.addEventListener('change', this.changeHandler);
   }
   handleChange(e) {
      if (!Object.hasOwn(e.target.dataset, 'setting')) {
         return;
      }
      let value = e.target.value;
      if (e.target.value === 'on') {
         value = e.target.checked ? 'on' : 'off';
      }
      this.saveSetting(e.target.name, value);
   }
   saveSetting(name, value) {
      this.cache.setItem(name, value);
      if (this.isLoggedIn) {
      let old;
      if (this.isLoggedIn){
         old = this.cache.get(name);
      }
      this.cache.set(name, value);
      if (this.isLoggedIn && old && old !== value) {
         this.saveToServer(name, value);
      }
   }
   loadSetting(name) {
      let value = this.cache.getItem(name);
      if (this.isLoggedIn) {
   async saveToServer(name, value)
   {
      if (!this.isLoggedIn || !['dark-mode'].includes(name)){
         return;
      }
      const headers = {
         'X-WP-Nonce': window.auth.getNonce(),
         'Content-Type': 'application/json'
      };
      const body = {
         user: window.auth.getUser(),
         setting: name,
         value: value
      };
      const response = await fetch(
         `${jvbSettings.api}settings`,
      {
            method:  'POST',
            headers: headers,
            body: JSON.stringify(body)
         }
      );
      const result = await response.json();
   }
   loadSetting(name) {
      return this.cache.get(name);
   }
   loadUserSetting(name) {
@@ -60,68 +152,72 @@
   }
}
document.addEventListener('DOMContentLoaded', function() {
   window.jvbUserSettings = new UserSettings();
});
// Theme switching functionality
document.addEventListener('DOMContentLoaded', function() {
   console.log('Theme switch initiated');
   const themeSwitch = document.getElementById('theme-switch');
   if (!themeSwitch) return;
   // Initialize theme from localStorage or system preference
   const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
   const storedTheme = localStorage.getItem('theme');
   if (storedTheme) {
      document.documentElement.classList.toggle('dark', storedTheme === 'dark');
      themeSwitch.checked = storedTheme === 'dark';
   } else {
      document.documentElement.classList.toggle('dark', prefersDark.matches);
      themeSwitch.checked = prefersDark.matches;
   }
   // Handle theme switch changes
   themeSwitch.addEventListener('change', async function () {
      const isDark = this.checked;
      document.documentElement.classList.toggle('dark', isDark);
      localStorage.setItem('theme', isDark ? 'dark' : 'light');
      // If user is logged in, save preference
      if (jvbSettings.currentUser !== null) {
         try {
            await fetch(`${jvbSettings.api}settings`, {
               method: 'POST',
               headers: {
                  'Content-Type': 'application/json',
                  'X-WP-Nonce': jvbSettings.nonce,
                  'action_nonce': jvbSettings.dash,
               },
               body: JSON.stringify({
                  dark_mode: isDark,
                  user: jvbSettings.currentUser
               })
            });
         } catch (error) {
            console.error('Failed to save theme preference:', error);
         }
      }
      // Update label
      const label = document.getElementById('theme-switch');
      if (label) {
         label.title = isDark ? 'Toggle Light Mode' : 'Toggle Dark Mode';
      }
   });
   // Handle system theme changes
   prefersDark.addEventListener('change', (e) => {
      if (!localStorage.getItem('theme')) {
         const isDark = e.matches;
         document.documentElement.classList.toggle('dark', isDark);
         themeSwitch.checked = isDark;
document.addEventListener('DOMContentLoaded', async function() {
   window.auth.subscribe((event) => {
      if (event === 'auth-loaded') {
         window.jvbUserSettings = new UserSettings();
      }
   });
});
//
// // Theme switching functionality
// document.addEventListener('DOMContentLoaded', function() {
//    console.log('Theme switch initiated');
//    const themeSwitch = document.getElementById('theme-switch');
//
//    if (!themeSwitch) return;
//
//    // Initialize theme from localStorage or system preference
//    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
//    const storedTheme = localStorage.getItem('theme');
//
//    if (storedTheme) {
//       document.documentElement.classList.toggle('dark', storedTheme === 'dark');
//       themeSwitch.checked = storedTheme === 'dark';
//    } else {
//       document.documentElement.classList.toggle('dark', prefersDark.matches);
//       themeSwitch.checked = prefersDark.matches;
//    }
//
//    // Handle theme switch changes
//    themeSwitch.addEventListener('change', async function () {
//       const isDark = this.checked;
//       document.documentElement.classList.toggle('dark', isDark);
//       localStorage.setItem('theme', isDark ? 'dark' : 'light');
//
//       // If user is logged in, save preference
//       if (window.auth.getUser() !== null) {
//          try {
//             await fetch(`${jvbSettings.api}settings`, {
//                method: 'POST',
//                headers: {
//                   'Content-Type': 'application/json',
//                   'X-WP-Nonce': window.auth.getNonce(),
//                   'action_nonce': window.auth.getNonce('dash'),
//                },
//                body: JSON.stringify({
//                   dark_mode: isDark,
//                   user: window.auth.getUser()
//                })
//             });
//          } catch (error) {
//             console.error('Failed to save theme preference:', error);
//          }
//       }
//
//       // Update label
//       const label = document.getElementById('theme-switch');
//       if (label) {
//          label.title = isDark ? 'Toggle Light Mode' : 'Toggle Dark Mode';
//       }
//    });
//
//    // Handle system theme changes
//    prefersDark.addEventListener('change', (e) => {
//       if (!localStorage.getItem('theme')) {
//          const isDark = e.matches;
//          document.documentElement.classList.toggle('dark', isDark);
//          themeSwitch.checked = isDark;
//       }
//    });
// });