Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1428/entropy screen changes #1446

Merged
merged 21 commits into from
Sep 11, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@types/react-redux": "^5.0.15",
"@types/react-test-renderer": "^16.8.1",
"@types/redux-mock-store": "^1.0.1",
"@types/sjcl": "^1.0.28",
"@typescript-eslint/eslint-plugin": "^1.5.0",
"@typescript-eslint/parser": "^1.5.0",
"babel-jest": "^24.8.0",
Expand Down
11 changes: 8 additions & 3 deletions src/lib/entropyGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const sjcl = require('sjcl')
import * as sjcl from 'sjcl'

export interface EntropyGeneratorInterface {
addFromDelta: (d: number) => void
getProgress: () => number
generateRandomString: (wordCount: number) => string
}

export class EntropyGenerator implements EntropyGenerator {
export class EntropyGenerator implements EntropyGeneratorInterface {
private generator = new sjcl.prng(10)

addFromDelta(d: number): void {
Expand All @@ -17,8 +17,13 @@ export class EntropyGenerator implements EntropyGenerator {
return this.generator.getProgress()
}

/**
* Once the generator is ready, it can be used to generate a random buffer
* @param wordCount - Amount of random words to generate (1 word - 4 bytes)
* @returns Hex string encoding wordCount * 4 bytes random bytes
*/

generateRandomString(wordCount: number): string {
// returns an array of length wordCount filled with random 4 byte words.
const intArray = new Int32Array(this.generator.randomWords(wordCount))
const buf = Buffer.from(intArray.buffer)
return buf.toString('hex')
Expand Down
5 changes: 3 additions & 2 deletions src/resources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ export const MoreIcon = require('src/resources/svg/MoreIcon').default
export const NameIcon = require('src/resources/svg/NameIcon').default
export const EmailIcon = require('src/resources/svg/EmailIcon').default
export const PhoneIcon = require('src/resources/svg/PhoneIcon').default
export const AccessibilityIcon = require('src/resources/svg/AccessibilityIcon')
.default
export const AccessibilityIcon = require('src/resources/svg/AccessibilityIcon').default
export const IdentityMenuIcon = require('./svg/IdentityMenuIcon').default
export const DocumentsMenuIcon = require('./svg/DocumentsMenuIcon').default
export const RecordsMenuIcon = require('./svg/RecordsMenuIcon').default
export const SettingsMenuIcon = require('./svg/SettingsMenuIcon').default
export const HandIcon = require('./svg/HandIcon').default
export const SplashIcon = require('./svg/SplashIcon').default
export const CheckMarkIcon = require('./svg/CheckmarkIcon').default
export const NextIcon = require('./svg/NextIcon').default
export const PreviousIcon = require('./svg/PreviousIcon').default
Expand Down
19 changes: 19 additions & 0 deletions src/resources/svg/HandIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import Svg, { Defs, G, Path } from 'react-native-svg'
/* SVGR has dropped some elements not supported by react-native-svg: filter */

const SvgHandIcon = props => (
<Svg width={94} height={101} {...props}>
<Defs></Defs>
<G
filter="url(#HandIcon_svg__a)"
transform="translate(4 1.5)"
fill="#FFEFDF"
fillRule="nonzero"
>
<Path d="M86.144 69.365c-1.803-4.854-2.208-8.4-2.602-11.827-.531-4.621-1.079-9.402-5.003-16.748L67.786 20.66c-1.732-3.24-6.038-4.491-9.04-2.617-1.005.627-1.842 1.568-2.417 2.692-1.114-1.732-2.738-2.97-4.644-3.522-2.134-.619-4.362-.298-6.276.892-1.82 1.136-3.09 2.91-3.706 4.911-2.587-2.31-6.34-2.774-9.412-.854-1.788 1.115-3.101 2.873-3.73 4.982L14.324 5.506C10.136-.664 6.016.592 3.93 1.895 2.01 3.093.742 5 .36 7.269c-.353 2.086.062 4.375 1.194 6.488l22.892 40.197c.478.84 1.497 1.103 2.275.586.779-.519 1.022-1.618.542-2.458L4.393 11.927c-.713-1.338-.99-2.763-.779-4.018.209-1.235.89-2.243 1.97-2.917.745-.465 3.008-1.881 6.058 2.608L29.35 34.516c.511.776 1.497.983 2.243.469.743-.517.98-1.574.538-2.4a5.709 5.709 0 0 1-.496-4.07c.342-1.384 1.164-2.541 2.31-3.256 2.371-1.477 5.415-.6 6.782 1.963l1.647 3.086a.036.036 0 0 1 .007.01c.457.857 1.47 1.147 2.26.655.79-.493 1.062-1.586.605-2.442-1.368-2.562-.554-5.848 1.817-7.327a4.612 4.612 0 0 1 3.765-.536c1.282.372 2.35 1.258 3.012 2.5l2.477 4.633.005.011c.458.855 1.469 1.146 2.261.654.791-.493 1.062-1.586.606-2.442-.419-.781-.523-1.77-.285-2.71.238-.937.783-1.73 1.496-2.175 1.449-.904 3.687-.254 4.52 1.309l10.754 20.13c3.59 6.717 4.073 10.936 4.584 15.4.38 3.311.771 6.724 2.301 11.267l-32.004 19.97C44.98 82.727 36.459 75.92 25.2 68.963a199.17 199.17 0 0 0-3.612-2.18c-3.04-1.791-5.188-5.353-5.226-8.658-.016-1.502.42-3.578 2.597-4.935.793-.495 1.064-1.59.608-2.444-.459-.855-1.473-1.148-2.262-.654-2.779 1.736-4.29 4.603-4.25 8.075.05 4.611 2.844 9.335 6.95 11.757a192.98 192.98 0 0 1 3.552 2.142c11.573 7.152 20.128 14.083 25.425 20.6.323.397.78.608 1.242.608.283 0 .57-.079.828-.24L85.436 71.58c.713-.445 1.014-1.389.708-2.215z" />
</G>
</Svg>
)

export default SvgHandIcon
12 changes: 12 additions & 0 deletions src/resources/svg/SplashIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import Svg, { G, Path } from 'react-native-svg'

const SvgSplashIcon = props => (
<Svg width={35} height={38} {...props}>
<G fill="#FFEFDF" fillRule="nonzero">
<Path d="M10.497 14.371c.322.35.746.524 1.17.524.423 0 .846-.174 1.169-.524a1.89 1.89 0 0 0 0-2.528l-4.68-5.056c-.647-.7-1.694-.7-2.34 0a1.89 1.89 0 0 0 0 2.528l4.68 5.056zM28.042 14.897a1.59 1.59 0 0 0 1.17-.524l4.678-5.058c.647-.7.647-1.83 0-2.528-.645-.7-1.692-.7-2.339 0l-4.678 5.058a1.89 1.89 0 0 0 0 2.528c.322.348.746.524 1.17.524zM19.853 11.23c.914 0 1.655-.801 1.655-1.788V2.291c0-.987-.741-1.788-1.655-1.788-.913 0-1.654.8-1.654 1.788v7.15c0 .988.741 1.789 1.654 1.789zM9.928 21.957c0-.987-.742-1.788-1.655-1.788H1.654C.741 20.17 0 20.97 0 21.957s.741 1.788 1.654 1.788h6.62c.912 0 1.654-.801 1.654-1.788zM10.495 29.543L5.815 34.6c-.647.699-.647 1.83 0 2.528.323.35.746.523 1.17.523.423 0 .847-.173 1.17-.523l4.68-5.058c.644-.698.644-1.83 0-2.528a1.567 1.567 0 0 0-2.34 0z" />
</G>
</Svg>
)

export default SvgSplashIcon
35 changes: 15 additions & 20 deletions src/ui/registration/components/entropy.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import React from 'react'
import { StyleSheet, View, Text } from 'react-native'
import { Container, JolocomButton } from 'src/ui/structure/'
import { Container } from 'src/ui/structure/'
import { MaskedImageComponent } from 'src/ui/registration/components/maskedImage'
import I18n from 'src/locales/i18n'
import strings from '../../../locales/strings'
import { Typography, Colors } from 'src/styles'
import { HandAnimationComponent } from './handAnimation'

interface Props {
addPoint: (x: number, y: number) => void
submitEntropy: () => void
readonly progress: number
}

const styles = StyleSheet.create({
mainContainer: {
backgroundColor: Colors.blackMain,
},
footerButton: {
position: 'absolute',
bottom: '5%',
},
text: {
...Typography.subMainText,
textAlign: 'center',
Expand All @@ -31,10 +27,14 @@ const styles = StyleSheet.create({
bigFont: {
fontSize: Typography.text4XL,
},
contentContainer: {
flex: 1,
flexDirection: 'column',
},
})

export const EntropyComponent: React.SFC<Props> = props => {
const { progress, submitEntropy, addPoint } = props
export const EntropyComponent: React.FC<Props> = props => {
const { progress, addPoint } = props

const msg =
progress === 0
Expand All @@ -48,19 +48,14 @@ export const EntropyComponent: React.SFC<Props> = props => {
return (
<Container style={styles.mainContainer}>
<Text style={textStyle}>{msg}</Text>
<View style={{ width: '100%' }}>
<MaskedImageComponent disabled={progress === 1} addPoint={addPoint} />
</View>
<View style={styles.footerButton}>
{progress === 1 ? (
<JolocomButton
upperCase={false}
raised={true}
text={I18n.t(strings.CONTINUE)}
onPress={submitEntropy}
/>
<Container style={styles.contentContainer}>
{progress === 0 ? (
<View style={{ position: 'absolute' }}>
<HandAnimationComponent />
</View>
) : null}
</View>
<MaskedImageComponent disabled={progress === 1} addPoint={addPoint} />
</Container>
</Container>
)
}
66 changes: 66 additions & 0 deletions src/ui/registration/components/handAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useRef, useEffect } from 'react'
import { StyleSheet, View, Animated } from 'react-native'
import { HandIcon, SplashIcon } from 'src/resources/index'

interface Props {}

const styles = StyleSheet.create({
handPosition: {
// TODO change to be % based
top: -29,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this need to be % based? Because magic numbers seem hack-y?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as long as there's a comment explaining that this is the position where the hand fits in the sparkly bit, it should be fine.

left: 8,
},
splashPosition: {
top: 0,
left: 0,
},
})

// TODO explain this better
export const usePulseForBoth = () => {
// We need two changing values to use for the opacity,
const handPV = useRef(new Animated.Value(0)).current
const splashPV = useRef(new Animated.Value(0)).current

// here we define how these values change
// in parallel, they change in sync
const pulse = () =>
Animated.parallel([
// these sequences are made of individual time frames, here I'm just
// making a list of timings which each move to the next value
Animated.sequence(
[1, 0, 1, 0, 0, 1, 0].map(n =>
Animated.timing(splashPV, { toValue: n }),
),
),
Animated.sequence(
[1, 1, 1, 0, 0, 1, 1].map(n => Animated.timing(handPV, { toValue: n })),
),
// this must have itself as a callback to loop
]).start(pulse)

// this is react hook magic, whatever functional component this is called in
// will start the loop and clean up when it's lifetime is over
useEffect(() => {
const timeout = setTimeout(pulse, 0)
return () => clearTimeout(timeout)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Late to the party, but this will not work because the timeout has already fired. The recursive callbacks (pulse) need to have a stop flag. Will resolve in #1417

})

// return your shiny new looping animated values
return { handPV, splashPV }
}

export const HandAnimationComponent: React.FC<Props> = props => {
const { handPV, splashPV } = usePulseForBoth()

return (
<View>
<Animated.View style={{ opacity: splashPV, ...styles.splashPosition }}>
<SplashIcon />
</Animated.View>
<Animated.View style={{ opacity: handPV, ...styles.handPosition }}>
<HandIcon />
</Animated.View>
</View>
)
}
7 changes: 4 additions & 3 deletions src/ui/registration/containers/entropy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ interface State {
}

// we are gonna collect some from the user and the rest from the OS
const ENOUGH_ENTROPY_PROGRESS = 0.6
const ENOUGH_ENTROPY_PROGRESS = 0.3
const POST_COLLECTION_WAIT_TIME = 1000
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that this wait time seems a bit unnatural - I'm not sure the best course of action though. Instantaneous is also a bit jumpy.

Copy link
Collaborator

@Exulansis Exulansis Sep 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally the navigation would be a bit smoother. I don't think it's a matter of the timeout so much, and rather the animation used during navigation (or in this case the lack of one). Not entirely sure how to approach this / what the best course of action is.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We disabled the animations/transitions between the starting screens - this is probably a casualty of that. I would suggest lowering the timeout for now and then iterating on solutions to make it smoother in the future.


export class EntropyContainer extends React.Component<Props, State> {
private entropyGenerator!: EntropyGeneratorInterface
Expand All @@ -42,7 +43,7 @@ export class EntropyContainer extends React.Component<Props, State> {
this.entropyGenerator = this.setUpEntropyGenerator()
}

private setUpEntropyGenerator(): EntropyGenerator {
private setUpEntropyGenerator(): EntropyGeneratorInterface {
return new EntropyGenerator()
}

Expand Down Expand Up @@ -71,6 +72,7 @@ export class EntropyContainer extends React.Component<Props, State> {
}
const encodedEntropy = this.generateRandomString()
this.setState({ encodedEntropy })
setTimeout(this.submitEntropy, POST_COLLECTION_WAIT_TIME)
}
}

Expand All @@ -88,7 +90,6 @@ export class EntropyContainer extends React.Component<Props, State> {
<EntropyComponent
addPoint={this.addPoint}
progress={this.state.entropyProgress}
submitEntropy={this.submitEntropy}
/>
</React.Fragment>
)
Expand Down
61 changes: 21 additions & 40 deletions tests/ui/components/__snapshots__/entropy.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,19 @@ exports[`Entropy component matches the snapshot when drawn upon and insufficient
>
50 %
</Text>
<View
<Container
style={
Object {
"width": "100%",
"flex": 1,
"flexDirection": "column",
}
}
>
<MaskedImageComponent
addPoint={[Function]}
disabled={false}
/>
</View>
<View
style={
Object {
"bottom": "5%",
"position": "absolute",
}
}
/>
</Container>
</Container>
`;

Expand All @@ -74,26 +67,28 @@ exports[`Entropy component matches the snapshot when not drawn upon and insuffic
>
For security purposes, we need some randomness. Please tap the screen and draw on it randomly
</Text>
<View
<Container
style={
Object {
"width": "100%",
"flex": 1,
"flexDirection": "column",
}
}
>
<View
style={
Object {
"position": "absolute",
}
}
>
<HandAnimationComponent />
</View>
<MaskedImageComponent
addPoint={[Function]}
disabled={false}
/>
</View>
<View
style={
Object {
"bottom": "5%",
"position": "absolute",
}
}
/>
</Container>
</Container>
`;

Expand Down Expand Up @@ -125,32 +120,18 @@ exports[`Entropy component matches the snapshot with when drawn upon and suffici
>
100 %
</Text>
<View
<Container
style={
Object {
"width": "100%",
"flex": 1,
"flexDirection": "column",
}
}
>
<MaskedImageComponent
addPoint={[Function]}
disabled={true}
/>
</View>
<View
style={
Object {
"bottom": "5%",
"position": "absolute",
}
}
>
<JolocomButton
onPress={[Function]}
raised={true}
text="Continue"
upperCase={false}
/>
</View>
</Container>
</Container>
`;
1 change: 0 additions & 1 deletion tests/ui/containers/__snapshots__/entropy.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ exports[`Entropy container mounts correctly and matches the snapshot 1`] = `
<EntropyComponent
addPoint={[Function]}
progress={0}
submitEntropy={[Function]}
/>
</Fragment>
`;
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,11 @@
dependencies:
redux "^4.0.0"

"@types/sjcl@^1.0.28":
version "1.0.28"
resolved "https://registry.yarnpkg.com/@types/sjcl/-/sjcl-1.0.28.tgz#4693eb6943e385e844a70fb25b4699db286c7214"
integrity sha1-RpPraUPjhehEpw+yW0aZ2yhschQ=

"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
Expand Down