import { browser } from '$app/environment'; import root from '$lib/Utility/root'; import { get, writable } from 'svelte/store'; import settingsSyncPulled from './settingsSyncPulled'; import settingsSyncTimes from './settingsSyncTimes'; import identity from './identity'; const VERSION = '1.0.1'; export interface Settings { cacheMangaMinutes: number; cacheMinutes: number; displayUpcomingAnimeCollapsed: boolean; displayAnimeCollapsed: boolean; displayMangaCollapsed: boolean; displayNotStarted: boolean; displayUnresolved: boolean; calculateChaptersRoundedDown: boolean; displaySortedByDifference: boolean; displayOutboundLinksTo: 'anilist' | 'livechartme' | 'animeschedule' | 'myanimelist'; displayPausedMedia: boolean; displayLimitListHeight: boolean; displaySocialButton: boolean; calculateGuessingDisabled: boolean; displayHoverNavigation: boolean; displayTitleFormat: 'english' | 'romaji' | 'native'; calculateGuessMethod: 'median' | 'iqr_median' | 'iqr_mode' | 'mode'; calculateDisableOutOfDateVolumeWarning: boolean; calculatePreferNativeChapterCount: boolean; displayPlannedAnime: boolean; displayFurigana: boolean; displayAoButa: | 'kaede' | 'mai' | 'mai_2' | 'nodoka' | 'rio' | 'sakuta' | 'shouko' | 'tomoe' | 'random' | 'none'; disableManga: boolean; disableAnime: boolean; disableUpcomingAnime: boolean; display24HourTime: boolean; displayCountdownRightAligned: boolean; displayNativeCountdown: boolean; displayHoverCover: boolean; displayDisableAnimations: boolean; displayDisableNotifications: boolean; displayCoverModeAnime: boolean; displayCoverModeManga: boolean; displayCoverWidth: number; displayShortCountdown: boolean; displayScheduleListMode: boolean; displayLanguage: 'en' | 'ja'; displayDisableLastActivityWarning: boolean; settingsSync: boolean; settingsVersion?: string; displayBlurAdultContent: boolean; displayCopyMediaTitleNotLink: boolean; displayTotalDueEpisodes: boolean; displayAniListNotifications: boolean; } const defaultSettings: Settings = { // Display displayOutboundLinksTo: 'anilist', displayPausedMedia: true, displayPlannedAnime: true, displayLimitListHeight: false, displaySocialButton: false, displayUnresolved: false, displayTitleFormat: 'english', displayFurigana: false, displayHoverNavigation: false, displayNotStarted: false, displayUpcomingAnimeCollapsed: false, displayAnimeCollapsed: false, displayMangaCollapsed: false, displaySortedByDifference: false, displayAoButa: 'none', disableManga: false, disableAnime: false, disableUpcomingAnime: false, display24HourTime: false, displayCountdownRightAligned: false, displayNativeCountdown: false, displayHoverCover: false, displayDisableAnimations: false, displayDisableNotifications: false, displayCoverModeAnime: true, displayCoverModeManga: true, displayCoverWidth: 100, // 116.609 displayShortCountdown: false, displayScheduleListMode: false, displayLanguage: 'en', displayDisableLastActivityWarning: false, displayBlurAdultContent: true, displayCopyMediaTitleNotLink: false, displayTotalDueEpisodes: false, displayAniListNotifications: false, // Calculation calculateChaptersRoundedDown: true, calculateDisableOutOfDateVolumeWarning: false, calculateGuessingDisabled: true, calculateGuessMethod: 'iqr_mode', calculatePreferNativeChapterCount: false, // Cache cacheMangaMinutes: 120, cacheMinutes: 30, // Sync settingsSync: false, settingsVersion: VERSION }; const createStore = () => { const { subscribe, set, update } = writable( JSON.parse( browser ? localStorage.getItem('settings') ?? JSON.stringify(defaultSettings) : JSON.stringify(defaultSettings) ) ); let state: Settings; subscribe((value) => (state = value)); return { subscribe, set, update, reset: () => set(defaultSettings), get: () => { const keys = Object.keys(defaultSettings); const settingsKeys = Object.keys(state); const updatedSettings = { ...state }; for (const key of keys) if (!settingsKeys.includes(key)) (updatedSettings[key as keyof Settings] as unknown) = defaultSettings[key as keyof Settings]; if (browser) localStorage.setItem('settings', JSON.stringify(updatedSettings)); return updatedSettings; }, setKey: (key: keyof Settings, value: unknown) => update((settings) => ({ ...settings, [key]: value })) }; }; const settings = createStore(); settings.subscribe((value) => { if (browser) localStorage.setItem('settings', JSON.stringify(value)); if (value.settingsSync && get(settingsSyncPulled) == true) fetch(root(`/api/configuration?id=${get(identity).id}`)).then((response) => { if (response.ok) response.json().then((data) => { const isEqualsJson = (object1: Settings, object2: Settings) => { type AnyObject = { [key: string]: unknown }; return ( Object.keys(object1).length === Object.keys(object2).length && Object.keys(object1).every( (key) => (object1 as unknown as AnyObject)[key] == (object2 as unknown as AnyObject)[key] ) ); }; if (data && data.configuration && !isEqualsJson(data.configuration, value)) { fetch(root(`/api/configuration`), { method: 'PUT', body: JSON.stringify(value) }).then((response) => { if (response.ok) console.log('Pushed local configuration'); settingsSyncTimes.update((times) => ({ ...times, lastPush: new Date() })); }); } }); }); }); export default settings;