Skip to content

Commit 5f1e989

Browse files
committed
refactor(platform): add service to manage notification and toast
1 parent 0c93171 commit 5f1e989

5 files changed

Lines changed: 173 additions & 51 deletions

File tree

packages/platform/src/app/core/http/useHttp.ts

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import { useEventCallback, useUnmount } from '@react-devui/hooks';
1313

1414
import { environment } from '../../../environments';
1515
import { LOGIN_PATH, PREV_ROUTE_KEY } from '../../config/other';
16-
import { getGlobalKey } from '../../utils/vars';
17-
import { useToasts } from '../state';
16+
import { ToastService } from '../../utils';
1817
import { TOKEN } from '../token';
1918
import './mock';
2019

@@ -71,29 +70,9 @@ export function useHttp() {
7170
if (error.response) {
7271
switch (error.response.status) {
7372
case 401:
74-
useToasts.setState((draft) => {
75-
const key = getGlobalKey();
76-
draft.push({
77-
key,
78-
children: t('User not authorized'),
79-
dVisible: true,
80-
dType: 'error',
81-
onClose: () => {
82-
useToasts.setState((draft) => {
83-
draft.find((n) => n.key === key)!.dVisible = false;
84-
});
85-
},
86-
afterVisibleChange: (visible) => {
87-
if (!visible) {
88-
useToasts.setState((draft) => {
89-
draft.splice(
90-
draft.findIndex((n) => n.key === key),
91-
1
92-
);
93-
});
94-
}
95-
},
96-
});
73+
ToastService.open({
74+
children: t('User not authorized'),
75+
dType: 'error',
9776
});
9877
navigate(LOGIN_PATH, { state: { [PREV_ROUTE_KEY]: location } });
9978
break;

packages/platform/src/app/routes/login/Login.tsx

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import { getClassName } from '@react-devui/utils';
1313
import { AppLanguage } from '../../components';
1414
import { APP_NAME } from '../../config/other';
1515
import { TOKEN, useHttp, useInit } from '../../core';
16-
import { useNotifications } from '../../core/state';
17-
import { getGlobalKey } from '../../utils/vars';
16+
import { NotificationService } from '../../utils';
1817
import styles from './Login.module.scss';
1918
import { BASE64_DATA } from './base64.out';
2019

@@ -74,30 +73,10 @@ export default function Login(): JSX.Element | null {
7473
},
7574
error: (error) => {
7675
setLoginLoading(false);
77-
useNotifications.setState((draft) => {
78-
const key = getGlobalKey();
79-
draft.push({
80-
key,
81-
dVisible: true,
82-
dTitle: error.response!.status,
83-
dDescription: error.response!.statusText,
84-
dType: 'error',
85-
onClose: () => {
86-
useNotifications.setState((draft) => {
87-
draft.find((n) => n.key === key)!.dVisible = false;
88-
});
89-
},
90-
afterVisibleChange: (visible) => {
91-
if (!visible) {
92-
useNotifications.setState((draft) => {
93-
draft.splice(
94-
draft.findIndex((n) => n.key === key),
95-
1
96-
);
97-
});
98-
}
99-
},
100-
});
76+
NotificationService.open({
77+
dTitle: error.response!.status,
78+
dDescription: error.response!.statusText,
79+
dType: 'error',
10180
});
10281
},
10382
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export { base64url } from './base64url';
2+
export { NotificationService } from './notification-service';
3+
export { ToastService } from './toast-service';
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import type { DNotificationProps } from '@react-devui/ui';
2+
3+
import { useNotifications } from '../core/state';
4+
import { getGlobalKey } from './vars';
5+
6+
interface NotificationInstance {
7+
key: string | number;
8+
close: () => void;
9+
rerender: (props: DNotificationProps) => void;
10+
}
11+
12+
export class NotificationService {
13+
static open(props: Omit<DNotificationProps, 'dVisible'>, _key?: string | number): NotificationInstance {
14+
const key = _key ?? getGlobalKey();
15+
16+
useNotifications.setState((draft) => {
17+
draft.push({
18+
...props,
19+
key,
20+
dVisible: true,
21+
onClose: () => {
22+
props.onClose?.();
23+
24+
NotificationService.close(key);
25+
},
26+
afterVisibleChange: (visible) => {
27+
props.afterVisibleChange?.(visible);
28+
29+
if (!visible) {
30+
const index = useNotifications.state.findIndex((n) => n.key === key);
31+
if (index !== -1) {
32+
useNotifications.setState((draft) => {
33+
draft.splice(index, 1);
34+
});
35+
}
36+
}
37+
},
38+
});
39+
});
40+
41+
return {
42+
key,
43+
close: () => {
44+
NotificationService.close(key);
45+
},
46+
rerender: (props) => {
47+
NotificationService.rerender(key, props);
48+
},
49+
};
50+
}
51+
52+
static close(key: string | number) {
53+
const index = useNotifications.state.findIndex((n) => n.key === key);
54+
if (index !== -1) {
55+
useNotifications.setState((draft) => {
56+
draft[index].dVisible = false;
57+
});
58+
}
59+
}
60+
61+
static rerender(key: string | number, props: DNotificationProps) {
62+
const index = useNotifications.state.findIndex((n) => n.key === key);
63+
if (index !== -1) {
64+
useNotifications.setState((draft) => {
65+
draft.splice(index, 1, { key, ...props });
66+
});
67+
}
68+
}
69+
70+
static closeAll(animation = true) {
71+
if (animation) {
72+
useNotifications.setState((draft) => {
73+
draft.forEach((notification) => {
74+
notification.dVisible = false;
75+
});
76+
});
77+
} else {
78+
useNotifications.setState([]);
79+
}
80+
}
81+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import type { DToastProps } from '@react-devui/ui';
2+
3+
import { useToasts } from '../core/state';
4+
import { getGlobalKey } from './vars';
5+
6+
interface ToastInstance {
7+
key: string | number;
8+
close: () => void;
9+
rerender: (props: DToastProps) => void;
10+
}
11+
12+
export class ToastService {
13+
static open(props: Omit<DToastProps, 'dVisible'>, _key?: string | number): ToastInstance {
14+
const key = _key ?? getGlobalKey();
15+
16+
useToasts.setState((draft) => {
17+
draft.push({
18+
...props,
19+
key,
20+
dVisible: true,
21+
onClose: () => {
22+
props.onClose?.();
23+
24+
ToastService.close(key);
25+
},
26+
afterVisibleChange: (visible) => {
27+
props.afterVisibleChange?.(visible);
28+
29+
if (!visible) {
30+
const index = useToasts.state.findIndex((n) => n.key === key);
31+
if (index !== -1) {
32+
useToasts.setState((draft) => {
33+
draft.splice(index, 1);
34+
});
35+
}
36+
}
37+
},
38+
});
39+
});
40+
41+
return {
42+
key,
43+
close: () => {
44+
ToastService.close(key);
45+
},
46+
rerender: (props) => {
47+
ToastService.rerender(key, props);
48+
},
49+
};
50+
}
51+
52+
static close(key: string | number) {
53+
const index = useToasts.state.findIndex((n) => n.key === key);
54+
if (index !== -1) {
55+
useToasts.setState((draft) => {
56+
draft[index].dVisible = false;
57+
});
58+
}
59+
}
60+
61+
static rerender(key: string | number, props: DToastProps) {
62+
const index = useToasts.state.findIndex((n) => n.key === key);
63+
if (index !== -1) {
64+
useToasts.setState((draft) => {
65+
draft.splice(index, 1, { key, ...props });
66+
});
67+
}
68+
}
69+
70+
static closeAll(animation = true) {
71+
if (animation) {
72+
useToasts.setState((draft) => {
73+
draft.forEach((toast) => {
74+
toast.dVisible = false;
75+
});
76+
});
77+
} else {
78+
useToasts.setState([]);
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)