Research-Stack/2-Search-Space/search/stract/frontend/src/lib/stores.ts

96 lines
3.2 KiB
TypeScript

import { browser } from '$app/environment';
import { writable } from 'svelte/store';
import type { OpticOption } from './optics';
import type { SiteRankings } from './rankings';
const parseJSONWithFallback = <T>(json: string, fallback: T, message = '') => {
try {
return JSON.parse(json);
} catch (e) {
if (message) console.warn(message, { json });
return fallback;
}
};
const writableLocalStorage = <T>(
key: string,
defaultValue: T,
storage = browser && localStorage,
) => {
const storedValue = storage && storage.getItem(key);
const store = writable<T>(
typeof storedValue == 'string'
? parseJSONWithFallback(storedValue, defaultValue, `Failed to parse value stored in '${key}'`)
: defaultValue,
);
store.subscribe(($value) => {
if (browser && storage) {
if (typeof $value == 'undefined') {
storage.removeItem(key);
} else {
storage.setItem(key, JSON.stringify($value));
}
}
});
const { set } = store;
store.set = (value: T) => {
if (storage) {
set(value);
}
};
return store;
};
const SAFE_SEARCH_KEY = 'safeSearch';
export const safeSearchStore = writableLocalStorage<boolean>(SAFE_SEARCH_KEY, false);
const POST_SEARCH_KEY = 'postSearch';
export const postSearchStore = writableLocalStorage<boolean>(POST_SEARCH_KEY, false);
const OPTICS_KEY = 'optics';
export const opticsStore = writableLocalStorage<OpticOption[]>(OPTICS_KEY, []);
const OPTICS_SHOW_KEY = 'opticsShow';
export const opticsShowStore = writableLocalStorage<Record<string, boolean>>(OPTICS_SHOW_KEY, {});
const ALLOW_STATS_KEY = 'allowStats';
export const allowStatsStore = writableLocalStorage<boolean>(ALLOW_STATS_KEY, true);
const HOST_RANKINGS_KEY = 'host_rankings';
export const hostRankingsStore = writableLocalStorage<SiteRankings>(HOST_RANKINGS_KEY, {});
const SEARCH_QUERY_KEY = 'searchQuery';
export const searchQueryStore = writableLocalStorage<string | undefined>(SEARCH_QUERY_KEY, void 0);
const QUERY_ID_KEY = 'queryId';
export const queryIdStore = writableLocalStorage<string | undefined>(QUERY_ID_KEY, void 0);
const MARK_PAGES_WITH_ADS_KEY = 'markPagesWithAds';
export const markPagesWithAdsStore = writableLocalStorage<boolean>(MARK_PAGES_WITH_ADS_KEY, false);
const RESULTS_IN_NEW_TAB_KEY = 'resultsInNewTab';
export const resultsInNewTab = writableLocalStorage<boolean>(RESULTS_IN_NEW_TAB_KEY, false);
const USE_KEYBOARD_SHORTCUTS = 'useKeyboardShortcuts';
export const useKeyboardShortcuts = writableLocalStorage<boolean>(USE_KEYBOARD_SHORTCUTS, true);
const SHOW_RANKINGS_SIGNALS = 'showRankingSignals';
export const showRankingSignals = writableLocalStorage<boolean>(SHOW_RANKINGS_SIGNALS, false);
const MARK_PAGES_WITH_PAYWALL_KEY = 'markPagesWithPaywall';
export const markPagesWithPaywallStore = writableLocalStorage<boolean>(
MARK_PAGES_WITH_PAYWALL_KEY,
true,
);
const THEME_KEY = 'theme';
export const themeStore = writableLocalStorage<string | void>(THEME_KEY, void 0);
if (browser)
themeStore?.subscribe(($theme) => {
const c = document.documentElement.className.replace(/theme-[^ ]+/, ``);
const theme = $theme?.toLowerCase() || '';
document.documentElement.className = `${c} ${theme}`.trim();
});