Make textAtom and showTocAtom in Markdown element optional (#331)

Fix backwards-compatibility for the Markdown element by adding back the option to pass text directly to the element and make atom parameters optional.
This commit is contained in:
Evan Simkowitz 2024-09-05 15:35:57 -07:00 committed by GitHub
parent fc5e53e476
commit 015ebf5dd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 28 additions and 28 deletions

View File

@ -8,7 +8,8 @@ import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import remarkGfm from "remark-gfm";
import { Atom, useAtomValue } from "jotai";
import { useAtomValueSafe } from "@/util/util";
import { Atom } from "jotai";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import RemarkFlexibleToc, { TocItem } from "remark-flexible-toc";
import { useHeight } from "../hook/useHeight";
@ -75,17 +76,18 @@ const CodeBlock = ({ children, onClickExecute }: CodeBlockProps) => {
};
type MarkdownProps = {
textAtom: Atom<string> | Atom<Promise<string>>;
showTocAtom: Atom<boolean>;
text?: string;
textAtom?: Atom<string> | Atom<Promise<string>>;
showTocAtom?: Atom<boolean>;
style?: React.CSSProperties;
className?: string;
onClickExecute?: (cmd: string) => void;
};
const Markdown = ({ textAtom, showTocAtom, style, className, onClickExecute }: MarkdownProps) => {
const text = useAtomValue(textAtom);
const Markdown = ({ text, textAtom, showTocAtom, style, className, onClickExecute }: MarkdownProps) => {
const textAtomValue = useAtomValueSafe(textAtom);
const tocRef = useRef<TocItem[]>([]);
const showToc = useAtomValue(showTocAtom);
const showToc = useAtomValueSafe(showTocAtom) ?? false;
const contentsRef = useRef<HTMLDivElement>(null);
const contentsHeight = useHeight(contentsRef, 200);
@ -133,6 +135,8 @@ const Markdown = ({ textAtom, showTocAtom, style, className, onClickExecute }: M
}
}, [showToc, tocRef]);
text = textAtomValue ?? text;
return (
<div className={clsx("markdown", className)} style={style} ref={contentsRef}>
<OverlayScrollbarsComponent

View File

@ -5,17 +5,18 @@ import { Modal } from "@/app/modals/modal";
import { Markdown } from "@/element/markdown";
import { modalsModel } from "@/store/modalmodel";
import * as keyutil from "@/util/keyutil";
import * as React from "react";
import { UserInputService } from "../store/services";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import "./userinputmodal.less";
const UserInputModal = (userInputRequest: UserInputRequest) => {
const [responseText, setResponseText] = React.useState("");
const [countdown, setCountdown] = React.useState(Math.floor(userInputRequest.timeoutms / 1000));
const checkboxStatus = React.useRef(false);
const [responseText, setResponseText] = useState("");
const [countdown, setCountdown] = useState(Math.floor(userInputRequest.timeoutms / 1000));
const checkboxStatus = useRef(false);
const queryTextAtom = useState;
const handleSendCancel = React.useCallback(() => {
const handleSendCancel = useCallback(() => {
UserInputService.SendUserInputResponse({
type: "userinputresp",
requestid: userInputRequest.requestid,
@ -24,7 +25,7 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
modalsModel.popModal();
}, [responseText, userInputRequest]);
const handleSendText = React.useCallback(() => {
const handleSendText = useCallback(() => {
UserInputService.SendUserInputResponse({
type: "userinputresp",
requestid: userInputRequest.requestid,
@ -34,7 +35,7 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
modalsModel.popModal();
}, [responseText, userInputRequest]);
const handleSendConfirm = React.useCallback(() => {
const handleSendConfirm = useCallback(() => {
UserInputService.SendUserInputResponse({
type: "userinputresp",
requestid: userInputRequest.requestid,
@ -44,7 +45,7 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
modalsModel.popModal();
}, [userInputRequest]);
const handleSubmit = React.useCallback(() => {
const handleSubmit = useCallback(() => {
switch (userInputRequest.responsetype) {
case "text":
handleSendText();
@ -55,7 +56,7 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
}
}, [handleSendConfirm, handleSendText, userInputRequest.responsetype]);
const handleKeyDown = React.useCallback(
const handleKeyDown = useCallback(
(waveEvent: WaveKeyboardEvent): boolean => {
if (keyutil.checkKeyPressed(waveEvent, "Escape")) {
handleSendCancel();
@ -69,14 +70,14 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
[handleSendCancel, handleSubmit]
);
const queryText = React.useMemo(() => {
const queryText = useMemo(() => {
if (userInputRequest.markdown) {
return <Markdown text={userInputRequest.querytext} className="userinput-markdown" />;
}
return <span className="userinput-text">{userInputRequest.querytext}</span>;
}, [userInputRequest.markdown, userInputRequest.querytext]);
const inputBox = React.useMemo(() => {
const inputBox = useMemo(() => {
if (userInputRequest.responsetype === "confirm") {
return <></>;
}
@ -93,7 +94,7 @@ const UserInputModal = (userInputRequest: UserInputRequest) => {
);
}, [userInputRequest.responsetype, userInputRequest.publictext, responseText, handleKeyDown, setResponseText]);
React.useEffect(() => {
useEffect(() => {
let timeout: ReturnType<typeof setTimeout>;
if (countdown == 0) {
timeout = setTimeout(() => {

View File

@ -180,8 +180,6 @@ Other useful metadata values to override block titles, icons, colors, themes, et
`;
const helpTextAtom = atom(helpText);
class HelpViewModel implements ViewModel {
viewType: string;
showTocAtom: PrimitiveAtom<boolean>;
@ -210,7 +208,7 @@ function makeHelpViewModel() {
}
function HelpView({ model }: { model: HelpViewModel }) {
return <Markdown textAtom={helpTextAtom} showTocAtom={model.showTocAtom} className="help-view" />;
return <Markdown text={helpText} showTocAtom={model.showTocAtom} className="help-view" />;
}
export { HelpView, HelpViewModel, makeHelpViewModel };

View File

@ -11,7 +11,7 @@ import { isBlank } from "@/util/util";
import { atom, Atom, PrimitiveAtom, useAtomValue, useSetAtom, WritableAtom } from "jotai";
import type { OverlayScrollbars } from "overlayscrollbars";
import { OverlayScrollbarsComponent, OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
import tinycolor from "tinycolor2";
import "./waveai.less";
@ -217,11 +217,8 @@ function makeWaveAiViewModel(blockId): WaveAiModel {
return waveAiModel;
}
const showTocAtomDummy = atom(false);
const ChatItem = ({ chatItem, itemCount }: ChatItemProps) => {
const { isAssistant, text, isError } = chatItem;
const textAtom = useMemo(() => atom(text), [text]);
const senderClassName = isAssistant ? "chat-msg-assistant" : "chat-msg-user";
const msgClassName = `chat-msg ${senderClassName}`;
const cssVar = "--panel-bg-color";
@ -242,7 +239,7 @@ const ChatItem = ({ chatItem, itemCount }: ChatItemProps) => {
<div className="chat-msg-header">
<i className="fa-sharp fa-solid fa-sparkles"></i>
</div>
<Markdown textAtom={textAtom} showTocAtom={showTocAtomDummy} />
<Markdown text={text} />
</>
) : (
<>
@ -258,7 +255,7 @@ const ChatItem = ({ chatItem, itemCount }: ChatItemProps) => {
<div className="chat-msg-header">
<i className="fa-sharp fa-solid fa-user"></i>
</div>
<Markdown className="msg-text" textAtom={textAtom} showTocAtom={showTocAtomDummy} />
<Markdown className="msg-text" text={text} />
</>
);
};

View File

@ -163,7 +163,7 @@ function jotaiLoadableValue<T>(value: Loadable<T>, def: T): T {
const NullAtom = atom(null);
function useAtomValueSafe<T>(atom: Atom<T>): T {
function useAtomValueSafe<T>(atom: Atom<T> | Atom<Promise<T>>): T {
if (atom == null) {
return useAtomValue(NullAtom) as T;
}