Skip to content

Commit

Permalink
Merge pull request #644 from nervosnetwork/rc/v0.1.0-alpha.6
Browse files Browse the repository at this point in the history
[ᚬmaster] Release v0.1.0 alpha.6
  • Loading branch information
ashchan authored Jul 12, 2019
2 parents a3c9f31 + 45fab10 commit c7d64ba
Show file tree
Hide file tree
Showing 42 changed files with 643 additions and 454 deletions.
2 changes: 2 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ jobs:
CSC_KEY_PASSWORD: $(macSiginingCertificatePassword)
WIN_CSC_LINK: $(winSiginingCertificate.secureFilePath)
WIN_CSC_KEY_PASSWORD: $(winSiginingCertificatePassword)
APPLE_ID: $(appleId)
APPLE_ID_PASSWORD: $(appleIdPassword)
- task: GitHubRelease@0
inputs:
gitHubConnection: nervos-bot
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "0.1.0-alpha.5",
"version": "0.1.0-alpha.6",
"npmClient": "yarn",
"useWorkspaces": true
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@nervosnetwork/neuron",
"productName": "Neuron",
"description": "CKB Neuron Wallet",
"version": "0.1.0-alpha.5",
"version": "0.1.0-alpha.6",
"private": true,
"author": {
"name": "Nervos Core Dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/neuron-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nervosnetwork/neuron-ui",
"version": "0.1.0-alpha.5",
"version": "0.1.0-alpha.6",
"private": true,
"author": {
"name": "Nervos Core Dev",
Expand Down
96 changes: 96 additions & 0 deletions packages/neuron-ui/src/components/PasswordRequest/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Stack, Text, Label, Modal, TextField, PrimaryButton, DefaultButton } from 'office-ui-fabric-react'
import { StateWithDispatch, AppActions } from 'states/stateProvider/reducer'
import actionCreators from 'states/stateProvider/actionCreators'

const PasswordRequest = ({
app: {
send: { txID, outputs, description },
passwordRequest: { walletID = '', actionType = null, password = '' },
},
settings: { wallets = [] },
dispatch,
}: React.PropsWithoutRef<StateWithDispatch>) => {
const [t] = useTranslation()
const wallet = useMemo(() => wallets.find(w => w.id === walletID), [walletID, wallets])
const onDismiss = useCallback(() => {
dispatch({
type: AppActions.DismissPasswordRequest,
payload: null,
})
}, [dispatch])

const onConfirm = useCallback(() => {
const params = { id: walletID, password }
switch (actionType) {
case 'delete': {
dispatch(actionCreators.deleteWallet(params))
break
}
case 'backup': {
dispatch(actionCreators.backupWallet(params))
break
}
case 'send': {
dispatch(actionCreators.submitTransaction(txID, walletID, outputs, description, password))
break
}
default: {
break
}
}
}, [dispatch, walletID, password, actionType, txID, description, outputs])

const onChange = useCallback(
(_e, value?: string) => {
if (undefined !== value) {
dispatch({
type: AppActions.UpdatePassword,
payload: value,
})
}
},
[dispatch]
)
const onKeyPress = useCallback(
(e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
if (e.key === 'Enter') {
onConfirm()
}
},
[onConfirm]
)
if (!wallet) {
return null
}
return (
<Modal isOpen={!!actionType} onDismiss={onDismiss}>
{
<Stack
tokens={{ childrenGap: 15 }}
styles={{
root: {
padding: 30,
},
}}
>
<Text variant="xLarge">{t(`password-request.${actionType}.title`, { name: wallet ? wallet.name : '' })}</Text>
<Label required title="password">
{t('password-request.password')}
</Label>
<TextField value={password} type="password" onChange={onChange} autoFocus onKeyPress={onKeyPress} />
<Stack horizontalAlign="end" horizontal tokens={{ childrenGap: 15 }}>
<DefaultButton onClick={onDismiss}>{t('common.cancel')}</DefaultButton>
<PrimaryButton onClick={onConfirm} disabled={!password}>
{t('common.confirm')}
</PrimaryButton>
</Stack>
</Stack>
}
</Modal>
)
}

PasswordRequest.displayName = 'PasswordRequest'
export default PasswordRequest
102 changes: 78 additions & 24 deletions packages/neuron-ui/src/components/Send/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,50 @@
import React, { useCallback, useEffect, useMemo } from 'react'
import React, { useCallback, useEffect } from 'react'
import { IDropdownOption } from 'office-ui-fabric-react'

import { AppActions, StateDispatch } from 'states/stateProvider/reducer'
import actionCreators from 'states/stateProvider/actionCreators'

import { Message } from 'utils/const'
import { verifyAddress } from 'utils/validators'
import { TransactionOutput } from '.'

const validateTransactionParams = ({ items, dispatch }: { items: TransactionOutput[]; dispatch: StateDispatch }) => {
const errorAction = {
type: AppActions.AddNotification,
payload: {
type: 'warning',
timestamp: Date.now(),
content: Message.AtLeastOneAddressNeeded,
},
}
if (!items.length || !items[0].address) {
dispatch(errorAction)
return false
}
const invalid = items.some(
(item): boolean => {
if (!verifyAddress(item.address)) {
errorAction.payload.content = Message.InvalidAddress
return true
}
if (Number.isNaN(+item.amount) || +item.amount < 0) {
errorAction.payload.content = Message.InvalidAmount
return true
}
const [, decimal = ''] = item.amount.split('.')
if (decimal.length > 8) {
errorAction.payload.content = Message.InvalidAmount
return true
}
return false
}
)
if (invalid) {
dispatch(errorAction)
return false
}
return true
}

const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
useCallback(
(field: string) => (idx: number) => (value: string) => {
Expand All @@ -14,7 +53,7 @@ const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
payload: {
idx,
item: {
[field]: value,
[field]: value.trim(),
},
},
})
Expand All @@ -41,24 +80,38 @@ const useRemoveTransactionOutput = (dispatch: StateDispatch) =>
[dispatch]
)

