diff --git a/package-lock.json b/package-lock.json index e4ef706..8898fcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,6 +59,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "expo-dev-client": "^4.0.20", "prettier": "^3.3.3", "typescript": "~5.3.3" } @@ -10703,6 +10704,106 @@ "expo": "*" } }, + "node_modules/expo-dev-client": { + "version": "4.0.20", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-4.0.20.tgz", + "integrity": "sha512-lSr5PoJSqXD2srzWyPY3sb8kcwRaLWNCVemdQryW796tglm6sTnSbRhmUGtUPvrm6Bk+rZAmQNFsqKh1sjHfqg==", + "dev": true, + "dependencies": { + "expo-dev-launcher": "4.0.22", + "expo-dev-menu": "5.0.16", + "expo-dev-menu-interface": "1.8.3", + "expo-manifests": "~0.14.0", + "expo-updates-interface": "~0.16.2" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher": { + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-4.0.22.tgz", + "integrity": "sha512-U8SR4MphP+QatjmD+sQ7AWtKwy7faPpW2PcaPBPnfzBiDc3yk8Kc2sf6/JyN7bUmvA6PFqTnsSJMlZEWi917OQ==", + "dev": true, + "dependencies": { + "ajv": "8.11.0", + "expo-dev-menu": "5.0.16", + "expo-manifests": "~0.14.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-launcher/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/expo-dev-launcher/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/expo-dev-launcher/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-dev-menu": { + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-5.0.16.tgz", + "integrity": "sha512-zsUiVCvVWT9ve5EsYEGHGu0dJac13NoEQkmzOjhmvcQXb7+OnKgwtBiNAX6rvponfnx9il506rnyZ+0M9CbwYQ==", + "dev": true, + "dependencies": { + "expo-dev-menu-interface": "1.8.3", + "semver": "^7.5.4" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu-interface": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-1.8.3.tgz", + "integrity": "sha512-QM0LRozeFT5Ek0N7XpV93M+HMdEKRLEOXn0aW5M3uoUlnqC1+PLtF3HMy3k3hMKTTE/kJ1y1Z7akH07T0lunCQ==", + "dev": true, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-dev-menu/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/expo-font": { "version": "12.0.9", "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-12.0.9.tgz", @@ -10714,6 +10815,12 @@ "expo": "*" } }, + "node_modules/expo-json-utils": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.13.1.tgz", + "integrity": "sha512-mlfaSArGVb+oJmUcR22jEONlgPp0wj4iNIHfQ2je9Q8WTOqMc0Ws9tUciz3JdJnhffdHqo/k8fpvf0IRmN5HPA==", + "dev": true + }, "node_modules/expo-keep-awake": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-13.0.2.tgz", @@ -10723,6 +10830,19 @@ "expo": "*" } }, + "node_modules/expo-manifests": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.14.3.tgz", + "integrity": "sha512-L3b5/qocBPiQjbW0cpOHfnqdKZbTJS7sA3mgeDJT+mWga/xYsdpma1EfNmsuvrOzjLGjStr1k1fceM9Bl49aqQ==", + "dev": true, + "dependencies": { + "@expo/config": "~9.0.0", + "expo-json-utils": "~0.13.0" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.11.1.tgz", @@ -10849,6 +10969,15 @@ "integrity": "sha512-/t3xdbS8KB0prj5KG5w7z+wZPFlPtkgs95BsmrP/E7Q0xHXTcDcQ6Cu2FkFuRM+PKTb17cJDnLkawyS5vDLxMA==", "license": "MIT" }, + "node_modules/expo-updates-interface": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-0.16.2.tgz", + "integrity": "sha512-929XBU70q5ELxkKADj1xL0UIm3HvhYhNAOZv5DSk7rrKvLo7QDdPyl+JVnwZm9LrkNbH4wuE2rLoKu1KMgZ+9A==", + "dev": true, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo/node_modules/expo-file-system": { "version": "17.0.1", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-17.0.1.tgz", diff --git a/package.json b/package.json index 9ad9557..88cc00d 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "expo-dev-client": "^4.0.20", "prettier": "^3.3.3", "typescript": "~5.3.3" } diff --git a/src/App.tsx b/src/App.tsx index b9f7ecc..cb156cf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; -import Dusken from './Dusken'; +import AppInner from './AppInner'; import { useDeepLinking } from './hooks'; import { store, persistor } from './reduxStore'; import { loadTheme } from './theme'; @@ -31,7 +31,7 @@ export default function App() { urlScheme={Constants.expoConfig?.scheme as string} merchantIdentifier="merchant.no.neuf.chateau" // https://developer.apple.com/account/resources/identifiers/list/merchant > - + diff --git a/src/AppInner.tsx b/src/AppInner.tsx new file mode 100644 index 0000000..5f90a87 --- /dev/null +++ b/src/AppInner.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +import Navigation from './Navigation'; +import { useLogoutUsersWithNoToken } from './hooks'; + +const AppInner = () => { + useLogoutUsersWithNoToken(); + + return ; +}; + +export default AppInner; diff --git a/src/Dusken.tsx b/src/Dusken.tsx deleted file mode 100644 index 72caab4..0000000 --- a/src/Dusken.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React, { useEffect } from 'react'; - -import Navigation from './Navigation'; -import { logout } from './actions'; -import { useAppDispatch, useAppSelector } from './hooks'; - -const Dusken = () => { - const user = useAppSelector((store) => store.user); - const userToken = useAppSelector((store) => store.userToken); - const dispatch = useAppDispatch(); - - useEffect(() => { - // logout authenticated users without token - if (user && !userToken) { - dispatch(logout()); - } - }); - - return ; -}; - -export default Dusken; diff --git a/src/hooks.tsx b/src/hooks.tsx index 479c9e0..8892dff 100644 --- a/src/hooks.tsx +++ b/src/hooks.tsx @@ -4,6 +4,7 @@ import { Linking } from 'react-native'; import type { TypedUseSelectorHook } from 'react-redux'; import { useDispatch, useSelector, useStore } from 'react-redux'; +import { logout } from './actions'; import type { AppDispatch, AppStore, RootState } from './reduxStore'; export function usePrevious(value: T): T | undefined { @@ -55,3 +56,16 @@ export const useDeepLinking = () => { export const useAppDispatch: () => AppDispatch = useDispatch; export const useAppSelector: TypedUseSelectorHook = useSelector; export const useAppStore: () => AppStore = useStore; + +/** Logout authenticated users without token */ +export function useLogoutUsersWithNoToken() { + const user = useAppSelector((store) => store.user); + const userToken = useAppSelector((store) => store.userToken); + const dispatch = useAppDispatch(); + + useEffect(() => { + if (user && !userToken) { + dispatch(logout()); + } + }); +} diff --git a/src/reducers.ts b/src/reducers.ts index 2471717..9f53614 100644 --- a/src/reducers.ts +++ b/src/reducers.ts @@ -47,7 +47,7 @@ function formatErrors(errs: Record) { // FIXME: refactor using redux slices // eslint-disable-next-line @typescript-eslint/default-param-last, @typescript-eslint/no-explicit-any -export default function duskenApp(state = initialState, action: any) { +export default function appReducers(state = initialState, action: any) { switch (action.type) { /* Login */ case LOGIN_REQUEST: