Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
41 changes: 19 additions & 22 deletions packages/neuron-ui/src/components/ClearCache/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React, { useEffect, useCallback, useState, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
import { ReactComponent as Attention } from 'widgets/Icons/Attention.svg'
import WarningIcon from 'widgets/Icons/Warning.png'
import { StateDispatch, addPopup } from 'states'
import { clearCellCache } from 'services/remote'
import { cacheClearDate } from 'services/localCache'
import { isSuccessResponse, useDialog, uniformTimeFormatter } from 'utils'

import { Tooltip } from 'widgets/Icons/icon'
import styles from './style.module.scss'

const I18N_PATH = 'settings.clear-cache'
Expand Down Expand Up @@ -71,28 +71,25 @@ const ClearCache = ({ dispatch }: { dispatch: StateDispatch }) => {

return (
<>
<div className={`${styles.clearCache} ${styles.detail}`}>
{clearedDate ? (
<div className={styles.date}>{t('settings.general.cache-cleared-on', { date: clearedDate })}</div>
) : null}
<div className={styles.desc}>
<Attention />
{t('settings.general.clear-cache-description')}
</div>
</div>
<div className={`${styles.clearCache} ${styles.action}`}>
<Button label={t(`settings.general.clear-cache`)} onClick={showDialog} disabled={isClearing}>
{isClearing ? (
<Spinner
label={t('settings.general.clear-cache')}
labelPosition="right"
styles={{ root: { marginRight: 5 } }}
/>
) : (
(t('settings.general.clear-cache') as string)
)}
</Button>
<div className={styles.clearCache}>
{t('settings.data.cache')}
<span className={styles.tooltip} data-tooltip={t('settings.data.clear-cache-description')}>
<Tooltip />
</span>
:
</div>
<div className={styles.clearedDate}>{t('settings.data.cache-cleared-on', { date: clearedDate })}</div>
<Button label={t('settings.data.clear-cache')} onClick={showDialog} disabled={isClearing}>
{isClearing ? (
<Spinner
label={t('settings.data.clearing-cache')}
labelPosition="right"
styles={{ root: { marginRight: 5 } }}
/>
) : (
(t('settings.data.clear-cache') as string)
)}
</Button>
<dialog ref={dialogRef} className={styles.dialog}>
<img src={WarningIcon} alt="warning" className={styles.warningIcon} />
<div className={styles.title}>{t(`${I18N_PATH}.title`)}</div>
Expand Down
48 changes: 27 additions & 21 deletions packages/neuron-ui/src/components/ClearCache/style.module.scss
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
@import '../../styles//mixin.scss';

.clearCache {
&.detail {
grid-area: clear-cache-detail;
.date {
display: flex;
align-items: center;
font-size: 0.875rem;
height: 1.125rem;
margin-bottom: 5px;
}
.desc {
display: flex;
font-size: 0.6875rem;
color: #666;
font-weight: bold;
display: flex;

.tooltip {
position: relative;
display: inline-flex;
align-items: center;
padding-left: 4px;

&::after {
display: none;
position: absolute;
left: -20px;
top: 120%;
content: attr(data-tooltip);
padding: 4px 12px;
border-radius: 6px;
background: #cccccc99;
font-weight: 300;
width: 600px;
}
svg {
height: 0.6875rem;
width: 0.6875rem;
filter: grayscale(1) opacity(0.6);
margin: 2px 5px 0 0;

&:hover::after {
display: block;
}
}
&.action {
grid-area: clear-cache-action;
}
}

.clearedDate {
font-size: 12px;
}

.dialog {
Expand Down
70 changes: 70 additions & 0 deletions packages/neuron-ui/src/components/DataSetting/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
getCkbNodeDataPath,
getIndexerDataPath,
invokeShowOpenDialog,
startProcessMonitor,
stopProcessMonitor,
setCkbNodeDataPath,
setIndexerDataPath,
} from 'services/remote'
import { isSuccessResponse, useDialogWrapper, useDidMount } from 'utils'

export const useDataPath = (
getPath: typeof getCkbNodeDataPath | typeof getIndexerDataPath,
setPath: typeof setCkbNodeDataPath | typeof setIndexerDataPath,
type: Parameters<typeof stopProcessMonitor>[0]
) => {
const [t] = useTranslation()
const [prevPath, setPrevPath] = useState<string>()
const [currentPath, setCurrentPath] = useState<string | undefined>()
const { dialogRef, openDialog, closeDialog } = useDialogWrapper()
useDidMount(() => {
getPath(undefined).then(res => {
if (isSuccessResponse(res)) {
setPrevPath(res.result!)
}
})
})
const onSetting = useCallback(() => {
invokeShowOpenDialog({
buttonLabel: t('settings.data.set', { lng: navigator.language }),
Comment thread
Keith-CY marked this conversation as resolved.
properties: ['openDirectory', 'createDirectory', 'promptToCreate', 'treatPackageAsDirectory'],
}).then(res => {
if (isSuccessResponse(res) && !res.result?.canceled && res.result?.filePaths?.length) {
setCurrentPath(res.result?.filePaths?.[0])
stopProcessMonitor(type).then(stopRes => {
if (isSuccessResponse(stopRes)) {
openDialog()
}
})
}
})
}, [t, type])
const onCancel = useCallback(() => {
startProcessMonitor(type).then(res => {
if (isSuccessResponse(res)) {
closeDialog()
}
})
}, [closeDialog, type])
const onConfirm = useCallback(() => {
setPath(currentPath!).then(res => {
if (isSuccessResponse(res)) {
setPrevPath(currentPath)
closeDialog()
}
})
}, [currentPath, closeDialog, setPrevPath, setPath])
return {
prevPath,
currentPath,
onSetting,
dialogRef,
onCancel,
onConfirm,
}
}

export default useDataPath
66 changes: 66 additions & 0 deletions packages/neuron-ui/src/components/DataSetting/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@import '../../styles/mixin.scss';

.root {
margin-top: 20px;
display: grid;
grid-template-columns: auto 1fr 140px;
grid-gap: 30px 20px;
align-items: center;

.name {
font-weight: bold;
}

.content {
font-size: 12px;
word-break: break-all;
}

button {
line-height: 1;
height: 1.625rem;
}
}

.dialog {
@include dialog-container;
padding: 30px 50px;

.describe {
word-break: break-all;
font-size: 14px;
}

.attention {
position: relative;
padding-left: 1rem;
font-size: 0.75rem;
letter-spacing: 0.5px;
margin: 14px 0 20px 0;
color: #666;

svg {
position: absolute;
left: 0;
top: 0.13rem;
filter: grayscale(1) opacity(0.6);
width: 0.625rem;
height: 0.625rem;
}
}

.action {
padding-top: 16px;
display: flex;
justify-content: space-between;
}
}

.path {
display: flex;
align-items: center;

& > svg {
flex-shrink: 0;
}
}
Comment thread
yanguoyu marked this conversation as resolved.
92 changes: 92 additions & 0 deletions packages/neuron-ui/src/components/DataSetting/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import ClearCache from 'components/ClearCache'
import { useDispatch } from 'states'
import { getCkbNodeDataPath, getIndexerDataPath, setCkbNodeDataPath, setIndexerDataPath } from 'services/remote'
import { ReactComponent as Attention } from 'widgets/Icons/ExperimentalAttention.svg'
import CopyZone from 'widgets/CopyZone'
import { OpenFolder } from 'widgets/Icons/icon'
import { shell } from 'electron'
import { useDataPath } from './hooks'

import styles from './index.module.scss'

const itemProps: Record<
'ckbNode' | 'indexer',
{
type: 'ckb' | 'ckb-indexer'
getPath: typeof getCkbNodeDataPath | typeof getIndexerDataPath
setPath: typeof setCkbNodeDataPath | typeof setIndexerDataPath
titleI18nKey: string
tipI18nKey: string
}
> = {
ckbNode: {
type: 'ckb',
getPath: getCkbNodeDataPath,
setPath: setCkbNodeDataPath,
titleI18nKey: 'ckb-node-data',
tipI18nKey: 'remove-ckb-data-tip',
},
indexer: {
type: 'ckb-indexer',
getPath: getIndexerDataPath,
setPath: setIndexerDataPath,
titleI18nKey: 'ckb-indexer-data',
tipI18nKey: 'remove-indexer-data-tip',
},
}

const SetItem = ({ type }: { type: keyof typeof itemProps }) => {
const props = itemProps[type]
const [t] = useTranslation()
const { onSetting, prevPath, currentPath, dialogRef, onCancel, onConfirm } = useDataPath(
props.getPath,
props.setPath,
props.type
)
const openPath = useCallback(() => {
if (prevPath) {
shell.openPath(prevPath!)
}
}, [prevPath])
return (
<>
<div className={styles.name}>{t(`settings.data.${props.titleI18nKey}`)}:</div>
<div className={styles.path}>
<CopyZone content={prevPath || ''} className={styles.content}>
{prevPath}
</CopyZone>
<OpenFolder onClick={openPath} />
</div>
<Button label={t('settings.data.set')} onClick={onSetting} />
<dialog ref={dialogRef} className={styles.dialog}>
<div className={styles.describe}>{t(`settings.data.${props.tipI18nKey}`, { prevPath, currentPath })}</div>
<div className={styles.attention}>
<Attention />
{t('settings.data.resync-describe')}
</div>
<div className={styles.action}>
<Button label={t('settings.data.cancel')} type="cancel" onClick={onCancel} />
<Button label={t('settings.data.move-data-finish')} type="primary" onClick={onConfirm} />
<Button label={t('settings.data.re-sync')} type="primary" onClick={onConfirm} />
</div>
</dialog>
</>
)
}

const DataSetting = () => {
const dispatch = useDispatch()
return (
<div className={styles.root}>
<SetItem type="ckbNode" />
<SetItem type="indexer" />
<ClearCache dispatch={dispatch} />
</div>
)
}

DataSetting.displayName = 'DataSetting'
export default DataSetting
4 changes: 3 additions & 1 deletion packages/neuron-ui/src/components/ErrorBoundary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { handleViewError } from 'services/remote'

const handleError = (error: Error) => {
handleViewError(error.toString())
window.location.reload()
if (process.env.NODE_ENV !== 'development') {
window.location.reload()
}
return { hasError: true }
}

Expand Down
6 changes: 1 addition & 5 deletions packages/neuron-ui/src/components/GeneralSetting/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React, { useCallback, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { ProgressIndicator } from 'office-ui-fabric-react'
import ClearCache from 'components/ClearCache'
import Button from 'widgets/Button'
import Spinner from 'widgets/Spinner'
import Dropdown from 'widgets/Dropdown'
import { StateDispatch } from 'states'
import { checkForUpdates, downloadUpdate, installUpdate, setLocale, getVersion } from 'services/remote'
import { CONSTANTS } from 'utils'

Expand Down Expand Up @@ -72,10 +70,9 @@ const UpdateDownloadStatus = ({ progress = 0, newVersion = '', releaseNotes = ''

interface GeneralSettingProps {
updater: State.AppUpdater
dispatch: StateDispatch
}

const GeneralSetting = ({ updater, dispatch }: GeneralSettingProps) => {
const GeneralSetting = ({ updater }: GeneralSettingProps) => {
const [t, i18n] = useTranslation()
const [lng, setLng] = useState(i18n.language)

Expand Down Expand Up @@ -127,7 +124,6 @@ const GeneralSetting = ({ updater, dispatch }: GeneralSettingProps) => {
</div>
</>
)}
<ClearCache dispatch={dispatch} />
<div className={`${styles.language} ${styles.label}`}>{t('settings.general.language')}</div>
<div className={`${styles.language} ${styles.select}`}>
<Dropdown
Expand Down
Loading