Skip to content

Commit

Permalink
feat: transaction page support node-connect mode (#350)
Browse files Browse the repository at this point in the history
* feat: transaction page support node-connect mode

* chore: optimize english text for readable

* feat: support cellbase display

* feat: optimize ver name

* feat: support node-connect mode state hold

* feat: home page support get lastest tx & block by node

* chore: fix typo
  • Loading branch information
PainterPuppets authored Jun 25, 2024
1 parent dc903db commit 97fdaa9
Show file tree
Hide file tree
Showing 60 changed files with 2,099 additions and 336 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@
"dependencies": {
"@ant-design/icons": "4.8.1",
"@ckb-lumos/base": "0.23.0",
"@ckb-lumos/bi": "0.23.0",
"@ckb-lumos/codec": "0.23.0",
"@ckb-lumos/config-manager": "0.23.0",
"@ckb-lumos/common-scripts": "0.23.0",
"@ckb-lumos/helpers": "0.23.0",
"@ckb-lumos/molecule": "0.23.0",
"@ckb-lumos/rpc": "0.23.0",
"@microlink/react-json-view": "1.23.0",
"@nervosnetwork/ckb-sdk-rpc": "0.109.1",
"@nervosnetwork/ckb-sdk-utils": "0.109.1",
"@radix-ui/react-icons": "1.3.0",
"@radix-ui/react-radio-group": "1.1.3",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@rgbpp-sdk/ckb": "0.0.0-snap-20240408100333",
"@sentry/react": "7.117.0",
Expand Down
25 changes: 20 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,29 @@ import Routers from './routes'
import Toast from './components/Toast'
import { isMainnet } from './utils/chain'
import { DASQueryContextProvider } from './hooks/useDASAccount'
import { CKBNodeProvider } from './hooks/useCKBNode'
import { getPrimaryColor, getSecondaryColor } from './constants/common'
import Decoder from './components/Decoder'
import config from './config'

const { BACKUP_NODES: backupNodes } = config

const appStyle = {
width: '100vw',
height: '100vh',
maxWidth: '100%',
}

const queryClient = new QueryClient()
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
refetchIntervalInBackground: false,
},
},
})

const App = () => {
const theme = useMemo<DefaultTheme>(
Expand All @@ -30,10 +43,12 @@ const App = () => {
<ThemeProvider theme={theme}>
<div style={appStyle} data-net={isMainnet() ? 'mainnet' : 'testnet'}>
<QueryClientProvider client={queryClient}>
<DASQueryContextProvider>
<Routers />
<Toast />
</DASQueryContextProvider>
<CKBNodeProvider defaultEndpoint={backupNodes[0]}>
<DASQueryContextProvider>
<Routers />
<Toast />
</DASQueryContextProvider>
</CKBNodeProvider>
</QueryClientProvider>
</div>
</ThemeProvider>
Expand Down
44 changes: 44 additions & 0 deletions src/components/Header/CKBNodeComp/CKBNodeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useCKBNode } from '../../../hooks/useCKBNode'
import CommonModal from '../../CommonModal'
import { HelpTip } from '../../HelpTip'
import { Switch } from '../../ui/Switch'
import CloseIcon from '../../../assets/modal_close.png'
import styles from './style.module.scss'

export const CKBNodeModal = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation()
const ref = useRef<HTMLDivElement>(null)
const { isActivated, setIsActivated } = useCKBNode()

return (
<CommonModal isOpen onClose={onClose}>
<div ref={ref} className={styles.modalWrapper}>
<div className={styles.contentWrapper}>
<div className={styles.modalTitle}>
<p>{t('navbar.node')}</p>
<button type="button" onClick={onClose} className={styles.closeBtn}>
<img src={CloseIcon} alt="close icon" />
</button>
</div>

<div className={styles.switcher}>
<label htmlFor="node-connect-mode">{t('node.node_connect_mode')}</label>
<HelpTip title={t('node.node_connect_tooltip')} />
<Switch
id="node-connect-mode"
style={{ marginLeft: 'auto' }}
checked={isActivated}
onCheckedChange={checked => setIsActivated(checked)}
/>
</div>

<button type="button" className={styles.doneBtn} onClick={onClose}>
{t('node.done')}
</button>
</div>
</div>
</CommonModal>
)
}
25 changes: 25 additions & 0 deletions src/components/Header/CKBNodeComp/NodeAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState } from 'react'
import { Trans } from 'react-i18next'
import { CKBNodeModal } from './CKBNodeModal'

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

