react-native#AsyncStorage TypeScript Examples
The following examples show how to use
react-native#AsyncStorage.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LoadAssets.tsx From react-native-meetio with MIT License | 7 votes |
LoadAssets = ({ assets, fonts, children }: LoadAssetsProps) => {
const [isNavigationReady, setIsNavigationReady] = useState(!__DEV__);
const [initialState, setInitialState] = useState<InitialState | undefined>();
const ready = useLoadAssets(assets || [], fonts || {});
useEffect(() => {
const restoreState = async () => {
try {
const savedStateString = await AsyncStorage.getItem(
NAVIGATION_STATE_KEY
);
const state = savedStateString
? JSON.parse(savedStateString)
: undefined;
setInitialState(state);
} finally {
setIsNavigationReady(true);
}
};
if (!isNavigationReady) {
restoreState();
}
}, [isNavigationReady]);
const onStateChange = useCallback((state) => {
AsyncStorage.setItem(NAVIGATION_STATE_KEY, JSON.stringify(state));
}, []);
if (!ready || !isNavigationReady) {
return <AppLoading />;
}
return (
<NavigationContainer {...{ onStateChange, initialState }}>
{children}
</NavigationContainer>
);
}
Example #2
Source File: Login.tsx From jmix-frontend with Apache License 2.0 | 6 votes |
onSubmit = () => {
if (!this.isSubmitEnabled) {
return;
}
this.clearErrors();
this.loading = true;
this.props
.onLoginSubmit(this.login, this.password)
.then(_value => {
return AsyncStorage.setItem(REST_TOKEN_STORAGE_KEY, jmixREST.restApiToken);
})
.catch(err => {
if (err.response) {
err.response.json().then((message) => {
if (message.error === OAUTH2_INVALID_GRANT) {
this.badCredentialsError = true;
} else {
this.serverError = true;
}
});
} else {
this.serverError = true;
}
})
.finally(() => {
this.loading = false;
});
};
Example #3
Source File: StorageAsync.ts From companion-kit with MIT License | 6 votes |
StorageAsync: IStorage = {
getValue(key: string): Promise<string> {
return AsyncStorage.getItem(key);
},
setValue(key: string, value: string): Promise<void> {
if (!key) {
throw new Error('[StorageAsync] key must be not empty! got:' + key);
}
if (!value) {
throw new Error('[StorageAsync] value must be not null! use \'remove\' instead. Got: ' + `${key} | ${value}` );
}
return AsyncStorage.setItem(key, value);
},
async hasValue(key: string): Promise<boolean> {
try {
const value = await StorageAsync.getValue(key);
return !!value;
} catch (err) {
return false;
}
},
remove(key: string): Promise<void> {
return AsyncStorage.removeItem(key);
},
}
Example #4
Source File: theme.tsx From ecoleta with MIT License | 6 votes |
ThemeProvider: React.FC = ({ children }) => {
const deviceTheme = useColorScheme();
const [theme, setTheme] = useState(deviceTheme === 'light' ? light : dark);
useEffect(() => {
async function getPersistedTheme(): Promise<void> {
const persistedTheme = await AsyncStorage.getItem('theme');
if (persistedTheme) {
setTheme(persistedTheme === 'light' ? light : dark);
}
}
getPersistedTheme();
}, []);
const persistTheme = useCallback(async themeToPersist => {
setTheme(themeToPersist === 'light' ? light : dark);
await AsyncStorage.setItem('theme', themeToPersist);
}, []);
useEffect(() => {
persistTheme(deviceTheme);
}, [deviceTheme, persistTheme]);
const toggleTheme = useCallback(() => {
persistTheme(theme.title === 'light' ? 'dark' : 'light');
}, [theme.title, persistTheme]);
return (
<StyledProvider theme={theme}>
<ThemeContext.Provider value={{ toggleTheme }}>
{children}
</ThemeContext.Provider>
</StyledProvider>
);
}
Example #5
Source File: status.ts From selftrace with MIT License | 6 votes |
subscribeToAuthStateChange = () => (dispatch: Dispatch) => {
API.initialize();
return API.requestAuthStateListener((async (user: UserInfo) => {
if (!user) {
// Case 1: Signed out
await Promise.all([
AsyncStorage.removeItem('wellbeing'),
AsyncStorage.removeItem('locationLastUpdatedAt'),
AsyncStorage.removeItem('lastMapCenter'),
]);
return dispatch(setAuthStatusToSignedOut());
}
// Case 2: Signed in
const userInfo = {
email: user.email,
uid: user.uid,
};
await downloadUserInfoToLocalDB(user.uid);
await pullUserInfoFromLocalDBToRedux(dispatch);
return dispatch(setAuthStatusToSignedIn(userInfo));
}) as any);
}
Example #6
Source File: userInfo.ts From selftrace with MIT License | 6 votes |
export async function downloadUserInfoToLocalDB(uid: string): Promise<void> {
try {
const userDoc = await API.requestUserInfo(uid);
if (!userDoc) {
// The user has just signed up. The server is creating the user document in Firestore.
return undefined;
}
const { wellbeing, symptomMap } = userDoc;
const storageTasks: Promise<void>[] = [];
if (wellbeing) {
storageTasks.push(AsyncStorage.setItem('wellbeing', wellbeing.toString()));
}
if (symptomMap) {
storageTasks.push(AsyncStorage.setItem('symptomMap', JSON.stringify(symptomMap)));
}
if (storageTasks.length > 0) {
await Promise.all(storageTasks);
}
return Promise.resolve();
} catch (err) {
return Promise.reject(err);
}
}
Example #7
Source File: helpers.tsx From js-examples with MIT License | 6 votes |
generateIdentity = async (): Promise<PrivateKey> => {
let idStr = await AsyncStorage.getItem(IDENTITY_KEY)
if (idStr) {
return PrivateKey.fromString(idStr)
} else {
const id = PrivateKey.fromRandom()
idStr = id.toString()
await AsyncStorage.setItem(IDENTITY_KEY, idStr)
return id
}
}
Example #8
Source File: helpers.ts From selftrace with MIT License | 6 votes |
export async function pullUserInfoFromLocalDBToRedux(dispatch: Dispatch) {
try {
const [wellbeingRaw, symptomMapRaw] = await Promise.all([
AsyncStorage.getItem('wellbeing'),
AsyncStorage.getItem('symptomMap'),
]);
dispatch(
receiveUpdateUserInfoResponse({
wellbeing: wellbeingRaw === null ? undefined : Number(wellbeingRaw),
symptomMap: symptomMapRaw === null ? {} : JSON.parse(symptomMapRaw),
})
);
dispatch(clearUpdateUserInfoProgress());
} catch (err) {
//
}
}
Example #9
Source File: helpers.tsx From js-examples with MIT License | 6 votes |
getCachedUserThread = async (): Promise<ThreadID | undefined> => {
/**
* All storage should be scoped to the identity
*
* If the identity changes and you try to use an old database,
* it will error due to not authorized.
*/
const idStr = await AsyncStorage.getItem(USER_THREAD_ID)
if (idStr) {
/**
* Temporary hack to get ThreadID working in RN
*/
const id: ThreadID = ThreadID.fromString(idStr)
return id
}
return undefined
}
Example #10
Source File: CustomAppearanceProvider.tsx From selftrace with MIT License | 6 votes |
async function rehydrateAppearanceState() {
if (!shouldRehydrate || !AsyncStorage) {
return defaultState;
}
try {
const item = await AsyncStorage.getItem(appearanceStorageKey);
return item ? JSON.parse(item) : null;
} catch (ignored) {
return defaultState;
}
}
Example #11
Source File: expo-mixpanel-analytics.ts From beancount-mobile with MIT License | 6 votes |
constructor(token: string) {
this.ready = false;
this.queue = [];
this.token = token;
this.userId = null;
this.clientId = Constants.deviceId;
this.osVersion = Platform.Version;
this.superProps;
Constants.getWebViewUserAgentAsync().then((userAgent) => {
this.userAgent = userAgent;
this.appName = Constants.manifest.name;
this.appId = Constants.manifest.slug;
this.appVersion = Constants.manifest.version;
this.screenSize = `${width}x${height}`;
this.deviceName = Constants.deviceName;
if (isIosPlatform && Constants.platform && Constants.platform.ios) {
this.platform = Constants.platform.ios.platform;
this.model = Constants.platform.ios.model;
} else {
this.platform = "android";
}
AsyncStorage.getItem(ASYNC_STORAGE_KEY, (_, result) => {
if (result) {
try {
this.superProps = JSON.parse(result) || {};
// eslint-disable-next-line no-empty
} catch {}
}
this.ready = true;
this.identify(this.clientId);
this._flush();
});
});
}
Example #12
Source File: TutorialScreen.tsx From lets-fork-native with MIT License | 6 votes |
TutorialScreen = React.memo((props: Props): React.ReactElement => {
const { setShowApp } = props
const renderItem = (item: Item): React.ReactElement => (
<View style={styles.slide}>
<Text style={styles.text}>{item.item.text}</Text>
</View>
)
const onDone = (): void => {
setShowApp(true)
AsyncStorage.setItem('showApp', 'true')
}
return (
<View style={styles.container}>
<View style={styles.headerContainer}>
<MaterialIcons style={styles.icon} name="restaurant" color={colors.white} size={26} />
<RNText style={styles.header}>Let's Fork</RNText>
</View>
<AppIntroSlider
renderItem={renderItem}
data={slides}
onDone={onDone}
/>
</View>
)
})
Example #13
Source File: App.tsx From jmix-frontend with Apache License 2.0 | 5 votes |
export default function App() {
return (
<JmixAppProvider jmixREST={jmixREST} retrieveRestApiToken={() => AsyncStorage.getItem(REST_TOKEN_STORAGE_KEY)}>
<Root/>
</JmixAppProvider>
);
}
Example #14
Source File: helpers.tsx From js-examples with MIT License | 5 votes |
cacheUserThread = async (id: ThreadID) => {
await AsyncStorage.setItem(USER_THREAD_ID, id.toString())
}
Example #15
Source File: expo-mixpanel-analytics.ts From beancount-mobile with MIT License | 5 votes |
reset() {
this.identify(this.clientId);
try {
AsyncStorage.setItem(ASYNC_STORAGE_KEY, JSON.stringify({}));
// eslint-disable-next-line no-empty
} catch {}
}
Example #16
Source File: expo-mixpanel-analytics.ts From beancount-mobile with MIT License | 5 votes |
register(props: any) {
this.superProps = props;
try {
AsyncStorage.setItem(ASYNC_STORAGE_KEY, JSON.stringify(props));
// eslint-disable-next-line no-empty
} catch {}
}
Example #17
Source File: announcement.tsx From beancount-mobile with MIT License | 5 votes |
export function Announcement(props: Props): JSX.Element {
const [hide, setHide] = React.useState(true);
React.useEffect(() => {
async function init() {
try {
const value = await AsyncStorage.getItem("@HideAnnouncement:key");
if (value !== null) {
setHide(value === "true");
} else {
setHide(false);
}
} catch (error) {
console.error(`failed to get hide announcement value: ${error}`);
}
}
init();
}, []);
const { title, subtitle, icon, navigation } = props;
const theme = useTheme();
const styles = getStyles(theme.colorTheme);
if (hide) {
return <View />;
}
return (
<TouchableOpacity
style={styles.container}
onPress={async () => {
try {
await AsyncStorage.setItem("@SubscriptionFlash:key", "true");
} catch (error) {
console.error(`failed to set subscription flash value: ${error}`);
}
navigation.navigate("Mine");
}}
>
<View style={styles.titleContainer}>
<Text style={styles.subtitle}>{subtitle}</Text>
<Text numberOfLines={2} style={styles.title}>
{title}
</Text>
</View>
<View>{icon}</View>
<TouchableOpacity
style={styles.closeButton}
activeOpacity={0.9}
onPress={async () => {
setHide(true);
try {
await AsyncStorage.setItem("@HideAnnouncement:key", "true");
} catch (error) {
console.error(`failed to set hide announcement value: ${error}`);
}
}}
>
<Text style={styles.closeText}>✕</Text>
</TouchableOpacity>
</TouchableOpacity>
);
}
Example #18
Source File: RestaurantScreen.tsx From lets-fork-native with MIT License | 5 votes |
RestaurantScreen = React.memo((props: Props) => {
const { route } = props
const { restaurant } = route.params
// Request a review from users every 10 times they view a
// match restaurant. The app will stop asking once they click
// 'Sure' on Android, or once every 365 days for iOS
React.useEffect(() => {
async function requestReview(): Promise<void> {
const [restaurantsViewed, hasReviewed] = await Promise.all([
AsyncStorage.getItem('restaurantsViewed'),
AsyncStorage.getItem('hasReviewed'),
])
if (Number(restaurantsViewed) % 10 === 0) {
setTimeout(() => {
if (Platform.OS === 'android') {
if (!hasReviewed) {
Alert.alert(
"Enjoying Let's Fork?",
'Leave a review on the Play Store',
[
{ text: 'Maybe Later' },
{
text: 'Sure',
onPress: async (): Promise<void> => {
await AsyncStorage.setItem('hasReviewed', 'true')
return StoreReview.requestReview()
},
},
],
{ cancelable: false },
)
}
} else {
StoreReview.requestReview()
}
}, 3000)
}
AsyncStorage.setItem('restaurantsViewed', `${Number(restaurantsViewed) + 1}`)
}
requestReview()
}, [])
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<Details
photos
restaurant={restaurant}
/>
</ScrollView>
</SafeAreaView>
)
})
Example #19
Source File: CustomAppearanceProvider.tsx From selftrace with MIT License | 5 votes |
async function cacheAppearanceState(appearance) {
await AsyncStorage.setItem(appearanceStorageKey, JSON.stringify(appearance));
}
Example #20
Source File: userInfo.ts From selftrace with MIT License | 5 votes |
uploadUserInfo = (
uid: string,
updatedInfo: Partial<API.FirestoreUserDoc>,
haveDetailsChanged: boolean
) => async (dispatch: Dispatch) => {
dispatch(startUpdateUserInfoRequest());
try {
const locationLastUpdatedAtRaw = await AsyncStorage.getItem('locationLastUpdatedAt');
const hasNotUpdatedLocationFor30Mins =
!locationLastUpdatedAtRaw || Date.now() - Number(locationLastUpdatedAtRaw) > 1000 * 60 * 30;
const isUserUnwell =
updatedInfo.wellbeing === Wellbeing.ShowingSymptoms ||
updatedInfo.wellbeing === Wellbeing.TestedPositive;
const updatedInfoFinal: Partial<API.FirestoreUserDoc> = { ...updatedInfo };
if (!isUserUnwell) {
// Case 1: User is well
updatedInfoFinal.lastLocation = API.deletionSentinel() as any;
await API.requestUpdateUserInfo(uid, updatedInfoFinal);
await AsyncStorage.removeItem('locationLastUpdatedAt');
} else if (haveDetailsChanged || hasNotUpdatedLocationFor30Mins) {
// Case 2: User is unwell and their details are not up to date
if (hasNotUpdatedLocationFor30Mins) {
dispatch(startRetrievingUserLocation());
const { latitude, longitude } = await retrieveLastLocationWithPermission();
updatedInfoFinal.lastLocation = { lat: latitude, lng: longitude };
}
await API.requestUpdateUserInfo(uid, updatedInfoFinal);
await AsyncStorage.setItem('locationLastUpdatedAt', Date.now().toString());
} else {
// Case 3: User is unwell but their details are up-to-date
await PromiseUtils.sleep(750); // Simulate update request
}
dispatch(receiveUpdateUserInfoResponse(updatedInfo));
setTimeout(() => {
dispatch(clearUpdateUserInfoProgress());
}, GRACEFUL_EXIT_DURATION);
} catch (err) {
const error =
err instanceof LocationPermissionError
? new Error('Update failed because you did not agree to share your location.') // TODO: Localize
: err;
dispatch(receiveUpdateUserInfoError(error));
}
}
Example #21
Source File: App.tsx From lets-fork-native with MIT License | 4 votes |
export default function App(): React.ReactElement {
const [showApp, setShowApp] = React.useState(false)
const [fontsLoaded] = useFonts({ VarelaRound_400Regular })
const [loading, setLoading] = React.useState<boolean>(true)
const [location, setLocation] = React.useState<Location.LocationObject>()
const [party, setParty] = React.useState<Party>({} as Party)
const linking = {
prefixes: ['https://letsfork.app', 'letsfork://', 'exp://192.168.178.76:19000/+'],
config: {
screens: {
Party: 'party/:id',
},
},
}
React.useEffect(() => {
// Keep track of current matches
let matches: Restaurant[] = []
ws.onopen = (): void => {
console.log('opened')
}
ws.onmessage = (msg): void => {
console.log(msg.data)
const data: Party = JSON.parse(msg.data)
const newMatches = JSON.stringify(data.matches?.map((r) => r.id).sort())
const oldMatches = JSON.stringify(matches?.map((r) => r.id).sort())
// Alert when there are new matches
if (data.matches?.length
&& oldMatches !== newMatches) {
matches = data.matches
Alert.alert(
'You have a new match!',
'Click the icon in the top right to view your matches',
)
}
setParty(data)
}
ws.onclose = (msg): void => {
console.log('closed', msg.reason)
}
ws.onerror = (err): void => {
console.log('websocket error:', err)
}
}, [])
const loadApplicationAsync = async (): Promise<void> => {
const { status } = await Location.requestPermissionsAsync()
if (status !== 'granted') {
console.log('Permission to access location was denied')
}
const [loc, val] = await Promise.all([
Location.getCurrentPositionAsync({}),
AsyncStorage.getItem('showApp'),
])
if (loc) setLocation(loc)
// User has seen intro
if (val) setShowApp(true)
}
if (loading || !fontsLoaded) {
return (
<AppLoading
startAsync={loadApplicationAsync}
onFinish={(): void => setLoading(false)}
onError={console.warn}
/>
)
}
if (!showApp) {
return <TutorialScreen setShowApp={setShowApp} />
}
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Create"
options={(): object => ({
headerTitle: (): null => null,
})}
>
{(props): React.ReactElement => (
<CreateScreen
{...props}
ws={ws}
location={location}
/>
)}
</Stack.Screen>
<Stack.Screen
name="Home"
component={HomeScreen}
options={(): object => ({
headerShown: false,
})}
/>
<Stack.Screen
name="Join"
options={(): object => ({
headerTitle: (): null => null,
})}
>
{(props): React.ReactElement => <JoinScreen {...props} ws={ws} />}
</Stack.Screen>
<Stack.Screen
name="Match"
options={(): object => ({
headerTitle: (): null => null,
})}
>
{(props): React.ReactElement => <MatchScreen {...props} party={party} />}
</Stack.Screen>
<Stack.Screen
name="Party"
options={({ navigation }): object => ({
gestureEnabled: false,
headerTitle: (): null => null,
headerLeft: (): React.ReactElement => (
<TouchableOpacity
style={styles.backButton}
onPress={(): void => Alert.alert(
'Are you sure you want to exit?',
'Exiting will make you lose all data in this party',
[
{ text: 'Cancel' },
{
text: 'OK',
onPress: (): void => {
ws.send(JSON.stringify({ type: 'quit' }))
navigation.navigate('Home')
setParty({} as Party)
},
},
],
{ cancelable: true },
)}
>
<MaterialIcons name="close" color="black" size={24} />
</TouchableOpacity>
),
headerRight: (): React.ReactElement | null => (
party.status === 'active'
? <Menu navigation={navigation} />
: null
),
})}
>
{(props): React.ReactElement => (
<PartyScreen
{...props}
ws={ws}
party={party}
setParty={setParty}
/>
)}
</Stack.Screen>
<Stack.Screen
name="Restaurant"
component={RestaurantScreen}
options={(): object => ({
headerTitle: (): null => null,
})}
/>
<Stack.Screen
name="Share"
options={(): object => ({
headerTitle: (): null => null,
})}
>
{(props): React.ReactElement => (
<ShareScreen {...props} party={party} />
)}
</Stack.Screen>
</Stack.Navigator>
</NavigationContainer>
)
}
Example #22
Source File: about.tsx From beancount-mobile with MIT License | 4 votes |
About = connect( (state: AppState) => ({ authToken: state.base.authToken, locale: state.base.locale, currentTheme: state.base.currentTheme, userId: state.base.userId, }), (dispatch) => ({ logout(authToken: string): void { dispatch(actionLogout(authToken)); }, updateReduxState(payload: { base: { locale: string } }): void { dispatch(actionUpdateReduxState(payload)); }, }) )( ({ authToken, locale, logout, updateReduxState, currentTheme, userId, navigation, }: Props) => { const theme = useTheme().colorTheme; const { setLocale } = React.useContext(LocalizationContext); const pickerSource = [ { value: ReportStatus.WEEKLY, label: i18n.t("weekly") }, { value: ReportStatus.MONTHLY, label: i18n.t("monthly") }, { value: ReportStatus.OFF, label: i18n.t("off") }, ]; useEffect(() => { async function init() { await registerForPushNotificationAsync(); } init(); }, []); const [reportAnimateCount, setReportAnimateCount] = useState(0); const [subscriptionFlash, setSubscriptionFlash] = useState(false); const isFocused = useIsFocused(); React.useEffect(() => { async function init() { try { const value = await AsyncStorage.getItem("@SubscriptionFlash:key"); if (value !== null) { setSubscriptionFlash(value === "true"); } else { setSubscriptionFlash(false); } await AsyncStorage.setItem("@SubscriptionFlash:key", "false"); } catch (error) { console.error(`failed to get subscription flash value: ${error}`); } } init(); }, [isFocused]); useEffect(() => { if (subscriptionFlash) { const interval = setInterval(() => { if (reportAnimateCount < 5) { setReportAnimateCount(reportAnimateCount + 1); } }, 300); return () => clearInterval(interval); } setReportAnimateCount(0); return undefined; }, [subscriptionFlash, reportAnimateCount]); const { emailReportStatus } = useUserProfile(userId); const [reportStatus, setReportStatue] = useState<string>( emailReportStatus ? emailReportStatus.toString() : "" ); useEffect(() => { setReportStatue(emailReportStatus ? emailReportStatus.toString() : ""); }, [emailReportStatus]); const { error, mutate } = useUpdateReportSubscribeToRemote(); const getReportStatusLabel = (status: string) => { switch (status) { case ReportStatus.OFF: return i18n.t("off"); case ReportStatus.WEEKLY: return i18n.t("weekly"); case ReportStatus.MONTHLY: return i18n.t("monthly"); default: return i18n.t("off"); } }; const getReportStatusEnum = (status: string) => { switch (status) { case ReportStatus.OFF: return ReportStatus.OFF; case ReportStatus.WEEKLY: return ReportStatus.WEEKLY; case ReportStatus.MONTHLY: return ReportStatus.MONTHLY; default: return ReportStatus.OFF; } }; const renderAppSection = () => { const backgroundColor = { backgroundColor: theme.white, color: theme.text01, }; const { spendingReportSubscription } = useFeatureFlags(userId); return ( // @ts-ignore <List style={backgroundColor} renderHeader={<ListHeader>{i18n.t("about")}</ListHeader>} > <Item disabled extra={Platform.OS === "ios" ? "Apple Store" : "Google Play"} arrow="horizontal" style={backgroundColor} onPress={async () => { const storeUrl = Platform.OS === "ios" ? "https://apps.apple.com/us/app/id1527950512" : "https://play.google.com/store/apps/details?id=io.beancount.android"; if (storeUrl) { await WebBrowser.openBrowserAsync(storeUrl); await analytics.track("tap_review_app", { storeUrl }); } }} > {i18n.t("reviewApp")} </Item> {spendingReportSubscription && ( <Picker data={pickerSource} cols={1} extra={getReportStatusLabel(reportStatus)} onChange={async (value) => { const newValue = value ? String(value[0]) : ""; if (newValue === reportStatus) { return; } setReportStatue(newValue); const loadingKey = Toast.loading(i18n.t("updating")); await mutate({ variables: { userId, status: getReportStatusEnum(newValue) }, }); Portal.remove(loadingKey); if (!error) { Toast.success(i18n.t("updateSuccess")); } else { console.error("failed to update report status", error); Toast.fail(i18n.t("updateFailed")); } }} > <Item style={[ backgroundColor, { backgroundColor: reportAnimateCount % 2 === 1 ? theme.warning : theme.white, }, ]} arrow="horizontal" > {i18n.t("subscribe")} </Item> </Picker> )} <Item disabled style={backgroundColor} extra={ <Switch value={String(locale).startsWith("en")} onValueChange={async (value) => { const changeTo = value ? "en" : "zh"; updateReduxState({ base: { locale: changeTo }, }); i18n.locale = changeTo; setLocale(changeTo); await analytics.track("tap_switch_language", { changeTo }); }} /> } > {i18n.t("currentLanguage")} <Brief> {String(locale).startsWith("en") ? i18n.t("english") : i18n.t("chinese")} </Brief> </Item> <Item style={backgroundColor} disabled extra={ <Switch value={currentTheme === "dark"} onValueChange={async (value) => { const mode = value ? "dark" : "light"; updateReduxState({ base: { currentTheme: mode }, }); await analytics.track("tap_switch_theme", { mode }); }} /> } > {i18n.t("theme")} <Brief>{currentTheme === "dark" ? "Dark" : "Light"}</Brief> </Item> <Item style={backgroundColor} disabled extra={Constants.nativeAppVersion} > {i18n.t("currentVersion")} </Item> {authToken ? ( <Item style={backgroundColor} disabled onPress={() => { Alert.alert( "", i18n.t("logoutAlertMsg"), [ { text: i18n.t("logoutAlertCancel"), style: "cancel" }, { text: i18n.t("logoutAlertConfirm"), onPress: () => { logout(authToken); }, }, ], { cancelable: false } ); }} > {i18n.t("logout")} </Item> ) : ( <View /> )} </List> ); }; return ( <ScrollView style={{ backgroundColor: theme.white }}> <AccountHeader /> <InviteSection navigation={navigation} /> {renderAppSection()} </ScrollView> ); } )
Example #23
Source File: index.tsx From selftrace with MIT License | 4 votes |
function MapPage({ wellbeing }: Props) {
const [state, setState] = React.useState<State>({
clusters: [],
isLoading: false,
lastMapCenter: undefined,
lastMapZoom: undefined,
});
React.useEffect(() => {
(async function loadLastMapConfig() {
const [lastMapCenterRaw, lastMapZoomRaw] = await Promise.all([
AsyncStorage.getItem('lastMapCenter'),
AsyncStorage.getItem('lastMapZoom'),
]);
if (lastMapCenterRaw || lastMapZoomRaw) {
setState(prev => {
const newState: State = { ...prev };
if (lastMapCenterRaw !== null) {
newState.lastMapCenter = JSON.parse(lastMapCenterRaw);
}
if (lastMapZoomRaw !== null) {
newState.lastMapZoom = Number(lastMapZoomRaw);
}
return newState;
});
}
})();
}, []);
// TODO: The "delaying" logic should probably lie outside of the component
async function handleRegionChange({ region, zoom }: { region: Geo.Region; zoom: number }) {
const requestStartedAt = Date.now();
let requestEndedAt = requestStartedAt;
setState(prevState => ({
...prevState,
clusters: [],
isLoading: true,
}));
let newClusters: ClusterObject[] = [];
const center: Geo.LocationShort = {
lat: region.latitude,
lng: region.longitude,
};
try {
[, , newClusters] = await Promise.all([
AsyncStorage.setItem('lastMapCenter', JSON.stringify(center)),
AsyncStorage.setItem('lastMapZoom', zoom.toString()),
API.requestClusters(region),
]);
requestEndedAt = Date.now();
} catch (err) {
requestEndedAt = Date.now();
} finally {
const executionTime = requestEndedAt - requestStartedAt;
const endRequest = () =>
setState(prev => ({
...prev,
clusters: newClusters.map(cluster => ({
key: ReactUtils.generateListKey(),
data: cluster,
})),
isLoading: false,
}));
if (executionTime < MIN_EXECUTION_TIME) {
setTimeout(endRequest, MIN_EXECUTION_TIME - executionTime);
} else {
endRequest();
}
}
}
const wellbeingIsDefined = !!wellbeing;
return (
<PageContainer isFullScreen isProtected>
{wellbeingIsDefined ? (
<CoronaMap
center={state.lastMapCenter}
zoom={state.lastMapZoom}
clusters={state.clusters}
isLoading={state.isLoading}
onRegionChangeComplete={handleRegionChange}
style={styles.mapContainer}
/>
) : (
<>
<CoronaMap clusters={[]} isLoading={false} style={styles.mapContainer} />
<BlurView
tint="dark"
intensity={75}
style={[StyleSheet.absoluteFill, { justifyContent: 'center', alignItems: 'center' }]}>
<View style={styles.warningContainer}>
<Icon.Lock color="white" style={styles.lockIcon} />
<Text style={styles.warningTitle}>{t('screens.map.chooseWellbeingTitle')}</Text>
<Text style={styles.warningMessage}>{t('screens.map.chooseWellbeingMessage')}</Text>
</View>
</BlurView>
</>
)}
</PageContainer>
);
}