@burdenoff/microfe-conversations 2026.530.1 → 2026.601.1
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/dist/conversations/ConversationsAdminRoutes.js +19 -21
- package/dist/conversations/ConversationsAdminRoutes.js.map +1 -1
- package/dist/conversations/hooks/useConversationQueries.js +46 -36
- package/dist/conversations/hooks/useConversationQueries.js.map +1 -1
- package/dist/conversations/hooks/useMessageQueries.js +2 -1
- package/dist/conversations/hooks/useMessageQueries.js.map +1 -1
- package/dist/conversations/hooks/useMessageSubscriptions.js +22 -23
- package/dist/conversations/hooks/useMessageSubscriptions.js.map +1 -1
- package/dist/conversations/pages/ConversationAdminPages.js +60 -38
- package/dist/conversations/pages/ConversationAdminPages.js.map +1 -1
- package/dist/conversations/pages/ConversationDetailPage.js +237 -179
- package/dist/conversations/pages/ConversationDetailPage.js.map +1 -1
- package/dist/conversations/providers/ConversationsProvider.js +75 -67
- package/dist/conversations/providers/ConversationsProvider.js.map +1 -1
- package/dist/generated/wspace-operations.js +82 -58
- package/dist/generated/wspace-operations.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,35 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
1
|
+
import { AdminConversationsLandingPage as e } from "./pages/AdminConversationsLandingPage.js";
|
|
2
|
+
import { AppInstallationsPage as t, BulkOperationsPage as n, ConversationAuditLogPage as r, ModerationQueuePage as i } from "./pages/ConversationAdminPages.js";
|
|
3
|
+
import { Navigate as a, Route as o, Routes as s } from "react-router-dom";
|
|
4
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
5
|
//#region src/conversations/ConversationsAdminRoutes.tsx
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/* @__PURE__ */ l(s, {
|
|
6
|
+
function u() {
|
|
7
|
+
return /* @__PURE__ */ l(s, { children: [
|
|
8
|
+
/* @__PURE__ */ c(o, {
|
|
11
9
|
index: !0,
|
|
12
|
-
element: /* @__PURE__ */
|
|
10
|
+
element: /* @__PURE__ */ c(e, {})
|
|
13
11
|
}),
|
|
14
|
-
|
|
12
|
+
/* @__PURE__ */ c(o, {
|
|
15
13
|
path: "moderation",
|
|
16
|
-
element: /* @__PURE__ */
|
|
14
|
+
element: /* @__PURE__ */ c(i, {})
|
|
17
15
|
}),
|
|
18
|
-
|
|
16
|
+
/* @__PURE__ */ c(o, {
|
|
19
17
|
path: "bulk",
|
|
20
|
-
element: /* @__PURE__ */
|
|
18
|
+
element: /* @__PURE__ */ c(n, {})
|
|
21
19
|
}),
|
|
22
|
-
|
|
20
|
+
/* @__PURE__ */ c(o, {
|
|
23
21
|
path: "audit",
|
|
24
|
-
element: /* @__PURE__ */
|
|
22
|
+
element: /* @__PURE__ */ c(r, {})
|
|
25
23
|
}),
|
|
26
|
-
|
|
24
|
+
/* @__PURE__ */ c(o, {
|
|
27
25
|
path: "apps",
|
|
28
|
-
element: /* @__PURE__ */
|
|
26
|
+
element: /* @__PURE__ */ c(t, {})
|
|
29
27
|
}),
|
|
30
|
-
/* @__PURE__ */
|
|
28
|
+
/* @__PURE__ */ c(o, {
|
|
31
29
|
path: "*",
|
|
32
|
-
element: /* @__PURE__ */
|
|
30
|
+
element: /* @__PURE__ */ c(a, {
|
|
33
31
|
to: ".",
|
|
34
32
|
replace: !0
|
|
35
33
|
})
|
|
@@ -37,6 +35,6 @@ function d() {
|
|
|
37
35
|
] });
|
|
38
36
|
}
|
|
39
37
|
//#endregion
|
|
40
|
-
export {
|
|
38
|
+
export { u as ConversationsAdminRoutes };
|
|
41
39
|
|
|
42
40
|
//# sourceMappingURL=ConversationsAdminRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationsAdminRoutes.js","names":[],"sources":["../../src/conversations/ConversationsAdminRoutes.tsx"],"sourcesContent":["import { Navigate, Route, Routes } from \"react-router-dom\";\n\nimport { AdminConversationsLandingPage } from \"./pages/AdminConversationsLandingPage\";\nimport {\n AppInstallationsPage,\n BulkOperationsPage,\n ConversationAuditLogPage,\n ModerationQueuePage,\n} from \"./pages/ConversationAdminPages\";\
|
|
1
|
+
{"version":3,"file":"ConversationsAdminRoutes.js","names":[],"sources":["../../src/conversations/ConversationsAdminRoutes.tsx"],"sourcesContent":["import { Navigate, Route, Routes } from \"react-router-dom\";\n\nimport { AdminConversationsLandingPage } from \"./pages/AdminConversationsLandingPage\";\nimport {\n AppInstallationsPage,\n BulkOperationsPage,\n ConversationAuditLogPage,\n ModerationQueuePage,\n} from \"./pages/ConversationAdminPages\";\n\n/**\n * Admin-facing routes for the Conversations microfrontend.\n *\n * All imports in this file are eager — when real admin pages are added\n * and become `React.lazy()`, wrap the `<Routes>` below in\n * `<LazyPageBoundary source=\"admin\">` (from ./components/LazyPageBoundary)\n * to get the shared retry / spinner UI.\n *\n * Routes (relative to basePath, e.g., /conversations):\n * - / -> AdminConversationsLandingPage (overview + section directory)\n * - /moderation -> Moderation queue\n * - /bulk -> Bulk operations\n * - /audit -> Audit log viewer\n * - /apps -> App installations\n * - * -> redirect to landing\n */\nexport function ConversationsAdminRoutes() {\n return (\n <Routes>\n <Route index element={<AdminConversationsLandingPage />} />\n <Route path=\"moderation\" element={<ModerationQueuePage />} />\n <Route path=\"bulk\" element={<BulkOperationsPage />} />\n <Route path=\"audit\" element={<ConversationAuditLogPage />} />\n <Route path=\"apps\" element={<AppInstallationsPage />} />\n <Route path=\"*\" element={<Navigate to=\".\" replace />} />\n </Routes>\n );\n}\n"],"mappings":";;;;;AA0BA,SAAgB,IAA2B;AACzC,QACE,kBAAC,GAAD,EAAA,UAAA;EACE,kBAAC,GAAD;GAAO,OAAA;GAAM,SAAS,kBAAC,GAAD,EAAiC,CAAA;GAAI,CAAA;EAC3D,kBAAC,GAAD;GAAO,MAAK;GAAa,SAAS,kBAAC,GAAD,EAAuB,CAAA;GAAI,CAAA;EAC7D,kBAAC,GAAD;GAAO,MAAK;GAAO,SAAS,kBAAC,GAAD,EAAsB,CAAA;GAAI,CAAA;EACtD,kBAAC,GAAD;GAAO,MAAK;GAAQ,SAAS,kBAAC,GAAD,EAA4B,CAAA;GAAI,CAAA;EAC7D,kBAAC,GAAD;GAAO,MAAK;GAAO,SAAS,kBAAC,GAAD,EAAwB,CAAA;GAAI,CAAA;EACxD,kBAAC,GAAD;GAAO,MAAK;GAAI,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAI,SAAA;IAAU,CAAA;GAAI,CAAA;EACjD,EAAA,CAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useConversations as e } from "../providers/ConversationsProvider.js";
|
|
2
|
-
import { useArchiveConversationMutation as t, useCreateConversationMutation as n, useGetConversationQuery as r, useGetConversationsQuery as i,
|
|
3
|
-
import { mapConversation as
|
|
4
|
-
import { useCallback as
|
|
2
|
+
import { useArchiveConversationMutation as t, useCreateConversationMutation as n, useGetConversationQuery as r, useGetConversationsQuery as i, useLeaveConversationMutation as a, useMuteConversationMutation as o, usePinConversationMutation as s, useSearchConversationsQuery as c, useUnarchiveConversationMutation as l, useUnmuteConversationMutation as u, useUnpinConversationMutation as d, useUpdateConversationByHookMutation as f } from "../../generated/wspace-operations.js";
|
|
3
|
+
import { mapConversation as p } from "../utils/mappers.js";
|
|
4
|
+
import { useCallback as m, useMemo as h } from "react";
|
|
5
5
|
//#region src/conversations/hooks/useConversationQueries.ts
|
|
6
|
-
function
|
|
6
|
+
function g(t) {
|
|
7
7
|
let { workspaceId: n } = e(), r = i({
|
|
8
8
|
variables: {
|
|
9
9
|
first: t?.first ?? 25,
|
|
@@ -16,7 +16,7 @@ function h(t) {
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
skip: !n
|
|
19
|
-
}), a =
|
|
19
|
+
}), a = h(() => r.data?.conversations.edges.map((e) => p(e.node)) ?? [], [r.data]), o = r.data?.conversations.pageInfo.hasNextPage ?? !1;
|
|
20
20
|
return {
|
|
21
21
|
conversations: a,
|
|
22
22
|
loading: r.loading,
|
|
@@ -40,13 +40,15 @@ function h(t) {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function _(t) {
|
|
44
44
|
let { workspaceId: n } = e(), i = r({
|
|
45
45
|
variables: { id: t },
|
|
46
46
|
skip: !n || !t
|
|
47
47
|
});
|
|
48
48
|
return {
|
|
49
|
-
conversation: i.data?.conversation ?
|
|
49
|
+
conversation: i.data?.conversation ? p(i.data.conversation) : null,
|
|
50
|
+
members: i.data?.conversation?.members.edges.map((e) => e.node).filter((e) => !!e) ?? [],
|
|
51
|
+
membersTotalCount: i.data?.conversation?.members.totalCount ?? 0,
|
|
50
52
|
loading: i.loading,
|
|
51
53
|
error: i.error ?? null,
|
|
52
54
|
refetch: () => {
|
|
@@ -54,8 +56,8 @@ function g(t) {
|
|
|
54
56
|
}
|
|
55
57
|
};
|
|
56
58
|
}
|
|
57
|
-
function
|
|
58
|
-
let { workspaceId: n } = e(), r = t.trim(), i =
|
|
59
|
+
function v(t) {
|
|
60
|
+
let { workspaceId: n } = e(), r = t.trim(), i = c({
|
|
59
61
|
variables: {
|
|
60
62
|
query: r,
|
|
61
63
|
first: 25
|
|
@@ -63,15 +65,15 @@ function _(t) {
|
|
|
63
65
|
skip: !n || r.length < 2
|
|
64
66
|
});
|
|
65
67
|
return {
|
|
66
|
-
conversations: i.data?.searchConversations.edges.map((e) =>
|
|
68
|
+
conversations: i.data?.searchConversations.edges.map((e) => p(e.node)) ?? [],
|
|
67
69
|
loading: i.loading,
|
|
68
70
|
error: i.error ?? null
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
|
-
function
|
|
73
|
+
function y() {
|
|
72
74
|
let { workspaceId: t } = e(), [r, i] = n();
|
|
73
75
|
return {
|
|
74
|
-
createConversation:
|
|
76
|
+
createConversation: m(async (e) => {
|
|
75
77
|
if (!t) throw Error("Workspace context is required to create a conversation");
|
|
76
78
|
try {
|
|
77
79
|
let { data: n } = await r({ variables: { input: {
|
|
@@ -81,7 +83,7 @@ function v() {
|
|
|
81
83
|
description: e.description,
|
|
82
84
|
participantIds: e.participantIds
|
|
83
85
|
} } }), i = n?.createConversation.conversation;
|
|
84
|
-
return i ?
|
|
86
|
+
return i ? p(i) : null;
|
|
85
87
|
} catch (e) {
|
|
86
88
|
throw e instanceof Error ? e : /* @__PURE__ */ Error("Failed to create conversation");
|
|
87
89
|
}
|
|
@@ -90,10 +92,10 @@ function v() {
|
|
|
90
92
|
error: i.error ?? null
|
|
91
93
|
};
|
|
92
94
|
}
|
|
93
|
-
function
|
|
94
|
-
let [e, n] = t(), [r, i] =
|
|
95
|
+
function b() {
|
|
96
|
+
let [e, n] = t(), [r, i] = l(), [c, f] = s(), [p, h] = d(), [g, _] = o(), [v, y] = u(), [b, x] = a();
|
|
95
97
|
return {
|
|
96
|
-
archiveConversation:
|
|
98
|
+
archiveConversation: m(async (t) => {
|
|
97
99
|
let { data: n } = await e({
|
|
98
100
|
variables: { id: t },
|
|
99
101
|
refetchQueries: ["GetConversations"],
|
|
@@ -101,7 +103,7 @@ function y() {
|
|
|
101
103
|
});
|
|
102
104
|
return n?.archiveConversation.id === t;
|
|
103
105
|
}, [e]),
|
|
104
|
-
unarchiveConversation:
|
|
106
|
+
unarchiveConversation: m(async (e) => {
|
|
105
107
|
let { data: t } = await r({
|
|
106
108
|
variables: { id: e },
|
|
107
109
|
refetchQueries: ["GetConversations"],
|
|
@@ -109,33 +111,41 @@ function y() {
|
|
|
109
111
|
});
|
|
110
112
|
return t?.unarchiveConversation.id === e;
|
|
111
113
|
}, [r]),
|
|
112
|
-
pinConversation:
|
|
113
|
-
let { data: t } = await
|
|
114
|
+
pinConversation: m(async (e) => {
|
|
115
|
+
let { data: t } = await c({ variables: { conversationId: e } });
|
|
114
116
|
return !!t?.pinConversation?.id;
|
|
115
|
-
}, [
|
|
116
|
-
unpinConversation:
|
|
117
|
-
let { data: t } = await
|
|
117
|
+
}, [c]),
|
|
118
|
+
unpinConversation: m(async (e) => {
|
|
119
|
+
let { data: t } = await p({ variables: { conversationId: e } });
|
|
118
120
|
return !!t?.unpinConversation?.id;
|
|
119
|
-
}, [
|
|
120
|
-
muteConversation:
|
|
121
|
-
let { data: t } = await
|
|
121
|
+
}, [p]),
|
|
122
|
+
muteConversation: m(async (e) => {
|
|
123
|
+
let { data: t } = await g({ variables: { conversationId: e } });
|
|
122
124
|
return !!t?.muteConversation?.id;
|
|
123
|
-
}, [
|
|
124
|
-
unmuteConversation:
|
|
125
|
-
let { data: t } = await
|
|
125
|
+
}, [g]),
|
|
126
|
+
unmuteConversation: m(async (e) => {
|
|
127
|
+
let { data: t } = await v({ variables: { conversationId: e } });
|
|
126
128
|
return !!t?.unmuteConversation?.id;
|
|
127
|
-
}, [
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
}, [v]),
|
|
130
|
+
leaveConversation: m(async (e) => {
|
|
131
|
+
let { data: t } = await b({
|
|
132
|
+
variables: { conversationId: e },
|
|
133
|
+
refetchQueries: ["GetConversations"],
|
|
134
|
+
awaitRefetchQueries: !0
|
|
135
|
+
});
|
|
136
|
+
return t?.leaveConversation.success ?? !1;
|
|
137
|
+
}, [b]),
|
|
138
|
+
loading: n.loading || i.loading || f.loading || h.loading || _.loading || y.loading || x.loading,
|
|
139
|
+
error: n.error ?? i.error ?? f.error ?? h.error ?? _.error ?? y.error ?? x.error ?? null
|
|
130
140
|
};
|
|
131
141
|
}
|
|
132
|
-
function
|
|
133
|
-
let [e, t] =
|
|
142
|
+
function x() {
|
|
143
|
+
let [e, t] = f();
|
|
134
144
|
return {
|
|
135
|
-
updateConversation:
|
|
145
|
+
updateConversation: m(async (t) => {
|
|
136
146
|
try {
|
|
137
147
|
let { data: n } = await e({ variables: { input: t } }), r = n?.updateConversation?.conversation;
|
|
138
|
-
return r ?
|
|
148
|
+
return r ? p(r) : null;
|
|
139
149
|
} catch (e) {
|
|
140
150
|
throw e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update conversation");
|
|
141
151
|
}
|
|
@@ -145,6 +155,6 @@ function b() {
|
|
|
145
155
|
};
|
|
146
156
|
}
|
|
147
157
|
//#endregion
|
|
148
|
-
export {
|
|
158
|
+
export { b as useConversationActions, y as useCreateConversation, _ as useGetConversation, g as useGetConversations, v as useSearchConversations, x as useUpdateConversation };
|
|
149
159
|
|
|
150
160
|
//# sourceMappingURL=useConversationQueries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConversationQueries.js","names":[],"sources":["../../../src/conversations/hooks/useConversationQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useArchiveConversationMutation,\n useCreateConversationMutation,\n useGetConversationQuery,\n useGetConversationsQuery,\n useMuteConversationMutation,\n usePinConversationMutation,\n useSearchConversationsQuery,\n useUnarchiveConversationMutation,\n useUnmuteConversationMutation,\n useUnpinConversationMutation,\n useUpdateConversationByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type * as WspaceTypes from \"../../generated/wspace-types\";\nimport type {\n Conversation,\n ConversationState,\n ConversationType,\n ConversationVisibility,\n} from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapConversation } from \"../utils/mappers\";\n\ninterface UseGetConversationsOptions {\n first?: number;\n after?: string;\n types?: ConversationType[];\n /**\n * Conversation lifecycle states to include. When omitted the backend\n * returns ACTIVE conversations by default (filtering is union, not\n * exclusion, so `[\"ACTIVE\"]` and `undefined` are interchangeable for the\n * default inbox). Pass `[\"ARCHIVED\"]` to drive the archived tab.\n */\n states?: ConversationState[];\n hasUnread?: boolean;\n isPinned?: boolean;\n}\n\ninterface UseGetConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n fetchMore: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a paginated list of conversations.\n */\nexport function useGetConversations(\n options?: UseGetConversationsOptions,\n): UseGetConversationsResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationsQuery({\n variables: {\n first: options?.first ?? 25,\n after: options?.after,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n skip: !workspaceId,\n });\n\n const conversations = useMemo(\n () =>\n queryResult.data?.conversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const hasNextPage =\n queryResult.data?.conversations.pageInfo.hasNextPage ?? false;\n\n return {\n conversations,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage,\n fetchMore: () => {\n const endCursor = queryResult.data?.conversations.pageInfo.endCursor;\n if (!endCursor || !hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n first: options?.first ?? 25,\n after: endCursor,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseGetConversationResult {\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a single conversation by ID.\n */\nexport function useGetConversation(\n conversationId: string,\n): UseGetConversationResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationQuery({\n variables: { id: conversationId },\n skip: !workspaceId || !conversationId,\n });\n\n return {\n conversation: queryResult.data?.conversation\n ? mapConversation(queryResult.data.conversation)\n : null,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseSearchConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Search conversations by query string.\n */\nexport function useSearchConversations(\n query: string,\n): UseSearchConversationsResult {\n const { workspaceId } = useConversations();\n const trimmedQuery = query.trim();\n const queryResult = useSearchConversationsQuery({\n variables: { query: trimmedQuery, first: 25 },\n skip: !workspaceId || trimmedQuery.length < 2,\n });\n\n return {\n conversations:\n queryResult.data?.searchConversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n };\n}\n\ninterface CreateConversationInput {\n type: ConversationType;\n title?: string;\n description?: string;\n participantIds: string[];\n visibility?: ConversationVisibility;\n}\n\ninterface UseCreateConversationResult {\n createConversation: (\n input: CreateConversationInput,\n ) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Create a new conversation.\n */\nexport function useCreateConversation(): UseCreateConversationResult {\n const { workspaceId } = useConversations();\n const [createConversationMutation, mutationState] =\n useCreateConversationMutation();\n\n const createConversation = useCallback(\n async (input: CreateConversationInput): Promise<Conversation | null> => {\n if (!workspaceId) {\n throw new Error(\n \"Workspace context is required to create a conversation\",\n );\n }\n\n try {\n const { data } = await createConversationMutation({\n variables: {\n input: {\n workspaceId,\n type: input.type as WspaceTypes.ConversationType,\n title: input.title,\n description: input.description,\n participantIds: input.participantIds,\n },\n },\n });\n\n const conversation = data?.createConversation.conversation;\n return conversation ? mapConversation(conversation) : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to create conversation\");\n }\n },\n [createConversationMutation, workspaceId],\n );\n\n return {\n createConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseUpdateConversationResult {\n archiveConversation: (id: string) => Promise<boolean>;\n unarchiveConversation: (id: string) => Promise<boolean>;\n pinConversation: (id: string) => Promise<boolean>;\n unpinConversation: (id: string) => Promise<boolean>;\n muteConversation: (id: string) => Promise<boolean>;\n unmuteConversation: (id: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Conversation mutation operations.\n */\nexport function useConversationActions(): UseUpdateConversationResult {\n const [archiveConversationMutation, archiveState] =\n useArchiveConversationMutation();\n const [unarchiveConversationMutation, unarchiveState] =\n useUnarchiveConversationMutation();\n const [pinConversationMutation, pinState] = usePinConversationMutation();\n const [unpinConversationMutation, unpinState] =\n useUnpinConversationMutation();\n const [muteConversationMutation, muteState] = useMuteConversationMutation();\n const [unmuteConversationMutation, unmuteState] =\n useUnmuteConversationMutation();\n\n const archiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n // refetch GetConversations so the row drops out of the inbox (and the\n // Archived tab gains it) without waiting for a manual refresh.\n const { data } = await archiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.archiveConversation.id === id;\n },\n [archiveConversationMutation],\n );\n\n const unarchiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unarchiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.unarchiveConversation.id === id;\n },\n [unarchiveConversationMutation],\n );\n\n const pinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await pinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.pinConversation?.id);\n },\n [pinConversationMutation],\n );\n\n const unpinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unpinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unpinConversation?.id);\n },\n [unpinConversationMutation],\n );\n\n const muteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await muteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.muteConversation?.id);\n },\n [muteConversationMutation],\n );\n\n const unmuteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unmuteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unmuteConversation?.id);\n },\n [unmuteConversationMutation],\n );\n\n return {\n archiveConversation,\n unarchiveConversation,\n pinConversation,\n unpinConversation,\n muteConversation,\n unmuteConversation,\n loading:\n archiveState.loading ||\n unarchiveState.loading ||\n pinState.loading ||\n unpinState.loading ||\n muteState.loading ||\n unmuteState.loading,\n error:\n (archiveState.error as Error | undefined) ??\n (unarchiveState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n (muteState.error as Error | undefined) ??\n (unmuteState.error as Error | undefined) ??\n null,\n };\n}\n\ninterface UseUpdateConversationOptions {\n updateConversation: (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useUpdateConversation(): UseUpdateConversationOptions {\n const [updateConversationMutation, mutationState] =\n useUpdateConversationByHookMutation();\n\n const updateConversation = useCallback(\n async (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }): Promise<Conversation | null> => {\n try {\n const { data } = await updateConversationMutation({\n variables: { input },\n });\n const typedData = data as\n | {\n updateConversation?: {\n conversation?: Record<string, unknown> | null;\n };\n }\n | undefined;\n const conversation = typedData?.updateConversation?.conversation;\n return conversation\n ? mapConversation(conversation as Record<string, unknown>)\n : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to update conversation\");\n }\n },\n [updateConversationMutation],\n );\n\n return {\n updateConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useConversationQueries.js","names":[],"sources":["../../../src/conversations/hooks/useConversationQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n type GetConversationQuery,\n useArchiveConversationMutation,\n useCreateConversationMutation,\n useGetConversationQuery,\n useGetConversationsQuery,\n useMuteConversationMutation,\n useLeaveConversationMutation,\n usePinConversationMutation,\n useSearchConversationsQuery,\n useUnarchiveConversationMutation,\n useUnmuteConversationMutation,\n useUnpinConversationMutation,\n useUpdateConversationByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type * as WspaceTypes from \"../../generated/wspace-types\";\nimport type {\n Conversation,\n ConversationState,\n ConversationType,\n ConversationVisibility,\n} from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapConversation } from \"../utils/mappers\";\n\ninterface UseGetConversationsOptions {\n first?: number;\n after?: string;\n types?: ConversationType[];\n /**\n * Conversation lifecycle states to include. When omitted the backend\n * returns ACTIVE conversations by default (filtering is union, not\n * exclusion, so `[\"ACTIVE\"]` and `undefined` are interchangeable for the\n * default inbox). Pass `[\"ARCHIVED\"]` to drive the archived tab.\n */\n states?: ConversationState[];\n hasUnread?: boolean;\n isPinned?: boolean;\n}\n\ninterface UseGetConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n fetchMore: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a paginated list of conversations.\n */\nexport function useGetConversations(\n options?: UseGetConversationsOptions,\n): UseGetConversationsResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationsQuery({\n variables: {\n first: options?.first ?? 25,\n after: options?.after,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n skip: !workspaceId,\n });\n\n const conversations = useMemo(\n () =>\n queryResult.data?.conversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const hasNextPage =\n queryResult.data?.conversations.pageInfo.hasNextPage ?? false;\n\n return {\n conversations,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage,\n fetchMore: () => {\n const endCursor = queryResult.data?.conversations.pageInfo.endCursor;\n if (!endCursor || !hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n first: options?.first ?? 25,\n after: endCursor,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseGetConversationResult {\n conversation: Conversation | null;\n members: ConversationMember[];\n membersTotalCount: number;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\nexport type ConversationMember = NonNullable<\n GetConversationQuery[\"conversation\"]\n>[\"members\"][\"edges\"][number][\"node\"];\ntype ConversationMemberEdge = NonNullable<\n GetConversationQuery[\"conversation\"]\n>[\"members\"][\"edges\"][number];\n\n/**\n * Hook: Fetch a single conversation by ID.\n */\nexport function useGetConversation(\n conversationId: string,\n): UseGetConversationResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationQuery({\n variables: { id: conversationId },\n skip: !workspaceId || !conversationId,\n });\n\n return {\n conversation: queryResult.data?.conversation\n ? mapConversation(queryResult.data.conversation)\n : null,\n members:\n queryResult.data?.conversation?.members.edges\n .map((edge: ConversationMemberEdge) => edge.node)\n .filter(\n (member: ConversationMember | null): member is ConversationMember =>\n Boolean(member),\n ) ?? [],\n membersTotalCount: queryResult.data?.conversation?.members.totalCount ?? 0,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseSearchConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Search conversations by query string.\n */\nexport function useSearchConversations(\n query: string,\n): UseSearchConversationsResult {\n const { workspaceId } = useConversations();\n const trimmedQuery = query.trim();\n const queryResult = useSearchConversationsQuery({\n variables: { query: trimmedQuery, first: 25 },\n skip: !workspaceId || trimmedQuery.length < 2,\n });\n\n return {\n conversations:\n queryResult.data?.searchConversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n };\n}\n\ninterface CreateConversationInput {\n type: ConversationType;\n title?: string;\n description?: string;\n participantIds: string[];\n visibility?: ConversationVisibility;\n}\n\ninterface UseCreateConversationResult {\n createConversation: (\n input: CreateConversationInput,\n ) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Create a new conversation.\n */\nexport function useCreateConversation(): UseCreateConversationResult {\n const { workspaceId } = useConversations();\n const [createConversationMutation, mutationState] =\n useCreateConversationMutation();\n\n const createConversation = useCallback(\n async (input: CreateConversationInput): Promise<Conversation | null> => {\n if (!workspaceId) {\n throw new Error(\n \"Workspace context is required to create a conversation\",\n );\n }\n\n try {\n const { data } = await createConversationMutation({\n variables: {\n input: {\n workspaceId,\n type: input.type as WspaceTypes.ConversationType,\n title: input.title,\n description: input.description,\n participantIds: input.participantIds,\n },\n },\n });\n\n const conversation = data?.createConversation.conversation;\n return conversation ? mapConversation(conversation) : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to create conversation\");\n }\n },\n [createConversationMutation, workspaceId],\n );\n\n return {\n createConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseUpdateConversationResult {\n archiveConversation: (id: string) => Promise<boolean>;\n unarchiveConversation: (id: string) => Promise<boolean>;\n pinConversation: (id: string) => Promise<boolean>;\n unpinConversation: (id: string) => Promise<boolean>;\n muteConversation: (id: string) => Promise<boolean>;\n unmuteConversation: (id: string) => Promise<boolean>;\n leaveConversation: (id: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Conversation mutation operations.\n */\nexport function useConversationActions(): UseUpdateConversationResult {\n const [archiveConversationMutation, archiveState] =\n useArchiveConversationMutation();\n const [unarchiveConversationMutation, unarchiveState] =\n useUnarchiveConversationMutation();\n const [pinConversationMutation, pinState] = usePinConversationMutation();\n const [unpinConversationMutation, unpinState] =\n useUnpinConversationMutation();\n const [muteConversationMutation, muteState] = useMuteConversationMutation();\n const [unmuteConversationMutation, unmuteState] =\n useUnmuteConversationMutation();\n const [leaveConversationMutation, leaveState] =\n useLeaveConversationMutation();\n\n const archiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n // refetch GetConversations so the row drops out of the inbox (and the\n // Archived tab gains it) without waiting for a manual refresh.\n const { data } = await archiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.archiveConversation.id === id;\n },\n [archiveConversationMutation],\n );\n\n const unarchiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unarchiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.unarchiveConversation.id === id;\n },\n [unarchiveConversationMutation],\n );\n\n const pinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await pinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.pinConversation?.id);\n },\n [pinConversationMutation],\n );\n\n const unpinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unpinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unpinConversation?.id);\n },\n [unpinConversationMutation],\n );\n\n const muteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await muteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.muteConversation?.id);\n },\n [muteConversationMutation],\n );\n\n const unmuteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unmuteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unmuteConversation?.id);\n },\n [unmuteConversationMutation],\n );\n\n const leaveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await leaveConversationMutation({\n variables: { conversationId: id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.leaveConversation.success ?? false;\n },\n [leaveConversationMutation],\n );\n\n return {\n archiveConversation,\n unarchiveConversation,\n pinConversation,\n unpinConversation,\n muteConversation,\n unmuteConversation,\n leaveConversation,\n loading:\n archiveState.loading ||\n unarchiveState.loading ||\n pinState.loading ||\n unpinState.loading ||\n muteState.loading ||\n unmuteState.loading ||\n leaveState.loading,\n error:\n (archiveState.error as Error | undefined) ??\n (unarchiveState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n (muteState.error as Error | undefined) ??\n (unmuteState.error as Error | undefined) ??\n (leaveState.error as Error | undefined) ??\n null,\n };\n}\n\ninterface UseUpdateConversationOptions {\n updateConversation: (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useUpdateConversation(): UseUpdateConversationOptions {\n const [updateConversationMutation, mutationState] =\n useUpdateConversationByHookMutation();\n\n const updateConversation = useCallback(\n async (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }): Promise<Conversation | null> => {\n try {\n const { data } = await updateConversationMutation({\n variables: { input },\n });\n const typedData = data as\n | {\n updateConversation?: {\n conversation?: Record<string, unknown> | null;\n };\n }\n | undefined;\n const conversation = typedData?.updateConversation?.conversation;\n return conversation\n ? mapConversation(conversation as Record<string, unknown>)\n : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to update conversation\");\n }\n },\n [updateConversationMutation],\n );\n\n return {\n updateConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n"],"mappings":";;;;;AAqDA,SAAgB,EACd,GAC2B;CAC3B,IAAM,EAAE,mBAAgB,GAAkB,EACpC,IAAc,EAAyB;EAC3C,WAAW;GACT,OAAO,GAAS,SAAS;GACzB,OAAO,GAAS;GAChB,QAAQ;IACN,OAAO,GAAS;IAGhB,QAAQ,GAAS;IAGjB,WAAW,GAAS;IACpB,UAAU,GAAS;IACpB;GACF;EACD,MAAM,CAAC;EACR,CAAC,EAEI,IAAgB,QAElB,EAAY,MAAM,cAAc,MAAM,KACnC,MAA4C,EAAgB,EAAK,KAAK,CACxE,IAAI,EAAE,EACT,CAAC,EAAY,KAAK,CACnB,EAEK,IACJ,EAAY,MAAM,cAAc,SAAS,eAAe;AAE1D,QAAO;EACL;EACA,SAAS,EAAY;EACrB,OAAO,EAAY,SAAS;EAC5B;EACA,iBAAiB;GACf,IAAM,IAAY,EAAY,MAAM,cAAc,SAAS;AACvD,IAAC,KAAa,CAAC,KACd,EAAY,UAAU,EACzB,WAAW;IACT,OAAO,GAAS,SAAS;IACzB,OAAO;IACP,QAAQ;KACN,OAAO,GAAS;KAGhB,QAAQ,GAAS;KAGjB,WAAW,GAAS;KACpB,UAAU,GAAS;KACpB;IACF,EACF,CAAC;;EAEJ,eAAe;AACR,KAAY,SAAS;;EAE7B;;AAsBH,SAAgB,EACd,GAC0B;CAC1B,IAAM,EAAE,mBAAgB,GAAkB,EACpC,IAAc,EAAwB;EAC1C,WAAW,EAAE,IAAI,GAAgB;EACjC,MAAM,CAAC,KAAe,CAAC;EACxB,CAAC;AAEF,QAAO;EACL,cAAc,EAAY,MAAM,eAC5B,EAAgB,EAAY,KAAK,aAAa,GAC9C;EACJ,SACE,EAAY,MAAM,cAAc,QAAQ,MACrC,KAAK,MAAiC,EAAK,KAAK,CAChD,QACE,MACC,EAAQ,EACX,IAAI,EAAE;EACX,mBAAmB,EAAY,MAAM,cAAc,QAAQ,cAAc;EACzE,SAAS,EAAY;EACrB,OAAO,EAAY,SAAS;EAC5B,eAAe;AACR,KAAY,SAAS;;EAE7B;;AAYH,SAAgB,EACd,GAC8B;CAC9B,IAAM,EAAE,mBAAgB,GAAkB,EACpC,IAAe,EAAM,MAAM,EAC3B,IAAc,EAA4B;EAC9C,WAAW;GAAE,OAAO;GAAc,OAAO;GAAI;EAC7C,MAAM,CAAC,KAAe,EAAa,SAAS;EAC7C,CAAC;AAEF,QAAO;EACL,eACE,EAAY,MAAM,oBAAoB,MAAM,KACzC,MAA4C,EAAgB,EAAK,KAAK,CACxE,IAAI,EAAE;EACT,SAAS,EAAY;EACrB,OAAO,EAAY,SAAS;EAC7B;;AAsBH,SAAgB,IAAqD;CACnE,IAAM,EAAE,mBAAgB,GAAkB,EACpC,CAAC,GAA4B,KACjC,GAA+B;AAkCjC,QAAO;EACL,oBAjCyB,EACzB,OAAO,MAAiE;AACtE,OAAI,CAAC,EACH,OAAU,MACR,yDACD;AAGH,OAAI;IACF,IAAM,EAAE,YAAS,MAAM,EAA2B,EAChD,WAAW,EACT,OAAO;KACL;KACA,MAAM,EAAM;KACZ,OAAO,EAAM;KACb,aAAa,EAAM;KACnB,gBAAgB,EAAM;KACvB,EACF,EACF,CAAC,EAEI,IAAe,GAAM,mBAAmB;AAC9C,WAAO,IAAe,EAAgB,EAAa,GAAG;YAC/C,GAAK;AACZ,UAAM,aAAe,QACjB,IACA,gBAAI,MAAM,gCAAgC;;KAGlD,CAAC,GAA4B,EAAY,CAC1C;EAIC,SAAS,EAAc;EACvB,OAAO,EAAc,SAAS;EAC/B;;AAkBH,SAAgB,IAAsD;CACpE,IAAM,CAAC,GAA6B,KAClC,GAAgC,EAC5B,CAAC,GAA+B,KACpC,GAAkC,EAC9B,CAAC,GAAyB,KAAY,GAA4B,EAClE,CAAC,GAA2B,KAChC,GAA8B,EAC1B,CAAC,GAA0B,KAAa,GAA6B,EACrE,CAAC,GAA4B,KACjC,GAA+B,EAC3B,CAAC,GAA2B,KAChC,GAA8B;AAgFhC,QAAO;EACL,qBA/E0B,EAC1B,OAAO,MAAiC;GAGtC,IAAM,EAAE,YAAS,MAAM,EAA4B;IACjD,WAAW,EAAE,OAAI;IACjB,gBAAgB,CAAC,mBAAmB;IACpC,qBAAqB;IACtB,CAAC;AACF,UAAO,GAAM,oBAAoB,OAAO;KAE1C,CAAC,EAA4B,CAC9B;EAoEC,uBAlE4B,EAC5B,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAA8B;IACnD,WAAW,EAAE,OAAI;IACjB,gBAAgB,CAAC,mBAAmB;IACpC,qBAAqB;IACtB,CAAC;AACF,UAAO,GAAM,sBAAsB,OAAO;KAE5C,CAAC,EAA8B,CAChC;EAyDC,iBAvDsB,EACtB,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAAwB,EAC7C,WAAW,EAAE,gBAAgB,GAAI,EAClC,CAAC;AACF,UAAO,EAAQ,GAAM,iBAAiB;KAExC,CAAC,EAAwB,CAC1B;EAgDC,mBA9CwB,EACxB,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAA0B,EAC/C,WAAW,EAAE,gBAAgB,GAAI,EAClC,CAAC;AACF,UAAO,EAAQ,GAAM,mBAAmB;KAE1C,CAAC,EAA0B,CAC5B;EAuCC,kBArCuB,EACvB,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAAyB,EAC9C,WAAW,EAAE,gBAAgB,GAAI,EAClC,CAAC;AACF,UAAO,EAAQ,GAAM,kBAAkB;KAEzC,CAAC,EAAyB,CAC3B;EA8BC,oBA5ByB,EACzB,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAA2B,EAChD,WAAW,EAAE,gBAAgB,GAAI,EAClC,CAAC;AACF,UAAO,EAAQ,GAAM,oBAAoB;KAE3C,CAAC,EAA2B,CAC7B;EAqBC,mBAnBwB,EACxB,OAAO,MAAiC;GACtC,IAAM,EAAE,YAAS,MAAM,EAA0B;IAC/C,WAAW,EAAE,gBAAgB,GAAI;IACjC,gBAAgB,CAAC,mBAAmB;IACpC,qBAAqB;IACtB,CAAC;AACF,UAAO,GAAM,kBAAkB,WAAW;KAE5C,CAAC,EAA0B,CAC5B;EAUC,SACE,EAAa,WACb,EAAe,WACf,EAAS,WACT,EAAW,WACX,EAAU,WACV,EAAY,WACZ,EAAW;EACb,OACG,EAAa,SACb,EAAe,SACf,EAAS,SACT,EAAW,SACX,EAAU,SACV,EAAY,SACZ,EAAW,SACZ;EACH;;AAeH,SAAgB,IAAsD;CACpE,IAAM,CAAC,GAA4B,KACjC,GAAqC;AAkCvC,QAAO;EACL,oBAjCyB,EACzB,OAAO,MAM6B;AAClC,OAAI;IACF,IAAM,EAAE,YAAS,MAAM,EAA2B,EAChD,WAAW,EAAE,UAAO,EACrB,CAAC,EAQI,IAPY,GAOc,oBAAoB;AACpD,WAAO,IACH,EAAgB,EAAwC,GACxD;YACG,GAAK;AACZ,UAAM,aAAe,QACjB,IACA,gBAAI,MAAM,gCAAgC;;KAGlD,CAAC,EAA2B,CAC7B;EAIC,SAAS,EAAc;EACvB,OAAO,EAAc,SAAS;EAC/B"}
|
|
@@ -11,7 +11,8 @@ function p(t, n) {
|
|
|
11
11
|
after: n?.after,
|
|
12
12
|
before: n?.before
|
|
13
13
|
},
|
|
14
|
-
skip: !r || !t
|
|
14
|
+
skip: !r || !t,
|
|
15
|
+
pollInterval: n?.pollInterval
|
|
15
16
|
}), o = f(() => i.data?.messages.edges.map((e) => u(e.node)) ?? [], [i.data]), s = i.data?.messages.pageInfo;
|
|
16
17
|
return {
|
|
17
18
|
messages: o,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageQueries.js","names":[],"sources":["../../../src/conversations/hooks/useMessageQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useAddReactionMutation,\n useDeleteMessageMutation,\n useEditMessageMutation,\n GetMessagesDocument,\n useGetMessagesQuery,\n usePinMessageByHookMutation,\n useRemoveReactionMutation,\n useSendMessageMutation,\n useUnpinMessageByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type { Message, MessageType } from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapMessage } from \"../utils/mappers\";\n\ninterface UseGetMessagesOptions {\n first?: number;\n after?: string;\n before?: string;\n}\n\ninterface UseGetMessagesResult {\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchMore: () => void;\n fetchPrevious: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch paginated messages for a conversation.\n */\nexport function useGetMessages(\n conversationId: string,\n options?: UseGetMessagesOptions,\n): UseGetMessagesResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetMessagesQuery({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: options?.after,\n before: options?.before,\n },\n skip: !workspaceId || !conversationId,\n });\n\n const messages = useMemo(\n () =>\n queryResult.data?.messages.edges.map(\n (edge: { node: Record<string, unknown> }) => mapMessage(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const pageInfo = queryResult.data?.messages.pageInfo;\n\n return {\n messages,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage: pageInfo?.hasNextPage ?? false,\n hasPreviousPage: pageInfo?.hasPreviousPage ?? false,\n fetchMore: () => {\n const endCursor = pageInfo?.endCursor;\n if (!endCursor || !pageInfo?.hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: endCursor,\n },\n });\n },\n fetchPrevious: () => {\n const startCursor = pageInfo?.startCursor;\n if (!startCursor || !pageInfo?.hasPreviousPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n before: startCursor,\n first: options?.first ?? 50,\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface SendMessageInput {\n conversationId: string;\n content: string;\n type?: MessageType;\n parentMessageId?: string;\n attachmentIds?: string[];\n mentionUserIds?: string[];\n refetchFirst?: number;\n}\n\ninterface UseSendMessageResult {\n sendMessage: (input: SendMessageInput) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Send a message to a conversation.\n */\nexport function useSendMessage(): UseSendMessageResult {\n const [sendMessageMutation, mutationState] = useSendMessageMutation();\n\n const sendMessage = useCallback(\n async (input: SendMessageInput): Promise<Message | null> => {\n try {\n const { data } = await sendMessageMutation({\n variables: {\n input: {\n conversationId: input.conversationId,\n type: input.type ?? \"TEXT\",\n content: { text: input.content },\n parentMessageId: input.parentMessageId,\n attachmentIds: input.attachmentIds,\n mentionUserIds: input.mentionUserIds,\n },\n },\n refetchQueries: [\n {\n query: GetMessagesDocument,\n variables: {\n conversationId: input.conversationId,\n first: input.refetchFirst ?? 50,\n },\n },\n ],\n });\n\n const message = data?.sendMessage.message;\n return message ? mapMessage(message) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to send message\");\n }\n },\n [sendMessageMutation],\n );\n\n return {\n sendMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseEditMessageResult {\n editMessage: (\n messageId: string,\n content: string,\n reason?: string,\n ) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Edit an existing message.\n */\nexport function useEditMessage(): UseEditMessageResult {\n const [editMessageMutation, mutationState] = useEditMessageMutation();\n\n const editMessage = useCallback(\n async (\n messageId: string,\n content: string,\n reason?: string,\n ): Promise<Message | null> => {\n try {\n const { data } = await editMessageMutation({\n variables: {\n input: {\n id: messageId,\n content: { text: content },\n reason,\n },\n },\n });\n const message = data?.editMessage;\n return message ? mapMessage(message as Record<string, unknown>) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to edit message\");\n }\n },\n [editMessageMutation],\n );\n\n return {\n editMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseMessageActionsResult {\n deleteMessage: (messageId: string) => Promise<boolean>;\n addReaction: (messageId: string, emoji: string) => Promise<boolean>;\n removeReaction: (messageId: string, emoji: string) => Promise<boolean>;\n pinMessage: (messageId: string) => Promise<boolean>;\n unpinMessage: (messageId: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Message action mutations (delete, react, pin).\n */\nexport function useMessageActions(): UseMessageActionsResult {\n const [deleteMessageMutation, deleteState] = useDeleteMessageMutation();\n const [addReactionMutation, addReactionState] = useAddReactionMutation();\n const [removeReactionMutation, removeReactionState] =\n useRemoveReactionMutation();\n const [pinMessageMutation, pinState] = usePinMessageByHookMutation();\n const [unpinMessageMutation, unpinState] = useUnpinMessageByHookMutation();\n\n const deleteMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await deleteMessageMutation({\n variables: { id: messageId },\n });\n return data?.deleteMessage.success ?? false;\n },\n [deleteMessageMutation],\n );\n\n const addReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await addReactionMutation({\n variables: { messageId, emoji },\n });\n return Boolean(data?.addReaction.id);\n },\n [addReactionMutation],\n );\n\n const removeReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await removeReactionMutation({\n variables: { messageId, emoji },\n });\n return data?.removeReaction.success ?? false;\n },\n [removeReactionMutation],\n );\n\n const pinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await pinMessageMutation({ variables: { messageId } });\n return Boolean(data?.pinMessage?.id);\n },\n [pinMessageMutation],\n );\n\n const unpinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await unpinMessageMutation({ variables: { messageId } });\n return Boolean(data?.unpinMessage?.id);\n },\n [unpinMessageMutation],\n );\n\n return {\n deleteMessage,\n addReaction,\n removeReaction,\n pinMessage,\n unpinMessage,\n loading:\n deleteState.loading ||\n addReactionState.loading ||\n removeReactionState.loading ||\n pinState.loading ||\n unpinState.loading,\n error:\n (deleteState.error as Error | undefined) ??\n (addReactionState.error as Error | undefined) ??\n (removeReactionState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n null,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useMessageQueries.js","names":[],"sources":["../../../src/conversations/hooks/useMessageQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useAddReactionMutation,\n useDeleteMessageMutation,\n useEditMessageMutation,\n GetMessagesDocument,\n useGetMessagesQuery,\n usePinMessageByHookMutation,\n useRemoveReactionMutation,\n useSendMessageMutation,\n useUnpinMessageByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type { Message, MessageType } from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapMessage } from \"../utils/mappers\";\n\ninterface UseGetMessagesOptions {\n first?: number;\n after?: string;\n before?: string;\n pollInterval?: number;\n}\n\ninterface UseGetMessagesResult {\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchMore: () => void;\n fetchPrevious: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch paginated messages for a conversation.\n */\nexport function useGetMessages(\n conversationId: string,\n options?: UseGetMessagesOptions,\n): UseGetMessagesResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetMessagesQuery({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: options?.after,\n before: options?.before,\n },\n skip: !workspaceId || !conversationId,\n pollInterval: options?.pollInterval,\n });\n\n const messages = useMemo(\n () =>\n queryResult.data?.messages.edges.map(\n (edge: { node: Record<string, unknown> }) => mapMessage(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const pageInfo = queryResult.data?.messages.pageInfo;\n\n return {\n messages,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage: pageInfo?.hasNextPage ?? false,\n hasPreviousPage: pageInfo?.hasPreviousPage ?? false,\n fetchMore: () => {\n const endCursor = pageInfo?.endCursor;\n if (!endCursor || !pageInfo?.hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: endCursor,\n },\n });\n },\n fetchPrevious: () => {\n const startCursor = pageInfo?.startCursor;\n if (!startCursor || !pageInfo?.hasPreviousPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n before: startCursor,\n first: options?.first ?? 50,\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface SendMessageInput {\n conversationId: string;\n content: string;\n type?: MessageType;\n parentMessageId?: string;\n attachmentIds?: string[];\n mentionUserIds?: string[];\n refetchFirst?: number;\n}\n\ninterface UseSendMessageResult {\n sendMessage: (input: SendMessageInput) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Send a message to a conversation.\n */\nexport function useSendMessage(): UseSendMessageResult {\n const [sendMessageMutation, mutationState] = useSendMessageMutation();\n\n const sendMessage = useCallback(\n async (input: SendMessageInput): Promise<Message | null> => {\n try {\n const { data } = await sendMessageMutation({\n variables: {\n input: {\n conversationId: input.conversationId,\n type: input.type ?? \"TEXT\",\n content: { text: input.content },\n parentMessageId: input.parentMessageId,\n attachmentIds: input.attachmentIds,\n mentionUserIds: input.mentionUserIds,\n },\n },\n refetchQueries: [\n {\n query: GetMessagesDocument,\n variables: {\n conversationId: input.conversationId,\n first: input.refetchFirst ?? 50,\n },\n },\n ],\n });\n\n const message = data?.sendMessage.message;\n return message ? mapMessage(message) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to send message\");\n }\n },\n [sendMessageMutation],\n );\n\n return {\n sendMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseEditMessageResult {\n editMessage: (\n messageId: string,\n content: string,\n reason?: string,\n ) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Edit an existing message.\n */\nexport function useEditMessage(): UseEditMessageResult {\n const [editMessageMutation, mutationState] = useEditMessageMutation();\n\n const editMessage = useCallback(\n async (\n messageId: string,\n content: string,\n reason?: string,\n ): Promise<Message | null> => {\n try {\n const { data } = await editMessageMutation({\n variables: {\n input: {\n id: messageId,\n content: { text: content },\n reason,\n },\n },\n });\n const message = data?.editMessage;\n return message ? mapMessage(message as Record<string, unknown>) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to edit message\");\n }\n },\n [editMessageMutation],\n );\n\n return {\n editMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseMessageActionsResult {\n deleteMessage: (messageId: string) => Promise<boolean>;\n addReaction: (messageId: string, emoji: string) => Promise<boolean>;\n removeReaction: (messageId: string, emoji: string) => Promise<boolean>;\n pinMessage: (messageId: string) => Promise<boolean>;\n unpinMessage: (messageId: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Message action mutations (delete, react, pin).\n */\nexport function useMessageActions(): UseMessageActionsResult {\n const [deleteMessageMutation, deleteState] = useDeleteMessageMutation();\n const [addReactionMutation, addReactionState] = useAddReactionMutation();\n const [removeReactionMutation, removeReactionState] =\n useRemoveReactionMutation();\n const [pinMessageMutation, pinState] = usePinMessageByHookMutation();\n const [unpinMessageMutation, unpinState] = useUnpinMessageByHookMutation();\n\n const deleteMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await deleteMessageMutation({\n variables: { id: messageId },\n });\n return data?.deleteMessage.success ?? false;\n },\n [deleteMessageMutation],\n );\n\n const addReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await addReactionMutation({\n variables: { messageId, emoji },\n });\n return Boolean(data?.addReaction.id);\n },\n [addReactionMutation],\n );\n\n const removeReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await removeReactionMutation({\n variables: { messageId, emoji },\n });\n return data?.removeReaction.success ?? false;\n },\n [removeReactionMutation],\n );\n\n const pinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await pinMessageMutation({ variables: { messageId } });\n return Boolean(data?.pinMessage?.id);\n },\n [pinMessageMutation],\n );\n\n const unpinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await unpinMessageMutation({ variables: { messageId } });\n return Boolean(data?.unpinMessage?.id);\n },\n [unpinMessageMutation],\n );\n\n return {\n deleteMessage,\n addReaction,\n removeReaction,\n pinMessage,\n unpinMessage,\n loading:\n deleteState.loading ||\n addReactionState.loading ||\n removeReactionState.loading ||\n pinState.loading ||\n unpinState.loading,\n error:\n (deleteState.error as Error | undefined) ??\n (addReactionState.error as Error | undefined) ??\n (removeReactionState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n null,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ConversationAddedDocument as e, ConversationDeletedDocument as t, ConversationUpdatedDocument as n, GetMessagesDocument as r, MessageAddedDocument as i, MessageDeletedDocument as a, MessageUpdatedDocument as o, ParticipantChangedDocument as s } from "../../generated/wspace-operations.js";
|
|
2
|
-
import {
|
|
3
|
-
import { useApolloClient as l, useSubscription as u } from "@apollo/client/react";
|
|
2
|
+
import { useApolloClient as c, useSubscription as l } from "@apollo/client/react";
|
|
4
3
|
//#region src/conversations/hooks/useMessageSubscriptions.ts
|
|
5
|
-
function
|
|
4
|
+
function u(e, t, n, i) {
|
|
6
5
|
e.updateQuery({
|
|
7
6
|
query: r,
|
|
8
7
|
variables: {
|
|
9
8
|
conversationId: t,
|
|
10
|
-
first:
|
|
9
|
+
first: i
|
|
11
10
|
}
|
|
12
11
|
}, (e) => {
|
|
13
12
|
if (!e) return e;
|
|
@@ -26,44 +25,44 @@ function d(e, t, n) {
|
|
|
26
25
|
};
|
|
27
26
|
});
|
|
28
27
|
}
|
|
29
|
-
function
|
|
28
|
+
function d(e, t) {
|
|
30
29
|
e.evict({ id: e.identify({
|
|
31
30
|
__typename: "Message",
|
|
32
31
|
id: t
|
|
33
32
|
}) }), e.gc();
|
|
34
33
|
}
|
|
35
|
-
function
|
|
36
|
-
let
|
|
37
|
-
|
|
34
|
+
function f(e, t = 50) {
|
|
35
|
+
let n = c();
|
|
36
|
+
l(i, {
|
|
38
37
|
variables: { conversationId: e ?? "" },
|
|
39
38
|
skip: !e,
|
|
40
|
-
onData: ({ data:
|
|
41
|
-
let
|
|
42
|
-
!
|
|
39
|
+
onData: ({ data: r }) => {
|
|
40
|
+
let i = r.data?.messageAdded;
|
|
41
|
+
!i || !e || u(n.cache, e, i, t);
|
|
43
42
|
},
|
|
44
43
|
onError: (e) => console.warn("[useMessageStream] messageAdded error:", e)
|
|
45
|
-
}),
|
|
44
|
+
}), l(o, {
|
|
46
45
|
variables: { conversationId: e ?? "" },
|
|
47
46
|
skip: !e,
|
|
48
47
|
onError: (e) => console.warn("[useMessageStream] messageUpdated error:", e)
|
|
49
|
-
}),
|
|
48
|
+
}), l(a, {
|
|
50
49
|
variables: { conversationId: e ?? "" },
|
|
51
50
|
skip: !e,
|
|
52
51
|
onData: ({ data: e }) => {
|
|
53
|
-
let
|
|
54
|
-
|
|
52
|
+
let t = e.data?.messageDeleted?.messageId;
|
|
53
|
+
t && d(n.cache, t);
|
|
55
54
|
},
|
|
56
55
|
onError: (e) => console.warn("[useMessageStream] messageDeleted error:", e)
|
|
57
|
-
})
|
|
56
|
+
});
|
|
58
57
|
}
|
|
59
|
-
function
|
|
60
|
-
let i =
|
|
61
|
-
|
|
58
|
+
function p(r) {
|
|
59
|
+
let i = c();
|
|
60
|
+
l(e, {
|
|
62
61
|
onData: ({ data: e }) => {
|
|
63
62
|
e.data?.conversationAdded && (i.cache.evict({ fieldName: "conversations" }), i.cache.gc());
|
|
64
63
|
},
|
|
65
64
|
onError: (e) => console.warn("[useConversationStream] conversationAdded error:", e)
|
|
66
|
-
}),
|
|
65
|
+
}), l(t, {
|
|
67
66
|
variables: { conversationId: r ?? "" },
|
|
68
67
|
skip: !r,
|
|
69
68
|
onData: ({ data: e }) => {
|
|
@@ -74,17 +73,17 @@ function m(r) {
|
|
|
74
73
|
}) }), i.cache.gc());
|
|
75
74
|
},
|
|
76
75
|
onError: (e) => console.warn("[useConversationStream] conversationDeleted error:", e)
|
|
77
|
-
}),
|
|
76
|
+
}), l(n, {
|
|
78
77
|
variables: { conversationId: r ?? "" },
|
|
79
78
|
skip: !r,
|
|
80
79
|
onError: (e) => console.warn("[useConversationStream] conversationUpdated error:", e)
|
|
81
|
-
}),
|
|
80
|
+
}), l(s, {
|
|
82
81
|
variables: { conversationId: r ?? "" },
|
|
83
82
|
skip: !r,
|
|
84
83
|
onError: (e) => console.warn("[useConversationStream] participantChanged error:", e)
|
|
85
84
|
});
|
|
86
85
|
}
|
|
87
86
|
//#endregion
|
|
88
|
-
export {
|
|
87
|
+
export { p as useConversationStream, f as useMessageStreamForConversation };
|
|
89
88
|
|
|
90
89
|
//# sourceMappingURL=useMessageSubscriptions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageSubscriptions.js","names":[],"sources":["../../../src/conversations/hooks/useMessageSubscriptions.ts"],"sourcesContent":["/**\n * Real-time message subscription hooks.\n *\n * Wires the GraphQL subscriptions defined in\n * `src/operations/wspace/conversations/subscriptions/messageSubscriptions.graphql`\n * into Apollo cache updates so pages do not have to poll.\n *\n * Usage in a page:\n * useMessageStreamForConversation(conversationId);\n *\n * The hook ignores subscription errors (logs only) — the page UI continues to\n * work with whatever is already in the cache; the next refresh / refetch\n * recovers any missed events.\n *\n * NOTE: This
|
|
1
|
+
{"version":3,"file":"useMessageSubscriptions.js","names":[],"sources":["../../../src/conversations/hooks/useMessageSubscriptions.ts"],"sourcesContent":["/**\n * Real-time message subscription hooks.\n *\n * Wires the GraphQL subscriptions defined in\n * `src/operations/wspace/conversations/subscriptions/messageSubscriptions.graphql`\n * into Apollo cache updates so pages do not have to poll.\n *\n * Usage in a page:\n * useMessageStreamForConversation(conversationId);\n *\n * The hook ignores subscription errors (logs only) — the page UI continues to\n * work with whatever is already in the cache; the next refresh / refetch\n * recovers any missed events.\n *\n * NOTE: This is the primary real-time path. Pages may keep a light,\n * low-frequency polling fallback when a host transport can keep the stream open\n * but miss events.\n */\nimport { type ApolloCache, type FetchResult } from \"@apollo/client\";\nimport { useApolloClient } from \"@apollo/client/react\";\nimport { useSubscription } from \"@apollo/client/react\";\n\nimport {\n MessageAddedDocument,\n MessageUpdatedDocument,\n MessageDeletedDocument,\n type MessageAddedSubscription,\n type MessageUpdatedSubscription,\n type MessageDeletedSubscription,\n GetMessagesDocument,\n type GetMessagesQuery,\n type GetMessagesQueryVariables,\n} from \"../../generated/wspace-operations\";\n\ninterface MessageEdge {\n __typename?: \"MessageEdge\";\n cursor?: string | null;\n node?: { id: string; [key: string]: unknown } | null;\n}\n\ninterface MessagesConnection {\n __typename?: \"MessageConnection\";\n edges?: MessageEdge[] | null;\n pageInfo?: unknown;\n totalCount?: number | null;\n}\n\n/**\n * Append a new message to the cached `messages(conversationId: …)` connection\n * if it isn't already present.\n */\nfunction appendToCache(\n cache: ApolloCache,\n conversationId: string,\n newMessage: { id: string; [key: string]: unknown },\n first: number,\n): void {\n cache.updateQuery<GetMessagesQuery, GetMessagesQueryVariables>(\n {\n query: GetMessagesDocument,\n variables: { conversationId, first },\n },\n (existing: GetMessagesQuery | null) => {\n if (!existing) return existing;\n const conn = existing.messages as MessagesConnection | null | undefined;\n const edges = conn?.edges ?? [];\n if (edges.some((e) => e?.node?.id === newMessage.id)) return existing;\n\n return {\n ...existing,\n messages: {\n ...(conn ?? {}),\n edges: [\n ...edges,\n {\n __typename: \"MessageEdge\",\n cursor: newMessage.id,\n node: newMessage,\n },\n ],\n totalCount: (conn?.totalCount ?? edges.length) + 1,\n },\n } as GetMessagesQuery;\n },\n );\n}\n\n/**\n * Evict a deleted message from the cache.\n */\nfunction evictFromCache(cache: ApolloCache, messageId: string): void {\n cache.evict({ id: cache.identify({ __typename: \"Message\", id: messageId }) });\n cache.gc();\n}\n\nexport function useMessageStreamForConversation(\n conversationId: string | undefined,\n first = 50,\n): void {\n const client = useApolloClient();\n\n // Inbound new messages\n useSubscription<MessageAddedSubscription>(MessageAddedDocument, {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onData: ({ data }: { data: FetchResult<MessageAddedSubscription> }) => {\n const msg = data.data?.messageAdded;\n if (!msg || !conversationId) return;\n appendToCache(client.cache, conversationId, msg as { id: string }, first);\n },\n onError: (err) =>\n console.warn(\"[useMessageStream] messageAdded error:\", err),\n });\n\n // Edits\n useSubscription<MessageUpdatedSubscription>(MessageUpdatedDocument, {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onError: (err) =>\n console.warn(\"[useMessageStream] messageUpdated error:\", err),\n // Apollo merges by `id` automatically (cache normalisation) — no manual write needed.\n });\n\n // Deletes\n useSubscription<MessageDeletedSubscription>(MessageDeletedDocument, {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onData: ({ data }: { data: FetchResult<MessageDeletedSubscription> }) => {\n const messageId = data.data?.messageDeleted?.messageId;\n if (!messageId) return;\n evictFromCache(client.cache, messageId);\n },\n onError: (err) =>\n console.warn(\"[useMessageStream] messageDeleted error:\", err),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Conversation-level streams (used by the list and landing pages).\n// These imports resolve once codegen surfaces them from the new\n// subscriptions/conversationSubscriptions.graphql file.\n// ---------------------------------------------------------------------------\n\nimport {\n ConversationAddedDocument,\n ConversationUpdatedDocument,\n ConversationDeletedDocument,\n ParticipantChangedDocument,\n type ConversationAddedSubscription,\n type ConversationUpdatedSubscription,\n type ConversationDeletedSubscription,\n type ParticipantChangedSubscription,\n} from \"../../generated/wspace-operations\";\n\n/**\n * Subscribe to all conversation-level lifecycle events for the current actor.\n *\n * - `conversationAdded` — refresh the conversation list when one is created.\n * - `conversationDeleted` — evict from cache when one is removed.\n * - `conversationUpdated` — Apollo normalisation handles automatically; no\n * manual write required.\n * - `participantChanged` — refresh members panel.\n *\n * Use at the top of the list page / landing page once. Safe to call multiple\n * times across components — Apollo deduplicates.\n */\nexport function useConversationStream(\n conversationId?: string | undefined,\n): void {\n const client = useApolloClient();\n\n useSubscription<ConversationAddedSubscription>(ConversationAddedDocument, {\n onData: ({\n data,\n }: {\n data: FetchResult<ConversationAddedSubscription>;\n }) => {\n const conv = data.data?.conversationAdded;\n if (!conv) return;\n // Invalidate the list so the next render picks up the new conversation.\n // Cheaper than maintaining a manual append into every list variant.\n client.cache.evict({ fieldName: \"conversations\" });\n client.cache.gc();\n },\n onError: (err) =>\n console.warn(\"[useConversationStream] conversationAdded error:\", err),\n });\n\n useSubscription<ConversationDeletedSubscription>(\n ConversationDeletedDocument,\n {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onData: ({\n data,\n }: {\n data: FetchResult<ConversationDeletedSubscription>;\n }) => {\n const id = data.data?.conversationDeleted?.conversationId;\n if (!id) return;\n client.cache.evict({\n id: client.cache.identify({ __typename: \"Conversation\", id }),\n });\n client.cache.gc();\n },\n onError: (err) =>\n console.warn(\"[useConversationStream] conversationDeleted error:\", err),\n },\n );\n\n useSubscription<ConversationUpdatedSubscription>(\n ConversationUpdatedDocument,\n {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onError: (err) =>\n console.warn(\"[useConversationStream] conversationUpdated error:\", err),\n },\n );\n\n useSubscription<ParticipantChangedSubscription>(ParticipantChangedDocument, {\n variables: { conversationId: conversationId ?? \"\" },\n skip: !conversationId,\n onError: (err) =>\n console.warn(\"[useConversationStream] participantChanged error:\", err),\n });\n}\n"],"mappings":";;;AAmDA,SAAS,EACP,GACA,GACA,GACA,GACM;AACN,GAAM,YACJ;EACE,OAAO;EACP,WAAW;GAAE;GAAgB;GAAO;EACrC,GACA,MAAsC;AACrC,MAAI,CAAC,EAAU,QAAO;EACtB,IAAM,IAAO,EAAS,UAChB,IAAQ,GAAM,SAAS,EAAE;AAG/B,SAFI,EAAM,MAAM,MAAM,GAAG,MAAM,OAAO,EAAW,GAAG,GAAS,IAEtD;GACL,GAAG;GACH,UAAU;IACR,GAAI,KAAQ,EAAE;IACd,OAAO,CACL,GAAG,GACH;KACE,YAAY;KACZ,QAAQ,EAAW;KACnB,MAAM;KACP,CACF;IACD,aAAa,GAAM,cAAc,EAAM,UAAU;IAClD;GACF;GAEJ;;AAMH,SAAS,EAAe,GAAoB,GAAyB;AAEnE,CADA,EAAM,MAAM,EAAE,IAAI,EAAM,SAAS;EAAE,YAAY;EAAW,IAAI;EAAW,CAAC,EAAE,CAAC,EAC7E,EAAM,IAAI;;AAGZ,SAAgB,EACd,GACA,IAAQ,IACF;CACN,IAAM,IAAS,GAAiB;AAyBhC,CAtBA,EAA0C,GAAsB;EAC9D,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,SAAS,EAAE,cAA4D;GACrE,IAAM,IAAM,EAAK,MAAM;AACnB,IAAC,KAAO,CAAC,KACb,EAAc,EAAO,OAAO,GAAgB,GAAuB,EAAM;;EAE3E,UAAU,MACR,QAAQ,KAAK,0CAA0C,EAAI;EAC9D,CAAC,EAGF,EAA4C,GAAwB;EAClE,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,UAAU,MACR,QAAQ,KAAK,4CAA4C,EAAI;EAEhE,CAAC,EAGF,EAA4C,GAAwB;EAClE,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,SAAS,EAAE,cAA8D;GACvE,IAAM,IAAY,EAAK,MAAM,gBAAgB;AACxC,QACL,EAAe,EAAO,OAAO,EAAU;;EAEzC,UAAU,MACR,QAAQ,KAAK,4CAA4C,EAAI;EAChE,CAAC;;AAgCJ,SAAgB,EACd,GACM;CACN,IAAM,IAAS,GAAiB;AAmDhC,CAjDA,EAA+C,GAA2B;EACxE,SAAS,EACP,cAGI;AACS,KAAK,MAAM,sBAIxB,EAAO,MAAM,MAAM,EAAE,WAAW,iBAAiB,CAAC,EAClD,EAAO,MAAM,IAAI;;EAEnB,UAAU,MACR,QAAQ,KAAK,oDAAoD,EAAI;EACxE,CAAC,EAEF,EACE,GACA;EACE,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,SAAS,EACP,cAGI;GACJ,IAAM,IAAK,EAAK,MAAM,qBAAqB;AACtC,SACL,EAAO,MAAM,MAAM,EACjB,IAAI,EAAO,MAAM,SAAS;IAAE,YAAY;IAAgB;IAAI,CAAC,EAC9D,CAAC,EACF,EAAO,MAAM,IAAI;;EAEnB,UAAU,MACR,QAAQ,KAAK,sDAAsD,EAAI;EAC1E,CACF,EAED,EACE,GACA;EACE,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,UAAU,MACR,QAAQ,KAAK,sDAAsD,EAAI;EAC1E,CACF,EAED,EAAgD,GAA4B;EAC1E,WAAW,EAAE,gBAAgB,KAAkB,IAAI;EACnD,MAAM,CAAC;EACP,UAAU,MACR,QAAQ,KAAK,qDAAqD,EAAI;EACzE,CAAC"}
|