stream-chat 9.37.0 → 9.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,8 @@ export declare class NotificationManager {
15
15
  addWarning({ message, origin, options }: AddNotificationPayload): string;
16
16
  addInfo({ message, origin, options }: AddNotificationPayload): string;
17
17
  addSuccess({ message, origin, options }: AddNotificationPayload): string;
18
+ clearTimeout(id: string): void;
19
+ startTimeout(id: string, durationOverride?: number): void;
18
20
  remove(id: string): void;
19
21
  clear(): void;
20
22
  }
@@ -19,8 +19,6 @@ export type Notification = {
19
19
  id: string;
20
20
  /** The notification message text */
21
21
  message: string;
22
- /** The severity level of the notification */
23
- severity: NotificationSeverity;
24
22
  /** Timestamp when notification was created */
25
23
  createdAt: number;
26
24
  /**
@@ -30,6 +28,8 @@ export type Notification = {
30
28
  origin: NotificationOrigin;
31
29
  /** Array of action buttons for the notification */
32
30
  actions?: NotificationAction[];
31
+ /** The severity level of the notification. Defaults to undefined unless explicitly provided. */
32
+ severity?: NotificationSeverity;
33
33
  /**
34
34
  * Optional code that can be used to group the notifications of the same type, e.g. attachment-upload-blocked.
35
35
  * Format: domain:entity:operation:result
@@ -74,16 +74,21 @@ export type Notification = {
74
74
  * 'system:resource:unavailable'; // System resource unavailable
75
75
  */
76
76
  type?: string;
77
- /** Optional timestamp when notification should expire */
78
- expiresAt?: number;
77
+ /** Optional auto-dismiss duration in milliseconds. The timeout starts when NotificationManager.startTimeout() is called. */
78
+ duration?: number;
79
79
  /** Optional metadata to attach to the notification */
80
80
  metadata?: Record<string, unknown>;
81
+ /** Optional tags that can be used for routing or grouping notifications (e.g. `target:channel`). */
82
+ tags?: string[];
81
83
  /** In case of error notification the instance of the originally thrown error */
82
84
  originalError?: Error;
83
85
  };
84
86
  /** Configuration options when creating a notification */
