Skip to content

Commit

Permalink
Merge pull request ChatGPTNextWeb#1678 from Yidadaa/export
Browse files Browse the repository at this point in the history
feat: close ChatGPTNextWeb#580 export messages as image
  • Loading branch information
Yidadaa authored May 21, 2023
2 parents 909eb38 + f430cce commit cffcf9d
Show file tree
Hide file tree
Showing 11 changed files with 934 additions and 54 deletions.
53 changes: 9 additions & 44 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import RenameIcon from "../icons/rename.svg";
import ExportIcon from "../icons/share.svg";
import ReturnIcon from "../icons/return.svg";
import CopyIcon from "../icons/copy.svg";
import DownloadIcon from "../icons/download.svg";
import LoadingIcon from "../icons/three-dots.svg";
import PromptIcon from "../icons/prompt.svg";
import MaskIcon from "../icons/mask.svg";
Expand Down Expand Up @@ -53,57 +52,20 @@ import { IconButton } from "./button";
import styles from "./home.module.scss";
import chatStyle from "./chat.module.scss";

import { ListItem, Modal, showModal, showToast } from "./ui-lib";
import { ListItem, Modal } from "./ui-lib";
import { useLocation, useNavigate } from "react-router-dom";
import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
import { Avatar } from "./emoji";
import { MaskAvatar, MaskConfig } from "./mask";
import { useMaskStore } from "../store/mask";
import { useCommand } from "../command";
import { prettyObject } from "../utils/format";
import { ExportMessageModal } from "./exporter";

const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => <LoadingIcon />,
});

function exportMessages(messages: ChatMessage[], topic: string) {
const mdText =
`# ${topic}\n\n` +
messages
.map((m) => {
return m.role === "user"
? `## ${Locale.Export.MessageFromYou}:\n${m.content}`
: `## ${Locale.Export.MessageFromChatGPT}:\n${m.content.trim()}`;
})
.join("\n\n");
const filename = `${topic}.md`;

showModal({
title: Locale.Export.Title,
children: (
<div className="markdown-body">
<pre className={styles["export-content"]}>{mdText}</pre>
</div>
),
actions: [
<IconButton
key="copy"
icon={<CopyIcon />}
bordered
text={Locale.Export.Copy}
onClick={() => copyToClipboard(mdText)}
/>,
<IconButton
key="download"
icon={<DownloadIcon />}
bordered
text={Locale.Export.Download}
onClick={() => downloadAs(mdText, filename)}
/>,
],
});
}

export function SessionConfigModel(props: { onClose: () => void }) {
const chatStore = useChatStore();
const session = chatStore.currentSession();
Expand Down Expand Up @@ -451,6 +413,8 @@ export function Chat() {
const config = useAppConfig();
const fontSize = config.fontSize;

const [showExport, setShowExport] = useState(false);

const inputRef = useRef<HTMLTextAreaElement>(null);
const [userInput, setUserInput] = useState("");
const [isLoading, setIsLoading] = useState(false);
Expand Down Expand Up @@ -739,10 +703,7 @@ export function Chat() {
bordered
title={Locale.Chat.Actions.Export}
onClick={() => {
exportMessages(
session.messages.filter((msg) => !msg.isError),
session.topic,
);
setShowExport(true);
}}
/>
</div>
Expand Down Expand Up @@ -917,6 +878,10 @@ export function Chat() {
/>
</div>
</div>

{showExport && (
<ExportMessageModal onClose={() => setShowExport(false)} />
)}
</div>
);
}
212 changes: 212 additions & 0 deletions app/components/exporter.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
.message-exporter {
&-body {
margin-top: 20px;
}
}

.export-content {
white-space: break-spaces;
padding: 10px !important;
}

.steps {
background-color: var(--gray);
border-radius: 10px;
overflow: hidden;
padding: 5px;
position: relative;
box-shadow: var(--card-shadow) inset;

.steps-progress {
$padding: 5px;
height: calc(100% - 2 * $padding);
width: calc(100% - 2 * $padding);
position: absolute;
top: $padding;
left: $padding;

&-inner {
box-sizing: border-box;
box-shadow: var(--card-shadow);
border: var(--border-in-light);
content: "";
display: inline-block;
width: 0%;
height: 100%;
background-color: var(--white);
transition: all ease 0.3s;
border-radius: 8px;
}
}

.steps-inner {
display: flex;
transform: scale(1);

.step {
flex-grow: 1;
padding: 5px 10px;
font-size: 14px;
color: var(--black);
opacity: 0.5;
transition: all ease 0.3s;

display: flex;
align-items: center;
justify-content: center;

$radius: 8px;

&-finished {
opacity: 0.9;
}

&:hover {
opacity: 0.8;
}

&-current {
color: var(--primary);
}

.step-index {
background-color: var(--gray);
border: var(--border-in-light);
border-radius: 6px;
display: inline-block;
padding: 0px 5px;
font-size: 12px;
margin-right: 8px;
opacity: 0.8;
}

.step-name {
font-size: 12px;
}
}
}
}

.preview-actions {
margin-bottom: 20px;
display: flex;
justify-content: space-between;

button {
flex-grow: 1;
&:not(:last-child) {
margin-right: 10px;
}
}
}

.image-previewer {
.preview-body {
border-radius: 10px;
padding: 20px;
box-shadow: var(--card-shadow) inset;
background-color: var(--gray);

.chat-info {
background-color: var(--second);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: flex-end;
position: relative;
overflow: hidden;

@media screen and (max-width: 600px) {
flex-direction: column;
align-items: flex-start;

.icons {
margin-bottom: 20px;
}
}

.logo {
position: absolute;
top: 0px;
left: 0px;
transform: scale(2);
}

.main-title {
font-size: 20px;
font-weight: bolder;
}

.sub-title {
font-size: 12px;
}

.icons {
margin-top: 10px;
display: flex;
align-items: center;

.icon-space {
font-size: 12px;
margin: 0 10px;
font-weight: bolder;
color: var(--primary);
}
}

.chat-info-item {
font-size: 12px;
color: var(--primary);
padding: 2px 15px;
border-radius: 10px;
background-color: var(--white);
box-shadow: var(--card-shadow);

&:not(:last-child) {
margin-bottom: 5px;
}
}
}

.message {
margin-bottom: 20px;
display: flex;

.avatar {
margin-right: 10px;
}

.body {
border-radius: 10px;
padding: 8px 10px;
max-width: calc(100% - 104px);
box-shadow: var(--card-shadow);
border: var(--border-in-light);
}

&-assistant {
.body {
background-color: var(--white);
}
}

&-user {
flex-direction: row-reverse;

.avatar {
margin-right: 0;
}

.body {
background-color: var(--second);
margin-right: 10px;
}
}
}
}

.default-theme {
}
}
Loading

0 comments on commit cffcf9d

Please sign in to comment.