Files
AFFiNE-Mirror/packages/frontend/component/src/components/notification-center/index.jotai.ts
T
devin-ai-integration e100d252b2 fix(core): add null checks for timeout refs and event listeners for React 19 compatibility (#9116)
## Description
- Add null checks before clearTimeout calls in colorful-fallback.tsx, edgeless.dialog.tsx, and local.dialog.tsx
- Fix event listener cleanup in unfolding.tsx
- Update tsconfig.jsx to use react-jsx transform

## Testing
- [x] Verified type safety improvements for React 19 compatibility
- [x] Ensured proper cleanup of event listeners and timeouts
- [x] Confirmed no unintended side effects from the changes

Link to Devin run: https://app.devin.ai/sessions/2e790f3ea0d84402837ec6c3c6f83e4c
2024-12-12 09:43:42 +00:00

83 lines
2.4 KiB
TypeScript

import { atom } from 'jotai';
import { nanoid } from 'nanoid';
import type { JSX, ReactNode } from 'react';
/**
* @deprecated use `import type { Notification } from '@affine/component'` instead
*/
export type Notification = {
key?: string;
title: string;
message?: string;
type: 'success' | 'error' | 'warning' | 'info';
theme?: 'light' | 'dark' | 'default';
timeout?: number;
progressingBar?: boolean;
multimedia?: ReactNode | JSX.Element;
// actions
action?: () => Promise<void>;
actionLabel?: string;
};
const notificationsBaseAtom = atom<Notification[]>([]);
const expandNotificationCenterBaseAtom = atom(false);
const cleanupQueueAtom = atom<(() => unknown)[]>([]);
/**
* @deprecated use `import { notify } from '@affine/component'` instead
*/
export const expandNotificationCenterAtom = atom<boolean, [boolean], void>(
get => get(expandNotificationCenterBaseAtom),
(get, set, value) => {
if (value === false) {
get(cleanupQueueAtom).forEach(cleanup => cleanup());
set(cleanupQueueAtom, []);
}
set(expandNotificationCenterBaseAtom, value);
}
);
/**
* @deprecated use `import { notify } from '@affine/component'` instead
*/
export const notificationsAtom = atom<Notification[]>(get =>
get(notificationsBaseAtom)
);
/**
* @deprecated use `import { notify } from '@affine/component'` instead
*/
export const removeNotificationAtom = atom(null, (_, set, key: string) => {
set(notificationsBaseAtom, notifications =>
notifications.filter(notification => notification.key !== key)
);
});
/**
* @deprecated use `import { notify } from '@affine/component'` instead
*/
export const pushNotificationAtom = atom<null, [Notification], void>(
null,
(_, set, newNotification) => {
newNotification.key = newNotification.key || nanoid();
const key = newNotification.key;
const removeNotification = () =>
set(notificationsBaseAtom, notifications =>
notifications.filter(notification => notification.key !== key)
);
const action: (() => Promise<void>) | undefined = newNotification.action
? (() => {
const action: () => Promise<void> = newNotification.action;
return async function actionNotificationWrapper() {
removeNotification();
return action();
};
})()
: undefined;
set(notificationsBaseAtom, notifications => [
// push to the top
{ ...newNotification, action },
...notifications,
]);
}
);