feat: readable midjourney actions

This commit is contained in:
Zhang Minghan 2024-03-11 17:40:05 +08:00
parent de5d863686
commit a5d2c8c1ff
8 changed files with 85 additions and 13 deletions

View File

@ -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 {

View File

@ -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>

View File

@ -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>

View File

@ -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,
}); });
} }

View File

@ -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": "复制消息",

View File

@ -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",

View File

@ -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": "メッセージをコピー",

View File

@ -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": "Копировать сообщение",