mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-02 19:55:18 +02:00
refactor(mentions): consolidate sidebar document handling into mentionedDocumentsAtom and remove sidebarSelectedDocumentsAtom references
This commit is contained in:
parent
960f761c6c
commit
1427809119
5 changed files with 54 additions and 181 deletions
|
|
@ -24,7 +24,6 @@ import {
|
|||
mentionedDocumentIdsAtom,
|
||||
mentionedDocumentsAtom,
|
||||
messageDocumentsMapAtom,
|
||||
sidebarSelectedDocumentsAtom,
|
||||
} from "@/atoms/chat/mentioned-documents.atom";
|
||||
import {
|
||||
clearPlanOwnerRegistry,
|
||||
|
|
@ -216,12 +215,10 @@ export default function NewChatPage() {
|
|||
// Get disabled tools from the tool toggle UI
|
||||
const disabledTools = useAtomValue(disabledToolsAtom);
|
||||
|
||||
// Get mentioned document IDs from the composer (derived from @ mentions + sidebar selections)
|
||||
// Get mentioned document IDs from the composer.
|
||||
const mentionedDocumentIds = useAtomValue(mentionedDocumentIdsAtom);
|
||||
const mentionedDocuments = useAtomValue(mentionedDocumentsAtom);
|
||||
const sidebarDocuments = useAtomValue(sidebarSelectedDocumentsAtom);
|
||||
const setMentionedDocuments = useSetAtom(mentionedDocumentsAtom);
|
||||
const setSidebarDocuments = useSetAtom(sidebarSelectedDocumentsAtom);
|
||||
const setMessageDocumentsMap = useSetAtom(messageDocumentsMapAtom);
|
||||
const setCurrentThreadState = useSetAtom(currentThreadAtom);
|
||||
const setTargetCommentId = useSetAtom(setTargetCommentIdAtom);
|
||||
|
|
@ -319,7 +316,6 @@ export default function NewChatPage() {
|
|||
setCurrentThread(null);
|
||||
setMentionedDocuments([]);
|
||||
tokenUsageStore.clear();
|
||||
setSidebarDocuments([]);
|
||||
setMessageDocumentsMap({});
|
||||
clearPlanOwnerRegistry();
|
||||
closeReportPanel();
|
||||
|
|
@ -387,7 +383,6 @@ export default function NewChatPage() {
|
|||
urlChatId,
|
||||
setMessageDocumentsMap,
|
||||
setMentionedDocuments,
|
||||
setSidebarDocuments,
|
||||
closeReportPanel,
|
||||
closeEditorPanel,
|
||||
removeChatTab,
|
||||
|
|
@ -578,15 +573,14 @@ export default function NewChatPage() {
|
|||
messageLength: userQuery.length,
|
||||
});
|
||||
|
||||
// Combine @-mention chips + sidebar selections for display & persistence
|
||||
// Collect unique mentioned docs for display & persistence
|
||||
const allMentionedDocs: MentionedDocumentInfo[] = [];
|
||||
const seenDocKeys = new Set<string>();
|
||||
for (const doc of [...mentionedDocuments, ...sidebarDocuments]) {
|
||||
for (const doc of mentionedDocuments) {
|
||||
const key = `${doc.document_type}:${doc.id}`;
|
||||
if (!seenDocKeys.has(key)) {
|
||||
seenDocKeys.add(key);
|
||||
allMentionedDocs.push({ id: doc.id, title: doc.title, document_type: doc.document_type });
|
||||
}
|
||||
if (seenDocKeys.has(key)) continue;
|
||||
seenDocKeys.add(key);
|
||||
allMentionedDocs.push({ id: doc.id, title: doc.title, document_type: doc.document_type });
|
||||
}
|
||||
|
||||
if (allMentionedDocs.length > 0) {
|
||||
|
|
@ -689,7 +683,6 @@ export default function NewChatPage() {
|
|||
// Clear mentioned documents after capturing them
|
||||
if (hasDocumentIds || hasSurfsenseDocIds) {
|
||||
setMentionedDocuments([]);
|
||||
setSidebarDocuments([]);
|
||||
}
|
||||
|
||||
const response = await fetch(`${backendUrl}/api/v1/new_chat`, {
|
||||
|
|
@ -979,9 +972,7 @@ export default function NewChatPage() {
|
|||
messages,
|
||||
mentionedDocumentIds,
|
||||
mentionedDocuments,
|
||||
sidebarDocuments,
|
||||
setMentionedDocuments,
|
||||
setSidebarDocuments,
|
||||
setMessageDocumentsMap,
|
||||
setAgentCreatedDocuments,
|
||||
queryClient,
|
||||
|
|
|
|||
|
|
@ -10,33 +10,34 @@ import type { Document } from "@/contracts/types/document.types";
|
|||
export const mentionedDocumentsAtom = atom<Pick<Document, "id" | "title" | "document_type">[]>([]);
|
||||
|
||||
/**
|
||||
* Atom to store documents selected via the sidebar checkboxes / row clicks.
|
||||
* These power the selected-sources badge and backend doc filters.
|
||||
* Back-compat alias for sidebar checkbox selection.
|
||||
* This now points to mentionedDocumentsAtom so the app has a single source
|
||||
* of truth for mentioned/selected documents.
|
||||
*/
|
||||
export const sidebarSelectedDocumentsAtom = atom<
|
||||
Pick<Document, "id" | "title" | "document_type">[]
|
||||
>([]);
|
||||
|
||||
export interface SidebarMentionEvent {
|
||||
kind: "add" | "remove";
|
||||
docs: Pick<Document, "id" | "title" | "document_type">[];
|
||||
nonce: number;
|
||||
}
|
||||
Pick<Document, "id" | "title" | "document_type">[],
|
||||
[
|
||||
| Pick<Document, "id" | "title" | "document_type">[]
|
||||
| ((
|
||||
prev: Pick<Document, "id" | "title" | "document_type">[]
|
||||
) => Pick<Document, "id" | "title" | "document_type">[]),
|
||||
],
|
||||
void
|
||||
>(
|
||||
(get) => get(mentionedDocumentsAtom),
|
||||
(get, set, update) => {
|
||||
const prev = get(mentionedDocumentsAtom);
|
||||
const next = typeof update === "function" ? update(prev) : update;
|
||||
set(mentionedDocumentsAtom, next);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Event atom used to tell the composer that documents were selected/unselected
|
||||
* from sidebar checkboxes, so chips can be inserted/removed in-editor.
|
||||
*/
|
||||
export const sidebarMentionEventAtom = atom<SidebarMentionEvent | null>(null);
|
||||
|
||||
/**
|
||||
* Derived read-only atom that merges @-mention chips and sidebar selections
|
||||
* into a single deduplicated set of document IDs for the backend.
|
||||
* Derived read-only atom that maps deduplicated mentioned docs
|
||||
* into backend payload fields.
|
||||
*/
|
||||
export const mentionedDocumentIdsAtom = atom((get) => {
|
||||
const chipDocs = get(mentionedDocumentsAtom);
|
||||
const sidebarDocs = get(sidebarSelectedDocumentsAtom);
|
||||
const allDocs = [...chipDocs, ...sidebarDocs];
|
||||
const allDocs = get(mentionedDocumentsAtom);
|
||||
const seen = new Set<string>();
|
||||
const deduped = allDocs.filter((d) => {
|
||||
const key = `${d.document_type}:${d.id}`;
|
||||
|
|
|
|||
|
|
@ -11,25 +11,13 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { flushSync } from "react-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
|
||||
import type { Document } from "@/contracts/types/document.types";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
// Render a React element to an HTML string on the client without pulling
|
||||
// `react-dom/server` into the bundle. `createRoot` + `flushSync` use the
|
||||
// same `react-dom` package React itself imports, so this adds zero new
|
||||
// runtime weight.
|
||||
function renderElementToHTML(element: ReactElement): string {
|
||||
const container = document.createElement("div");
|
||||
const root = createRoot(container);
|
||||
flushSync(() => {
|
||||
root.render(element);
|
||||
});
|
||||
const html = container.innerHTML;
|
||||
root.unmount();
|
||||
return html;
|
||||
return renderToStaticMarkup(element);
|
||||
}
|
||||
|
||||
export interface MentionedDocument {
|
||||
|
|
@ -182,7 +170,7 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
editorRef.current.appendChild(document.createElement("br"));
|
||||
editorRef.current.appendChild(document.createElement("br"));
|
||||
setIsEmpty(false);
|
||||
onChange?.(initialText, Array.from(mentionedDocs.values()));
|
||||
onChange?.(initialText, initialDocuments);
|
||||
editorRef.current.focus();
|
||||
const sel = window.getSelection();
|
||||
const range = document.createRange();
|
||||
|
|
@ -194,7 +182,7 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
range.insertNode(anchor);
|
||||
anchor.scrollIntoView({ block: "end" });
|
||||
anchor.remove();
|
||||
}, [initialText]);
|
||||
}, [initialText, initialDocuments, onChange]);
|
||||
|
||||
// Focus at the end of the editor
|
||||
const focusAtEnd = useCallback(() => {
|
||||
|
|
@ -779,6 +767,7 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
{/* biome-ignore lint/a11y/noStaticElementInteractions: contenteditable mention editor requires a div for inline chips */}
|
||||
<div
|
||||
ref={editorRef}
|
||||
contentEditable={!disabled}
|
||||
|
|
@ -801,9 +790,6 @@ export const InlineMentionEditor = forwardRef<InlineMentionEditorRef, InlineMent
|
|||
)}
|
||||
style={{ wordBreak: "break-word" }}
|
||||
data-placeholder={placeholder}
|
||||
aria-label="Message input with inline mentions"
|
||||
role="textbox"
|
||||
aria-multiline="true"
|
||||
/>
|
||||
{/* Placeholder with fade animation on change */}
|
||||
{isEmpty && (
|
||||
|
|
|
|||
|
|
@ -38,12 +38,9 @@ import {
|
|||
import { chatSessionStateAtom } from "@/atoms/chat/chat-session-state.atom";
|
||||
import {
|
||||
mentionedDocumentsAtom,
|
||||
sidebarMentionEventAtom,
|
||||
sidebarSelectedDocumentsAtom,
|
||||
} from "@/atoms/chat/mentioned-documents.atom";
|
||||
import { connectorDialogOpenAtom } from "@/atoms/connector-dialog/connector-dialog.atoms";
|
||||
import { connectorsAtom } from "@/atoms/connectors/connector-query.atoms";
|
||||
import { documentsSidebarOpenAtom } from "@/atoms/documents/ui.atoms";
|
||||
import { membersAtom } from "@/atoms/members/members-query.atoms";
|
||||
import {
|
||||
globalNewLLMConfigsAtom,
|
||||
|
|
@ -336,8 +333,6 @@ const ClipboardChip: FC<{ text: string; onDismiss: () => void }> = ({ text, onDi
|
|||
const Composer: FC = () => {
|
||||
// Document mention state (atoms persist across component remounts)
|
||||
const [mentionedDocuments, setMentionedDocuments] = useAtom(mentionedDocumentsAtom);
|
||||
const setSidebarDocs = useSetAtom(sidebarSelectedDocumentsAtom);
|
||||
const [sidebarMentionEvent, setSidebarMentionEvent] = useAtom(sidebarMentionEventAtom);
|
||||
const [showDocumentPopover, setShowDocumentPopover] = useState(false);
|
||||
const [showPromptPicker, setShowPromptPicker] = useState(false);
|
||||
const [mentionQuery, setMentionQuery] = useState("");
|
||||
|
|
@ -578,7 +573,6 @@ const Composer: FC = () => {
|
|||
aui.composer().send();
|
||||
editorRef.current?.clear();
|
||||
setMentionedDocuments([]);
|
||||
setSidebarDocs([]);
|
||||
|
||||
// With turnAnchor="top", ViewportSlack adds min-height to the last
|
||||
// assistant message so that scrolling-to-bottom actually positions the
|
||||
|
|
@ -625,7 +619,6 @@ const Composer: FC = () => {
|
|||
clipboardInitialText,
|
||||
aui,
|
||||
setMentionedDocuments,
|
||||
setSidebarDocs,
|
||||
threadViewportStore,
|
||||
]);
|
||||
|
||||
|
|
@ -663,40 +656,29 @@ const Composer: FC = () => {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sidebarMentionEvent) return;
|
||||
const editor = editorRef.current;
|
||||
if (!editor) return;
|
||||
|
||||
const eventDocs = sidebarMentionEvent.docs;
|
||||
if (eventDocs.length === 0) {
|
||||
setSidebarMentionEvent(null);
|
||||
return;
|
||||
const toKey = (doc: { id: number; document_type?: string }) =>
|
||||
`${doc.document_type ?? "UNKNOWN"}:${doc.id}`;
|
||||
|
||||
const atomDocs = mentionedDocuments;
|
||||
const editorDocs = editor.getMentionedDocuments();
|
||||
const atomKeys = new Set(atomDocs.map(toKey));
|
||||
const editorKeys = new Set(editorDocs.map(toKey));
|
||||
|
||||
for (const doc of atomDocs) {
|
||||
if (!editorKeys.has(toKey(doc))) {
|
||||
editor.insertDocumentChip(doc, { removeTriggerText: false });
|
||||
}
|
||||
}
|
||||
|
||||
const docKey = (doc: Pick<Document, "id" | "title" | "document_type">) =>
|
||||
`${doc.document_type}:${doc.id}`;
|
||||
const mentionedKeys = new Set(mentionedDocuments.map(docKey));
|
||||
|
||||
if (sidebarMentionEvent.kind === "add") {
|
||||
const docsToAdd = eventDocs.filter((doc) => !mentionedKeys.has(docKey(doc)));
|
||||
for (const doc of docsToAdd) {
|
||||
editorRef.current?.insertDocumentChip(doc, { removeTriggerText: false });
|
||||
for (const doc of editorDocs) {
|
||||
if (!atomKeys.has(toKey(doc))) {
|
||||
editor.removeDocumentChip(doc.id, doc.document_type);
|
||||
}
|
||||
if (docsToAdd.length > 0) {
|
||||
setMentionedDocuments((prev) => {
|
||||
const existing = new Set(prev.map(docKey));
|
||||
const uniqueAdds = docsToAdd.filter((doc) => !existing.has(docKey(doc)));
|
||||
return uniqueAdds.length > 0 ? [...prev, ...uniqueAdds] : prev;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const removeKeys = new Set(eventDocs.map(docKey));
|
||||
for (const doc of eventDocs) {
|
||||
editorRef.current?.removeDocumentChip(doc.id, doc.document_type);
|
||||
}
|
||||
setMentionedDocuments((prev) => prev.filter((doc) => !removeKeys.has(docKey(doc))));
|
||||
}
|
||||
|
||||
setSidebarMentionEvent(null);
|
||||
}, [sidebarMentionEvent, mentionedDocuments, setMentionedDocuments, setSidebarMentionEvent]);
|
||||
}, [mentionedDocuments]);
|
||||
|
||||
return (
|
||||
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col gap-2">
|
||||
|
|
@ -775,8 +757,6 @@ interface ComposerActionProps {
|
|||
|
||||
const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false }) => {
|
||||
const mentionedDocuments = useAtomValue(mentionedDocumentsAtom);
|
||||
const sidebarDocs = useAtomValue(sidebarSelectedDocumentsAtom);
|
||||
const setDocumentsSidebarOpen = useSetAtom(documentsSidebarOpenAtom);
|
||||
const setConnectorDialogOpen = useSetAtom(connectorDialogOpenAtom);
|
||||
const [toolsPopoverOpen, setToolsPopoverOpen] = useState(false);
|
||||
const isDesktop = useMediaQuery("(min-width: 640px)");
|
||||
|
|
@ -1222,15 +1202,6 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
|||
</AnimatePresence>
|
||||
</button>
|
||||
)}
|
||||
{sidebarDocs.length > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setDocumentsSidebarOpen(true)}
|
||||
className="rounded-full border border-border/60 bg-accent/50 px-2.5 py-1 text-xs font-medium text-foreground/80 transition-colors hover:bg-accent"
|
||||
>
|
||||
{sidebarDocs.length} {sidebarDocs.length === 1 ? "source" : "sources"} selected
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{!hasModelConfigured && (
|
||||
<div className="flex items-center gap-1.5 text-amber-600 dark:text-amber-400 text-xs">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import type React from "react";
|
|||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
sidebarMentionEventAtom,
|
||||
sidebarSelectedDocumentsAtom,
|
||||
} from "@/atoms/chat/mentioned-documents.atom";
|
||||
import { connectorDialogOpenAtom } from "@/atoms/connector-dialog/connector-dialog.atoms";
|
||||
|
|
@ -416,7 +415,6 @@ function AuthenticatedDocumentsSidebarBase({
|
|||
const { mutateAsync: deleteDocumentMutation } = useAtomValue(deleteDocumentMutationAtom);
|
||||
|
||||
const [sidebarDocs, setSidebarDocs] = useAtom(sidebarSelectedDocumentsAtom);
|
||||
const setSidebarMentionEvent = useSetAtom(sidebarMentionEventAtom);
|
||||
const mentionedDocIds = useMemo(() => new Set(sidebarDocs.map((d) => d.id)), [sidebarDocs]);
|
||||
|
||||
// Folder state
|
||||
|
|
@ -864,17 +862,6 @@ function AuthenticatedDocumentsSidebarBase({
|
|||
const key = `${doc.document_type}:${doc.id}`;
|
||||
if (isMentioned) {
|
||||
setSidebarDocs((prev) => prev.filter((d) => `${d.document_type}:${d.id}` !== key));
|
||||
setSidebarMentionEvent({
|
||||
kind: "remove",
|
||||
docs: [
|
||||
{
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
document_type: doc.document_type as DocumentTypeEnum,
|
||||
},
|
||||
],
|
||||
nonce: Date.now(),
|
||||
});
|
||||
} else {
|
||||
setSidebarDocs((prev) => {
|
||||
if (prev.some((d) => `${d.document_type}:${d.id}` === key)) return prev;
|
||||
|
|
@ -883,20 +870,9 @@ function AuthenticatedDocumentsSidebarBase({
|
|||
{ id: doc.id, title: doc.title, document_type: doc.document_type as DocumentTypeEnum },
|
||||
];
|
||||
});
|
||||
setSidebarMentionEvent({
|
||||
kind: "add",
|
||||
docs: [
|
||||
{
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
document_type: doc.document_type as DocumentTypeEnum,
|
||||
},
|
||||
],
|
||||
nonce: Date.now(),
|
||||
});
|
||||
}
|
||||
},
|
||||
[setSidebarDocs, setSidebarMentionEvent]
|
||||
[setSidebarDocs]
|
||||
);
|
||||
|
||||
const handleToggleFolderSelect = useCallback(
|
||||
|
|
@ -918,14 +894,6 @@ function AuthenticatedDocumentsSidebarBase({
|
|||
if (subtreeDocs.length === 0) return;
|
||||
|
||||
if (selectAll) {
|
||||
const existingKeys = new Set(sidebarDocs.map((d) => `${d.document_type}:${d.id}`));
|
||||
const docsToAdd = subtreeDocs
|
||||
.filter((d) => !existingKeys.has(`${d.document_type}:${d.id}`))
|
||||
.map((d) => ({
|
||||
id: d.id,
|
||||
title: d.title,
|
||||
document_type: d.document_type as DocumentTypeEnum,
|
||||
}));
|
||||
setSidebarDocs((prev) => {
|
||||
const existingDocKeys = new Set(prev.map((d) => `${d.document_type}:${d.id}`));
|
||||
const newDocs = subtreeDocs
|
||||
|
|
@ -937,35 +905,14 @@ function AuthenticatedDocumentsSidebarBase({
|
|||
}));
|
||||
return newDocs.length > 0 ? [...prev, ...newDocs] : prev;
|
||||
});
|
||||
if (docsToAdd.length > 0) {
|
||||
setSidebarMentionEvent({
|
||||
kind: "add",
|
||||
docs: docsToAdd,
|
||||
nonce: Date.now(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const keysToRemove = new Set(subtreeDocs.map((d) => `${d.document_type}:${d.id}`));
|
||||
const docsToRemove = sidebarDocs
|
||||
.filter((d) => keysToRemove.has(`${d.document_type}:${d.id}`))
|
||||
.map((d) => ({
|
||||
id: d.id,
|
||||
title: d.title,
|
||||
document_type: d.document_type as DocumentTypeEnum,
|
||||
}));
|
||||
setSidebarDocs((prev) =>
|
||||
prev.filter((d) => !keysToRemove.has(`${d.document_type}:${d.id}`))
|
||||
);
|
||||
if (docsToRemove.length > 0) {
|
||||
setSidebarMentionEvent({
|
||||
kind: "remove",
|
||||
docs: docsToRemove,
|
||||
nonce: Date.now(),
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
[treeDocuments, foldersByParent, sidebarDocs, setSidebarDocs, setSidebarMentionEvent]
|
||||
[treeDocuments, foldersByParent, setSidebarDocs]
|
||||
);
|
||||
|
||||
const searchFilteredDocuments = useMemo(() => {
|
||||
|
|
@ -1626,7 +1573,6 @@ function AnonymousDocumentsSidebar({
|
|||
const [search, setSearch] = useState("");
|
||||
|
||||
const [sidebarDocs, setSidebarDocs] = useAtom(sidebarSelectedDocumentsAtom);
|
||||
const setSidebarMentionEvent = useSetAtom(sidebarMentionEventAtom);
|
||||
const mentionedDocIds = useMemo(() => new Set(sidebarDocs.map((d) => d.id)), [sidebarDocs]);
|
||||
|
||||
const handleToggleChatMention = useCallback(
|
||||
|
|
@ -1634,17 +1580,6 @@ function AnonymousDocumentsSidebar({
|
|||
const key = `${doc.document_type}:${doc.id}`;
|
||||
if (isMentioned) {
|
||||
setSidebarDocs((prev) => prev.filter((d) => `${d.document_type}:${d.id}` !== key));
|
||||
setSidebarMentionEvent({
|
||||
kind: "remove",
|
||||
docs: [
|
||||
{
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
document_type: doc.document_type as DocumentTypeEnum,
|
||||
},
|
||||
],
|
||||
nonce: Date.now(),
|
||||
});
|
||||
} else {
|
||||
setSidebarDocs((prev) => {
|
||||
if (prev.some((d) => `${d.document_type}:${d.id}` === key)) return prev;
|
||||
|
|
@ -1653,20 +1588,9 @@ function AnonymousDocumentsSidebar({
|
|||
{ id: doc.id, title: doc.title, document_type: doc.document_type as DocumentTypeEnum },
|
||||
];
|
||||
});
|
||||
setSidebarMentionEvent({
|
||||
kind: "add",
|
||||
docs: [
|
||||
{
|
||||
id: doc.id,
|
||||
title: doc.title,
|
||||
document_type: doc.document_type as DocumentTypeEnum,
|
||||
},
|
||||
],
|
||||
nonce: Date.now(),
|
||||
});
|
||||
}
|
||||
},
|
||||
[setSidebarDocs, setSidebarMentionEvent]
|
||||
[setSidebarDocs]
|
||||
);
|
||||
|
||||
const uploadedDoc = anonMode.isAnonymous ? anonMode.uploadedDoc : null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue