Unify K1 discovery ownership and verification across enrollment paths
This commit is contained in:
@@ -3,7 +3,7 @@ import { Button } from "@nodedc/ui-react";
|
||||
|
||||
import type { XgridsConnectionAttempt } from "../api";
|
||||
import { hostFailureDiagnosticPresentation } from "../hostDiagnosticPresentation";
|
||||
import { STATION_WIFI_FAILURE_MESSAGES } from "../networkFailurePresentation";
|
||||
import { BLE_DISCOVERY_FAILURE_MESSAGES, STATION_WIFI_FAILURE_MESSAGES } from "../networkFailurePresentation";
|
||||
|
||||
const connectionAttemptStageLabels: Record<string, string> = {
|
||||
accepted: "Запрос принят",
|
||||
@@ -97,6 +97,7 @@ function publicConnectionErrorLabel(
|
||||
structured: ReturnType<typeof hostFailureDiagnosticPresentation>,
|
||||
): string {
|
||||
const publicCode = attempt?.public_error_code?.trim();
|
||||
if (attempt?.side_effect_status === "none" && publicCode && BLE_DISCOVERY_FAILURE_MESSAGES[publicCode]) return BLE_DISCOVERY_FAILURE_MESSAGES[publicCode];
|
||||
if (publicCode && publicConnectionErrorLabels[publicCode]) {
|
||||
return publicConnectionErrorLabels[publicCode];
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@ import {
|
||||
Button,
|
||||
GlassSurface,
|
||||
Icon,
|
||||
IconButton,
|
||||
Select,
|
||||
StatusBadge,
|
||||
TextField,
|
||||
type StatusTone,
|
||||
} from "@nodedc/ui-react";
|
||||
|
||||
import {K1WifiPasswordField} from "./K1WifiPasswordField";
|
||||
|
||||
import type {
|
||||
BleDevice,
|
||||
ConnectionVerifyRequest,
|
||||
@@ -1291,12 +1292,6 @@ export function K1ProvisioningPipeline({
|
||||
const [selectedDeviceSnapshot, setSelectedDeviceSnapshot] = useState<BleDevice | null>(null);
|
||||
const [ssid, setSsid] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [passwordVisible, setPasswordVisible] = useState(false);
|
||||
useEffect(() => {
|
||||
if (password.length === 0 && passwordVisible) {
|
||||
setPasswordVisible(false);
|
||||
}
|
||||
}, [password, passwordVisible]);
|
||||
const connectionMode = desiredMode;
|
||||
const [successfulLocalConnect, setSuccessfulLocalConnect] =
|
||||
useState<CompletedLocalNetworkIntent | null>(null);
|
||||
@@ -2729,7 +2724,6 @@ export function K1ProvisioningPipeline({
|
||||
setExplicitProvisioningDraft(null);
|
||||
setSsid("");
|
||||
setPassword("");
|
||||
setPasswordVisible(false);
|
||||
setConnectionAttemptPresentation(null);
|
||||
setCandidateUnavailableMessage(null);
|
||||
setReadOnlyReconnectPresentation(null);
|
||||
@@ -3107,31 +3101,13 @@ export function K1ProvisioningPipeline({
|
||||
spellCheck={false}
|
||||
placeholder={modeCopy.ssidPlaceholder}
|
||||
/>
|
||||
<div className="password-field-row">
|
||||
<TextField
|
||||
label="Пароль Wi‑Fi"
|
||||
hint={connectionAttemptOwnsDraft
|
||||
? "Удалён после отправки"
|
||||
: "Только в оперативной памяти"}
|
||||
type={passwordVisible ? "text" : "password"}
|
||||
value={connectionAttemptOwnsDraft ? "" : password}
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
disabled={provisioningFieldsDisabled}
|
||||
autoComplete="off"
|
||||
placeholder={connectionAttemptOwnsDraft
|
||||
? "Пароль передан"
|
||||
: "Введите пароль"}
|
||||
/>
|
||||
<IconButton
|
||||
label={passwordVisible ? "Скрыть пароль" : "Показать пароль"}
|
||||
shape="rounded"
|
||||
disabled={provisioningFieldsDisabled || password.length === 0}
|
||||
aria-pressed={passwordVisible}
|
||||
onClick={() => setPasswordVisible((visible) => !visible)}
|
||||
>
|
||||
<Icon name={passwordVisible ? "eye-off" : "eye"} />
|
||||
</IconButton>
|
||||
</div>
|
||||
<K1WifiPasswordField
|
||||
value={connectionAttemptOwnsDraft ? "" : password}
|
||||
onChange={setPassword}
|
||||
disabled={provisioningFieldsDisabled}
|
||||
hint={connectionAttemptOwnsDraft ? "Удалён после отправки" : "Только в оперативной памяти"}
|
||||
placeholder={connectionAttemptOwnsDraft ? "Пароль передан" : "Введите пароль"}
|
||||
/>
|
||||
{applyAction}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.password-field-row {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: end;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import {useEffect, useState} from 'react';
|
||||
import {Icon, IconButton, TextField} from '@nodedc/ui-react';
|
||||
import './K1WifiPasswordField.css';
|
||||
|
||||
/** The same Wi-Fi entry composition for direct and onboard K1 enrollment. */
|
||||
export function K1WifiPasswordField({value, onChange, disabled, hint, placeholder}: {
|
||||
value:string; onChange:(value:string)=>void; disabled?:boolean;
|
||||
hint?:string; placeholder?:string;
|
||||
}) {
|
||||
const [visible,setVisible]=useState(false);
|
||||
useEffect(()=>{if(!value)setVisible(false);},[value]);
|
||||
return <div className="password-field-row">
|
||||
<TextField label="Пароль Wi‑Fi" type={visible?'text':'password'} value={value}
|
||||
onChange={event=>onChange(event.target.value)} disabled={disabled}
|
||||
hint={hint} placeholder={placeholder} autoComplete="off" spellCheck={false}/>
|
||||
<IconButton label={visible?'Скрыть пароль':'Показать пароль'} shape="rounded"
|
||||
disabled={disabled||!value} aria-pressed={visible} onClick={()=>setVisible(current=>!current)}>
|
||||
<Icon name={visible?'eye-off':'eye'}/>
|
||||
</IconButton>
|
||||
</div>;
|
||||
}
|
||||
Reference in New Issue
Block a user