Skip to content

Commit

Permalink
feat: Offline Sign with new ui (#2638)
Browse files Browse the repository at this point in the history
  • Loading branch information
devchenyan authored Apr 23, 2023
1 parent 945a63d commit c6f3be3
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 179 deletions.
149 changes: 65 additions & 84 deletions packages/neuron-ui/src/components/OfflineSign/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { useRef, useCallback, useMemo, useState, useEffect } from 'react'
import React, { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { isSuccessResponse, RoutePath, useDidMount } from 'utils'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
import Dialog from 'widgets/Dialog'
import { addNotification, useDispatch, useState as useGlobalState } from 'states'
import { broadcastTransaction, getCurrentWallet, OfflineSignStatus } from 'services/remote'
import { ReactComponent as HardWalletIcon } from 'widgets/Icons/HardWallet.svg'
Expand All @@ -12,7 +11,6 @@ import OfflineSignDialog from '../OfflineSignDialog'
import styles from './offlineSign.module.scss'

const OfflineSign = () => {
const dialogRef = useRef<HTMLDialogElement | null>(null)
const {
app: { loadedTransaction = {} },
} = useGlobalState()
Expand Down Expand Up @@ -48,41 +46,33 @@ const OfflineSign = () => {
navigate(-1)
}, [navigate])

const onSign = useCallback(
(e: React.FormEvent) => {
e.preventDefault()
setIsSigning(true)
},
[setIsSigning]
)

const onBroadcast = useCallback(
async (e: React.FormEvent) => {
e.preventDefault()
setIsBroadcasting(true)
try {
const res = await broadcastTransaction({
...json,
walletID: wallet!.id,
})
if (isSuccessResponse(res)) {
navigate(RoutePath.History)
} else {
addNotification({
type: 'alert',
timestamp: +new Date(),
code: res.status,
content: typeof res.message === 'string' ? res.message : res.message.content,
meta: typeof res.message === 'string' ? undefined : res.message.meta,
})(dispatch)
onBack()
}
} finally {
setIsBroadcasting(false)
const onSign = useCallback(() => {
setIsSigning(true)
}, [setIsSigning])

const onBroadcast = useCallback(async () => {
setIsBroadcasting(true)
try {
const res = await broadcastTransaction({
...json,
walletID: wallet!.id,
})
if (isSuccessResponse(res)) {
navigate(RoutePath.History)
} else {
addNotification({
type: 'alert',
timestamp: +new Date(),
code: res.status,
content: typeof res.message === 'string' ? res.message : res.message.content,
meta: typeof res.message === 'string' ? undefined : res.message.meta,
})(dispatch)
onBack()
}
},
[wallet, json, navigate, dispatch, onBack]
)
} finally {
setIsBroadcasting(false)
}
}, [wallet, json, navigate, dispatch, onBack])

useDidMount(() => {
getCurrentWallet().then(res => {
Expand All @@ -92,12 +82,6 @@ const OfflineSign = () => {
})
})

useEffect(() => {
if (!isSigning && dialogRef.current && !dialogRef.current.open) {
dialogRef.current.showModal()
}
}, [isSigning])

const signDialogOnDismiss = useCallback(() => {
setIsSigning(false)
}, [])
Expand All @@ -109,46 +93,43 @@ const OfflineSign = () => {
}

return (
<dialog ref={dialogRef} className={styles.dialog}>
<form className={styles.container}>
<header className={styles.title}>{t('offline-sign.title')}</header>
<section className={styles.main}>
<table>
<tbody>
<tr>
<td className={styles.first}>{t('offline-sign.json-file')}</td>
<td>{filePath}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.status.label')}</td>
<td>{status}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.wallet')}</td>
<td>
{wallet?.device ? <HardWalletIcon /> : null}
<span>{wallet?.name ?? ''}</span>
</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.content')}</td>
</tr>
</tbody>
</table>
<textarea disabled value={jsonContent} className={styles.textarea} />
</section>
<footer className={styles.footer}>
<Button type="cancel" label={t('offline-sign.actions.cancel')} onClick={onBack} />
{signStatus === OfflineSignStatus.Signed ? (
<Button type="submit" label={t('offline-sign.actions.broadcast')} onClick={onBroadcast}>
{isBroadCasting ? <Spinner /> : (t('offline-sign.actions.broadcast') as string)}
</Button>
) : (
<Button type="submit" label={t('offline-sign.actions.sign')} onClick={onSign} />
)}
</footer>
</form>
</dialog>
<Dialog
show={!isSigning}
title={t('offline-sign.title')}
cancelText={t('offline-sign.actions.cancel')}
onCancel={onBack}
confirmText={
signStatus === OfflineSignStatus.Signed ? t('offline-sign.actions.broadcast') : t('offline-sign.actions.sign')
}
isLoading={signStatus === OfflineSignStatus.Signed && isBroadCasting}
onConfirm={signStatus === OfflineSignStatus.Signed ? onBroadcast : onSign}
>
<div className={styles.main}>
<table>
<tbody>
<tr>
<td className={styles.first}>{t('offline-sign.json-file')}</td>
<td>{filePath}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.status.label')}</td>
<td>{status}</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.wallet')}</td>
<td>
{wallet?.device ? <HardWalletIcon /> : null}
<span>{wallet?.name ?? ''}</span>
</td>
</tr>
<tr>
<td className={styles.first}>{t('offline-sign.content')}</td>
</tr>
</tbody>
</table>
<textarea disabled value={jsonContent} className={styles.textarea} />
</div>
</Dialog>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,68 +1,32 @@
@import '../../styles/mixin.scss';

.dialog {
@include dialog-container;
padding: 30px 50px;
min-height: 245px;
width: 600px;

.container {
display: flex;
flex-direction: column;

.main {
flex: 1;
margin: 25px 0;
tr {
td {
font-size: 14px;
svg {
width: 14px;
height: 14px;
margin-right: 4px;
position: relative;
top: 2px;
}
}
.first {
padding-right: 30px;
color: #434343;
}
.main {
tr {
td {
font-size: 14px;
line-height: 26px;
color: var(--main-text-color);
svg {
width: 14px;
height: 14px;
margin-right: 4px;
position: relative;
top: 2px;
}
}
}

&::backdrop {
@include overlay;
}

.footer {
@include dialog-footer;
flex-shrink: 0;

button {
margin-left: 10px;
.first {
padding-right: 24px;
color: var(--input-second-color);
}
}
}

.content {
color: #434343;
font-size: 14px;
margin-bottom: 7px;
}

.title {
font-size: 1.125rem;
line-height: 1.375rem;
font-weight: bold;
letter-spacing: 0.9px;
margin: 0;
}

.textarea {
margin-top: 7px;
width: 100%;
height: 140px;
color: var(--main-text-color);
margin-top: 17px;
width: 648px;
height: 206px;
resize: none;
background: var(--secondary-background-color);
border: 1px solid var(--divide-line-color);
border-radius: 8px;
padding: 16px;
}
50 changes: 16 additions & 34 deletions packages/neuron-ui/src/components/OfflineSignDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react'
import React, { useState, useCallback, useMemo, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import TextField from 'widgets/TextField'
import Spinner from 'widgets/Spinner'
import Dialog from 'widgets/Dialog'
import HardwareSign from 'components/HardwareSign'
import { ErrorCode, RoutePath, isSuccessResponse, errorFormatter, useDidMount } from 'utils'
import { ErrorCode, RoutePath, isSuccessResponse, errorFormatter } from 'utils'

import {
useState as useGlobalState,
Expand Down Expand Up @@ -40,7 +39,6 @@ const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss }:
const dispatch = useDispatch()
const [t] = useTranslation()
const navigate = useNavigate()
const dialogRef = useRef<HTMLDialogElement | null>(null)

const [password, setPassword] = useState('')
const [error, setError] = useState('')
Expand All @@ -51,12 +49,6 @@ const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss }:
setError('')
}, [signType, setError, setPassword])

useDidMount(() => {
if (dialogRef.current) {
dialogRef.current.showModal()
}
})

const disabled = !password || isSigning

const signAndExport = useCallback(async () => {
Expand Down Expand Up @@ -207,29 +199,19 @@ const OfflineSignDialog = ({ isBroadcast, wallet, offlineSignJSON, onDismiss }:
}

return (
<dialog ref={dialogRef} className={styles.dialog}>
<form onSubmit={onSubmit}>
<h2 className={styles.title}>{title}</h2>
<TextField
label={t('password-request.password')}
value={password}
field="password"
type="password"
title={t('password-request.password')}
onChange={onChange}
autoFocus
required
className={styles.passwordInput}
error={error}
/>
<div className={styles.footer}>
<Button label={t('common.cancel')} type="cancel" onClick={onDismiss} />
<Button label={t('common.confirm')} type="submit" disabled={disabled}>
{isSigning ? <Spinner /> : (t('common.confirm') as string)}
</Button>
</div>
</form>
</dialog>
<Dialog show title={title} onCancel={onDismiss} onConfirm={onSubmit} disabled={disabled} isLoading={isSigning}>
<TextField
label={t('password-request.password')}
value={password}
field="password"
type="password"
title={t('password-request.password')}
onChange={onChange}
autoFocus
className={styles.passwordInput}
error={error}
/>
</Dialog>
)
}

Expand Down
3 changes: 1 addition & 2 deletions packages/neuron-ui/src/widgets/Button/button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@
vertical-align: sub;
margin-left: 4px;
& > path {
fill: white;
fill: var(--primary-text-color);
}
}
}

1 comment on commit c6f3be3

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

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

Packaging for test is done in 4776688029

Please sign in to comment.