may share prompt

This commit is contained in:
an-lee
2024-01-12 01:40:17 +08:00
parent f9b1c14b4c
commit e05f2c57eb
8 changed files with 83 additions and 16 deletions

View File

@@ -335,5 +335,7 @@
"shareAudio": "Share audio",
"areYouSureToShareThisAudioToCommunity": "Are you sure to share this audio to community?",
"shareVideo": "Share video",
"areYouSureToShareThisVideoToCommunity": "Are you sure to share this video to community?"
"areYouSureToShareThisVideoToCommunity": "Are you sure to share this video to community?",
"sharePrompt": "Share prompt",
"areYouSureToShareThisPromptToCommunity": "Are you sure to share this prompt to community?"
}

View File

@@ -335,5 +335,7 @@
"shareAudio": "分享音频",
"areYouSureToShareThisAudioToCommunity": "您确定要分享此音频到社区吗?",
"shareVideo": "分享视频",
"areYouSureToShareThisVideoToCommunity": "您确定要分享此视频到社区吗?"
"areYouSureToShareThisVideoToCommunity": "您确定要分享此视频到社区吗?",
"sharePrompt": "分享提示语",
"areYouSureToShareThisPromptToCommunity": "您确定要分享此提示语到社区吗?"
}

View File

@@ -157,7 +157,7 @@ export class Transcription extends Model<Transcription> {
@AfterFind
static expireProcessingState(transcription: Transcription) {
if (transcription.state !== "processing") return;
if (transcription?.state !== "processing") return;
if (transcription.updatedAt.getTime() + PROCESS_TIMEOUT < Date.now()) {
if (transcription.result) {

View File

@@ -94,14 +94,14 @@ export const AssistantMessageComponent = (props: {
<AvatarImage></AvatarImage>
<AvatarFallback className="bg-white">AI</AvatarFallback>
</Avatar>
<div className="flex flex-col gap-2 px-4 py-2 bg-white border rounded-lg shadow-sm w-full prose max-w-prose">
<div className="flex flex-col gap-2 px-4 py-2 bg-white border rounded-lg shadow-sm w-full">
{configuration?.autoSpeech && speeching ? (
<div className="p-4">
<LoaderIcon className="w-8 h-8 animate-spin" />
</div>
) : (
<Markdown
className="select-text"
className="select-text prose"
components={{
a({ node, children, ...props }) {
try {

View File

@@ -8,8 +8,9 @@ export const MessageComponent = (props: {
configuration: { [key: string]: any };
onResend?: () => void;
onRemove?: () => void;
onShare?: () => void;
}) => {
const { message, configuration, onResend, onRemove } = props;
const { message, configuration, onResend, onRemove, onShare } = props;
if (message.role === "assistant") {
return (
<AssistantMessageComponent
@@ -24,6 +25,7 @@ export const MessageComponent = (props: {
configuration={configuration}
onResend={onResend}
onRemove={onRemove}
onShare={onShare}
/>
);
}

View File

@@ -17,6 +17,7 @@ import {
AlertCircleIcon,
CopyIcon,
CheckIcon,
Share2Icon,
} from "lucide-react";
import { useCopyToClipboard } from "@uidotdev/usehooks";
import { t } from "i18next";
@@ -27,8 +28,9 @@ export const UserMessageComponent = (props: {
configuration?: { [key: string]: any };
onResend?: () => void;
onRemove?: () => void;
onShare?: () => void;
}) => {
const { message, onResend, onRemove } = props;
const { message, onResend, onRemove, onShare } = props;
const speech = message.speeches?.[0];
const { user } = useContext(AppSettingsProviderContext);
const [_, copyToClipboard] = useCopyToClipboard();
@@ -41,7 +43,7 @@ export const UserMessageComponent = (props: {
>
<DropdownMenu>
<div className="flex flex-col gap-2 px-4 py-2 bg-sky-500/30 border-sky-500 rounded-lg shadow-sm w-full">
<Markdown className="select-text">{message.content}</Markdown>
<Markdown className="select-text prose">{message.content}</Markdown>
{Boolean(speech) && <SpeechPlayer speech={speech} />}
@@ -81,6 +83,15 @@ export const UserMessageComponent = (props: {
}}
/>
)}
{message.createdAt && (
<Share2Icon
data-tooltip-id="global-tooltip"
data-tooltip-content={t("share")}
className="w-3 h-3 cursor-pointer"
onClick={onShare}
/>
)}
</div>
</div>
<DropdownMenuContent>

View File

@@ -8,6 +8,7 @@ import {
DefaultVideoLayout,
defaultLayoutIcons,
} from "@vidstack/react/player/layouts/default";
import Markdown from "react-markdown";
export const Posts = () => {
const { webApi } = useContext(AppSettingsProviderContext);
@@ -16,7 +17,6 @@ export const Posts = () => {
const fetchPosts = async () => {
webApi.posts().then(
(res) => {
console.log(res);
setPosts(res.posts);
},
(err) => {
@@ -60,7 +60,9 @@ const PostCard = (props: { post: PostType }) => {
<div className="">{post.user.name}</div>
</div>
</div>
{post.content && <div className="mb-4">{post.content}</div>}
{post.content && (
<Markdown className="prose select-text mb-4">{post.content}</Markdown>
)}
{post.targetType == "Medium" && <PostMedium medium={post.target} />}
</div>
);

View File

@@ -1,5 +1,12 @@
import { useState, useEffect, useReducer, useContext, useRef } from "react";
import {
AlertDialog,
AlertDialogHeader,
AlertDialogDescription,
AlertDialogTitle,
AlertDialogContent,
AlertDialogFooter,
AlertDialogCancel,
Button,
ScrollArea,
Textarea,
@@ -8,11 +15,7 @@ import {
SheetTrigger,
useToast,
} from "@renderer/components/ui";
import {
MessageComponent,
ConversationForm,
SpeechForm,
} from "@renderer/components";
import { MessageComponent, ConversationForm } from "@renderer/components";
import { SendIcon, BotIcon, LoaderIcon, SettingsIcon } from "lucide-react";
import { Link, useParams } from "react-router-dom";
import { t } from "i18next";
@@ -29,9 +32,11 @@ export default () => {
const [editting, setEditting] = useState<boolean>(false);
const [conversation, setConversation] = useState<ConversationType>();
const { addDblistener, removeDbListener } = useContext(DbProviderContext);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { EnjoyApp, webApi } = useContext(AppSettingsProviderContext);
const [content, setConent] = useState<string>("");
const [submitting, setSubmitting] = useState<boolean>(false);
const [sharing, setSharing] = useState<MessageType>();
const { toast } = useToast();
const [messages, dispatchMessages] = useReducer(messagesReducer, []);
@@ -169,6 +174,28 @@ export default () => {
}, 500);
};
const handleShare = async (message: MessageType) => {
if (message.role === "user") {
const content = message.content;
webApi
.createPost({
content,
})
.then(() => {
toast({
description: t("sharedSuccessfully"),
});
})
.catch((err) => {
toast({
title: t("shareFailed"),
description: err.message,
});
});
setSharing(null);
}
};
useEffect(() => {
fetchConversation();
fetchMessages();
@@ -258,6 +285,7 @@ export default () => {
dispatchMessages({ type: "destroy", record: message });
}}
onShare={() => setSharing(message)}
/>
))}
{offset > -1 && (
@@ -278,6 +306,26 @@ export default () => {
</div>
</ScrollArea>
<AlertDialog
open={Boolean(sharing)}
onOpenChange={() => setSharing(null)}
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{t("sharePrompt")}</AlertDialogTitle>
<AlertDialogDescription>
{t("areYouSureToShareThisPromptToCommunity")}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t("cancel")}</AlertDialogCancel>
<Button variant="default" onClick={() => handleShare(sharing)}>
{t("share")}
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<div className="px-4 absolute w-full bottom-0 left-0 h-14 bg-muted z-50">
<div className="focus-within:bg-white px-4 py-2 flex items-center space-x-4 rounded-lg border">
<Textarea