11import React from "react" ;
22import { Dimensions , Platform } from "react-native" ;
3+ import AsyncStorage from "@react-native-async-storage/async-storage" ;
34import createThemeValuesProxy from "./createThemeValuesProxy" ;
45import DefaultTheme from "./DefaultTheme" ;
5- import { Breakpoints , ReadTheme , ValidatedTheme } from "./types" ;
6+ import {
7+ Breakpoints ,
8+ ChangeThemeOptions ,
9+ ReadTheme ,
10+ ValidatedTheme ,
11+ } from "./types" ;
12+
13+ const SAVED_SELECTED_THEME_KEY = "saved_selected_theme" ;
614
715type ThemeContextType = {
816 theme : ReadTheme ;
@@ -34,18 +42,9 @@ const Provider: React.FC<React.PropsWithChildren<ProviderProps>> = ({
3442 Dimensions . get ( "window" ) . width
3543 ) ;
3644
37- React . useEffect ( ( ) => {
38- const listener = Dimensions . addEventListener ( "change" , ( { window } ) =>
39- setDeviceWidth ( window . width )
40- ) ;
41- return ( ) => {
42- listener . remove ( ) ;
43- } ;
44- } ) ;
45-
4645 const changeTheme = React . useCallback (
47- ( themeName : string ) => {
48- const theme = themes . find ( ( theme ) => theme . name === themeName ) ;
46+ ( themeName : string , options ?: ChangeThemeOptions ) => {
47+ const theme = themes . find ( ( t ) => t . name === themeName ) ;
4948 if ( ! theme ) {
5049 console . warn (
5150 "Theme with name" ,
@@ -55,6 +54,12 @@ const Provider: React.FC<React.PropsWithChildren<ProviderProps>> = ({
5554 return ;
5655 }
5756 setCurrentTheme ( theme ) ;
57+
58+ if ( options ?. persistent === true ) {
59+ AsyncStorage . setItem ( SAVED_SELECTED_THEME_KEY , themeName ) . catch ( ( e ) => {
60+ console . warn ( "Failed to persist selected theme" , e ) ;
61+ } ) ;
62+ }
5863 } ,
5964 [ themes , setCurrentTheme ]
6065 ) ;
@@ -98,6 +103,30 @@ const Provider: React.FC<React.PropsWithChildren<ProviderProps>> = ({
98103 [ currentTheme , deviceWidth , breakpoints ]
99104 ) ;
100105
106+ React . useEffect ( ( ) => {
107+ const listener = Dimensions . addEventListener ( "change" , ( { window } ) =>
108+ setDeviceWidth ( window . width )
109+ ) ;
110+ return ( ) => {
111+ listener . remove ( ) ;
112+ } ;
113+ } ) ;
114+
115+ React . useEffect ( ( ) => {
116+ const run = async ( ) => {
117+ const savedSelectedThemeName = await AsyncStorage . getItem (
118+ SAVED_SELECTED_THEME_KEY
119+ ) ;
120+ if ( savedSelectedThemeName ) {
121+ changeTheme ( savedSelectedThemeName ) ;
122+ }
123+ } ;
124+ run ( ) ;
125+
126+ // This should only run once, ignore deps
127+ // eslint-disable-next-line react-hooks/exhaustive-deps
128+ } , [ ] ) ;
129+
101130 return (
102131 < ThemeContext . Provider value = { { theme : proxiedTheme , changeTheme } } >
103132 { children }
@@ -110,7 +139,10 @@ const useTheme = (): ReadTheme => {
110139 return theme ;
111140} ;
112141
113- const useChangeTheme = ( ) : ( ( themeName : string ) => void ) => {
142+ const useChangeTheme = ( ) : ( (
143+ themeName : string ,
144+ options ?: ChangeThemeOptions
145+ ) => void ) => {
114146 const { changeTheme } = React . useContext ( ThemeContext ) ;
115147 return changeTheme ;
116148} ;
0 commit comments