Skip to content

Commit c7d64ba

Browse files
authored
Merge pull request #644 from nervosnetwork/rc/v0.1.0-alpha.6
[ᚬmaster] Release v0.1.0 alpha.6
2 parents a3c9f31 + 45fab10 commit c7d64ba

File tree

42 files changed

+643
-454
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+643
-454
lines changed

azure-pipelines.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ jobs:
134134
CSC_KEY_PASSWORD: $(macSiginingCertificatePassword)
135135
WIN_CSC_LINK: $(winSiginingCertificate.secureFilePath)
136136
WIN_CSC_KEY_PASSWORD: $(winSiginingCertificatePassword)
137+
APPLE_ID: $(appleId)
138+
APPLE_ID_PASSWORD: $(appleIdPassword)
137139
- task: GitHubRelease@0
138140
inputs:
139141
gitHubConnection: nervos-bot

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"packages": [
33
"packages/*"
44
],
5-
"version": "0.1.0-alpha.5",
5+
"version": "0.1.0-alpha.6",
66
"npmClient": "yarn",
77
"useWorkspaces": true
88
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@nervosnetwork/neuron",
33
"productName": "Neuron",
44
"description": "CKB Neuron Wallet",
5-
"version": "0.1.0-alpha.5",
5+
"version": "0.1.0-alpha.6",
66
"private": true,
77
"author": {
88
"name": "Nervos Core Dev",

packages/neuron-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nervosnetwork/neuron-ui",
3-
"version": "0.1.0-alpha.5",
3+
"version": "0.1.0-alpha.6",
44
"private": true,
55
"author": {
66
"name": "Nervos Core Dev",
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import React, { useCallback, useMemo } from 'react'
2+
import { useTranslation } from 'react-i18next'
3+
import { Stack, Text, Label, Modal, TextField, PrimaryButton, DefaultButton } from 'office-ui-fabric-react'
4+
import { StateWithDispatch, AppActions } from 'states/stateProvider/reducer'
5+
import actionCreators from 'states/stateProvider/actionCreators'
6+
7+
const PasswordRequest = ({
8+
app: {
9+
send: { txID, outputs, description },
10+
passwordRequest: { walletID = '', actionType = null, password = '' },
11+
},
12+
settings: { wallets = [] },
13+
dispatch,
14+
}: React.PropsWithoutRef<StateWithDispatch>) => {
15+
const [t] = useTranslation()
16+
const wallet = useMemo(() => wallets.find(w => w.id === walletID), [walletID, wallets])
17+
const onDismiss = useCallback(() => {
18+
dispatch({
19+
type: AppActions.DismissPasswordRequest,
20+
payload: null,
21+
})
22+
}, [dispatch])
23+
24+
const onConfirm = useCallback(() => {
25+
const params = { id: walletID, password }
26+
switch (actionType) {
27+
case 'delete': {
28+
dispatch(actionCreators.deleteWallet(params))
29+
break
30+
}
31+
case 'backup': {
32+
dispatch(actionCreators.backupWallet(params))
33+
break
34+
}
35+
case 'send': {
36+
dispatch(actionCreators.submitTransaction(txID, walletID, outputs, description, password))
37+
break
38+
}
39+
default: {
40+
break
41+
}
42+
}
43+
}, [dispatch, walletID, password, actionType, txID, description, outputs])
44+
45+
const onChange = useCallback(
46+
(_e, value?: string) => {
47+
if (undefined !== value) {
48+
dispatch({
49+
type: AppActions.UpdatePassword,
50+
payload: value,
51+
})
52+
}
53+
},
54+
[dispatch]
55+
)
56+
const onKeyPress = useCallback(
57+
(e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
58+
if (e.key === 'Enter') {
59+
onConfirm()
60+
}
61+
},
62+
[onConfirm]
63+
)
64+
if (!wallet) {
65+
return null
66+
}
67+
return (
68+
<Modal isOpen={!!actionType} onDismiss={onDismiss}>
69+
{
70+
<Stack
71+
tokens={{ childrenGap: 15 }}
72+
styles={{
73+
root: {
74+
padding: 30,
75+
},
76+
}}
77+
>
78+
<Text variant="xLarge">{t(`password-request.${actionType}.title`, { name: wallet ? wallet.name : '' })}</Text>
79+
<Label required title="password">
80+
{t('password-request.password')}
81+
</Label>
82+
<TextField value={password} type="password" onChange={onChange} autoFocus onKeyPress={onKeyPress} />
83+
<Stack horizontalAlign="end" horizontal tokens={{ childrenGap: 15 }}>
84+
<DefaultButton onClick={onDismiss}>{t('common.cancel')}</DefaultButton>
85+
<PrimaryButton onClick={onConfirm} disabled={!password}>
86+
{t('common.confirm')}
87+
</PrimaryButton>
88+
</Stack>
89+
</Stack>
90+
}
91+
</Modal>
92+
)
93+
}
94+
95+
PasswordRequest.displayName = 'PasswordRequest'
96+
export default PasswordRequest

packages/neuron-ui/src/components/Send/hooks.ts

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,50 @@
1-
import React, { useCallback, useEffect, useMemo } from 'react'
1+
import React, { useCallback, useEffect } from 'react'
22
import { IDropdownOption } from 'office-ui-fabric-react'
33

44
import { AppActions, StateDispatch } from 'states/stateProvider/reducer'
5-
import actionCreators from 'states/stateProvider/actionCreators'
65

6+
import { Message } from 'utils/const'
7+
import { verifyAddress } from 'utils/validators'
78
import { TransactionOutput } from '.'
89

10+
const validateTransactionParams = ({ items, dispatch }: { items: TransactionOutput[]; dispatch: StateDispatch }) => {
11+
const errorAction = {
12+
type: AppActions.AddNotification,
13+
payload: {
14+
type: 'warning',
15+
timestamp: Date.now(),
16+
content: Message.AtLeastOneAddressNeeded,
17+
},
18+
}
19+
if (!items.length || !items[0].address) {
20+
dispatch(errorAction)
21+
return false
22+
}
23+
const invalid = items.some(
24+
(item): boolean => {
25+
if (!verifyAddress(item.address)) {
26+
errorAction.payload.content = Message.InvalidAddress
27+
return true
28+
}
29+
if (Number.isNaN(+item.amount) || +item.amount < 0) {
30+
errorAction.payload.content = Message.InvalidAmount
31+
return true
32+
}
33+
const [, decimal = ''] = item.amount.split('.')
34+
if (decimal.length > 8) {
35+
errorAction.payload.content = Message.InvalidAmount
36+
return true
37+
}
38+
return false
39+
}
40+
)
41+
if (invalid) {
42+
dispatch(errorAction)
43+
return false
44+
}
45+
return true
46+
}
47+
948
const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
1049
useCallback(
1150
(field: string) => (idx: number) => (value: string) => {
@@ -14,7 +53,7 @@ const useUpdateTransactionOutput = (dispatch: StateDispatch) =>
1453
payload: {
1554
idx,
1655
item: {
17-
[field]: value,
56+
[field]: value.trim(),
1857
},
1958
},
2059
})
@@ -41,24 +80,38 @@ const useRemoveTransactionOutput = (dispatch: StateDispatch) =>
4180
[dispatch]
4281
)
4382

44-
const useOnSubmit = (dispatch: StateDispatch) =>
83+
const useOnSubmit = (items: TransactionOutput[], dispatch: StateDispatch) =>
4584
useCallback(
46-
(id: string = '', walletID: string = '', items: TransactionOutput[] = [], description: string = '') => () => {
47-
setTimeout(() => {
48-
dispatch(actionCreators.submitTransaction(id, walletID, items, description))
49-
}, 10)
85+
(walletID: string = '') => () => {
86+
if (validateTransactionParams({ items, dispatch })) {
87+
dispatch({
88+
type: AppActions.UpdateTransactionID,
89+
payload: null,
90+
})
91+
dispatch({
92+
type: AppActions.RequestPassword,
93+
payload: {
94+
walletID,
95+
actionType: 'send',
96+
},
97+
})
98+
}
5099
},
51-
[dispatch]
100+
[dispatch, items]
52101
)
53102

54-
const useOnItemChange = (updateTransactionOutput: Function) => (field: string = '', idx: number = -1) => (
55-
_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
56-
value?: string
57-
) => {
58-
if (undefined !== value) {
59-
updateTransactionOutput(field)(idx)(value)
60-
}
61-
}
103+
const useOnItemChange = (updateTransactionOutput: Function) =>
104+
useCallback(
105+
(field: string = '', idx: number = -1) => (
106+
_e: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
107+
value?: string
108+
) => {
109+
if (undefined !== value) {
110+
updateTransactionOutput(field)(idx)(value)
111+
}
112+
},
113+
[updateTransactionOutput]
114+
)
62115

63116
const useCapacityUnitChange = (updateTransactionOutput: Function) =>
64117
useCallback(
@@ -76,7 +129,7 @@ const useUpdateTransactionPrice = (dispatch: StateDispatch) =>
76129
if (undefined !== value) {
77130
dispatch({
78131
type: AppActions.UpdateSendPrice,
79-
payload: value,
132+
payload: value.trim(),
80133
})
81134
}
82135
},
@@ -105,11 +158,16 @@ const clear = (dispatch: StateDispatch) => {
105158

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

108-
export const useInitialize = (address: string, dispatch: React.Dispatch<any>, history: any) => {
161+
export const useInitialize = (
162+
address: string,
163+
items: TransactionOutput[],
164+
dispatch: React.Dispatch<any>,
165+
history: any
166+
) => {
109167
const updateTransactionOutput = useUpdateTransactionOutput(dispatch)
110168
const onItemChange = useOnItemChange(updateTransactionOutput)
111169
const onCapacityUnitChange = useCapacityUnitChange(updateTransactionOutput)
112-
const onSubmit = useOnSubmit(dispatch)
170+
const onSubmit = useOnSubmit(items, dispatch)
113171
const addTransactionOutput = useAddTransactionOutput(dispatch)
114172
const removeTransactionOutput = useRemoveTransactionOutput(dispatch)
115173
const updateTransactionPrice = useUpdateTransactionPrice(dispatch)
@@ -125,11 +183,7 @@ export const useInitialize = (address: string, dispatch: React.Dispatch<any>, hi
125183
}
126184
}, [address, dispatch, history, updateTransactionOutput])
127185

128-
// TODO: generate new id on every submission
129-
const id = useMemo(() => Math.round(Math.random() * 1000).toString(), [])
130-
131186
return {
132-
id,
133187
updateTransactionOutput,
134188
onItemChange,
135189
onCapacityUnitChange,

packages/neuron-ui/src/components/Send/index.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ const Send = ({
4040
}: React.PropsWithoutRef<StateWithDispatch & RouteComponentProps<{ address: string }>>) => {
4141
const { t } = useTranslation()
4242
const {
43-
id,
4443
updateTransactionOutput,
4544
onItemChange,
4645
onSubmit,
@@ -49,7 +48,7 @@ const Send = ({
4948
updateTransactionPrice,
5049
onDescriptionChange,
5150
onClear,
52-
} = useInitialize(address, dispatch, history)
51+
} = useInitialize(address, send.outputs, dispatch, history)
5352

5453
return (
5554
<Stack verticalFill tokens={{ childrenGap: 15 }}>
@@ -153,12 +152,7 @@ const Send = ({
153152
{sending ? (
154153
<Spinner />
155154
) : (
156-
<PrimaryButton
157-
type="submit"
158-
onClick={onSubmit(id, walletID, send.outputs, send.description)}
159-
disabled={sending}
160-
text={t('send.send')}
161-
/>
155+
<PrimaryButton type="submit" onClick={onSubmit(walletID)} disabled={sending} text={t('send.send')} />
162156
)}
163157
</Stack>
164158
</Stack>

packages/neuron-ui/src/components/WalletSetting/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const WalletSetting = ({
5959
key: wallet.id,
6060
text: wallet.name,
6161
checked: wallet.id === currentID,
62+
disabled: wallet.id === currentID,
6263
onRenderLabel: ({ text }: IChoiceGroupOption) => {
6364
return (
6465
<span className="ms-ChoiceFieldLabel" onContextMenu={onContextMenu(wallet.id)}>

0 commit comments

Comments
 (0)