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: