From 3736acbe70ff7ced22cba957e1cdb16eb359867f Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Wed, 22 May 2024 16:59:16 +0200 Subject: [PATCH] Add option to auto-open last example in the example app (#2918) ## Description Adds option to automatically open the last viewed example when opening (or reloading) the example app. https://github.com/software-mansion/react-native-gesture-handler/assets/21055725/2977ac8b-dcea-49b8-a8db-228afd75dcc7 ## Test plan Check if the last viewed example gets auto-opened when the option is enabled --- example/App.tsx | 84 ++++++++++++++++++++++++++++++++++++++++++-- example/package.json | 1 + example/yarn.lock | 19 ++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/example/App.tsx b/example/App.tsx index 376256ee73..b11d825a9f 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { Text, View, @@ -10,13 +10,16 @@ import { } from 'react-native'; import { createStackNavigator, + StackNavigationProp, StackScreenProps, } from '@react-navigation/stack'; import { NavigationContainer, ParamListBase } from '@react-navigation/native'; import { GestureHandlerRootView, RectButton, + Switch, } from 'react-native-gesture-handler'; +import AsyncStorage from '@react-native-async-storage/async-storage'; import OverflowParent from './src/release_tests/overflowParent'; import DoublePinchRotate from './src/release_tests/doubleScalePinchAndRotate'; import DoubleDraggable from './src/release_tests/doubleDraggable'; @@ -169,6 +172,9 @@ const EXAMPLES: ExamplesSection[] = [ }, ]; +const OPEN_LAST_EXAMPLE_KEY = 'openLastExample'; +const LAST_EXAMPLE_KEY = 'lastExample'; + type RootStackParamList = { Home: undefined; TouchableExample: { item: string }; @@ -215,17 +221,38 @@ export default function App() { ); } +function navigate( + navigation: StackNavigationProp, + dest: string +) { + AsyncStorage.setItem(LAST_EXAMPLE_KEY, dest); + navigation.navigate(dest); +} + function MainScreen({ navigation }: StackScreenProps) { + useEffect(() => { + AsyncStorage.multiGet([OPEN_LAST_EXAMPLE_KEY, LAST_EXAMPLE_KEY]).then( + ([openLastExample, lastExample]) => { + if (openLastExample[1] === 'true' && lastExample[1]) { + navigate(navigation, lastExample[1]); + } + } + ); + // we only want to run this effect once + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ( example.name} + ListHeaderComponent={OpenLastExampleSetting} renderItem={({ item }) => ( navigation.navigate(name)} + onPressItem={(name) => navigate(navigation, name)} /> )} renderSectionHeader={({ section: { sectionTitle } }) => ( @@ -237,6 +264,41 @@ function MainScreen({ navigation }: StackScreenProps) { ); } +function OpenLastExampleSetting() { + const [openLastExample, setOpenLastExample] = React.useState(false); + + useEffect(() => { + AsyncStorage.getItem(OPEN_LAST_EXAMPLE_KEY).then((value) => { + setOpenLastExample(value === 'true'); + }); + }, []); + + function updateSetting(value: boolean) { + AsyncStorage.setItem(OPEN_LAST_EXAMPLE_KEY, value.toString()); + setOpenLastExample(value); + } + + return ( + { + updateSetting(!openLastExample); + }}> + + Open last example on launch + { + updateSetting(!openLastExample); + }} + /> + + + ); +} + interface MainScreenItemProps { name: string; onPressItem: (name: string) => void; @@ -277,8 +339,24 @@ const styles = StyleSheet.create({ flex: 1, height: 50, padding: 10, + backgroundColor: '#fff', + }, + buttonContent: { + flex: 1, flexDirection: 'row', alignItems: 'center', - backgroundColor: '#fff', + justifyContent: 'space-between', + }, + autoOpenSetting: { + margin: 16, + borderRadius: 16, + backgroundColor: '#eef0ff', + paddingHorizontal: 16, + justifyContent: 'space-between', + elevation: 8, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.25, + shadowRadius: 3.84, }, }); diff --git a/example/package.json b/example/package.json index 48d6d9a83a..053aa19c7a 100644 --- a/example/package.json +++ b/example/package.json @@ -16,6 +16,7 @@ "dependencies": { "@expo/metro-config": "~0.18.1", "@expo/metro-runtime": "^3.2.1", + "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-community/slider": "^4.5.2", "@react-native-community/viewpager": "^5.0.11", "@react-native-masked-view/masked-view": "^0.2.8", diff --git a/example/yarn.lock b/example/yarn.lock index 7397127985..d0a1f3218d 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -1565,6 +1565,13 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@react-native-async-storage/async-storage@^1.23.1": + version "1.23.1" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz#cad3cd4fab7dacfe9838dce6ecb352f79150c883" + integrity sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA== + dependencies: + merge-options "^3.0.4" + "@react-native-community/cli-clean@13.6.6": version "13.6.6" resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-13.6.6.tgz#87c7ad8746c38dab0fe7b3c6ff89d44351d5d943" @@ -4971,6 +4978,11 @@ is-path-inside@^3.0.2: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -5951,6 +5963,13 @@ memory-cache@~0.2.0: resolved "https://registry.yarnpkg.com/memory-cache/-/memory-cache-0.2.0.tgz#7890b01d52c00c8ebc9d533e1f8eb17e3034871a" integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"