mirror of
https://github.com/selfxyz/self.git
synced 2026-02-19 02:24:25 -05:00
* Refactor NFC scanner tests to use a global variable for platform OS, allowing dynamic switching between iOS and Android during tests. This change improves test isolation and avoids hoisting issues with jest.mock. * Triggering GitHub workflows * Add status animations and self logos * Update utilities and styles for statuses * Remove old LED implementation and occurences * Update Self QR Code with new design * Add status banner * Remove console and use QRcodeSteps in styles * Add ARIA and use Memo to prevent re-renders * Add refs for success and error callbacks * Use ref for self app in qrcode * Use selfapp ref consistently * Update connected state animtion * Skip 'parses Android response' test in nfcScanner --------- Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz> Co-authored-by: Javier Cortejoso <javier.cortejoso@gmail.com>
117 lines
3.1 KiB
TypeScript
117 lines
3.1 KiB
TypeScript
import type { SelfApp } from '@selfxyz/sdk-common';
|
|
import { getUniversalLink, REDIRECT_URL, WS_DB_RELAYER } from '@selfxyz/sdk-common';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import { qrWrapperStyle } from '../utils/styles.js';
|
|
import { QRcodeSteps } from '../utils/utils.js';
|
|
import { initWebSocket } from '../utils/websocket.js';
|
|
import QRCode from './QRCode.js';
|
|
import StatusBanner from './StatusBanner.js';
|
|
|
|
interface SelfQRcodeProps {
|
|
selfApp: SelfApp;
|
|
onSuccess: () => void;
|
|
onError: (data: { error_code?: string; reason?: string }) => void;
|
|
type?: 'websocket' | 'deeplink';
|
|
websocketUrl?: string;
|
|
size?: number;
|
|
darkMode?: boolean;
|
|
showBorder?: boolean;
|
|
showStatusText?: boolean;
|
|
}
|
|
|
|
const SelfQRcodeWrapper = (props: SelfQRcodeProps) => {
|
|
const [isClient, setIsClient] = useState(false);
|
|
useEffect(() => {
|
|
setIsClient(true);
|
|
}, []);
|
|
|
|
if (!isClient) {
|
|
return null;
|
|
}
|
|
return <SelfQRcode {...props} />;
|
|
};
|
|
|
|
const SelfQRcode = ({
|
|
selfApp,
|
|
onSuccess,
|
|
onError,
|
|
type = 'websocket',
|
|
websocketUrl = WS_DB_RELAYER,
|
|
size = 300,
|
|
darkMode = false,
|
|
showBorder = true,
|
|
showStatusText = true,
|
|
}: SelfQRcodeProps) => {
|
|
const [proofStep, setProofStep] = useState(QRcodeSteps.WAITING_FOR_MOBILE);
|
|
const [sessionId, setSessionId] = useState('');
|
|
const socketRef = useRef<ReturnType<typeof initWebSocket> | null>(null);
|
|
|
|
// Refs for callbacks to avoid unnecessary WebSocket reconnections.
|
|
const onSuccessRef = useRef(onSuccess);
|
|
const onErrorRef = useRef(onError);
|
|
const selfAppRef = useRef(selfApp);
|
|
|
|
useEffect(() => {
|
|
onSuccessRef.current = onSuccess;
|
|
onErrorRef.current = onError;
|
|
selfAppRef.current = selfApp;
|
|
}, [onSuccess, onError, selfApp]);
|
|
|
|
useEffect(() => {
|
|
setSessionId(uuidv4());
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (sessionId && !socketRef.current) {
|
|
console.log('[QRCode] Initializing new WebSocket connection');
|
|
socketRef.current = initWebSocket(
|
|
websocketUrl,
|
|
{
|
|
...selfAppRef.current,
|
|
sessionId: sessionId,
|
|
},
|
|
type,
|
|
setProofStep,
|
|
() => onSuccessRef.current(),
|
|
(data) => onErrorRef.current(data)
|
|
);
|
|
}
|
|
|
|
return () => {
|
|
console.log('[QRCode] Cleaning up WebSocket connection');
|
|
if (socketRef.current) {
|
|
socketRef.current();
|
|
socketRef.current = null;
|
|
}
|
|
};
|
|
}, [sessionId, type, websocketUrl]);
|
|
|
|
if (!sessionId) {
|
|
return null;
|
|
}
|
|
|
|
const qrValue =
|
|
type === 'websocket'
|
|
? `${REDIRECT_URL}?sessionId=${sessionId}`
|
|
: getUniversalLink({
|
|
...selfAppRef.current,
|
|
sessionId: sessionId,
|
|
});
|
|
|
|
return (
|
|
<div
|
|
style={qrWrapperStyle(proofStep, showBorder)}
|
|
role="img"
|
|
aria-label="Self authentication QR code"
|
|
>
|
|
<QRCode value={qrValue} size={size} darkMode={darkMode} proofStep={proofStep} />
|
|
{showStatusText && <StatusBanner proofStep={proofStep} qrSize={size} />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Also export other components/types that might be needed
|
|
export { SelfQRcode, SelfQRcodeWrapper };
|