mirror of
https://github.com/pezkuwichain/pezkuwi-ui.git
synced 2026-05-01 04:18:00 +00:00
Bump dependencies (#334)
* Bump dependencies * QR display component to functional * Small adjustments
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 0.55.0-beta.x
|
||||
|
||||
- Adjust react-qr `Scan*` makign `onScan` callbacks required
|
||||
- Rework the react-qr display to use functional components
|
||||
- Bump to `@polkadot/api` 1.21.1
|
||||
- Bump to `@polkadot/util` 2.15.1
|
||||
|
||||
## 0.54.1 Jun 16, 2020
|
||||
|
||||
- Add genesisHash to signer payload (Thanks to https://github.com/hanwencheng)
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.3",
|
||||
"@babel/runtime": "^7.10.3",
|
||||
"@polkadot/dev": "^0.55.11",
|
||||
"@polkadot/dev": "^0.55.12",
|
||||
"@polkadot/ts": "^0.3.26",
|
||||
"@types/jest": "^26.0.0",
|
||||
"babel-plugin-transform-vue-template": "^0.4.2",
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"@polkadot/util-crypto": "^2.15.1",
|
||||
"@react-native-community/cli-platform-ios": "^4.10.1",
|
||||
"@types/react-test-renderer": "16.9.2",
|
||||
"babel-jest": "^26.0.1",
|
||||
"babel-jest": "^26.1.0",
|
||||
"metro-react-native-babel-preset": "^0.59.0",
|
||||
"react-test-renderer": "16.13.1"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { BaseProps } from './types';
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { xxhashAsHex } from '@polkadot/util-crypto';
|
||||
|
||||
@@ -16,13 +16,16 @@ interface Props extends BaseProps {
|
||||
value: Uint8Array;
|
||||
}
|
||||
|
||||
interface State {
|
||||
interface FrameState {
|
||||
frames: Uint8Array[];
|
||||
frameIdx: number;
|
||||
image: string | null;
|
||||
valueHash: string | null;
|
||||
}
|
||||
|
||||
interface TimerState {
|
||||
timerDelay: number;
|
||||
timerId: number | null;
|
||||
valueHash: string | null;
|
||||
}
|
||||
|
||||
const FRAME_DELAY = 2500;
|
||||
@@ -40,99 +43,94 @@ function getDataUrl (value: Uint8Array): string {
|
||||
return qr.createDataURL(16, 0);
|
||||
}
|
||||
|
||||
class Display extends React.PureComponent<Props, State> {
|
||||
public state: State = {
|
||||
frameIdx: 0,
|
||||
frames: [],
|
||||
image: null,
|
||||
timerDelay: FRAME_DELAY,
|
||||
timerId: null,
|
||||
valueHash: null
|
||||
};
|
||||
function Display ({ className, size, skipEncoding, style, value }: Props): React.ReactElement<Props> | null {
|
||||
const [{ image }, setFrameState] = useState<FrameState>({ frameIdx: 0, frames: [], image: null, valueHash: null });
|
||||
const [containerStyle, setContainerStyle] = useState(createImgSize(size));
|
||||
const timerRef = useRef<TimerState>({ timerDelay: FRAME_DELAY, timerId: null });
|
||||
|
||||
public static getDerivedStateFromProps ({ skipEncoding = false, value }: Props, prevState: State): Pick<State, never> | null {
|
||||
const valueHash = xxhashAsHex(value);
|
||||
// run on initial load to setup the global timer and provide and unsubscribe
|
||||
useEffect((): () => void => {
|
||||
const nextFrame = () => setFrameState((state): FrameState => {
|
||||
// when we have a single frame, we only ever fire once
|
||||
if (state.frames.length <= 1) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (valueHash === prevState.valueHash) {
|
||||
return null;
|
||||
}
|
||||
let frameIdx = state.frameIdx + 1;
|
||||
|
||||
const frames: Uint8Array[] = skipEncoding
|
||||
? [value]
|
||||
: createFrames(value);
|
||||
// when we overflow, skip to the first and slightly increase the delay between frames
|
||||
if (frameIdx === state.frames.length) {
|
||||
frameIdx = 0;
|
||||
timerRef.current.timerDelay = timerRef.current.timerDelay + TIMER_INC;
|
||||
}
|
||||
|
||||
// encode on demand
|
||||
return {
|
||||
frameIdx: 0,
|
||||
frames,
|
||||
image: getDataUrl(frames[0]),
|
||||
valueHash
|
||||
timerRef.current.timerId = setTimeout(nextFrame, timerRef.current.timerDelay);
|
||||
|
||||
// only encode the frames on demand, not above as part of the
|
||||
// state derivation - in the case of large payloads, this should
|
||||
// be slightly more responsive on initial load
|
||||
return {
|
||||
...state,
|
||||
frameIdx,
|
||||
image: getDataUrl(state.frames[frameIdx])
|
||||
};
|
||||
});
|
||||
|
||||
timerRef.current.timerId = window.setTimeout(nextFrame, FRAME_DELAY);
|
||||
|
||||
return (): void => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
timerRef.current.timerId && clearTimeout(timerRef.current.timerId);
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
public componentDidMount (): void {
|
||||
this.setState({
|
||||
timerId: window.setTimeout(this.nextFrame, FRAME_DELAY)
|
||||
useEffect((): void => {
|
||||
setContainerStyle(createImgSize(size));
|
||||
}, [size]);
|
||||
|
||||
useEffect((): void => {
|
||||
setFrameState((state): FrameState => {
|
||||
const valueHash = xxhashAsHex(value);
|
||||
|
||||
if (valueHash === state.valueHash) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const frames: Uint8Array[] = skipEncoding
|
||||
? [value]
|
||||
: createFrames(value);
|
||||
|
||||
// encode on demand
|
||||
return {
|
||||
frameIdx: 0,
|
||||
frames,
|
||||
image: getDataUrl(frames[0]),
|
||||
valueHash
|
||||
};
|
||||
});
|
||||
}, [skipEncoding, value]);
|
||||
|
||||
if (!image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public componentWillUnmount (): void {
|
||||
const { timerId } = this.state;
|
||||
|
||||
if (timerId) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
}
|
||||
|
||||
public render (): React.ReactNode {
|
||||
const { className, size, style } = this.props;
|
||||
const { image } = this.state;
|
||||
|
||||
if (!image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={containerStyle}
|
||||
>
|
||||
<div
|
||||
className={className}
|
||||
style={createImgSize(size)}
|
||||
className='ui--qr-Display'
|
||||
style={style}
|
||||
>
|
||||
<div
|
||||
className='ui--qr-Display'
|
||||
style={style}
|
||||
>
|
||||
<img src={image} />
|
||||
</div>
|
||||
<img src={image} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private nextFrame = (): void => {
|
||||
const { frameIdx, frames, timerDelay } = this.state;
|
||||
|
||||
if (!frames || frames.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextIdx = frameIdx === frames.length - 1
|
||||
? 0
|
||||
: frameIdx + 1;
|
||||
const nextDelay = timerDelay + ((nextIdx === 0) ? TIMER_INC : 0);
|
||||
const timerId = setTimeout(this.nextFrame, nextDelay);
|
||||
|
||||
// only encode the frames on demand, not above as part of the
|
||||
// state derivation - in the case of large payloads, this should
|
||||
// be slightly more responsive on initial load
|
||||
this.setState({
|
||||
frameIdx: nextIdx,
|
||||
image: getDataUrl(frames[nextIdx]),
|
||||
timerDelay: nextDelay,
|
||||
timerId
|
||||
});
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default styled(Display as React.ComponentClass<Props>)`
|
||||
export default React.memo(styled(Display)`
|
||||
.ui--qr-Display {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@@ -146,4 +144,4 @@ export default styled(Display as React.ComponentClass<Props>)`
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
`);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { BaseProps } from './types';
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import Reader from 'react-qr-reader';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createImgSize } from './util';
|
||||
interface Props extends BaseProps {
|
||||
delay?: number;
|
||||
onError?: (error: Error) => void;
|
||||
onScan?: (data: string) => void;
|
||||
onScan: (data: string) => void;
|
||||
}
|
||||
|
||||
const DEFAULT_DELAY = 150;
|
||||
@@ -23,26 +23,26 @@ const DEFAULT_ERROR = (error: Error): void => {
|
||||
};
|
||||
|
||||
function Scan ({ className, delay = DEFAULT_DELAY, onError = DEFAULT_ERROR, onScan, size, style }: Props): React.ReactElement<Props> {
|
||||
const [containerStyle, setContainerStyle] = useState(createImgSize(size));
|
||||
|
||||
useEffect((): void => {
|
||||
setContainerStyle(createImgSize(size));
|
||||
}, [size]);
|
||||
|
||||
const _onError = useCallback(
|
||||
(error: Error): void => onError(error),
|
||||
(error: Error) => onError(error),
|
||||
[onError]
|
||||
);
|
||||
|
||||
const _onScan = useCallback(
|
||||
(data: string | null): void => {
|
||||
if (!data || !onScan) {
|
||||
return;
|
||||
}
|
||||
|
||||
onScan(data);
|
||||
},
|
||||
(data: string | null) => data && onScan(data),
|
||||
[onScan]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={createImgSize(size)}
|
||||
style={containerStyle}
|
||||
>
|
||||
<Reader
|
||||
className='ui--qr-Scan'
|
||||
|
||||
@@ -20,31 +20,29 @@ interface ScanType {
|
||||
|
||||
interface Props extends BaseProps {
|
||||
onError?: (error: Error) => void;
|
||||
onScan?: (scanned: ScanType) => void;
|
||||
onScan: (scanned: ScanType) => void;
|
||||
}
|
||||
|
||||
function ScanAddress ({ className, onError, onScan, size, style }: Props): React.ReactElement<Props> {
|
||||
const _onScan = useCallback(
|
||||
(data: string | null): void => {
|
||||
if (!data || !onScan) {
|
||||
return;
|
||||
}
|
||||
if (data) {
|
||||
try {
|
||||
const [prefix, content, genesisHash, name] = data.split(':');
|
||||
const isValidPrefix = prefix === ADDRESS_PREFIX || prefix === SEED_PREFIX;
|
||||
|
||||
try {
|
||||
const [prefix, content, genesisHash, name] = data.split(':');
|
||||
const isValidPrefix = prefix === ADDRESS_PREFIX || prefix === SEED_PREFIX;
|
||||
assert(isValidPrefix, `Invalid prefix received, expected '${ADDRESS_PREFIX}/${SEED_PREFIX}' , found '${prefix}'`);
|
||||
|
||||
assert(isValidPrefix, `Invalid prefix received, expected '${ADDRESS_PREFIX}/${SEED_PREFIX}' , found '${prefix}'`);
|
||||
const isAddress = prefix === ADDRESS_PREFIX;
|
||||
|
||||
const isAddress = prefix === ADDRESS_PREFIX;
|
||||
if (isAddress) {
|
||||
decodeAddress(content);
|
||||
}
|
||||
|
||||
if (isAddress) {
|
||||
decodeAddress(content);
|
||||
onScan({ content, genesisHash, isAddress, name });
|
||||
} catch (error) {
|
||||
console.error('@polkadot/react-qr:QrScanAddress', (error as Error).message, data);
|
||||
}
|
||||
|
||||
onScan({ content, genesisHash, isAddress, name });
|
||||
} catch (error) {
|
||||
console.error('@polkadot/react-qr:QrScanAddress', (error as Error).message, data);
|
||||
}
|
||||
},
|
||||
[onScan]
|
||||
|
||||
@@ -14,18 +14,12 @@ interface ScanType {
|
||||
|
||||
interface Props extends BaseProps {
|
||||
onError?: (error: Error) => void;
|
||||
onScan?: (scanned: ScanType) => void;
|
||||
onScan: (scanned: ScanType) => void;
|
||||
}
|
||||
|
||||
function ScanSignature ({ className, onError, onScan, size, style }: Props): React.ReactElement<Props> {
|
||||
const _onScan = useCallback(
|
||||
(signature: string | null): void => {
|
||||
if (!signature || !onScan) {
|
||||
return;
|
||||
}
|
||||
|
||||
onScan({ signature: `0x${signature}` });
|
||||
},
|
||||
(signature: string | null) => signature && onScan({ signature: `0x${signature}` }),
|
||||
[onScan]
|
||||
);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/keyring": "^2.15.1",
|
||||
"@polkadot/types": "^1.20.1",
|
||||
"@polkadot/types": "^1.22.0-beta.1",
|
||||
"@polkadot/util": "^2.15.1",
|
||||
"@types/ledgerhq__hw-transport-node-hid": "^4.22.1",
|
||||
"@types/ledgerhq__hw-transport-webusb": "^4.70.0",
|
||||
|
||||
Reference in New Issue
Block a user