85
- export type NotificationOptions = Partial<Pick<Notification, 'type' | 'severity' | 'actions' | 'metadata' | 'originalError'>> & {
86
- /** How long a notification should be displayed in milliseconds */
87
+ export type NotificationOptions = Partial<Pick<Notification, 'type' | 'severity' | 'actions' | 'metadata' | 'tags' | 'originalError'>> & {
88
+ /**
89
+ * How long a notification should be displayed in milliseconds.
90
+ * Use `0` for persistent (no auto-dismiss); call `client.notifications.remove(id)` to dismiss.
91
+ */
87
92
  duration?: number;
88
93
  };
89
94
  /**
@@ -96,8 +101,10 @@ export type NotificationState = {
96
101
  };
97
102
  /** State shape for the notification store */
98
103
  export type NotificationManagerState = NotificationState;
104
+ export type NotificationSortComparator = (a: Notification, b: Notification) => number;
99
105
  export type NotificationManagerConfig = {
100
- durations: Record<NotificationSeverity, number>;
106
+ durations: Partial<Record<NotificationSeverity, number>>;
107
+ sortComparator?: NotificationSortComparator;
101
108
  };
102
109
  export type AddNotificationPayload = Pick<Notification, 'message' | 'origin'> & {
103
110
  options?: NotificationOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stream-chat",
3
- "version": "9.37.0",
3
+ "version": "9.38.0",
4
4
  "description": "JS SDK for the Stream Chat API",
5
5
  "homepage": "https://getstream.io/chat/",
6
6
  "author": {
@@ -42,8 +42,9 @@ export class NotificationManager {
42
42
  add({ message, origin, options = {} }: AddNotificationPayload): string {
43
43
  const id = generateUUIDv4();
44
44
  const now = Date.now();
45
- const severity = options.severity || 'info';
46
- const duration = options.duration ?? this.config.durations[severity];
45
+ const severity = options.severity;
46
+ const duration =
47
+ options.duration ?? (severity ? this.config.durations[severity] : undefined);
47
48
 
48
49
  const notification: Notification = {
49
50
  id,
@@ -52,24 +53,21 @@ export class NotificationManager {
52
53
  type: options?.type,
53
54
  severity,
54
55
  createdAt: now,
55
- expiresAt: now + duration,
56
+ duration,
56
57
  actions: options.actions,
57
58
  metadata: options.metadata,
59
+ tags: options.tags,
58
60
  originalError: options.originalError,
59
61
  };
60
62
 
63
+ const notifications = [...this.store.getLatestValue().notifications, notification];
64
+
61
65
  this.store.partialNext({
62
- notifications: [...this.store.getLatestValue().notifications, notification],
66
+ notifications: this.config.sortComparator
67
+ ? [...notifications].sort(this.config.sortComparator)
68
+ : notifications,
63
69
  });
64
70
 
65
- if (notification.expiresAt) {
66
- const timeout = setTimeout(() => {
67
- this.remove(id);
68
- }, options.duration || this.config.durations[notification.severity]);
69
-
70
- this.timeouts.set(id, timeout);
71
- }
72
-
73
71
  return id;
74
72
  }
75
73
 
@@ -89,12 +87,34 @@ export class NotificationManager {
89
87
  return this.add({ message, origin, options: { ...options, severity: 'success' } });
90
88
  }
91
89
 
92
- remove(id: string): void {
90
+ clearTimeout(id: string): void {
93
91
  const timeout = this.timeouts.get(id);
94
- if (timeout) {
95
- clearTimeout(timeout);
96
- this.timeouts.delete(id);
97
- }
92
+
93
+ if (!timeout) return;
94
+
95
+ clearTimeout(timeout);
96
+ this.timeouts.delete(id);
97
+ }
98
+
99
+ startTimeout(id: string, durationOverride?: number): void {
100
+ const notification = this.store
101
+ .getLatestValue()
102
+ .notifications.find((n) => n.id === id);
103
+ const duration = durationOverride ?? notification?.duration;
104
+
105
+ if (!notification || !duration) return;
106
+
107
+ this.clearTimeout(id);
108
+
109
+ const timeout = setTimeout(() => {
110
+ this.remove(id);
111
+ }, duration);
112
+
113
+ this.timeouts.set(id, timeout);
114
+ }
115
+
116
+ remove(id: string): void {
117
+ this.clearTimeout(id);
98
118
 
99
119
  this.store.partialNext({
100
120
  notifications: this.store.getLatestValue().notifications.filter((n) => n.id !== id),
@@ -24,8 +24,6 @@ export type Notification = {
24
24
  id: string;
25
25
  /** The notification message text */
26
26
  message: string;
27
- /** The severity level of the notification */
28
- severity: NotificationSeverity;
29
27
  /** Timestamp when notification was created */
30
28
  createdAt: number;
31
29
  /**
@@ -35,6 +33,8 @@ export type Notification = {
35
33
  origin: NotificationOrigin;
36
34
  /** Array of action buttons for the notification */
37
35
  actions?: NotificationAction[];
36
+ /** The severity level of the notification. Defaults to undefined unless explicitly provided. */
37
+ severity?: NotificationSeverity;
38
38
  /**
39
39
  * Optional code that can be used to group the notifications of the same type, e.g. attachment-upload-blocked.
40
40
  * Format: domain:entity:operation:result
@@ -79,19 +79,27 @@ export type Notification = {
79
79
  * 'system:resource:unavailable'; // System resource unavailable
80
80
  */
81
81
  type?: string;
82
- /** Optional timestamp when notification should expire */
83
- expiresAt?: number;
82
+ /** Optional auto-dismiss duration in milliseconds. The timeout starts when NotificationManager.startTimeout() is called. */
83
+ duration?: number;
84
84
  /** Optional metadata to attach to the notification */
85
85
  metadata?: Record<string, unknown>;
86
+ /** Optional tags that can be used for routing or grouping notifications (e.g. `target:channel`). */
87
+ tags?: string[];
86
88
  /** In case of error notification the instance of the originally thrown error */
87
89
  originalError?: Error;
88
90
  };
89
91
 
90
92
  /** Configuration options when creating a notification */
91
93
  export type NotificationOptions = Partial<
92
- Pick<Notification, 'type' | 'severity' | 'actions' | 'metadata' | 'originalError'>
94
+ Pick<
95
+ Notification,
96
+ 'type' | 'severity' | 'actions' | 'metadata' | 'tags' | 'originalError'
97
+ >
93
98
  > & {
94
- /** How long a notification should be displayed in milliseconds */
99
+ /**
100
+ * How long a notification should be displayed in milliseconds.
101
+ * Use `0` for persistent (no auto-dismiss); call `client.notifications.remove(id)` to dismiss.
102
+ */
95
103
  duration?: number;
96
104
  };
97
105
 
@@ -107,8 +115,11 @@ export type NotificationState = {
107
115
  /** State shape for the notification store */
108
116
  export type NotificationManagerState = NotificationState;
109
117
 
118
+ export type NotificationSortComparator = (a: Notification, b: Notification) => number;
119
+
110
120
  export type NotificationManagerConfig = {
111
- durations: Record<NotificationSeverity, number>;
121
+ durations: Partial<Record<NotificationSeverity, number>>;
122
+ sortComparator?: NotificationSortComparator;
112
123
  };
113
124
 
114
125
  export type AddNotificationPayload = Pick<Notification, 'message' | 'origin'> & {