@omg-dev/protocol 0.6.137 → 0.6.138
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/session-mention-token.d.ts +14 -5
- package/dist/session-mention-token.d.ts.map +1 -1
- package/dist/session-mention-token.js +11 -4
- package/dist/session-mention-token.js.map +1 -1
- package/dist/threads.d.ts +146 -0
- package/dist/threads.d.ts.map +1 -0
- package/dist/threads.js +172 -0
- package/dist/threads.js.map +1 -0
- package/package.json +1 -1
|
@@ -50,6 +50,16 @@ export type SessionIds = {
|
|
|
50
50
|
nativeSessionId?: string | null;
|
|
51
51
|
/** Shown in place of a bare id when a reference is rendered. */
|
|
52
52
|
title?: string | null;
|
|
53
|
+
/** Agent kind, for the icon on a rendered reference. */
|
|
54
|
+
agent?: string | null;
|
|
55
|
+
/** Project name, shown as a badge on a rendered reference. */
|
|
56
|
+
project?: string | null;
|
|
57
|
+
};
|
|
58
|
+
/** What a rendered reference shows. Stable per ref, so React can compare it. */
|
|
59
|
+
export type SessionRefLabel = {
|
|
60
|
+
title: string | null;
|
|
61
|
+
agent: string | null;
|
|
62
|
+
project: string | null;
|
|
53
63
|
};
|
|
54
64
|
/** The subset of OmgClient a reference lookup needs, so tests can fake it. */
|
|
55
65
|
export type SessionRefClient = {
|
|
@@ -92,12 +102,11 @@ export declare function createSessionRefOpener(deps: {
|
|
|
92
102
|
/** True when `href` was a session reference and has been taken over. */
|
|
93
103
|
open(href: string): boolean;
|
|
94
104
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* keeps showing the id.
|
|
105
|
+
* Title and agent for `ref`, or null while unknown. The first call for a
|
|
106
|
+
* ref starts one lookup; `subscribe` fires when it lands. A ref that names
|
|
107
|
+
* no session stays null so the caller keeps showing the id.
|
|
99
108
|
*/
|
|
100
|
-
label(ref: string):
|
|
109
|
+
label(ref: string): SessionRefLabel | null;
|
|
101
110
|
subscribe(listener: () => void): () => void;
|
|
102
111
|
};
|
|
103
112
|
//# sourceMappingURL=session-mention-token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-mention-token.d.ts","sourceRoot":"","sources":["../src/session-mention-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9D;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAWzE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOnE;AAQD,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"session-mention-token.d.ts","sourceRoot":"","sources":["../src/session-mention-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -142,6 +142,13 @@ export function createSessionRefOpener(deps) {
|
|
|
142
142
|
let generation = 0;
|
|
143
143
|
// Titles belong to the registered client: a switch clears them.
|
|
144
144
|
let labels = new Map();
|
|
145
|
+
const toLabel = (session) => session
|
|
146
|
+
? {
|
|
147
|
+
title: session.title?.trim() || null,
|
|
148
|
+
agent: session.agent?.trim() || null,
|
|
149
|
+
project: session.project?.trim() || null,
|
|
150
|
+
}
|
|
151
|
+
: null;
|
|
145
152
|
const pending = new Set();
|
|
146
153
|
const listeners = new Set();
|
|
147
154
|
const notify = () => {
|
|
@@ -169,9 +176,9 @@ export function createSessionRefOpener(deps) {
|
|
|
169
176
|
return null;
|
|
170
177
|
const known = findSessionRef(ref, client.peekSessions());
|
|
171
178
|
if (known) {
|
|
172
|
-
const
|
|
173
|
-
labels.set(key,
|
|
174
|
-
return
|
|
179
|
+
const found = toLabel(known);
|
|
180
|
+
labels.set(key, found);
|
|
181
|
+
return found;
|
|
175
182
|
}
|
|
176
183
|
if (pending.has(key))
|
|
177
184
|
return null;
|
|
@@ -184,7 +191,7 @@ export function createSessionRefOpener(deps) {
|
|
|
184
191
|
if (current !== client || generation !== startedAt)
|
|
185
192
|
return;
|
|
186
193
|
pending.delete(key);
|
|
187
|
-
labels.set(key, session
|
|
194
|
+
labels.set(key, toLabel(session));
|
|
188
195
|
notify();
|
|
189
196
|
});
|
|
190
197
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-mention-token.js","sourceRoot":"","sources":["../src/session-mention-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,SAAS,GAAG,+EAA+E,CAAC;AAClG,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/E,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,MAAM,CAAC,4CAA4C,WAAW,MAAM,EAAE,GAAG,CAAC,CAAC;AACxF,CAAC;AAQD,mEAAmE;AACnE,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAAiB,EAAE,KAAa;IACxE,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;IACjD,OAAO,KAAK,KAAK,iBAAiB,GAAG,GAAG,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,iBAAiB,WAAW,IAAI,CAAC,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrB,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,eAAe,CAAC,EAAE,CAAC;IACxD,IAAI,iEAAiE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,OAAO,eAAe,CAAC,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;
|
|
1
|
+
{"version":3,"file":"session-mention-token.js","sourceRoot":"","sources":["../src/session-mention-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads on the wire, and the rules every client draws them with.
|
|
3
|
+
*
|
|
4
|
+
* One owner for the server (src/threads.ts), iOS and the web app. A thread is
|
|
5
|
+
* people-first chat with no agent behind it; omg joins only on `@omg`, and a
|
|
6
|
+
* task it starts is drawn as a card whose state is decided by
|
|
7
|
+
* `taskCardState` below. Keeping that rule here is what stops the phone and
|
|
8
|
+
* the web from disagreeing about whether a task "needs you".
|
|
9
|
+
*/
|
|
10
|
+
export type ThreadAuthor = {
|
|
11
|
+
kind: "human";
|
|
12
|
+
participantId: string;
|
|
13
|
+
name: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "omg";
|
|
16
|
+
};
|
|
17
|
+
export type ThreadTaskEvent = "started" | "finished" | "blocked" | "failed";
|
|
18
|
+
export type ThreadMessage = {
|
|
19
|
+
id: string;
|
|
20
|
+
threadId: string;
|
|
21
|
+
ts: number;
|
|
22
|
+
author: ThreadAuthor;
|
|
23
|
+
text: string;
|
|
24
|
+
/** Present on omg's task messages: which task, and what happened to it. */
|
|
25
|
+
task?: {
|
|
26
|
+
sessionId: string;
|
|
27
|
+
event: ThreadTaskEvent;
|
|
28
|
+
title?: string | null;
|
|
29
|
+
project?: string | null;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The top-level message this is a reply to, as in Slack. omg always answers
|
|
33
|
+
* in the replies of the message that mentioned it, and a task's updates go
|
|
34
|
+
* to the same replies. Absent: a top-level message.
|
|
35
|
+
*/
|
|
36
|
+
replyTo?: string | null;
|
|
37
|
+
/** Client only: sent, not yet stored. */
|
|
38
|
+
pending?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export type ThreadProject = {
|
|
41
|
+
cwd: string;
|
|
42
|
+
name: string;
|
|
43
|
+
};
|
|
44
|
+
export type ThreadSummary = {
|
|
45
|
+
id: string;
|
|
46
|
+
title: string;
|
|
47
|
+
createdAt: number;
|
|
48
|
+
updatedAt: number;
|
|
49
|
+
project: ThreadProject | null;
|
|
50
|
+
lastMessage: Pick<ThreadMessage, "author" | "text" | "ts"> | null;
|
|
51
|
+
};
|
|
52
|
+
export type ThreadTaskRow = {
|
|
53
|
+
sessionId: string;
|
|
54
|
+
title: string | null;
|
|
55
|
+
project: string | null;
|
|
56
|
+
busy: boolean;
|
|
57
|
+
status: string | null;
|
|
58
|
+
/** Not in the live session list any more. */
|
|
59
|
+
ended: boolean;
|
|
60
|
+
};
|
|
61
|
+
export type ThreadParticipant = {
|
|
62
|
+
id: string;
|
|
63
|
+
kind: string;
|
|
64
|
+
role?: string;
|
|
65
|
+
display: {
|
|
66
|
+
name?: string | null;
|
|
67
|
+
fallback: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export type ThreadDetail = {
|
|
71
|
+
/** The caller's participant id, so a client can put their own bubbles on the right. */
|
|
72
|
+
me: string;
|
|
73
|
+
thread: ThreadSummary;
|
|
74
|
+
participants: ThreadParticipant[];
|
|
75
|
+
messages: ThreadMessage[];
|
|
76
|
+
tasks: ThreadTaskRow[];
|
|
77
|
+
};
|
|
78
|
+
export type TaskCardState = "working" | "needs-you" | "done" | "failed" | "ended";
|
|
79
|
+
export declare const TASK_STATE_LABEL: Record<TaskCardState, string>;
|
|
80
|
+
/** Only an explicit mention wakes omg. An address like x@omg.dev does not. */
|
|
81
|
+
export declare const OMG_MENTION: RegExp;
|
|
82
|
+
export declare function mentionsOmg(text: string): boolean;
|
|
83
|
+
/** The same id in either form: a full uuid or a short prefix. */
|
|
84
|
+
export declare function sameSession(a: string | null | undefined, b: string | null | undefined): boolean;
|
|
85
|
+
/** The newest event omg posted for a task. */
|
|
86
|
+
export declare function latestTaskEvent(messages: readonly ThreadMessage[], sessionId: string): ThreadTaskEvent | null;
|
|
87
|
+
/**
|
|
88
|
+
* A question waiting on the person wins over everything but a running turn.
|
|
89
|
+
* Then the live row: busy is working. An idle task is done once it has
|
|
90
|
+
* reported and working until then; a task gone from the list is its last
|
|
91
|
+
* report, or "ended".
|
|
92
|
+
*/
|
|
93
|
+
export declare function taskCardState(input: {
|
|
94
|
+
event: ThreadTaskEvent | null;
|
|
95
|
+
row: ThreadTaskRow | null | undefined;
|
|
96
|
+
openAsk: boolean;
|
|
97
|
+
}): TaskCardState;
|
|
98
|
+
/**
|
|
99
|
+
* Which messages draw a card. Each task is drawn once, at the message that
|
|
100
|
+
* started it; later messages about the same task are plain omg messages,
|
|
101
|
+
* because the card above already shows the live state.
|
|
102
|
+
*/
|
|
103
|
+
export declare function cardMessageIds(messages: readonly ThreadMessage[]): Set<string>;
|
|
104
|
+
/** One line for a thread row: who spoke last, and what they said. */
|
|
105
|
+
export declare function threadPreview(thread: Pick<ThreadSummary, "lastMessage">): string;
|
|
106
|
+
/** The task a message is about, as the card needs it. Pure, for both clients. */
|
|
107
|
+
export declare function taskCardFor(message: ThreadMessage, detail: Pick<ThreadDetail, "tasks">, messages: readonly ThreadMessage[], openAskSessionIds: readonly (string | null | undefined)[]): {
|
|
108
|
+
sessionId: string;
|
|
109
|
+
title: string;
|
|
110
|
+
project: string | null;
|
|
111
|
+
state: TaskCardState;
|
|
112
|
+
} | null;
|
|
113
|
+
/** Slack's rule: a message joins the one above when the same author wrote it within this long. */
|
|
114
|
+
export declare const THREAD_GROUP_MS: number;
|
|
115
|
+
/**
|
|
116
|
+
* Whether a message starts a new group: its own avatar, name and time. The
|
|
117
|
+
* rest of a group is just text under the first message.
|
|
118
|
+
*/
|
|
119
|
+
export declare function startsMessageGroup(previous: ThreadMessage | undefined, message: ThreadMessage): boolean;
|
|
120
|
+
/** A stable avatar colour for a person, from their participant id. */
|
|
121
|
+
export declare function authorHue(author: ThreadAuthor): number;
|
|
122
|
+
export declare function authorName(author: ThreadAuthor): string;
|
|
123
|
+
/** Top-level messages: what the main list shows. */
|
|
124
|
+
export declare function topLevelMessages(messages: readonly ThreadMessage[]): ThreadMessage[];
|
|
125
|
+
/** The replies to one top-level message, oldest first. */
|
|
126
|
+
export declare function repliesTo(messages: readonly ThreadMessage[], rootId: string): ThreadMessage[];
|
|
127
|
+
export type ReplySummary = {
|
|
128
|
+
count: number;
|
|
129
|
+
lastTs: number;
|
|
130
|
+
/** Who replied, first reply first, each once. */
|
|
131
|
+
authors: ThreadAuthor[];
|
|
132
|
+
/** The task started in these replies, if any, for a state chip on the root. */
|
|
133
|
+
taskSessionId: string | null;
|
|
134
|
+
};
|
|
135
|
+
/** The "N replies" line under a top-level message, or null when it has none. */
|
|
136
|
+
export declare function replySummary(messages: readonly ThreadMessage[], rootId: string): ReplySummary | null;
|
|
137
|
+
/**
|
|
138
|
+
* Pull Home's list down past the refresh to start a thread. Distances in
|
|
139
|
+
* points (iOS) or CSS pixels (web). A normal refresh fires well before the
|
|
140
|
+
* first; the second arms the thread, and releasing then opens it.
|
|
141
|
+
*/
|
|
142
|
+
export declare const THREAD_PULL_HINT = 90;
|
|
143
|
+
export declare const THREAD_PULL_ARM = 150;
|
|
144
|
+
/** 0: nothing. 1: show "keep pulling". 2: armed, release starts a thread. */
|
|
145
|
+
export declare function threadPullStage(pull: number): 0 | 1 | 2;
|
|
146
|
+
//# sourceMappingURL=threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../src/threads.ts"],"names":[],"mappings":"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"}
|
package/dist/threads.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threads on the wire, and the rules every client draws them with.
|
|
3
|
+
*
|
|
4
|
+
* One owner for the server (src/threads.ts), iOS and the web app. A thread is
|
|
5
|
+
* people-first chat with no agent behind it; omg joins only on `@omg`, and a
|
|
6
|
+
* task it starts is drawn as a card whose state is decided by
|
|
7
|
+
* `taskCardState` below. Keeping that rule here is what stops the phone and
|
|
8
|
+
* the web from disagreeing about whether a task "needs you".
|
|
9
|
+
*/
|
|
10
|
+
export const TASK_STATE_LABEL = {
|
|
11
|
+
working: "Working",
|
|
12
|
+
"needs-you": "Needs you",
|
|
13
|
+
done: "Done",
|
|
14
|
+
failed: "Failed",
|
|
15
|
+
ended: "Ended",
|
|
16
|
+
};
|
|
17
|
+
/** Only an explicit mention wakes omg. An address like x@omg.dev does not. */
|
|
18
|
+
export const OMG_MENTION = /(^|[^\w@])@omg\b/i;
|
|
19
|
+
export function mentionsOmg(text) {
|
|
20
|
+
return OMG_MENTION.test(text);
|
|
21
|
+
}
|
|
22
|
+
/** The same id in either form: a full uuid or a short prefix. */
|
|
23
|
+
export function sameSession(a, b) {
|
|
24
|
+
if (!a || !b)
|
|
25
|
+
return false;
|
|
26
|
+
const x = a.toLowerCase();
|
|
27
|
+
const y = b.toLowerCase();
|
|
28
|
+
return x === y || (x.length >= 8 && y.startsWith(x)) || (y.length >= 8 && x.startsWith(y));
|
|
29
|
+
}
|
|
30
|
+
/** The newest event omg posted for a task. */
|
|
31
|
+
export function latestTaskEvent(messages, sessionId) {
|
|
32
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
33
|
+
const task = messages[i].task;
|
|
34
|
+
if (task && sameSession(task.sessionId, sessionId))
|
|
35
|
+
return task.event;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A question waiting on the person wins over everything but a running turn.
|
|
41
|
+
* Then the live row: busy is working. An idle task is done once it has
|
|
42
|
+
* reported and working until then; a task gone from the list is its last
|
|
43
|
+
* report, or "ended".
|
|
44
|
+
*/
|
|
45
|
+
export function taskCardState(input) {
|
|
46
|
+
const waiting = input.openAsk || input.row?.status === "blocked" || input.event === "blocked";
|
|
47
|
+
if (waiting && !input.row?.busy)
|
|
48
|
+
return "needs-you";
|
|
49
|
+
if (input.row?.busy)
|
|
50
|
+
return "working";
|
|
51
|
+
if (input.event === "failed")
|
|
52
|
+
return "failed";
|
|
53
|
+
if (input.event === "finished")
|
|
54
|
+
return "done";
|
|
55
|
+
if (input.row && !input.row.ended)
|
|
56
|
+
return "working";
|
|
57
|
+
return "ended";
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Which messages draw a card. Each task is drawn once, at the message that
|
|
61
|
+
* started it; later messages about the same task are plain omg messages,
|
|
62
|
+
* because the card above already shows the live state.
|
|
63
|
+
*/
|
|
64
|
+
export function cardMessageIds(messages) {
|
|
65
|
+
const seen = new Set();
|
|
66
|
+
const ids = new Set();
|
|
67
|
+
for (const message of messages) {
|
|
68
|
+
const task = message.task;
|
|
69
|
+
if (!task)
|
|
70
|
+
continue;
|
|
71
|
+
const key = task.sessionId.toLowerCase();
|
|
72
|
+
if (seen.has(key))
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(key);
|
|
75
|
+
ids.add(message.id);
|
|
76
|
+
}
|
|
77
|
+
return ids;
|
|
78
|
+
}
|
|
79
|
+
/** One line for a thread row: who spoke last, and what they said. */
|
|
80
|
+
export function threadPreview(thread) {
|
|
81
|
+
const last = thread.lastMessage;
|
|
82
|
+
if (!last)
|
|
83
|
+
return "No messages yet";
|
|
84
|
+
const who = last.author.kind === "omg" ? "omg" : last.author.name;
|
|
85
|
+
return `${who}: ${last.text.replace(/\s+/g, " ").trim()}`;
|
|
86
|
+
}
|
|
87
|
+
/** The task a message is about, as the card needs it. Pure, for both clients. */
|
|
88
|
+
export function taskCardFor(message, detail, messages, openAskSessionIds) {
|
|
89
|
+
const task = message.task;
|
|
90
|
+
if (!task)
|
|
91
|
+
return null;
|
|
92
|
+
const row = detail.tasks.find((t) => sameSession(t.sessionId, task.sessionId));
|
|
93
|
+
return {
|
|
94
|
+
sessionId: task.sessionId,
|
|
95
|
+
title: row?.title || task.title || "Task",
|
|
96
|
+
project: row?.project || task.project || null,
|
|
97
|
+
state: taskCardState({
|
|
98
|
+
event: latestTaskEvent(messages, task.sessionId),
|
|
99
|
+
row,
|
|
100
|
+
openAsk: openAskSessionIds.some((id) => sameSession(task.sessionId, id)),
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Slack's rule: a message joins the one above when the same author wrote it within this long. */
|
|
105
|
+
export const THREAD_GROUP_MS = 5 * 60_000;
|
|
106
|
+
/**
|
|
107
|
+
* Whether a message starts a new group: its own avatar, name and time. The
|
|
108
|
+
* rest of a group is just text under the first message.
|
|
109
|
+
*/
|
|
110
|
+
export function startsMessageGroup(previous, message) {
|
|
111
|
+
if (!previous)
|
|
112
|
+
return true;
|
|
113
|
+
if (message.ts - previous.ts > THREAD_GROUP_MS)
|
|
114
|
+
return true;
|
|
115
|
+
if (previous.author.kind !== message.author.kind)
|
|
116
|
+
return true;
|
|
117
|
+
if (message.author.kind === "human" && previous.author.kind === "human") {
|
|
118
|
+
return previous.author.participantId !== message.author.participantId;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
/** A stable avatar colour for a person, from their participant id. */
|
|
123
|
+
export function authorHue(author) {
|
|
124
|
+
if (author.kind === "omg")
|
|
125
|
+
return 11;
|
|
126
|
+
let hash = 0;
|
|
127
|
+
for (const char of author.participantId)
|
|
128
|
+
hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
|
|
129
|
+
return hash % 360;
|
|
130
|
+
}
|
|
131
|
+
export function authorName(author) {
|
|
132
|
+
return author.kind === "omg" ? "omg" : author.name;
|
|
133
|
+
}
|
|
134
|
+
/** Top-level messages: what the main list shows. */
|
|
135
|
+
export function topLevelMessages(messages) {
|
|
136
|
+
return messages.filter((message) => !message.replyTo);
|
|
137
|
+
}
|
|
138
|
+
/** The replies to one top-level message, oldest first. */
|
|
139
|
+
export function repliesTo(messages, rootId) {
|
|
140
|
+
return messages.filter((message) => message.replyTo === rootId);
|
|
141
|
+
}
|
|
142
|
+
/** The "N replies" line under a top-level message, or null when it has none. */
|
|
143
|
+
export function replySummary(messages, rootId) {
|
|
144
|
+
const replies = repliesTo(messages, rootId);
|
|
145
|
+
if (!replies.length)
|
|
146
|
+
return null;
|
|
147
|
+
const authors = [];
|
|
148
|
+
for (const reply of replies) {
|
|
149
|
+
const same = authors.some((a) => a.kind === reply.author.kind &&
|
|
150
|
+
(a.kind === "omg" || (reply.author.kind === "human" && a.participantId === reply.author.participantId)));
|
|
151
|
+
if (!same)
|
|
152
|
+
authors.push(reply.author);
|
|
153
|
+
}
|
|
154
|
+
const task = [...replies].reverse().find((reply) => reply.task)?.task ?? null;
|
|
155
|
+
return { count: replies.length, lastTs: replies[replies.length - 1].ts, authors, taskSessionId: task?.sessionId ?? null };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Pull Home's list down past the refresh to start a thread. Distances in
|
|
159
|
+
* points (iOS) or CSS pixels (web). A normal refresh fires well before the
|
|
160
|
+
* first; the second arms the thread, and releasing then opens it.
|
|
161
|
+
*/
|
|
162
|
+
export const THREAD_PULL_HINT = 90;
|
|
163
|
+
export const THREAD_PULL_ARM = 150;
|
|
164
|
+
/** 0: nothing. 1: show "keep pulling". 2: armed, release starts a thread. */
|
|
165
|
+
export function threadPullStage(pull) {
|
|
166
|
+
if (pull >= THREAD_PULL_ARM)
|
|
167
|
+
return 2;
|
|
168
|
+
if (pull >= THREAD_PULL_HINT)
|
|
169
|
+
return 1;
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=threads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads.js","sourceRoot":"","sources":["../src/threads.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiEH,MAAM,CAAC,MAAM,gBAAgB,GAAkC;IAC7D,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,WAAW;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAE/C,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,WAAW,CAAC,CAA4B,EAAE,CAA4B;IACpF,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,eAAe,CAAC,QAAkC,EAAE,SAAiB;IACnF,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9B,IAAI,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;IACxE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAI7B;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC;IAC9F,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI;QAAE,OAAO,WAAW,CAAC;IACpD,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IACpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAkC;IAC/D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,MAA0C;IACtE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,iBAAiB,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAClE,OAAO,GAAG,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,WAAW,CACzB,OAAsB,EACtB,MAAmC,EACnC,QAAkC,EAClC,iBAAyD;IAEzD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/E,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM;QACzC,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI;QAC7C,KAAK,EAAE,aAAa,CAAC;YACnB,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;YAChD,GAAG;YACH,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;SACzE,CAAC;KACH,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,MAAM,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAmC,EAAE,OAAsB;IAC5F,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC,EAAE,GAAG,eAAe;QAAE,OAAO,IAAI,CAAC;IAC5D,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9D,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACxE,OAAO,QAAQ,CAAC,MAAM,CAAC,aAAa,KAAK,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,SAAS,CAAC,MAAoB;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,aAAa;QAAE,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACvF,OAAO,IAAI,GAAG,GAAG,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,OAAO,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,QAAkC;IACjE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,SAAS,CAAC,QAAkC,EAAE,MAAc;IAC1E,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;AAClE,CAAC;AAWD,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,QAAkC,EAAE,MAAc;IAC7E,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9B,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI;YAC5B,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,aAAa,KAAK,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QAC3G,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IAC9E,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC;AAC5H,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,IAAI,IAAI,eAAe;QAAE,OAAO,CAAC,CAAC;IACtC,IAAI,IAAI,IAAI,gBAAgB;QAAE,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
|