@epam/ai-dial-chat-hooks 1.3.0-dev.311 → 1.3.0-dev.317
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/entry-points/project.d.ts +1 -0
- package/entry-points/project.d.ts.map +1 -1
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +135 -134
- package/package.json +18 -18
- package/project/project-conversation-data-source.d.ts +1 -1
- package/project/project-conversation-data-source.d.ts.map +1 -1
- package/project/project-mapping.d.ts +3 -0
- package/project/project-mapping.d.ts.map +1 -1
- package/project/project-mapping.js +23 -19
- package/project/project-viewed-marks.d.ts +9 -0
- package/project/project-viewed-marks.d.ts.map +1 -0
- package/project/project-viewed-marks.js +8 -0
- package/project/use-pinned-project-chats.d.ts +58 -0
- package/project/use-pinned-project-chats.d.ts.map +1 -0
- package/project/use-pinned-project-chats.js +269 -0
- package/project/use-project-actions.d.ts +5 -1
- package/project/use-project-actions.d.ts.map +1 -1
- package/project/use-project-actions.js +34 -31
- package/project/use-project-conversations.d.ts.map +1 -1
- package/project/use-project-conversations.js +83 -86
- package/project.js +19 -18
- package/shared/serialized-writer.d.ts +2 -0
- package/shared/serialized-writer.d.ts.map +1 -1
- package/shared/serialized-writer.js +28 -19
|
@@ -1,39 +1,43 @@
|
|
|
1
1
|
import { ProjectSource as e } from "@epam/ai-dial-chat-api-client";
|
|
2
|
-
import {
|
|
3
|
-
import { ProjectSource as
|
|
2
|
+
import { FilterTab as t, RequestStatus as n, getAttachmentTypeFromMime as r, inferMimeTypeFromPath as i } from "@epam/ai-dial-chat-shared";
|
|
3
|
+
import { ProjectSource as a } from "@epam/ai-dial-projects";
|
|
4
4
|
//#region src/project/project-mapping.ts
|
|
5
|
-
var
|
|
6
|
-
[e.Personal]:
|
|
7
|
-
[e.Shared]:
|
|
8
|
-
[e.Organization]:
|
|
9
|
-
},
|
|
5
|
+
var o = "", s = {
|
|
6
|
+
[e.Personal]: a.Personal,
|
|
7
|
+
[e.Shared]: a.Shared,
|
|
8
|
+
[e.Organization]: a.Organization
|
|
9
|
+
}, c = (e) => s[e], l = {
|
|
10
|
+
[e.Personal]: t.MyChats,
|
|
11
|
+
[e.Shared]: t.Shared,
|
|
12
|
+
[e.Organization]: t.Organization
|
|
13
|
+
}, u = (e) => l[e], d = (e) => ({
|
|
10
14
|
id: e.id,
|
|
11
15
|
name: e.name,
|
|
12
|
-
source:
|
|
16
|
+
source: c(e.source),
|
|
13
17
|
parentPath: e.parentPath,
|
|
14
18
|
updatedAt: e.updatedAt ?? e.createdAt
|
|
15
|
-
}),
|
|
19
|
+
}), f = (e) => ({
|
|
16
20
|
name: e.name,
|
|
17
21
|
description: e.description,
|
|
18
22
|
instructions: e.instructions,
|
|
19
23
|
contextFiles: e.contextFiles.map(({ name: e }) => ({
|
|
20
24
|
name: e,
|
|
21
|
-
contentType:
|
|
25
|
+
contentType: i(e) ?? o
|
|
22
26
|
}))
|
|
23
|
-
}),
|
|
24
|
-
let
|
|
27
|
+
}), p = (e) => e.contextFiles.map(({ name: e, size: t }) => {
|
|
28
|
+
let a = i(e) ?? o;
|
|
25
29
|
return {
|
|
26
30
|
id: `stored:${e}`,
|
|
27
31
|
name: e,
|
|
28
|
-
size:
|
|
29
|
-
contentType:
|
|
30
|
-
type:
|
|
31
|
-
status:
|
|
32
|
+
size: t,
|
|
33
|
+
contentType: a,
|
|
34
|
+
type: r(a),
|
|
35
|
+
status: n.Idle,
|
|
32
36
|
isStored: !0
|
|
33
37
|
};
|
|
34
|
-
}),
|
|
38
|
+
}), m = (e) => e.map(({ name: e }) => ({
|
|
35
39
|
name: e,
|
|
36
|
-
contentType:
|
|
40
|
+
contentType: i(e) ?? o
|
|
37
41
|
}));
|
|
38
42
|
//#endregion
|
|
39
|
-
export {
|
|
43
|
+
export { m as mapProjectArtifactsToOutputs, f as mapProjectDetailsToViewModel, d as mapProjectDtoToItem, c as mapProjectSource, u as mapProjectSourceToFilterTab, p as mapStoredContextFiles };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ProjectConversationItemDto } from '@epam/ai-dial-chat-api-client';
|
|
2
|
+
/** Conversation id → its `updatedAt` when the viewer marked it viewed. */
|
|
3
|
+
export type ViewedMarks = Map<string, number | undefined>;
|
|
4
|
+
/**
|
|
5
|
+
* Returns whether a listed conversation shows as unread once the viewer's
|
|
6
|
+
* marks apply, and drops a mark that the listing's newer `updatedAt` outdated.
|
|
7
|
+
*/
|
|
8
|
+
export declare const applyViewedMark: (marks: ViewedMarks, { id, updatedAt, isUnread, }: Pick<ProjectConversationItemDto, "id" | "updatedAt" | "isUnread">) => boolean;
|
|
9
|
+
//# sourceMappingURL=project-viewed-marks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-viewed-marks.d.ts","sourceRoot":"","sources":["../../src/project/project-viewed-marks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAEhF,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,WAAW,EAClB,8BAIG,IAAI,CAAC,0BAA0B,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,KACnE,OAaF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/project/project-viewed-marks.ts
|
|
2
|
+
var e = (e, { id: t, updatedAt: n, isUnread: r }) => {
|
|
3
|
+
if (!e.has(t)) return r;
|
|
4
|
+
let i = e.get(t);
|
|
5
|
+
return n != null && i != null && n > i && (e.delete(t), r);
|
|
6
|
+
};
|
|
7
|
+
//#endregion
|
|
8
|
+
export { e as applyViewedMark };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ProjectDetailsDto } from '@epam/ai-dial-chat-api-client';
|
|
2
|
+
import { ProjectsApiClient } from './projects-api-client';
|
|
3
|
+
/** Most chats listed under one pinned project. */
|
|
4
|
+
export declare const PINNED_PROJECT_CHATS_LIMIT = 10;
|
|
5
|
+
/** What `usePinnedProjectChats` needs from the host besides the ids. */
|
|
6
|
+
export interface PinnedProjectChatsOptions {
|
|
7
|
+
/** No request is sent and `projects` is empty while `false`. */
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
/** The project no longer exists (a watch `DELETE`, or `404` on a read). Called at most once per id. */
|
|
10
|
+
onProjectDeleted: (projectId: string) => void;
|
|
11
|
+
}
|
|
12
|
+
/** A chat listed under a pinned project. */
|
|
13
|
+
export interface PinnedProjectChat {
|
|
14
|
+
/** The conversation's DIAL id. */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Display title; the file-name title when its body could not be read. */
|
|
17
|
+
title: string;
|
|
18
|
+
/** The caller has not seen the conversation's current version. */
|
|
19
|
+
isUnread?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** A loaded pinned project and its newest chats. */
|
|
22
|
+
export interface PinnedProjectChats {
|
|
23
|
+
/** The project's details as last read; `canEdit`, `contentVersion` and `conversationCount` feed the host's actions. */
|
|
24
|
+
project: ProjectDetailsDto;
|
|
25
|
+
/** At most `PINNED_PROJECT_CHATS_LIMIT` chats, newest first. */
|
|
26
|
+
chats: PinnedProjectChat[];
|
|
27
|
+
/** The project has more chats than `chats` holds. */
|
|
28
|
+
hasMore: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** What `usePinnedProjectChats` returns. */
|
|
31
|
+
export interface PinnedProjectChatsResult {
|
|
32
|
+
/** Loaded projects, in `projectIds` order; an id whose load failed is absent while it is retried. */
|
|
33
|
+
projects: PinnedProjectChats[];
|
|
34
|
+
/** True until every id of the current `projectIds` settled once. */
|
|
35
|
+
isLoading: boolean;
|
|
36
|
+
/** Clears a chat's unread state locally until a read reports a newer version. Sends no request. */
|
|
37
|
+
markViewed: (conversationId: string) => void;
|
|
38
|
+
/** Silently re-reads one loaded project, through the same per-project gate as a watch event. */
|
|
39
|
+
refresh: (projectId: string) => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Loads each pinned project's details and newest chats through the injected
|
|
43
|
+
* client, and keeps them current with one watch stream over every pinned
|
|
44
|
+
* project. A changed project is refreshed silently, one refresh at a time per
|
|
45
|
+
* project plus one trailing run; a deleted one is dropped and reported. A
|
|
46
|
+
* first load that fails with anything but a `404` is retried with a bounded
|
|
47
|
+
* backoff, and the project stays out of the watch until it loads. A dropped
|
|
48
|
+
* stream is reopened with a bounded backoff and followed by a refresh of every
|
|
49
|
+
* project; a watch that cannot be opened is not retried for the same projects.
|
|
50
|
+
* Requests are aborted on unmount, when `enabled` turns false, and for an id
|
|
51
|
+
* that leaves `projectIds`.
|
|
52
|
+
*
|
|
53
|
+
* @param client - Configured project requests, from `createProjectsApiClient`; it must be referentially stable, because a new object reloads.
|
|
54
|
+
* @param projectIds - The pinned project ids, in display order.
|
|
55
|
+
* @param options - Whether the tree is enabled and the delete callback; the callback is read at event time, so a new identity never resubscribes.
|
|
56
|
+
*/
|
|
57
|
+
export declare const usePinnedProjectChats: (client: Pick<ProjectsApiClient, "getProject" | "listProjectConversations" | "getProjectConversationTitles" | "watchProjects">, projectIds: string[], { enabled, onProjectDeleted }: PinnedProjectChatsOptions) => PinnedProjectChatsResult;
|
|
58
|
+
//# sourceMappingURL=use-pinned-project-chats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pinned-project-chats.d.ts","sourceRoot":"","sources":["../../src/project/use-pinned-project-chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAKvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,kDAAkD;AAClD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAW7C,wEAAwE;AACxE,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,uGAAuG;IACvG,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,uHAAuH;IACvH,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gEAAgE;IAChE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,wBAAwB;IACvC,qGAAqG;IACrG,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAC;IACnB,mGAAmG;IACnG,UAAU,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,gGAAgG;IAChG,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAiFD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,IAAI,CACV,iBAAiB,EACf,YAAY,GACZ,0BAA0B,GAC1B,8BAA8B,GAC9B,eAAe,CAClB,EACD,YAAY,MAAM,EAAE,EACpB,+BAA+B,yBAAyB,KACvD,wBAqXF,CAAC"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { getApiErrorStatus as e } from "../api-error/api-error.js";
|
|
2
|
+
import { runProjectWatch as t } from "./project-watch-stream.js";
|
|
3
|
+
import { applyViewedMark as n } from "./project-viewed-marks.js";
|
|
4
|
+
import { ProjectWatchAction as r } from "@epam/ai-dial-chat-api-client";
|
|
5
|
+
import { useCallback as i, useEffect as a, useMemo as o, useRef as s, useState as c } from "react";
|
|
6
|
+
//#region src/project/use-pinned-project-chats.ts
|
|
7
|
+
var l = 10, u = 1e3, d = [
|
|
8
|
+
1e3,
|
|
9
|
+
2e3,
|
|
10
|
+
4e3,
|
|
11
|
+
8e3,
|
|
12
|
+
16e3
|
|
13
|
+
], f = "\n", p = {
|
|
14
|
+
snapshots: /* @__PURE__ */ new Map(),
|
|
15
|
+
settled: /* @__PURE__ */ new Set(),
|
|
16
|
+
watchKey: ""
|
|
17
|
+
}, m = [], h = (e, { settled: t, snapshots: n }, r) => {
|
|
18
|
+
let i = [...e].sort();
|
|
19
|
+
return i.every((e) => t.has(e)) ? i.filter((e) => n.has(e)).slice(0, u).join(f) : r;
|
|
20
|
+
}, g = (e, t) => {
|
|
21
|
+
if (!e.snapshots.has(t) && !e.settled.has(t)) return e;
|
|
22
|
+
let n = new Map(e.snapshots);
|
|
23
|
+
n.delete(t);
|
|
24
|
+
let r = new Set(e.settled);
|
|
25
|
+
return r.delete(t), {
|
|
26
|
+
...e,
|
|
27
|
+
snapshots: n,
|
|
28
|
+
settled: r
|
|
29
|
+
};
|
|
30
|
+
}, _ = (e, t) => {
|
|
31
|
+
if (t.length === 0) return e;
|
|
32
|
+
let n = new Map(t.map((e) => [e.id, e]));
|
|
33
|
+
return e.map((e) => {
|
|
34
|
+
let t = n.get(e.id);
|
|
35
|
+
return t ? {
|
|
36
|
+
...e,
|
|
37
|
+
title: t.title,
|
|
38
|
+
isTitlePending: !1
|
|
39
|
+
} : e;
|
|
40
|
+
});
|
|
41
|
+
}, v = (l, u, { enabled: v, onProjectDeleted: y }) => {
|
|
42
|
+
let [b, x] = c(p), S = s(b);
|
|
43
|
+
a(() => {
|
|
44
|
+
S.current = b;
|
|
45
|
+
});
|
|
46
|
+
let C = s(y);
|
|
47
|
+
a(() => {
|
|
48
|
+
C.current = y;
|
|
49
|
+
});
|
|
50
|
+
let w = s(/* @__PURE__ */ new Set()), T = s(/* @__PURE__ */ new Map()), E = s(/* @__PURE__ */ new Map()), D = s(/* @__PURE__ */ new Set()), O = s(/* @__PURE__ */ new Map()), k = s(/* @__PURE__ */ new Map()), A = s(null), j = o(() => [...new Set(u)].sort().join(f), [u]), M = i(async (e, t) => {
|
|
51
|
+
let [n, r] = await Promise.allSettled([l.getProject(e, t), l.listProjectConversations(e, t)]);
|
|
52
|
+
if (n.status === "rejected") throw n.reason;
|
|
53
|
+
let i = r.status === "fulfilled" ? r.value.items : [], a = i.slice(0, 10), o = a.filter((e) => e.isTitlePending).map((e) => e.name);
|
|
54
|
+
if (o.length > 0) try {
|
|
55
|
+
let { items: n } = await l.getProjectConversationTitles(e, o, t);
|
|
56
|
+
a = _(a, n);
|
|
57
|
+
} catch {}
|
|
58
|
+
return {
|
|
59
|
+
project: n.value,
|
|
60
|
+
items: a,
|
|
61
|
+
hasMore: i.length > 10
|
|
62
|
+
};
|
|
63
|
+
}, [l]), N = i(({ project: e, items: t, hasMore: r }) => {
|
|
64
|
+
for (let { id: e, updatedAt: n } of t) k.current.set(e, n);
|
|
65
|
+
return {
|
|
66
|
+
project: e,
|
|
67
|
+
hasMore: r,
|
|
68
|
+
chats: t.map((e) => ({
|
|
69
|
+
id: e.id,
|
|
70
|
+
title: e.title,
|
|
71
|
+
...n(O.current, e) ? { isUnread: !0 } : {}
|
|
72
|
+
}))
|
|
73
|
+
};
|
|
74
|
+
}, []), P = i((e) => {
|
|
75
|
+
D.current.has(e) || (D.current.add(e), C.current(e));
|
|
76
|
+
}, []), F = i((e) => {
|
|
77
|
+
E.current.get(e)?.controller?.abort(), E.current.delete(e);
|
|
78
|
+
}, []), I = i((e) => {
|
|
79
|
+
F(e), x((t) => {
|
|
80
|
+
if (!t.snapshots.has(e)) return t;
|
|
81
|
+
let n = new Map(t.snapshots);
|
|
82
|
+
return n.delete(e), {
|
|
83
|
+
...t,
|
|
84
|
+
snapshots: n,
|
|
85
|
+
watchKey: h(w.current, {
|
|
86
|
+
settled: t.settled,
|
|
87
|
+
snapshots: n
|
|
88
|
+
}, t.watchKey)
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
}, [F]), L = i((t) => {
|
|
92
|
+
if (!S.current.snapshots.has(t)) return;
|
|
93
|
+
let n = E.current.get(t);
|
|
94
|
+
if (n ?? (n = {
|
|
95
|
+
isRefreshing: !1,
|
|
96
|
+
isPending: !1
|
|
97
|
+
}, E.current.set(t, n)), n.isRefreshing) {
|
|
98
|
+
n.isPending = !0;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let r = n, i = new AbortController();
|
|
102
|
+
r.isRefreshing = !0, r.controller = i, (async () => {
|
|
103
|
+
try {
|
|
104
|
+
let e = await M(t, i.signal);
|
|
105
|
+
if (i.signal.aborted) return;
|
|
106
|
+
let n = N(e);
|
|
107
|
+
x((e) => {
|
|
108
|
+
if (!e.snapshots.has(t)) return e;
|
|
109
|
+
let r = new Map(e.snapshots);
|
|
110
|
+
return r.set(t, n), {
|
|
111
|
+
...e,
|
|
112
|
+
snapshots: r
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
} catch (n) {
|
|
116
|
+
if (i.signal.aborted) return;
|
|
117
|
+
e(n) === 404 && (I(t), P(t));
|
|
118
|
+
} finally {
|
|
119
|
+
r.isRefreshing = !1, r.isPending && !i.signal.aborted && E.current.get(t) === r && (r.isPending = !1, L(t));
|
|
120
|
+
}
|
|
121
|
+
})();
|
|
122
|
+
}, [
|
|
123
|
+
I,
|
|
124
|
+
M,
|
|
125
|
+
P,
|
|
126
|
+
N
|
|
127
|
+
]), R = i((t, n, r = 0) => {
|
|
128
|
+
let i = () => {
|
|
129
|
+
T.current.get(t) === n && T.current.delete(t);
|
|
130
|
+
};
|
|
131
|
+
(async () => {
|
|
132
|
+
try {
|
|
133
|
+
let e = await M(t, n.signal);
|
|
134
|
+
if (n.signal.aborted) return;
|
|
135
|
+
let r = N(e);
|
|
136
|
+
x((e) => {
|
|
137
|
+
let n = new Map(e.snapshots);
|
|
138
|
+
n.set(t, r);
|
|
139
|
+
let i = new Set(e.settled).add(t);
|
|
140
|
+
return {
|
|
141
|
+
snapshots: n,
|
|
142
|
+
settled: i,
|
|
143
|
+
watchKey: h(w.current, {
|
|
144
|
+
settled: i,
|
|
145
|
+
snapshots: n
|
|
146
|
+
}, e.watchKey)
|
|
147
|
+
};
|
|
148
|
+
}), i();
|
|
149
|
+
} catch (a) {
|
|
150
|
+
if (n.signal.aborted) return;
|
|
151
|
+
x((e) => {
|
|
152
|
+
if (e.settled.has(t)) return e;
|
|
153
|
+
let n = new Set(e.settled).add(t);
|
|
154
|
+
return {
|
|
155
|
+
...e,
|
|
156
|
+
settled: n,
|
|
157
|
+
watchKey: h(w.current, {
|
|
158
|
+
settled: n,
|
|
159
|
+
snapshots: e.snapshots
|
|
160
|
+
}, e.watchKey)
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
let o = e(a) === 404, s = o ? void 0 : d[r];
|
|
164
|
+
if (s == null) {
|
|
165
|
+
i(), o && P(t);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
let c = setTimeout(() => R(t, n, r + 1), s);
|
|
169
|
+
n.signal.addEventListener("abort", () => clearTimeout(c), { once: !0 });
|
|
170
|
+
}
|
|
171
|
+
})();
|
|
172
|
+
}, [
|
|
173
|
+
M,
|
|
174
|
+
P,
|
|
175
|
+
N
|
|
176
|
+
]);
|
|
177
|
+
a(() => () => {
|
|
178
|
+
for (let e of T.current.values()) e.abort();
|
|
179
|
+
T.current.clear();
|
|
180
|
+
for (let e of E.current.values()) e.controller?.abort();
|
|
181
|
+
E.current.clear(), w.current.clear(), D.current.clear(), O.current.clear(), k.current.clear(), x(p);
|
|
182
|
+
}, [l, v]), a(() => {
|
|
183
|
+
if (!v) return;
|
|
184
|
+
let e = new Set(j === "" ? [] : j.split(f));
|
|
185
|
+
for (let t of [...w.current]) e.has(t) || (w.current.delete(t), D.current.delete(t), T.current.get(t)?.abort(), T.current.delete(t), F(t), x((e) => {
|
|
186
|
+
let n = g(e, t);
|
|
187
|
+
return {
|
|
188
|
+
...n,
|
|
189
|
+
watchKey: h(w.current, n, e.watchKey)
|
|
190
|
+
};
|
|
191
|
+
}));
|
|
192
|
+
for (let t of e) {
|
|
193
|
+
if (w.current.has(t)) continue;
|
|
194
|
+
w.current.add(t);
|
|
195
|
+
let e = new AbortController();
|
|
196
|
+
T.current.set(t, e), R(t, e);
|
|
197
|
+
}
|
|
198
|
+
}, [
|
|
199
|
+
v,
|
|
200
|
+
j,
|
|
201
|
+
F,
|
|
202
|
+
R
|
|
203
|
+
]);
|
|
204
|
+
let z = v && j !== "" && j.split(f).some((e) => !b.settled.has(e)), B = v ? b.watchKey : "", { watchProjects: V } = l;
|
|
205
|
+
a(() => {
|
|
206
|
+
if (V == null || B === "" || B === A.current) return;
|
|
207
|
+
let e = new AbortController();
|
|
208
|
+
return t({
|
|
209
|
+
watchProjects: V,
|
|
210
|
+
ids: B.split(f),
|
|
211
|
+
signal: e.signal,
|
|
212
|
+
onEvent: (t) => {
|
|
213
|
+
if (e.signal.aborted) return;
|
|
214
|
+
let n = S.current.snapshots.get(t.id);
|
|
215
|
+
n != null && (t.action === r.Delete ? (I(t.id), P(t.id)) : (t.etag == null || t.etag !== n.project.etag) && L(t.id));
|
|
216
|
+
},
|
|
217
|
+
onReconnected: () => {
|
|
218
|
+
for (let e of S.current.snapshots.keys()) L(e);
|
|
219
|
+
},
|
|
220
|
+
onUnavailable: () => {
|
|
221
|
+
A.current = B;
|
|
222
|
+
}
|
|
223
|
+
}), () => e.abort();
|
|
224
|
+
}, [
|
|
225
|
+
V,
|
|
226
|
+
B,
|
|
227
|
+
I,
|
|
228
|
+
P,
|
|
229
|
+
L
|
|
230
|
+
]);
|
|
231
|
+
let H = i((e) => {
|
|
232
|
+
k.current.has(e) && (O.current.set(e, k.current.get(e)), x((t) => {
|
|
233
|
+
let n;
|
|
234
|
+
for (let [r, i] of t.snapshots) i.chats.some((t) => t.id === e && t.isUnread) && (n ??= new Map(t.snapshots), n.set(r, {
|
|
235
|
+
...i,
|
|
236
|
+
chats: i.chats.map((t) => t.id === e ? {
|
|
237
|
+
id: t.id,
|
|
238
|
+
title: t.title
|
|
239
|
+
} : t)
|
|
240
|
+
}));
|
|
241
|
+
return n ? {
|
|
242
|
+
...t,
|
|
243
|
+
snapshots: n
|
|
244
|
+
} : t;
|
|
245
|
+
}));
|
|
246
|
+
}, []);
|
|
247
|
+
return {
|
|
248
|
+
projects: o(() => {
|
|
249
|
+
if (!v) return m;
|
|
250
|
+
let e = /* @__PURE__ */ new Set(), t = [];
|
|
251
|
+
for (let n of u) {
|
|
252
|
+
if (e.has(n)) continue;
|
|
253
|
+
e.add(n);
|
|
254
|
+
let r = b.snapshots.get(n);
|
|
255
|
+
r && t.push(r);
|
|
256
|
+
}
|
|
257
|
+
return t;
|
|
258
|
+
}, [
|
|
259
|
+
v,
|
|
260
|
+
u,
|
|
261
|
+
b.snapshots
|
|
262
|
+
]),
|
|
263
|
+
isLoading: z,
|
|
264
|
+
markViewed: H,
|
|
265
|
+
refresh: L
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
//#endregion
|
|
269
|
+
export { l as PINNED_PROJECT_CHATS_LIMIT, v as usePinnedProjectChats };
|
|
@@ -24,6 +24,10 @@ export interface ProjectActionsHandlers {
|
|
|
24
24
|
onError: (error: ProjectActionError, requestId?: string) => void;
|
|
25
25
|
/** Re-reads the project, e.g. after a delete lost to a concurrent change. */
|
|
26
26
|
onReload: () => void;
|
|
27
|
+
/** Whether the delete confirmation is open, when the host owns that state. Defaults to the hook's own state. */
|
|
28
|
+
isDeleteOpen?: boolean;
|
|
29
|
+
/** Called with the new state whenever the delete confirmation opens or closes: a request, a cancel, a success or a conflict. */
|
|
30
|
+
onDeleteOpenChange?: (isOpen: boolean) => void;
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
33
|
* Pin, archive and context-file downloads, and the confirmed delete of one
|
|
@@ -34,7 +38,7 @@ export interface ProjectActionsHandlers {
|
|
|
34
38
|
* @param project - The loaded project, or `null` while none is loaded.
|
|
35
39
|
* @param handlers - Host behaviour the actions delegate to.
|
|
36
40
|
*/
|
|
37
|
-
export declare const useProjectActions: (client: Pick<ProjectsApiClient, "deleteProject" | "downloadProjectArchive">, project: ProjectDetailsDto | null, { isPinned, setPinned, saveFile, onArchiveDownloaded, onDeleted, onError, onReload, }: ProjectActionsHandlers) => {
|
|
41
|
+
export declare const useProjectActions: (client: Pick<ProjectsApiClient, "deleteProject" | "downloadProjectArchive">, project: ProjectDetailsDto | null, { isPinned, setPinned, saveFile, onArchiveDownloaded, onDeleted, onError, onReload, isDeleteOpen: controlledDeleteOpen, onDeleteOpenChange, }: ProjectActionsHandlers) => {
|
|
38
42
|
isPinned: boolean;
|
|
39
43
|
isPinPending: boolean;
|
|
40
44
|
togglePin: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-project-actions.d.ts","sourceRoot":"","sources":["../../src/project/use-project-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,iEAAiE;AACjE,oBAAY,kBAAkB;IAC5B,GAAG,QAAQ;IACX,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,8EAA8E;IAC9E,gBAAgB,sBAAsB;CACvC;AAED,sDAAsD;AACtD,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,yEAAyE;IACzE,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sFAAsF;IACtF,SAAS,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD,gFAAgF;IAChF,OAAO,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"use-project-actions.d.ts","sourceRoot":"","sources":["../../src/project/use-project-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,iEAAiE;AACjE,oBAAY,kBAAkB;IAC5B,GAAG,QAAQ;IACX,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,8EAA8E;IAC9E,gBAAgB,sBAAsB;CACvC;AAED,sDAAsD;AACtD,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB,kDAAkD;IAClD,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,yEAAyE;IACzE,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sFAAsF;IACtF,SAAS,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD,gFAAgF;IAChF,OAAO,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gHAAgH;IAChH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gIAAgI;IAChI,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAChD;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,wBAAwB,CAAC,EAC3E,SAAS,iBAAiB,GAAG,IAAI,EACjC,+IAUG,sBAAsB;;;;;;;;;;CAyG1B,CAAC"}
|
|
@@ -5,84 +5,87 @@ import { useCallback as r, useMemo as i, useState as a } from "react";
|
|
|
5
5
|
//#region src/project/use-project-actions.ts
|
|
6
6
|
var o = /* @__PURE__ */ function(e) {
|
|
7
7
|
return e.Pin = "pin", e.Download = "download", e.Delete = "delete", e.ChangedElsewhere = "changed-elsewhere", e;
|
|
8
|
-
}({}), s = (o, s, { isPinned: c, setPinned: l, saveFile: u, onArchiveDownloaded: d, onDeleted: f, onError: p, onReload: m }) => {
|
|
9
|
-
let [
|
|
8
|
+
}({}), s = (o, s, { isPinned: c, setPinned: l, saveFile: u, onArchiveDownloaded: d, onDeleted: f, onError: p, onReload: m, isDeleteOpen: h, onDeleteOpenChange: g }) => {
|
|
9
|
+
let [_, v] = a(!1), [y, b] = a(!1), [x, S] = a(!1), C = h != null, w = h ?? y, T = r((e) => {
|
|
10
|
+
C || b(e), g?.(e);
|
|
11
|
+
}, [C, g]), E = r(async (t, n) => {
|
|
10
12
|
let { traceId: r } = await e(t);
|
|
11
13
|
p(n, r);
|
|
12
|
-
}, [p]),
|
|
14
|
+
}, [p]), D = r(async () => {
|
|
13
15
|
if (s != null) {
|
|
14
|
-
|
|
16
|
+
v(!0);
|
|
15
17
|
try {
|
|
16
18
|
await l(s.id, !c);
|
|
17
19
|
} catch (e) {
|
|
18
|
-
await
|
|
20
|
+
await E(e, "pin");
|
|
19
21
|
} finally {
|
|
20
|
-
|
|
22
|
+
v(!1);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
}, [
|
|
24
26
|
s,
|
|
25
27
|
c,
|
|
26
28
|
l,
|
|
27
|
-
|
|
28
|
-
]),
|
|
29
|
+
E
|
|
30
|
+
]), O = r(async () => {
|
|
29
31
|
if (s != null) try {
|
|
30
32
|
let e = await u(await o.downloadProjectArchive(s.id), `${t(s.name)}.zip`);
|
|
31
33
|
d?.(e);
|
|
32
34
|
} catch (e) {
|
|
33
|
-
await
|
|
35
|
+
await E(e, "download");
|
|
34
36
|
}
|
|
35
37
|
}, [
|
|
36
38
|
o,
|
|
37
39
|
s,
|
|
38
40
|
u,
|
|
39
41
|
d,
|
|
40
|
-
|
|
41
|
-
]),
|
|
42
|
-
|
|
43
|
-
}, [
|
|
42
|
+
E
|
|
43
|
+
]), k = r(() => T(!0), [T]), A = r(() => {
|
|
44
|
+
x || T(!1);
|
|
45
|
+
}, [x, T]), j = r(async () => {
|
|
44
46
|
if (s != null) {
|
|
45
|
-
|
|
47
|
+
S(!0);
|
|
46
48
|
try {
|
|
47
|
-
await o.deleteProject(s.id, s.contentVersion),
|
|
49
|
+
await o.deleteProject(s.id, s.contentVersion), T(!1), f(s);
|
|
48
50
|
} catch (t) {
|
|
49
51
|
let { code: r, traceId: i } = await e(t);
|
|
50
52
|
if (r === n.ProjectChanged) {
|
|
51
|
-
|
|
53
|
+
T(!1), p("changed-elsewhere", i), m();
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
56
|
p("delete", i);
|
|
55
57
|
} finally {
|
|
56
|
-
|
|
58
|
+
S(!1);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
}, [
|
|
60
62
|
o,
|
|
61
63
|
s,
|
|
64
|
+
T,
|
|
62
65
|
f,
|
|
63
66
|
p,
|
|
64
67
|
m
|
|
65
68
|
]);
|
|
66
69
|
return i(() => ({
|
|
67
70
|
isPinned: c,
|
|
68
|
-
isPinPending:
|
|
69
|
-
togglePin:
|
|
70
|
-
downloadArchive:
|
|
71
|
-
isDeleteOpen:
|
|
72
|
-
isDeleting:
|
|
73
|
-
requestDelete:
|
|
74
|
-
cancelDelete:
|
|
75
|
-
confirmDelete:
|
|
71
|
+
isPinPending: _,
|
|
72
|
+
togglePin: D,
|
|
73
|
+
downloadArchive: O,
|
|
74
|
+
isDeleteOpen: w,
|
|
75
|
+
isDeleting: x,
|
|
76
|
+
requestDelete: k,
|
|
77
|
+
cancelDelete: A,
|
|
78
|
+
confirmDelete: j
|
|
76
79
|
}), [
|
|
77
80
|
c,
|
|
78
|
-
h,
|
|
79
|
-
S,
|
|
80
|
-
C,
|
|
81
81
|
_,
|
|
82
|
-
|
|
82
|
+
D,
|
|
83
|
+
O,
|
|
83
84
|
w,
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
x,
|
|
86
|
+
k,
|
|
87
|
+
A,
|
|
88
|
+
j
|
|
86
89
|
]);
|
|
87
90
|
};
|
|
88
91
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-project-conversations.d.ts","sourceRoot":"","sources":["../../src/project/use-project-conversations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-project-conversations.d.ts","sourceRoot":"","sources":["../../src/project/use-project-conversations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AA8E/D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,IAAI,CACV,iBAAiB,EACf,0BAA0B,GAC1B,8BAA8B,GAC9B,2BAA2B,GAC3B,2BAA2B,GAC3B,+BAA+B,CAClC,EACD,WAAW,MAAM,GAAG,IAAI;;;;IA6NtB,8CAA8C;;IAE9C,2DAA2D;;;;iBA1ChD,MAAM,YAAY,MAAM;iBAaxB,MAAM;;qBAlCZ,MAAM;CAwEd,CAAC"}
|