From 96966eb7daca3b7960bfb511abc11e341ac07082 Mon Sep 17 00:00:00 2001 From: OWK50GA Date: Sun, 22 Dec 2024 17:27:15 +0100 Subject: [PATCH 1/2] customized lock time --- .vscode/settings.json | 2 + .../CRX/background/services/VaultService.ts | 1 + .../app/src/systems/CRX/utils/lockTimer.ts | 31 +++++ packages/app/src/systems/CRX/utils/secret.ts | 12 +- packages/app/src/systems/Core/types.ts | 1 + .../pages/LockTimeout/LockTimeout.stories.tsx | 52 +++++++++ .../pages/LockTimeout/LockTimeout.tsx | 107 ++++++++++++++++++ .../Settings/pages/LockTimeout/index.tsx | 1 + .../app/src/systems/Settings/pages/index.ts | 1 + packages/app/src/systems/Settings/routes.tsx | 4 +- .../systems/Sidebar/constants/sidebarItems.ts | 7 ++ 11 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 packages/app/src/systems/CRX/utils/lockTimer.ts create mode 100644 packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.stories.tsx create mode 100644 packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.tsx create mode 100644 packages/app/src/systems/Settings/pages/LockTimeout/index.tsx diff --git a/.vscode/settings.json b/.vscode/settings.json index 112501c36..57aa69f07 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,4 +15,6 @@ "typescript.suggest.paths": true, "typescript.suggest.enabled": true, "typescript.suggest.completeFunctionCalls": true, + }, + "typescript.tsdk": "node_modules/typescript/lib" } diff --git a/packages/app/src/systems/CRX/background/services/VaultService.ts b/packages/app/src/systems/CRX/background/services/VaultService.ts index e8530c5d2..959cf81e8 100644 --- a/packages/app/src/systems/CRX/background/services/VaultService.ts +++ b/packages/app/src/systems/CRX/background/services/VaultService.ts @@ -6,6 +6,7 @@ import { import type { DatabaseRestartEvent, RequestMessage } from '@fuel-wallet/types'; import { AUTO_LOCK_IN_MINUTES } from '~/config'; import { VaultServer } from '~/systems/Vault/services/VaultServer'; +import lockTimer from '../../utils/lockTimer'; import { clearSession, diff --git a/packages/app/src/systems/CRX/utils/lockTimer.ts b/packages/app/src/systems/CRX/utils/lockTimer.ts new file mode 100644 index 000000000..a9dd2ebe8 --- /dev/null +++ b/packages/app/src/systems/CRX/utils/lockTimer.ts @@ -0,0 +1,31 @@ +// 5, 30, 2 hours, 6 hours, 12 hours, never. + +type TimerDurations = 5 | 30 | 120 | 360 | 720; // Allowed duration in minutes. + +class LockerTimer { + private duration: TimerDurations | null = null; + + constructor(duration: number) { + this.validateDuration(duration); + } + + private validateDuration(duration: number) { + const validDurations: TimerDurations[] = [5, 30, 120, 360, 720]; + if (!validDurations.includes(duration as TimerDurations)) { + throw new Error( + `Invalid Timer duration. Valid durations are ${validDurations.join(', ')} minutes.` + ); + } + this.duration = duration as TimerDurations; + } + + public getDuration(): number { + return this?.duration as number; + } + + public setDuration(duration: number) { + this.validateDuration(duration); + } +} + +export default new LockerTimer(5); diff --git a/packages/app/src/systems/CRX/utils/secret.ts b/packages/app/src/systems/CRX/utils/secret.ts index c078ea214..d058141d8 100644 --- a/packages/app/src/systems/CRX/utils/secret.ts +++ b/packages/app/src/systems/CRX/utils/secret.ts @@ -1,5 +1,6 @@ import dayjs from 'dayjs'; import { decrypt, encrypt } from 'fuels'; +import { AUTO_LOCK_IN_MINUTES } from '~/config'; const SALT_KEY = 'salt'; @@ -31,14 +32,21 @@ export async function resetTimer() { }); } +export async function saveLockTimeSetting(minutes: number) { + await chrome.storage.local.set({ userLockTime: minutes }); +} + export async function saveSecret(secret: string, autoLockInMinutes: number) { const salt = await createSalt(); try { + const { userLockTime } = await chrome.storage.local.get('userLockTime'); + const effectiveLockTime = userLockTime || autoLockInMinutes; + const encrypted = await encrypt(salt, secret); chrome.storage.session.set({ data: encrypted, - lockTime: autoLockInMinutes, - timer: dayjs().add(autoLockInMinutes, 'minute').valueOf(), + lockTime: effectiveLockTime, + timer: dayjs().add(effectiveLockTime, 'minute').valueOf(), }); } catch { clearSession(); diff --git a/packages/app/src/systems/Core/types.ts b/packages/app/src/systems/Core/types.ts index 01b0a3d97..5084b9dfa 100644 --- a/packages/app/src/systems/Core/types.ts +++ b/packages/app/src/systems/Core/types.ts @@ -35,6 +35,7 @@ export const Pages = { settings: route('/settings'), settingsChangePassword: route('/settings/change-password'), settingsConnectedApps: route('/settings/connected-apps'), + settingsSetLockTimeout: route('/settings/set-lock'), // added send: route('/send'), sendConfirm: route('/send/confirm'), accounts: route('/accounts'), diff --git a/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.stories.tsx b/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.stories.tsx new file mode 100644 index 000000000..ae1ae70e9 --- /dev/null +++ b/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.stories.tsx @@ -0,0 +1,52 @@ +// import { LockTimeout } from "./LockTimeout"; +// import { Meta, Story } from '@storybook/react'; + +// export default { +// component: LockTimeout, +// title: 'Settings/Pages/4. LockTimeout', +// parameters: { +// viewport: { +// defaultViewport: 'chromeExtension', +// }, +// }, +// // loaders: [ +// // async () => { +// // // await AccountService.clearAccounts(); +// // // await AccountService.addAccount({ data: MOCK_ACCOUNTS[0] }); +// // return {}; +// // }, +// // ], +// } as Meta; + +// const Template: Story = (args) => ; + +import type { Meta, Story } from '@storybook/react'; +// LockTimer.stories.tsx +import React from 'react'; +import { LockTimeout } from './LockTimeout'; // Import the LockTimer component + +export default { + title: 'Components/LockTimer', // Storybook category and name + component: LockTimeout, // The component being showcased +} as Meta; + +const Template: Story = (args) => ; // Template for stories + +// Default state: Displays a list of lock times +export const Default = Template.bind({}); +Default.args = { + availableTimes: ['5 minutes', '10 minutes', '30 minutes', '1 hour'], +}; + +// Empty state: No lock times available +export const Empty = Template.bind({}); +Empty.args = { + availableTimes: [], +}; + +// Error state: Error loading times +export const ErrorState = Template.bind({}); +ErrorState.args = { + availableTimes: [], + error: 'Failed to load available lock times.', +}; diff --git a/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.tsx b/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.tsx new file mode 100644 index 000000000..c514d0ab4 --- /dev/null +++ b/packages/app/src/systems/Settings/pages/LockTimeout/LockTimeout.tsx @@ -0,0 +1,107 @@ +import { Box, VStack } from '@fuel-ui/react'; +import dayjs from 'dayjs'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { saveLockTimeSetting } from '~/systems/CRX/utils'; +import { Layout } from '~/systems/Core'; +import { Pages } from '~/systems/Core'; + +const availableTime = [ + '5 minutes', + '30 minutes', + '2 hours', + '6 hours', + '12 hours', + 'Never', +]; +export function LockTimeout() { + const navigate = useNavigate(); + const goBack = () => navigate(Pages.wallet()); + const [selectedTime, setSelectedTime] = useState( + availableTime[0] + ); + + const handleSelectTime = async (time: string) => { + setSelectedTime(time); + if (selectedTime === 'Never') { + await saveLockTimeSetting(Number.MAX_SAFE_INTEGER); + } + if (!selectedTime) return; + const timeValue = Number.parseInt(selectedTime); + + try { + await saveLockTimeSetting(timeValue); + + const { data } = await chrome.storage.session.get('data'); + if (data) { + await chrome.storage.session.set({ + timer: dayjs().add(timeValue, 'minute').valueOf(), + }); + } + } catch (err) { + console.error(err); + } + }; + + return ( + + + + + {availableTime.map((time) => { + return ( + handleSelectTime(time)} + > + {time} + {time === selectedTime && ( + ✔️ + )} + + ); + })} + + + + ); +} + +const cssObj: { [key: string]: React.CSSProperties } = { + container: { + fontFamily: 'Arial, sans-serif', + padding: '20px', + maxWidth: '400px', + margin: 'auto', + border: '1px solid #ddd', + borderRadius: '8px', + boxShadow: '0 2px 4px rgba(0,0,0,0.1)', + }, + title: { + textAlign: 'center', + marginBottom: '20px', + fontSize: '1.5rem', + color: '#333', + }, + list: { + listStyle: 'none', + padding: 0, + margin: 0, + }, + listItem: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '10px 10px', + margin: '5px 0', + borderRadius: '4px', + cursor: 'pointer', + transition: 'background-color 0.2s', + }, + checkMark: { + color: 'white', + fontWeight: 'bold', + borderRadius: '50%', + }, +}; diff --git a/packages/app/src/systems/Settings/pages/LockTimeout/index.tsx b/packages/app/src/systems/Settings/pages/LockTimeout/index.tsx new file mode 100644 index 000000000..79df6c39d --- /dev/null +++ b/packages/app/src/systems/Settings/pages/LockTimeout/index.tsx @@ -0,0 +1 @@ +export * from './LockTimeout'; diff --git a/packages/app/src/systems/Settings/pages/index.ts b/packages/app/src/systems/Settings/pages/index.ts index 759891c07..9cebe024d 100644 --- a/packages/app/src/systems/Settings/pages/index.ts +++ b/packages/app/src/systems/Settings/pages/index.ts @@ -1,3 +1,4 @@ export { ViewSeedPhrase } from './ViewSeedPhrase'; export { ChangePassword } from './ChangePassword'; export { Connections } from './Connections'; +export { LockTimeout } from './LockTimeout'; diff --git a/packages/app/src/systems/Settings/routes.tsx b/packages/app/src/systems/Settings/routes.tsx index 3aebd9be4..5c7d00917 100644 --- a/packages/app/src/systems/Settings/routes.tsx +++ b/packages/app/src/systems/Settings/routes.tsx @@ -2,11 +2,13 @@ import { Route } from 'react-router-dom'; import { Pages } from '../Core/types'; -import { ChangePassword, Connections } from './pages'; +import { ChangePassword, Connections, LockTimeout } from './pages'; export const settingsRoutes = ( } path={Pages.settingsChangePassword()} /> } path={Pages.settingsConnectedApps()} /> + } path={Pages.settingsSetLockTimeout()} /> + {/* Test Page} /> */} ); diff --git a/packages/app/src/systems/Sidebar/constants/sidebarItems.ts b/packages/app/src/systems/Sidebar/constants/sidebarItems.ts index 2c4b1d392..e886cbad8 100644 --- a/packages/app/src/systems/Sidebar/constants/sidebarItems.ts +++ b/packages/app/src/systems/Sidebar/constants/sidebarItems.ts @@ -74,6 +74,13 @@ export const sidebarItems = (hasErrors: boolean): Array => label: 'Change Password', path: Pages.settingsChangePassword(), }, + { + // added this object + key: 'set-lock-timeout', + icon: 'Clock', + label: 'Auto Lock', + path: Pages.settingsSetLockTimeout(), + }, { key: 'logout', icon: 'Logout', From cfddd120f25a91758ec5fb1b0ab08fd5298fedb2 Mon Sep 17 00:00:00 2001 From: OWK50GA Date: Mon, 23 Dec 2024 00:21:31 +0100 Subject: [PATCH 2/2] removed locktimer.ts --- .../app/src/systems/CRX/utils/lockTimer.ts | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 packages/app/src/systems/CRX/utils/lockTimer.ts diff --git a/packages/app/src/systems/CRX/utils/lockTimer.ts b/packages/app/src/systems/CRX/utils/lockTimer.ts deleted file mode 100644 index a9dd2ebe8..000000000 --- a/packages/app/src/systems/CRX/utils/lockTimer.ts +++ /dev/null @@ -1,31 +0,0 @@ -// 5, 30, 2 hours, 6 hours, 12 hours, never. - -type TimerDurations = 5 | 30 | 120 | 360 | 720; // Allowed duration in minutes. - -class LockerTimer { - private duration: TimerDurations | null = null; - - constructor(duration: number) { - this.validateDuration(duration); - } - - private validateDuration(duration: number) { - const validDurations: TimerDurations[] = [5, 30, 120, 360, 720]; - if (!validDurations.includes(duration as TimerDurations)) { - throw new Error( - `Invalid Timer duration. Valid durations are ${validDurations.join(', ')} minutes.` - ); - } - this.duration = duration as TimerDurations; - } - - public getDuration(): number { - return this?.duration as number; - } - - public setDuration(duration: number) { - this.validateDuration(duration); - } -} - -export default new LockerTimer(5);