mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 16:33:26 +00:00
refactor: use mmkv and zustand persist middleware for main storage
This commit is contained in:
@@ -24,7 +24,6 @@
|
|||||||
"@movie-web/tmdb": "*",
|
"@movie-web/tmdb": "*",
|
||||||
"@octokit/rest": "^20.0.2",
|
"@octokit/rest": "^20.0.2",
|
||||||
"@react-native-anywhere/polyfill-base64": "0.0.1-alpha.0",
|
"@react-native-anywhere/polyfill-base64": "0.0.1-alpha.0",
|
||||||
"@react-native-async-storage/async-storage": "1.21.0",
|
|
||||||
"@react-navigation/native": "^6.1.9",
|
"@react-navigation/native": "^6.1.9",
|
||||||
"@tamagui/animations-moti": "^1.91.4",
|
"@tamagui/animations-moti": "^1.91.4",
|
||||||
"@tamagui/babel-plugin": "^1.91.4",
|
"@tamagui/babel-plugin": "^1.91.4",
|
||||||
@@ -62,6 +61,7 @@
|
|||||||
"react-native-context-menu-view": "^1.14.1",
|
"react-native-context-menu-view": "^1.14.1",
|
||||||
"react-native-gesture-handler": "~2.14.1",
|
"react-native-gesture-handler": "~2.14.1",
|
||||||
"react-native-ios-modal": "^0.1.8",
|
"react-native-ios-modal": "^0.1.8",
|
||||||
|
"react-native-mmkv": "^2.12.2",
|
||||||
"react-native-modal": "^13.0.1",
|
"react-native-modal": "^13.0.1",
|
||||||
"react-native-quick-base64": "^2.0.8",
|
"react-native-quick-base64": "^2.0.8",
|
||||||
"react-native-quick-crypto": "^0.6.1",
|
"react-native-quick-crypto": "^0.6.1",
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import type { SelectProps } from "tamagui";
|
import type { SelectProps } from "tamagui";
|
||||||
import React, { useEffect, useState } from "react";
|
import React from "react";
|
||||||
import { TouchableOpacity } from "react-native-gesture-handler";
|
import { TouchableOpacity } from "react-native-gesture-handler";
|
||||||
import * as Application from "expo-application";
|
import * as Application from "expo-application";
|
||||||
import * as Linking from "expo-linking";
|
import * as Linking from "expo-linking";
|
||||||
@@ -23,7 +23,7 @@ import ScreenLayout from "~/components/layout/ScreenLayout";
|
|||||||
import { MWSelect } from "~/components/ui/Select";
|
import { MWSelect } from "~/components/ui/Select";
|
||||||
import { MWSwitch } from "~/components/ui/Switch";
|
import { MWSwitch } from "~/components/ui/Switch";
|
||||||
import { checkForUpdate } from "~/lib/update";
|
import { checkForUpdate } from "~/lib/update";
|
||||||
import { getGestureControls, saveGestureControls } from "~/settings";
|
import { usePlayerSettingsStore } from "~/stores/settings";
|
||||||
import { useThemeStore } from "~/stores/theme";
|
import { useThemeStore } from "~/stores/theme";
|
||||||
|
|
||||||
const themeOptions: ThemeStoreOption[] = [
|
const themeOptions: ThemeStoreOption[] = [
|
||||||
@@ -35,18 +35,11 @@ const themeOptions: ThemeStoreOption[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function SettingsScreen() {
|
export default function SettingsScreen() {
|
||||||
const [gestureControlsEnabled, setGestureControlsEnabled] = useState(true);
|
const { gestureControls, setGestureControls } = usePlayerSettingsStore();
|
||||||
const toastController = useToastController();
|
const toastController = useToastController();
|
||||||
|
|
||||||
useEffect(() => {
|
const handleGestureControlsToggle = (isEnabled: boolean) => {
|
||||||
void getGestureControls().then((enabled) => {
|
setGestureControls(isEnabled);
|
||||||
setGestureControlsEnabled(enabled);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleGestureControlsToggle = async (isEnabled: boolean) => {
|
|
||||||
setGestureControlsEnabled(isEnabled);
|
|
||||||
await saveGestureControls(isEnabled);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVersionPress = async () => {
|
const handleVersionPress = async () => {
|
||||||
@@ -78,7 +71,7 @@ export default function SettingsScreen() {
|
|||||||
<Label minWidth={110}>Gesture controls</Label>
|
<Label minWidth={110}>Gesture controls</Label>
|
||||||
<Separator minHeight={20} vertical />
|
<Separator minHeight={20} vertical />
|
||||||
<MWSwitch
|
<MWSwitch
|
||||||
checked={gestureControlsEnabled}
|
checked={gestureControls}
|
||||||
onCheckedChange={handleGestureControlsToggle}
|
onCheckedChange={handleGestureControlsToggle}
|
||||||
>
|
>
|
||||||
<MWSwitch.Thumb animation="quicker" />
|
<MWSwitch.Thumb animation="quicker" />
|
||||||
|
@@ -23,9 +23,9 @@ import { useBrightness } from "~/hooks/player/useBrightness";
|
|||||||
import { usePlaybackSpeed } from "~/hooks/player/usePlaybackSpeed";
|
import { usePlaybackSpeed } from "~/hooks/player/usePlaybackSpeed";
|
||||||
import { usePlayer } from "~/hooks/player/usePlayer";
|
import { usePlayer } from "~/hooks/player/usePlayer";
|
||||||
import { useVolume } from "~/hooks/player/useVolume";
|
import { useVolume } from "~/hooks/player/useVolume";
|
||||||
import { getGestureControls } from "~/settings";
|
|
||||||
import { useAudioTrackStore } from "~/stores/audio";
|
import { useAudioTrackStore } from "~/stores/audio";
|
||||||
import { usePlayerStore } from "~/stores/player/store";
|
import { usePlayerStore } from "~/stores/player/store";
|
||||||
|
import { usePlayerSettingsStore } from "~/stores/settings";
|
||||||
import { CaptionRenderer } from "./CaptionRenderer";
|
import { CaptionRenderer } from "./CaptionRenderer";
|
||||||
import { ControlsOverlay } from "./ControlsOverlay";
|
import { ControlsOverlay } from "./ControlsOverlay";
|
||||||
|
|
||||||
@@ -62,13 +62,7 @@ export const VideoPlayer = () => {
|
|||||||
const toggleAudio = usePlayerStore((state) => state.toggleAudio);
|
const toggleAudio = usePlayerStore((state) => state.toggleAudio);
|
||||||
const toggleState = usePlayerStore((state) => state.toggleState);
|
const toggleState = usePlayerStore((state) => state.toggleState);
|
||||||
|
|
||||||
const [gestureControlsEnabled, setGestureControlsEnabled] = useState(true);
|
const { gestureControls } = usePlayerSettingsStore();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
void getGestureControls().then((enabled) => {
|
|
||||||
setGestureControlsEnabled(enabled);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const updateResizeMode = (newMode: ResizeMode) => {
|
const updateResizeMode = (newMode: ResizeMode) => {
|
||||||
setResizeMode(newMode);
|
setResizeMode(newMode);
|
||||||
@@ -85,7 +79,7 @@ export const VideoPlayer = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const doubleTapGesture = Gesture.Tap()
|
const doubleTapGesture = Gesture.Tap()
|
||||||
.enabled(gestureControlsEnabled && isIdle)
|
.enabled(gestureControls && isIdle)
|
||||||
.numberOfTaps(2)
|
.numberOfTaps(2)
|
||||||
.onEnd(() => {
|
.onEnd(() => {
|
||||||
runOnJS(toggleAudio)();
|
runOnJS(toggleAudio)();
|
||||||
@@ -95,7 +89,7 @@ export const VideoPlayer = () => {
|
|||||||
const screenHalfWidth = Dimensions.get("window").width / 2;
|
const screenHalfWidth = Dimensions.get("window").width / 2;
|
||||||
|
|
||||||
const panGesture = Gesture.Pan()
|
const panGesture = Gesture.Pan()
|
||||||
.enabled(gestureControlsEnabled && isIdle)
|
.enabled(gestureControls && isIdle)
|
||||||
.onStart((event) => {
|
.onStart((event) => {
|
||||||
if (event.x > screenHalfWidth) {
|
if (event.x > screenHalfWidth) {
|
||||||
runOnJS(setShowVolumeOverlay)(true);
|
runOnJS(setShowVolumeOverlay)(true);
|
||||||
|
@@ -5,7 +5,7 @@ import * as FileSystem from "expo-file-system";
|
|||||||
import * as MediaLibrary from "expo-media-library";
|
import * as MediaLibrary from "expo-media-library";
|
||||||
import { useToastController } from "@tamagui/toast";
|
import { useToastController } from "@tamagui/toast";
|
||||||
|
|
||||||
import { loadDownloadHistory, saveDownloadHistory } from "~/settings";
|
import { useDownloadHistoryStore } from "~/stores/settings";
|
||||||
|
|
||||||
export interface DownloadItem {
|
export interface DownloadItem {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -48,8 +48,8 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
const toastController = useToastController();
|
const toastController = useToastController();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeDownloads = async () => {
|
const initializeDownloads = () => {
|
||||||
const storedDownloads = await loadDownloadHistory();
|
const { downloads: storedDownloads } = useDownloadHistoryStore.getState();
|
||||||
if (storedDownloads) {
|
if (storedDownloads) {
|
||||||
setDownloads(storedDownloads);
|
setDownloads(storedDownloads);
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void saveDownloadHistory(downloads.slice(0, 10));
|
useDownloadHistoryStore.setState({ downloads });
|
||||||
}, [downloads]);
|
}, [downloads]);
|
||||||
|
|
||||||
const startDownload = async (
|
const startDownload = async (
|
||||||
@@ -195,7 +195,7 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
const removeDownload = (id: string) => {
|
const removeDownload = (id: string) => {
|
||||||
const updatedDownloads = downloads.filter((download) => download.id !== id);
|
const updatedDownloads = downloads.filter((download) => download.id !== id);
|
||||||
setDownloads(updatedDownloads);
|
setDownloads(updatedDownloads);
|
||||||
void saveDownloadHistory(updatedDownloads);
|
useDownloadHistoryStore.setState({ downloads: updatedDownloads });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -1,84 +0,0 @@
|
|||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
||||||
|
|
||||||
import type { DownloadItem } from "~/hooks/DownloadManagerContext";
|
|
||||||
import type { ThemeStoreOption } from "~/stores/theme";
|
|
||||||
|
|
||||||
interface ThemeSettings {
|
|
||||||
theme: ThemeStoreOption;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PlayerSettings {
|
|
||||||
gestureControls: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Settings {
|
|
||||||
themes?: ThemeSettings;
|
|
||||||
player?: PlayerSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const settingsKey = "settings";
|
|
||||||
|
|
||||||
const saveSettings = async (newSettings: Partial<Settings>) => {
|
|
||||||
const settings = await loadSettings();
|
|
||||||
const mergedSettings = { ...settings, ...newSettings };
|
|
||||||
await AsyncStorage.setItem(settingsKey, JSON.stringify(mergedSettings));
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadSettings = async (): Promise<Settings | null> => {
|
|
||||||
const json = await AsyncStorage.getItem(settingsKey);
|
|
||||||
return json ? (JSON.parse(json) as Settings) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTheme = async (): Promise<ThemeStoreOption> => {
|
|
||||||
const settings = await loadSettings();
|
|
||||||
return settings?.themes?.theme ?? "main";
|
|
||||||
};
|
|
||||||
|
|
||||||
export const saveTheme = async (newTheme: ThemeStoreOption) => {
|
|
||||||
const existingSettings = await loadSettings();
|
|
||||||
const settings: Settings = existingSettings?.themes?.theme
|
|
||||||
? {
|
|
||||||
themes: { theme: newTheme },
|
|
||||||
}
|
|
||||||
: { themes: { theme: "main" } };
|
|
||||||
await saveSettings(settings);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface DownloadHistory {
|
|
||||||
downloads: DownloadItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadHistoryKey = "downloadHistory";
|
|
||||||
|
|
||||||
export const saveDownloadHistory = async (downloads: DownloadItem[]) => {
|
|
||||||
const json = await AsyncStorage.getItem(downloadHistoryKey);
|
|
||||||
const settings = json
|
|
||||||
? (JSON.parse(json) as DownloadHistory)
|
|
||||||
: { downloads: [] };
|
|
||||||
settings.downloads = downloads;
|
|
||||||
await AsyncStorage.setItem(downloadHistoryKey, JSON.stringify(settings));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const loadDownloadHistory = async (): Promise<DownloadItem[]> => {
|
|
||||||
const json = await AsyncStorage.getItem(downloadHistoryKey);
|
|
||||||
const settings = json
|
|
||||||
? (JSON.parse(json) as DownloadHistory)
|
|
||||||
: { downloads: [] };
|
|
||||||
return settings.downloads;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getGestureControls = async (): Promise<boolean> => {
|
|
||||||
const settings = await loadSettings();
|
|
||||||
return settings?.player?.gestureControls ?? true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const saveGestureControls = async (gestureControls: boolean) => {
|
|
||||||
const settings = (await loadSettings()) ?? {};
|
|
||||||
|
|
||||||
if (!settings.player) {
|
|
||||||
settings.player = { gestureControls: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.player.gestureControls = gestureControls;
|
|
||||||
await saveSettings(settings);
|
|
||||||
};
|
|
86
apps/expo/src/stores/settings/index.ts
Normal file
86
apps/expo/src/stores/settings/index.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import type { StateStorage } from "zustand/middleware";
|
||||||
|
import { MMKV } from "react-native-mmkv";
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { createJSONStorage, persist } from "zustand/middleware";
|
||||||
|
|
||||||
|
import type { DownloadItem } from "~/hooks/DownloadManagerContext";
|
||||||
|
import type { ThemeStoreOption } from "~/stores/theme";
|
||||||
|
|
||||||
|
const storage = new MMKV();
|
||||||
|
|
||||||
|
const zustandStorage: StateStorage = {
|
||||||
|
getItem: (name: string): string | null => {
|
||||||
|
const value = storage.getString(name);
|
||||||
|
return value ?? null;
|
||||||
|
},
|
||||||
|
setItem: (name: string, value: string): void => {
|
||||||
|
storage.set(name, value);
|
||||||
|
},
|
||||||
|
removeItem: (name: string): void => {
|
||||||
|
storage.delete(name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ThemeStoreState {
|
||||||
|
theme: ThemeStoreOption;
|
||||||
|
setTheme: (theme: ThemeStoreOption) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useThemeSettingsStore = create<
|
||||||
|
ThemeStoreState,
|
||||||
|
[["zustand/persist", ThemeStoreState]]
|
||||||
|
>(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
theme: "main",
|
||||||
|
setTheme: (theme: ThemeStoreOption) => set({ theme }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "theme-settings",
|
||||||
|
storage: createJSONStorage(() => zustandStorage),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
interface PlayerStoreState {
|
||||||
|
gestureControls: boolean;
|
||||||
|
setGestureControls: (enabled: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePlayerSettingsStore = create<
|
||||||
|
PlayerStoreState,
|
||||||
|
[["zustand/persist", PlayerStoreState]]
|
||||||
|
>(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
gestureControls: true,
|
||||||
|
setGestureControls: (enabled: boolean) =>
|
||||||
|
set({ gestureControls: enabled }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "player-settings",
|
||||||
|
storage: createJSONStorage(() => zustandStorage),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
interface DownloadHistoryStoreState {
|
||||||
|
downloads: DownloadItem[];
|
||||||
|
setDownloads: (downloads: DownloadItem[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDownloadHistoryStore = create<
|
||||||
|
DownloadHistoryStoreState,
|
||||||
|
[["zustand/persist", DownloadHistoryStoreState]]
|
||||||
|
>(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
downloads: [],
|
||||||
|
setDownloads: (downloads: DownloadItem[]) => set({ downloads }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "download-history",
|
||||||
|
storage: createJSONStorage(() => zustandStorage),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
@@ -2,7 +2,7 @@ import { setAlternateAppIcon } from "expo-alternate-app-icons";
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { immer } from "zustand/middleware/immer";
|
import { immer } from "zustand/middleware/immer";
|
||||||
|
|
||||||
import { getTheme, saveTheme } from "~/settings";
|
import { useThemeSettingsStore } from "~/stores/settings";
|
||||||
|
|
||||||
export type ThemeStoreOption = "main" | "blue" | "gray" | "red" | "teal";
|
export type ThemeStoreOption = "main" | "blue" | "gray" | "red" | "teal";
|
||||||
|
|
||||||
@@ -13,25 +13,16 @@ export interface ThemeStore {
|
|||||||
|
|
||||||
export const useThemeStore = create(
|
export const useThemeStore = create(
|
||||||
immer<ThemeStore>((set) => {
|
immer<ThemeStore>((set) => {
|
||||||
void getTheme().then((savedTheme) => {
|
const { theme, setTheme: updateTheme } = useThemeSettingsStore.getState();
|
||||||
set((s) => {
|
|
||||||
s.theme = savedTheme;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: "main",
|
theme,
|
||||||
setTheme: (newTheme) => {
|
setTheme: (newTheme) => {
|
||||||
saveTheme(newTheme)
|
updateTheme(newTheme);
|
||||||
.then(() => {
|
set((state) => {
|
||||||
set((s) => {
|
state.theme = newTheme;
|
||||||
s.theme = newTheme;
|
void setAlternateAppIcon(newTheme);
|
||||||
void setAlternateAppIcon(newTheme);
|
});
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Failed to save theme:", error);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
37
pnpm-lock.yaml
generated
37
pnpm-lock.yaml
generated
@@ -44,9 +44,6 @@ importers:
|
|||||||
'@react-native-anywhere/polyfill-base64':
|
'@react-native-anywhere/polyfill-base64':
|
||||||
specifier: 0.0.1-alpha.0
|
specifier: 0.0.1-alpha.0
|
||||||
version: 0.0.1-alpha.0
|
version: 0.0.1-alpha.0
|
||||||
'@react-native-async-storage/async-storage':
|
|
||||||
specifier: 1.21.0
|
|
||||||
version: 1.21.0(react-native@0.73.6)
|
|
||||||
'@react-navigation/native':
|
'@react-navigation/native':
|
||||||
specifier: ^6.1.9
|
specifier: ^6.1.9
|
||||||
version: 6.1.9(react-native@0.73.6)(react@18.2.0)
|
version: 6.1.9(react-native@0.73.6)(react@18.2.0)
|
||||||
@@ -158,6 +155,9 @@ importers:
|
|||||||
react-native-ios-modal:
|
react-native-ios-modal:
|
||||||
specifier: ^0.1.8
|
specifier: ^0.1.8
|
||||||
version: 0.1.8(react-native@0.73.6)(react@18.2.0)
|
version: 0.1.8(react-native@0.73.6)(react@18.2.0)
|
||||||
|
react-native-mmkv:
|
||||||
|
specifier: ^2.12.2
|
||||||
|
version: 2.12.2(react-native@0.73.6)(react@18.2.0)
|
||||||
react-native-modal:
|
react-native-modal:
|
||||||
specifier: ^13.0.1
|
specifier: ^13.0.1
|
||||||
version: 13.0.1(react-native@0.73.6)(react@18.2.0)
|
version: 13.0.1(react-native@0.73.6)(react@18.2.0)
|
||||||
@@ -3041,15 +3041,6 @@ packages:
|
|||||||
base-64: 0.1.0
|
base-64: 0.1.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@react-native-async-storage/async-storage@1.21.0(react-native@0.73.6):
|
|
||||||
resolution: {integrity: sha512-JL0w36KuFHFCvnbOXRekqVAUplmOyT/OuCQkogo6X98MtpSaJOKEAeZnYO8JB0U/RIEixZaGI5px73YbRm/oag==}
|
|
||||||
peerDependencies:
|
|
||||||
react-native: ^0.0.0-0 || >=0.60 <1.0
|
|
||||||
dependencies:
|
|
||||||
merge-options: 3.0.4
|
|
||||||
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@react-native-community/cli-clean@12.3.6:
|
/@react-native-community/cli-clean@12.3.6:
|
||||||
resolution: {integrity: sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==}
|
resolution: {integrity: sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9089,11 +9080,6 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/is-plain-obj@2.1.0:
|
|
||||||
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/is-plain-object@2.0.4:
|
/is-plain-object@2.0.4:
|
||||||
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
|
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -10017,13 +10003,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==}
|
resolution: {integrity: sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/merge-options@3.0.4:
|
|
||||||
resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
is-plain-obj: 2.1.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/merge-stream@2.0.0:
|
/merge-stream@2.0.0:
|
||||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||||
|
|
||||||
@@ -11543,6 +11522,16 @@ packages:
|
|||||||
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
|
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-native-mmkv@2.12.2(react-native@0.73.6)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '*'
|
||||||
|
react-native: '>=0.71.0'
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-native-modal@13.0.1(react-native@0.73.6)(react@18.2.0):
|
/react-native-modal@13.0.1(react-native@0.73.6)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==}
|
resolution: {integrity: sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
Reference in New Issue
Block a user