Revert "fix(settings): fix unsaved change detection for non-admin-message con…" (#1100)
This reverts commit 87043f35cb.
This commit is contained in:
@@ -9,7 +9,7 @@ import { PkiRegenerateDialog } from "@components/Dialog/PkiRegenerateDialog.tsx"
|
|||||||
import { createZodResolver } from "@components/Form/createZodResolver.ts";
|
import { createZodResolver } from "@components/Form/createZodResolver.ts";
|
||||||
import { DynamicForm, type DynamicFormFormInit } from "@components/Form/DynamicForm.tsx";
|
import { DynamicForm, type DynamicFormFormInit } from "@components/Form/DynamicForm.tsx";
|
||||||
import { useDevice } from "@core/stores";
|
import { useDevice } from "@core/stores";
|
||||||
import { deepCompareConfig, normalizeBytes } from "@core/utils/deepCompareConfig.ts";
|
import { deepCompareConfig } from "@core/utils/deepCompareConfig.ts";
|
||||||
import { getX25519PrivateKey, getX25519PublicKey } from "@core/utils/x25519.ts";
|
import { getX25519PrivateKey, getX25519PublicKey } from "@core/utils/x25519.ts";
|
||||||
import { fromByteArray, toByteArray } from "base64-js";
|
import { fromByteArray, toByteArray } from "base64-js";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
@@ -87,20 +87,7 @@ export const Security = ({ onFormInit }: SecurityConfigProps) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize empty byte arrays -> undefined for comparison so
|
if (deepCompareConfig(config.security, payload, true)) {
|
||||||
// empty base64 strings from the form match undefined/empty fields
|
|
||||||
// in the existing config and allow removeChange to work.
|
|
||||||
const normalizeSecurity = (s: ParsedSecurity | undefined) => {
|
|
||||||
if (!s) return s;
|
|
||||||
return {
|
|
||||||
...s,
|
|
||||||
privateKey: normalizeBytes(s.privateKey),
|
|
||||||
publicKey: normalizeBytes(s.publicKey),
|
|
||||||
adminKey: s.adminKey?.map((b) => normalizeBytes(b)) as unknown,
|
|
||||||
} as ParsedSecurity;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (deepCompareConfig(normalizeSecurity(config.security), normalizeSecurity(payload), true)) {
|
|
||||||
removeChange({ type: "config", variant: "security" });
|
removeChange({ type: "config", variant: "security" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import type { Types } from "@meshtastic/core";
|
import type { Types } from "@meshtastic/core";
|
||||||
|
|
||||||
// Config type discriminators
|
// Config type discriminators
|
||||||
export type ValidRadioConfigType = "lora" | "security";
|
export type ValidConfigType =
|
||||||
|
|
||||||
export type ValidDeviceConfigType =
|
|
||||||
| "device"
|
| "device"
|
||||||
| "position"
|
| "position"
|
||||||
| "power"
|
| "power"
|
||||||
| "network"
|
| "network"
|
||||||
| "display"
|
| "display"
|
||||||
| "bluetooth";
|
| "lora"
|
||||||
|
| "bluetooth"
|
||||||
export type ValidConfigType = ValidRadioConfigType | ValidDeviceConfigType;
|
| "security";
|
||||||
|
|
||||||
export type ValidModuleConfigType =
|
export type ValidModuleConfigType =
|
||||||
| "mqtt"
|
| "mqtt"
|
||||||
@@ -159,47 +157,6 @@ export function getConfigChangeCount(registry: ChangeRegistry): number {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get count of radio config changes
|
|
||||||
*/
|
|
||||||
export function getRadioConfigChangeCount(registry: ChangeRegistry): number {
|
|
||||||
let count = 0;
|
|
||||||
for (const keyStr of registry.changes.keys()) {
|
|
||||||
const key = deserializeKey(keyStr);
|
|
||||||
if (key.type === "config" && (key.variant === "lora" || key.variant === "security")) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Channel is displayed under Radio section in UI, so include channel changes in the count
|
|
||||||
count += getChannelChangeCount(registry);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get count of device config changes
|
|
||||||
*/
|
|
||||||
export function getDeviceConfigChangeCount(registry: ChangeRegistry): number {
|
|
||||||
let count = 0;
|
|
||||||
for (const keyStr of registry.changes.keys()) {
|
|
||||||
const key = deserializeKey(keyStr);
|
|
||||||
if (
|
|
||||||
key.type === "config" &&
|
|
||||||
(key.variant === "device" ||
|
|
||||||
key.variant === "position" ||
|
|
||||||
key.variant === "power" ||
|
|
||||||
key.variant === "network" ||
|
|
||||||
key.variant === "display" ||
|
|
||||||
key.variant === "bluetooth")
|
|
||||||
) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasUserChange(registry)) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get count of module config changes
|
* Get count of module config changes
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ export const mockDeviceStore: Device = {
|
|||||||
hasChannelChange: vi.fn().mockReturnValue(false),
|
hasChannelChange: vi.fn().mockReturnValue(false),
|
||||||
hasUserChange: vi.fn().mockReturnValue(false),
|
hasUserChange: vi.fn().mockReturnValue(false),
|
||||||
getConfigChangeCount: vi.fn().mockReturnValue(0),
|
getConfigChangeCount: vi.fn().mockReturnValue(0),
|
||||||
getRadioConfigChangeCount: vi.fn().mockReturnValue(0),
|
|
||||||
getDeviceConfigChangeCount: vi.fn().mockReturnValue(0),
|
|
||||||
getModuleConfigChangeCount: vi.fn().mockReturnValue(0),
|
getModuleConfigChangeCount: vi.fn().mockReturnValue(0),
|
||||||
getChannelChangeCount: vi.fn().mockReturnValue(0),
|
getChannelChangeCount: vi.fn().mockReturnValue(0),
|
||||||
getAllConfigChanges: vi.fn().mockReturnValue([]),
|
getAllConfigChanges: vi.fn().mockReturnValue([]),
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import {
|
|||||||
getAllModuleConfigChanges,
|
getAllModuleConfigChanges,
|
||||||
getChannelChangeCount,
|
getChannelChangeCount,
|
||||||
getConfigChangeCount,
|
getConfigChangeCount,
|
||||||
getRadioConfigChangeCount,
|
|
||||||
getDeviceConfigChangeCount,
|
|
||||||
getModuleConfigChangeCount,
|
getModuleConfigChangeCount,
|
||||||
hasChannelChange,
|
hasChannelChange,
|
||||||
hasConfigChange,
|
hasConfigChange,
|
||||||
@@ -121,8 +119,6 @@ export interface Device extends DeviceData {
|
|||||||
hasChannelChange: (index: Types.ChannelNumber) => boolean;
|
hasChannelChange: (index: Types.ChannelNumber) => boolean;
|
||||||
hasUserChange: () => boolean;
|
hasUserChange: () => boolean;
|
||||||
getConfigChangeCount: () => number;
|
getConfigChangeCount: () => number;
|
||||||
getRadioConfigChangeCount: () => number;
|
|
||||||
getDeviceConfigChangeCount: () => number;
|
|
||||||
getModuleConfigChangeCount: () => number;
|
getModuleConfigChangeCount: () => number;
|
||||||
getChannelChangeCount: () => number;
|
getChannelChangeCount: () => number;
|
||||||
getAllConfigChanges: () => Protobuf.Config.Config[];
|
getAllConfigChanges: () => Protobuf.Config.Config[];
|
||||||
@@ -821,24 +817,6 @@ function deviceFactory(
|
|||||||
return getConfigChangeCount(device.changeRegistry);
|
return getConfigChangeCount(device.changeRegistry);
|
||||||
},
|
},
|
||||||
|
|
||||||
getRadioConfigChangeCount: () => {
|
|
||||||
const device = get().devices.get(id);
|
|
||||||
if (!device) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getRadioConfigChangeCount(device.changeRegistry);
|
|
||||||
},
|
|
||||||
|
|
||||||
getDeviceConfigChangeCount: () => {
|
|
||||||
const device = get().devices.get(id);
|
|
||||||
if (!device) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getDeviceConfigChangeCount(device.changeRegistry);
|
|
||||||
},
|
|
||||||
|
|
||||||
getModuleConfigChangeCount: () => {
|
getModuleConfigChangeCount: () => {
|
||||||
const device = get().devices.get(id);
|
const device = get().devices.get(id);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
|
|||||||
@@ -6,13 +6,6 @@ function isUint8Array(v: unknown): v is Uint8Array {
|
|||||||
return v instanceof Uint8Array;
|
return v instanceof Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeBytes(value: unknown): unknown {
|
|
||||||
if (value instanceof Uint8Array && value.byteLength === 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
|
function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
|
||||||
if (a.byteLength !== b.byteLength) {
|
if (a.byteLength !== b.byteLength) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ const ConfigPage = () => {
|
|||||||
setModuleConfig,
|
setModuleConfig,
|
||||||
addChannel,
|
addChannel,
|
||||||
getConfigChangeCount,
|
getConfigChangeCount,
|
||||||
getRadioConfigChangeCount,
|
|
||||||
getDeviceConfigChangeCount,
|
|
||||||
getModuleConfigChangeCount,
|
getModuleConfigChangeCount,
|
||||||
getChannelChangeCount,
|
getChannelChangeCount,
|
||||||
getAdminMessageChangeCount,
|
getAdminMessageChangeCount,
|
||||||
@@ -52,9 +50,9 @@ const ConfigPage = () => {
|
|||||||
const routerState = useRouterState();
|
const routerState = useRouterState();
|
||||||
const { t } = useTranslation("config");
|
const { t } = useTranslation("config");
|
||||||
|
|
||||||
const radioConfigChangeCount = getRadioConfigChangeCount();
|
const configChangeCount = getConfigChangeCount();
|
||||||
const deviceConfigChangeCount = getDeviceConfigChangeCount();
|
|
||||||
const moduleConfigChangeCount = getModuleConfigChangeCount();
|
const moduleConfigChangeCount = getModuleConfigChangeCount();
|
||||||
|
const channelChangeCount = getChannelChangeCount();
|
||||||
const adminMessageChangeCount = getAdminMessageChangeCount();
|
const adminMessageChangeCount = getAdminMessageChangeCount();
|
||||||
|
|
||||||
const sections = useMemo(
|
const sections = useMemo(
|
||||||
@@ -64,7 +62,7 @@ const ConfigPage = () => {
|
|||||||
route: radioRoute,
|
route: radioRoute,
|
||||||
label: t("navigation.radioConfig"),
|
label: t("navigation.radioConfig"),
|
||||||
icon: RadioTowerIcon,
|
icon: RadioTowerIcon,
|
||||||
changeCount: radioConfigChangeCount,
|
changeCount: configChangeCount,
|
||||||
component: RadioConfig,
|
component: RadioConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -72,7 +70,7 @@ const ConfigPage = () => {
|
|||||||
route: deviceRoute,
|
route: deviceRoute,
|
||||||
label: t("navigation.deviceConfig"),
|
label: t("navigation.deviceConfig"),
|
||||||
icon: RouterIcon,
|
icon: RouterIcon,
|
||||||
changeCount: deviceConfigChangeCount,
|
changeCount: moduleConfigChangeCount,
|
||||||
component: DeviceConfig,
|
component: DeviceConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -80,11 +78,11 @@ const ConfigPage = () => {
|
|||||||
route: moduleRoute,
|
route: moduleRoute,
|
||||||
label: t("navigation.moduleConfig"),
|
label: t("navigation.moduleConfig"),
|
||||||
icon: LayersIcon,
|
icon: LayersIcon,
|
||||||
changeCount: moduleConfigChangeCount,
|
changeCount: channelChangeCount,
|
||||||
component: ModuleConfig,
|
component: ModuleConfig,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[t, radioConfigChangeCount, deviceConfigChangeCount, moduleConfigChangeCount],
|
[t, configChangeCount, moduleConfigChangeCount, channelChangeCount],
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeSection =
|
const activeSection =
|
||||||
@@ -265,7 +263,7 @@ const ConfigPage = () => {
|
|||||||
getModuleConfigChangeCount() > 0 ||
|
getModuleConfigChangeCount() > 0 ||
|
||||||
getChannelChangeCount() > 0 ||
|
getChannelChangeCount() > 0 ||
|
||||||
adminMessageChangeCount > 0;
|
adminMessageChangeCount > 0;
|
||||||
const hasPending = hasDrafts;
|
const hasPending = hasDrafts || rhfState.isDirty;
|
||||||
const buttonOpacity = hasPending ? "opacity-100" : "opacity-0";
|
const buttonOpacity = hasPending ? "opacity-100" : "opacity-0";
|
||||||
const saveDisabled = isSaving || !rhfState.isValid || !hasPending;
|
const saveDisabled = isSaving || !rhfState.isValid || !hasPending;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user