mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 08:03:20 +00:00
fix(relay): share the diagnostics payload with the settings pane
The Settings → Mobile pane had its own inline "Copy diagnostics" builder that still wrote the selected address into a payload users are asked to share, and lacked the relay status and app version. Both entry points now call one collectMobileRelayDiagnosticsPayload, so they emit one shape with no network identifier. RelayDrainRetrySchedule reuses relayRetryDelayMs instead of carrying a second copy of the same backoff constants and formula. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
11ad3776f7
commit
fb135c95f7
@@ -1,5 +1,4 @@
|
||||
const RETRY_BASE_MS = 1_000
|
||||
const RETRY_MAX_MS = 5 * 60_000
|
||||
import { relayRetryDelayMs } from './relay-retry-delay'
|
||||
|
||||
export class RelayDrainRetrySchedule {
|
||||
private timer: ReturnType<typeof setTimeout> | null = null
|
||||
@@ -15,10 +14,8 @@ export class RelayDrainRetrySchedule {
|
||||
if (this.timer) {
|
||||
return
|
||||
}
|
||||
const exponent = Math.min(this.attempt, Math.ceil(Math.log2(RETRY_MAX_MS / RETRY_BASE_MS)))
|
||||
const capMs = Math.min(RETRY_MAX_MS, RETRY_BASE_MS * 2 ** exponent)
|
||||
const jitterMs = relayRetryDelayMs(this.attempt, this.random)
|
||||
this.attempt++
|
||||
const jitterMs = Math.floor(this.random() * (capMs + 1))
|
||||
this.timer = setTimeout(
|
||||
() => {
|
||||
this.timer = null
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react
|
||||
import { toast } from 'sonner'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
import { useAppStore } from '@/store'
|
||||
import { resolveClientEnvironmentInfo } from '@/lib/client-environment-info'
|
||||
import type { Platform, StepIndex } from './MobileHero'
|
||||
import type { IosChannel } from './mobile-platform-copy'
|
||||
import type { MobileNetworkInterface } from '../settings/mobile-network-interface-selection'
|
||||
@@ -20,7 +19,7 @@ import { useMobilePairingQrInvalidation } from './use-mobile-pairing-qr-invalida
|
||||
import { useMobileInstallActions } from './use-mobile-install-actions'
|
||||
import { useMobilePagePairedDevices } from './use-mobile-page-paired-devices'
|
||||
import type { MobileRelayMintFailure } from '../../../../shared/mobile-relay-mint-failure'
|
||||
import { buildMobileRelayDiagnosticsPayload } from './mobile-relay-diagnostics-payload'
|
||||
import { collectMobileRelayDiagnosticsPayload } from './mobile-relay-diagnostics-payload'
|
||||
import {
|
||||
type MobilePairingAddressChange,
|
||||
useMobilePairingAddressPreference
|
||||
@@ -149,18 +148,9 @@ export default function MobilePage(): React.JSX.Element {
|
||||
return
|
||||
}
|
||||
// Why: users share this payload — an address (selected or relay cell) would leak a LAN/Tailscale IP or hostname.
|
||||
const [relayStatus, environment] = await Promise.all([
|
||||
window.api.mobile
|
||||
.getRelayStatus()
|
||||
.then((detail) => detail.status)
|
||||
.catch(() => 'offline' as const),
|
||||
resolveClientEnvironmentInfo()
|
||||
])
|
||||
const payload = buildMobileRelayDiagnosticsPayload({
|
||||
const payload = await collectMobileRelayDiagnosticsPayload({
|
||||
connectionMode,
|
||||
failure: relayMintFailure,
|
||||
relayStatus,
|
||||
appVersion: environment.appVersion
|
||||
failure: relayMintFailure
|
||||
})
|
||||
try {
|
||||
await window.api.ui.writeClipboardText(JSON.stringify(payload, null, 2))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { MobilePairingConnectionMode } from '../../../../shared/mobile-pairing-connection-mode'
|
||||
import type { MobileRelayMintFailure } from '../../../../shared/mobile-relay-mint-failure'
|
||||
import type { MobileRelayStatus } from '../../../../shared/mobile-relay-status'
|
||||
import { resolveClientEnvironmentInfo } from '@/lib/client-environment-info'
|
||||
|
||||
export type MobileRelayDiagnosticsPayload = {
|
||||
kind: 'mobile_pairing_relay_failure'
|
||||
@@ -28,3 +29,23 @@ export function buildMobileRelayDiagnosticsPayload(args: {
|
||||
at: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
|
||||
// Why here rather than at each call site: both "Copy diagnostics" buttons must
|
||||
// fetch the same two fields the same way, and MobilePane sits at the line ceiling.
|
||||
export async function collectMobileRelayDiagnosticsPayload(args: {
|
||||
connectionMode: MobilePairingConnectionMode
|
||||
failure: MobileRelayMintFailure
|
||||
}): Promise<MobileRelayDiagnosticsPayload> {
|
||||
const [relayStatus, environment] = await Promise.all([
|
||||
window.api.mobile
|
||||
.getRelayStatus()
|
||||
.then((detail) => detail.status)
|
||||
.catch(() => 'offline' as const),
|
||||
resolveClientEnvironmentInfo()
|
||||
])
|
||||
return buildMobileRelayDiagnosticsPayload({
|
||||
...args,
|
||||
relayStatus,
|
||||
appVersion: environment.appVersion
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { MobileAutoRestoreFitSection } from './MobileAutoRestoreFitSection'
|
||||
import { MobilePairingConnectionOptions } from './MobilePairingConnectionOptions'
|
||||
import { MobilePairingSetupSection } from './MobilePairingSetupSection'
|
||||
import { MobileRelayMintFailureNotice } from '../mobile/mobile-relay-mint-failure-notice'
|
||||
import { collectMobileRelayDiagnosticsPayload } from '../mobile/mobile-relay-diagnostics-payload'
|
||||
import { WindowsFirewallNotice } from '../mobile/WindowsFirewallNotice'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import {
|
||||
@@ -300,20 +301,13 @@ export function MobilePane(): React.JSX.Element {
|
||||
if (relayMintFailure == null) {
|
||||
return
|
||||
}
|
||||
// Why: users share this payload, so it carries no address (selected or relay cell).
|
||||
const payload = await collectMobileRelayDiagnosticsPayload({
|
||||
connectionMode,
|
||||
failure: relayMintFailure
|
||||
})
|
||||
try {
|
||||
await window.api.ui.writeClipboardText(
|
||||
JSON.stringify(
|
||||
{
|
||||
kind: 'mobile_pairing_relay_failure',
|
||||
preferredConnectionMode: connectionMode,
|
||||
failure: relayMintFailure,
|
||||
selectedAddress: selectedAddress ?? null,
|
||||
at: new Date().toISOString()
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
)
|
||||
await window.api.ui.writeClipboardText(JSON.stringify(payload, null, 2))
|
||||
if (mountedRef.current) {
|
||||
toast.success(
|
||||
translate('auto.components.settings.MobilePane.diagnosticsCopied', 'Diagnostics copied')
|
||||
@@ -329,7 +323,7 @@ export function MobilePane(): React.JSX.Element {
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [connectionMode, mountedRef, relayMintFailure, selectedAddress])
|
||||
}, [connectionMode, mountedRef, relayMintFailure])
|
||||
|
||||
// Why: another window can persist a different path; the shared hook syncs
|
||||
// connectionMode here without routing through changeConnectionMode. Treat
|
||||
|
||||
Reference in New Issue
Block a user