Source: stores/settings.js

/*
 * Copyright © 2024-2025 The CTAN Team and individual authors
 *
 * This file is distributed under the 3-clause BSD license.
 * See file LICENSE for details.
 */
import { defineStore } from 'pinia'

/**
 * The fallback values for the state parameters if the local storage is not set.
 */
const stateFallback = {
  animationSpeed: 2,
  locale: 'en',
  shurtcuts: true,
  showIcons: true,
  showImages: true,
  texLogos: true,
  theme: 'light',
  view: 'tiles'
}

let stored = localStorage.getItem('ctan.settings')
if (stored) {
  stored = JSON.parse(stored)
} else {
  stored = stateFallback
  localStorage.setItem('ctan.settings', JSON.stringify(stored))
}

/**
 * This is the store for user settings of the CTAN portal.
 *
 * @author Gerd Neugebauer <gene@ctan.org>
 */
export const useSettingsStore = defineStore('settings', {
  state: () => ({
    /**
     * The indicator for the animation speed.
     */
    animationSpeed: stored.animationSpeed,
    
    /**
     * The locale. Supported values are at least 'en' and 'de'.
     */
    locale: stored.locale,

    /**
     * The boolean indicator for keyboard shortcuts.
     */
    shortcuts: stored.shortcuts,

    /**
     * The boolean indicator for icons.
     */
    showIcons: stored.showIcons,

    /**
     * The boolean indicator for images.
     */
    showImages: stored.showImages,

    /**
     * The boolean indicator for TeX logos.
     */
    texLogos: stored.texLogos,

    /**
     * The theme. Supporte values are 'light' and 'dark'.
     */
    theme: stored.theme,

    /**
     * The view. Supported values are 'tiles' and 'list'
     */
    view: stored.view
  }),

  actions: {
    /**
     * Return the name of the icon or the empty string.
     * 
     * @param {*} icon the name of the icon 
     */
    icon (icon) {
      return this.showIcons ? icon : ''
    },

    /**
     * Intialise external variables for locale and theme.
     *
     * @param {*} vuetify the vuetify instance
     * @param {*} i18n the i18n instance
     */
    init (vuetify, i18n) {
      i18n.locale = this.locale
      vuetify.theme.global.name = this.theme
    },

    /**
     * Load the settings from local storage into memory.
     */
    load () {
      const stored = localStorage.getItem('ctan.settings')
      if (stored !== undefined)  {
        stored = JSON .parse(stored)
        this.animationSpeed = stored.animationSpeed
        this.locale = stored.locale
        this.i18n.locale = stored.locale
        this.showIcons = stored.showIcons
        this.showImages = stored.showImages
        this.texLogos = stored.texLogos
        this.theme = stored.theme
        this.view = stored.view
      }
    },

    /**
     * Setter for the animation speed to the next value.
     */
    nextAnimationSpeed () {
      this.animationSpeed = (this.animationSpeed + 1) % 4
      this.save()
    },

    /**
     * Save all settings in the local storage.
     */
    save () {
      localStorage.setItem('ctan.settings', JSON.stringify(this.$state))
    },

    /**
     * Setter for the locale.
     *
     * @param {*} locale the new locale
     */
    setLocale (locale, i18n) {
      this.locale = locale
      i18n.locale = locale
      this.save()
    },

    /**
     * Setter for the theme.
     *
     * @param {*} theme the new theme
     */
    setTheme (t, theme) {
      this.theme = t
      theme.global.name = t
      this.save()
    },

    /**
     * Setter for the view.
     *
     * @param {*} view the new view
     */
    setView (t, view) {
      this.view = t
      this.save()
    },

    /**
     * Setter for the shortcuts flag to the other value.
     */
    toggleShortcuts () {
      this.shortcuts = !this.shortcuts
      this.save()
    },

    /**
     * Setter for the show icons flag to the other value.
     */
    toggleShowIcons () {
      this.showIcons = !this.showIcons
      this.save()
    },

    /**
     * Setter for the show images flag to the other value.
     */
    toggleShowImages () {
      this.showImages = !this.showImages
      this.save()
    },

    /**
     * Setter for the TeX logos flag to the other value.
     */
    toggleTexLogos () {
      this.texLogos = !this.texLogos
      this.save()
    },

    /**
     * Setter for the theme. The next theme is used.
     */
    toggleTheme () {
      this.theme = (this.theme === 'light' ? 'dark' : 'light')
      this.save()
      return this.theme
    }
  }
})