From 13da06a270e2d790dfecd842d66dbc1a782d4057 Mon Sep 17 00:00:00 2001 From: Triston Armstrong Date: Sun, 17 Mar 2024 15:01:06 -0500 Subject: [PATCH] refactor(all): rework how state is being managed this rewrites a lot of hooks and removes providers in exchange for the store api BREAKING CHANGE: breaks everything fix #1 --- src/App.tsx | 17 +++++----- src/ProviderWrapper.tsx | 13 -------- src/hooks/navigationStores.ts | 13 ++++++++ src/hooks/stationStores.ts | 39 ++++++++++++++++++++++ src/hooks/storageStores.ts | 35 ++++++++++++++++++++ src/hooks/useNavigator.ts | 19 ----------- src/main.ts | 4 +-- src/pages/Add.tsx | 24 ++++++-------- src/pages/Main.tsx | 18 ++++++----- src/pages/Player.tsx | 12 +++---- src/providers/StationsProvider.tsx | 37 --------------------- src/providers/StorageProvider.tsx | 52 ------------------------------ 12 files changed, 124 insertions(+), 159 deletions(-) delete mode 100644 src/ProviderWrapper.tsx create mode 100644 src/hooks/navigationStores.ts create mode 100644 src/hooks/stationStores.ts create mode 100644 src/hooks/storageStores.ts delete mode 100644 src/hooks/useNavigator.ts delete mode 100644 src/providers/StationsProvider.tsx delete mode 100644 src/providers/StorageProvider.tsx diff --git a/src/App.tsx b/src/App.tsx index ddc955e..3df3201 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,23 +1,24 @@ -import { Navs, useNavigator } from "./hooks/useNavigator" import { useEffect } from "kaioken" -import { useStationsProvider } from "./providers/StationsProvider" import Main from "./pages/Main" import Player from "./pages/Player" -import { useStorageContext } from "./providers/StorageProvider" import Add from "./pages/Add" +import useNavigationStore, { Navs } from "./hooks/navigationStores" +import { useStorage } from "./hooks/storageStores" +import { useStationsStore } from "./hooks/stationStores" export function App() { - const { setStations } = useStationsProvider() - const { getStationsFile } = useStorageContext() - const { nav } = useNavigator() + const { getStationsFile } = useStorage() + const { override } = useStationsStore() + const { value } = useNavigationStore() useEffect(() => { getStationsFile() - .then(res => res && setStations(res)) + .then(res => res && override(res)) .catch() }, []) - switch (nav) { + + switch (value) { case Navs.MAIN: return
case Navs.ADD: diff --git a/src/ProviderWrapper.tsx b/src/ProviderWrapper.tsx deleted file mode 100644 index ed4c810..0000000 --- a/src/ProviderWrapper.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { App } from "./App"; -import { StationsContextProvider } from "./providers/StationsProvider"; -import { StorageContextProvider } from "./providers/StorageProvider"; - -export default function ProviderWrapper() { - return ( - - - - - - ) -} diff --git a/src/hooks/navigationStores.ts b/src/hooks/navigationStores.ts new file mode 100644 index 0000000..5e7a5db --- /dev/null +++ b/src/hooks/navigationStores.ts @@ -0,0 +1,13 @@ +import { createStore } from "kaioken" + +export enum Navs { + MAIN, + ADD, + PLAYER, +} + +const useNavigationStore = createStore(Navs.MAIN, (set) => ({ + navigate: (value) => set(() => value), +})) + +export default useNavigationStore diff --git a/src/hooks/stationStores.ts b/src/hooks/stationStores.ts new file mode 100644 index 0000000..ee72682 --- /dev/null +++ b/src/hooks/stationStores.ts @@ -0,0 +1,39 @@ +import { writeTextFile } from "@tauri-apps/api/fs" +import { createStore } from "kaioken" + +export const useStationsStore = createStore( + null as Station[] | null, + (set) => ({ + add: (station: Station): Station[] => { + let newState: Station[] | null = null + set((state) => { + newState = [...(state ?? []), station] + return newState + }) + //@ts-ignore + return newState + }, + delete: (stationId) => + set( + (state) => state?.filter((station) => station.id !== stationId) ?? [] + ), + override: (stationsList: Station[]) => { + set((_state) => stationsList) + }, + }) +) + +export const useSelectStationStore = createStore( + null as Station | null, + (set) => ({ + make: (station) => set((_state) => station), + clear: () => set((_state) => null), + }) +) + +export interface Station { + id: string + url: string + avatar: string + title: string +} diff --git a/src/hooks/storageStores.ts b/src/hooks/storageStores.ts new file mode 100644 index 0000000..9c6b163 --- /dev/null +++ b/src/hooks/storageStores.ts @@ -0,0 +1,35 @@ +import { exists, readTextFile, writeTextFile } from "@tauri-apps/api/fs" +import { appDataDir } from "@tauri-apps/api/path" +import { createStore } from "kaioken" +import { Station } from "../hooks/stationStores" + +export const useStorageStore = createStore( + null as string | null, + (_set) => ({}) +) + +export function useStorage() { + async function _createStationsFile(path: string): Promise { + await writeTextFile(path, "[]", { append: false }) + return [] + } + + async function getStationsFile(): Promise { + let dir: null | string = null + try { + dir = await appDataDir() + } catch (err) { + console.error("getStationsFile: ", err) + return undefined + } + if (!dir) return undefined + const path = `${dir}stations.json` + if (!(await exists(path))) return await _createStationsFile(path) + const jsonString = await readTextFile(path) + const json = JSON.parse(jsonString) as Station[] + useStorageStore.setState(() => path) + return json + } + + return { getStationsFile } +} diff --git a/src/hooks/useNavigator.ts b/src/hooks/useNavigator.ts deleted file mode 100644 index cddf300..0000000 --- a/src/hooks/useNavigator.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { useState } from "kaioken" -export enum Navs { - MAIN, - ADD, - PLAYER, -} - -export function useNavigator() { - const [nav, setNav] = useState(Navs.MAIN) - - function _setNavitation(newNav: Navs) { - setNav(newNav) - } - - return { - nav, - setNavitation: _setNavitation, - } -} diff --git a/src/main.ts b/src/main.ts index 7e87a77..4013b8a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ +import { App } from "./App" import "./styles.css" import { mount } from "kaioken" -import ProviderWrapper from "./ProviderWrapper" const root = document.getElementById("root")! -mount(ProviderWrapper, root) +mount(App, root) diff --git a/src/pages/Add.tsx b/src/pages/Add.tsx index b50313d..df7c4a0 100644 --- a/src/pages/Add.tsx +++ b/src/pages/Add.tsx @@ -1,35 +1,31 @@ import { writeTextFile } from "@tauri-apps/api/fs" -import { Navs, useNavigator } from "../hooks/useNavigator" -import { Station, useStationsProvider } from "../providers/StationsProvider" import { useModel } from "kaioken" -import { useStorageContext } from "../providers/StorageProvider" +import { Station, useStationsStore } from "../hooks/stationStores" +import { useStorageStore } from "../hooks/storageStores" +import useNavigationStore, { Navs } from "../hooks/navigationStores" export default function Add() { - const { setNavitation } = useNavigator() - const { setStations } = useStationsProvider() - const { appDataDirRef } = useStorageContext() + const { value } = useStorageStore() const [titleRef, title,] = useModel('') const [streamRef, streamUrl,] = useModel('') const [avatarRef, avatarUrl,] = useModel('') function _handleStationAdd() { const data: Station = { + id: Math.random().toString(16).slice(2), url: streamUrl, avatar: avatarUrl, title: title } - setStations(prev => { - const newStations = [...(prev ?? []), data] - // write file - writeTextFile(appDataDirRef.current!, JSON.stringify(newStations)) - return newStations - }) - setNavitation(Navs.MAIN) + const store = useStationsStore.methods.add(data) + const valid = store && value + valid && void writeTextFile(value, JSON.stringify(store)) + useNavigationStore.setState(Navs.MAIN) } return (
- +
) } @@ -40,7 +42,7 @@ export default function Main() { ))} - + ) diff --git a/src/pages/Player.tsx b/src/pages/Player.tsx index 61162b4..6f0ac8b 100644 --- a/src/pages/Player.tsx +++ b/src/pages/Player.tsx @@ -1,13 +1,13 @@ -import { Navs, useNavigator } from "../hooks/useNavigator" -import { useStationsProvider } from "../providers/StationsProvider" +import useNavigationStore, { Navs } from "../hooks/navigationStores" +import { useSelectStationStore } from "../hooks/stationStores" export default function Player() { - const { setNavitation } = useNavigator() - const { setSelectedStation, selectedStation } = useStationsProvider() + const { value: selectedStation, make } = useSelectStationStore() + const { navigate } = useNavigationStore() function _handlePlayerBackClick() { - setNavitation(Navs.MAIN) - setSelectedStation(null) + navigate(Navs.MAIN) + make(null) } return ( diff --git a/src/providers/StationsProvider.tsx b/src/providers/StationsProvider.tsx deleted file mode 100644 index 2eff1d9..0000000 --- a/src/providers/StationsProvider.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { createContext, useContext, useState } from 'kaioken'; - -interface StationsContextType { - stations: Station[] | null - setStations: (value: Kaioken.StateSetter) => void - selectedStation: Station | null - setSelectedStation: (value: Kaioken.StateSetter) => void -} - -const StationsContext = createContext({} as StationsContextType); - -export const useStationsProvider = () => useContext(StationsContext) - -interface MyContextProviderProps { - children?: Kaioken.VNode | Kaioken.VNode[] -} -export function StationsContextProvider(props: MyContextProviderProps) { - const [stations, setStations] = useState(null) - const [selectedStation, setSelectedStation] = useState(null) - - const value = { - stations, setStations, - selectedStation, setSelectedStation - }; - - return ( - - {props.children} - - ); -} - -export interface Station { - url: string - avatar: string - title: string -} diff --git a/src/providers/StorageProvider.tsx b/src/providers/StorageProvider.tsx deleted file mode 100644 index 37e6ec3..0000000 --- a/src/providers/StorageProvider.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { exists, readTextFile, writeTextFile } from '@tauri-apps/api/fs'; -import { appDataDir } from '@tauri-apps/api/path'; -import { createContext, useContext, useRef } from 'kaioken'; -import { Station } from './StationsProvider'; - -interface StorageContextType { - appDataDirRef: Kaioken.Ref, - getStationsFile: () => Promise -} - -const StorageContext = createContext({} as StorageContextType); - -export const useStorageContext = () => useContext(StorageContext) - -export function StorageContextProvider(props: any) { - const appDataDirRef = useRef(null) - - async function _getStationsFile(): Promise { - let dir: null | string = null - try { - dir = await appDataDir() - } catch (err) { - console.error(err) - return undefined - } - if (!dir) return undefined - const path = `${dir}/stations.json` - if (!(await exists(path))) - return await _createStationsFile(path) - const jsonString = await readTextFile(path) - const json = JSON.parse(jsonString) as Station[] - appDataDirRef.current = path - return json - } - - async function _createStationsFile(path: string): Promise { - await writeTextFile(path, "[]", { append: false }) - return [] - } - - - const value: StorageContextType = { - appDataDirRef, - getStationsFile: _getStationsFile - }; - - return ( - - {props.children} - - ); -}