mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
switch to jotai
This commit is contained in:
parent
17f5639aef
commit
4606586102
6
App.tsx
6
App.tsx
@ -1,17 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
import { RecoilRoot } from 'recoil';
|
|
||||||
import SplashPage from './src/components/SplashPage';
|
import SplashPage from './src/components/SplashPage';
|
||||||
import RootNavigator from './src/components/navigation/RootNavigator';
|
import RootNavigator from './src/components/navigation/RootNavigator';
|
||||||
|
import { Provider } from 'jotai';
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<RecoilRoot>
|
<Provider>
|
||||||
<SplashPage>
|
<SplashPage>
|
||||||
<NavigationContainer>
|
<NavigationContainer>
|
||||||
<RootNavigator />
|
<RootNavigator />
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</SplashPage>
|
</SplashPage>
|
||||||
</RecoilRoot>
|
</Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
5
index.js
5
index.js
@ -1,11 +1,6 @@
|
|||||||
import 'react-native-gesture-handler';
|
import 'react-native-gesture-handler';
|
||||||
import 'react-native-get-random-values';
|
import 'react-native-get-random-values';
|
||||||
|
|
||||||
import { AppRegistry, LogBox } from 'react-native';
|
|
||||||
// ignore recoil's timer warning on android:
|
|
||||||
// https://github.com/facebookexperimental/Recoil/issues/1030
|
|
||||||
LogBox.ignoreLogs(["timer"]);
|
|
||||||
|
|
||||||
import { enableScreens } from 'react-native-screens';
|
import { enableScreens } from 'react-native-screens';
|
||||||
enableScreens();
|
enableScreens();
|
||||||
|
|
||||||
|
|||||||
86
package-lock.json
generated
86
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"@react-navigation/material-top-tabs": "^5.3.15",
|
"@react-navigation/material-top-tabs": "^5.3.15",
|
||||||
"@react-navigation/native": "^5.9.4",
|
"@react-navigation/native": "^5.9.4",
|
||||||
"@react-navigation/stack": "^5.14.5",
|
"@react-navigation/stack": "^5.14.5",
|
||||||
|
"jotai": "^1.1.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"react": "17.0.1",
|
"react": "17.0.1",
|
||||||
"react-native": "0.64.1",
|
"react-native": "0.64.1",
|
||||||
@ -27,7 +28,6 @@
|
|||||||
"react-native-screens": "^3.4.0",
|
"react-native-screens": "^3.4.0",
|
||||||
"react-native-tab-view": "^2.16.0",
|
"react-native-tab-view": "^2.16.0",
|
||||||
"react-native-track-player": "^1.2.7",
|
"react-native-track-player": "^1.2.7",
|
||||||
"recoil": "^0.3.1",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"xmldom": "^0.5.0"
|
"xmldom": "^0.5.0"
|
||||||
},
|
},
|
||||||
@ -6116,11 +6116,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/hamt_plus": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
|
|
||||||
},
|
|
||||||
"node_modules/has": {
|
"node_modules/has": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
@ -8461,6 +8456,47 @@
|
|||||||
"@sideway/pinpoint": "^2.0.0"
|
"@sideway/pinpoint": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jotai": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jotai/-/jotai-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-+c/bMxS/c1LgsOYVfevOYLAu+WEgn85TJhmBoNSNHjMV+mTKZY0ACSyCrX1yz8KialK4+Ggm6d7Ek3sTXy8UgA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@urql/core": "*",
|
||||||
|
"immer": "*",
|
||||||
|
"optics-ts": "*",
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-query": "*",
|
||||||
|
"valtio": "*",
|
||||||
|
"wonka": "*",
|
||||||
|
"xstate": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@urql/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"optics-ts": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-query": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"valtio": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"wonka": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"xstate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -10772,25 +10808,6 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/recoil": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.3.1.tgz",
|
|
||||||
"integrity": "sha512-KNA3DRqgxX4rRC8E7fc6uIw7BACmMPuraIYy+ejhE8tsw7w32CetMm8w7AMZa34wzanKKkev3vl3H7Z4s0QSiA==",
|
|
||||||
"dependencies": {
|
|
||||||
"hamt_plus": "1.0.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.13.1"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"react-dom": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react-native": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@ -17936,11 +17953,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"hamt_plus": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
|
|
||||||
},
|
|
||||||
"has": {
|
"has": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
@ -19673,6 +19685,12 @@
|
|||||||
"@sideway/pinpoint": "^2.0.0"
|
"@sideway/pinpoint": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jotai": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jotai/-/jotai-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-+c/bMxS/c1LgsOYVfevOYLAu+WEgn85TJhmBoNSNHjMV+mTKZY0ACSyCrX1yz8KialK4+Ggm6d7Ek3sTXy8UgA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -21513,14 +21531,6 @@
|
|||||||
"resolve": "^1.1.6"
|
"resolve": "^1.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"recoil": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.3.1.tgz",
|
|
||||||
"integrity": "sha512-KNA3DRqgxX4rRC8E7fc6uIw7BACmMPuraIYy+ejhE8tsw7w32CetMm8w7AMZa34wzanKKkev3vl3H7Z4s0QSiA==",
|
|
||||||
"requires": {
|
|
||||||
"hamt_plus": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
"@react-navigation/material-top-tabs": "^5.3.15",
|
"@react-navigation/material-top-tabs": "^5.3.15",
|
||||||
"@react-navigation/native": "^5.9.4",
|
"@react-navigation/native": "^5.9.4",
|
||||||
"@react-navigation/stack": "^5.14.5",
|
"@react-navigation/stack": "^5.14.5",
|
||||||
|
"jotai": "^1.1.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"react": "17.0.1",
|
"react": "17.0.1",
|
||||||
"react-native": "0.64.1",
|
"react-native": "0.64.1",
|
||||||
@ -29,7 +30,6 @@
|
|||||||
"react-native-screens": "^3.4.0",
|
"react-native-screens": "^3.4.0",
|
||||||
"react-native-tab-view": "^2.16.0",
|
"react-native-tab-view": "^2.16.0",
|
||||||
"react-native-track-player": "^1.2.7",
|
"react-native-track-player": "^1.2.7",
|
||||||
"recoil": "^0.3.1",
|
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"xmldom": "^0.5.0"
|
"xmldom": "^0.5.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, FlatList, Text, View } from 'react-native';
|
import { FlatList, Text, View } from 'react-native';
|
||||||
import { useRecoilValue, useResetRecoilState } from 'recoil';
|
import { useAtomValue } from 'jotai/utils';
|
||||||
import { Artist } from '../models/music';
|
import { Artist } from '../models/music';
|
||||||
import { artistsState } from '../state/music';
|
import { artistsAtom } from '../state/music';
|
||||||
|
|
||||||
const ArtistItem: React.FC<{ item: Artist } > = ({ item }) => (
|
const ArtistItem: React.FC<{ item: Artist } > = ({ item }) => (
|
||||||
<View>
|
<View>
|
||||||
@ -15,7 +15,7 @@ const ArtistItem: React.FC<{ item: Artist } > = ({ item }) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const List = () => {
|
const List = () => {
|
||||||
const artists = useRecoilValue(artistsState);
|
const artists = useAtomValue(artistsAtom);
|
||||||
|
|
||||||
const renderItem: React.FC<{ item: Artist }> = ({ item }) => (
|
const renderItem: React.FC<{ item: Artist }> = ({ item }) => (
|
||||||
<ArtistItem item={item} />
|
<ArtistItem item={item} />
|
||||||
@ -30,24 +30,10 @@ const List = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListPlusControls = () => {
|
|
||||||
const resetArtists = useResetRecoilState(artistsState);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View>
|
|
||||||
<Button
|
|
||||||
title='Reset to default'
|
|
||||||
onPress={resetArtists}
|
|
||||||
/>
|
|
||||||
<List />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ArtistsList = () => (
|
const ArtistsList = () => (
|
||||||
<View>
|
<View>
|
||||||
<React.Suspense fallback={<Text>Loading...</Text>}>
|
<React.Suspense fallback={<Text>Loading...</Text>}>
|
||||||
<ListPlusControls />
|
<List />
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { useNavigation } from '@react-navigation/core';
|
import { useNavigation } from '@react-navigation/core';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import md5 from 'md5';
|
import md5 from 'md5';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, Text, View } from 'react-native';
|
import { Button, Text, View } from 'react-native';
|
||||||
import { useRecoilState } from 'recoil';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { appSettingsState } from '../state/settings';
|
import { appSettingsAtom } from '../state/settings';
|
||||||
|
|
||||||
const TestControls = () => {
|
const TestControls = () => {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
@ -19,7 +19,7 @@ const TestControls = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ServerSettingsView = () => {
|
const ServerSettingsView = () => {
|
||||||
const [appSettings, setAppSettings] = useRecoilState(appSettingsState);
|
const [appSettings, setAppSettings] = useAtom(appSettingsAtom);
|
||||||
|
|
||||||
const bootstrapServer = () => {
|
const bootstrapServer = () => {
|
||||||
if (appSettings.servers.length !== 0) {
|
if (appSettings.servers.length !== 0) {
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
|
import { useAtomValue } from 'jotai/utils';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { FlatList, Text, View } from 'react-native';
|
import { FlatList, Text, View } from 'react-native';
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { Album } from '../../models/music';
|
import { Album } from '../../models/music';
|
||||||
import { albumsState, albumsUpdatingState, useUpdateAlbums } from '../../state/music';
|
import { albumsAtom, albumsUpdatingAtom, useUpdateAlbums } from '../../state/music';
|
||||||
import colors from '../../styles/colors';
|
import colors from '../../styles/colors';
|
||||||
import textStyles from '../../styles/text';
|
import textStyles from '../../styles/text';
|
||||||
import TopTabContainer from '../common/TopTabContainer';
|
import TopTabContainer from '../common/TopTabContainer';
|
||||||
@ -89,8 +89,8 @@ const AlbumListRenderItem: React.FC<{ item: Album }> = ({ item }) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const AlbumsList = () => {
|
const AlbumsList = () => {
|
||||||
const albums = useRecoilValue(albumsState);
|
const albums = useAtomValue(albumsAtom);
|
||||||
const updating = useRecoilValue(albumsUpdatingState);
|
const updating = useAtomValue(albumsUpdatingAtom);
|
||||||
const updateAlbums = useUpdateAlbums();
|
const updateAlbums = useUpdateAlbums();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
import { useAtomValue } from 'jotai/utils';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { FlatList, Image, Text, View } from 'react-native';
|
import { FlatList, Image, Text, View } from 'react-native';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
import { Artist } from '../../models/music';
|
import { Artist } from '../../models/music';
|
||||||
import { artistsState, artistsUpdatingState, useUpdateArtists } from '../../state/music';
|
import { artistsAtom, artistsUpdatingAtom, useUpdateArtists } from '../../state/music';
|
||||||
import textStyles from '../../styles/text';
|
import textStyles from '../../styles/text';
|
||||||
import TopTabContainer from '../common/TopTabContainer';
|
import TopTabContainer from '../common/TopTabContainer';
|
||||||
|
|
||||||
@ -28,8 +28,8 @@ const ArtistItem: React.FC<{ item: Artist } > = ({ item }) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const ArtistsList = () => {
|
const ArtistsList = () => {
|
||||||
const artists = useRecoilValue(artistsState);
|
const artists = useAtomValue(artistsAtom);
|
||||||
const updating = useRecoilValue(artistsUpdatingState);
|
const updating = useAtomValue(artistsUpdatingAtom);
|
||||||
const updateArtists = useUpdateArtists();
|
const updateArtists = useUpdateArtists();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,27 +1,21 @@
|
|||||||
import { atom, useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
import { atom, useAtom } from 'jotai';
|
||||||
|
import { useAtomValue, useUpdateAtom } from 'jotai/utils';
|
||||||
import { Album, Artist } from '../models/music';
|
import { Album, Artist } from '../models/music';
|
||||||
import { SubsonicApiClient } from '../subsonic/api';
|
import { SubsonicApiClient } from '../subsonic/api';
|
||||||
import { activeServer } from './settings';
|
import { activeServerAtom } from './settings';
|
||||||
|
|
||||||
export const artistsState = atom<Artist[]>({
|
export const artistsAtom = atom<Artist[]>([]);
|
||||||
key: 'artistsState',
|
export const artistsUpdatingAtom = atom(false);
|
||||||
default: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const artistsUpdatingState = atom<boolean>({
|
|
||||||
key: 'artistsUpdatingState',
|
|
||||||
default: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useUpdateArtists = () => {
|
export const useUpdateArtists = () => {
|
||||||
const server = useRecoilValue(activeServer);
|
const server = useAtomValue(activeServerAtom);
|
||||||
|
const [updating, setUpdating] = useAtom(artistsUpdatingAtom);
|
||||||
|
const setArtists = useUpdateAtom(artistsAtom);
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
return () => Promise.resolve();
|
return () => Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const [updating, setUpdating] = useRecoilState(artistsUpdatingState);
|
|
||||||
const setArtists = useSetRecoilState(artistsState);
|
|
||||||
|
|
||||||
return async () => {
|
return async () => {
|
||||||
if (updating) {
|
if (updating) {
|
||||||
return;
|
return;
|
||||||
@ -42,25 +36,18 @@ export const useUpdateArtists = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const albumsState = atom<Album[]>({
|
export const albumsAtom = atom<Album[]>([]);
|
||||||
key: 'albumsState',
|
export const albumsUpdatingAtom = atom(false);
|
||||||
default: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const albumsUpdatingState = atom<boolean>({
|
|
||||||
key: 'albumsUpdatingState',
|
|
||||||
default: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const useUpdateAlbums = () => {
|
export const useUpdateAlbums = () => {
|
||||||
const server = useRecoilValue(activeServer);
|
const server = useAtomValue(activeServerAtom);
|
||||||
|
const [updating, setUpdating] = useAtom(albumsUpdatingAtom);
|
||||||
|
const setAlbums = useUpdateAtom(albumsAtom);
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
return () => Promise.resolve();
|
return () => Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const [updating, setUpdating] = useRecoilState(albumsUpdatingState);
|
|
||||||
const setAlbums = useSetRecoilState(albumsState);
|
|
||||||
|
|
||||||
return async () => {
|
return async () => {
|
||||||
if (updating) {
|
if (updating) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,28 +1,12 @@
|
|||||||
import { atom, DefaultValue, selector } from 'recoil';
|
import { atom } from 'jotai';
|
||||||
import { AppSettings, Server } from '../models/settings';
|
import { AppSettings } from '../models/settings';
|
||||||
import { getAppSettings, setAppSettings } from '../storage/settings';
|
import atomWithAsyncStorage from '../storage/atomWithAsyncStorage';
|
||||||
|
|
||||||
export const appSettingsState = atom<AppSettings>({
|
export const appSettingsAtom = atomWithAsyncStorage<AppSettings>('@appSettings', {
|
||||||
key: 'appSettingsState',
|
servers: [],
|
||||||
default: selector({
|
|
||||||
key: 'appSettingsState/default',
|
|
||||||
get: () => getAppSettings(),
|
|
||||||
}),
|
|
||||||
effects_UNSTABLE: [
|
|
||||||
({ onSet }) => {
|
|
||||||
onSet((newValue) => {
|
|
||||||
if (!(newValue instanceof DefaultValue)) {
|
|
||||||
setAppSettings(newValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const activeServer = selector<Server | undefined>({
|
export const activeServerAtom = atom((get) => {
|
||||||
key: 'activeServer',
|
const appSettings = get(appSettingsAtom);
|
||||||
get: ({get}) => {
|
return appSettings.servers.find(x => x.id == appSettings.activeServer);
|
||||||
const appSettings = get(appSettingsState);
|
|
||||||
return appSettings.servers.find(x => x.id == appSettings.activeServer);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,26 +1,28 @@
|
|||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
export async function getItem(key: string): Promise<string | null> {
|
export async function getItem(key: string): Promise<any | null> {
|
||||||
try {
|
try {
|
||||||
return await AsyncStorage.getItem(key);
|
const item = await AsyncStorage.getItem(key);
|
||||||
|
return item ? JSON.parse(item) : null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`getItem error (key: ${key})`, e);
|
console.error(`getItem error (key: ${key})`, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function multiGet(keys: string[]): Promise<[string, string | null][]> {
|
export async function multiGet(keys: string[]): Promise<[string, any | null][]> {
|
||||||
try {
|
try {
|
||||||
return await AsyncStorage.multiGet(keys);
|
const items = await AsyncStorage.multiGet(keys);
|
||||||
|
return items.map(x => [x[0], x[1] ? JSON.parse(x[1]) : null]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`multiGet error`, e);
|
console.error(`multiGet error`, e);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setItem(key: string, item: string): Promise<void> {
|
export async function setItem(key: string, item: any): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await AsyncStorage.setItem(key, item);
|
await AsyncStorage.setItem(key, JSON.stringify(item));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`setItem error (key: ${key})`, e);
|
console.error(`setItem error (key: ${key})`, e);
|
||||||
}
|
}
|
||||||
@ -28,7 +30,7 @@ export async function setItem(key: string, item: string): Promise<void> {
|
|||||||
|
|
||||||
export async function multiSet(items: string[][]): Promise<void> {
|
export async function multiSet(items: string[][]): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await AsyncStorage.multiSet(items);
|
await AsyncStorage.multiSet(items.map(x => [x[0], JSON.stringify(x[1])]));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`multiSet error`, e);
|
console.error(`multiSet error`, e);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/storage/atomWithAsyncStorage.ts
Normal file
10
src/storage/atomWithAsyncStorage.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { atomWithStorage } from 'jotai/utils';
|
||||||
|
import { getItem, setItem } from './asyncstorage';
|
||||||
|
|
||||||
|
export default <T>(key: string, defaultValue: T) => {
|
||||||
|
return atomWithStorage<T>(key, defaultValue, {
|
||||||
|
getItem: async () => await getItem(key) || defaultValue,
|
||||||
|
setItem: setItem,
|
||||||
|
delayInit: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { AppSettings } from '../models/settings';
|
|
||||||
import { getItem, setItem } from './asyncstorage';
|
|
||||||
|
|
||||||
const appSettingsKey = '@appSettings';
|
|
||||||
|
|
||||||
export async function getAppSettings(): Promise<AppSettings> {
|
|
||||||
const item = await getItem(appSettingsKey);
|
|
||||||
return item ? JSON.parse(item) : {
|
|
||||||
servers: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setAppSettings(appSettings: AppSettings): Promise<void> {
|
|
||||||
await setItem(appSettingsKey, JSON.stringify(appSettings));
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user