Skip to content

Commit c24dade

Browse files
committed
frontend: start working on more compact/hidden chat threads
1 parent 80401f0 commit c24dade

File tree

10 files changed

+79
-55
lines changed

10 files changed

+79
-55
lines changed

src/packages/frontend/chat/chat-log.tsx

+29-20
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@
77
Render all the messages in the chat.
88
*/
99

10+
// cSpell:ignore: timespan
11+
1012
import { Alert, Button } from "antd";
1113
import { Set as immutableSet } from "immutable";
1214
import { MutableRefObject, useEffect, useMemo, useRef } from "react";
1315
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
16+
1417
import { chatBotName, isChatBot } from "@cocalc/frontend/account/chatbot";
1518
import { useRedux, useTypedRedux } from "@cocalc/frontend/app-framework";
1619
import { Icon } from "@cocalc/frontend/components";
1720
import useVirtuosoScrollHook from "@cocalc/frontend/components/virtuoso-scroll-hook";
1821
import { HashtagBar } from "@cocalc/frontend/editors/task-editor/hashtag-bar";
22+
import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list";
1923
import {
2024
cmp,
2125
hoursToTimeIntervalHuman,
@@ -24,12 +28,21 @@ import {
2428
} from "@cocalc/util/misc";
2529
import type { ChatActions } from "./actions";
2630
import Composing from "./composing";
27-
import Message from "./message";
28-
import type { ChatMessageTyped, ChatMessages, Mode } from "./types";
29-
import { getSelectedHashtagsSearch, newest_content } from "./utils";
30-
import { getRootMessage, getThreadRootDate } from "./utils";
31-
import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list";
3231
import { filterMessages } from "./filter-messages";
32+
import Message from "./message";
33+
import type {
34+
ChatMessageTyped,
35+
ChatMessages,
36+
CostEstimate,
37+
Mode,
38+
NumChildren,
39+
} from "./types";
40+
import {
41+
getRootMessage,
42+
getSelectedHashtagsSearch,
43+
getThreadRootDate,
44+
newest_content,
45+
} from "./utils";
3346

3447
interface Props {
3548
project_id: string; // used to render links more effectively
@@ -83,7 +96,7 @@ export function ChatLog({
8396
} = useMemo<{
8497
dates: string[];
8598
numFolded: number;
86-
numChildren;
99+
numChildren: NumChildren;
87100
}>(() => {
88101
const { dates, numFolded, numChildren } = getSortedDates(
89102
messages,
@@ -288,10 +301,7 @@ function isPrevMessageSender(
288301
);
289302
}
290303

291-
function isThread(
292-
message: ChatMessageTyped,
293-
numChildren: { [date: number]: number },
294-
) {
304+
function isThread(message: ChatMessageTyped, numChildren: NumChildren) {
295305
if (message.get("reply_to") != null) {
296306
return true;
297307
}
@@ -324,7 +334,7 @@ export function getSortedDates(
324334
): {
325335
dates: string[];
326336
numFolded: number;
327-
numChildren: { [date: number]: number };
337+
numChildren: NumChildren;
328338
} {
329339
let numFolded = 0;
330340
let m = messages;
@@ -342,7 +352,7 @@ export function getSortedDates(
342352

343353
// Do a linear pass through all messages to divide into threads, so that
344354
// getSortedDates is O(n) instead of O(n^2) !
345-
const numChildren: { [date: number]: number } = {};
355+
const numChildren: NumChildren = {};
346356
for (const [_, message] of m) {
347357
const parent = message.get("reply_to");
348358
if (parent != null) {
@@ -486,22 +496,21 @@ export function MessageList({
486496
selectedDate,
487497
numChildren,
488498
}: {
489-
messages;
490-
account_id;
499+
messages: ChatMessages;
500+
account_id: string;
491501
user_map;
492502
mode;
493503
sortedDates;
494504
virtuosoRef?;
495-
search?;
496-
project_id?;
497-
path?;
498-
fontSize?;
505+
project_id?: string;
506+
path?: string;
507+
fontSize?: number;
499508
selectedHashtags?;
500509
actions?;
501-
costEstimate?;
510+
costEstimate?: CostEstimate;
502511
manualScrollRef?;
503512
selectedDate?: string;
504-
numChildren?;
513+
numChildren?: NumChildren;
505514
}) {
506515
const virtuosoHeightsRef = useRef<{ [index: number]: number }>({});
507516
const virtuosoScroll = useVirtuosoScrollHook({

src/packages/frontend/chat/chatroom.tsx

+8-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import { Button, Divider, Input, Select, Space, Tooltip } from "antd";
77
import { debounce } from "lodash";
8+
import { FormattedMessage } from "react-intl";
9+
810
import { ButtonGroup, Col, Row, Well } from "@cocalc/frontend/antd-bootstrap";
911
import {
1012
React,
@@ -18,16 +20,15 @@ import { Icon, Loading } from "@cocalc/frontend/components";
1820
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
1921
import { FrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
2022
import { hoursToTimeIntervalHuman } from "@cocalc/util/misc";
21-
import { FormattedMessage } from "react-intl";
2223
import type { ChatActions } from "./actions";
23-
import type { ChatState } from "./store";
2424
import { ChatLog } from "./chat-log";
25+
import Filter from "./filter";
2526
import ChatInput from "./input";
2627
import { LLMCostEstimationChat } from "./llm-cost-estimation";
28+
import type { ChatState } from "./store";
2729
import { SubmitMentionsFn } from "./types";
2830
import { INPUT_HEIGHT, markChatAsReadIfUnseen } from "./utils";
2931
import VideoChatButton from "./video/launch-button";
30-
import Filter from "./filter";
3132

3233
const FILTER_RECENT_NONE = {
3334
value: 0,
@@ -68,7 +69,7 @@ interface Props {
6869
project_id: string;
6970
path: string;
7071
is_visible?: boolean;
71-
font_size: number;
72+
fontSize: number;
7273
desc?;
7374
}
7475

@@ -77,7 +78,7 @@ export function ChatRoom({
7778
project_id,
7879
path,
7980
is_visible,
80-
font_size,
81+
fontSize,
8182
desc,
8283
}: Props) {
8384
const useEditor = useEditorRedux<ChatState>({ project_id, path });
@@ -285,7 +286,7 @@ export function ChatRoom({
285286
path={path}
286287
scrollToBottomRef={scrollToBottomRef}
287288
mode={"standalone"}
288-
fontSize={font_size}
289+
fontSize={fontSize}
289290
search={search}
290291
filterRecentH={filterRecentH}
291292
selectedHashtags={selectedHashtags}
@@ -304,7 +305,7 @@ export function ChatRoom({
304305
}}
305306
>
306307
<ChatInput
307-
fontSize={font_size}
308+
fontSize={fontSize}
308309
autoFocus
309310
cacheId={`${path}${project_id}-new`}
310311
input={input}

src/packages/frontend/chat/llm-cost-estimation.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import {
77
ESTIMATION_HELP_TEXT,
88
MODEL_FREE_TO_USE,
99
} from "@cocalc/frontend/misc/llm-cost-estimation";
10+
import type { CostEstimate } from "./types";
1011

1112
export function LLMCostEstimationChat({
1213
costEstimate,
1314
compact,
1415
style,
1516
}: {
16-
costEstimate?: { min: number; max: number } | null;
17+
costEstimate?: CostEstimate;
1718
compact: boolean; // only mean is shown
1819
style?: CSS;
1920
}) {

src/packages/frontend/chat/message.tsx

+15-12
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6+
// cSpell:ignore blankcolumn
7+
68
import { Badge, Button, Col, Popconfirm, Row, Space, Tooltip } from "antd";
79
import { List, Map } from "immutable";
810
import { CSSProperties, useEffect, useLayoutEffect } from "react";
911
import { useIntl } from "react-intl";
12+
1013
import { Avatar } from "@cocalc/frontend/account/avatar/avatar";
1114
import {
1215
CSS,
@@ -55,14 +58,14 @@ const BORDER = "2px solid #ccc";
5558

5659
const SHOW_EDIT_BUTTON_MS = 15000;
5760

58-
const TRHEAD_STYLE_SINGLE: CSS = {
61+
const THREAD_STYLE_SINGLE: CSS = {
5962
marginLeft: "15px",
6063
marginRight: "15px",
6164
paddingLeft: "15px",
6265
} as const;
6366

6467
const THREAD_STYLE: CSS = {
65-
...TRHEAD_STYLE_SINGLE,
68+
...THREAD_STYLE_SINGLE,
6669
borderLeft: BORDER,
6770
borderRight: BORDER,
6871
} as const;
@@ -102,7 +105,7 @@ interface Props {
102105
user_map?: Map<string, any>;
103106
project_id?: string; // improves relative links if given
104107
path?: string;
105-
font_size: number;
108+
font_size?: number;
106109
is_prev_sender?: boolean;
107110
show_avatar?: boolean;
108111
mode: Mode;
@@ -395,7 +398,7 @@ export default function Message({
395398
marginTop = "5px";
396399
}
397400

398-
const message_style: CSSProperties = {
401+
const messageStyle: CSSProperties = {
399402
color,
400403
background,
401404
wordWrap: "break-word",
@@ -418,7 +421,7 @@ export default function Message({
418421
const showEditButton = Date.now() - date < SHOW_EDIT_BUTTON_MS;
419422
const feedback = message.getIn(["feedback", account_id]);
420423
const otherFeedback =
421-
isLLMThread && msgWrittenByLLM ? 0 : (message.get("feedback")?.size ?? 0);
424+
isLLMThread && msgWrittenByLLM ? 0 : message.get("feedback")?.size ?? 0;
422425
const showOtherFeedback = otherFeedback > 0;
423426

424427
const editControlRow = () => {
@@ -563,7 +566,7 @@ export default function Message({
563566
) : undefined}
564567
</div>
565568
<div
566-
style={message_style}
569+
style={messageStyle}
567570
className="smc-chat-message"
568571
onDoubleClick={edit_message}
569572
>
@@ -844,7 +847,7 @@ export default function Message({
844847
return THREAD_STYLE_TOP;
845848
}
846849
} else {
847-
return TRHEAD_STYLE_SINGLE;
850+
return THREAD_STYLE_SINGLE;
848851
}
849852
} else if (allowReply) {
850853
return THREAD_STYLE_BOTTOM;
@@ -945,7 +948,7 @@ export default function Message({
945948
);
946949
}
947950

948-
function getThreadfoldOrBlank() {
951+
function getThreadFoldOrBlank() {
949952
const xs = 2;
950953
if (is_thread_body || (!is_thread_body && !is_thread)) {
951954
return BLANK_COLUMN(xs);
@@ -964,7 +967,7 @@ export default function Message({
964967
width: "100%",
965968
textAlign: "center",
966969
};
967-
const iconname = is_folded
970+
const iconName = is_folded
968971
? mode === "standalone"
969972
? reverseRowOrdering
970973
? "right-circle-o"
@@ -978,7 +981,7 @@ export default function Message({
978981
onClick={() => actions?.toggleFoldThread(message.get("date"), index)}
979982
icon={
980983
<Icon
981-
name={iconname}
984+
name={iconName}
982985
style={{ fontSize: mode === "standalone" ? "22px" : "18px" }}
983986
/>
984987
}
@@ -1027,14 +1030,14 @@ export default function Message({
10271030

10281031
switch (mode) {
10291032
case "standalone":
1030-
const cols = [avatar_column(), contentColumn(), getThreadfoldOrBlank()];
1033+
const cols = [avatar_column(), contentColumn(), getThreadFoldOrBlank()];
10311034
if (reverseRowOrdering) {
10321035
cols.reverse();
10331036
}
10341037
return cols;
10351038

10361039
case "sidechat":
1037-
return [getThreadfoldOrBlank(), contentColumn()];
1040+
return [getThreadFoldOrBlank(), contentColumn()];
10381041

10391042
default:
10401043
unreachable(mode);

src/packages/frontend/chat/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,7 @@ export type SubmitMentionsFn = (
8383
) => string;
8484

8585
export type SubmitMentionsRef = MutableRefObject<SubmitMentionsFn | undefined>;
86+
87+
export type NumChildren = { [date: number]: number };
88+
89+
export type CostEstimate = { min: number; max: number } | null;

src/packages/frontend/chat/viewer.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22
Used for viewing a list of messages, e.g., in timetravel.
33
*/
44

5-
import { MessageList, getSortedDates } from "./chat-log";
6-
import { useTypedRedux } from "@cocalc/frontend/app-framework";
7-
import { useMemo } from "react";
85
import { Map as immutableMap } from "immutable";
6+
import { useMemo } from "react";
7+
8+
import type { Document } from "@cocalc/sync/editor/generic/types";
9+
import { useTypedRedux } from "@cocalc/frontend/app-framework";
10+
import { MessageList, getSortedDates } from "./chat-log";
911
import type { ChatMessages } from "./types";
1012

1113
export default function Viewer({
1214
doc,
1315
font_size,
1416
}: {
15-
doc;
17+
doc: Document;
1618
font_size?: number;
1719
}) {
1820
const messages = useMemo<ChatMessages>(() => {

src/packages/frontend/cspell.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
"rtypes",
3636
"rclass",
3737
"ipython",
38-
"Miniterm"
38+
"Miniterm",
39+
"syncdoc",
40+
"synctables"
3941
],
4042
"ignoreWords": [
4143
"LLMs",
@@ -55,7 +57,8 @@
5557
"mintime",
5658
"PoweroffOutlined",
5759
"immutablejs",
58-
"reuseinflight"
60+
"reuseinflight",
61+
"sidechat"
5962
],
6063
"flagWords": [],
6164
"ignorePaths": ["node_modules/**", "dist/**", "dist-ts/**", "build/**"],

src/packages/frontend/frame-editors/chat-editor/editor.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ Top-level react component for editing chat
88
*/
99

1010
import { createElement } from "react";
11+
1112
import { ChatRoom } from "@cocalc/frontend/chat/chatroom";
12-
import { set } from "@cocalc/util/misc";
1313
import { createEditor } from "@cocalc/frontend/frame-editors/frame-tree/editor";
1414
import type { EditorDescription } from "@cocalc/frontend/frame-editors/frame-tree/types";
1515
import { terminal } from "@cocalc/frontend/frame-editors/terminal-editor/editor";
1616
import { time_travel } from "@cocalc/frontend/frame-editors/time-travel-editor/editor";
17+
import { set } from "@cocalc/util/misc";
1718
import { search } from "./search";
1819

1920
const chatroom: EditorDescription = {

0 commit comments

Comments
 (0)