fix fast refresh

This commit is contained in:
Josh Hawkins 2026-02-01 12:44:54 -06:00
parent 3e708255a7
commit 718757fc60
4 changed files with 66 additions and 67 deletions

View File

@ -1,5 +1,5 @@
import { useMemo } from "react"; import { useMemo } from "react";
import { createConfigSection } from "./BaseSection"; import { ConfigSection } from "./BaseSection";
import type { BaseSectionProps, SectionConfig } from "./BaseSection"; import type { BaseSectionProps, SectionConfig } from "./BaseSection";
import { getSectionConfig } from "@/utils/sectionConfigsUtils"; import { getSectionConfig } from "@/utils/sectionConfigsUtils";
@ -19,17 +19,10 @@ export function ConfigSectionTemplate({
[sectionKey, level], [sectionKey, level],
); );
const SectionComponent = useMemo(
() =>
createConfigSection({
sectionPath: sectionKey,
defaultConfig,
}),
[sectionKey, defaultConfig],
);
return ( return (
<SectionComponent <ConfigSection
sectionPath={sectionKey}
defaultConfig={defaultConfig}
level={level} level={level}
sectionConfig={sectionConfig ?? defaultConfig} sectionConfig={sectionConfig ?? defaultConfig}
{...rest} {...rest}

View File

@ -2,10 +2,11 @@
// Reusable components for both global and camera-level settings // Reusable components for both global and camera-level settings
export { export {
createConfigSection, ConfigSection,
type BaseSectionProps, type BaseSectionProps,
type SectionConfig, type SectionConfig,
type CreateSectionOptions, type CreateSectionOptions,
type ConfigSectionProps,
} from "./BaseSection"; } from "./BaseSection";
export { export {
ConfigSectionTemplate, ConfigSectionTemplate,

View File

@ -39,7 +39,10 @@ import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView";
import MaintenanceSettingsView from "@/views/settings/MaintenanceSettingsView"; import MaintenanceSettingsView from "@/views/settings/MaintenanceSettingsView";
import GlobalConfigView from "@/views/settings/GlobalConfigView"; import GlobalConfigView from "@/views/settings/GlobalConfigView";
import CameraConfigView from "@/views/settings/CameraConfigView"; import CameraConfigView from "@/views/settings/CameraConfigView";
import { createSingleSectionPage } from "@/views/settings/SingleSectionPage"; import {
SingleSectionPage,
type SettingsPageProps,
} from "@/views/settings/SingleSectionPage";
import { useSearchEffect } from "@/hooks/use-overlay-state"; import { useSearchEffect } from "@/hooks/use-overlay-state";
import { useNavigate, useSearchParams } from "react-router-dom"; import { useNavigate, useSearchParams } from "react-router-dom";
import { useInitialCameraState } from "@/api/ws"; import { useInitialCameraState } from "@/api/ws";
@ -93,16 +96,18 @@ const allSettingsViews = [
] as const; ] as const;
type SettingsType = (typeof allSettingsViews)[number]; type SettingsType = (typeof allSettingsViews)[number];
const MqttSettingsPage = createSingleSectionPage({ const MqttSettingsPage = (props: SettingsPageProps) => (
sectionKey: "mqtt", <SingleSectionPage sectionKey="mqtt" level="global" {...props} />
level: "global", );
});
const CameraMqttSettingsPage = createSingleSectionPage({ const CameraMqttSettingsPage = (props: SettingsPageProps) => (
sectionKey: "mqtt", <SingleSectionPage
level: "camera", sectionKey="mqtt"
showOverrideIndicator: false, level="camera"
}); showOverrideIndicator={false}
{...props}
/>
);
const settingsGroups = [ const settingsGroups = [
{ {

View File

@ -18,58 +18,58 @@ export type SingleSectionPageOptions = {
showOverrideIndicator?: boolean; showOverrideIndicator?: boolean;
}; };
export function createSingleSectionPage({ export type SingleSectionPageProps = SettingsPageProps &
SingleSectionPageOptions;
export function SingleSectionPage({
sectionKey, sectionKey,
level, level,
sectionConfig, sectionConfig,
requiresRestart, requiresRestart,
showOverrideIndicator = true, showOverrideIndicator = true,
}: SingleSectionPageOptions) { selectedCamera,
return function SingleSectionPage({ setUnsavedChanges,
selectedCamera, }: SingleSectionPageProps) {
setUnsavedChanges, const sectionNamespace =
}: SettingsPageProps) { level === "camera" ? "config/cameras" : "config/global";
const sectionNamespace = const { t, i18n } = useTranslation([
level === "camera" ? "config/cameras" : "config/global"; sectionNamespace,
const { t, i18n } = useTranslation([ "views/settings",
sectionNamespace, "common",
"views/settings", ]);
"common",
]);
if (level === "camera" && !selectedCamera) {
return (
<div className="flex h-full items-center justify-center text-muted-foreground">
{t("configForm.camera.noCameras", { ns: "views/settings" })}
</div>
);
}
if (level === "camera" && !selectedCamera) {
return ( return (
<div className="flex size-full flex-col pr-2"> <div className="flex h-full items-center justify-center text-muted-foreground">
<div className="mb-4"> {t("configForm.camera.noCameras", { ns: "views/settings" })}
<Heading as="h3">
{t(`${sectionKey}.label`, { ns: sectionNamespace })}
</Heading>
{i18n.exists(`${sectionKey}.description`, {
ns: sectionNamespace,
}) && (
<p className="text-sm text-muted-foreground">
{t(`${sectionKey}.description`, { ns: sectionNamespace })}
</p>
)}
</div>
<ConfigSectionTemplate
sectionKey={sectionKey}
level={level}
cameraName={level === "camera" ? selectedCamera : undefined}
showOverrideIndicator={showOverrideIndicator}
onSave={() => setUnsavedChanges?.(false)}
showTitle={false}
sectionConfig={sectionConfig}
requiresRestart={requiresRestart}
/>
</div> </div>
); );
}; }
return (
<div className="flex size-full flex-col pr-2">
<div className="mb-4">
<Heading as="h3">
{t(`${sectionKey}.label`, { ns: sectionNamespace })}
</Heading>
{i18n.exists(`${sectionKey}.description`, {
ns: sectionNamespace,
}) && (
<p className="text-sm text-muted-foreground">
{t(`${sectionKey}.description`, { ns: sectionNamespace })}
</p>
)}
</div>
<ConfigSectionTemplate
sectionKey={sectionKey}
level={level}
cameraName={level === "camera" ? selectedCamera : undefined}
showOverrideIndicator={showOverrideIndicator}
onSave={() => setUnsavedChanges?.(false)}
showTitle={false}
sectionConfig={sectionConfig}
requiresRestart={requiresRestart}
/>
</div>
);
} }