fix: chat accepts quotes now

This commit is contained in:
gosangam
2026-08-29 11:58:33 +05:30
parent 028a8d7e1c
commit 76cd106ef7
11 changed files with 559 additions and 41 deletions
+45 -12
View File
@@ -6,16 +6,16 @@ import {
Copy,
FolderPlus,
Link as LinkIcon,
MessageCircle,
MoreHorizontal,
Send,
Share2,
} from "lucide-react";
import { toast } from "sonner";
import { formatCopyText, getSourceReference } from "@/lib/source-reference";
import { buildHighlightUrl } from "@/lib/text-highlight";
import { buildHighlightPath, buildHighlightUrl } from "@/lib/text-highlight";
import { bookmarks, SocialError } from "@/lib/social";
import {
KautilyaIcon,
useMediaQuery,
useCopyFeedback,
type Position,
@@ -25,6 +25,8 @@ import { FloatingToolbar } from "./selection-toolbar/floating-toolbar";
import { CollectionsDrawer } from "./selection-toolbar/collections-drawer";
import { MorePopover, type MoreItem } from "./selection-toolbar/more-popover";
import { ComposePost } from "./selection-toolbar/compose-post";
import { ShareToChatDialog } from "@/components/chat/share-to-chat-dialog";
import type { QuotePayload } from "@/lib/chat";
import { useAuth } from "./auth/auth-provider";
import { useAuthGate } from "./auth/auth-gate";
@@ -34,6 +36,8 @@ import { useAuthGate } from "./auth/auth-gate";
export function TextSelectionToolbar() {
const [selectedText, setSelectedText] = useState("");
// The passage to share, captured at click time. Non-null opens the dialog.
const [chatQuote, setChatQuote] = useState<QuotePayload | null>(null);
const [toolbarPos, setToolbarPos] = useState<Position | null>(null);
const [showMore, setShowMore] = useState(false);
const [morePos, setMorePos] = useState<Position>({ x: 0, y: 0 });
@@ -337,6 +341,21 @@ export function TextSelectionToolbar() {
setShowCollections(true);
}
async function onChat() {
// Snapshot the passage first: requireAuth may open a login flow, and
// finishAction clears the selection — the dialog outlives both.
const ref = getSourceReference();
const quote: QuotePayload = {
// Relative, not absolute: the BFF only accepts in-app paths for quotes.
path: buildHighlightPath(selectedText),
title: ref ? (ref.detail ? `${ref.title} — ${ref.detail}` : ref.title) : "",
text: selectedText,
};
if (!(await requireAuth())) return;
setChatQuote(quote);
finishAction();
}
async function onPost() {
if (!(await requireAuth())) return;
if (isMobile) saveAndClearSelection();
@@ -418,14 +437,11 @@ export function TextSelectionToolbar() {
const isAuthed = !!user;
const askAction: ToolbarAction = {
key: "ask",
label: "Ask Kautilya",
icon: <KautilyaIcon className="size-3.5" />,
onClick: () => {
// TODO: Implement Ask Kautilya
finishAction();
},
const chatAction: ToolbarAction = {
key: "chat",
label: "Chat",
icon: <MessageCircle className="size-3.5" />,
onClick: onChat,
className: "text-amber-400 hover:bg-amber-400/15 hover:text-amber-300",
};
@@ -445,7 +461,7 @@ export function TextSelectionToolbar() {
};
const authedToolbarActions: ToolbarAction[] = [
askAction,
chatAction,
{
key: "post",
label: "Post",
@@ -466,7 +482,6 @@ export function TextSelectionToolbar() {
];
const publicToolbarActions: ToolbarAction[] = [
askAction,
{
key: "copy",
label: "Copy",
@@ -515,6 +530,17 @@ export function TextSelectionToolbar() {
];
const publicMoreItems: MoreItem[] = [
{
key: "chat-public",
label: "Chat",
description: "Send this passage to someone",
icon: <MessageCircle className="size-5" />,
locked: true,
onClick: async () => {
setShowMore(false);
await onChat();
},
},
{
key: "share-as-post",
label: "Share as Post",
@@ -601,6 +627,13 @@ export function TextSelectionToolbar() {
isMobile={isMobile}
selectedText={selectedText}
/>
{chatQuote !== null && (
<ShareToChatDialog
quote={chatQuote}
onClose={() => setChatQuote(null)}
/>
)}
</div>
);
}