Skip to content

Commit

Permalink
signer qr chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
sorokin0andrey committed May 6, 2024
1 parent 34ed79b commit 3c65857
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 27 deletions.
46 changes: 46 additions & 0 deletions packages/mobile/src/screens/SignerConfirmScreen/QrCodeView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { View, ViewStyle, deviceWidth, ns } from '@tonkeeper/uikit';
import { FC, memo, useCallback } from 'react';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
import QRCode from 'react-native-qrcode-styled';
import { LayoutChangeEvent } from 'react-native';

export const QR_SIZE = deviceWidth - ns(16) * 2 - ns(24) * 2;

export const QR_WRAP_STYLE: ViewStyle = {
width: QR_SIZE,
height: QR_SIZE,
alignItems: 'center',
justifyContent: 'center',
};

interface Props {
data: string;
index: number;
currentChunkIndex: Animated.SharedValue<number>;
}

export const QrCodeView: FC<Props> = memo((props) => {
const { data, index, currentChunkIndex } = props;

const qrCodeScale = useSharedValue(1);

const handleQrCodeLayout = useCallback(
(e: LayoutChangeEvent) => {
qrCodeScale.value = QR_SIZE / e.nativeEvent.layout.width;
},
[qrCodeScale],
);

const qrStyle = useAnimatedStyle(() => ({
transform: [{ scale: qrCodeScale.value }],
opacity: index === currentChunkIndex.value ? 1 : 0,
}));

return (
<View style={QR_WRAP_STYLE}>
<Animated.View style={qrStyle}>
<QRCode data={data} onLayout={handleQrCodeLayout} pieceSize={8} />
</Animated.View>
</View>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,30 @@ import {
deviceWidth,
ns,
} from '@tonkeeper/uikit';
import { useCallback, useEffect, useRef } from 'react';
import { useEffect, useMemo, useRef } from 'react';
import { tk } from '$wallet';
import QRCode from 'react-native-qrcode-styled';
import QRCodeScanner from 'react-native-qrcode-scanner';
import { DeeplinkOrigin, useDeeplinking } from '$libs/deeplinking';
import { useParams } from '@tonkeeper/router/src/imperative';
import { t } from '@tonkeeper/shared/i18n';
import { LayoutChangeEvent } from 'react-native';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
import { ScannerMask } from '$core/ScanQR/ScannerMask';
import { delay } from '@tonkeeper/core';

const QR_SIZE = deviceWidth - ns(16) * 2 - ns(24) * 2;

const QR_WRAP_STYLE: ViewStyle = {
width: QR_SIZE,
height: QR_SIZE,
alignItems: 'center',
justifyContent: 'center',
};
import { QR_WRAP_STYLE, QrCodeView } from './QrCodeView';
import Animated, {
useSharedValue,
withDelay,
withRepeat,
withSequence,
withTiming,
} from 'react-native-reanimated';

function getChunks(input: string, chunkSize: number): string[] {
const chunks: string[] = [];
for (let i = 0; i < input.length; i += chunkSize) {
chunks.push(input.substring(i, i + chunkSize));
}
return chunks;
}

const SCANNER_SIZE = deviceWidth - ns(16) * 2;

Expand All @@ -50,18 +54,9 @@ export const SignerConfirmScreen = () => {

const deeplinking = useDeeplinking();

const qrCodeScale = useSharedValue(1);
const chunks = useMemo(() => getChunks(deeplink, 256), [deeplink]);

const handleQrCodeLayout = useCallback(
(e: LayoutChangeEvent) => {
qrCodeScale.value = QR_SIZE / e.nativeEvent.layout.width;
},
[qrCodeScale],
);

const qrStyle = useAnimatedStyle(() => ({
transform: [{ scale: qrCodeScale.value }],
}));
const currentChunkIndex = useSharedValue(0);

useEffect(() => {
return () => {
Expand Down Expand Up @@ -90,6 +85,17 @@ export const SignerConfirmScreen = () => {
}
};

useEffect(() => {
if (chunks.length > 0) {
currentChunkIndex.value = withRepeat(
withSequence(
...chunks.map((_, index) => withDelay(100, withTiming(index, { duration: 0 }))),
),
-1,
);
}
}, [chunks, currentChunkIndex]);

return (
<Modal>
<Modal.Header title={t('signerConfirm.title')} titlePosition="left" />
Expand All @@ -104,9 +110,15 @@ export const SignerConfirmScreen = () => {
<Spacer y={16} />
<View style={styles.qrCodeContainer}>
<View style={QR_WRAP_STYLE}>
<Animated.View style={qrStyle}>
<QRCode data={deeplink} onLayout={handleQrCodeLayout} pieceSize={8} />
</Animated.View>
{chunks.map((chunk, index) => (
<Animated.View style={styles.qrChunk.static} key={chunk}>
<QrCodeView
index={index}
data={chunk}
currentChunkIndex={currentChunkIndex}
/>
</Animated.View>
))}
</View>
</View>
<Spacer y={16} />
Expand Down Expand Up @@ -158,6 +170,11 @@ const styles = Steezy.create(({ colors, corners, safeArea }) => ({
paddingVertical: 24,
alignItems: 'center',
},
qrChunk: {
position: 'absolute',
top: 0,
left: 0,
},
cameraContainer: {
backgroundColor: colors.constantBlack,
alignItems: 'center',
Expand Down

0 comments on commit 3c65857

Please sign in to comment.