const NodeAlert = () => {
const [nodeModalVisible, setNodeModalVisible] = useState(false)
return (
<>
<div className={styles.alert}>
<Trans
i18nKey="node.alert"
components={{
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
switcher: <span className={styles.clickable} onClick={() => setNodeModalVisible(true)} />,
}}
/>
</div>
{nodeModalVisible ? <CKBNodeModal onClose={() => setNodeModalVisible(false)} /> : null}
</>
)
}

export default NodeAlert
101 changes: 101 additions & 0 deletions src/components/Header/CKBNodeComp/style.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
@import '../../../styles/variables.module';

.contentWrapper {
background-color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 4px;
width: 80vw;
max-width: 280px;
padding: 24px;

@media screen and (width <= 750px) {
padding: 16px;
width: calc(100vw - 32px);
}

p {
margin: 0;
}
}

.modalTitle {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
color: #333;
font-weight: 600;
font-size: 16px;
line-height: 20px;
}

.modalContent {
width: 100%;
margin-top: 32px;
}

.languageSelect {
color: #333;
}

.closeBtn {
border: none;
background: transparent;
cursor: pointer;

img {
width: 13px;
height: 13px;
}
}

.doneBtn {
width: 100%;
margin-top: 32px;
height: 47px;
background: var(--primary-color);
border: none;
border-radius: 4px;
color: #fff;
font-size: 16px;
cursor: pointer;
}

.loading {
text-align: center;
}

.switcher {
margin-top: 32px;
width: 100%;
display: flex;
align-items: center;

label {
color: black;
}
}

.alert {
position: sticky;
color: #fff;
font-size: 14px;
font-weight: 450;
line-height: 1.2;
text-align: center;
padding: 1rem;
background-color: #fa8f00;

@media (width <= $mobileBreakPoint) {
text-align: left;
}
}

.clickable {
color: var(--primary-color);
cursor: pointer;
text-decoration: underline;
}
4 changes: 3 additions & 1 deletion src/components/Header/MaintainAlert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import axios from 'axios'
import config from '../../../config'
import { useCKBNode } from '../../../hooks/useCKBNode'
import { useLatestBlockNumber } from '../../../services/ExplorerService'
import styles from './styles.module.scss'

