Files
openmaic/OpenMAIC/components/storage-health-notice.tsx
T

53 lines
2.0 KiB
TypeScript

'use client';
import { useEffect } from 'react';
import { toast } from 'sonner';
import { useI18n } from '@/lib/hooks/use-i18n';
import { acknowledgePersistLoss, subscribeToPersistHealth } from '@/lib/store/persist-health';
/**
* Surfaces the persistence failures the user cannot otherwise notice.
*
* When the storage seam refuses to write — its key never hydrated, so writing
* would replace stored data with defaults — the app keeps working, the store
* keeps updating in memory, and every change is lost on reload. Renders nothing
* until that happens.
*/
export function StorageHealthNotice() {
const { t } = useI18n();
useEffect(
() =>
subscribeToPersistHealth(({ name, status }) => {
// Two toasts per key, deliberately not one. "Storage is down" is a
// condition that recovery retracts; "your edits were lost" is a fact
// that recovery does not undo, so they cannot share an id — dismissing
// the first would take the second with it. Both are sticky and
// de-duplicated: neither resolves on its own, and repeating them per
// refused write would bury the app.
if (status === 'changes-lost') {
toast.error(t('settings.persistChangesLost'), {
id: `persist-changes-lost:${name}`,
duration: Infinity,
// The only way out is the user acknowledging it — and the
// acknowledgement has to reach the channel, or the same store
// losing changes again is swallowed as a duplicate and a later
// subscriber resurrects a toast that was already dealt with.
closeButton: true,
onDismiss: () => acknowledgePersistLoss(name),
});
return;
}
const id = `persist-unavailable:${name}`;
if (status === 'recovered') {
toast.dismiss(id);
return;
}
toast.error(t('settings.persistUnavailable'), { id, duration: Infinity });
}),
[t],
);
return null;
}