// Copyright 2017-2026 @pezkuwi/app-settings authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { Option } from '@pezkuwi/apps-config/settings/types'; import type { SettingsStruct } from '@pezkuwi/ui-settings/types'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { createLanguages, createSs58 } from '@pezkuwi/apps-config'; import { allNetworks } from '@pezkuwi/networks'; import { Button, Dropdown, MarkWarning } from '@pezkuwi/react-components'; import { useApi, useIpfs, useLedger } from '@pezkuwi/react-hooks'; import { settings } from '@pezkuwi/ui-settings'; import { useTranslation } from './translate.js'; import { createIdenticon, createOption, save, saveAndReload } from './util.js'; interface Props { className?: string; } const _ledgerConnOptions = settings.availableLedgerConn; const _ledgerAppOptions = settings.availableLedgerApp; function General ({ className = '' }: Props): React.ReactElement { const { t } = useTranslation(); const { chainSS58, isApiReady, isElectron } = useApi(); const { isIpfs } = useIpfs(); const { hasLedgerChain, hasWebUsb } = useLedger(); // tri-state: null = nothing changed, false = no reload, true = reload required const [changed, setChanged] = useState(null); const [state, setSettings] = useState((): SettingsStruct => { const values = settings.get(); return { ...values, uiTheme: values.uiTheme === 'dark' ? 'dark' : 'light' }; }); const ledgerConnOptions = useMemo( () => _ledgerConnOptions.filter(({ value }) => !isElectron || value !== 'webusb'), [isElectron] ); const iconOptions = useMemo( () => settings.availableIcons .map((o): Option => createIdenticon(o, ['default'])) .concat(createIdenticon({ info: 'robohash', text: 'RoboHash', value: 'robohash' })), [] ); const prefixOptions = useMemo( (): (Option | React.ReactNode)[] => { const network = allNetworks.find(({ prefix }) => prefix === chainSS58); return createSs58(t).map((o) => createOption(o, ['default'], 'empty', (o.value === -1 ? isApiReady ? network ? ` (${network.displayName}, ${chainSS58 || 0})` : ` (${chainSS58 || 0})` : undefined : ` (${o.value})` )) ); }, [chainSS58, isApiReady, t] ); const storageOptions = useMemo( () => [ { text: t('Allow local in-browser account storage'), value: 'on' }, { text: t('Do not allow local in-browser account storage'), value: 'off' } ], [t] ); const themeOptions = useMemo( () => [ { text: t('Light theme'), value: 'light' }, { text: t('Dark theme'), value: 'dark' } ], [t] ); const translateLanguages = useMemo( () => createLanguages(t), [t] ); useEffect((): void => { const prev = settings.get() as unknown as Record; const hasChanges = Object.entries(state).some(([key, value]) => prev[key] !== value); const needsReload = prev.apiUrl !== state.apiUrl || prev.prefix !== state.prefix; setChanged( hasChanges ? needsReload : null ); }, [state]); const _handleChange = useCallback( (key: keyof SettingsStruct) => (value: T) => setSettings((state) => ({ ...state, [key]: value })), [] ); const _saveAndReload = useCallback( () => saveAndReload(state), [state] ); const _save = useCallback( (): void => { save(state); setChanged(null); }, [state] ); return (

{t('UI options')}

{t('account options')}

{!isIpfs && !isElectron && ( <>
{state.storage === 'on' && (
)} )} {hasLedgerChain && ( <>
{hasWebUsb ? state.ledgerConn !== 'none' ? (
) : null : (
) } )}
); } export default React.memo(General);