Skip to content

Commit

Permalink
fix: dtis 260 session manage (#449)
Browse files Browse the repository at this point in the history
* fix: merge develop

* fix: remove comment

* fix: using locker as a page

* fix: remove old lock modal

* feat: set max value for z-index

* feat: refactor

* feat: add useActivityTimer hook for locking the app

* fix: remove comment

* fix: render app just on initialized

* fix: render app on reload

* fix: process.env.NODE_ENV warning and create/refactor LoadingPage
  • Loading branch information
jimcase committed May 7, 2024
1 parent e17deae commit 0aa7c3c
Show file tree
Hide file tree
Showing 22 changed files with 544 additions and 416 deletions.
6 changes: 4 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
"env": {
"browser": true,
"es2021": true,
"jest": true
"jest": true,
"node": true
},
"globals": {
"__dirname": true,
"NodeJS": true
"NodeJS": true,
"process": "readonly"
},
"extends": [
"eslint:recommended",
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@capacitor-community/barcode-scanner": "^4.0.1",
"@capacitor-community/sqlite": "^5.5.0",
"@capacitor/android": "^5.0.0",
"@capacitor/app": "^5.0.7",
"@capacitor/clipboard": "^5.0.0",
"@capacitor/core": "^5.0.0",
"@capacitor/ios": "^5.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src/core/agent/services/connectionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
ConnectionNoteStorage,
ConnectionRecord,
CredentialStorage,
ConnectionStorage } from "../records";
ConnectionStorage,
} from "../records";
import { PreferencesKeys, PreferencesStorage } from "../../storage";
import { waitAndGetDoneOp } from "./utils";
import { ConnectionHistoryType, KeriaContact } from "./connection.types";
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@
}
]
},
"lockmodal": {
"lockpage": {
"title": "Welcome back",
"description": "Please enter your passcode to login",
"error": "Incorrect passcode",
Expand Down
10 changes: 4 additions & 6 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import React, { useEffect, useState } from "react";
import React, { useEffect } from "react";
import { IonReactRouter } from "@ionic/react-router";
import { IonRouterOutlet, IonSpinner } from "@ionic/react";
import { Redirect, Route, useLocation } from "react-router-dom";
import { IonRouterOutlet } from "@ionic/react";
import { Redirect, Route } from "react-router-dom";
import { Onboarding } from "../ui/pages/Onboarding";
import { GenerateSeedPhrase } from "../ui/pages/GenerateSeedPhrase";
import { SetPasscode } from "../ui/pages/SetPasscode";
import { VerifySeedPhrase } from "../ui/pages/VerifySeedPhrase";
import { CreatePassword } from "../ui/pages/CreatePassword";
import { useAppDispatch, useAppSelector } from "../store/hooks";
import {
getAuthentication,
getRoutes,
getStateCache,
setCurrentRoute,
} from "../store/reducers/stateCache";
import { getNextRoute } from "./nextRoute";
import { TabsMenu, tabsRoutes } from "../ui/components/navigation/TabsMenu";
import { PublicRoutes, RoutePath } from "./paths";
import { RoutePath } from "./paths";
import { IdentifierDetails } from "../ui/pages/IdentifierDetails";
import { CredentialDetails } from "../ui/pages/CredentialDetails";
import { ConnectionDetails } from "../ui/pages/ConnectionDetails";
import { LockModal } from "../ui/components/LockModal";

const Routes = () => {
const stateCache = useAppSelector(getStateCache);
Expand Down
14 changes: 2 additions & 12 deletions src/routes/nextRoute/nextRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,13 @@ import { RoutePath, TabsRoutePath } from "../paths";
import { ToastMsgType } from "../../ui/globals/types";

const getNextRootRoute = (store: StoreState) => {
const isInitialized = store.stateCache.initialized;
const authentication = store.stateCache.authentication;
const routes = store.stateCache.routes;
const initialRoute =
routes.some((route) => route.path === "/") || routes.length === 0;

let path;
if (routes.length === 1 && !isInitialized) {
path = RoutePath.ONBOARDING;
} else if (authentication.passcodeIsSet && authentication.seedPhraseIsSet) {
if (authentication.passcodeIsSet && authentication.seedPhraseIsSet) {
path = RoutePath.TABS_MENU;
} else {
if (initialRoute) {
path = RoutePath.ONBOARDING;
} else {
path = routes[0].path;
}
path = RoutePath.ONBOARDING;
}

return { pathname: path };
Expand Down
28 changes: 13 additions & 15 deletions src/ui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getAuthentication,
getCurrentOperation,
getCurrentRoute,
getStateCache,
getToastMsg,
} from "../store/reducers/stateCache";
import { useAppSelector } from "../store/hooks";
Expand All @@ -27,19 +28,20 @@ import { SetUserName } from "./components/SetUserName";
import { TabsRoutePath } from "../routes/paths";
import { MobileHeaderPreview } from "./components/MobileHeaderPreview";
import { CustomToast } from "./components/CustomToast/CustomToast";
import { LockModal } from "./components/LockModal";
import { LockPage } from "./pages/LockPage/LockPage";
import { LoadingPage } from "./pages/LoadingPage/LoadingPage";

setupIonicReact();

const App = () => {
const stateCache = useAppSelector(getStateCache);
const authentication = useAppSelector(getAuthentication);
const currentRoute = useAppSelector(getCurrentRoute);
const [showSetUserName, setShowSetUserName] = useState(false);
const currentOperation = useAppSelector(getCurrentOperation);
const toastMsg = useAppSelector(getToastMsg);
const [showScan, setShowScan] = useState(false);
const [showToast, setShowToast] = useState(false);
const [lockIsRendered, setLockIsRendered] = useState(false);

const isPreviewMode = useMemo(
() => new URLSearchParams(window.location.search).has("browserPreview"),
Expand Down Expand Up @@ -93,17 +95,7 @@ const App = () => {
}, []);

const renderApp = () => {
if (!lockIsRendered) {
// We need to include the LockModal in the loading page to track when is rendered
return (
<>
<LockModal didEnter={() => setLockIsRendered(true)} />
<div className="loading-page">
<IonSpinner name="crescent" />
</div>
</>
);
} else if (showScan) {
if (showScan) {
return <FullPageScanner setShowScan={setShowScan} />;
} else {
return (
Expand All @@ -119,8 +111,14 @@ const App = () => {
<IonApp>
<AppWrapper>
<StrictMode>
{lockIsRendered && !authentication.loggedIn ? <LockModal /> : null}
{renderApp()}
{stateCache.initialized ? (
<>
{renderApp()}
{!authentication.loggedIn ? <LockPage /> : null}
</>
) : (
<LoadingPage />
)}
<SetUserName
isOpen={showSetUserName}
setIsOpen={setShowSetUserName}
Expand Down
141 changes: 69 additions & 72 deletions src/ui/components/AppWrapper/AppWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ReactNode, useEffect, useState } from "react";
import { useAppDispatch, useAppSelector } from "../../../store/hooks";
import {
getAuthentication,
logout,
setAuthentication,
setCurrentOperation,
setInitialized,
Expand Down Expand Up @@ -43,6 +42,8 @@ import { CredentialStatus } from "../../../core/agent/services/credentialService
import { FavouriteIdentifier } from "../../../store/reducers/identifiersCache/identifiersCache.types";
import "./AppWrapper.scss";
import { ConfigurationService } from "../../../core/configuration";
import { PreferencesStorageItem } from "../../../core/storage/preferences/preferencesStorage.type";
import { useActivityTimer } from "./hooks/useActivityTimer";
import { setWalletConnectionsCache } from "../../../store/reducers/walletConnectionsCache";
import { walletConnectionsFix } from "../../__fixtures__/walletConnectionsFix";

Expand Down Expand Up @@ -111,40 +112,7 @@ const AppWrapper = (props: { children: ReactNode }) => {
const dispatch = useAppDispatch();
const authentication = useAppSelector(getAuthentication);
const [agentInitErr, setAgentInitErr] = useState(false);

const ACTIVITY_TIMEOUT = 60000;
let timer: NodeJS.Timeout;

useEffect(() => {
const handleActivity = () => {
clearTimeout(timer);
timer = setTimeout(() => {
dispatch(logout());
}, ACTIVITY_TIMEOUT);
};

// TODO: detect appStateChange in android and ios to reduce the ACTIVITY_TIMEOUT
// App.addListener("appStateChange", handleAppStateChange);
window.addEventListener("load", handleActivity);
document.addEventListener("mousemove", handleActivity);
document.addEventListener("touchstart", handleActivity);
document.addEventListener("touchmove", handleActivity);
document.addEventListener("click", handleActivity);
document.addEventListener("focus", handleActivity);
document.addEventListener("keydown", handleActivity);
document.addEventListener("scroll", handleActivity);

return () => {
window.removeEventListener("load", handleActivity);
document.removeEventListener("mousemove", handleActivity);
document.removeEventListener("touchstart", handleActivity);
document.removeEventListener("touchmove", handleActivity);
document.removeEventListener("click", handleActivity);
document.removeEventListener("focus", handleActivity);
document.removeEventListener("keydown", handleActivity);
clearTimeout(timer);
};
}, []);
useActivityTimer();

useEffect(() => {
initApp();
Expand Down Expand Up @@ -173,48 +141,80 @@ const AppWrapper = (props: { children: ReactNode }) => {
};

const loadPreferences = async () => {
const getPreferenceSafe = async (key: string) => {
try {
return await PreferencesStorage.get(key);
} catch (e) {
// TODO: handle error
}
};
const userName = await getPreferenceSafe(PreferencesKeys.APP_USER_NAME);

let userName: PreferencesStorageItem = { userName: "" };
const passcodeIsSet = await checkKeyStore(KeyStoreKeys.APP_PASSCODE);
const seedPhraseIsSet = await checkKeyStore(
KeyStoreKeys.IDENTITY_ROOT_XPRV_KEY
);
const passwordIsSet = await checkKeyStore(KeyStoreKeys.APP_OP_PASSWORD);

const updatedAuthentication = {
...authentication,
loggedIn: false,
userName: userName?.userName as string,
passcodeIsSet,
seedPhraseIsSet,
passwordIsSet,
};
try {
const identifiersFavourites = await PreferencesStorage.get(
PreferencesKeys.APP_IDENTIFIERS_FAVOURITES
);
dispatch(
setFavouritesIdentifiersCache(
identifiersFavourites.favourites as FavouriteIdentifier[]
)
);
} catch (e) {
if (
!(e instanceof Error) ||
!(
e instanceof Error &&
e.message ===
`${PreferencesStorage.KEY_NOT_FOUND} ${PreferencesKeys.APP_IDENTIFIERS_FAVOURITES}`
)
) {
throw e;
}
}

dispatch(setAuthentication(updatedAuthentication));
try {
const credsFavourites = await PreferencesStorage.get(
PreferencesKeys.APP_CREDS_FAVOURITES
);
dispatch(
setFavouritesCredsCache(
credsFavourites.favourites as FavouriteIdentifier[]
)
);
} catch (e) {
if (
!(e instanceof Error) ||
!(
e instanceof Error &&
e.message ===
`${PreferencesStorage.KEY_NOT_FOUND} ${PreferencesKeys.APP_CREDS_FAVOURITES}`
)
) {
throw e;
}
}

const identifiersFavourites = await getPreferenceSafe(
PreferencesKeys.APP_IDENTIFIERS_FAVOURITES
);
dispatch(
setFavouritesIdentifiersCache(
identifiersFavourites?.favourites as FavouriteIdentifier[]
)
);
try {
userName = await PreferencesStorage.get(PreferencesKeys.APP_USER_NAME);
} catch (e) {
if (
!(e instanceof Error) ||
!(
e instanceof Error &&
e.message ===
`${PreferencesStorage.KEY_NOT_FOUND} ${PreferencesKeys.APP_USER_NAME}`
)
) {
throw e;
}
}

const credsFavourites = await getPreferenceSafe(
PreferencesKeys.APP_CREDS_FAVOURITES
);
dispatch(
setFavouritesCredsCache(
credsFavourites?.favourites as FavouriteIdentifier[]
)
setAuthentication({
...authentication,
userName: userName.userName as string,
passcodeIsSet,
seedPhraseIsSet,
passwordIsSet,
})
);
};

Expand All @@ -226,7 +226,6 @@ const AppWrapper = (props: { children: ReactNode }) => {
isInitialized = await PreferencesStorage.get(
PreferencesKeys.APP_ALREADY_INIT
);
dispatch(setInitialized(isInitialized?.initialized as boolean));
} catch (e) {
await SecureStorage.delete(KeyStoreKeys.APP_PASSCODE);
await SecureStorage.delete(KeyStoreKeys.IDENTITY_ENTROPY);
Expand All @@ -250,9 +249,8 @@ const AppWrapper = (props: { children: ReactNode }) => {
}
dispatch(setPauseQueueIncomingRequest(true));

await loadDatabase().catch((e) => {
/* TODO: handle error */
});
await loadDatabase();
dispatch(setInitialized(isInitialized?.initialized as boolean));

Agent.agent.connections.onConnectionStateChanged((event) => {
return connectionStateChangedHandler(event, dispatch);
Expand Down Expand Up @@ -292,7 +290,6 @@ const AppWrapper = (props: { children: ReactNode }) => {
// @TODO - foconnor: We should allow the app to load and give more accurate feedback - this is a temp solution.
// Hence this isn't in i18n.
if (agentInitErr) {
//if (false) {
return (
<div className="agent-init-error-msg">
<p>
Expand Down

0 comments on commit 0aa7c3c

Please sign in to comment.