This commit is contained in:
Josh Hawkins 2026-03-11 11:35:12 -05:00
parent 98e9e79881
commit 18d413fbee
3 changed files with 69 additions and 16 deletions

View File

@ -1067,6 +1067,33 @@ export default function Settings() {
setNewProfiles((prev) => (prev.includes(name) ? prev : [...prev, name]));
}, []);
const handleRemoveNewProfile = useCallback((name: string) => {
setNewProfiles((prev) => prev.filter((p) => p !== name));
// Clear any editing state for this profile
setEditingProfile((prev) => {
const updated = { ...prev };
for (const key of Object.keys(updated)) {
if (updated[key] === name) {
delete updated[key];
}
}
return updated;
});
// Clear any pending data for this profile
setPendingDataBySection((prev) => {
const profileSegment = `profiles.${name}.`;
const updated = { ...prev };
let changed = false;
for (const key of Object.keys(updated)) {
if (key.includes(profileSegment)) {
delete updated[key];
changed = true;
}
}
return changed ? updated : prev;
});
}, []);
const handleDeleteProfileSection = useCallback(
async (camera: string, section: string, profile: string) => {
try {
@ -1105,6 +1132,7 @@ export default function Settings() {
allProfileNames,
onSelectProfile: handleSelectProfile,
onAddProfile: handleAddProfile,
onRemoveNewProfile: handleRemoveNewProfile,
onDeleteProfileSection: handleDeleteProfileSection,
}),
[
@ -1113,6 +1141,7 @@ export default function Settings() {
allProfileNames,
handleSelectProfile,
handleAddProfile,
handleRemoveNewProfile,
handleDeleteProfileSection,
],
);
@ -1780,6 +1809,8 @@ export default function Settings() {
pendingDataBySection={pendingDataBySection}
onPendingDataChange={handlePendingDataChange}
profileState={profileState}
profilesUIEnabled={profilesUIEnabled}
setProfilesUIEnabled={setProfilesUIEnabled}
/>
);
})()}

View File

@ -15,6 +15,7 @@ export type ProfileState = {
profile: string | null,
) => void;
onAddProfile: (name: string) => void;
onRemoveNewProfile: (name: string) => void;
onDeleteProfileSection: (
camera: string,
section: string,

View File

@ -142,6 +142,15 @@ export default function ProfilesView({
const handleDeleteProfile = useCallback(async () => {
if (!deleteProfile || !config) return;
// If this is an unsaved (new) profile, just remove it from local state
const isNewProfile = profileState?.newProfiles.includes(deleteProfile);
if (isNewProfile) {
profileState?.onRemoveNewProfile(deleteProfile);
setDeleteProfile(null);
return;
}
setDeleting(true);
try {
@ -184,7 +193,15 @@ export default function ProfilesView({
setDeleting(false);
setDeleteProfile(null);
}
}, [deleteProfile, activeProfile, config, updateConfig, updateProfiles, t]);
}, [
deleteProfile,
activeProfile,
config,
profileState,
updateConfig,
updateProfiles,
t,
]);
if (!config || !profilesData) {
return null;
@ -193,14 +210,15 @@ export default function ProfilesView({
const hasProfiles = allProfileNames.length > 0;
return (
<div className="flex size-full flex-col lg:pr-2">
<Heading as="h4" className="mb-5">
{t("profiles.title", { ns: "views/settings" })}
</Heading>
<div className="flex size-full max-w-5xl flex-col lg:pr-2">
<Heading as="h4">{t("profiles.title", { ns: "views/settings" })}</Heading>
<div className="my-1 text-sm text-muted-foreground">
{t("profiles.disabledDescription", { ns: "views/settings" })}
</div>
{/* Enable Profiles Toggle — shown only when no profiles exist */}
{!hasProfiles && setProfilesUIEnabled && (
<div className="mb-6 rounded-lg border border-border/70 bg-card/30 p-4">
<div className="my-6 max-w-xl rounded-lg border border-border/70 bg-card/30 p-4">
<div className="flex items-center justify-between">
<Label htmlFor="profiles-toggle" className="cursor-pointer">
{t("profiles.enableSwitch", { ns: "views/settings" })}
@ -211,14 +229,15 @@ export default function ProfilesView({
onCheckedChange={setProfilesUIEnabled}
/>
</div>
<p className="mt-3 text-sm text-muted-foreground">
{profilesUIEnabled
? t("profiles.enabledDescription", { ns: "views/settings" })
: t("profiles.disabledDescription", { ns: "views/settings" })}
</p>
</div>
)}
{profilesUIEnabled && (
<p className="mb-5 max-w-xl text-sm text-primary-variant">
{t("profiles.enabledDescription", { ns: "views/settings" })}
</p>
)}
{/* Active Profile Section — only when profiles exist */}
{hasProfiles && (
<div className="mb-6 rounded-lg border border-border/70 bg-card/30 p-4">
@ -275,11 +294,13 @@ export default function ProfilesView({
{/* Profile Cards */}
{!hasProfiles ? (
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
{!profilesUIEnabled && (
<p>{t("profiles.noProfiles", { ns: "views/settings" })}</p>
)}
</div>
profilesUIEnabled ? (
<p className="text-sm text-muted-foreground">
{t("profiles.noProfiles", { ns: "views/settings" })}
</p>
) : (
<div />
)
) : (
<div className="flex flex-col gap-3">
{allProfileNames.map((profile) => {