mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 01:57:57 +00:00
Remove preview link from mobile setup (#35619)
* Revert incorrect mobile download destination * Remove mobile preview install option
This commit is contained in:
@@ -76,8 +76,7 @@ describe('HeroFlow height', () => {
|
||||
platform="ios"
|
||||
onPlatformChange={vi.fn()}
|
||||
installQrUrl={null}
|
||||
iosChannel="preview"
|
||||
onIosChannelChange={vi.fn()}
|
||||
installCopy={{ ctaLabel: 'Open TestFlight', url: 'https://example.com' }}
|
||||
onOpenAndroidInstallGuide={vi.fn()}
|
||||
onOpenInstallUrl={vi.fn()}
|
||||
onCopyInstallUrl={vi.fn()}
|
||||
@@ -123,8 +122,7 @@ describe('HeroFlow height', () => {
|
||||
platform="ios"
|
||||
onPlatformChange={vi.fn()}
|
||||
installQrUrl={null}
|
||||
iosChannel="preview"
|
||||
onIosChannelChange={vi.fn()}
|
||||
installCopy={{ ctaLabel: 'Open TestFlight', url: 'https://example.com' }}
|
||||
onOpenAndroidInstallGuide={vi.fn()}
|
||||
onOpenInstallUrl={vi.fn()}
|
||||
onCopyInstallUrl={vi.fn()}
|
||||
@@ -165,6 +163,7 @@ describe('HeroFlow height', () => {
|
||||
const onOpenAndroidInstallGuide = vi.fn()
|
||||
renderFlow(0, {
|
||||
platform: 'android',
|
||||
installCopy: { ctaLabel: 'Download APK', url: 'https://example.com/app-release.apk' },
|
||||
onOpenAndroidInstallGuide
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ArrowLeft, ArrowRight, Copy } from 'lucide-react'
|
||||
import { cn } from '../../lib/utils'
|
||||
import type { MobileNetworkInterface } from '../settings/mobile-network-interface-selection'
|
||||
import { AndroidLogo, IosBrandIcon } from './MobileBrandIcons'
|
||||
import { getChannelTagline, type IosChannel } from './mobile-platform-copy'
|
||||
import type { InstallCopy } from './mobile-platform-copy'
|
||||
import type { MobilePairingConnectionMode } from '../../../../shared/mobile-pairing-connection-mode'
|
||||
import type { MobileRelayMintFailure } from '../../../../shared/mobile-relay-mint-failure'
|
||||
import { MobileHeroPairingStep } from './MobileHeroPairingStep'
|
||||
@@ -20,8 +20,7 @@ type HeroFlowProps = {
|
||||
platform: Platform
|
||||
onPlatformChange: (next: Platform) => void
|
||||
installQrUrl: string | null
|
||||
iosChannel: IosChannel
|
||||
onIosChannelChange: (next: IosChannel) => void
|
||||
installCopy: InstallCopy
|
||||
onOpenAndroidInstallGuide: () => void
|
||||
onOpenInstallUrl: () => void
|
||||
onCopyInstallUrl: () => void
|
||||
@@ -59,8 +58,7 @@ export function HeroFlow({
|
||||
platform,
|
||||
onPlatformChange,
|
||||
installQrUrl,
|
||||
iosChannel,
|
||||
onIosChannelChange,
|
||||
installCopy,
|
||||
onOpenAndroidInstallGuide,
|
||||
onOpenInstallUrl,
|
||||
onCopyInstallUrl,
|
||||
@@ -164,39 +162,9 @@ export function HeroFlow({
|
||||
{translate('auto.components.mobile.MobileHero.ac1eb64952', 'Android')}
|
||||
</button>
|
||||
</div>
|
||||
{platform === 'ios' ? (
|
||||
<div
|
||||
className="mp-channel-toggle"
|
||||
role="radiogroup"
|
||||
aria-label={translate(
|
||||
'auto.components.mobile.MobileHero.channel.group',
|
||||
'Release channel'
|
||||
)}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={iosChannel === 'preview'}
|
||||
className={cn(iosChannel === 'preview' && 'is-active')}
|
||||
onClick={() => onIosChannelChange('preview')}
|
||||
>
|
||||
{translate('auto.components.mobile.MobileHero.channel.preview', 'Preview')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={iosChannel === 'stable'}
|
||||
className={cn(iosChannel === 'stable' && 'is-active')}
|
||||
onClick={() => onIosChannelChange('stable')}
|
||||
>
|
||||
{translate('auto.components.mobile.MobileHero.channel.stable', 'Stable')}
|
||||
</button>
|
||||
<span className="mp-channel-tagline">{getChannelTagline(iosChannel)}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="mp-inline-actions">
|
||||
<button type="button" className="mp-ghost-action" onClick={onOpenInstallUrl}>
|
||||
{translate('auto.components.mobile.MobileHero.downloadApp', 'Download app')}
|
||||
{installCopy.ctaLabel}
|
||||
</button>
|
||||
<button type="button" className="mp-text-link" onClick={onCopyInstallUrl}>
|
||||
<Copy className="size-3.5" />
|
||||
|
||||
@@ -3,7 +3,6 @@ import { toast } from 'sonner'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
import { useAppStore } from '@/store'
|
||||
import type { Platform, StepIndex } from './MobileHero'
|
||||
import type { IosChannel } from './mobile-platform-copy'
|
||||
import type { MobileNetworkInterface } from '../settings/mobile-network-interface-selection'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { useMobilePageEscape } from './use-mobile-page-escape'
|
||||
@@ -28,8 +27,6 @@ export default function MobilePage(): React.JSX.Element {
|
||||
const [stepIdx, setStepIdx] = useState<StepIndex>(0)
|
||||
|
||||
const [platform, setPlatform] = useState<Platform>('ios')
|
||||
// Default to the daily iOS preview unless the user chooses the public release.
|
||||
const [iosChannel, setIosChannel] = useState<IosChannel>('preview')
|
||||
|
||||
const [pairQrDataUrl, setPairQrDataUrl] = useState<string | null>(null)
|
||||
const [pairQrSize, setPairQrSize] = useState<number | null>(null)
|
||||
@@ -80,11 +77,9 @@ export default function MobilePage(): React.JSX.Element {
|
||||
showPairedDevices,
|
||||
stage
|
||||
} = useMobilePagePairedDevices({ stepIdx, setStepIdx })
|
||||
const installQrUrl = useMobileInstallQr(stage, platform, iosChannel)
|
||||
const { copyInstallUrl, openAndroidInstallGuide, openInstallUrl } = useMobileInstallActions(
|
||||
platform,
|
||||
iosChannel
|
||||
)
|
||||
const installQrUrl = useMobileInstallQr(stage, platform)
|
||||
const { copyInstallUrl, openAndroidInstallGuide, openInstallUrl } =
|
||||
useMobileInstallActions(platform)
|
||||
|
||||
const { generatePairing } = useMobilePairingGeneration({
|
||||
connectionMode,
|
||||
@@ -339,8 +334,6 @@ export default function MobilePage(): React.JSX.Element {
|
||||
handleBack={handleBack}
|
||||
handleContinue={handleContinue}
|
||||
installQrUrl={installQrUrl}
|
||||
iosChannel={iosChannel}
|
||||
setIosChannel={setIosChannel}
|
||||
loadNetworkInterfaces={() => void loadNetworkInterfaces()}
|
||||
networkInterfaces={networkInterfaces}
|
||||
openAndroidInstallGuide={openAndroidInstallGuide}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
type Platform,
|
||||
type StepIndex
|
||||
} from './MobileHero'
|
||||
import type { IosChannel } from './mobile-platform-copy'
|
||||
import { getInstallCopy } from './mobile-platform-copy'
|
||||
import type { MobilePageStage } from './mobile-page-stage'
|
||||
import { MobilePageToolbar } from './MobilePageToolbar'
|
||||
import { PhoneCarousel } from './PhoneCarousel'
|
||||
@@ -32,8 +32,6 @@ type MobilePageContentProps = {
|
||||
handleBack: () => void
|
||||
handleContinue: () => void
|
||||
installQrUrl: string | null
|
||||
iosChannel: IosChannel
|
||||
setIosChannel: (channel: IosChannel) => void
|
||||
loadNetworkInterfaces: () => void
|
||||
networkInterfaces: MobileNetworkInterface[]
|
||||
openAndroidInstallGuide: () => void
|
||||
@@ -80,8 +78,6 @@ export function MobilePageContent({
|
||||
handleBack,
|
||||
handleContinue,
|
||||
installQrUrl,
|
||||
iosChannel,
|
||||
setIosChannel,
|
||||
loadNetworkInterfaces,
|
||||
networkInterfaces,
|
||||
openAndroidInstallGuide,
|
||||
@@ -134,8 +130,7 @@ export function MobilePageContent({
|
||||
platform={platform}
|
||||
onPlatformChange={setPlatform}
|
||||
installQrUrl={installQrUrl}
|
||||
iosChannel={iosChannel}
|
||||
onIosChannelChange={setIosChannel}
|
||||
installCopy={getInstallCopy(platform)}
|
||||
onOpenAndroidInstallGuide={openAndroidInstallGuide}
|
||||
onOpenInstallUrl={openInstallUrl}
|
||||
onCopyInstallUrl={copyInstallUrl}
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import type { Platform } from './MobileHero'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
|
||||
// iOS offers App Store and TestFlight tracks; Android has a single APK track.
|
||||
export type IosChannel = 'stable' | 'preview'
|
||||
export type InstallCopy = { ctaLabel: string; url: string }
|
||||
|
||||
export const ANDROID_INSTALL_GUIDE_URL = 'https://www.onorca.dev/docs/android-apk'
|
||||
|
||||
const IOS_CHANNEL_URLS: Record<IosChannel, string> = {
|
||||
stable: 'https://apps.apple.com/app/orca-ide/id6766130217',
|
||||
preview: 'https://testflight.apple.com/join/YjeGMQBA'
|
||||
}
|
||||
|
||||
const ANDROID_INSTALL_URL = 'https://www.onorca.dev/download/android'
|
||||
|
||||
export function getInstallCopy(platform: Platform, iosChannel: IosChannel): { url: string } {
|
||||
return { url: platform === 'ios' ? IOS_CHANNEL_URLS[iosChannel] : ANDROID_INSTALL_URL }
|
||||
}
|
||||
|
||||
export function getChannelTagline(iosChannel: IosChannel): string {
|
||||
return iosChannel === 'preview'
|
||||
? translate(
|
||||
'auto.components.mobile.mobile.platform.copy.preview.tagline',
|
||||
'Newest features, updated daily.'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.mobile.platform.copy.stable.tagline',
|
||||
'The public release, updated weekly.'
|
||||
)
|
||||
export function getInstallCopy(platform: Platform): InstallCopy {
|
||||
return platform === 'ios'
|
||||
? {
|
||||
ctaLabel: translate(
|
||||
'auto.components.mobile.mobile.platform.copy.openAppStore',
|
||||
'Open App Store'
|
||||
),
|
||||
url: 'https://apps.apple.com/app/orca-ide/id6766130217'
|
||||
}
|
||||
: {
|
||||
ctaLabel: translate(
|
||||
'auto.components.mobile.mobile.platform.copy.downloadApk',
|
||||
'Download APK'
|
||||
),
|
||||
url: 'https://www.onorca.dev/download/android'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { cleanup, renderHook } from '@testing-library/react'
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
import { useMobileInstallActions } from './use-mobile-install-actions'
|
||||
|
||||
afterEach(cleanup)
|
||||
|
||||
it.each([
|
||||
['ios', 'preview'],
|
||||
['ios', 'stable'],
|
||||
['android', 'stable']
|
||||
] as const)('opens the download page for %s and %s', (platform, channel) => {
|
||||
const openUrl = vi.fn()
|
||||
Object.defineProperty(window, 'api', { configurable: true, value: { shell: { openUrl } } })
|
||||
const { result } = renderHook(() => useMobileInstallActions(platform, channel))
|
||||
|
||||
result.current.openInstallUrl()
|
||||
|
||||
expect(openUrl).toHaveBeenCalledWith('https://onorca.dev/download')
|
||||
})
|
||||
@@ -3,12 +3,9 @@ import { toast } from 'sonner'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { Platform } from './MobileHero'
|
||||
import { ANDROID_INSTALL_GUIDE_URL, getInstallCopy, type IosChannel } from './mobile-platform-copy'
|
||||
import { ANDROID_INSTALL_GUIDE_URL, getInstallCopy } from './mobile-platform-copy'
|
||||
|
||||
export function useMobileInstallActions(
|
||||
platform: Platform,
|
||||
iosChannel: IosChannel
|
||||
): {
|
||||
export function useMobileInstallActions(platform: Platform): {
|
||||
copyInstallUrl: () => Promise<void>
|
||||
openAndroidInstallGuide: () => void
|
||||
openInstallUrl: () => void
|
||||
@@ -16,8 +13,8 @@ export function useMobileInstallActions(
|
||||
const mountedRef = useMountedRef()
|
||||
|
||||
const openInstallUrl = useCallback((): void => {
|
||||
void window.api.shell.openUrl('https://onorca.dev/download')
|
||||
}, [])
|
||||
void window.api.shell.openUrl(getInstallCopy(platform).url)
|
||||
}, [platform])
|
||||
|
||||
const openAndroidInstallGuide = useCallback((): void => {
|
||||
void window.api.shell.openUrl(ANDROID_INSTALL_GUIDE_URL)
|
||||
@@ -25,7 +22,7 @@ export function useMobileInstallActions(
|
||||
|
||||
const copyInstallUrl = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
await window.api.ui.writeClipboardText(getInstallCopy(platform, iosChannel).url)
|
||||
await window.api.ui.writeClipboardText(getInstallCopy(platform).url)
|
||||
if (mountedRef.current) {
|
||||
toast.success(
|
||||
translate('auto.components.mobile.MobilePage.fad833de8d', 'Install link copied')
|
||||
@@ -39,7 +36,7 @@ export function useMobileInstallActions(
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [iosChannel, mountedRef, platform])
|
||||
}, [mountedRef, platform])
|
||||
|
||||
return { copyInstallUrl, openAndroidInstallGuide, openInstallUrl }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import QRCodeBrowser from 'qrcode/lib/browser'
|
||||
import type { Platform } from './MobileHero'
|
||||
import { getInstallCopy, type IosChannel } from './mobile-platform-copy'
|
||||
import { getInstallCopy } from './mobile-platform-copy'
|
||||
import type { MobilePageStage } from './mobile-page-stage'
|
||||
|
||||
async function renderQrDataUrl(text: string): Promise<string> {
|
||||
@@ -14,8 +14,7 @@ async function renderQrDataUrl(text: string): Promise<string> {
|
||||
|
||||
export function useMobileInstallQr(
|
||||
stage: MobilePageStage | null,
|
||||
platform: Platform,
|
||||
iosChannel: IosChannel
|
||||
platform: Platform
|
||||
): string | null {
|
||||
const [installQrUrl, setInstallQrUrl] = useState<string | null>(null)
|
||||
|
||||
@@ -28,7 +27,7 @@ export function useMobileInstallQr(
|
||||
let cancelled = false
|
||||
void (async () => {
|
||||
try {
|
||||
const dataUrl = await renderQrDataUrl(getInstallCopy(platform, iosChannel).url)
|
||||
const dataUrl = await renderQrDataUrl(getInstallCopy(platform).url)
|
||||
if (!cancelled) {
|
||||
setInstallQrUrl(dataUrl)
|
||||
}
|
||||
@@ -41,7 +40,7 @@ export function useMobileInstallQr(
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [platform, iosChannel, stage])
|
||||
}, [platform, stage])
|
||||
|
||||
return installQrUrl
|
||||
}
|
||||
|
||||
@@ -14665,7 +14665,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "App herunterladen",
|
||||
"a8fb43cf1c": "Fortfahren",
|
||||
"3f90dbd274": "Abschließen",
|
||||
"b622eba64d": "Zurück",
|
||||
@@ -14698,11 +14697,6 @@
|
||||
"e59a252eca": "Code erneut generieren",
|
||||
"d0b52871ce": "Die Smartphones sind gekoppelt.",
|
||||
"051978a785": "Das Smartphone ist gekoppelt.",
|
||||
"channel": {
|
||||
"group": "Veröffentlichungskanal",
|
||||
"preview": "Vorschau",
|
||||
"stable": "Stabil"
|
||||
},
|
||||
"pairingQrError": "Dieser Kopplungscode konnte nicht als QR-Code dargestellt werden. Stattdessen in Orca Mobile kopieren.",
|
||||
"noRelayCode": "Kein Kopplungscode verfügbar",
|
||||
"noPairingCode": "Kein Kopplungscode verfügbar",
|
||||
@@ -14749,12 +14743,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Neueste Funktionen, täglich aktualisiert."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "Die öffentliche Version, wöchentlich aktualisiert."
|
||||
}
|
||||
"downloadApk": "APK herunterladen",
|
||||
"openAppStore": "App Store öffnen"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14733,11 +14733,6 @@
|
||||
"e59a252eca": "Regenerate code",
|
||||
"d0b52871ce": "Your phones are paired.",
|
||||
"051978a785": "Your phone is paired.",
|
||||
"channel": {
|
||||
"group": "Release channel",
|
||||
"preview": "Preview",
|
||||
"stable": "Stable"
|
||||
},
|
||||
"pairingQrError": "This pairing code couldn’t be rendered as a QR code. Copy it into Orca Mobile instead.",
|
||||
"noRelayCode": "No pairing code available",
|
||||
"noPairingCode": "No pairing code available",
|
||||
@@ -14753,8 +14748,7 @@
|
||||
"androidHelp": {
|
||||
"guide": "Install guide"
|
||||
},
|
||||
"openAppAndScan": "Open Orca Mobile, tap <strong>Pair Desktop</strong>, and scan the code.",
|
||||
"downloadApp": "Download app"
|
||||
"openAppAndScan": "Open Orca Mobile, tap <strong>Pair Desktop</strong>, and scan the code."
|
||||
},
|
||||
"MobilePage": {
|
||||
"e17393c6a3": "Phone preview",
|
||||
@@ -14785,12 +14779,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Newest features, updated daily."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "The public release, updated weekly."
|
||||
}
|
||||
"downloadApk": "Download APK",
|
||||
"openAppStore": "Open App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14531,7 +14531,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "Descargar la aplicación",
|
||||
"a8fb43cf1c": "Continuar",
|
||||
"3f90dbd274": "Hecho",
|
||||
"b622eba64d": "Atrás",
|
||||
@@ -14564,11 +14563,6 @@
|
||||
"e59a252eca": "Regenerar código",
|
||||
"d0b52871ce": "Tus teléfonos están emparejados.",
|
||||
"051978a785": "Tu teléfono está emparejado.",
|
||||
"channel": {
|
||||
"group": "Canal de versión",
|
||||
"preview": "Vista previa",
|
||||
"stable": "Estable"
|
||||
},
|
||||
"pairingQrError": "Este código de emparejamiento no se pudo representar como código QR. Cópialo en Orca Mobile.",
|
||||
"directAddressDisclosure": "También usar una ruta local más rápida",
|
||||
"directAddressHint": "Opcional. Elige la dirección Wi‑Fi o Tailscale que el teléfono usará cuando esté cerca — suele ser más rápido que Relay. Relay sigue funcionando cuando estás fuera.",
|
||||
@@ -14615,12 +14609,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Las funciones más recientes, actualizadas a diario."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "La versión pública, actualizada semanalmente."
|
||||
}
|
||||
"downloadApk": "Descargar APK",
|
||||
"openAppStore": "Abrir App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14717,7 +14717,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "Télécharger l’application",
|
||||
"a8fb43cf1c": "Continuer",
|
||||
"3f90dbd274": "Terminé",
|
||||
"b622eba64d": "Retour",
|
||||
@@ -14750,11 +14749,6 @@
|
||||
"e59a252eca": "Régénérer le code",
|
||||
"d0b52871ce": "Vos téléphones sont appairés.",
|
||||
"051978a785": "Votre téléphone est appairé.",
|
||||
"channel": {
|
||||
"group": "Canal de release",
|
||||
"preview": "Aperçu",
|
||||
"stable": "Stable"
|
||||
},
|
||||
"pairingQrError": "Ce code d'appairage n'a pas pu être rendu sous forme de QR code. Copiez-le plutôt dans Orca Mobile.",
|
||||
"noRelayCode": "Aucun code d'appairage disponible",
|
||||
"noPairingCode": "Aucun code d'appairage disponible",
|
||||
@@ -14801,12 +14795,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Fonctionnalités les plus récentes, mises à jour chaque jour."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "La version publique, mise à jour chaque semaine."
|
||||
}
|
||||
"downloadApk": "Télécharger l'APK",
|
||||
"openAppStore": "Ouvrir l'App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14167,7 +14167,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "アプリをダウンロード",
|
||||
"a8fb43cf1c": "Continue",
|
||||
"3f90dbd274": "完了",
|
||||
"b622eba64d": "戻る",
|
||||
@@ -14200,11 +14199,6 @@
|
||||
"e59a252eca": "コードを再生成する",
|
||||
"d0b52871ce": "スマートフォンはペアリングされています。",
|
||||
"051978a785": "スマートフォンはペアリングされています。",
|
||||
"channel": {
|
||||
"group": "リリースチャンネル",
|
||||
"preview": "プレビュー",
|
||||
"stable": "安定版"
|
||||
},
|
||||
"pairingQrError": "このペアリングコードを QR コードとして表示できませんでした。代わりに Orca Mobile にコピーしてください。",
|
||||
"directAddressDisclosure": "より速いローカル経路も使う",
|
||||
"directAddressHint": "任意。近く(同じ Wi‑Fi または Tailscale)にいるときにスマホが使うアドレスを選びます。通常は Relay より高速です。外出中は引き続き Relay が使われます。",
|
||||
@@ -14251,12 +14245,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "最新機能を毎日更新。"
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "一般公開版、毎週更新。"
|
||||
}
|
||||
"downloadApk": "APK をダウンロード",
|
||||
"openAppStore": "App Store を開く"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14167,7 +14167,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "앱 다운로드",
|
||||
"a8fb43cf1c": "Continue",
|
||||
"3f90dbd274": "완료",
|
||||
"b622eba64d": "뒤로",
|
||||
@@ -14200,11 +14199,6 @@
|
||||
"e59a252eca": "코드 재생성",
|
||||
"d0b52871ce": "휴대전화가 페어링되었습니다.",
|
||||
"051978a785": "휴대전화가 페어링되었습니다.",
|
||||
"channel": {
|
||||
"group": "릴리스 채널",
|
||||
"preview": "미리 보기",
|
||||
"stable": "안정 버전"
|
||||
},
|
||||
"pairingQrError": "이 페어링 코드를 QR 코드로 표시할 수 없습니다. 대신 Orca Mobile에 복사하세요.",
|
||||
"directAddressDisclosure": "더 빠른 로컬 경로도 사용",
|
||||
"directAddressHint": "선택 사항. 근처에 있을 때(같은 Wi‑Fi 또는 Tailscale) 휴대폰이 사용할 주소를 고르세요. 보통 Relay보다 빠릅니다. 외부에 있을 때는 여전히 Relay를 사용합니다.",
|
||||
@@ -14251,12 +14245,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "최신 기능, 매일 업데이트."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "정식 출시 버전, 매주 업데이트."
|
||||
}
|
||||
"downloadApk": "APK 다운로드",
|
||||
"openAppStore": "App Store 열기"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15811,7 +15811,6 @@
|
||||
}
|
||||
},
|
||||
"MobileHero": {
|
||||
"downloadApp": "Baixar aplicativo",
|
||||
"a8fb43cf1c": "Continuar",
|
||||
"3f90dbd274": "Concluído",
|
||||
"b622eba64d": "Voltar",
|
||||
@@ -15844,11 +15843,6 @@
|
||||
"e59a252eca": "Gerar novo código",
|
||||
"d0b52871ce": "Seus celulares estão pareados.",
|
||||
"051978a785": "Seu celular está pareado.",
|
||||
"channel": {
|
||||
"group": "Canal de lançamento",
|
||||
"preview": "Preview",
|
||||
"stable": "Estável"
|
||||
},
|
||||
"pairingQrError": "Este código de pareamento não pôde ser renderizado como um código QR. Copie-o no Orca Mobile em vez disso.",
|
||||
"noRelayCode": "Nenhum código de pareamento disponível",
|
||||
"noPairingCode": "Nenhum código de pareamento disponível",
|
||||
@@ -15940,12 +15934,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Recursos mais novos, atualizados diariamente."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "O lançamento público, atualizado semanalmente."
|
||||
}
|
||||
"downloadApk": "Baixar APK",
|
||||
"openAppStore": "Abrir App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15067,7 +15067,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "Скачать приложение",
|
||||
"a8fb43cf1c": "Продолжить",
|
||||
"3f90dbd274": "Готово",
|
||||
"b622eba64d": "Назад",
|
||||
@@ -15100,11 +15099,6 @@
|
||||
"e59a252eca": "Создать новый код",
|
||||
"d0b52871ce": "Ваши телефоны подключены.",
|
||||
"051978a785": "Ваш телефон подключён.",
|
||||
"channel": {
|
||||
"group": "Канал выпуска",
|
||||
"preview": "Предварительный",
|
||||
"stable": "Стабильный"
|
||||
},
|
||||
"pairingQrError": "Не удалось представить этот код сопряжения как QR-код. Вместо этого скопируйте его в Orca Mobile.",
|
||||
"noRelayCode": "Код сопряжения недоступен",
|
||||
"noPairingCode": "Код сопряжения недоступен",
|
||||
@@ -15151,12 +15145,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "Новые возможности, обновления каждый день."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "Общедоступный выпуск, обновления каждую неделю."
|
||||
}
|
||||
"downloadApk": "Скачать APK",
|
||||
"openAppStore": "Открыть App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14651,7 +14651,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "Uygulamayı indir",
|
||||
"a8fb43cf1c": "Devam Et",
|
||||
"3f90dbd274": "Bitti",
|
||||
"b622eba64d": "Geri",
|
||||
@@ -14684,11 +14683,6 @@
|
||||
"e59a252eca": "Kodu yeniden oluştur",
|
||||
"d0b52871ce": "Telefonlarınız eşleştirildi.",
|
||||
"051978a785": "Telefonunuz eşleştirildi.",
|
||||
"channel": {
|
||||
"group": "Sürüm kanalı",
|
||||
"preview": "Önizleme",
|
||||
"stable": "Kararlı"
|
||||
},
|
||||
"pairingQrError": "Bu eşleştirme kodu QR koduna dönüştürülemedi. Bunun yerine kodu Orca Mobile'a kopyalayın.",
|
||||
"noRelayCode": "Kullanılabilir eşleştirme kodu yok",
|
||||
"noPairingCode": "Kullanılabilir eşleştirme kodu yok",
|
||||
@@ -14735,12 +14729,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "En yeni özellikler, günlük güncellenir."
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "Genel sürüm, haftalık güncellenir."
|
||||
}
|
||||
"downloadApk": "APK indir",
|
||||
"openAppStore": "App Store'u aç"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14485,7 +14485,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "下載應用程式",
|
||||
"a8fb43cf1c": "繼續",
|
||||
"3f90dbd274": "完成",
|
||||
"b622eba64d": "返回",
|
||||
@@ -14518,11 +14517,6 @@
|
||||
"e59a252eca": "重新產生配對碼",
|
||||
"d0b52871ce": "您的手機已配對。",
|
||||
"051978a785": "您的手機已配對。",
|
||||
"channel": {
|
||||
"group": "發布管道",
|
||||
"preview": "預覽版",
|
||||
"stable": "穩定版"
|
||||
},
|
||||
"pairingQrError": "無法將此配對碼呈現為 QR Code。請改為將其複製到 Orca Mobile。",
|
||||
"noRelayCode": "沒有可用的配對碼",
|
||||
"noPairingCode": "沒有可用的配對碼",
|
||||
@@ -14569,12 +14563,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "最新功能,每日更新。"
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "公開發布版,每週更新。"
|
||||
}
|
||||
"downloadApk": "下載 APK",
|
||||
"openAppStore": "開啟 App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14167,7 +14167,6 @@
|
||||
},
|
||||
"mobile": {
|
||||
"MobileHero": {
|
||||
"downloadApp": "下载应用",
|
||||
"a8fb43cf1c": "继续",
|
||||
"3f90dbd274": "完成",
|
||||
"b622eba64d": "返回",
|
||||
@@ -14200,11 +14199,6 @@
|
||||
"e59a252eca": "重新生成代码",
|
||||
"d0b52871ce": "您的手机已配对。",
|
||||
"051978a785": "您的手机已配对。",
|
||||
"channel": {
|
||||
"group": "发布渠道",
|
||||
"preview": "预览版",
|
||||
"stable": "稳定版"
|
||||
},
|
||||
"pairingQrError": "无法将此配对码呈现为二维码。请改为将其复制到 Orca Mobile。",
|
||||
"directAddressDisclosure": "也可使用更快的本地连接",
|
||||
"directAddressHint": "可选。选择手机在附近(同一 Wi‑Fi 或 Tailscale)时使用的地址,通常比 Relay 更快。外出时仍走 Relay。",
|
||||
@@ -14251,12 +14245,8 @@
|
||||
"mobile": {
|
||||
"platform": {
|
||||
"copy": {
|
||||
"preview": {
|
||||
"tagline": "最新功能,每日更新。"
|
||||
},
|
||||
"stable": {
|
||||
"tagline": "公开发布版,每周更新。"
|
||||
}
|
||||
"downloadApk": "下载 APK",
|
||||
"openAppStore": "打开 App Store"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user