chore(k1): checkpoint connection recovery work

This commit is contained in:
DCCONSTRUCTIONS
2026-08-21 08:12:22 +03:00
parent a3138f3d71
commit c7843a3c7e
22 changed files with 969 additions and 293 deletions
@@ -27,6 +27,7 @@ import {
recoverableAcquisition,
requiresCanonicalStopAfterTerminalLocalFailure,
requiresReadOnlyPhysicalRecovery,
savedBridgeRequiresNetworkSetup,
sourceStatusLabel,
} from "./lifecycle";
import { phaseLabel, phaseTone } from "./presentation";
@@ -34,6 +35,7 @@ import {
useXgridsK1Controller,
type XgridsK1Controller,
} from "./runtimeContext";
import type { PendingAction } from "./useXgridsK1Runtime";
import type { XgridsK1State } from "./api";
import {
DEFAULT_CONNECTION_MODE,
@@ -59,6 +61,9 @@ export function physicalRecoveryConnectionDetail(
state: XgridsK1State | null | undefined,
): string | null {
if (!requiresReadOnlyPhysicalRecovery(state)) return null;
if (savedBridgeRequiresNetworkSetup(state)) {
return "K1 ответил по Bluetooth, но не подключён к сохранённой общей сети. Настройки устройства не изменялись; подключите K1 к общей сети заново.";
}
const retirementAvailable = Boolean(
unavailablePhysicalRetirementAuthority(state),
);
@@ -91,9 +96,11 @@ function connectionPhaseFallbackLabel(phase: string | null | undefined): string
*/
export function shouldRenderK1OperationalPanels(
state: XgridsK1State | null | undefined,
pendingAction: PendingAction | null = null,
): boolean {
return Boolean(
hasControlAuthority(state)
pendingAction === "live"
|| hasControlAuthority(state)
|| state?.source_mode === "live"
|| state?.source_mode === "replay"
|| recoverableAcquisition(state)
@@ -167,11 +174,13 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
const confirmedLive = isConfirmedLiveState(state);
const sourceRuntimeBusy = isSourceRuntimeBusy(state);
const livePreparationPending = controller.pendingAction === "live";
const preparedAcquisition = recoverableAcquisition(state)?.state === "prepared";
const activeRecoveryPresentation = activeStreamRecoveryPresentation(state);
const sourceLabel = activeRecoveryPresentation?.title ?? sourceStatusLabel(state);
const releasedAcquisitionFailure = isReleasedTerminalAcquisitionFailure(state);
const physicalRecoveryRequired = requiresReadOnlyPhysicalRecovery(state);
const savedBridgeNetworkSetupRequired = savedBridgeRequiresNetworkSetup(state);
const physicalStopRecoverySettling = isPhysicalStopRecoverySettling(state);
const recoveredPhysicalScanning = physicalRecoveryRequired
&& state?.application_control_session?.state === "scanning"
@@ -265,7 +274,9 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: sourceRuntimeBusy || preparedAcquisition
? "warning"
: "neutral";
const connectionPhaseLabel = sourceRuntimeBusy || preparedAcquisition
const connectionPhaseLabel = livePreparationPending
? "Подготовка приёма"
: sourceRuntimeBusy || preparedAcquisition
? sourceLabel
: activeRecoveryPresentation
? activeRecoveryPresentation.title
@@ -274,7 +285,9 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: recoveredPhysicalScanning
? "Сканирование продолжается"
: physicalRecoveryRequired
? "Требуется действие"
? savedBridgeNetworkSetupRequired
? "Нужна настройка сети"
: "Требуется действие"
: projectedPhase === "error"
? connectionPhaseFallbackLabel(projectedPhase)
: connectionTopology?.status === "active"
@@ -288,7 +301,9 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: connectionTopology?.source === "last-known"
? "Подключение отсутствует"
: connectionPhaseFallbackLabel(projectedPhase);
const connectionPhaseTone = sourceRuntimeBusy || preparedAcquisition
const connectionPhaseTone = livePreparationPending
? "warning"
: sourceRuntimeBusy || preparedAcquisition
? sourceTone
: activeRecoveryPresentation
? activeRecoveryPresentation.tone
@@ -301,7 +316,9 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: connectionTopology?.status === "configured-unverified"
? "neutral"
: "neutral";
const connectionPhaseDetail = physicalStopRecoverySettling
const connectionPhaseDetail = livePreparationPending
? "Подготовка продолжается."
: physicalStopRecoverySettling
? "Команда остановки уже принята. Завершение выполняется без повторной команды."
: activeRecoveryPresentation
? activeRecoveryPresentation.detail
@@ -315,7 +332,10 @@ export function XgridsK1Connection({ model, host }: DevicePluginConnectionProps)
: !sourceRuntimeBusy && connectionTopology?.status === "active"
? "Готово к новой сессии."
: "Ожидается состояние локального контура.";
const operationalPanelsVisible = shouldRenderK1OperationalPanels(state);
const operationalPanelsVisible = shouldRenderK1OperationalPanels(
state,
controller.pendingAction,
);
return (
<div className="device-workspace xgrids-k1-plugin">