From 7d86454ff5cff38848382674e4d9ceee6392e326 Mon Sep 17 00:00:00 2001 From: Keith Date: Mon, 18 Nov 2019 17:52:47 +0800 Subject: [PATCH] feat(neuron-ui): add copy address and copy tx hash context menus on the tx detail view. --- .../src/components/Transaction/index.tsx | 85 ++++++++++++++++++- packages/neuron-ui/src/locales/en.json | 4 +- packages/neuron-ui/src/locales/zh.json | 4 +- .../neuron-ui/src/services/remote/index.ts | 11 +++ 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/packages/neuron-ui/src/components/Transaction/index.tsx b/packages/neuron-ui/src/components/Transaction/index.tsx index 1c9136507f..e73e0b0536 100644 --- a/packages/neuron-ui/src/components/Transaction/index.tsx +++ b/packages/neuron-ui/src/components/Transaction/index.tsx @@ -2,7 +2,14 @@ import React, { useEffect, useState, useMemo, useCallback } from 'react' import { useTranslation } from 'react-i18next' import { Stack, DetailsList, Text, CheckboxVisibility, IColumn, Icon } from 'office-ui-fabric-react' import { currentWallet as currentWalletCache } from 'services/localCache' -import { getTransaction, showErrorMessage, getAllNetworks, getCurrentNetworkID, openExternal } from 'services/remote' +import { + getTransaction, + showErrorMessage, + getAllNetworks, + getCurrentNetworkID, + openExternal, + openContextMenu, +} from 'services/remote' import { ckbCore } from 'services/chain' import { transactionState } from 'states/initStates/chain' @@ -111,7 +118,7 @@ const Transaction = () => { name: t('transaction.index'), minWidth: 60, maxWidth: 60, - onRender: (item?: any | State.DetailedOutput) => { + onRender: (item?: State.DetailedOutput) => { if (item) { return item.outPoint.index } @@ -216,7 +223,7 @@ const Transaction = () => { return } getTransaction({ hash, walletID: currentWallet.id }) - .then((res: any) => { + .then(res => { if (res.status) { setTransaction(res.result) } else { @@ -270,6 +277,75 @@ const Transaction = () => { [t, transaction] ) + const onBasicInfoContextMenu = useCallback( + (property: { label: string; value: string }, index?: number) => { + if (index === 0 && property && property.value) { + const menuTemplate = [ + { + label: t('common.copy-tx-hash'), + click: () => { + window.clipboard.writeText(property.value) + }, + }, + ] + openContextMenu(menuTemplate) + } + }, + [t] + ) + + const onInputContextMenu = useCallback( + (input?: State.DetailedInput) => { + if (input && input.lock && input.lock.args) { + try { + const address = ckbCore.utils.bech32Address(input.lock.args, { + prefix: addressPrefix, + type: ckbCore.utils.AddressType.HashIdx, + codeHashOrCodeHashIndex: '0x00', + }) + const menuTemplate = [ + { + label: t('common.copy-address'), + click: () => { + window.clipboard.writeText(address) + }, + }, + ] + openContextMenu(menuTemplate) + } catch (err) { + console.error(err) + } + } + }, + [addressPrefix, t] + ) + + const onOutputContextMenu = useCallback( + (output?: State.DetailedOutput) => { + if (output && output.lock && output.lock.args) { + try { + const address = ckbCore.utils.bech32Address(output.lock.args, { + prefix: addressPrefix, + type: ckbCore.utils.AddressType.HashIdx, + codeHashOrCodeHashIndex: '0x00', + }) + const menuTemplate = [ + { + label: t('common.copy-address'), + click: () => { + window.clipboard.writeText(address) + }, + }, + ] + openContextMenu(menuTemplate) + } catch (err) { + console.error(err) + } + } + }, + [addressPrefix, t] + ) + if (error.code) { return ( @@ -290,6 +366,7 @@ const Transaction = () => { checkboxVisibility={CheckboxVisibility.hidden} compact isHeaderVisible={false} + onItemContextMenu={onBasicInfoContextMenu} /> @@ -303,6 +380,7 @@ const Transaction = () => { items={transaction.inputs} columns={inputColumns} checkboxVisibility={CheckboxVisibility.hidden} + onItemContextMenu={onInputContextMenu} compact isHeaderVisible /> @@ -317,6 +395,7 @@ const Transaction = () => { items={transaction.outputs} columns={outputColumns} checkboxVisibility={CheckboxVisibility.hidden} + onItemContextMenu={onOutputContextMenu} compact isHeaderVisible /> diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 7521caf19c..41ee775adf 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -241,7 +241,9 @@ "toggle": { "on": "On", "off": "Off" - } + }, + "copy-tx-hash": "Copy transaction hash", + "copy-address": "Copy address" }, "notification-panel": { "title": "Notifications" diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 4809dc1eae..09b33fc319 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -241,7 +241,9 @@ "toggle": { "on": "开", "off": "关" - } + }, + "copy-tx-hash": "复制交易 Hash", + "copy-address": "复制地址" }, "notification-panel": { "title": "通知中心" diff --git a/packages/neuron-ui/src/services/remote/index.ts b/packages/neuron-ui/src/services/remote/index.ts index 4d0f24c5ae..1e03678d54 100644 --- a/packages/neuron-ui/src/services/remote/index.ts +++ b/packages/neuron-ui/src/services/remote/index.ts @@ -81,6 +81,16 @@ export const openExternal = (url: string) => { } } +export const openContextMenu = (template: { label: string; click: Function }[]): void => { + if (!window.remote) { + window.alert(REMOTE_MODULE_NOT_FOUND) + } else { + const { Menu } = window.remote.require('electron') + const menu = Menu.buildFromTemplate(template) + menu.popup() + } +} + export default { getLocale, validateMnemonic, @@ -90,4 +100,5 @@ export default { showOpenDialog, getWinID, openExternal, + openContextMenu, }