From af100577c9a25bef66f7233326eab395bea9e0d9 Mon Sep 17 00:00:00 2001 From: William Grant <0x96ea@gmail.com> Date: Wed, 12 Jun 2024 01:51:21 +1000 Subject: [PATCH 01/12] feat: single store with ipc communications added a storage hook for the frontend --- src/main/main.ts | 20 ++++-- src/modules/storage.ts | 63 ++++++++++++++++++ src/modules/storeVariables.ts | 54 ++++++++++------ src/modules/utils.ts | 7 -- src/renderer/App.tsx | 12 ++-- src/renderer/hooks/storage.tsx | 114 +++++++++++++++++++++++++++++++++ 6 files changed, 229 insertions(+), 41 deletions(-) create mode 100644 src/modules/storage.ts create mode 100644 src/renderer/hooks/storage.tsx diff --git a/src/main/main.ts b/src/main/main.ts index 53becebf..fe662839 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -4,14 +4,15 @@ import { autoUpdater } from 'electron-updater'; import path from 'path'; const DiscordRPC = require('discord-rpc'); import { OPEN_NEW_ISSUE_URL, SPONSOR_URL } from '../constants/utils'; -import { getAccessToken } from '../modules/anilist/anilistApi'; +import { fetchAccessToken } from '../modules/anilist/anilistApi'; import { clientData } from '../modules/clientData'; import isAppImage from '../modules/packaging/isAppImage'; import MenuBuilder from './menu'; import { resolveHtmlPath } from './util'; import { OS } from '../modules/os'; +import { setupStore, STORE } from '../modules/storeVariables'; -const STORE = new Store(); +setupStore(); app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors'); @@ -91,8 +92,6 @@ const createWindow = async () => { mainWindow.show(); mainWindow.maximize(); - if (STORE.get('logged') !== true) STORE.set('logged', false); - autoUpdater.checkForUpdates(); } }); @@ -235,7 +234,7 @@ app.on('open-url', async (event, url) => { async function handleLogin(code: any) { try { - const token = await getAccessToken(code); + const token = await fetchAccessToken(code); STORE.set('access_token', token); STORE.set('logged', true); } catch (error: any) { @@ -293,6 +292,17 @@ ipcMain.on('download-update', () => { let pth = autoUpdater.downloadUpdate(); }); +ipcMain.handle('getStoreValue', (_, key) => { + const value = STORE.get(key); + console.log('store - get', key, value); + return value; +}); + +ipcMain.handle('setStoreValue', (_, key, value) => { + console.log('store - set', key, value); + return STORE.set(key, value); +}); + /* DISCORD RPC */ const clientId = '1212475013408628818'; diff --git a/src/modules/storage.ts b/src/modules/storage.ts new file mode 100644 index 00000000..27cf91c6 --- /dev/null +++ b/src/modules/storage.ts @@ -0,0 +1,63 @@ +// only use on renderer side + +import { ipcRenderer } from "electron"; +import { DEFAULTS, LanguageOptions, StoreKeys } from "./storeVariables"; + +const getLogged = async (): Promise => { + const logged = await ipcRenderer.invoke('getStoreValue', 'logged'); + return logged; +} + +const getAccessToken = async (): Promise => { + const token = await ipcRenderer.invoke('getStoreValue', 'access_token'); + return token || ''; +}; + +const getUpdateProgress = async ():Promise => { + const progress = await ipcRenderer.invoke('getStoreValue', 'update_progress'); + return progress; +} + +const getDubbed = async (): Promise => { + const dubbed = await ipcRenderer.invoke('getStoreValue', 'dubbed'); + return dubbed || DEFAULTS.dubbed; +} + +const getSourceFlag = async (): Promise => { + const sourceFlag = await ipcRenderer.invoke('getStoreValue', 'source_flag'); + return sourceFlag || DEFAULTS.source_flag; +}; + +const getIntroSkipTime = async (): Promise => { + const introSkipTime = await ipcRenderer.invoke('getStoreValue', 'intro_skip_time'); + return introSkipTime || DEFAULTS.intro_skip_time; +} + +const getShowDuration = async (): Promise => { + const showDuration = await ipcRenderer.invoke('getStoreValue', 'show_duration'); + return showDuration || DEFAULTS.show_duration; +} + +const getTrailerVolumeOn = async (): Promise => { + const trailerVolumeOn = await ipcRenderer.invoke('getStoreValue', 'trailer_volume_on'); + return trailerVolumeOn || DEFAULTS.trailer_volume_on; +} + +const set = async (key: StoreKeys, value: any, callback?: () => void): Promise => { + await ipcRenderer.invoke('setStoreValue', key, value); + if (callback) { + void callback(); + } +} + +export const STORAGE = { + set, + getLogged, + getAccessToken, + getUpdateProgress, + getDubbed, + getSourceFlag, + getIntroSkipTime, + getShowDuration, + getTrailerVolumeOn +} diff --git a/src/modules/storeVariables.ts b/src/modules/storeVariables.ts index 485ad454..cf140d56 100644 --- a/src/modules/storeVariables.ts +++ b/src/modules/storeVariables.ts @@ -1,25 +1,37 @@ import Store from 'electron-store'; -const STORE = new Store(); -export const setDefaultStoreVariables = () => { - if (!STORE.has('update_progress')) STORE.set('update_progress', false); - if (!STORE.has('dubbed')) STORE.set('dubbed', false); - if (!STORE.has('source_flag')) STORE.set('source_flag', 'US'); - if (!STORE.has('intro_skip_time')) STORE.set('intro_skip_time', 85); - if (!STORE.has('show_duration')) STORE.set('show_duration', true); - if (!STORE.has('trailer_volume_on')) STORE.set('trailer_volume_on', false); -} +// one store to rule them all. Use STORE and setupStore in main proccess and call STORAGE on the renderer side +export const STORE: Store> = new Store(); + +export type StoreKeys = + | 'logged' + | 'access_token' + | 'update_progress' + | 'dubbed' + | 'source_flag' + | 'intro_skip_time' + | 'show_duration' + | 'trailer_volume_on'; + +export type LanguageOptions = 'IT' | 'US'; -export const getSourceFlag = async (): Promise<'IT' | 'US' | null> => { - switch (STORE.get('source_flag')) { - case 'US': { - return 'US'; - } - case 'IT': { - return 'IT'; - } - default: { - return null; - } - } +export const DEFAULTS: Record = { + logged: false, + access_token: '', + update_progress: false, + dubbed: false, + source_flag: 'US', + intro_skip_time: 85, + show_duration: true, + trailer_volume_on: false, }; + +export const setupStore = () => { + if (!STORE.has('logged')) STORE.set('logged', DEFAULTS.logged); + if (!STORE.has('update_progress')) STORE.set('update_progress', DEFAULTS.update_progress); + if (!STORE.has('dubbed')) STORE.set('dubbed', DEFAULTS.dubbed); + if (!STORE.has('source_flag')) STORE.set('source_flag', DEFAULTS.source_flag); + if (!STORE.has('intro_skip_time')) STORE.set('intro_skip_time', DEFAULTS.intro_skip_time); + if (!STORE.has('show_duration')) STORE.set('show_duration', DEFAULTS.show_duration); + if (!STORE.has('trailer_volume_on')) STORE.set('trailer_volume_on', DEFAULTS.trailer_volume_on); +} diff --git a/src/modules/utils.ts b/src/modules/utils.ts index 7a86b6c4..4ea09584 100644 --- a/src/modules/utils.ts +++ b/src/modules/utils.ts @@ -1,10 +1,7 @@ -import Store from 'electron-store'; - import { AnimeData, ListAnimeData } from '../types/anilistAPITypes'; import { Media, MediaFormat, MediaStatus } from '../types/anilistGraphQLTypes'; import { animeCustomTitles } from '../modules/animeCustomTitles'; -const STORE = new Store(); const MONTHS = { '1': 'January', '2': 'February', @@ -321,10 +318,6 @@ export const parseAirdate = (airdate: string) => export const getParsedAnimeTitles = (animeEntry: Media): string[] => { var animeTitles = getTitlesAndSynonyms(animeEntry); - // const customTitle = - // animeCustomTitles[STORE.get('source_flag') as string][animeEntry?.id!]; - // if (customTitle) animeTitles.unshift(customTitle); - animeTitles.forEach((title) => { if (title.includes('Season ')) animeTitles.push(title.replace('Season ', '')); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index fd9eaa36..e2847b10 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -3,7 +3,6 @@ import '../styles/animations.css'; import '../styles/style.css'; import 'react-loading-skeleton/dist/skeleton.css'; -import Store from 'electron-store'; import { createContext, useEffect, useState } from 'react'; import { SkeletonTheme } from 'react-loading-skeleton'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; @@ -24,27 +23,24 @@ import Tab2 from './tabs/Tab2'; import Tab3 from './tabs/Tab3'; import Tab4 from './tabs/Tab4'; -import { setDefaultStoreVariables } from '../modules/storeVariables'; import { ipcRenderer } from 'electron'; import AutoUpdateModal from './components/modals/AutoUpdateModal'; import WindowControls from './WindowControls'; +import { useStorage } from './hooks/storage'; import { OS } from '../modules/os'; ipcRenderer.on('console-log', (event, toPrint) => { console.log(toPrint); }); -const store = new Store(); export const AuthContext = createContext(false); export const ViewerIdContext = createContext(null); export default function App() { - const [logged, setLogged] = useState(store.get('logged') as boolean); + const { logged } = useStorage(); const [viewerId, setViewerId] = useState(null); const [showUpdateModal, setShowUpdateModal] = useState(false); - setDefaultStoreVariables(); - ipcRenderer.on('auto-update', async () => { setShowUpdateModal(true); }); @@ -128,12 +124,12 @@ export default function App() { }; useEffect(() => { - fetchTab1AnimeData(); + void fetchTab1AnimeData(); }, []); useEffect(() => { if (tab2Click) { - fetchTab2AnimeData(); + void fetchTab2AnimeData(); } }, [tab2Click, viewerId]); diff --git a/src/renderer/hooks/storage.tsx b/src/renderer/hooks/storage.tsx new file mode 100644 index 00000000..daf5bda7 --- /dev/null +++ b/src/renderer/hooks/storage.tsx @@ -0,0 +1,114 @@ +import { useEffect, useState } from 'react'; +import { STORAGE } from '../../modules/storage'; +import { + DEFAULTS, + LanguageOptions, + StoreKeys, +} from '../../modules/storeVariables'; + +export const useStorage = () => { + const [logged, setLogged] = useState(DEFAULTS.logged); + const [accessToken, setAccessToken] = useState(DEFAULTS.access_token); + const [updateProgress, setUpdateProgress] = useState( + DEFAULTS.update_progress, + ); + const [watchDubbed, setWatchDubbed] = useState(DEFAULTS.dubbed); + const [selectedLanguage, setSelectedLanguage] = useState( + DEFAULTS.source_flag, + ); + const [skipTime, setSkipTime] = useState(DEFAULTS.intro_skip_time); + const [showDuration, setShowDuration] = useState( + DEFAULTS.show_duration, + ); + const [trailerVolumeOn, setTrailerVolumeOn] = useState( + DEFAULTS.trailer_volume_on, + ); + + const loadStorage = async () => { + const _logged = await STORAGE.getLogged(); + if (_logged !== logged) setLogged(_logged); + + const _accessToken = await STORAGE.getAccessToken(); + if (_accessToken !== accessToken) setAccessToken(_accessToken); + + const _updateProgress = await STORAGE.getUpdateProgress(); + if (_updateProgress !== updateProgress) setUpdateProgress(_updateProgress); + + const _watchDubbed = await STORAGE.getDubbed(); + if (_watchDubbed !== watchDubbed) setWatchDubbed(_watchDubbed); + + const _selectedLanguage = await STORAGE.getSourceFlag(); + if (_selectedLanguage !== selectedLanguage) + setSelectedLanguage(_selectedLanguage); + + const _skipTime = await STORAGE.getIntroSkipTime(); + if (_skipTime !== skipTime) setSkipTime(_skipTime); + + const _showDuration = await STORAGE.getShowDuration(); + if (_showDuration !== showDuration) setShowDuration(_showDuration); + + const _trailerVolumeOn = await STORAGE.getTrailerVolumeOn(); + if (_trailerVolumeOn !== trailerVolumeOn) + setTrailerVolumeOn(_trailerVolumeOn); + }; + + const updateStorage = async (key: StoreKeys, value: any) => { + let _value = null; + switch (key) { + case 'logged': + _value = await STORAGE.getLogged(); + setLogged(value); + break; + case 'access_token': + _value = await STORAGE.getAccessToken(); + setAccessToken(value); + break; + case 'update_progress': + _value = await STORAGE.getUpdateProgress(); + setUpdateProgress(value); + break; + case 'dubbed': + _value = await STORAGE.getDubbed(); + setWatchDubbed(value); + break; + case 'source_flag': + _value = await STORAGE.getSourceFlag(); + setSelectedLanguage(value); + break; + case 'intro_skip_time': + _value = await STORAGE.getIntroSkipTime(); + setSkipTime(value); + break; + case 'show_duration': + _value = await STORAGE.getShowDuration(); + setShowDuration(value); + break; + case 'trailer_volume_on': + _value = await STORAGE.getTrailerVolumeOn(); + setTrailerVolumeOn(value); + break; + default: + } + + await STORAGE.set(key, value); + console.log( + `store - ${key} updated to ${value} ${_value !== value ? `(was ${_value})` : ''}`, + ); + }; + + useEffect(() => { + void loadStorage(); + }, []); + + return { + logged, + accessToken, + updateProgress, + watchDubbed, + selectedLanguage, + skipTime, + showDuration, + trailerVolumeOn, + updateStorage, + }; +}; From 863221a80b2a708a992bf87d7c419f6cbdb35686 Mon Sep 17 00:00:00 2001 From: William Grant <0x96ea@gmail.com> Date: Wed, 12 Jun 2024 03:06:22 +1000 Subject: [PATCH 02/12] feat: fixed log in not being detected used storage methods in some places --- src/main/main.ts | 5 +- src/modules/anilist/anilistApi.ts | 32 +++++----- src/modules/providers/api.ts | 10 ++- src/modules/storage.ts | 50 ++++++++------- src/modules/storeVariables.ts | 61 ++++++++++++------- src/renderer/App.tsx | 30 +++++---- src/renderer/MainNavbar.tsx | 4 +- src/renderer/components/UserNavbar.tsx | 6 +- src/renderer/components/modals/AnimeModal.tsx | 23 ++++--- .../components/modals/AnimeModalElements.tsx | 6 +- src/renderer/hooks/storage.tsx | 18 +++--- src/renderer/tabs/Tab1.tsx | 18 +++--- src/renderer/tabs/Tab4.tsx | 51 ++++++---------- 13 files changed, 160 insertions(+), 154 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index fe662839..b349a65d 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,5 +1,4 @@ import { app, BrowserWindow, dialog, ipcMain, shell } from 'electron'; -import Store from 'electron-store'; import { autoUpdater } from 'electron-updater'; import path from 'path'; const DiscordRPC = require('discord-rpc'); @@ -10,9 +9,7 @@ import isAppImage from '../modules/packaging/isAppImage'; import MenuBuilder from './menu'; import { resolveHtmlPath } from './util'; import { OS } from '../modules/os'; -import { setupStore, STORE } from '../modules/storeVariables'; - -setupStore(); +import { STORE } from '../modules/storeVariables'; app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors'); diff --git a/src/modules/anilist/anilistApi.ts b/src/modules/anilist/anilistApi.ts index c801c12b..c8556f0e 100644 --- a/src/modules/anilist/anilistApi.ts +++ b/src/modules/anilist/anilistApi.ts @@ -1,5 +1,3 @@ -import Store from 'electron-store'; - import { AnimeData, CurrentListAnime, @@ -12,8 +10,8 @@ import { clientData } from '../clientData'; import { getOptions, makeRequest } from '../requests'; import isAppImage from '../packaging/isAppImage'; import { app, ipcRenderer } from 'electron'; +import { STORAGE } from '../storage'; -const STORE: any = new Store(); const CLIENT_DATA: ClientData = clientData; const PAGES: number = 20; const METHOD: string = 'POST'; @@ -86,7 +84,7 @@ const MEDIA_DATA: string = ` * @param {*} code * @returns access token */ -export const getAccessToken = async (code: string): Promise => { +export const fetchAccessToken = async (code: string): Promise => { const url = 'https://anilist.co/api/v2/oauth/token'; const data = { @@ -120,7 +118,7 @@ export const getViewerId = async (): Promise => { `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -151,7 +149,7 @@ export const getViewerInfo = async (viewerId: number | null) => { `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -197,7 +195,7 @@ export const getViewerList = async ( `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -230,7 +228,7 @@ export const getFollowingUsers = async (viewerId: any) => { `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -259,7 +257,7 @@ export const getAnimeInfo = async (animeId: any) => { `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -301,7 +299,7 @@ export const getTrendingAnime = async ( if (viewerId) { var headers: any = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -344,7 +342,7 @@ export const getMostPopularAnime = async ( if (viewerId) { var headers: any = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -384,7 +382,7 @@ export const getNextReleases = async (viewerId: number | null) => { if (viewerId) { var headers: any = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -428,7 +426,7 @@ export const searchFilteredAnime = async ( if (viewerId) { var headers: any = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -498,7 +496,7 @@ export const getAnimesByGenre = async (genre: any, viewerId: number | null) => { if (viewerId) { var headers: any = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -572,7 +570,7 @@ export const updateAnimeFromList = async ( `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -612,7 +610,7 @@ export const deleteAnimeFromList = async (id: any): Promise => { console.log('delte: ', id); var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; @@ -649,7 +647,7 @@ export const updateAnimeProgress = async ( `; var headers = { - Authorization: 'Bearer ' + STORE.get('access_token'), + Authorization: 'Bearer ' + (await STORAGE.getAccessToken()), 'Content-Type': 'application/json', Accept: 'application/json', }; diff --git a/src/modules/providers/api.ts b/src/modules/providers/api.ts index 280db501..13159403 100644 --- a/src/modules/providers/api.ts +++ b/src/modules/providers/api.ts @@ -1,13 +1,11 @@ import { IVideo } from '@consumet/extensions'; -import Store from 'electron-store'; import { ListAnimeData } from '../../types/anilistAPITypes'; import { animeCustomTitles } from '../animeCustomTitles'; import { getParsedAnimeTitles } from '../utils'; import { getEpisodeUrl as animeunity } from './animeunity'; import { getEpisodeUrl as gogoanime } from './gogoanime'; - -const STORE = new Store(); +import { STORAGE } from '../storage'; /** * Gets the episode url and isM3U8 flag, with stored language and dubbed @@ -20,11 +18,11 @@ export const getUniversalEpisodeUrl = async ( listAnimeData: ListAnimeData, episode: number, ): Promise => { - const lang = (await STORE.get('source_flag')) as string; - const dubbed = (await STORE.get('dubbed')) as boolean; + const lang = await STORAGE.getSourceFlag(); + const dubbed = await STORAGE.getDubbed(); const customTitle = - animeCustomTitles[STORE.get('source_flag') as string][ + animeCustomTitles[lang][ listAnimeData.media?.id! ]; diff --git a/src/modules/storage.ts b/src/modules/storage.ts index 27cf91c6..a7937247 100644 --- a/src/modules/storage.ts +++ b/src/modules/storage.ts @@ -1,54 +1,60 @@ // only use on renderer side import { ipcRenderer } from "electron"; -import { DEFAULTS, LanguageOptions, StoreKeys } from "./storeVariables"; +import { LanguageOptions, StoreKeys } from './storeVariables'; const getLogged = async (): Promise => { const logged = await ipcRenderer.invoke('getStoreValue', 'logged'); return logged; -} +}; const getAccessToken = async (): Promise => { const token = await ipcRenderer.invoke('getStoreValue', 'access_token'); - return token || ''; + return token; }; -const getUpdateProgress = async ():Promise => { +const getUpdateProgress = async (): Promise => { const progress = await ipcRenderer.invoke('getStoreValue', 'update_progress'); return progress; -} +}; const getDubbed = async (): Promise => { const dubbed = await ipcRenderer.invoke('getStoreValue', 'dubbed'); - return dubbed || DEFAULTS.dubbed; -} + return dubbed; +}; const getSourceFlag = async (): Promise => { const sourceFlag = await ipcRenderer.invoke('getStoreValue', 'source_flag'); - return sourceFlag || DEFAULTS.source_flag; + return sourceFlag; }; const getIntroSkipTime = async (): Promise => { - const introSkipTime = await ipcRenderer.invoke('getStoreValue', 'intro_skip_time'); - return introSkipTime || DEFAULTS.intro_skip_time; -} + const introSkipTime = await ipcRenderer.invoke( + 'getStoreValue', + 'intro_skip_time', + ); + return introSkipTime; +}; const getShowDuration = async (): Promise => { - const showDuration = await ipcRenderer.invoke('getStoreValue', 'show_duration'); - return showDuration || DEFAULTS.show_duration; -} + const showDuration = await ipcRenderer.invoke( + 'getStoreValue', + 'show_duration', + ); + return showDuration; +}; const getTrailerVolumeOn = async (): Promise => { - const trailerVolumeOn = await ipcRenderer.invoke('getStoreValue', 'trailer_volume_on'); - return trailerVolumeOn || DEFAULTS.trailer_volume_on; -} + const trailerVolumeOn = await ipcRenderer.invoke( + 'getStoreValue', + 'trailer_volume_on', + ); + return trailerVolumeOn; +}; -const set = async (key: StoreKeys, value: any, callback?: () => void): Promise => { +const set = async (key: StoreKeys, value: any): Promise => { await ipcRenderer.invoke('setStoreValue', key, value); - if (callback) { - void callback(); - } -} +}; export const STORAGE = { set, diff --git a/src/modules/storeVariables.ts b/src/modules/storeVariables.ts index cf140d56..d42e1397 100644 --- a/src/modules/storeVariables.ts +++ b/src/modules/storeVariables.ts @@ -1,8 +1,5 @@ import Store from 'electron-store'; -// one store to rule them all. Use STORE and setupStore in main proccess and call STORAGE on the renderer side -export const STORE: Store> = new Store(); - export type StoreKeys = | 'logged' | 'access_token' @@ -15,23 +12,43 @@ export type StoreKeys = export type LanguageOptions = 'IT' | 'US'; -export const DEFAULTS: Record = { - logged: false, - access_token: '', - update_progress: false, - dubbed: false, - source_flag: 'US', - intro_skip_time: 85, - show_duration: true, - trailer_volume_on: false, -}; - -export const setupStore = () => { - if (!STORE.has('logged')) STORE.set('logged', DEFAULTS.logged); - if (!STORE.has('update_progress')) STORE.set('update_progress', DEFAULTS.update_progress); - if (!STORE.has('dubbed')) STORE.set('dubbed', DEFAULTS.dubbed); - if (!STORE.has('source_flag')) STORE.set('source_flag', DEFAULTS.source_flag); - if (!STORE.has('intro_skip_time')) STORE.set('intro_skip_time', DEFAULTS.intro_skip_time); - if (!STORE.has('show_duration')) STORE.set('show_duration', DEFAULTS.show_duration); - if (!STORE.has('trailer_volume_on')) STORE.set('trailer_volume_on', DEFAULTS.trailer_volume_on); +export const STORE_SCHEMA: Record = { + logged: { + type: 'boolean', + default: false, + }, + access_token: { + type: 'string', + default: '', + }, + update_progress: { + type: 'boolean', + default: false, + }, + dubbed: { + type: 'boolean', + default: false, + }, + source_flag: { + type: 'string', + default: 'US', + }, + intro_skip_time: { + type: 'number', + default: 85, + }, + show_duration: { + type: 'boolean', + default: true, + }, + trailer_volume_on: { + type: 'boolean', + default: false, + }, } + +// one store to rule them all. Use STORE in the main proccess and call STORAGE on the renderer side +export const STORE: Store> = new Store({ + // NOTE Not ready to use this yet as it will break the app + // schema: STORE_SCHEMA, +}); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index e2847b10..b6f345c9 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -33,7 +33,6 @@ ipcRenderer.on('console-log', (event, toPrint) => { console.log(toPrint); }); -export const AuthContext = createContext(false); export const ViewerIdContext = createContext(null); export default function App() { @@ -47,6 +46,7 @@ export default function App() { // tab1 const [userInfo, setUserInfo] = useState(); + const [animeLoaded, setAnimeLoaded] = useState(false); const [currentListAnime, setCurrentListAnime] = useState< ListAnimeData[] | undefined >(undefined); @@ -80,24 +80,30 @@ export default function App() { const style = getComputedStyle(document.body); - const fetchTab1AnimeData = async () => { + const fetchTab1AnimeData = async (loggedIn: boolean) => { try { var id = null; - if (logged) { + if (loggedIn) { id = await getViewerId(); setViewerId(id); - setUserInfo(await getViewerInfo(id)); + const info = await getViewerInfo(id); + setUserInfo(info); const current = await getViewerList(id, 'CURRENT'); const rewatching = await getViewerList(id, 'REPEATING'); setCurrentListAnime(current.concat(rewatching)); } - setTrendingAnime(animeDataToListAnimeData(await getTrendingAnime(id))); - setMostPopularAnime( - animeDataToListAnimeData(await getMostPopularAnime(id)), - ); - setNextReleasesAnime(animeDataToListAnimeData(await getNextReleases(id))); + if (!animeLoaded) { + setTrendingAnime(animeDataToListAnimeData(await getTrendingAnime(id))); + setMostPopularAnime( + animeDataToListAnimeData(await getMostPopularAnime(id)), + ); + setNextReleasesAnime( + animeDataToListAnimeData(await getNextReleases(id)), + ); + setAnimeLoaded(true); + } } catch (error) { console.log('Tab1 error: ' + error); } @@ -124,8 +130,8 @@ export default function App() { }; useEffect(() => { - void fetchTab1AnimeData(); - }, []); + void fetchTab1AnimeData(logged); + }, [logged]); useEffect(() => { if (tab2Click) { @@ -134,7 +140,6 @@ export default function App() { }, [tab2Click, viewerId]); return ( - - ); } diff --git a/src/renderer/MainNavbar.tsx b/src/renderer/MainNavbar.tsx index 1c2ec7e5..6e803776 100644 --- a/src/renderer/MainNavbar.tsx +++ b/src/renderer/MainNavbar.tsx @@ -16,9 +16,9 @@ import { useContext, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import isAppImage from '../modules/packaging/isAppImage'; -import { AuthContext } from './App'; import AuthCodeModal from './components/modals/AuthCodeModal'; import UserModal from './components/modals/UserModal'; +import { useStorage } from './hooks/storage'; const Li: React.FC<{ text: string; @@ -55,7 +55,7 @@ const LiLink: React.FC<{ }; const MainNavbar: React.FC<{ avatar?: string }> = ({ avatar }) => { - const logged = useContext(AuthContext); + const {logged} = useStorage(); const [activeTab, setActiveTab] = useState(1); const [showUserModal, setShowUserModal] = useState(false); diff --git a/src/renderer/components/UserNavbar.tsx b/src/renderer/components/UserNavbar.tsx index f590b3fe..6947250a 100644 --- a/src/renderer/components/UserNavbar.tsx +++ b/src/renderer/components/UserNavbar.tsx @@ -7,8 +7,7 @@ import { } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ipcRenderer } from 'electron'; -import { useContext } from 'react'; -import { AuthContext } from '../App'; +import { useStorage } from '../hooks/storage'; interface LiProps { text: string; @@ -32,8 +31,7 @@ interface UserNavbarProps { } const UserNavbar: React.FC = ({ avatar }) => { - const logged = useContext(AuthContext); - + const { logged } = useStorage(); return (