import { useCallback } from 'react'; import { colors, strings } from '../../config.json'; import { messages } from '../../shared/gettext'; import { getDownloadUrl } from '../../shared/version'; import { useAppContext } from '../context'; import { useHistory } from '../lib/history'; import { RoutePath } from '../lib/routes'; import { useSelector } from '../redux/store'; import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup'; import * as Cell from './cell'; import { BackAction } from './KeyboardNavigation'; import { Layout, SettingsContainer } from './Layout'; import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import { StyledCellIcon, StyledContent, StyledNavigationScrollbars, StyledQuitButton, StyledSettingsContent, } from './SettingsStyles'; export default function Support() { const history = useHistory(); const loginState = useSelector((state) => state.account.status); const connectedToDaemon = useSelector((state) => state.userInterface.connectedToDaemon); const isMacOs13OrNewer = useSelector((state) => state.userInterface.isMacOs13OrNewer); const showSubSettings = loginState.type === 'ok' && connectedToDaemon; const showSplitTunneling = window.env.platform !== 'darwin' || isMacOs13OrNewer; return ( { // TRANSLATORS: Title label in navigation bar messages.pgettext('navigation-bar', 'Settings') } {messages.pgettext('navigation-bar', 'Settings')} {showSubSettings ? ( <> {showSplitTunneling && ( )} ) : ( )} {window.env.development && ( )} ); } function UserInterfaceSettingsButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.userInterfaceSettings), [history]); return ( { // TRANSLATORS: Navigation button to the 'User interface settings' view messages.pgettext('settings-view', 'User interface settings') } ); } function MultihopButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.multihopSettings), [history]); const relaySettings = useSelector((state) => state.settings.relaySettings); const multihop = 'normal' in relaySettings ? relaySettings.normal.wireguard.useMultihop : false; const unavailable = 'normal' in relaySettings ? relaySettings.normal.tunnelProtocol === 'openvpn' : true; return ( {messages.pgettext('settings-view', 'Multihop')} {multihop && !unavailable ? messages.gettext('On') : messages.gettext('Off')} ); } function DaitaButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.daitaSettings), [history]); const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false); const relaySettings = useSelector((state) => state.settings.relaySettings); const unavailable = 'normal' in relaySettings ? relaySettings.normal.tunnelProtocol === 'openvpn' : true; return ( {strings.daita} {daita && !unavailable ? messages.gettext('On') : messages.gettext('Off')} ); } function VpnSettingsButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.vpnSettings), [history]); return ( { // TRANSLATORS: Navigation button to the 'VPN settings' view messages.pgettext('settings-view', 'VPN settings') } ); } function SplitTunnelingButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.splitTunneling), [history]); return ( {strings.splitTunneling} ); } function ApiAccessMethodsButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.apiAccessMethods), [history]); return ( { // TRANSLATORS: Navigation button to the 'API access methods' view messages.pgettext('settings-view', 'API access') } ); } function AppVersionButton() { const appVersion = useSelector((state) => state.version.current); const consistentVersion = useSelector((state) => state.version.consistent); const upToDateVersion = useSelector((state) => (state.version.suggestedUpgrade ? false : true)); const suggestedIsBeta = useSelector((state) => state.version.suggestedIsBeta ?? false); const isOffline = useSelector((state) => state.connection.isBlocked); const { openUrl } = useAppContext(); const openDownloadLink = useCallback( () => openUrl(getDownloadUrl(suggestedIsBeta)), [openUrl, suggestedIsBeta], ); let icon; let footer; if (!consistentVersion || !upToDateVersion) { const inconsistentVersionMessage = messages.pgettext( 'settings-view', 'App is out of sync. Please quit and restart.', ); const updateAvailableMessage = messages.pgettext( 'settings-view', 'Update available. Install the latest app version to stay up to date.', ); const message = !consistentVersion ? inconsistentVersionMessage : updateAvailableMessage; icon = ; footer = ( {message} ); } return ( {icon} {messages.pgettext('settings-view', 'App version')} {appVersion} {footer} ); } function SupportButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.support), [history]); return ( {messages.pgettext('settings-view', 'Support')} ); } function DebugButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.debug), [history]); return ( Developer tools ); } function QuitButton() { const { quit } = useAppContext(); const tunnelState = useSelector((state) => state.connection.status); return ( {tunnelState.state === 'disconnected' ? messages.gettext('Quit') : messages.gettext('Disconnect & quit')} ); }