const useOnSubmit = (dispatch: StateDispatch) =>
const useOnSubmit = (items: TransactionOutput[], dispatch: StateDispatch) =>
useCallback(
(id: string = '', walletID: string = '', items: TransactionOutput[] = [], description: string = '') => () => {
setTimeout(() => {
dispatch(actionCreators.submitTransaction(id, walletID, items, description))
}, 10)
(walletID: string = '') => () => {
if (validateTransactionParams({ items, dispatch })) {
dispatch({
type: AppActions.UpdateTransactionID,
payload: null,
})
dispatch({
type: AppActions.RequestPassword,
payload: {
walletID,
actionType: 'send',
},
})
}
},
[dispatch]
[dispatch, items]
)

const useOnItemChange = (updateTransactionOutput: Function) => (field: string = '', idx: number = -1) => (
_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
value?: string
) => {
if (undefined !== value) {
updateTransactionOutput(field)(idx)(value)
}
}
const useOnItemChange = (updateTransactionOutput: Function) =>
useCallback(
(field: string = '', idx: number = -1) => (
_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
value?: string
) => {
if (undefined !== value) {
updateTransactionOutput(field)(idx)(value)
}
},
[updateTransactionOutput]
)

const useCapacityUnitChange = (updateTransactionOutput: Function) =>
useCallback(
Expand All @@ -76,7 +129,7 @@ const useUpdateTransactionPrice = (dispatch: StateDispatch) =>
if (undefined !== value) {
dispatch({
type: AppActions.UpdateSendPrice,
payload: value,
payload: value.trim(),
})
}
},
Expand Down Expand Up @@ -105,11 +158,16 @@ const clear = (dispatch: StateDispatch) => {

const useClear = (dispatch: StateDispatch) => useCallback(() => clear(dispatch), [dispatch])

export const useInitialize = (address: string, dispatch: React.Dispatch<any>, history: any) => {
export const useInitialize = (
address: string,
items: TransactionOutput[],
dispatch: React.Dispatch<any>,
history: any
) => {
const updateTransactionOutput = useUpdateTransactionOutput(dispatch)
const onItemChange = useOnItemChange(updateTransactionOutput)
const onCapacityUnitChange = useCapacityUnitChange(updateTransactionOutput)
const onSubmit = useOnSubmit(dispatch)
const onSubmit = useOnSubmit(items, dispatch)
const addTransactionOutput = useAddTransactionOutput(dispatch)
const removeTransactionOutput = useRemoveTransactionOutput(dispatch)
const updateTransactionPrice = useUpdateTransactionPrice(dispatch)
Expand All @@ -125,11 +183,7 @@ export const useInitialize = (address: string, dispatch: React.Dispatch<any>, hi
}
}, [address, dispatch, history, updateTransactionOutput])

// TODO: generate new id on every submission
const id = useMemo(() => Math.round(Math.random() * 1000).toString(), [])

return {
id,
updateTransactionOutput,
onItemChange,
onCapacityUnitChange,
Expand Down
10 changes: 2 additions & 8 deletions packages/neuron-ui/src/components/Send/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const Send = ({
}: React.PropsWithoutRef<StateWithDispatch & RouteComponentProps<{ address: string }>>) => {
const { t } = useTranslation()
const {
id,
updateTransactionOutput,
onItemChange,
onSubmit,
Expand All @@ -49,7 +48,7 @@ const Send = ({
updateTransactionPrice,
onDescriptionChange,
onClear,
} = useInitialize(address, dispatch, history)
} = useInitialize(address, send.outputs, dispatch, history)

return (
<Stack verticalFill tokens={{ childrenGap: 15 }}>
Expand Down Expand Up @@ -153,12 +152,7 @@ const Send = ({
{sending ? (
<Spinner />
) : (
<PrimaryButton
type="submit"
onClick={onSubmit(id, walletID, send.outputs, send.description)}
disabled={sending}
text={t('send.send')}
/>
<PrimaryButton type="submit" onClick={onSubmit(walletID)} disabled={sending} text={t('send.send')} />
)}
</Stack>
</Stack>
Expand Down
1 change: 1 addition & 0 deletions packages/neuron-ui/src/components/WalletSetting/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const WalletSetting = ({
key: wallet.id,
text: wallet.name,
checked: wallet.id === currentID,
disabled: wallet.id === currentID,
onRenderLabel: ({ text }: IChoiceGroupOption) => {
return (
<span className="ms-ChoiceFieldLabel" onContextMenu={onContextMenu(wallet.id)}>
Expand Down
Loading

0 comments on commit c7d64ba

Please sign in to comment.