feat: support copy to clipboard

feat: move regenerate to all messages
feat: move stop generate to replace submit button
feat: make options' position more clear
This commit is contained in:
Wentao Lyu 2023-04-01 02:12:15 +08:00
parent bb1f8d731b
commit b67af67433
10 changed files with 372 additions and 180 deletions

View file

@ -1,26 +1,74 @@
import React from 'react';
// import Clipboard from '../svg/Clipboard';
import Clipboard from '../svg/Clipboard';
import EditIcon from '../svg/EditIcon';
import RegenerateIcon from '../svg/RegenerateIcon';
export default function HoverButtons({
isEditting,
enterEdit,
copyToClipboard,
conversation,
isSubmitting,
message,
regenerate
}) {
const { endpoint, jailbreak = false } = conversation;
const branchingSupported =
// azureOpenAI, openAI, chatGPTBrowser support branching, so edit enabled
!!['azureOpenAI', 'openAI', 'chatGPTBrowser'].find(e => e === endpoint) ||
// Sydney in bingAI supports branching, so edit enabled
(endpoint === 'bingAI' && jailbreak);
const editEnabled =
!message?.error &&
message?.isCreatedByUser &&
!message?.searchResult &&
!isEditting &&
branchingSupported;
// for now, once branching is supported, regerate will be enabled
const regenerateEnabled =
!message?.error &&
!message?.isCreatedByUser &&
!message?.searchResult &&
!isEditting &&
!isSubmitting &&
branchingSupported;
export default function HoverButtons({ visible, onClick, endpoint }) {
const enabled = !!['azureOpenAI', 'openAI', 'chatGPTBrowser'].find(e => e === endpoint);
console.log(enabled);
return (
<div className="visible mt-2 flex justify-center gap-3 self-end text-gray-400 md:gap-4 lg:absolute lg:top-0 lg:right-0 lg:mt-0 lg:translate-x-full lg:gap-1 lg:self-center lg:pl-2">
{visible && enabled ? (
<>
<button
className="resubmit-edit-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible"
onClick={onClick}
>
{/* <button className="rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400"> */}
<EditIcon />
</button>
</>
{editEnabled ? (
<button
className="hover-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible"
onClick={enterEdit}
type="button"
title="edit"
>
{/* <button className="rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400"> */}
<EditIcon />
</button>
) : null}
{/* <button className="rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400">
<Clipboard />
</button> */}
{regenerateEnabled ? (
<button
className="hover-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible"
onClick={regenerate}
type="button"
title="regenerate"
>
{/* <button className="rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400"> */}
<RegenerateIcon />
</button>
) : null}
<button
className="hover-button rounded-md p-1 hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200 disabled:dark:hover:text-gray-400 md:invisible md:group-hover:visible"
onClick={copyToClipboard}
type="button"
title="copy to clipboard"
>
<Clipboard />
</button>
</div>
);
}

View file

@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { useRecoilValue, useSetRecoilState, useResetRecoilState } from 'recoil';
import copy from 'copy-to-clipboard';
import SubRow from './Content/SubRow';
import Content from './Content/Content';
import MultiMessage from './MultiMessage';
@ -29,7 +30,7 @@ export default function Message({
const textEditor = useRef(null);
const last = !message?.children?.length;
const edit = message.messageId == currentEditId;
const { ask } = useMessageHandler();
const { ask, regenerate } = useMessageHandler();
const { switchToConversation } = store.useConversation();
const blinker = submitting && isSubmitting;
@ -87,6 +88,14 @@ export default function Message({
enterEdit(true);
};
const regenerateMessage = () => {
if (!isSubmitting && !message?.isCreatedByUser) regenerate(message);
};
const copyToClipboard = () => {
copy(message?.text);
};
const clickSearchResult = async () => {
if (!searchResult) return;
const convoResponse = await fetchById('convos', message.conversationId);
@ -177,9 +186,13 @@ export default function Message({
)}
</div>
<HoverButtons
endpoint={conversation?.endpoint}
visible={!error && isCreatedByUser && !edit && !searchResult}
onClick={() => enterEdit()}
isEditting={edit}
isSubmitting={isSubmitting}
message={message}
conversation={conversation}
enterEdit={() => enterEdit()}
regenerate={() => regenerateMessage()}
copyToClipboard={() => copyToClipboard()}
/>
<SubRow subclasses="switch-container">
<SiblingSwitch