diff --git a/src/packages/frontend/chat/actions.ts b/src/packages/frontend/chat/actions.ts index 5921686c703..d921cfa7304 100644 --- a/src/packages/frontend/chat/actions.ts +++ b/src/packages/frontend/chat/actions.ts @@ -90,9 +90,7 @@ export class ChatActions extends Actions { }; toggleFoldThread = (reply_to: Date, messageIndex?: number) => { - if (this.syncdb == null) { - return; - } + if (this.syncdb == null) return; const account_id = this.redux.getStore("account").get_account_id(); const cur = this.syncdb.get_one({ event: "chat", date: reply_to }); const folding = cur?.get("folding") ?? List([]); @@ -113,6 +111,29 @@ export class ChatActions extends Actions { } }; + foldAllThreads = (onlyLLM = true) => { + if (this.syncdb == null || this.store == null) return; + const messages = this.store.get("messages"); + if (messages == null) return; + const account_id = this.redux.getStore("account").get_account_id(); + for (const [_timestamp, message] of messages) { + // ignore replies + if (message.get("reply_to") != null) continue; + const date = message.get("date"); + if (!(date instanceof Date)) continue; + const isLLMThread = this.isLanguageModelThread(date) !== false; + if (onlyLLM && !isLLMThread) continue; + const folding = message?.get("folding") ?? List([]); + const folded = folding.includes(account_id); + if (!folded) { + this.syncdb.set({ + folding: folding.push(account_id), + date, + }); + } + } + }; + feedback = (message: ChatMessageTyped, feedback: Feedback | null) => { if (this.syncdb == null) return; const date = message.get("date"); @@ -479,6 +500,7 @@ export class ChatActions extends Actions { scrollToDate: null, }); }; + scrollToIndex = (index: number = -1) => { if (this.syncdb == null) return; // we first clear, then set it, since scroll to needs to diff --git a/src/packages/frontend/chat/chat-log.tsx b/src/packages/frontend/chat/chat-log.tsx index 1a316927575..1c859cdf8c7 100644 --- a/src/packages/frontend/chat/chat-log.tsx +++ b/src/packages/frontend/chat/chat-log.tsx @@ -7,15 +7,19 @@ Render all the messages in the chat. */ +// cSpell:ignore: timespan + import { Alert, Button } from "antd"; import { Set as immutableSet } from "immutable"; import { MutableRefObject, useEffect, useMemo, useRef } from "react"; import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; + import { chatBotName, isChatBot } from "@cocalc/frontend/account/chatbot"; import { useRedux, useTypedRedux } from "@cocalc/frontend/app-framework"; import { Icon } from "@cocalc/frontend/components"; import useVirtuosoScrollHook from "@cocalc/frontend/components/virtuoso-scroll-hook"; import { HashtagBar } from "@cocalc/frontend/editors/task-editor/hashtag-bar"; +import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list"; import { cmp, hoursToTimeIntervalHuman, @@ -24,12 +28,21 @@ import { } from "@cocalc/util/misc"; import type { ChatActions } from "./actions"; import Composing from "./composing"; -import Message from "./message"; -import type { ChatMessageTyped, ChatMessages, Mode } from "./types"; -import { getSelectedHashtagsSearch, newest_content } from "./utils"; -import { getRootMessage, getThreadRootDate } from "./utils"; -import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list"; import { filterMessages } from "./filter-messages"; +import Message from "./message"; +import type { + ChatMessageTyped, + ChatMessages, + CostEstimate, + Mode, + NumChildren, +} from "./types"; +import { + getRootMessage, + getSelectedHashtagsSearch, + getThreadRootDate, + newest_content, +} from "./utils"; interface Props { project_id: string; // used to render links more effectively @@ -83,7 +96,7 @@ export function ChatLog({ } = useMemo<{ dates: string[]; numFolded: number; - numChildren; + numChildren: NumChildren; }>(() => { const { dates, numFolded, numChildren } = getSortedDates( messages, @@ -288,10 +301,7 @@ function isPrevMessageSender( ); } -function isThread( - message: ChatMessageTyped, - numChildren: { [date: number]: number }, -) { +function isThread(message: ChatMessageTyped, numChildren: NumChildren) { if (message.get("reply_to") != null) { return true; } @@ -324,7 +334,7 @@ export function getSortedDates( ): { dates: string[]; numFolded: number; - numChildren: { [date: number]: number }; + numChildren: NumChildren; } { let numFolded = 0; let m = messages; @@ -342,7 +352,7 @@ export function getSortedDates( // Do a linear pass through all messages to divide into threads, so that // getSortedDates is O(n) instead of O(n^2) ! - const numChildren: { [date: number]: number } = {}; + const numChildren: NumChildren = {}; for (const [_, message] of m) { const parent = message.get("reply_to"); if (parent != null) { @@ -486,22 +496,21 @@ export function MessageList({ selectedDate, numChildren, }: { - messages; - account_id; + messages: ChatMessages; + account_id: string; user_map; mode; sortedDates; virtuosoRef?; - search?; - project_id?; - path?; - fontSize?; + project_id?: string; + path?: string; + fontSize?: number; selectedHashtags?; actions?; - costEstimate?; + costEstimate?: CostEstimate; manualScrollRef?; selectedDate?: string; - numChildren?; + numChildren?: NumChildren; }) { const virtuosoHeightsRef = useRef<{ [index: number]: number }>({}); const virtuosoScroll = useVirtuosoScrollHook({ diff --git a/src/packages/frontend/chat/chatroom.tsx b/src/packages/frontend/chat/chatroom.tsx index 227058b2936..4212e4a0872 100644 --- a/src/packages/frontend/chat/chatroom.tsx +++ b/src/packages/frontend/chat/chatroom.tsx @@ -5,6 +5,8 @@ import { Button, Divider, Input, Select, Space, Tooltip } from "antd"; import { debounce } from "lodash"; +import { FormattedMessage } from "react-intl"; + import { ButtonGroup, Col, Row, Well } from "@cocalc/frontend/antd-bootstrap"; import { React, @@ -18,16 +20,16 @@ import { Icon, Loading } from "@cocalc/frontend/components"; import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown"; import { FrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context"; import { hoursToTimeIntervalHuman } from "@cocalc/util/misc"; -import { FormattedMessage } from "react-intl"; import type { ChatActions } from "./actions"; -import type { ChatState } from "./store"; import { ChatLog } from "./chat-log"; +import Filter from "./filter"; +import { FoldAllThreads } from "./fold-threads"; import ChatInput from "./input"; import { LLMCostEstimationChat } from "./llm-cost-estimation"; +import type { ChatState } from "./store"; import { SubmitMentionsFn } from "./types"; import { INPUT_HEIGHT, markChatAsReadIfUnseen } from "./utils"; import VideoChatButton from "./video/launch-button"; -import Filter from "./filter"; const FILTER_RECENT_NONE = { value: 0, @@ -68,7 +70,7 @@ interface Props { project_id: string; path: string; is_visible?: boolean; - font_size: number; + fontSize: number; desc?; } @@ -77,7 +79,7 @@ export function ChatRoom({ project_id, path, is_visible, - font_size, + fontSize, desc, }: Props) { const useEditor = useEditorRedux({ project_id, path }); @@ -261,6 +263,7 @@ export function ChatRoom({ {render_video_chat_button()} + ); } @@ -285,7 +288,7 @@ export function ChatRoom({ path={path} scrollToBottomRef={scrollToBottomRef} mode={"standalone"} - fontSize={font_size} + fontSize={fontSize} search={search} filterRecentH={filterRecentH} selectedHashtags={selectedHashtags} @@ -304,7 +307,7 @@ export function ChatRoom({ }} > + + + ); +} diff --git a/src/packages/frontend/chat/llm-cost-estimation.tsx b/src/packages/frontend/chat/llm-cost-estimation.tsx index 385c7091824..b2c52fb9461 100644 --- a/src/packages/frontend/chat/llm-cost-estimation.tsx +++ b/src/packages/frontend/chat/llm-cost-estimation.tsx @@ -7,13 +7,14 @@ import { ESTIMATION_HELP_TEXT, MODEL_FREE_TO_USE, } from "@cocalc/frontend/misc/llm-cost-estimation"; +import type { CostEstimate } from "./types"; export function LLMCostEstimationChat({ costEstimate, compact, style, }: { - costEstimate?: { min: number; max: number } | null; + costEstimate?: CostEstimate; compact: boolean; // only mean is shown style?: CSS; }) { diff --git a/src/packages/frontend/chat/llm-msg-summarize.tsx b/src/packages/frontend/chat/llm-msg-summarize.tsx index bb602e781e4..17cbf6d3a17 100644 --- a/src/packages/frontend/chat/llm-msg-summarize.tsx +++ b/src/packages/frontend/chat/llm-msg-summarize.tsx @@ -7,7 +7,7 @@ import { Button, Collapse, Switch } from "antd"; import { useLanguageModelSetting } from "@cocalc/frontend/account/useLanguageModelSetting"; import { useAsyncEffect, useState } from "@cocalc/frontend/app-framework"; -import { Icon, Paragraph, RawPrompt } from "@cocalc/frontend/components"; +import { Icon, Paragraph, RawPrompt, Tip } from "@cocalc/frontend/components"; import AIAvatar from "@cocalc/frontend/components/ai-avatar"; import PopconfirmKeyboard from "@cocalc/frontend/components/popconfirm-keyboard"; import LLMSelector, { @@ -111,9 +111,14 @@ export function SummarizeThread({ onConfirm={() => actions?.summarizeThread({ model, reply_to, short })} okText="Summarize" > - + + + ); } diff --git a/src/packages/frontend/chat/message.tsx b/src/packages/frontend/chat/message.tsx index 5e04f4be331..22b718b22e0 100644 --- a/src/packages/frontend/chat/message.tsx +++ b/src/packages/frontend/chat/message.tsx @@ -3,10 +3,13 @@ * License: MS-RSL – see LICENSE.md for details */ -import { Badge, Button, Col, Popconfirm, Row, Space, Tooltip } from "antd"; +// cSpell:ignore blankcolumn + +import { Badge, Button, Col, Popconfirm, Row, Space } from "antd"; import { List, Map } from "immutable"; import { CSSProperties, useEffect, useLayoutEffect } from "react"; import { useIntl } from "react-intl"; + import { Avatar } from "@cocalc/frontend/account/avatar/avatar"; import { CSS, @@ -55,14 +58,14 @@ const BORDER = "2px solid #ccc"; const SHOW_EDIT_BUTTON_MS = 15000; -const TRHEAD_STYLE_SINGLE: CSS = { +const THREAD_STYLE_SINGLE: CSS = { marginLeft: "15px", marginRight: "15px", paddingLeft: "15px", } as const; const THREAD_STYLE: CSS = { - ...TRHEAD_STYLE_SINGLE, + ...THREAD_STYLE_SINGLE, borderLeft: BORDER, borderRight: BORDER, } as const; @@ -102,7 +105,7 @@ interface Props { user_map?: Map; project_id?: string; // improves relative links if given path?: string; - font_size: number; + font_size?: number; is_prev_sender?: boolean; show_avatar?: boolean; mode: Mode; @@ -180,6 +183,8 @@ export default function Message({ return message?.get("date")?.valueOf() ?? 0; }, [message.get("date")]); + const showEditButton = Date.now() - date < SHOW_EDIT_BUTTON_MS; + const generating = message.get("generating"); const history_size = useMemo( @@ -252,7 +257,7 @@ export default function Message({ } }, [replying]); - function editing_status(is_editing: boolean) { + function render_editing_status(is_editing: boolean) { let text; let other_editors = // @ts-ignore -- keySeq *is* a method of TypedMap @@ -380,163 +385,264 @@ export default function Message({ ); } - function contentColumn() { - let marginTop; - let value = newest_content(message); + function renderEditControlRow() { + if (isEditing) { + return null; + } + const showDeleteButton = + DELETE_BUTTON && newest_content(message).trim().length > 0; + const showEditingStatus = + (message.get("history")?.size ?? 0) > 1 || + (message.get("editing")?.size ?? 0) > 0; + const showHistory = (message.get("history")?.size ?? 0) > 1; + const showLLMFeedback = isLLMThread && msgWrittenByLLM; + + // Show the bottom line of the message -- this uses a LOT of extra + // vertical space, so only do it if there is a good reason to. + // Getting rid of this might be nice. + const show = + showEditButton || + showDeleteButton || + showEditingStatus || + showHistory || + showLLMFeedback; + if (!show) { + // important to explicitly check this before rendering below, since otherwise we get a big BLANK space. + return null; + } - const { background, color, lighten, message_class } = message_colors( - account_id, - message, + return ( +
+ + {showEditButton ? ( + + Edit this message. You can edit any past message at any + time by double clicking on it. Fix other people's typos. All + versions are stored. + + } + placement="left" + > + + + ) : undefined} + {showDeleteButton && ( + + { + actions?.setEditing(message, true); + setTimeout(() => actions?.sendEdit(message, ""), 1); + }} + > + + + + )} + {showEditingStatus && render_editing_status(isEditing)} + {showHistory && ( + + )} + {showLLMFeedback && ( + <> + + + + )} + +
); + } - if (!is_prev_sender && is_viewers_message) { - marginTop = MARGIN_TOP_VIEWER; - } else { - marginTop = "5px"; - } - - const message_style: CSSProperties = { - color, - background, - wordWrap: "break-word", - borderRadius: "5px", - marginTop, - fontSize: `${font_size}px`, - // no padding on bottom, since message itself is markdown, hence - // wrapped in

's, which have a big 10px margin on their bottoms - // already. - padding: selected ? "6px 6px 0 6px" : "9px 9px 0 9px", - ...(mode === "sidechat" - ? { marginLeft: "5px", marginRight: "5px" } - : undefined), - ...(selected ? { border: "3px solid #66bb6a" } : undefined), - maxHeight: is_folded ? "100px" : undefined, - overflowY: is_folded ? "auto" : undefined, - } as const; + function renderMessageBody({ lighten, message_class }) { + const value = newest_content(message); - const mainXS = mode === "standalone" ? 20 : 22; - const showEditButton = Date.now() - date < SHOW_EDIT_BUTTON_MS; const feedback = message.getIn(["feedback", account_id]); const otherFeedback = - isLLMThread && msgWrittenByLLM ? 0 : (message.get("feedback")?.size ?? 0); + isLLMThread && msgWrittenByLLM ? 0 : message.get("feedback")?.size ?? 0; const showOtherFeedback = otherFeedback > 0; - const editControlRow = () => { - if (isEditing) { - return null; - } - const showDeleteButton = - DELETE_BUTTON && newest_content(message).trim().length > 0; - const showEditingStatus = - (message.get("history")?.size ?? 0) > 1 || - (message.get("editing")?.size ?? 0) > 0; - const showHistory = (message.get("history")?.size ?? 0) > 1; - const showLLMFeedback = isLLMThread && msgWrittenByLLM; - - // Show the bottom line of the message -- this uses a LOT of extra - // vertical space, so only do it if there is a good reason to. - // Getting rid of this might be nice. - const show = - showEditButton || - showDeleteButton || - showEditingStatus || - showHistory || - showLLMFeedback; - if (!show) { - // important to explicitly check this before rendering below, since otherwise we get a big BLANK space. - return null; - } - - return ( -

- - {showEditButton ? ( - + + - ) : undefined} - {showDeleteButton && ( - - { - actions?.setEditing(message, true); - setTimeout(() => actions?.sendEdit(message, ""), 1); + type={feedback ? "dashed" : "text"} + onClick={() => { + actions?.feedback(message, feedback ? null : "positive"); }} > - - - + /> + + )} - {showEditingStatus && editing_status(isEditing)} - {showHistory && ( + - )} - {showLLMFeedback && ( - <> - - - - )} + -
- ); - }; + + + actions?.setHashtagState( + tag, + selectedHashtags?.has(tag) ? undefined : 1, + ) + : undefined + } + /> + {renderEditControlRow()} + + ); + } + + function contentColumn() { + const mainXS = mode === "standalone" ? 20 : 22; + + const { background, color, lighten, message_class } = message_colors( + account_id, + message, + ); + + const marginTop = + !is_prev_sender && is_viewers_message ? MARGIN_TOP_VIEWER : "5px"; + + const messageStyle: CSSProperties = { + color, + background, + wordWrap: "break-word", + borderRadius: "5px", + marginTop, + fontSize: `${font_size}px`, + // no padding on bottom, since message itself is markdown, hence + // wrapped in

's, which have a big 10px margin on their bottoms + // already. + padding: selected ? "6px 6px 0 6px" : "9px 9px 0 9px", + ...(mode === "sidechat" + ? { marginLeft: "5px", marginRight: "5px" } + : undefined), + ...(selected ? { border: "3px solid #66bb6a" } : undefined), + } as const; return ( @@ -563,124 +669,31 @@ export default function Message({ ) : undefined}

- {!isEditing && ( - - - )} - {!isEditing && ( - - actions?.setHashtagState( - tag, - selectedHashtags?.has(tag) ? undefined : 1, - ) - : undefined - } - /> - )} - {isEditing && renderEditMessage()} - {editControlRow()} + {isEditing + ? renderEditMessage() + : renderMessageBody({ lighten, message_class })}
- {show_history && ( -
- - - -
- )} - {replying ? renderComposeReply() : undefined} + {renderHistory()} + {renderComposeReply()} ); } + function renderHistory() { + if (!show_history) return; + return ( +
+ + + +
+ ); + } + function saveEditedMessage(): void { if (actions == null) return; const mesg = @@ -757,11 +770,14 @@ export default function Message({ } function renderComposeReply() { + if (!replying) return; + if (project_id == null || path == null || actions?.syncdb == null) { // should never get into this position // when null. return; } + const replyDate = -getThreadRootDate({ date, messages }); let input; let moveCursorToEndOfLine = false; @@ -844,7 +860,7 @@ export default function Message({ return THREAD_STYLE_TOP; } } else { - return TRHEAD_STYLE_SINGLE; + return THREAD_STYLE_SINGLE; } } else if (allowReply) { return THREAD_STYLE_BOTTOM; @@ -877,7 +893,8 @@ export default function Message({ return (
- ) : undefined} - + {showAISummarize && is_thread ? ( ) : undefined} + {is_thread && ( + + + + )}
); } @@ -917,35 +955,34 @@ export default function Message({ return; } - let label; - if (numChildren) { - label = ( - <> - {numChildren} {plural(numChildren, "Reply", "Replies")} - - ); - } else { - label = "View Replies"; - } + const label = numChildren ? ( + <> + Show {numChildren + 1} {plural(numChildren + 1, "Message", "Messages")}… + + ) : ( + "View Messages…" + ); return ( -
+ -
+ ); } - function getThreadfoldOrBlank() { + function getThreadFoldOrBlank() { const xs = 2; if (is_thread_body || (!is_thread_body && !is_thread)) { return BLANK_COLUMN(xs); @@ -953,24 +990,26 @@ export default function Message({ const style: CSS = mode === "standalone" ? { - color: "#666", + color: COLORS.GRAY_M, marginTop: MARGIN_TOP_VIEWER, marginLeft: "5px", marginRight: "5px", } : { - color: "#666", + color: COLORS.GRAY_M, marginTop: "5px", width: "100%", textAlign: "center", }; - const iconname = is_folded + + const iconName = is_folded ? mode === "standalone" ? reverseRowOrdering ? "right-circle-o" : "left-circle-o" : "right-circle-o" : "down-circle-o"; + const button = ( + string; export type SubmitMentionsRef = MutableRefObject; + +export type NumChildren = { [date: number]: number }; + +export type CostEstimate = { min: number; max: number } | null; diff --git a/src/packages/frontend/chat/utils.ts b/src/packages/frontend/chat/utils.ts index 8d101359ad5..c47fb8283ae 100644 --- a/src/packages/frontend/chat/utils.ts +++ b/src/packages/frontend/chat/utils.ts @@ -42,7 +42,7 @@ export function compute_cursor_offset_position( mentions: MentionList, ) { let index_offset = 0; - let usuable_cursor_index = cursor_plain_text_index; + let usable_cursor_index = cursor_plain_text_index; const mention_array = mentions.toJS() as any; for (let i = 0; i < mention_array.length; i++) { @@ -60,19 +60,19 @@ export function compute_cursor_offset_position( index_offset = mention_offset + id.length + SINGLE_MENTION_OFFSET; } } else if (cursor_plain_text_index > plainTextIndex + display.length / 2) { - usuable_cursor_index = plainTextIndex + display.length; + usable_cursor_index = plainTextIndex + display.length; if (i == mention_array.length - 1) { // Cursor is inside the second half of the last mention. index_offset = mention_offset + id.length + SINGLE_MENTION_OFFSET; } } else if (cursor_plain_text_index <= plainTextIndex + display.length / 2) { // Cursor is inside the first half of this mention - usuable_cursor_index = plainTextIndex; + usable_cursor_index = plainTextIndex; index_offset = mention_offset; break; } } - return index_offset + usuable_cursor_index; + return index_offset + usable_cursor_index; } export function newest_content(message: ChatMessageTyped): string { diff --git a/src/packages/frontend/chat/viewer.tsx b/src/packages/frontend/chat/viewer.tsx index 06c21e0f2cf..1a7e7e9d040 100644 --- a/src/packages/frontend/chat/viewer.tsx +++ b/src/packages/frontend/chat/viewer.tsx @@ -2,17 +2,19 @@ Used for viewing a list of messages, e.g., in timetravel. */ -import { MessageList, getSortedDates } from "./chat-log"; -import { useTypedRedux } from "@cocalc/frontend/app-framework"; -import { useMemo } from "react"; import { Map as immutableMap } from "immutable"; +import { useMemo } from "react"; + +import type { Document } from "@cocalc/sync/editor/generic/types"; +import { useTypedRedux } from "@cocalc/frontend/app-framework"; +import { MessageList, getSortedDates } from "./chat-log"; import type { ChatMessages } from "./types"; export default function Viewer({ doc, font_size, }: { - doc; + doc: Document; font_size?: number; }) { const messages = useMemo(() => { diff --git a/src/packages/frontend/components/icon.tsx b/src/packages/frontend/components/icon.tsx index ae128f850a7..fdca3b1a16b 100644 --- a/src/packages/frontend/components/icon.tsx +++ b/src/packages/frontend/components/icon.tsx @@ -200,6 +200,7 @@ import { TagsFilled, TagsOutlined, TagsTwoTone, + ToTopOutlined, TeamOutlined, ThunderboltOutlined, ToolOutlined, @@ -631,6 +632,7 @@ const IconSpec = { "down-square-outlined": DownSquareOutlined, "merge-cells-outlined": MergeCellsOutlined, "fork-outlined": ForkOutlined, + "to-top-outlined": ToTopOutlined, } as const; // Icon Fonts coming from https://www.iconfont.cn/?lang=en-us diff --git a/src/packages/frontend/components/tip.tsx b/src/packages/frontend/components/tip.tsx index a12c2d425b2..f081b7ff052 100644 --- a/src/packages/frontend/components/tip.tsx +++ b/src/packages/frontend/components/tip.tsx @@ -21,7 +21,7 @@ type Size = "xsmall" | "small" | "medium" | "large"; type Trigger = "hover" | "focus" | "click" | "contextMenu"; interface Props { - title?: string | JSX.Element | JSX.Element[]; // not checked for update + title?: string | JSX.Element | JSX.Element[] | (() => JSX.Element); // not checked for update placement?: TooltipPlacement; tip?: string | JSX.Element | JSX.Element[]; // not checked for update size?: Size; // IMPORTANT: this is currently ignored -- see https://github.com/sagemathinc/cocalc/pull/4155 @@ -75,10 +75,12 @@ export const Tip: React.FC = React.memo((props: Props) => { } = props; function render_title() { - if (!icon) return title; + const renderedTitle = typeof title === "function" ? title() : title; + if (!renderedTitle) return null; + if (!icon) return renderedTitle; return ( - {title} + {renderedTitle} ); } diff --git a/src/packages/frontend/cspell.json b/src/packages/frontend/cspell.json index 6a1f0e1c9db..95a65f49642 100644 --- a/src/packages/frontend/cspell.json +++ b/src/packages/frontend/cspell.json @@ -33,8 +33,10 @@ "statsmodels", "syncdb", "syncdoc", + "syncdoc", "syncstring", "synctable", + "synctables", "tidyverse", "timetravel", "tolerations", @@ -43,6 +45,7 @@ ], "ignoreWords": [ "antd", + "collab", "immutablejs", "ipynb", "isdir", @@ -57,6 +60,7 @@ "Popconfirm", "PoweroffOutlined", "reuseinflight", + "sidechat", "vertexai", "vfill", "xsmall" diff --git a/src/packages/frontend/editors/slate/mostly-static-markdown.tsx b/src/packages/frontend/editors/slate/mostly-static-markdown.tsx index 448c78fc94c..d28872fc515 100644 --- a/src/packages/frontend/editors/slate/mostly-static-markdown.tsx +++ b/src/packages/frontend/editors/slate/mostly-static-markdown.tsx @@ -2,7 +2,7 @@ Mostly static markdown, but with some minimal dynamic editable content, e.g., checkboxes, and maybe some other nice features, but much less than a full slate editor! -This is used a lot in the fronend app, whereas the fully static one is used a lot in the next.js app. +This is used a lot in the frontend app, whereas the fully static one is used a lot in the next.js app. Extras include: @@ -59,7 +59,7 @@ interface Props { onChange?: (string) => void; // if given support some very minimal amount of editing, e.g., checkboxes; onChange is called with modified markdown. selectedHashtags?: Set; // assumed lower case! toggleHashtag?: (string) => void; - searchWords?: Set | string[]; // higlight text that matches anything in here + searchWords?: Set | string[]; // highlight text that matches anything in here } export default function MostlyStaticMarkdown({ diff --git a/src/packages/frontend/frame-editors/chat-editor/editor.ts b/src/packages/frontend/frame-editors/chat-editor/editor.ts index f7ca86b114a..8297003495c 100644 --- a/src/packages/frontend/frame-editors/chat-editor/editor.ts +++ b/src/packages/frontend/frame-editors/chat-editor/editor.ts @@ -8,12 +8,13 @@ Top-level react component for editing chat */ import { createElement } from "react"; + import { ChatRoom } from "@cocalc/frontend/chat/chatroom"; -import { set } from "@cocalc/util/misc"; import { createEditor } from "@cocalc/frontend/frame-editors/frame-tree/editor"; import type { EditorDescription } from "@cocalc/frontend/frame-editors/frame-tree/types"; import { terminal } from "@cocalc/frontend/frame-editors/terminal-editor/editor"; import { time_travel } from "@cocalc/frontend/frame-editors/time-travel-editor/editor"; +import { set } from "@cocalc/util/misc"; import { search } from "./search"; const chatroom: EditorDescription = { diff --git a/src/packages/frontend/frame-editors/code-editor/actions.ts b/src/packages/frontend/frame-editors/code-editor/actions.ts index de3e8036aa4..ce1442123ed 100644 --- a/src/packages/frontend/frame-editors/code-editor/actions.ts +++ b/src/packages/frontend/frame-editors/code-editor/actions.ts @@ -1134,7 +1134,7 @@ export class Actions< // need to check since this can get called by the close. if (!this._syncstring) return; // TODO: for now, just for the one syncstring obviously - // TOO: this is probably naive and slow too... + // TODO: this is probably naive and slow too... let cursors: Map>> = Map(); this._syncstring .get_cursors({ diff --git a/src/packages/frontend/frame-editors/frame-tree/commands/editor-menus.ts b/src/packages/frontend/frame-editors/frame-tree/commands/editor-menus.ts index d7716576c8a..4709f909e20 100644 --- a/src/packages/frontend/frame-editors/frame-tree/commands/editor-menus.ts +++ b/src/packages/frontend/frame-editors/frame-tree/commands/editor-menus.ts @@ -135,7 +135,7 @@ export function addEditorMenus({ const { children } = COMMANDS[name]; const cmdName = `${prefix}-${name}`; if (children == null) { - // everthing based entirely on spec object. + // everything based entirely on spec object. C[cmdName] = { ...cmd(name), ...COMMANDS[name], diff --git a/src/packages/frontend/frame-editors/time-travel-editor/viewer.tsx b/src/packages/frontend/frame-editors/time-travel-editor/viewer.tsx index ab453debf3c..02cdaf3b169 100644 --- a/src/packages/frontend/frame-editors/time-travel-editor/viewer.tsx +++ b/src/packages/frontend/frame-editors/time-travel-editor/viewer.tsx @@ -2,16 +2,16 @@ Render a document, where the rendering is determined by the file extension */ -import type { Document } from "@cocalc/sync/editor/generic/types"; +import ChatViewer from "@cocalc/frontend/chat/viewer"; import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown"; +import { TasksHistoryViewer } from "@cocalc/frontend/editors/task-editor/history-viewer"; +import { getScale } from "@cocalc/frontend/frame-editors/frame-tree/hooks"; +import Whiteboard from "@cocalc/frontend/frame-editors/whiteboard-editor/time-travel"; +import { HistoryViewer as JupyterHistoryViewer } from "@cocalc/frontend/jupyter/history-viewer"; +import type { Document } from "@cocalc/sync/editor/generic/types"; import { TextDocument } from "./document"; -import { TasksHistoryViewer } from "../../editors/task-editor/history-viewer"; -import { HistoryViewer as JupyterHistoryViewer } from "../../jupyter/history-viewer"; import { SagewsCodemirror } from "./sagews-codemirror"; -import Whiteboard from "@cocalc/frontend/frame-editors/whiteboard-editor/time-travel"; import { isObjectDoc } from "./view-document"; -import { getScale } from "@cocalc/frontend/frame-editors/frame-tree/hooks"; -import ChatViewer from "@cocalc/frontend/chat/viewer"; export const HAS_SPECIAL_VIEWER = new Set([ "tasks",