All files / src/features/theme/model theme.ts

87.09% Statements 27/31
66.66% Branches 8/12
100% Functions 8/8
86.66% Lines 26/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77      2x 2x       2x           3x       3x     3x 3x 3x             5x     5x 5x           2x     2x 2x           2x 5x 5x 5x     3x 3x 3x       2x 2x 2x 2x     5x                
import { computed, ref } from "vue";
import { defineStore } from "pinia";
 
export const THEME_STORAGE_KEY = "sujianji-theme";
export const DEFAULT_THEME = "qinghe";
 
export type StorefrontTheme = "subai" | "qinghe";
 
const THEME_COLORS: Record<StorefrontTheme, string> = {
  subai: "#f7f7f5",
  qinghe: "#f2f7f6",
};
 
function isStorefrontTheme(value: string | null): value is StorefrontTheme {
  return value === "subai" || value === "qinghe";
}
 
function readStoredTheme(): StorefrontTheme {
  Iif (typeof localStorage === "undefined") {
    return DEFAULT_THEME;
  }
  try {
    const stored = localStorage.getItem(THEME_STORAGE_KEY);
    return isStorefrontTheme(stored) ? stored : DEFAULT_THEME;
  } catch {
    return DEFAULT_THEME;
  }
}
 
function applyTheme(theme: StorefrontTheme) {
  Iif (typeof document === "undefined") {
    return;
  }
  document.documentElement.dataset.pjTheme = theme;
  document
    .querySelector<HTMLMetaElement>('meta[name="theme-color"]')
    ?.setAttribute("content", THEME_COLORS[theme]);
}
 
function persistTheme(theme: StorefrontTheme) {
  Iif (typeof localStorage === "undefined") {
    return;
  }
  try {
    localStorage.setItem(THEME_STORAGE_KEY, theme);
  } catch {
    // The selected theme still applies for the current page when storage is unavailable.
  }
}
 
export const useThemeStore = defineStore("storefront-theme", () => {
  const theme = ref<StorefrontTheme>(DEFAULT_THEME);
  const initialized = ref(false);
  const label = computed(() => theme.value === "qinghe" ? "青荷" : "素白");
 
  function initialize() {
    theme.value = readStoredTheme();
    applyTheme(theme.value);
    initialized.value = true;
  }
 
  function setTheme(nextTheme: StorefrontTheme) {
    theme.value = nextTheme;
    applyTheme(nextTheme);
    persistTheme(nextTheme);
    initialized.value = true;
  }
 
  return {
    theme,
    initialized,
    label,
    initialize,
    setTheme,
  };
});