Skip to content

Commit

Permalink
Added functionality to share a message vs chat (#481)
Browse files Browse the repository at this point in the history
* updated chatcraftchat model to have a function to share single message

* Updated messagebase to show share message option in the menu

* Display URL in prompt message

* URL should be copied to clipboard and message should be displayed

* Fixed lint error

* Revert settings.json unwanted commit
  • Loading branch information
Rachit1313 authored Mar 8, 2024
1 parent 599110f commit 7de82c0
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/components/Message/MessageBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,15 @@ import { useModels } from "../../hooks/use-models";
import { useSettings } from "../../hooks/use-settings";
import { useAlert } from "../../hooks/use-alert";
import ImageModal from "../ImageModal";
import { useCopyToClipboard } from "react-use";

// Styles for the message text are defined in CSS vs. Chakra-UI
import "./Message.css";
import useMobileBreakpoint from "../../hooks/use-mobile-breakpoint";
import { usingOfficialOpenAI } from "../../lib/ai";
import { ChatCraftChat } from "../../lib/ChatCraftChat";
import { useLiveQuery } from "dexie-react-hooks";
import { useUser } from "../../hooks/use-user";

export interface MessageBaseProps {
message: ChatCraftMessage;
Expand Down Expand Up @@ -106,6 +110,7 @@ function MessageBase({
disableFork,
disableEdit,
}: MessageBaseProps) {
const [, copyToClipboard] = useCopyToClipboard();
const { id, date, text, imageUrls } = message;
const { models } = useModels();
const { onCopy } = useClipboard(text);
Expand All @@ -123,6 +128,36 @@ function MessageBase({
const isLongMessage = text.length > 5000;
const displaySummaryText = !isOpen && (summaryText || isLongMessage);
const shouldShowDeleteMenu = Boolean(onDeleteBeforeClick || onDeleteClick || onDeleteAfterClick);
const chat = useLiveQuery(() => ChatCraftChat.find(chatId), [chatId]);
const { user } = useUser();
const handleShareMessage = useCallback(async () => {
if (!user) {
error({
title: "Failed to Share Message",
message: "Can't share message because user is not logged in",
});
return;
}
if (!chat) {
console.error("Chat not found");
return;
}
try {
// Use the shareSingleMessage method from the chat instance
const { url } = await chat.shareSingleMessage(user, message.id);
info({
title: "Message Shared Successfully",
message: `URL has been copied to clipboard`,
});
copyToClipboard(url);
} catch (err) {
console.error(err);
error({
title: "Failed to Share Message",
message: "An error occurred while trying to share the message.",
});
}
}, [message.id, user, chat, info, error, copyToClipboard]);

// Wrap the onToggle function with startTransition, state update should be deferred due to long message
// https://reactjs.org/docs/error-decoder.html?invariant=426
Expand Down Expand Up @@ -399,6 +434,19 @@ function MessageBase({
</SubMenu>
</>
)}
<MenuDivider />
<MenuItem
label="Share Message"
onClick={() => handleShareMessage()}
icon={
<IconButton
variant="ghost"
// icon={<YourShareIcon />} // Replace YourShareIcon with the actual icon you want to use for sharing
aria-label="Share message"
title="Share message"
/>
}
/>
{(!disableEdit || onDeleteClick) && <MenuDivider />}
{!disableEdit && (
<MenuItem
Expand Down
32 changes: 32 additions & 0 deletions src/lib/ChatCraftChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,38 @@ export class ChatCraftChat {
return shared;
}

//function to share single message
async shareSingleMessage(user: User, messageId: string) {
// Find the message to be shared
const messageToShare = this._messages.find((message) => message.id === messageId);
if (!messageToShare) {
throw new Error("Message not found");
}

// Clone the chat but only include the specified message
const clonedChatWithSingleMessage = new ChatCraftChat({
messages: [messageToShare.clone()],
summary: this.summary, // You might want to adjust the summary for the shared content
});

// Use the existing sharing logic to share the cloned chat
const shareUrl = createDataShareUrl(clonedChatWithSingleMessage, user);
await createShare(clonedChatWithSingleMessage, user);

const shared = new SharedChatCraftChat({
id: clonedChatWithSingleMessage.id,
url: shareUrl,
date: clonedChatWithSingleMessage.date,
summary: clonedChatWithSingleMessage.summary,
chat: clonedChatWithSingleMessage,
});

// Cache this locally in your db as well
await db.shared.add(shared.toDB());

return shared;
}

static async delete(id: string) {
const chat = await ChatCraftChat.find(id);
if (chat) {
Expand Down

0 comments on commit 7de82c0

Please sign in to comment.