ajaxter-chat 3.0.15 → 3.0.17

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.
@@ -59,6 +59,16 @@ export interface WidgetConfig {
59
59
  * @example https://api.example.com/widgets/reenable-request
60
60
  */
61
61
  reenableRequestUrl?: string;
62
+ /**
63
+ * Current presence from your API/DB (include in chatData or a session payload).
64
+ * When set, it initializes the status control and overrides session-only cache.
65
+ */
66
+ presenceStatus?: PresenceStatus;
67
+ /**
68
+ * Production: `POST` JSON `{ widgetId, apiKey, viewerUid?, status }` to save presence in your database.
69
+ * The client still mirrors to sessionStorage as a local fallback.
70
+ */
71
+ presenceUpdateUrl?: string;
62
72
  }
63
73
 
64
74
  export interface RemoteChatData {
@@ -89,6 +99,9 @@ export type Screen =
89
99
  export type UserListContext = 'support' | 'conversation';
90
100
  export type MessageType = 'text' | 'voice' | 'attachment' | 'emoji';
91
101
 
102
+ /** Home status selector; persist via `presenceUpdateUrl` in production */
103
+ export type PresenceStatus = 'ACTIVE' | 'AWAY' | 'DND';
104
+
92
105
  // ─── User ───────────────────────────────────────────────────────────────────
93
106
  export interface ChatUser {
94
107
  uid: string;
@@ -0,0 +1,56 @@
1
+ import type { PresenceStatus } from '../types';
2
+
3
+ const key = (widgetId: string) => `ajaxter_presence_${widgetId}`;
4
+
5
+ export function loadPresenceStatus(widgetId: string): PresenceStatus {
6
+ if (typeof sessionStorage === 'undefined') return 'ACTIVE';
7
+ try {
8
+ const v = sessionStorage.getItem(key(widgetId));
9
+ if (v === 'ACTIVE' || v === 'AWAY' || v === 'DND') return v;
10
+ } catch {
11
+ /* */
12
+ }
13
+ return 'ACTIVE';
14
+ }
15
+
16
+ export function savePresenceStatus(widgetId: string, status: PresenceStatus): void {
17
+ try {
18
+ sessionStorage.setItem(key(widgetId), status);
19
+ } catch {
20
+ /* quota */
21
+ }
22
+ }
23
+
24
+ /** Prefer server value from DB when the host includes it in config */
25
+ export function resolveInitialPresence(
26
+ widgetId: string,
27
+ serverStatus: PresenceStatus | undefined,
28
+ ): PresenceStatus {
29
+ if (serverStatus === 'ACTIVE' || serverStatus === 'AWAY' || serverStatus === 'DND') return serverStatus;
30
+ return loadPresenceStatus(widgetId);
31
+ }
32
+
33
+ export interface PresenceSyncPayload {
34
+ widgetId: string;
35
+ apiKey: string;
36
+ viewerUid?: string;
37
+ status: PresenceStatus;
38
+ }
39
+
40
+ /** Call your backend to persist presence (production DB). */
41
+ export async function syncPresenceToServer(url: string, payload: PresenceSyncPayload): Promise<void> {
42
+ const res = await fetch(url, {
43
+ method: 'POST',
44
+ headers: {
45
+ Accept: 'application/json',
46
+ 'Content-Type': 'application/json',
47
+ },
48
+ body: JSON.stringify(payload),
49
+ mode: 'cors',
50
+ credentials: 'omit',
51
+ });
52
+ if (!res.ok) {
53
+ const t = await res.text().catch(() => '');
54
+ throw new Error(t || `Presence sync failed (${res.status})`);
55
+ }
56
+ }