Expand All @@ -25,6 +26,7 @@ const getTipFromNode = (url: string): Promise<string> =>
const MaintainAlert = () => {
const { t } = useTranslation()
const synced = useLatestBlockNumber()
const { isActivated } = useCKBNode()
const { data: tip } = useQuery(
['backup_nodes'],
async () => {
Expand All @@ -49,7 +51,7 @@ const MaintainAlert = () => {

const lag = tip && synced ? tip - synced : 0

return lag >= threshold ? (
return lag >= threshold && !isActivated ? (
<div className={styles.container}>
{t('error.maintain', { tip: tip?.toLocaleString('en'), lag: lag.toLocaleString('en') })}
</div>
Expand Down
26 changes: 26 additions & 0 deletions src/components/Header/MenusComp/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,29 @@
.moreMenus {
margin-right: 0;
}

.linkWithBadge {
display: flex !important;
align-items: center;
gap: 8px;
}

.nodeStatus {
display: block;
width: 12px;
height: 12px;
border-radius: 999px;
}

.activate {
background-color: #00cc9b;
}

.clickable {
cursor: pointer;
transition: all 0.2s;

&:hover {
color: var(--primary-color);
}
}
28 changes: 22 additions & 6 deletions src/components/Header/MenusComp/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FC, memo, PropsWithChildren, useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand All @@ -8,9 +7,11 @@ import { Link } from '../../Link'
import { MobileMenuItem, MobileMenuOuterLink, HeaderMenuPanel, MobileMenuInnerLink } from './styled'
import styles from './index.module.scss'
import { LanguageModal } from '../LanguageComp/LanguageModal'
import { CKBNodeModal } from '../CKBNodeComp/CKBNodeModal'
import { ReactComponent as ArrowIcon } from './arrow.svg'
import { IS_MAINNET } from '../../../constants/common'
import { ReactComponent as MenuIcon } from './menu.svg'
import { useCKBNode } from '../../../hooks/useCKBNode'

export enum LinkType {
Inner,
Expand Down Expand Up @@ -120,8 +121,10 @@ const SubmenuDropdown: FC<PropsWithChildren<DropdownProps & { menu: MenuData[] }

export const MoreMenu = ({ isMobile = false }: { isMobile?: boolean }) => {
const { t } = useTranslation()
const { isActivated } = useCKBNode()
const [open, setOpen] = useState(false)
const [languageModalVisible, setLanguageModalVisible] = useState(false)
const [nodeModalVisible, setNodeModalVisible] = useState(false)

const Wrapper = isMobile ? MobileMenuItem : ({ children }: PropsWithChildren<{}>) => <>{children}</>

Expand All @@ -135,15 +138,25 @@ export const MoreMenu = ({ isMobile = false }: { isMobile?: boolean }) => {
<Link className={styles.link} to="/tools/address-conversion">
{t('footer.tools')}
</Link>
<a
className={styles.link}
<span
className={classNames(styles.link, styles.clickable)}
onClick={() => {
setOpen(false)
setLanguageModalVisible(true)
}}
>
{t('navbar.language')}
</a>
</span>
<span
className={classNames(styles.link, styles.clickable, styles.linkWithBadge)}
onClick={() => {
setOpen(false)
setNodeModalVisible(true)
}}
>
{t('navbar.node')}
<span className={classNames(styles.nodeStatus, { [styles.activate]: isActivated })} />
</span>
</div>
}
mouseEnterDelay={0}
Expand All @@ -156,12 +169,15 @@ export const MoreMenu = ({ isMobile = false }: { isMobile?: boolean }) => {
<ArrowIcon className={styles.icon} />
</MobileMenuOuterLink>
) : (
<a className={classNames(styles.headerMenusItem, styles.submenuTrigger, styles.moreMenus)}>
<span
className={classNames(styles.clickable, styles.headerMenusItem, styles.submenuTrigger, styles.moreMenus)}
>
<MenuIcon className={styles.moreIcon} />
</a>
</span>
)}
</Dropdown>
{languageModalVisible ? <LanguageModal onClose={() => setLanguageModalVisible(false)} /> : null}
{nodeModalVisible ? <CKBNodeModal onClose={() => setNodeModalVisible(false)} /> : null}
</Wrapper>
)
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import BlockchainComp from './BlockchainComp'
import { useMediaQuery } from '../../hooks'
import styles from './index.module.scss'
import MaintainAlert from './MaintainAlert'
import NodeAlert from './CKBNodeComp/NodeAlert'

import Sheet from './Sheet'
import { createGlobalState, useGlobalState } from '../../utils/state'
import MobileMenu from './MobileMenu'
import { useCKBNode } from '../../hooks/useCKBNode'

const LogoComp = () => (
<HeaderLogoPanel to="/">
Expand Down Expand Up @@ -54,6 +57,7 @@ export function useIsShowSearchBarInHeader() {

export default () => {
const isMobile = useMediaQuery(`(max-width: 1023px)`)
const { isActivated } = useCKBNode()
const { pathname } = useLocation()
const history = useHistory()
// TODO: This hard-coded implementation is not ideal, but currently the header is loaded before the page component,
Expand Down Expand Up @@ -98,6 +102,7 @@ export default () => {
)}
</HeaderPanel>
<MaintainAlert />
{isActivated ? <NodeAlert /> : null}
<Sheet />
{mobileMenuVisible && isMobile && <MobileMenu hideMobileMenu={() => setMobileMenuVisible(false)} />}
</div>
Expand Down
Loading

0 comments on commit 97fdaa9

Please sign in to comment.