diff --git a/src/app/ui/AppProvider/ReduxProvider.tsx b/src/app/ui/AppProvider/ReduxProvider.tsx index 2791ac799..135849e81 100644 --- a/src/app/ui/AppProvider/ReduxProvider.tsx +++ b/src/app/ui/AppProvider/ReduxProvider.tsx @@ -24,10 +24,6 @@ export const persistConfig = { }; const rootReducer = (state: any, action: AnyAction) => { - if (action.type === 'identity/onLogout') { - state = undefined; - } - const reducer = combineReducers({ identity: IdentityModel.reducer, applets: AppletModel.reducer, diff --git a/src/entities/identity/model/slice.ts b/src/entities/identity/model/slice.ts index e68bd22c2..440769ae4 100644 --- a/src/entities/identity/model/slice.ts +++ b/src/entities/identity/model/slice.ts @@ -22,9 +22,6 @@ const identitySlice = createSlice({ onAuthSuccess: (state, action: PayloadAction) => { state.user = action.payload; }, - onLogout: state => { - state.user = null; - }, }, }); diff --git a/src/features/logout/lib/clearEntityRecordStorages.ts b/src/features/login/lib/clearEntityRecordStorages.ts similarity index 100% rename from src/features/logout/lib/clearEntityRecordStorages.ts rename to src/features/login/lib/clearEntityRecordStorages.ts diff --git a/src/features/logout/lib/clearUploadQueueStorage.ts b/src/features/login/lib/clearUploadQueueStorage.ts similarity index 100% rename from src/features/logout/lib/clearUploadQueueStorage.ts rename to src/features/login/lib/clearUploadQueueStorage.ts diff --git a/src/features/logout/lib/index.ts b/src/features/login/lib/index.ts similarity index 100% rename from src/features/logout/lib/index.ts rename to src/features/login/lib/index.ts diff --git a/src/features/login/model/cleanupData.ts b/src/features/login/model/cleanupData.ts new file mode 100644 index 000000000..67c4818a4 --- /dev/null +++ b/src/features/login/model/cleanupData.ts @@ -0,0 +1,18 @@ +import { Logger } from '@shared/lib'; + +import { clearEntityRecordStorages, clearUploadQueueStorage } from '../lib'; + +export async function cleanupData() { + Logger.info('[cleanupData] Processing cleanup upon another user login'); + + try { + await clearEntityRecordStorages(); + clearUploadQueueStorage(); + + Logger.info('[cleanupData] Cleanup operation completed successfully'); + } catch (error) { + Logger.error( + `[cleanupData] Processing cleanup failed with error: ${error}`, + ); + } +} diff --git a/src/features/login/ui/LoginForm.tsx b/src/features/login/ui/LoginForm.tsx index 42e80df2b..0d54e6802 100644 --- a/src/features/login/ui/LoginForm.tsx +++ b/src/features/login/ui/LoginForm.tsx @@ -15,6 +15,7 @@ import { MixEvents, useAppDispatch, useAppForm, + useAppSelector, useFormChanges, } from '@shared/lib'; import { encryption } from '@shared/lib'; @@ -22,6 +23,7 @@ import { YStack, Box, BoxProps, SubmitButton, Center, Link } from '@shared/ui'; import { ErrorMessage, InputField } from '@shared/ui/form'; import { LoginFormSchema } from '../model'; +import { cleanupData } from '../model/cleanupData'; type Props = { onLoginSuccess: () => void; @@ -32,6 +34,7 @@ const LoginForm: FC = props => { const { navigate } = useNavigation(); const dispatch = useAppDispatch(); + const userId = useAppSelector(IdentityModel.selectors.selectUserId); const navigateToForgotPassword = () => { navigate('ForgotPassword'); @@ -43,12 +46,17 @@ const LoginForm: FC = props => { isLoading, reset, } = useLoginMutation({ - onSuccess: (response, variables) => { + onSuccess: async (response, variables) => { const userParams = { userId: response.data.result.user.id, email: response.data.result.user.email, password: variables.password, }; + + if (userParams.userId !== userId) { + await cleanupData(); + } + const userPrivateKey = encryption.getPrivateKey(userParams); UserPrivateKeyRecord.set(userPrivateKey); diff --git a/src/features/logout/model/hooks.ts b/src/features/logout/model/hooks.ts index 232a9feb6..2dd1a2dc5 100644 --- a/src/features/logout/model/hooks.ts +++ b/src/features/logout/model/hooks.ts @@ -6,22 +6,17 @@ import { onBeforeLogout } from '@app/entities/identity/lib/alerts'; import { NotificationModel } from '@app/entities/notification'; import { IdentityService } from '@app/shared/api'; import { SystemRecord } from '@app/shared/lib/records'; -import { IdentityModel } from '@entities/identity'; import { UserInfoRecord, UserPrivateKeyRecord } from '@entities/identity/lib'; import { SessionModel } from '@entities/session'; import { Logger, hasPendingMutations, isAppOnline, - useAppDispatch, AnalyticsService, useTCPSocket, } from '@shared/lib'; -import { clearEntityRecordStorages, clearUploadQueueStorage } from '../lib'; - export function useLogout() { - const dispatch = useAppDispatch(); const queryClient = useQueryClient(); const { closeConnection: closeActiveTCPConnection } = useTCPSocket(); @@ -42,14 +37,8 @@ export function useLogout() { AnalyticsService.logout(); - dispatch(IdentityModel.actions.onLogout()); - CacheManager.clearCache(); - clearEntityRecordStorages(); - - clearUploadQueueStorage(); - NotificationModel.NotificationManager.clearScheduledNotifications(); UserInfoRecord.clear(); diff --git a/src/features/logout/ui/LogoutRowButton.tsx b/src/features/logout/ui/LogoutRowButton.tsx index 34179207c..99cabe79e 100644 --- a/src/features/logout/ui/LogoutRowButton.tsx +++ b/src/features/logout/ui/LogoutRowButton.tsx @@ -6,13 +6,22 @@ import { RowButton, KeyIcon } from '@shared/ui'; import { useLogout } from '../model'; -const LogoutRowButton: FC = () => { +type Props = { + onPress: () => void; +}; + +const LogoutRowButton: FC = ({ onPress }) => { const { t } = useTranslation(); const { logout } = useLogout(); + function performLogout() { + logout(); + onPress(); + } + return ( { - const { navigate } = useNavigation(); + const { navigate, setOptions } = useNavigation(); const { t } = useTranslation(); + const [isLoading, setIsLoading] = useState(false); + + const { top } = useSafeAreaInsets(); + const userName = useAppSelector(IdentityModel.selectors.selectFirstName); const userEmail = useAppSelector(IdentityModel.selectors.selectEmail); @@ -43,45 +56,68 @@ const SettingsScreen: FC = () => { return hashed; }, []); + function setLoading() { + setIsLoading(true); + setOptions({ + headerShown: false, + }); + } + return ( - - - - - - - - - {userName} - {userEmail} - - {`${t( - 'about:device_id', - )}: ${hashedDeviceId}`} + <> + + + + + + + + + {userName} + {userEmail} + + {`${t( + 'about:device_id', + )}: ${hashedDeviceId}`} + + + + + + + + + + + - - - - - + - - - - + + + )} + ); }; diff --git a/src/shared/ui/RowButton.tsx b/src/shared/ui/RowButton.tsx index 6f7216985..5e1ff1b4b 100644 --- a/src/shared/ui/RowButton.tsx +++ b/src/shared/ui/RowButton.tsx @@ -9,6 +9,10 @@ type Props = { rightIcon?: ElementType; } & BoxProps; +const pressStyle = { + opacity: 0.5, +}; + const RowButton: FC = props => { const { onPress, @@ -27,6 +31,7 @@ const RowButton: FC = props => { ai="center" bbc="$lightGrey" bbw={1} + pressStyle={pressStyle} {...boxProps} > {title} diff --git a/src/shared/ui/SketchCanvas/DrawingGesture.ts b/src/shared/ui/SketchCanvas/DrawingGesture.ts index 38205f5e6..92fe58fc4 100644 --- a/src/shared/ui/SketchCanvas/DrawingGesture.ts +++ b/src/shared/ui/SketchCanvas/DrawingGesture.ts @@ -58,7 +58,7 @@ function DrawingGesture( }; }; - const androidGesture = () => + const androidPanGesture = () => Gesture.Pan() .manualActivation(true) .onTouchesDown((event, stateManager) => { @@ -79,7 +79,7 @@ function DrawingGesture( currentTouchIdRef.value = null; } }) - .onBegin(event => { + .onStart(event => { runOnJS(onTouchStart)(event, Date.now()); }) .onTouchesMove((event, manager) => { @@ -96,14 +96,14 @@ function DrawingGesture( runOnJS(onTouchProgress)(touchData, false, time); } }) - .onFinalize(() => { + .onEnd(() => { runOnJS(onTouchEnd)(); }); - const iosGesture = () => + const iosPanGesture = () => Gesture.Pan() .maxPointers(1) - .onBegin(event => { + .onStart(event => { const time = Date.now(); runOnJS(onTouchStart)(event, time); @@ -131,6 +131,30 @@ function DrawingGesture( runOnJS(onTouchEnd)(); }); + const tapGesture = () => + Gesture.Tap() + .onStart(event => { + runOnJS(onTouchStart)(event, Date.now()); + }) + .onEnd(() => { + runOnJS(onTouchEnd)(); + }); + + const longTapGesture = () => + Gesture.LongPress() + .onStart(event => { + runOnJS(onTouchStart)(event, Date.now()); + }) + .onEnd(() => { + runOnJS(onTouchEnd)(); + }); + + const iosGesture = () => + Gesture.Exclusive(iosPanGesture(), tapGesture(), longTapGesture()); + + const androidGesture = () => + Gesture.Exclusive(androidPanGesture(), tapGesture(), longTapGesture()); + const gesture = IS_IOS ? iosGesture() : androidGesture(); return gesture;