From 2e5711fcaabceb89a089070f95aca2de302c0bed Mon Sep 17 00:00:00 2001 From: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com> Date: Thu, 29 Oct 2026 22:55:38 +0000 Subject: [PATCH] fix(mobile): use paired ports in firewall help (#36130) * fix(mobile): use paired ports in firewall help * fix(mobile): use a namespace type in diagnostics test --- docs/site/content/docs/mobile.mdx | 17 ++++ mobile/app/troubleshoot.tsx | 4 +- .../troubleshoot-common-issues.test.ts | 50 +++++++++++ .../troubleshoot-common-issues.tsx | 47 ++++++++-- mobile/src/diagnostics/troubleshoot-view.tsx | 4 +- .../use-troubleshoot-diagnostics.test.tsx | 87 +++++++++++++++++++ .../use-troubleshoot-diagnostics.ts | 31 ++++++- mobile/src/i18n/locales/de.json | 3 +- mobile/src/i18n/locales/en.json | 3 +- mobile/src/i18n/locales/es.json | 3 +- mobile/src/i18n/locales/fr.json | 3 +- mobile/src/i18n/locales/ja.json | 3 +- mobile/src/i18n/locales/ko.json | 3 +- mobile/src/i18n/locales/pt.json | 3 +- mobile/src/i18n/locales/ru.json | 3 +- mobile/src/i18n/locales/tr.json | 3 +- mobile/src/i18n/locales/zh-Hant.json | 3 +- mobile/src/i18n/locales/zh.json | 3 +- 18 files changed, 250 insertions(+), 23 deletions(-) create mode 100644 mobile/src/diagnostics/troubleshoot-common-issues.test.ts create mode 100644 mobile/src/diagnostics/use-troubleshoot-diagnostics.test.tsx diff --git a/docs/site/content/docs/mobile.mdx b/docs/site/content/docs/mobile.mdx index 417eb35ff52..e8fed6790d1 100644 --- a/docs/site/content/docs/mobile.mdx +++ b/docs/site/content/docs/mobile.mdx @@ -104,6 +104,23 @@ The mobile terminal has a dedicated **Terminal settings** screen (Settings → T ## Troubleshooting +### Firewalls and Orca Relay + +For Orca Relay and sign-in, allow outbound TCP port `443` from the desktop and phone to these hosts: + +| Host | Purpose | Protocol | +| -------------------------------------------------------------------------------- | --------------------------------------------- | --------------------------------- | +| `login.onorca.dev` | Orca sign-in and Relay credentials | HTTPS | +| `auth.onorca.dev` | Hosted sign-in pages | HTTPS | +| `relay.onorca.dev` | Relay director, which assigns a regional cell | HTTPS and secure WebSockets (WSS) | +| `*.relay.onorca.dev`, including `c1.relay.onorca.dev` and `c27.relay.onorca.dev` | Regional Relay cells | HTTPS and secure WebSockets (WSS) | + +Allow WebSocket upgrades and long-lived connections to both `relay.onorca.dev` and the Relay cells. Cell assignments can change, so allow the cell hostname pattern as well as the director. Relay uses outbound connections; it does not need an inbound port or router port forwarding. + +For a direct LAN or Tailscale connection, allow the paired desktop's listening port instead. The default is `6768`, but a desktop using another port needs that port allowed. **Settings → Troubleshooting** shows the paired endpoint's port in its firewall advice. + +### Common issues + - **Stuck spinner on a worktree** — the phone tracks a heartbeat from the desktop agent process. If the desktop says idle but the phone shows working, force-refresh the worktree row to sync state. - **Pairing fails** — make sure your desktop and phone are signed into the same Orca account. Pairing codes expire after a few minutes; generate a fresh one if it's been sitting on the screen. - **Authentication failed / pairing invalid** — the desktop no longer accepts this device token (for example after desktop cleared paired devices). Try **Retry** on the banner first (transient rejections can recover without re-pairing). If it keeps failing, use **Re-pair** from desktop, or **Remove** the host and pair again. diff --git a/mobile/app/troubleshoot.tsx b/mobile/app/troubleshoot.tsx index 151db699a06..fd3472ced33 100644 --- a/mobile/app/troubleshoot.tsx +++ b/mobile/app/troubleshoot.tsx @@ -10,12 +10,14 @@ const isDevelopmentBuild = typeof __DEV__ !== 'undefined' && __DEV__ export default function NativeTroubleshootRoute() { const router = useRouter() - const { rootRef, diagnosticStatus, checks, runDiagnostics } = useTroubleshootDiagnostics() + const { rootRef, diagnosticStatus, checks, hostEndpoints, runDiagnostics } = + useTroubleshootDiagnostics() return ( void runDiagnostics()} onBack={() => router.back()} onConnectionLog={() => router.push('/connection-log')} diff --git a/mobile/src/diagnostics/troubleshoot-common-issues.test.ts b/mobile/src/diagnostics/troubleshoot-common-issues.test.ts new file mode 100644 index 00000000000..c67273e97c1 --- /dev/null +++ b/mobile/src/diagnostics/troubleshoot-common-issues.test.ts @@ -0,0 +1,50 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { SUPPORTED_UI_LOCALES } from '../../../src/shared/ui-locale' +import { activateMobileUiLocale, translate } from '../i18n/mobile-i18n' +import { troubleshootCommonIssues } from './troubleshoot-common-issues' + +vi.mock('lucide-react-native', () => ({ + WifiOff: () => null, + Shield: () => null, + Monitor: () => null, + Clock: () => null, + Globe: () => null, + Bell: () => null +})) + +afterEach(() => activateMobileUiLocale('en')) + +describe('troubleshooting firewall advice', () => { + it.each([ + { endpoints: ['ws://192.168.1.10:6769'], ports: ['6769'] }, + { endpoints: ['ws://[fd7a:115c:a1e0::1]:7777'], ports: ['7777'] }, + { endpoints: ['wss://desktop.example', 'ws://desktop.local'], ports: ['443', '80'] }, + { endpoints: [], ports: ['6768'] }, + { endpoints: ['invalid endpoint'], ports: ['6768'] }, + { + endpoints: ['ws://first.local:6769', 'ws://second.local:7777', 'ws://third.local:6769'], + ports: ['6769', '7777'] + } + ])('uses paired ports for $endpoints', ({ endpoints, ports }) => { + const sections = troubleshootCommonIssues(translate, endpoints).filter((section) => + section.id.startsWith('firewall') + ) + expect(sections.map((section) => section.title)).toEqual( + ports.map((port) => `Firewall Blocking Port ${port}`) + ) + expect(sections.map((section) => section.steps.find((step) => step.includes('ufw')))).toEqual( + ports.map((port) => `Linux: sudo ufw allow ${port}`) + ) + expect(new Set(sections.map((section) => section.id)).size).toBe(ports.length) + }) + + it.each(SUPPORTED_UI_LOCALES)('interpolates the paired port in %s', async (locale) => { + await activateMobileUiLocale(locale) + const section = troubleshootCommonIssues(translate, ['ws://desktop.local:6769']).find((entry) => + entry.id.startsWith('firewall') + ) + expect(section?.title).toContain('6769') + expect(section?.title).not.toContain('6768') + expect(section?.steps.some((step) => step.includes('sudo ufw allow 6769'))).toBe(true) + }) +}) diff --git a/mobile/src/diagnostics/troubleshoot-common-issues.tsx b/mobile/src/diagnostics/troubleshoot-common-issues.tsx index 050145486af..c348192196c 100644 --- a/mobile/src/diagnostics/troubleshoot-common-issues.tsx +++ b/mobile/src/diagnostics/troubleshoot-common-issues.tsx @@ -1,5 +1,6 @@ import { WifiOff, Shield, Monitor, Clock, Globe, Bell, type LucideIcon } from 'lucide-react-native' import type { Translate } from '../i18n/mobile-i18n' +import { endpointPort } from '../transport/host-endpoint' export type TroubleshootSection = { id: string @@ -8,7 +9,33 @@ export type TroubleshootSection = { steps: string[] } -export function troubleshootCommonIssues(t: Translate): TroubleshootSection[] { +export function troubleshootCommonIssues( + t: Translate, + endpoints: readonly string[] = [] +): TroubleshootSection[] { + const ports = new Set( + endpoints.map((endpoint) => { + const port = endpointPort(endpoint) + if (port) { + return port + } + try { + const url = new URL(endpoint) + if (url.protocol === 'wss:') { + return '443' + } + if (url.protocol === 'ws:') { + return '80' + } + } catch { + // Unreadable legacy endpoints keep the default firewall advice. + } + return '6768' + }) + ) + if (ports.size === 0) { + ports.add('6768') + } return [ { id: 'notifications', @@ -45,10 +72,16 @@ export function troubleshootCommonIssues(t: Translate): TroubleshootSection[] { ) ] }, - { - id: 'firewall', + ...Array.from(ports, (port) => ({ + id: `firewall-${port}`, icon: Shield, - title: t('diagnostics.troubleshootCommonIssues.firewallTitle', 'Firewall Blocking Port 6768'), + title: t( + 'diagnostics.troubleshootCommonIssues.firewallTitle', + 'Firewall Blocking Port {{port}}', + { + port + } + ), steps: [ t( 'diagnostics.troubleshootCommonIssues.macosFirewall', @@ -58,13 +91,15 @@ export function troubleshootCommonIssues(t: Translate): TroubleshootSection[] { 'diagnostics.troubleshootCommonIssues.windowsFirewall', 'Windows: Defender Firewall → Allow app — enable Orca for Private networks.' ), - 'Linux: sudo ufw allow 6768', + t('diagnostics.troubleshootCommonIssues.linuxFirewall', 'Linux: sudo ufw allow {{port}}', { + port + }), t( 'diagnostics.troubleshootCommonIssues.restrictedNetwork', 'Corporate/school networks may block P2P — try a personal hotspot.' ) ] - }, + })), { id: 'desktop', icon: Monitor, diff --git a/mobile/src/diagnostics/troubleshoot-view.tsx b/mobile/src/diagnostics/troubleshoot-view.tsx index 35f8ff6c50a..b073da808aa 100644 --- a/mobile/src/diagnostics/troubleshoot-view.tsx +++ b/mobile/src/diagnostics/troubleshoot-view.tsx @@ -40,6 +40,7 @@ export function TroubleshootView({ rootRef, diagnosticStatus, checks, + hostEndpoints, runDiagnostics, onBack, onConnectionLog, @@ -48,6 +49,7 @@ export function TroubleshootView({ rootRef?: (node: View | null) => void diagnosticStatus: DiagnosticStatus checks: CheckResult[] + hostEndpoints: readonly string[] runDiagnostics: () => void onBack: () => void onConnectionLog: () => void @@ -146,7 +148,7 @@ export function TroubleshootView({ - {troubleshootCommonIssues(t).map((section, i) => ( + {troubleshootCommonIssues(t, hostEndpoints).map((section, i) => ( {i > 0 && } ({ + catalog: vi.fn<() => Promise<{ endpoint: string }[]>>(), + profiles: vi.fn<() => Promise<{ name: string; endpoint: string }[]>>() +})) +vi.mock('react-native', () => ({ Platform: { OS: 'ios', Version: '27' } })) +vi.mock('../transport/host-store', () => ({ + loadHostCatalog: hosts.catalog, + loadHosts: hosts.profiles +})) +vi.mock('./host-reachability', async (importOriginal) => ({ + ...(await importOriginal()), + testHostReachability: async () => true +})) + +import { useTroubleshootDiagnostics } from './use-troubleshoot-diagnostics' + +let tree: ReactTestRenderer | undefined +const state: { current: ReturnType | null } = { current: null } +function Harness() { + state.current = useTroubleshootDiagnostics() + return null +} + +afterEach(async () => { + await act(async () => tree?.unmount()) + state.current = null + vi.resetAllMocks() + vi.unstubAllGlobals() +}) + +describe('troubleshooting paired endpoints', () => { + it('loads endpoint advice before the user runs diagnostics', async () => { + hosts.catalog.mockResolvedValue([{ endpoint: 'ws://desktop.local:6769' }]) + await act(async () => { + tree = create(createElement(Harness)) + }) + expect(state.current?.diagnosticStatus).toBe('idle') + expect(state.current?.hostEndpoints).toEqual(['ws://desktop.local:6769']) + }) + + it('keeps the newly probed endpoints when the initial catalog read finishes later', async () => { + let finishCatalog: (value: { endpoint: string }[]) => void = () => {} + hosts.catalog + .mockReturnValueOnce( + new Promise((resolve) => { + finishCatalog = resolve + }) + ) + .mockResolvedValue([{ endpoint: 'ws://desktop.local:7777' }]) + hosts.profiles.mockResolvedValue([{ name: 'Desktop', endpoint: 'ws://desktop.local:7777' }]) + vi.stubGlobal('fetch', async () => ({ ok: true })) + await act(async () => { + tree = create(createElement(Harness)) + }) + await act(async () => { + await state.current?.runDiagnostics() + }) + await act(async () => { + finishCatalog([{ endpoint: 'ws://desktop.local:6769' }]) + }) + expect(state.current?.hostEndpoints).toEqual(['ws://desktop.local:7777']) + expect(state.current?.checks).toContainEqual({ + label: 'Desktop', + status: 'pass', + detail: 'Reachable at desktop.local:7777' + }) + }) + + it('retains saved port advice after a run when the host credential is unavailable', async () => { + hosts.catalog.mockResolvedValue([{ endpoint: 'ws://desktop.local:6769' }]) + hosts.profiles.mockResolvedValue([]) + vi.stubGlobal('fetch', async () => ({ ok: true })) + await act(async () => { + tree = create(createElement(Harness)) + }) + expect(state.current?.hostEndpoints).toEqual(['ws://desktop.local:6769']) + await act(async () => { + await state.current?.runDiagnostics() + }) + expect(state.current?.hostEndpoints).toEqual(['ws://desktop.local:6769']) + }) +}) diff --git a/mobile/src/diagnostics/use-troubleshoot-diagnostics.ts b/mobile/src/diagnostics/use-troubleshoot-diagnostics.ts index 8d0d5a1af8f..280e8a204de 100644 --- a/mobile/src/diagnostics/use-troubleshoot-diagnostics.ts +++ b/mobile/src/diagnostics/use-troubleshoot-diagnostics.ts @@ -1,8 +1,8 @@ -import { useCallback, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import type { View } from 'react-native' import { Platform } from 'react-native' import { useMobileTranslation } from '../i18n/use-mobile-translation' -import { loadHosts } from '../transport/host-store' +import { loadHostCatalog, loadHosts } from '../transport/host-store' import { startDiagnosticFetchTimeout, type DiagnosticFetchTimeout @@ -14,10 +14,29 @@ export function useTroubleshootDiagnostics() { const t = useMobileTranslation() const [diagnosticStatus, setDiagnosticStatus] = useState('idle') const [checks, setChecks] = useState([]) + const [hostEndpoints, setHostEndpoints] = useState([]) const abortRef = useRef(false) const diagnosticRunRef = useRef(0) const activeInternetCheckRef = useRef(null) + useEffect(() => { + let disposed = false + const initialRunId = diagnosticRunRef.current + void loadHostCatalog().then( + (hosts) => { + if (!disposed && diagnosticRunRef.current === initialRunId) { + setHostEndpoints(hosts.map((host) => host.endpoint)) + } + }, + () => { + // Keep default advice when the saved host catalog cannot be read. + } + ) + return () => { + disposed = true + } + }, []) + const rootRef = useCallback((node: View | null): void => { if (node !== null) { return @@ -42,7 +61,11 @@ export function useTroubleshootDiagnostics() { const isCurrentRun = () => !abortRef.current && diagnosticRunRef.current === runId try { - const hosts = await loadHosts() + const [hosts, catalog] = await Promise.all([loadHosts(), loadHostCatalog()]) + if (!isCurrentRun()) { + return + } + setHostEndpoints(catalog.map((host) => host.endpoint)) results.push( hosts.length > 0 ? { @@ -166,5 +189,5 @@ export function useTroubleshootDiagnostics() { setDiagnosticStatus('done') }, [t]) - return { rootRef, diagnosticStatus, checks, runDiagnostics } + return { rootRef, diagnosticStatus, checks, hostEndpoints, runDiagnostics } } diff --git a/mobile/src/i18n/locales/de.json b/mobile/src/i18n/locales/de.json index 7b4c432e268..c7062ad3c92 100644 --- a/mobile/src/i18n/locales/de.json +++ b/mobile/src/i18n/locales/de.json @@ -1102,7 +1102,8 @@ "checkTailnet": "Prüfen, ob der Computer nicht im Ruhezustand ist und im Tailnet als verbunden angezeigt wird.", "desktopTitle": "Desktop-App läuft nicht", "disableVpn": "Dieses VPN deaktivieren oder Split-Tunneling / „Allow LAN“ aktivieren.", - "firewallTitle": "Firewall blockiert Port 6768", + "firewallTitle": "Firewall blockiert Port {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "Host-Adressen wie 100.x.x.x oder *.ts.net nutzen Tailscale – Tailscale eingeschaltet lassen.", "macosFirewall": "macOS: System Settings → Network → Firewall – Orca zulassen.", "notificationNetwork": "Mobilfunk oder ein anderes WLAN ausprobieren. Treffen Benachrichtigungen nach dem Wechsel ein, verzögert das ursprüngliche Netzwerk möglicherweise die Zustellung.", diff --git a/mobile/src/i18n/locales/en.json b/mobile/src/i18n/locales/en.json index dd50380a053..867fb8bf74b 100644 --- a/mobile/src/i18n/locales/en.json +++ b/mobile/src/i18n/locales/en.json @@ -361,7 +361,8 @@ "sameNetwork": "Both devices must be on the same LAN (unless connected through Tailscale).", "sameSubnet": "Ethernet and WiFi must share the same subnet.", "reconnectWifi": "Try reconnecting WiFi on both devices.", - "firewallTitle": "Firewall Blocking Port 6768", + "firewallTitle": "Firewall Blocking Port {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "macosFirewall": "macOS: System Settings → Network → Firewall — allow Orca.", "windowsFirewall": "Windows: Defender Firewall → Allow app — enable Orca for Private networks.", "restrictedNetwork": "Corporate/school networks may block P2P — try a personal hotspot.", diff --git a/mobile/src/i18n/locales/es.json b/mobile/src/i18n/locales/es.json index eb9995e1bc3..befc509224a 100644 --- a/mobile/src/i18n/locales/es.json +++ b/mobile/src/i18n/locales/es.json @@ -1145,7 +1145,8 @@ "checkTailnet": "Comprueba que el escritorio esté activo y aparezca conectado en tu red de Tailscale.", "desktopTitle": "App de escritorio cerrada", "disableVpn": "Desactiva esa VPN o activa la tunelización dividida / \"Allow LAN\".", - "firewallTitle": "El cortafuegos bloquea el puerto 6768", + "firewallTitle": "El cortafuegos bloquea el puerto {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "Las direcciones de host como 100.x.x.x o *.ts.net se conectan a través de Tailscale — mantenlo ACTIVADO.", "macosFirewall": "macOS: Ajustes del Sistema → Red → Firewall — permite las conexiones de Orca.", "notificationNetwork": "Prueba con datos móviles u otra red Wi-Fi. Si las alertas llegan tras cambiar de red, es posible que tu red esté retrasando la entrega.", diff --git a/mobile/src/i18n/locales/fr.json b/mobile/src/i18n/locales/fr.json index 2931691544b..2e0dbbbff06 100644 --- a/mobile/src/i18n/locales/fr.json +++ b/mobile/src/i18n/locales/fr.json @@ -1145,7 +1145,8 @@ "checkTailnet": "Vérifiez que l'ordinateur n'est pas en veille et apparaît connecté à votre tailnet.", "desktopTitle": "Application de bureau arrêtée", "disableVpn": "Désactivez ce VPN ou activez le routage fractionné / « Autoriser le LAN ».", - "firewallTitle": "Pare-feu bloquant le port 6768", + "firewallTitle": "Pare-feu bloquant le port {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "Les adresses d'hôte comme 100.x.x.x ou *.ts.net passent par Tailscale — laissez-le ACTIVÉ.", "macosFirewall": "macOS : Réglages Système → Réseau → Pare-feu — autorisez Orca.", "notificationNetwork": "Essayez les données mobiles ou un autre réseau Wi-Fi. Si les alertes arrivent après ce changement, votre réseau retarde peut-être leur réception.", diff --git a/mobile/src/i18n/locales/ja.json b/mobile/src/i18n/locales/ja.json index 3b1525f7aa9..9b544b325e2 100644 --- a/mobile/src/i18n/locales/ja.json +++ b/mobile/src/i18n/locales/ja.json @@ -1098,7 +1098,8 @@ "checkTailnet": "デスクトップがスリープ状態になっておらず、tailnet 内で接続済みと表示されていることを確認してください。", "desktopTitle": "デスクトップアプリが未起動", "disableVpn": "その VPN を無効にするか、スプリットトンネリングまたは「LAN を許可」を有効にしてください。", - "firewallTitle": "ファイアウォールがポート 6768 をブロック", + "firewallTitle": "ファイアウォールがポート {{port}} をブロック", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "100.x.x.x や *.ts.net のようなホストアドレスには Tailscale 経由で接続します。Tailscale をオンにしておいてください。", "macosFirewall": "macOS: 「システム設定」→「ネットワーク」→「ファイアウォール」で Orca を許可してください。", "notificationNetwork": "モバイルデータ通信か別の Wi-Fi ネットワークを試してください。切り替え後に通知が届く場合は、元のネットワークで配信が遅れている可能性があります。", diff --git a/mobile/src/i18n/locales/ko.json b/mobile/src/i18n/locales/ko.json index 74fed1fcdd3..cab462d4ed1 100644 --- a/mobile/src/i18n/locales/ko.json +++ b/mobile/src/i18n/locales/ko.json @@ -1098,7 +1098,8 @@ "checkTailnet": "데스크톱이 절전 모드가 아니며 tailnet에 연결된 상태로 표시되는지 확인하세요.", "desktopTitle": "데스크톱 앱이 실행되지 않음", "disableVpn": "해당 VPN을 끄거나 분할 터널링 / \"LAN 허용\"을 켜세요.", - "firewallTitle": "방화벽에서 포트 6768 차단", + "firewallTitle": "방화벽에서 포트 {{port}} 차단", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "100.x.x.x나 *.ts.net 같은 호스트 주소는 Tailscale을 통해 연결되므로 Tailscale을 켜 두세요.", "macosFirewall": "macOS: 시스템 설정 → 네트워크 → 방화벽에서 Orca를 허용하세요.", "notificationNetwork": "모바일 데이터나 다른 Wi-Fi 네트워크를 사용해 보세요. 전환 후 알림이 도착한다면 기존 네트워크에서 알림 전달이 지연되고 있을 수 있습니다.", diff --git a/mobile/src/i18n/locales/pt.json b/mobile/src/i18n/locales/pt.json index 3757abf34f0..3448e839fe2 100644 --- a/mobile/src/i18n/locales/pt.json +++ b/mobile/src/i18n/locales/pt.json @@ -1145,7 +1145,8 @@ "checkTailnet": "Verifique se o desktop está fora do modo de suspensão e aparece como conectado na sua tailnet.", "desktopTitle": "App desktop não está em execução", "disableVpn": "Desative essa VPN ou ative o tunelamento dividido / \"Permitir LAN\".", - "firewallTitle": "Firewall bloqueando a porta 6768", + "firewallTitle": "Firewall bloqueando a porta {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "Hosts com endereços como 100.x.x.x ou *.ts.net se conectam via Tailscale — mantenha-o ATIVADO.", "macosFirewall": "macOS: Ajustes do Sistema → Rede → Firewall — permita o Orca.", "notificationNetwork": "Tente usar os dados móveis ou outra rede Wi-Fi. Se os alertas chegarem após a troca, sua rede pode estar atrasando a entrega.", diff --git a/mobile/src/i18n/locales/ru.json b/mobile/src/i18n/locales/ru.json index 7f64f43f476..daf2c1bd921 100644 --- a/mobile/src/i18n/locales/ru.json +++ b/mobile/src/i18n/locales/ru.json @@ -1188,7 +1188,8 @@ "checkTailnet": "Убедитесь, что компьютер не спит и отображается как подключённый в вашей сети tailnet.", "desktopTitle": "Приложение на компьютере не запущено", "disableVpn": "Отключите этот VPN или включите раздельное туннелирование / «Разрешить LAN».", - "firewallTitle": "Брандмауэр блокирует порт 6768", + "firewallTitle": "Брандмауэр блокирует порт {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "Адреса серверов вида 100.x.x.x или *.ts.net доступны через Tailscale — оставьте его ВКЛЮЧЁННЫМ.", "macosFirewall": "macOS: Системные настройки → Сеть → Брандмауэр — разрешите подключения для Orca.", "notificationNetwork": "Переключитесь на мобильную сеть или другую сеть Wi-Fi. Если уведомления начнут приходить, возможно, ваша сеть задерживает их доставку.", diff --git a/mobile/src/i18n/locales/tr.json b/mobile/src/i18n/locales/tr.json index 23ec987e1d8..79b56a695a5 100644 --- a/mobile/src/i18n/locales/tr.json +++ b/mobile/src/i18n/locales/tr.json @@ -1102,7 +1102,8 @@ "checkTailnet": "Bilgisayarınızın uyku modunda olmadığını ve tailnet ağınızda bağlı göründüğünü kontrol edin.", "desktopTitle": "Masaüstü Uygulaması Çalışmıyor", "disableVpn": "Bu VPN'i devre dışı bırakın veya bölünmüş tünellemeyi / \"Allow LAN\" seçeneğini etkinleştirin.", - "firewallTitle": "Güvenlik Duvarı 6768 Portunu Engelliyor", + "firewallTitle": "Güvenlik Duvarı {{port}} Portunu Engelliyor", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "100.x.x.x veya *.ts.net gibi sunucu adreslerine Tailscale üzerinden bağlanılır — Tailscale'i AÇIK tutun.", "macosFirewall": "macOS: System Settings → Network → Firewall — Orca'ya izin verin.", "notificationNetwork": "Hücresel bağlantıyı veya başka bir Wi-Fi ağını deneyin. Ağ değiştirdikten sonra bildirimler geliyorsa ağınız iletimi geciktiriyor olabilir.", diff --git a/mobile/src/i18n/locales/zh-Hant.json b/mobile/src/i18n/locales/zh-Hant.json index 1d7dbfe242e..f5433c89099 100644 --- a/mobile/src/i18n/locales/zh-Hant.json +++ b/mobile/src/i18n/locales/zh-Hant.json @@ -1098,7 +1098,8 @@ "checkTailnet": "確認電腦未進入睡眠,且在您的 tailnet 中顯示為已連線。", "desktopTitle": "桌面版應用程式未執行", "disableVpn": "停用該 VPN,或啟用分割通道/「允許 LAN」。", - "firewallTitle": "防火牆封鎖連接埠 6768", + "firewallTitle": "防火牆封鎖連接埠 {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "100.x.x.x 或 *.ts.net 等主機位址會透過 Tailscale 連線,請保持 Tailscale 開啟。", "macosFirewall": "macOS:「系統設定」→「網路」→「防火牆」,允許 Orca 連線。", "notificationNetwork": "試著改用行動網路或其他 Wi-Fi 網路。若切換後能收到通知,原本的網路可能導致通知延遲送達。", diff --git a/mobile/src/i18n/locales/zh.json b/mobile/src/i18n/locales/zh.json index 2d25a6f0cdb..61c8a120cde 100644 --- a/mobile/src/i18n/locales/zh.json +++ b/mobile/src/i18n/locales/zh.json @@ -1098,7 +1098,8 @@ "checkTailnet": "确认桌面未休眠,并在 tailnet 中显示为已连接。", "desktopTitle": "桌面应用未运行", "disableVpn": "关闭该 VPN,或启用分流功能/“允许 LAN”选项。", - "firewallTitle": "防火墙拦截端口 6768", + "firewallTitle": "防火墙拦截端口 {{port}}", + "linuxFirewall": "Linux: sudo ufw allow {{port}}", "keepTailscaleOn": "100.x.x.x 或 *.ts.net 等主机地址通过 Tailscale 连接,请保持 Tailscale 开启。", "macosFirewall": "macOS:系统设置 → 网络 → 防火墙,允许 Orca 通过。", "notificationNetwork": "尝试切换到蜂窝网络或其他 Wi-Fi 网络。如果切换后能收到通知,则原网络可能导致通知延迟。",