diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index 7176ccc1dc9..7594d5f06ca 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -5721,6 +5721,8 @@ export default class KoniExtension { return await this.reconnectChain(request as string); case 'pri(chainService.disableChain)': return await this.disableChain(request as string); + case 'pri(chainService.disableAllChains)': + return this.#koniState.disableAllChains(); case 'pri(chainService.removeChain)': return this.removeCustomChain(request as string); case 'pri(chainService.validateCustomChain)': diff --git a/packages/extension-base/src/koni/background/handlers/State.ts b/packages/extension-base/src/koni/background/handlers/State.ts index e4c954fb8cd..07994954e92 100644 --- a/packages/extension-base/src/koni/background/handlers/State.ts +++ b/packages/extension-base/src/koni/background/handlers/State.ts @@ -949,6 +949,10 @@ export default class KoniState { return this.chainService.disableChain(chainSlug); } + public disableAllChains (): boolean { + return this.chainService.disableAllChains(); + } + public async enableChain (chainSlug: string, enableTokens = true): Promise { if (enableTokens) { await this.chainService.updateAssetSettingByChain(chainSlug, true); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 65a5deeeaa9..c00d5119e69 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -1213,6 +1213,17 @@ export class ChainService { return true; } + public disableAllChains (): boolean { + const chainStateMap = this.getChainStateMap(); + const activeChainSlugs = Object.keys(chainStateMap).filter((slug) => chainStateMap[slug].active); + + for (const chainSlug of activeChainSlugs) { + this.disableChain(chainSlug); + } + + return true; + } + private checkExistedPredefinedChain (latestChainInfoMap: Record, genesisHash?: string, evmChainId?: number) { let duplicatedSlug = ''; diff --git a/packages/extension-koni-ui/src/Popup/Settings/Chains/ManageChains.tsx b/packages/extension-koni-ui/src/Popup/Settings/Chains/ManageChains.tsx index 230d98b9d88..77460098386 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Chains/ManageChains.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Chains/ManageChains.tsx @@ -6,8 +6,9 @@ import { FilterModal, Layout, NetworkEmptyList, NetworkToggleItem, OptionType, P import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; import { ChainInfoWithState, useFilterModal, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import useChainInfoWithStateAndStatus, { ChainInfoWithStateAndStatus } from '@subwallet/extension-koni-ui/hooks/chain/useChainInfoWithStateAndStatus'; +import { disableAllNetwork } from '@subwallet/extension-koni-ui/messaging'; import { ManageChainsParam, ThemeProps } from '@subwallet/extension-koni-ui/types'; -import { ButtonProps, Icon, ModalContext, SwList } from '@subwallet/react-ui'; +import { ButtonProps, Icon, ModalContext, Switch, SwList } from '@subwallet/react-ui'; import { SwListSectionRef } from '@subwallet/react-ui/es/sw-list'; import { FadersHorizontal, Plus } from 'phosphor-react'; import React, { SyntheticEvent, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; @@ -40,6 +41,23 @@ function Component ({ className = '' }: Props): React.ReactElement { const { activeModal } = useContext(ModalContext); const chainInfoList = useChainInfoWithStateAndStatus(); const { filterSelectionMap, onApplyFilter, onChangeFilterOption, onCloseFilterModal, selectedFilters } = useFilterModal(FILTER_MODAL_ID); + const [disablingAll, setDisablingAll] = useState(false); + + const hasActiveChains = useMemo(() => { + return chainInfoList.some((chain) => chain.active); + }, [chainInfoList]); + + const onDisableAll = useCallback(() => { + if (!disablingAll) { + if (hasActiveChains) { + setDisablingAll(true); + disableAllNetwork() + .finally(() => { + setDisablingAll(false); + }); + } + } + }, [disablingAll, hasActiveChains]); const FILTER_OPTIONS = useMemo((): OptionType[] => ([ { label: t('ui.SETTINGS.screen.Setting.Chains.Manage.evmNetworks'), value: FilterValue.EVM }, @@ -171,6 +189,16 @@ function Component ({ className = '' }: Props): React.ReactElement { searchPlaceholder={t('ui.SETTINGS.screen.Setting.Chains.Manage.searchNetwork')} showActionBtn /> +
+ {t('Disable all networks')} + +
(({ theme: { token } }: Props) => { }, '.manage_chains__container': { - paddingTop: token.padding, paddingBottom: token.paddingSM, - flex: 1 + flex: 1, + + '.ant-sw-list-search-input': { + marginBottom: 40 + } + }, + + '.manage_chains__disable_all_row': { + position: 'absolute', + top: 116, + left: 0, + right: 0, + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-end', + gap: token.sizeXS, + padding: `0 ${token.padding}px`, + zIndex: 5 + }, + + '.manage_chains__disable_all_label': { + fontSize: token.fontSizeSM, + color: token.colorTextLight4 }, '.ant-network-item-content .__toggle-area': {