mirror of
https://github.com/coaidev/coai.git
synced 2025-05-19 21:10:18 +09:00
feat: readable midjourney actions
This commit is contained in:
parent
de5d863686
commit
a5d2c8c1ff
@ -115,6 +115,7 @@
|
|||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
border: 1px solid hsl(var(--border));
|
border: 1px solid hsl(var(--border));
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.virtual-action {
|
.virtual-action {
|
||||||
|
@ -8,7 +8,7 @@ import rehypeKatex from "rehype-katex";
|
|||||||
import rehypeRaw from "rehype-raw";
|
import rehypeRaw from "rehype-raw";
|
||||||
import { parseFile } from "./plugins/file.tsx";
|
import { parseFile } from "./plugins/file.tsx";
|
||||||
import "@/assets/markdown/all.less";
|
import "@/assets/markdown/all.less";
|
||||||
import { useEffect, useMemo } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { openDialog as openQuotaDialog } from "@/store/quota.ts";
|
import { openDialog as openQuotaDialog } from "@/store/quota.ts";
|
||||||
import { openDialog as openSubscriptionDialog } from "@/store/subscription.ts";
|
import { openDialog as openSubscriptionDialog } from "@/store/subscription.ts";
|
||||||
@ -22,6 +22,8 @@ import {
|
|||||||
Codepen,
|
Codepen,
|
||||||
Codesandbox,
|
Codesandbox,
|
||||||
Copy,
|
Copy,
|
||||||
|
Eye,
|
||||||
|
EyeOff,
|
||||||
Github,
|
Github,
|
||||||
Maximize,
|
Maximize,
|
||||||
Package,
|
Package,
|
||||||
@ -45,12 +47,12 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogTrigger,
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog.tsx";
|
} from "@/components/ui/dialog.tsx";
|
||||||
import { DialogClose } from "@radix-ui/react-dialog";
|
|
||||||
import { appLogo } from "@/conf/env.ts";
|
import { appLogo } from "@/conf/env.ts";
|
||||||
import { subscriptionDataSelector } from "@/store/globals.ts";
|
import { subscriptionDataSelector } from "@/store/globals.ts";
|
||||||
import { useMessageActions } from "@/store/chat.ts";
|
import { useMessageActions } from "@/store/chat.ts";
|
||||||
import { useTemporaryState } from "@/utils/hook.ts";
|
import { useTemporaryState } from "@/utils/hook.ts";
|
||||||
import Icon from "@/components/utils/Icon.tsx";
|
import Icon from "@/components/utils/Icon.tsx";
|
||||||
|
import { DialogClose } from "@radix-ui/react-dialog";
|
||||||
|
|
||||||
type MarkdownProps = {
|
type MarkdownProps = {
|
||||||
children: string;
|
children: string;
|
||||||
@ -109,6 +111,55 @@ function getVirtualIcon(command: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const commandI18nPrompt: Record<string, string> = {
|
||||||
|
"/VARIATION": "chat.actions.variant",
|
||||||
|
"/UPSCALE": "chat.actions.upscale",
|
||||||
|
"/REROLL": "chat.actions.reroll",
|
||||||
|
};
|
||||||
|
|
||||||
|
function getI18nPrompt(command: string) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const prompt = commandI18nPrompt[command];
|
||||||
|
return prompt && t(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
type VirtualPromptProps = {
|
||||||
|
message: string;
|
||||||
|
prefix: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
function VirtualPrompt({ message, prefix, children }: VirtualPromptProps) {
|
||||||
|
const [raw, setRaw] = useState<boolean>(false);
|
||||||
|
const toggle = (e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setRaw(!raw);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Comp = () => (
|
||||||
|
<>
|
||||||
|
{getVirtualIcon(prefix)}
|
||||||
|
{children} {getI18nPrompt(prefix)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`virtual-prompt flex flex-row items-center justify-center select-none`}
|
||||||
|
>
|
||||||
|
{raw ? message : <Comp />}
|
||||||
|
|
||||||
|
{!raw ? (
|
||||||
|
<Eye className={`h-4 w-4 ml-2 cursor-pointer`} onClick={toggle} />
|
||||||
|
) : (
|
||||||
|
<EyeOff className={`h-4 w-4 ml-2 cursor-pointer`} onClick={toggle} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function MarkdownContent({
|
function MarkdownContent({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
@ -120,7 +171,6 @@ function MarkdownContent({
|
|||||||
const { send: sendAction } = useMessageActions();
|
const { send: sendAction } = useMessageActions();
|
||||||
|
|
||||||
const { state, triggerState } = useTemporaryState();
|
const { state, triggerState } = useTemporaryState();
|
||||||
|
|
||||||
const subscription = useSelector(subscriptionDataSelector);
|
const subscription = useSelector(subscriptionDataSelector);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -243,7 +293,9 @@ function MarkdownContent({
|
|||||||
<DialogDescription className={`pb-2`}>
|
<DialogDescription className={`pb-2`}>
|
||||||
{t("chat.send-message-desc")}
|
{t("chat.send-message-desc")}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
<p className={`virtual-prompt`}>{message}</p>
|
<VirtualPrompt message={message} prefix={prefix}>
|
||||||
|
{children}
|
||||||
|
</VirtualPrompt>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
|
@ -159,9 +159,7 @@ function RedeemTable() {
|
|||||||
{data.map((redeem, idx) => (
|
{data.map((redeem, idx) => (
|
||||||
<TableRow key={idx} className={`whitespace-nowrap`}>
|
<TableRow key={idx} className={`whitespace-nowrap`}>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Badge variant={`outline`}>
|
<Badge variant={`outline`}>{redeem.quota}</Badge>
|
||||||
{redeem.quota}
|
|
||||||
</Badge>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{redeem.total}</TableCell>
|
<TableCell>{redeem.total}</TableCell>
|
||||||
<TableCell>{redeem.used}</TableCell>
|
<TableCell>{redeem.used}</TableCell>
|
||||||
|
@ -4,12 +4,13 @@ type Icon = {
|
|||||||
icon: React.ReactElement;
|
icon: React.ReactElement;
|
||||||
className?: string;
|
className?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
};
|
} & React.SVGProps<SVGSVGElement>;
|
||||||
|
|
||||||
function Icon({ icon, className, id }: Icon) {
|
function Icon({ icon, className, id, ...props }: Icon) {
|
||||||
return React.cloneElement(icon, {
|
return React.cloneElement(icon, {
|
||||||
className: className,
|
className: className,
|
||||||
id: id,
|
id: id,
|
||||||
|
...props,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,12 @@
|
|||||||
"recall-desc": "检测到您上次有未发送的消息,已经为您恢复。",
|
"recall-desc": "检测到您上次有未发送的消息,已经为您恢复。",
|
||||||
"recall-cancel": "取消",
|
"recall-cancel": "取消",
|
||||||
"send-message": "发送消息",
|
"send-message": "发送消息",
|
||||||
"send-message-desc": "是否确认发送此消息?"
|
"send-message-desc": "是否确认发送此消息?",
|
||||||
|
"actions": {
|
||||||
|
"upscale": "放大",
|
||||||
|
"variant": "变化",
|
||||||
|
"reroll": "重绘"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"copy": "复制消息",
|
"copy": "复制消息",
|
||||||
|
@ -88,7 +88,12 @@
|
|||||||
"placeholder-enter": "Write something... (Enter to send)",
|
"placeholder-enter": "Write something... (Enter to send)",
|
||||||
"placeholder-raw": "Write something...",
|
"placeholder-raw": "Write something...",
|
||||||
"send-message": "Send Message",
|
"send-message": "Send Message",
|
||||||
"send-message-desc": "Are you sure you want to send this message?"
|
"send-message-desc": "Are you sure you want to send this message?",
|
||||||
|
"actions": {
|
||||||
|
"upscale": "Zoom in",
|
||||||
|
"variant": "Change",
|
||||||
|
"reroll": "重绘"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"copy": "Copy Message",
|
"copy": "Copy Message",
|
||||||
|
@ -88,7 +88,12 @@
|
|||||||
"placeholder-enter": "何か書いてください... (送信するにはEnterキーを押してください)",
|
"placeholder-enter": "何か書いてください... (送信するにはEnterキーを押してください)",
|
||||||
"placeholder-raw": "何か書いてください...",
|
"placeholder-raw": "何か書いてください...",
|
||||||
"send-message": "メッセージを送信",
|
"send-message": "メッセージを送信",
|
||||||
"send-message-desc": "このメッセージを送信してもよろしいですか?"
|
"send-message-desc": "このメッセージを送信してもよろしいですか?",
|
||||||
|
"actions": {
|
||||||
|
"upscale": "拡大",
|
||||||
|
"variant": "変化",
|
||||||
|
"reroll": "再描画"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"copy": "メッセージをコピー",
|
"copy": "メッセージをコピー",
|
||||||
|
@ -88,7 +88,12 @@
|
|||||||
"placeholder-enter": "Напишите что-нибудь... (Введите, чтобы отправить)",
|
"placeholder-enter": "Напишите что-нибудь... (Введите, чтобы отправить)",
|
||||||
"placeholder-raw": "Напишите что-нибудь...",
|
"placeholder-raw": "Напишите что-нибудь...",
|
||||||
"send-message": "Отправить",
|
"send-message": "Отправить",
|
||||||
"send-message-desc": "Вы уверены, что хотите отправить это сообщение?"
|
"send-message-desc": "Вы уверены, что хотите отправить это сообщение?",
|
||||||
|
"actions": {
|
||||||
|
"upscale": "Увел",
|
||||||
|
"variant": "перемена",
|
||||||
|
"reroll": "Перерисовать"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"copy": "Копировать сообщение",
|
"copy": "Копировать сообщение",
|
||||||
|
Loading…
Reference in New Issue
Block a user