@messenger-box/platform-client 10.0.3-alpha.196 → 10.0.3-alpha.201
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.
- package/lib/context/ChatSettingsContext.d.ts +22 -0
- package/lib/context/ChatSettingsContext.d.ts.map +1 -0
- package/lib/context/ChatSettingsContext.js +35 -0
- package/lib/context/ChatSettingsContext.js.map +1 -0
- package/lib/graphql/mutations/channel-mutation.gql +4 -2
- package/lib/graphql/policies/messages-policies.d.ts.map +1 -1
- package/lib/graphql/policies/messages-policies.js +32 -49
- package/lib/graphql/policies/messages-policies.js.map +1 -1
- package/lib/hooks/index.d.ts +6 -0
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/use-chat-configuration.hook.d.ts +38 -0
- package/lib/hooks/use-chat-configuration.hook.d.ts.map +1 -0
- package/lib/hooks/use-chat-configuration.hook.js +127 -0
- package/lib/hooks/use-chat-configuration.hook.js.map +1 -0
- package/lib/hooks/use-send-message.hook.d.ts +106 -0
- package/lib/hooks/use-send-message.hook.d.ts.map +1 -0
- package/lib/hooks/use-send-message.hook.js +197 -0
- package/lib/hooks/use-send-message.hook.js.map +1 -0
- package/lib/hooks/use-stream-assembler.hook.d.ts +68 -0
- package/lib/hooks/use-stream-assembler.hook.d.ts.map +1 -0
- package/lib/hooks/use-stream-assembler.hook.js +147 -0
- package/lib/hooks/use-stream-assembler.hook.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatSettingsContext — React Context that makes chat configuration
|
|
3
|
+
* available throughout the component tree without prop-drilling.
|
|
4
|
+
*
|
|
5
|
+
* Wrap your root inbox component with <ChatSettingsProvider> and any
|
|
6
|
+
* descendant can call useChatSettings() to read/write config:
|
|
7
|
+
*
|
|
8
|
+
* const { get, set, loading } = useChatSettings();
|
|
9
|
+
* const agentEnabled = get('chat.agent.enabled') as boolean;
|
|
10
|
+
*/
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import { type UseChatConfigurationResult, type UseChatConfigurationOptions } from '../hooks/use-chat-configuration.hook';
|
|
13
|
+
export interface ChatSettingsProviderProps extends UseChatConfigurationOptions {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export declare function ChatSettingsProvider({ children, ...options }: ChatSettingsProviderProps): React.JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Read/write chat configuration from any descendant of ChatSettingsProvider.
|
|
19
|
+
* Throws if used outside the provider.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useChatSettings(): UseChatConfigurationResult;
|
|
22
|
+
//# sourceMappingURL=ChatSettingsContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatSettingsContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatSettingsContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,EAEH,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EACnC,MAAM,sCAAsC,CAAC;AAQ9C,MAAM,WAAW,yBAA0B,SAAQ,2BAA2B;IAC1E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,yBAAyB,qBAOvF;AAID;;;GAGG;AACH,wBAAgB,eAAe,IAAI,0BAA0B,CAM5D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React,{createContext,useMemo,useContext}from'react';import {useChatConfiguration}from'../hooks/use-chat-configuration.hook.js';/**
|
|
2
|
+
* ChatSettingsContext — React Context that makes chat configuration
|
|
3
|
+
* available throughout the component tree without prop-drilling.
|
|
4
|
+
*
|
|
5
|
+
* Wrap your root inbox component with <ChatSettingsProvider> and any
|
|
6
|
+
* descendant can call useChatSettings() to read/write config:
|
|
7
|
+
*
|
|
8
|
+
* const { get, set, loading } = useChatSettings();
|
|
9
|
+
* const agentEnabled = get('chat.agent.enabled') as boolean;
|
|
10
|
+
*/
|
|
11
|
+
// ─── Context ────────────────────────────────────────────────────────────────
|
|
12
|
+
const ChatSettingsContext = createContext(null);
|
|
13
|
+
function ChatSettingsProvider({
|
|
14
|
+
children,
|
|
15
|
+
...options
|
|
16
|
+
}) {
|
|
17
|
+
const cfg = useChatConfiguration(options);
|
|
18
|
+
// Stable reference so consumers don't re-render unless entries change
|
|
19
|
+
const value = useMemo(() => cfg, [cfg.entries, cfg.loading, cfg.error]);
|
|
20
|
+
return React.createElement(ChatSettingsContext.Provider, {
|
|
21
|
+
value: value
|
|
22
|
+
}, children);
|
|
23
|
+
}
|
|
24
|
+
// ─── Consumer hook ──────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Read/write chat configuration from any descendant of ChatSettingsProvider.
|
|
27
|
+
* Throws if used outside the provider.
|
|
28
|
+
*/
|
|
29
|
+
function useChatSettings() {
|
|
30
|
+
const ctx = useContext(ChatSettingsContext);
|
|
31
|
+
if (!ctx) {
|
|
32
|
+
throw new Error('useChatSettings() must be used inside <ChatSettingsProvider>');
|
|
33
|
+
}
|
|
34
|
+
return ctx;
|
|
35
|
+
}export{ChatSettingsProvider,useChatSettings};//# sourceMappingURL=ChatSettingsContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatSettingsContext.js","sources":["../../src/context/ChatSettingsContext.tsx"],"sourcesContent":[null],"names":[],"mappings":"sIAAA;;;;;;;;;AASG;AAQH;AAEA,MAAM,mBAAmB,GAAG,aAAa,CAAoC,IAAI,CAAC;AAQ5E,SAAU,oBAAoB,CAAC;AACjC,EAAA,QAAM;KAEN;;QAGA,GAAO,GAAA,oBAAC,CAAA,OAAA,CAAA;AACZ;AAEA,EAAA,MAAA,KAAA,GAAA,OAAA,CAAA,MAAA,GAAA,EAAA,CAAA,GAAA,CAAA,OAAA,EAAA,GAAA,CAAA,OAAA,EAAA,GAAA,CAAA,KAAA,CAAA,CAAA;AAEA,EAAA,OAAA,KAAA,CAAA,aAAA,CAAA,mBAAA,CAAA,QAAA,EAAA;;;AAGG;AACH;AACI;;AAEI;;AAEJ,SAAW,eAAA,GAAA;AACf,EAAC,MAAA,GAAA,GAAA,UAAA,CAAA,mBAAA,CAAA;;;;;"}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
mutation AddChannel($name:String!, $description:String
|
|
1
|
+
mutation AddChannel($name:String!, $description:String, $type: RoomType, $team: String, $settings: AnyObject){
|
|
2
2
|
createChannel(
|
|
3
3
|
name:$name,
|
|
4
4
|
description:$description,
|
|
5
5
|
type: $type,
|
|
6
|
-
team: $team
|
|
6
|
+
team: $team,
|
|
7
|
+
settings: $settings
|
|
7
8
|
){
|
|
8
9
|
id
|
|
9
10
|
title
|
|
10
11
|
type
|
|
12
|
+
settings
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-policies.d.ts","sourceRoot":"","sources":["../../../src/graphql/policies/messages-policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"messages-policies.d.ts","sourceRoot":"","sources":["../../../src/graphql/policies/messages-policies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,eAAO,MAAM,gBAAgB,EAAE,YA2S9B,CAAC"}
|
|
@@ -31,39 +31,35 @@ const messagesPolicies = {
|
|
|
31
31
|
merge: (existing = [], incoming = [], {
|
|
32
32
|
readField
|
|
33
33
|
}) => {
|
|
34
|
-
// Use a Map for O(1) lookups
|
|
35
|
-
const
|
|
36
|
-
//
|
|
34
|
+
// Use a Map for O(1) lookups to deduplicate by ID
|
|
35
|
+
const mergedMap = new Map();
|
|
36
|
+
// First add all existing messages to the map
|
|
37
37
|
if (existing && existing.length > 0) {
|
|
38
38
|
for (let i = 0; i < existing.length; i++) {
|
|
39
39
|
const id = readField('id', existing[i]);
|
|
40
40
|
if (id) {
|
|
41
|
-
|
|
41
|
+
mergedMap.set(id, existing[i]);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
// Add incoming items, overwriting existing ones
|
|
45
|
+
// Then add/overwrite with incoming messages
|
|
46
|
+
// This handles both optimistic updates and real responses
|
|
48
47
|
if (incoming && incoming.length > 0) {
|
|
49
48
|
for (let i = 0; i < incoming.length; i++) {
|
|
50
49
|
const item = incoming[i];
|
|
51
50
|
const id = readField('id', item);
|
|
52
51
|
if (id) {
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
result.push(item);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// Add remaining existing items not in incoming
|
|
59
|
-
if (existing && existing.length > 0) {
|
|
60
|
-
for (let i = 0; i < existing.length; i++) {
|
|
61
|
-
const id = readField('id', existing[i]);
|
|
62
|
-
if (id && !result.some(item => readField('id', item) === id)) {
|
|
63
|
-
result.push(existing[i]);
|
|
52
|
+
mergedMap.set(id, item);
|
|
64
53
|
}
|
|
65
54
|
}
|
|
66
55
|
}
|
|
56
|
+
// Convert back to array and sort by createdAt (oldest first, newest at bottom)
|
|
57
|
+
const result = Array.from(mergedMap.values());
|
|
58
|
+
result.sort((a, b) => {
|
|
59
|
+
const timeA = new Date(readField('createdAt', a) || 0).getTime();
|
|
60
|
+
const timeB = new Date(readField('createdAt', b) || 0).getTime();
|
|
61
|
+
return timeA - timeB;
|
|
62
|
+
});
|
|
67
63
|
return result;
|
|
68
64
|
}
|
|
69
65
|
},
|
|
@@ -119,7 +115,6 @@ const messagesPolicies = {
|
|
|
119
115
|
messages: {
|
|
120
116
|
keyArgs: ['channelId', 'parentId'],
|
|
121
117
|
merge(existing, incoming, {
|
|
122
|
-
args,
|
|
123
118
|
readField
|
|
124
119
|
}) {
|
|
125
120
|
if (!incoming) return existing;
|
|
@@ -135,39 +130,27 @@ const messagesPolicies = {
|
|
|
135
130
|
if (!existing.data || existing.data.length === 0) {
|
|
136
131
|
return incoming;
|
|
137
132
|
}
|
|
138
|
-
//
|
|
139
|
-
const
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const id = readField('id', mergedData[i]);
|
|
146
|
-
if (id) idSet.add(id);
|
|
133
|
+
// Merge by deduplicating on ID, then sort by createdAt
|
|
134
|
+
const mergedMap = new Map();
|
|
135
|
+
// Add existing messages
|
|
136
|
+
for (let i = 0; i < existing.data.length; i++) {
|
|
137
|
+
const msg = existing.data[i];
|
|
138
|
+
const id = readField('id', msg);
|
|
139
|
+
if (id) mergedMap.set(id, msg);
|
|
147
140
|
}
|
|
148
|
-
//
|
|
141
|
+
// Add/overwrite with incoming messages
|
|
149
142
|
for (let i = 0; i < incoming.data.length; i++) {
|
|
150
|
-
const
|
|
151
|
-
const id = readField('id',
|
|
152
|
-
if (
|
|
153
|
-
if (idSet.has(id)) {
|
|
154
|
-
// Replace existing message with same ID
|
|
155
|
-
const existingIndex = mergedData.findIndex(msg => readField('id', msg) === id);
|
|
156
|
-
if (existingIndex >= 0) {
|
|
157
|
-
mergedData[existingIndex] = incomingMsg;
|
|
158
|
-
}
|
|
159
|
-
} else {
|
|
160
|
-
// Add new message
|
|
161
|
-
if (isNewMessage) {
|
|
162
|
-
// Add to beginning for new messages
|
|
163
|
-
mergedData.unshift(incomingMsg);
|
|
164
|
-
} else {
|
|
165
|
-
// Add to end for pagination
|
|
166
|
-
mergedData.push(incomingMsg);
|
|
167
|
-
}
|
|
168
|
-
idSet.add(id);
|
|
169
|
-
}
|
|
143
|
+
const msg = incoming.data[i];
|
|
144
|
+
const id = readField('id', msg);
|
|
145
|
+
if (id) mergedMap.set(id, msg);
|
|
170
146
|
}
|
|
147
|
+
// Convert to array and sort oldest first (newest at bottom like Slack)
|
|
148
|
+
const mergedData = Array.from(mergedMap.values());
|
|
149
|
+
mergedData.sort((a, b) => {
|
|
150
|
+
const timeA = new Date(readField('createdAt', a) || 0).getTime();
|
|
151
|
+
const timeB = new Date(readField('createdAt', b) || 0).getTime();
|
|
152
|
+
return timeA - timeB;
|
|
153
|
+
});
|
|
171
154
|
return {
|
|
172
155
|
...existing,
|
|
173
156
|
totalCount: incoming.totalCount ?? existing.totalCount,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-policies.js","sources":["../../../src/graphql/policies/messages-policies.ts"],"sourcesContent":[null],"names":[],"mappings":"AAEO,MAAM,gBAAgB,GAAiB;AAC1C,EAAA,QAAA,EAAQ;;;;AAIJ,IAAA,MAAA,EAAA;AACI,MAAA,EAAA,EAAA;AACI,QAAA,IAAA,CAAA,QAAK,EAAA;AACD,UAAA;AACA,SAAA,EAAA;gBACJ;AACH,YAAA,SAAA;AACD,YAAA;AACI,WAAA,GAAA,SAAK;AACD,UAAA,OAAA,QAAA,GAAQ,CAAA,EAAA,qBAA6B,iBAAU,CAAA,CAAA;AAC/C,QAAA;;AAEP,MAAA,aAAA,EAAA;AACD,QAAA,IAAA,CAAA,QAAM,EAAA;AACF,UAAA;AACA,SAAA,EAAA;;AAEI,YAAA,SAAA;;uBAGA;AACI,UAAA,OAAA,QAAA,GAAA,CAAK,EAAA,SAAW,CAAC,CAAA,EAAG,QAAQ,CAAC,CAAA,GAAA,CAAA,EAAM,SAAQ,CAAA,CAAA;;;;6BAItC,EAAA,UAAA,CAAA;wBACL,GAAC,EAAA,EAAA,QAAA,GAAA,EAAA,EAAA;;;;
|
|
1
|
+
{"version":3,"file":"messages-policies.js","sources":["../../../src/graphql/policies/messages-policies.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -2,4 +2,10 @@ export { useUploadFile } from './use-upload-file.hook';
|
|
|
2
2
|
export { useUploadFiles } from './use-upload-files.hook';
|
|
3
3
|
export { useUploadFile as useUploadFileNative } from './use-upload-file.hook.native';
|
|
4
4
|
export { useUploadFiles as useUploadFilesNative } from './use-upload-files.hook.native';
|
|
5
|
+
export { useSendMessage } from './use-send-message.hook';
|
|
6
|
+
export type { SendMessageUser, FailedMessage, UseSendMessageOptions } from './use-send-message.hook';
|
|
7
|
+
export { useStreamAssembler, parseStreamMessage } from './use-stream-assembler.hook';
|
|
8
|
+
export type { ActiveStream, CompletedStream } from './use-stream-assembler.hook';
|
|
9
|
+
export { useChatConfiguration } from './use-chat-configuration.hook';
|
|
10
|
+
export type { ChatConfigurationEntry, UseChatConfigurationOptions, UseChatConfigurationResult, } from './use-chat-configuration.hook';
|
|
5
11
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/hooks/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,aAAa,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,cAAc,IAAI,oBAAoB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,aAAa,IAAI,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,cAAc,IAAI,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrG,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACrF,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,YAAY,EACR,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,GAC7B,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface ChatConfigurationEntry {
|
|
2
|
+
key: string;
|
|
3
|
+
value: unknown;
|
|
4
|
+
defaultValue: unknown;
|
|
5
|
+
valueType: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}
|
|
8
|
+
export interface UseChatConfigurationOptions {
|
|
9
|
+
/** Optional channelId for channel-scoped overrides */
|
|
10
|
+
channelId?: string;
|
|
11
|
+
/** Polling interval in ms (0 = disabled, default 0) */
|
|
12
|
+
pollInterval?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface UseChatConfigurationResult {
|
|
15
|
+
/** All configuration entries */
|
|
16
|
+
entries: ChatConfigurationEntry[];
|
|
17
|
+
/** Whether the initial query is loading */
|
|
18
|
+
loading: boolean;
|
|
19
|
+
/** Apollo error, if any */
|
|
20
|
+
error: any;
|
|
21
|
+
/** Get a single configuration value by key */
|
|
22
|
+
get: (key: string) => unknown;
|
|
23
|
+
/** Get a single entry by key (includes metadata) */
|
|
24
|
+
getEntry: (key: string) => ChatConfigurationEntry | undefined;
|
|
25
|
+
/** Update one or more configuration values */
|
|
26
|
+
set: (key: string, value: unknown) => Promise<void>;
|
|
27
|
+
/** Batch-update multiple keys at once */
|
|
28
|
+
setMany: (updates: Array<{
|
|
29
|
+
key: string;
|
|
30
|
+
value: unknown;
|
|
31
|
+
}>) => Promise<void>;
|
|
32
|
+
/** Reset a key to its schema default */
|
|
33
|
+
reset: (key: string) => Promise<void>;
|
|
34
|
+
/** Force refetch from server */
|
|
35
|
+
refetch: () => Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function useChatConfiguration(options?: UseChatConfigurationOptions): UseChatConfigurationResult;
|
|
38
|
+
//# sourceMappingURL=use-chat-configuration.hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-configuration.hook.d.ts","sourceRoot":"","sources":["../../src/hooks/use-chat-configuration.hook.ts"],"names":[],"mappings":"AA4DA,MAAM,WAAW,sBAAsB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IACxC,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACvC,gCAAgC;IAChC,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,KAAK,EAAE,GAAG,CAAC;IACX,8CAA8C;IAC9C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9B,oDAAoD;IACpD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,GAAG,SAAS,CAAC;IAC9D,8CAA8C;IAC9C,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,yCAAyC;IACzC,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,wCAAwC;IACxC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAID,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,2BAAgC,GAAG,0BAA0B,CAgF1G"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {useMemo,useCallback}from'react';import {gql,useQuery,useMutation}from'@apollo/client/index.js';/**
|
|
2
|
+
* useChatConfiguration — React hook for reading and updating chat settings.
|
|
3
|
+
*
|
|
4
|
+
* Provides a strongly-typed interface over the `chatConfiguration` GraphQL
|
|
5
|
+
* query/mutation pair. Values are cached in Apollo and kept fresh via
|
|
6
|
+
* polling or direct refetch after mutation.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const { get, set, reset, loading, entries } = useChatConfiguration();
|
|
10
|
+
* const agentEnabled = get('chat.agent.enabled'); // boolean | undefined
|
|
11
|
+
* await set('chat.agent.enabled', false); // update + refetch
|
|
12
|
+
* await reset('chat.agent.enabled'); // reset to default
|
|
13
|
+
*/
|
|
14
|
+
// ─── GraphQL documents ──────────────────────────────────────────────────────
|
|
15
|
+
const CHAT_CONFIGURATION_QUERY = gql`
|
|
16
|
+
query ChatConfiguration($channelId: String) {
|
|
17
|
+
chatConfiguration(channelId: $channelId) {
|
|
18
|
+
entries {
|
|
19
|
+
key
|
|
20
|
+
value
|
|
21
|
+
defaultValue
|
|
22
|
+
valueType
|
|
23
|
+
description
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
const UPDATE_CHAT_CONFIGURATION = gql`
|
|
29
|
+
mutation UpdateChatConfiguration($updates: [ChatConfigurationUpdateInput!]!, $channelId: String) {
|
|
30
|
+
updateChatConfiguration(updates: $updates, channelId: $channelId) {
|
|
31
|
+
entries {
|
|
32
|
+
key
|
|
33
|
+
value
|
|
34
|
+
defaultValue
|
|
35
|
+
valueType
|
|
36
|
+
description
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
const RESET_CHAT_CONFIGURATION = gql`
|
|
42
|
+
mutation ResetChatConfiguration($key: String!, $channelId: String) {
|
|
43
|
+
resetChatConfiguration(key: $key, channelId: $channelId) {
|
|
44
|
+
key
|
|
45
|
+
value
|
|
46
|
+
defaultValue
|
|
47
|
+
valueType
|
|
48
|
+
description
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
// ─── Hook ───────────────────────────────────────────────────────────────────
|
|
53
|
+
function useChatConfiguration(options = {}) {
|
|
54
|
+
const {
|
|
55
|
+
channelId,
|
|
56
|
+
pollInterval = 0
|
|
57
|
+
} = options;
|
|
58
|
+
const {
|
|
59
|
+
data,
|
|
60
|
+
loading,
|
|
61
|
+
error,
|
|
62
|
+
refetch: apolloRefetch
|
|
63
|
+
} = useQuery(CHAT_CONFIGURATION_QUERY, {
|
|
64
|
+
variables: {
|
|
65
|
+
channelId
|
|
66
|
+
},
|
|
67
|
+
pollInterval,
|
|
68
|
+
fetchPolicy: 'cache-and-network'
|
|
69
|
+
});
|
|
70
|
+
const [updateMutation] = useMutation(UPDATE_CHAT_CONFIGURATION);
|
|
71
|
+
const [resetMutation] = useMutation(RESET_CHAT_CONFIGURATION);
|
|
72
|
+
const entries = useMemo(() => data?.chatConfiguration?.entries ?? [], [data]);
|
|
73
|
+
// Index by key for O(1) lookups
|
|
74
|
+
const entryMap = useMemo(() => {
|
|
75
|
+
const map = new Map();
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
map.set(entry.key, entry);
|
|
78
|
+
}
|
|
79
|
+
return map;
|
|
80
|
+
}, [entries]);
|
|
81
|
+
const get = useCallback(key => entryMap.get(key)?.value, [entryMap]);
|
|
82
|
+
const getEntry = useCallback(key => entryMap.get(key), [entryMap]);
|
|
83
|
+
const set = useCallback(async (key, value) => {
|
|
84
|
+
await updateMutation({
|
|
85
|
+
variables: {
|
|
86
|
+
updates: [{
|
|
87
|
+
key,
|
|
88
|
+
value
|
|
89
|
+
}],
|
|
90
|
+
channelId
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
await apolloRefetch();
|
|
94
|
+
}, [updateMutation, apolloRefetch, channelId]);
|
|
95
|
+
const setMany = useCallback(async updates => {
|
|
96
|
+
await updateMutation({
|
|
97
|
+
variables: {
|
|
98
|
+
updates,
|
|
99
|
+
channelId
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
await apolloRefetch();
|
|
103
|
+
}, [updateMutation, apolloRefetch, channelId]);
|
|
104
|
+
const reset = useCallback(async key => {
|
|
105
|
+
await resetMutation({
|
|
106
|
+
variables: {
|
|
107
|
+
key,
|
|
108
|
+
channelId
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
await apolloRefetch();
|
|
112
|
+
}, [resetMutation, apolloRefetch, channelId]);
|
|
113
|
+
const refetch = useCallback(async () => {
|
|
114
|
+
await apolloRefetch();
|
|
115
|
+
}, [apolloRefetch]);
|
|
116
|
+
return {
|
|
117
|
+
entries,
|
|
118
|
+
loading,
|
|
119
|
+
error,
|
|
120
|
+
get,
|
|
121
|
+
getEntry,
|
|
122
|
+
set,
|
|
123
|
+
setMany,
|
|
124
|
+
reset,
|
|
125
|
+
refetch
|
|
126
|
+
};
|
|
127
|
+
}export{useChatConfiguration};//# sourceMappingURL=use-chat-configuration.hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-configuration.hook.js","sources":["../../src/hooks/use-chat-configuration.hook.ts"],"sourcesContent":[null],"names":[],"mappings":"uGAAA;;;;;;;;;;;;AAYG;AAIH;AAEA,MAAM,wBAAwB,GAAG,GAAG;;;;;;;;;;;;CAYnC;AAED,MAAM,yBAAyB,GAAG,GAAG;;;;;;;;;;;;CAYpC;AAED,MAAM,wBAAwB,GAAG,GAAG;;;;;;;;;;CAUnC;AAwCD;AAEM,SAAU,oBAAoB,CAAC,OAAA,GAAuC,EAAE,EAAA;QAC1E;AAEA,IAAA,SACI;gBAKA,GAAW;aACX;AACA,EAAA,MAAA;AACH,IAAA,IAAE;IAEH,OAAO;IACP,KAAA;AAEA,IAAA;MAEA,QAAA,CAAA,wBAAgC,EAAA;AAChC,IAAA,SAAM,EAAA;AACF,MAAA;AACA,KAAA;gBACQ;eACP,EAAA;AACD,GAAA,CAAA;AACJ,EAAA,MAAI,CAAA,cAAU,CAAA,GAAA,WAAA,CAAA,yBAAA,CAAA;QAEd,CAAA,aAAY,CAAA,GAAA,WAAsC,CAAA,yBAA0B;QAE5E,OAAM,GAAQ,OAAG,CAAA,MAAW,IAAE,EAAW,iBAAsD,SAAO,IAAA,EAAQ,EAAE,CAAC,IAAA,CAAA,CAAA;;AAIzG,EAAA,MAAA,yBAAqB;AACjB,IAAA,MAAA,GAAA,GAAA,IAAA,GAAW,EAAA;AACP,IAAA,KAAA,MAAA,KAAA,WAAe,EAAE;mBACjB,CAAA,GAAA,EAAS,KAAA,CAAA;AACZ,IAAA;AACJ,IAAA,OAAE,GAAA;aACH,CAAM,CAAA;QAET,GAAA,GAAA,2BAA+B,CAAA,GAAA,CAAA,GAAU,CAC7C,EAAC,KAAA,EAAA,CAAA,QAAA,CAAA,CAAA;QAEF,QAAM,cAAU,CAAW,OAClB,QAAiD,IAAmB,CAAA,GAAA,CAAA,EAAA,CAAA,QAAA,CAAA,CAAA;AACrE,EAAA,MAAA,GAAA,GAAM,mBAAe,GAAA,EAAA,KAAA,KAAA;AACjB,IAAA,MAAA,cAAW,CAAE;AAChB,MAAA,SAAE,EAAA;QACH,OAAM,EAAA,CAAA;UAET,GAAA;UAGC;AAEE,SAAA,CAAA;AACI,QAAA;AACH;;IAEL,MACC,aAAe;AAGpB,EAAA,CAAA,EAAA,CAAA,cAAgB,EAAA,aAAY,EAAK,SAAM,CAAA,CAAA;QACnC,OAAM,GAAA,WAAe,CAAC,MAAA,OAAA,IAAA;AAC1B,IAAA,MAAI,cAAgB,CAAA;MAEpB,SAAO,EAAA;QACH,OAAO;QACP;;;UAGA,aAAQ,EAAA;oBACL,EAAA,aAAA,EAAA,SAAA,CAAA,CAAA;QACH,KAAA,GAAO,WAAA,CAAA,MAAA,GAAA,IAAA;UACP,aAAK,CAAA;eACE,EAAA;QACT,GAAA;AACN,QAAC;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface SendMessageUser {
|
|
2
|
+
id: string;
|
|
3
|
+
givenName?: string;
|
|
4
|
+
familyName?: string;
|
|
5
|
+
email?: string;
|
|
6
|
+
username?: string;
|
|
7
|
+
fullName?: string;
|
|
8
|
+
picture?: string;
|
|
9
|
+
alias?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface FailedMessage {
|
|
12
|
+
id: string;
|
|
13
|
+
content: string;
|
|
14
|
+
fileIds?: string[];
|
|
15
|
+
timestamp: Date;
|
|
16
|
+
}
|
|
17
|
+
export interface UseSendMessageOptions {
|
|
18
|
+
channelId: string;
|
|
19
|
+
currentUser: SendMessageUser;
|
|
20
|
+
parentId?: string | null;
|
|
21
|
+
/** Number of messages per page (used for cache query variables) */
|
|
22
|
+
limit?: number;
|
|
23
|
+
/** Callback when message is sent successfully */
|
|
24
|
+
onSuccess?: () => void;
|
|
25
|
+
/** Callback when message fails */
|
|
26
|
+
onError?: (error: any, failedMessage: FailedMessage) => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Centralized hook for sending messages with Apollo cache optimistic updates.
|
|
30
|
+
* Provides instant message rendering, automatic cache updates via type policies,
|
|
31
|
+
* and failed message tracking with retry support.
|
|
32
|
+
*
|
|
33
|
+
* Usage:
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const { sendMessage, retryMessage, dismissFailed, failedMessages, sending } = useSendMessage({
|
|
36
|
+
* channelId,
|
|
37
|
+
* currentUser: { id: user.id, username: user.username, ... },
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // Send
|
|
41
|
+
* await sendMessage('Hello!', ['fileId1']);
|
|
42
|
+
*
|
|
43
|
+
* // Retry failed
|
|
44
|
+
* retryMessage(failedMessages[0]);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function useSendMessage({ channelId, currentUser, parentId, limit, onSuccess, onError, }: UseSendMessageOptions): {
|
|
48
|
+
sendMessage: (content: string, fileIds?: string[], postId?: string, uploadedFiles?: any[]) => Promise<void>;
|
|
49
|
+
retryMessage: (failedMsg: FailedMessage) => Promise<void>;
|
|
50
|
+
dismissFailed: (id: string) => void;
|
|
51
|
+
clearAllFailed: () => void;
|
|
52
|
+
failedMessages: FailedMessage[];
|
|
53
|
+
sending: boolean;
|
|
54
|
+
/** Exposed for advanced use (e.g. custom optimistic shapes with uploaded files) */
|
|
55
|
+
createOptimisticPost: (content: string, postId?: string, files?: any[]) => {
|
|
56
|
+
__typename: "Post";
|
|
57
|
+
id: string;
|
|
58
|
+
message: string;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
updatedAt: string;
|
|
61
|
+
isPinned: boolean;
|
|
62
|
+
type: any;
|
|
63
|
+
isDelivered: boolean;
|
|
64
|
+
isRead: boolean;
|
|
65
|
+
parentId: string;
|
|
66
|
+
fromServer: boolean;
|
|
67
|
+
props: any;
|
|
68
|
+
propsConfiguration: {
|
|
69
|
+
__typename: "MachineConfiguration";
|
|
70
|
+
id: any;
|
|
71
|
+
resource: any;
|
|
72
|
+
contents: any;
|
|
73
|
+
keys: any;
|
|
74
|
+
target: any;
|
|
75
|
+
overrides: any;
|
|
76
|
+
};
|
|
77
|
+
channel: {
|
|
78
|
+
__typename: "Channel";
|
|
79
|
+
id: string;
|
|
80
|
+
};
|
|
81
|
+
author: {
|
|
82
|
+
__typename: "UserAccount";
|
|
83
|
+
id: string;
|
|
84
|
+
givenName: string;
|
|
85
|
+
familyName: string;
|
|
86
|
+
email: string;
|
|
87
|
+
username: string;
|
|
88
|
+
fullName: string;
|
|
89
|
+
picture: string;
|
|
90
|
+
alias: string[];
|
|
91
|
+
tokens: any;
|
|
92
|
+
};
|
|
93
|
+
files: {
|
|
94
|
+
__typename: "FilesInfo";
|
|
95
|
+
totalCount: number;
|
|
96
|
+
data: any[];
|
|
97
|
+
};
|
|
98
|
+
replies: {
|
|
99
|
+
__typename: "Messages";
|
|
100
|
+
totalCount: number;
|
|
101
|
+
data: any[];
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
updateCache: (cache: any, newPost: any) => void;
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=use-send-message.hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-send-message.hook.d.ts","sourceRoot":"","sources":["../../src/hooks/use-send-message.hook.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;CAChE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,EAC3B,SAAS,EACT,WAAW,EACX,QAAe,EACf,KAAU,EACV,SAAS,EACT,OAAO,GACV,EAAE,qBAAqB;2BA4GA,MAAM,YAAY,MAAM,EAAE,WAAW,MAAM,kBAAkB,GAAG,EAAE;8BA+ChE,aAAa;wBAWI,MAAM;;;;IAezC,mFAAmF;oCAhLzE,MAAM,WAAW,MAAM,UAAU,GAAG,EAAE;;;;;;;;;;;;;;;;sBAgBxB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAkCnB,GAAG,WAAW,GAAG;EAkIhC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {useState,useCallback}from'react';import {useSendMessagesMutation}from'common/graphql';import {objectId}from'@messenger-box/core';/**
|
|
2
|
+
* Centralized hook for sending messages with Apollo cache optimistic updates.
|
|
3
|
+
* Provides instant message rendering, automatic cache updates via type policies,
|
|
4
|
+
* and failed message tracking with retry support.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const { sendMessage, retryMessage, dismissFailed, failedMessages, sending } = useSendMessage({
|
|
9
|
+
* channelId,
|
|
10
|
+
* currentUser: { id: user.id, username: user.username, ... },
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Send
|
|
14
|
+
* await sendMessage('Hello!', ['fileId1']);
|
|
15
|
+
*
|
|
16
|
+
* // Retry failed
|
|
17
|
+
* retryMessage(failedMessages[0]);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function useSendMessage({
|
|
21
|
+
channelId,
|
|
22
|
+
currentUser,
|
|
23
|
+
parentId = null,
|
|
24
|
+
limit = 30,
|
|
25
|
+
onSuccess,
|
|
26
|
+
onError
|
|
27
|
+
}) {
|
|
28
|
+
const [sendMessageMutation, {
|
|
29
|
+
loading: sending
|
|
30
|
+
}] = useSendMessagesMutation();
|
|
31
|
+
const [failedMessages, setFailedMessages] = useState([]);
|
|
32
|
+
const createOptimisticPost = useCallback((content, postId, files) => ({
|
|
33
|
+
__typename: 'Post',
|
|
34
|
+
id: postId || `optimistic-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
35
|
+
message: content,
|
|
36
|
+
createdAt: new Date().toISOString(),
|
|
37
|
+
updatedAt: new Date().toISOString(),
|
|
38
|
+
isPinned: false,
|
|
39
|
+
type: null,
|
|
40
|
+
isDelivered: false,
|
|
41
|
+
isRead: false,
|
|
42
|
+
parentId: parentId || null,
|
|
43
|
+
fromServer: false,
|
|
44
|
+
props: null,
|
|
45
|
+
propsConfiguration: {
|
|
46
|
+
__typename: 'MachineConfiguration',
|
|
47
|
+
id: null,
|
|
48
|
+
resource: '',
|
|
49
|
+
contents: null,
|
|
50
|
+
keys: null,
|
|
51
|
+
target: null,
|
|
52
|
+
overrides: null
|
|
53
|
+
},
|
|
54
|
+
channel: {
|
|
55
|
+
__typename: 'Channel',
|
|
56
|
+
id: channelId
|
|
57
|
+
},
|
|
58
|
+
author: {
|
|
59
|
+
__typename: 'UserAccount',
|
|
60
|
+
id: currentUser.id || '',
|
|
61
|
+
givenName: currentUser.givenName || '',
|
|
62
|
+
familyName: currentUser.familyName || '',
|
|
63
|
+
email: currentUser.email || '',
|
|
64
|
+
username: currentUser.username || currentUser.givenName || 'You',
|
|
65
|
+
fullName: currentUser.fullName || '',
|
|
66
|
+
picture: currentUser.picture || null,
|
|
67
|
+
alias: currentUser.alias || null,
|
|
68
|
+
tokens: null
|
|
69
|
+
},
|
|
70
|
+
files: {
|
|
71
|
+
__typename: 'FilesInfo',
|
|
72
|
+
totalCount: files?.length || 0,
|
|
73
|
+
data: files || []
|
|
74
|
+
},
|
|
75
|
+
replies: {
|
|
76
|
+
__typename: 'Messages',
|
|
77
|
+
totalCount: 0,
|
|
78
|
+
data: []
|
|
79
|
+
}
|
|
80
|
+
}), [channelId, currentUser, parentId]);
|
|
81
|
+
const updateCache = useCallback((cache, newPost) => {
|
|
82
|
+
if (!newPost) return;
|
|
83
|
+
// Use cache.modify to directly update the ROOT_QUERY messages field.
|
|
84
|
+
// This reliably triggers re-renders for ALL watching queries,
|
|
85
|
+
// regardless of what variables they pass (limit, skip, etc.).
|
|
86
|
+
// The storeFieldName check ensures we only modify the correct channel's data.
|
|
87
|
+
const targetChannelId = channelId.toString();
|
|
88
|
+
cache.modify({
|
|
89
|
+
fields: {
|
|
90
|
+
messages(existing, {
|
|
91
|
+
storeFieldName,
|
|
92
|
+
toReference
|
|
93
|
+
}) {
|
|
94
|
+
// Only modify messages for the matching channel
|
|
95
|
+
if (!storeFieldName.includes(targetChannelId)) return existing;
|
|
96
|
+
// Skip thread-level queries (those with parentId)
|
|
97
|
+
if (parentId) {
|
|
98
|
+
if (!storeFieldName.includes(parentId)) return existing;
|
|
99
|
+
} else {
|
|
100
|
+
// For channel-level messages, skip entries that have a parentId
|
|
101
|
+
// (i.e. thread queries) by checking for 'parentId' in the key
|
|
102
|
+
// but ONLY if the key explicitly has a non-null parentId
|
|
103
|
+
if (storeFieldName.includes('"parentId"') && !storeFieldName.includes('"parentId":null')) {
|
|
104
|
+
return existing;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (!existing) {
|
|
108
|
+
return {
|
|
109
|
+
__typename: 'Messages',
|
|
110
|
+
data: [toReference(newPost)],
|
|
111
|
+
totalCount: 1
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// Check if post already exists (dedup by ID)
|
|
115
|
+
const newRef = toReference(newPost);
|
|
116
|
+
const existingRefs = existing.data || [];
|
|
117
|
+
const alreadyExists = existingRefs.some(ref => ref?.__ref === newRef?.__ref);
|
|
118
|
+
if (alreadyExists) return existing;
|
|
119
|
+
return {
|
|
120
|
+
...existing,
|
|
121
|
+
data: [...existingRefs, newRef],
|
|
122
|
+
totalCount: (existing.totalCount || 0) + 1
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}, [channelId, parentId]);
|
|
128
|
+
const sendMessage = useCallback(async (content, fileIds, postId, uploadedFiles) => {
|
|
129
|
+
if (!content.trim() && (!fileIds || fileIds.length === 0)) return;
|
|
130
|
+
if (!channelId) return;
|
|
131
|
+
// Always ensure a postId so the optimistic response ID
|
|
132
|
+
// matches the server-returned ID (server uses _id: postId)
|
|
133
|
+
const resolvedPostId = postId || objectId();
|
|
134
|
+
const optimisticPost = createOptimisticPost(content, resolvedPostId, uploadedFiles);
|
|
135
|
+
try {
|
|
136
|
+
await sendMessageMutation({
|
|
137
|
+
variables: {
|
|
138
|
+
channelId,
|
|
139
|
+
content: content.trim(),
|
|
140
|
+
postId: resolvedPostId,
|
|
141
|
+
...(fileIds && fileIds.length > 0 ? {
|
|
142
|
+
files: fileIds
|
|
143
|
+
} : {})
|
|
144
|
+
},
|
|
145
|
+
optimisticResponse: {
|
|
146
|
+
__typename: 'Mutation',
|
|
147
|
+
sendMessage: optimisticPost
|
|
148
|
+
},
|
|
149
|
+
update: (cache, {
|
|
150
|
+
data
|
|
151
|
+
}) => {
|
|
152
|
+
// Update cache with real response, replacing optimistic entry
|
|
153
|
+
updateCache(cache, data?.sendMessage);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
// Remove from failed if this was a retry
|
|
157
|
+
setFailedMessages(prev => prev.filter(m => m.content !== content.trim()));
|
|
158
|
+
onSuccess?.();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
console.error('Error sending message:', err);
|
|
161
|
+
const failedMsg = {
|
|
162
|
+
id: `failed-${Date.now()}`,
|
|
163
|
+
content: content.trim(),
|
|
164
|
+
fileIds,
|
|
165
|
+
timestamp: new Date()
|
|
166
|
+
};
|
|
167
|
+
setFailedMessages(prev => [...prev, failedMsg]);
|
|
168
|
+
onError?.(err, failedMsg);
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
}, [channelId, createOptimisticPost, sendMessageMutation, updateCache, onSuccess, onError]);
|
|
172
|
+
const retryMessage = useCallback(async failedMsg => {
|
|
173
|
+
setFailedMessages(prev => prev.filter(m => m.id !== failedMsg.id));
|
|
174
|
+
try {
|
|
175
|
+
await sendMessage(failedMsg.content, failedMsg.fileIds);
|
|
176
|
+
} catch {
|
|
177
|
+
// sendMessage already re-adds to failed
|
|
178
|
+
}
|
|
179
|
+
}, [sendMessage]);
|
|
180
|
+
const dismissFailed = useCallback(id => {
|
|
181
|
+
setFailedMessages(prev => prev.filter(m => m.id !== id));
|
|
182
|
+
}, []);
|
|
183
|
+
const clearAllFailed = useCallback(() => {
|
|
184
|
+
setFailedMessages([]);
|
|
185
|
+
}, []);
|
|
186
|
+
return {
|
|
187
|
+
sendMessage,
|
|
188
|
+
retryMessage,
|
|
189
|
+
dismissFailed,
|
|
190
|
+
clearAllFailed,
|
|
191
|
+
failedMessages,
|
|
192
|
+
sending,
|
|
193
|
+
/** Exposed for advanced use (e.g. custom optimistic shapes with uploaded files) */
|
|
194
|
+
createOptimisticPost,
|
|
195
|
+
updateCache
|
|
196
|
+
};
|
|
197
|
+
}export{useSendMessage};//# sourceMappingURL=use-send-message.hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-send-message.hook.js","sources":["../../src/hooks/use-send-message.hook.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming protocol:
|
|
3
|
+
* [STREAM:<streamId>:<status>] <content>
|
|
4
|
+
*
|
|
5
|
+
* status = 'start' | 'delta' | 'end' | 'thinking' | 'tool'
|
|
6
|
+
*
|
|
7
|
+
* Delta messages carry the **full accumulated text** (not just the new chunk),
|
|
8
|
+
* so the hook always replaces `text` rather than appending.
|
|
9
|
+
*/
|
|
10
|
+
export interface ActiveStream {
|
|
11
|
+
streamId: string;
|
|
12
|
+
/** Full accumulated text so far */
|
|
13
|
+
text: string;
|
|
14
|
+
/** Author of the stream (from the first message) */
|
|
15
|
+
author: any;
|
|
16
|
+
/** Client-side timestamp when streaming started */
|
|
17
|
+
startedAt: number;
|
|
18
|
+
/** Server-side createdAt from the first stream message — use for timeline sorting */
|
|
19
|
+
serverCreatedAt: string | null;
|
|
20
|
+
/** Current status */
|
|
21
|
+
status: 'start' | 'delta' | 'thinking' | 'tool' | 'end';
|
|
22
|
+
/** Number of chunks received */
|
|
23
|
+
chunks: number;
|
|
24
|
+
}
|
|
25
|
+
export interface CompletedStream {
|
|
26
|
+
streamId: string;
|
|
27
|
+
text: string;
|
|
28
|
+
author: any;
|
|
29
|
+
startedAt: number;
|
|
30
|
+
/** Server-side createdAt from the first stream message — use for timeline sorting */
|
|
31
|
+
serverCreatedAt: string | null;
|
|
32
|
+
endedAt: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse a raw message string. Returns null if it's not a stream message.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseStreamMessage(raw: string): {
|
|
38
|
+
streamId: string;
|
|
39
|
+
status: 'start' | 'delta' | 'end' | 'thinking' | 'tool';
|
|
40
|
+
content: string;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* Hook that reassembles streaming messages into live text.
|
|
44
|
+
*
|
|
45
|
+
* Feed every incoming subscription message through `ingest()`.
|
|
46
|
+
* - If it's a stream fragment, it accumulates it and returns `true` (suppress from message list).
|
|
47
|
+
* - If it's a normal message, it returns `false` (add to list normally).
|
|
48
|
+
*
|
|
49
|
+
* The hook exposes:
|
|
50
|
+
* - `activeStreams` — streams still being typed (show typing bubble)
|
|
51
|
+
* - `completedStreams` — finished streams whose final text should persist inline
|
|
52
|
+
* until a clean (non-stream) copy of the same content arrives via polling.
|
|
53
|
+
*/
|
|
54
|
+
export declare function useStreamAssembler(): {
|
|
55
|
+
activeStreams: Map<string, ActiveStream>;
|
|
56
|
+
completedStreams: Map<string, CompletedStream>;
|
|
57
|
+
ingest: (message: {
|
|
58
|
+
id: string;
|
|
59
|
+
message: string;
|
|
60
|
+
author?: any;
|
|
61
|
+
createdAt?: any;
|
|
62
|
+
}) => boolean;
|
|
63
|
+
isSuppressed: (messageId: string) => boolean;
|
|
64
|
+
dismissCompleted: (streamId: string) => void;
|
|
65
|
+
dismissByText: (text: string) => void;
|
|
66
|
+
reset: () => void;
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=use-stream-assembler.hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-stream-assembler.hook.d.ts","sourceRoot":"","sources":["../../src/hooks/use-stream-assembler.hook.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,MAAM,EAAE,GAAG,CAAC;IACZ,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qBAAqB;IACrB,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,CAAC;IACxD,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;CACnB;AAID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;IACxD,OAAO,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAKP;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB;;;sBAkBhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,CAAC;QAAC,SAAS,CAAC,EAAE,GAAG,CAAA;KAAE,KAAG,OAAO;8BAqEzC,MAAM,KAAG,OAAO;iCAQb,MAAM;0BASb,MAAM;;EA4BlD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {useState,useRef,useCallback}from'react';const STREAM_PREFIX_RE = /^\[STREAM:([^:]+):(start|delta|end|thinking|tool)\]\s?([\s\S]*)$/;
|
|
2
|
+
/**
|
|
3
|
+
* Parse a raw message string. Returns null if it's not a stream message.
|
|
4
|
+
*/
|
|
5
|
+
function parseStreamMessage(raw) {
|
|
6
|
+
if (!raw) return null;
|
|
7
|
+
const m = STREAM_PREFIX_RE.exec(raw);
|
|
8
|
+
if (!m) return null;
|
|
9
|
+
return {
|
|
10
|
+
streamId: m[1],
|
|
11
|
+
status: m[2],
|
|
12
|
+
content: m[3]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Hook that reassembles streaming messages into live text.
|
|
17
|
+
*
|
|
18
|
+
* Feed every incoming subscription message through `ingest()`.
|
|
19
|
+
* - If it's a stream fragment, it accumulates it and returns `true` (suppress from message list).
|
|
20
|
+
* - If it's a normal message, it returns `false` (add to list normally).
|
|
21
|
+
*
|
|
22
|
+
* The hook exposes:
|
|
23
|
+
* - `activeStreams` — streams still being typed (show typing bubble)
|
|
24
|
+
* - `completedStreams` — finished streams whose final text should persist inline
|
|
25
|
+
* until a clean (non-stream) copy of the same content arrives via polling.
|
|
26
|
+
*/
|
|
27
|
+
function useStreamAssembler() {
|
|
28
|
+
const [activeStreams, setActiveStreams] = useState(new Map());
|
|
29
|
+
const [completedStreams, setCompletedStreams] = useState(new Map());
|
|
30
|
+
const streamsRef = useRef(new Map());
|
|
31
|
+
const completedRef = useRef(new Map());
|
|
32
|
+
// Set of message IDs we've already ingested as stream fragments — so the
|
|
33
|
+
// subscription updateQuery can skip them when deciding whether to add to the list.
|
|
34
|
+
const suppressedIdsRef = useRef(new Set());
|
|
35
|
+
/** Sync React state from refs */
|
|
36
|
+
const flush = useCallback(() => {
|
|
37
|
+
setActiveStreams(new Map(streamsRef.current));
|
|
38
|
+
setCompletedStreams(new Map(completedRef.current));
|
|
39
|
+
}, []);
|
|
40
|
+
/** Returns true if the message was a stream fragment (should be suppressed from list). */
|
|
41
|
+
const ingest = useCallback(message => {
|
|
42
|
+
const parsed = parseStreamMessage(message.message);
|
|
43
|
+
if (!parsed) return false; // normal message
|
|
44
|
+
const {
|
|
45
|
+
streamId,
|
|
46
|
+
status,
|
|
47
|
+
content
|
|
48
|
+
} = parsed;
|
|
49
|
+
suppressedIdsRef.current.add(message.id);
|
|
50
|
+
const existing = streamsRef.current.get(streamId);
|
|
51
|
+
if (status === 'start' || status === 'thinking') {
|
|
52
|
+
// Use existing serverCreatedAt if we already have one (don't overwrite on re-ingest)
|
|
53
|
+
const serverCreatedAt = existing?.serverCreatedAt || message.createdAt || null;
|
|
54
|
+
const stream = {
|
|
55
|
+
streamId,
|
|
56
|
+
text: content,
|
|
57
|
+
author: message.author || existing?.author,
|
|
58
|
+
startedAt: existing?.startedAt || Date.now(),
|
|
59
|
+
serverCreatedAt,
|
|
60
|
+
status,
|
|
61
|
+
chunks: existing?.chunks || 1
|
|
62
|
+
};
|
|
63
|
+
streamsRef.current.set(streamId, stream);
|
|
64
|
+
} else if (status === 'delta' || status === 'tool') {
|
|
65
|
+
if (existing) {
|
|
66
|
+
// Delta carries the full accumulated text — REPLACE, don't append
|
|
67
|
+
existing.text = content;
|
|
68
|
+
existing.status = status;
|
|
69
|
+
existing.chunks += 1;
|
|
70
|
+
// Capture serverCreatedAt from first message if we missed the start
|
|
71
|
+
if (!existing.serverCreatedAt && message.createdAt) {
|
|
72
|
+
existing.serverCreatedAt = message.createdAt;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
// Delta without a start — create one anyway
|
|
76
|
+
streamsRef.current.set(streamId, {
|
|
77
|
+
streamId,
|
|
78
|
+
text: content,
|
|
79
|
+
author: message.author,
|
|
80
|
+
startedAt: Date.now(),
|
|
81
|
+
serverCreatedAt: message.createdAt || null,
|
|
82
|
+
status,
|
|
83
|
+
chunks: 1
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
} else if (status === 'end') {
|
|
87
|
+
const finalText = content || existing?.text || '';
|
|
88
|
+
const author = existing?.author || message.author;
|
|
89
|
+
const startedAt = existing?.startedAt || Date.now();
|
|
90
|
+
const serverCreatedAt = existing?.serverCreatedAt || message.createdAt || null;
|
|
91
|
+
// Move from active → completed (keeps text visible inline)
|
|
92
|
+
streamsRef.current.delete(streamId);
|
|
93
|
+
completedRef.current.set(streamId, {
|
|
94
|
+
streamId,
|
|
95
|
+
text: finalText,
|
|
96
|
+
author,
|
|
97
|
+
startedAt,
|
|
98
|
+
serverCreatedAt,
|
|
99
|
+
endedAt: Date.now()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
flush();
|
|
103
|
+
return true;
|
|
104
|
+
}, [flush]);
|
|
105
|
+
/** Whether a message ID was suppressed as a stream fragment */
|
|
106
|
+
const isSuppressed = useCallback(messageId => {
|
|
107
|
+
return suppressedIdsRef.current.has(messageId);
|
|
108
|
+
}, []);
|
|
109
|
+
/**
|
|
110
|
+
* Dismiss a completed stream (call when the clean final message appears in
|
|
111
|
+
* the list via polling, so we don't show a duplicate).
|
|
112
|
+
*/
|
|
113
|
+
const dismissCompleted = useCallback(streamId => {
|
|
114
|
+
completedRef.current.delete(streamId);
|
|
115
|
+
setCompletedStreams(new Map(completedRef.current));
|
|
116
|
+
}, []);
|
|
117
|
+
/**
|
|
118
|
+
* Dismiss completed streams whose text matches a clean message that just
|
|
119
|
+
* arrived, avoiding duplicate display.
|
|
120
|
+
*/
|
|
121
|
+
const dismissByText = useCallback(text => {
|
|
122
|
+
for (const [sid, cs] of completedRef.current) {
|
|
123
|
+
// Fuzzy match — the clean message content should match the stream final text
|
|
124
|
+
if (cs.text.trim() === text.trim()) {
|
|
125
|
+
completedRef.current.delete(sid);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
setCompletedStreams(new Map(completedRef.current));
|
|
129
|
+
}, []);
|
|
130
|
+
/** Reset all state (e.g. on channel switch) */
|
|
131
|
+
const reset = useCallback(() => {
|
|
132
|
+
streamsRef.current.clear();
|
|
133
|
+
completedRef.current.clear();
|
|
134
|
+
suppressedIdsRef.current.clear();
|
|
135
|
+
setActiveStreams(new Map());
|
|
136
|
+
setCompletedStreams(new Map());
|
|
137
|
+
}, []);
|
|
138
|
+
return {
|
|
139
|
+
activeStreams,
|
|
140
|
+
completedStreams,
|
|
141
|
+
ingest,
|
|
142
|
+
isSuppressed,
|
|
143
|
+
dismissCompleted,
|
|
144
|
+
dismissByText,
|
|
145
|
+
reset
|
|
146
|
+
};
|
|
147
|
+
}export{parseStreamMessage,useStreamAssembler};//# sourceMappingURL=use-stream-assembler.hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-stream-assembler.hook.js","sources":["../../src/hooks/use-stream-assembler.hook.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{typePolicies}from'./graphql/index.js';export{getFilteredMenus,getFilteredRoutes,getFilteredTabs}from'./utils/index.js';export{useUploadFile}from'./hooks/use-upload-file.hook.js';export{useUploadFiles}from'./hooks/use-upload-files.hook.js';export{useUploadFile as useUploadFileNative}from'./hooks/use-upload-file.hook.native.js';export{useUploadFiles as useUploadFilesNative}from'./hooks/use-upload-files.hook.native.js';export{dataIdFromObject}from'./graphql/id-generation.js';export{schema}from'./graphql/schema/index.js';//# sourceMappingURL=index.js.map
|
|
1
|
+
export{typePolicies}from'./graphql/index.js';export{getFilteredMenus,getFilteredRoutes,getFilteredTabs}from'./utils/index.js';export{useUploadFile}from'./hooks/use-upload-file.hook.js';export{useUploadFiles}from'./hooks/use-upload-files.hook.js';export{useUploadFile as useUploadFileNative}from'./hooks/use-upload-file.hook.native.js';export{useUploadFiles as useUploadFilesNative}from'./hooks/use-upload-files.hook.native.js';export{useSendMessage}from'./hooks/use-send-message.hook.js';export{parseStreamMessage,useStreamAssembler}from'./hooks/use-stream-assembler.hook.js';export{useChatConfiguration}from'./hooks/use-chat-configuration.hook.js';export{ChatSettingsProvider,useChatSettings}from'./context/ChatSettingsContext.js';export{dataIdFromObject}from'./graphql/id-generation.js';export{schema}from'./graphql/schema/index.js';//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@messenger-box/platform-client",
|
|
3
|
-
"version": "10.0.3-alpha.
|
|
3
|
+
"version": "10.0.3-alpha.201",
|
|
4
4
|
"description": "Sample core for higher packages to depend on",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"watch": "yarn build:lib:watch"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@messenger-box/core": "10.0.3-alpha.
|
|
23
|
+
"@messenger-box/core": "10.0.3-alpha.201",
|
|
24
24
|
"key-mirror": "1.0.1",
|
|
25
25
|
"moment-timezone": "0.5.33"
|
|
26
26
|
},
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"typescript": {
|
|
36
36
|
"definition": "lib/index.d.ts"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "1be5725604232d5f432d47a63a712031da4d96c0"
|
|
39
39
|
}
|