Skip to content

Commit

Permalink
chore: bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Nodonisko committed Nov 29, 2024
1 parent 9171dca commit 61b3b75
Show file tree
Hide file tree
Showing 18 changed files with 155 additions and 104 deletions.
1 change: 1 addition & 0 deletions packages/eslint/src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const eslint = [
'**/node_modules/*',
'**/public/*',
'**/ci/',
'**/.expo/*',
'eslint-local-rules/*',
],
},
Expand Down
2 changes: 1 addition & 1 deletion suite-common/firmware/src/firmwareThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type FirmwareUpdateProps = {
ignoreBaseUrl?: boolean;
};

type FirmwareUpdateResult = {
export type FirmwareUpdateResult = {
device?: TrezorDevice;
toFwVersion?: string;
toBtcOnly?: boolean;
Expand Down
4 changes: 2 additions & 2 deletions suite-common/wallet-core/src/discovery/discoveryReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const selectDiscovery = (state: DiscoveryRootState) => state.wallet.disco
// Get discovery process for deviceState.
export const selectDiscoveryByDeviceState = (
state: DiscoveryRootState,
deviceState: DeviceState | StaticSessionId | undefined,
deviceState: DeviceState | StaticSessionId | undefined | null,
) =>
deviceState
? state.wallet.discovery.find(d =>
Expand All @@ -101,7 +101,7 @@ export const selectDeviceDiscovery = (state: DiscoveryRootState & DeviceRootStat

export const selectIsDiscoveryActiveByDeviceState = (
state: DiscoveryRootState & DeviceRootState,
deviceState: DeviceState | StaticSessionId | undefined,
deviceState: DeviceState | StaticSessionId | undefined | null,
) => {
const discovery = selectDiscoveryByDeviceState(state, deviceState);

Expand Down
2 changes: 1 addition & 1 deletion suite-native/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default ({ config }: ConfigContext): ExpoConfig => {
slug: appSlugs[buildType],
owner: appOwners[buildType],
version: suiteNativeVersion,
runtimeVersion: '12',
runtimeVersion: '15',
...(buildType === 'production'
? {}
: {
Expand Down
3 changes: 2 additions & 1 deletion suite-native/firmware/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
"dependencies": {
"@react-navigation/native": "6.1.18",
"@reduxjs/toolkit": "1.9.5",
"@shopify/react-native-skia": "1.5.3",
"@shopify/react-native-skia": "^1.5.10",
"@suite-common/firmware": "workspace:*",
"@suite-common/icons": "workspace:*",
"@suite-native/link": "workspace:*",
"@trezor/connect": "workspace:*",
"@trezor/styles": "workspace:*",
"react": "18.2.0",
Expand Down
57 changes: 31 additions & 26 deletions suite-native/firmware/src/components/UpdateProgressIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ import {
useSVG,
} from '@shopify/react-native-skia';

import { FirmwareOperationStatus } from '@suite-common/firmware';
import { useNativeStyles } from '@trezor/styles';

const CANVAS_SIZE = 160;
const CIRCLE_RADIUS = 128;
const CIRCLE_DIAMETER = 128;
const CIRCLE_CENTER = CANVAS_SIZE / 2;

const PROGRESS_STROKE_WIDTH = 5;
Expand All @@ -41,13 +40,13 @@ const CHECKMARK_SCALE = 1; // Adjust size
const LONG_LEG_RATIO = 0.25; // Reduce from 0.33 (1/3) to make long leg shorter

const checkmarkPath = Skia.Path.MakeFromSVGString(
`M${CIRCLE_CENTER - CIRCLE_RADIUS / 4 + CHECKMARK_OFFSET_X},${CIRCLE_CENTER + CHECKMARK_OFFSET_Y}` +
`l${(CIRCLE_RADIUS / 8) * CHECKMARK_SCALE},${(CIRCLE_RADIUS / 8) * CHECKMARK_SCALE}` +
`l${CIRCLE_RADIUS * LONG_LEG_RATIO * CHECKMARK_SCALE},-${CIRCLE_RADIUS * LONG_LEG_RATIO * CHECKMARK_SCALE}`,
`M${CIRCLE_CENTER - CIRCLE_DIAMETER / 4 + CHECKMARK_OFFSET_X},${CIRCLE_CENTER + CHECKMARK_OFFSET_Y}` +
`l${(CIRCLE_DIAMETER / 8) * CHECKMARK_SCALE},${(CIRCLE_DIAMETER / 8) * CHECKMARK_SCALE}` +
`l${CIRCLE_DIAMETER * LONG_LEG_RATIO * CHECKMARK_SCALE},-${CIRCLE_DIAMETER * LONG_LEG_RATIO * CHECKMARK_SCALE}`,
)!;

const progressCirclePath = Skia.Path.MakeFromSVGString(
`M ${CIRCLE_CENTER},${CIRCLE_CENTER - (CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2} A ${(CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2},${(CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2} 0 1,1 ${CIRCLE_CENTER},${CIRCLE_CENTER + (CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2} A ${(CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2},${(CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2} 0 1,1 ${CIRCLE_CENTER},${CIRCLE_CENTER - (CIRCLE_RADIUS - PROGRESS_STROKE_WIDTH) / 2}`,
`M ${CIRCLE_CENTER},${CIRCLE_CENTER - (CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2} A ${(CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2},${(CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2} 0 1,1 ${CIRCLE_CENTER},${CIRCLE_CENTER + (CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2} A ${(CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2},${(CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2} 0 1,1 ${CIRCLE_CENTER},${CIRCLE_CENTER - (CIRCLE_DIAMETER - PROGRESS_STROKE_WIDTH) / 2}`,
)!;

const fontStyle = {
Expand Down Expand Up @@ -104,17 +103,19 @@ const AnimatedOpacity = ({
);
};

export type UpdateProgressIndicatorStatus = 'starting' | 'success' | 'error' | 'inProgress';
export type UpdateProgressIndicatorProps = {
progress: number;
status: UpdateProgressIndicatorStatus;
};

// If you want to test animation states, use UpdateProgressIndicatorDemo, it will help you a lot.
export const UpdateProgressIndicator = ({
progress,
isError,
operation,
isStarting,
status,
}: {
progress: number;
isError: boolean;
operation: FirmwareOperationStatus['operation'];
isStarting: boolean;
status: UpdateProgressIndicatorStatus;
}) => {
const checkmarkAnimationProgress = useSharedValue(0);
const { utils } = useNativeStyles();
Expand All @@ -126,9 +127,11 @@ export const UpdateProgressIndicator = ({
const trezorLogoOpacity = useSharedValue(1);
const errorSvgOpacity = useSharedValue(0);
const paragraphOpacity = useSharedValue(0);
const isSuccess = operation === 'completed';
const isInProgress = !isStarting && !isSuccess && !isError;
const isDone = isSuccess || isError;

const isStarting = status === 'starting';
const isSuccess = status === 'success';
const isError = status === 'error';
const isInProgress = status === 'inProgress';

useEffect(() => {
if (isStarting) {
Expand All @@ -154,7 +157,7 @@ export const UpdateProgressIndicator = ({
paragraphOpacity.value = withTiming(1, { duration: 600 });
}
if (isSuccess) {
animatedBackgroundRadius.value = withSpring(CIRCLE_RADIUS / 2);
animatedBackgroundRadius.value = withSpring(CIRCLE_DIAMETER / 2);
backgroundColorFinished.value = utils.colors.textPrimaryDefault;

checkmarkAnimationProgress.value = withDelay(300, withSpring(1));
Expand All @@ -165,7 +168,7 @@ export const UpdateProgressIndicator = ({
paragraphOpacity.value = 0;
}
if (isError) {
animatedBackgroundRadius.value = withSpring(CIRCLE_RADIUS / 2);
animatedBackgroundRadius.value = withSpring(CIRCLE_DIAMETER / 2);
backgroundColorFinished.value = utils.colors.backgroundAlertRedBold;

checkmarkAnimationProgress.value = 0;
Expand Down Expand Up @@ -203,12 +206,14 @@ export const UpdateProgressIndicator = ({
.build();
}, [progress, utils.colors.textPrimaryDefault, isInProgress]);

const isDone = isSuccess || isError;

return (
<Canvas style={{ width: CANVAS_SIZE, height: CANVAS_SIZE }}>
<Circle
cx={CIRCLE_CENTER}
cy={CIRCLE_CENTER}
r={CIRCLE_RADIUS / 2}
r={CIRCLE_DIAMETER / 2}
color={utils.colors.backgroundSurfaceElevation1}
></Circle>

Expand All @@ -226,11 +231,11 @@ export const UpdateProgressIndicator = ({
<AnimatedOpacity opacity={trezorLogoOpacity}>
<ImageSVG
svg={trezorLogoSvg}
x={CIRCLE_CENTER - CIRCLE_RADIUS / 4}
y={CIRCLE_CENTER - CIRCLE_RADIUS / 4}
x={CIRCLE_CENTER - CIRCLE_DIAMETER / 4}
y={CIRCLE_CENTER - CIRCLE_DIAMETER / 4}
color={utils.colors.textPrimaryDefault}
width={CIRCLE_RADIUS / 2}
height={CIRCLE_RADIUS / 2}
width={CIRCLE_DIAMETER / 2}
height={CIRCLE_DIAMETER / 2}
opacity={trezorLogoOpacity}
/>
</AnimatedOpacity>
Expand Down Expand Up @@ -271,11 +276,11 @@ export const UpdateProgressIndicator = ({
<AnimatedOpacity opacity={errorSvgOpacity}>
<ImageSVG
svg={crossSvg}
x={CIRCLE_CENTER - CIRCLE_RADIUS / 4}
y={CIRCLE_CENTER - CIRCLE_RADIUS / 4}
x={CIRCLE_CENTER - CIRCLE_DIAMETER / 4}
y={CIRCLE_CENTER - CIRCLE_DIAMETER / 4}
color={utils.colors.backgroundAlertRedBold}
width={CIRCLE_RADIUS / 2}
height={CIRCLE_RADIUS / 2}
width={CIRCLE_DIAMETER / 2}
height={CIRCLE_DIAMETER / 2}
/>
</AnimatedOpacity>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import { useState } from 'react';

import { VStack, Button, HStack } from '@suite-native/atoms';
import { FirmwareOperationStatus } from '@suite-common/firmware';

import { UpdateProgressIndicator } from './UpdateProgressIndicator';
import { UpdateProgressIndicator, UpdateProgressIndicatorStatus } from './UpdateProgressIndicator';

// DEBUG ONLY:This component is useful for testing animation states of UpdateProgressIndicator
export const UpdateProgressIndicatorDemo = () => {
const [status, setStatus] = useState<{
isStarting: boolean;
isError: boolean;
operation: FirmwareOperationStatus['operation'] | null;
status: UpdateProgressIndicatorStatus;
progress: number;
}>({
isStarting: true,
isError: false,
operation: null,
status: 'starting',
progress: 0,
});

Expand All @@ -34,9 +29,7 @@ export const UpdateProgressIndicatorDemo = () => {
<Button
onPress={() =>
setStatus({
isStarting: true,
isError: false,
operation: null,
status: 'starting',
progress: 0,
})
}
Expand All @@ -46,9 +39,7 @@ export const UpdateProgressIndicatorDemo = () => {
<Button
onPress={() =>
setStatus({
isStarting: false,
isError: false,
operation: 'installing',
status: 'inProgress',
progress: 10,
})
}
Expand All @@ -58,9 +49,7 @@ export const UpdateProgressIndicatorDemo = () => {
<Button
onPress={() =>
setStatus({
isStarting: false,
isError: true,
operation: 'installing',
status: 'error',
progress: 10,
})
}
Expand All @@ -70,9 +59,7 @@ export const UpdateProgressIndicatorDemo = () => {
<Button
onPress={() =>
setStatus({
isStarting: false,
isError: false,
operation: 'completed',
status: 'success',
progress: 10,
})
}
Expand Down
27 changes: 22 additions & 5 deletions suite-native/firmware/src/hooks/useFirmware.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useCallback, useMemo, useRef, useState, useEffect } from 'react';
import { useDispatch } from 'react-redux';

import { useFirmwareInstallation, UseFirmwareInstallationParams } from '@suite-common/firmware';
import {
FirmwareUpdateResult,
useFirmwareInstallation,
UseFirmwareInstallationParams,
} from '@suite-common/firmware';
import { TxKeyPath, useTranslate } from '@suite-native/intl';

import { nativeFirmwareActions } from '../nativeFirmwareSlice';
Expand Down Expand Up @@ -58,6 +62,13 @@ export const useFirmware = (params: UseFirmwareInstallationParams) => {
const firmwareUpdate = useCallback(async () => {
const result = await firmwareUpdateCommon({ ignoreBaseUrl: true })
.unwrap()
.catch(error => {
if ((error as FirmwareUpdateResult)?.connectResponse?.success !== undefined) {
// This is a firmware update error that is handled by us and we expect promise not to be rejected (for example user cancelled the action on device)
return error as FirmwareUpdateResult;
}
throw error;
})
.then(({ connectResponse }) => {
return connectResponse;
})
Expand All @@ -76,16 +87,22 @@ export const useFirmware = (params: UseFirmwareInstallationParams) => {

const translatedText = useMemo(() => {
let text: { title: TxKeyPath; subtitle?: TxKeyPath } = {
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.started.title',
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.initializing.title',
};

const isInitialState = (status === 'started' && operation === null) || status === 'initial';

if (status === 'error') {
text = {
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.error.title',
};
} else if ((status === 'started' && operation === null) || status === 'initial') {
} else if (isInitialState && !confirmOnDevice) {
text = {
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.initializing.title',
};
} else if (isInitialState) {
text = {
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.started.title',
title: 'moduleDeviceSettings.firmware.firmwareUpdateProgress.confirming.title',
};
} else if (operation === 'validating') {
text = {
Expand All @@ -112,7 +129,7 @@ export const useFirmware = (params: UseFirmwareInstallationParams) => {
title: translate(text.title),
subtitle: text.subtitle ? translate(text.subtitle) : error,
};
}, [operation, status, error, translate]);
}, [operation, status, error, confirmOnDevice, translate]);

return {
...firmwareInstallation,
Expand Down
Loading

0 comments on commit 61b3b75

Please sign in to comment.