Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ux edit message and copy api_key #3975

Merged
merged 1 commit into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import {
} from '@janhq/core'

import { Input } from '@janhq/joi'
import { CopyIcon, EyeIcon, FolderOpenIcon } from 'lucide-react'
import {
CheckIcon,
CopyIcon,
EyeIcon,
EyeOffIcon,
FolderOpenIcon,
} from 'lucide-react'
import { Marked, Renderer } from 'marked'

type Props = {
Expand All @@ -34,6 +40,7 @@ const SettingDetailTextInputItem = ({
const { value, type, placeholder, textAlign, inputActions } =
settingProps.controllerProps as InputComponentProps
const [obscure, setObscure] = useState(type === 'password')
const [copied, setCopied] = useState(false)

const description = marked.parse(settingProps.description ?? '', {
async: false,
Expand All @@ -45,6 +52,10 @@ const SettingDetailTextInputItem = ({

const copy = useCallback(() => {
navigator.clipboard.writeText(value)
if (value.length > 0) {
setCopied(true)
}
setTimeout(() => setCopied(false), 2000) // Reset icon after 2 seconds
}, [value])

const onAction = useCallback(
Expand Down Expand Up @@ -84,6 +95,8 @@ const SettingDetailTextInputItem = ({
<InputExtraActions
actions={inputActions ?? []}
onAction={onAction}
copied={copied}
obscure={obscure}
/>
}
/>
Expand All @@ -95,33 +108,51 @@ const SettingDetailTextInputItem = ({
type InputActionProps = {
actions: InputAction[]
onAction: (action: InputAction) => void
copied: boolean
obscure: boolean
}

const InputExtraActions: React.FC<InputActionProps> = ({
actions,
onAction,
copied,
obscure,
}) => {
if (actions.length === 0) return <Fragment />

return (
<div className="flex flex-row space-x-2">
{actions.map((action) => {
console.log(action)
switch (action) {
case 'copy':
return (
return copied ? (
<CheckIcon
key={action}
size={16}
onClick={() => onAction('copy')}
className="text-green-600"
/>
) : (
<CopyIcon
key={action}
size={16}
onClick={() => onAction(action)}
onClick={() => onAction('copy')}
/>
)

case 'unobscure':
return (
return obscure ? (
<EyeIcon
key={action}
size={16}
onClick={() => onAction(action)}
onClick={() => onAction('unobscure')}
/>
) : (
<EyeOffIcon
key={action}
size={16}
onClick={() => onAction('unobscure')}
/>
)

Expand Down
2 changes: 2 additions & 0 deletions web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,50 +37,52 @@
}

const EditChatInput: React.FC<Props> = ({ message }) => {
const activeThread = useAtomValue(activeThreadAtom)
const { stateModel, stopInference } = useActiveModel()
const messages = useAtomValue(getCurrentChatMessagesAtom)

Check warning on line 42 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

40-42 lines are not covered with tests

const [editPrompt, setEditPrompt] = useAtom(editPromptAtom)
const { sendChatMessage } = useSendChatMessage()
const setMessages = useSetAtom(setConvoMessagesAtom)
const activeThreadId = useAtomValue(getActiveThreadIdAtom)
const spellCheck = useAtomValue(spellCheckAtom)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const setEditMessage = useSetAtom(editMessageAtom)
const [showDialog, setshowDialog] = useState(false)

Check warning on line 51 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

44-51 lines are not covered with tests

const onPromptChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setEditPrompt(e.target.value)

Check warning on line 54 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

53-54 lines are not covered with tests
}

useEffect(() => {
if (textareaRef.current) {
textareaRef.current.focus()
const length = textareaRef.current.value.length
textareaRef.current.setSelectionRange(length, length)

Check warning on line 61 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

57-61 lines are not covered with tests
}
}, [activeThreadId])

useEffect(() => {
if (textareaRef.current) {
textareaRef.current.style.height = '40px'
textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px'
textareaRef.current.style.overflow =

Check warning on line 69 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

65-69 lines are not covered with tests
textareaRef.current.clientHeight >= 390 ? 'auto' : 'hidden'
}
}, [editPrompt])

useEffect(() => {
setEditPrompt(message.content[0]?.text?.value)

Check warning on line 75 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

74-75 lines are not covered with tests
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const sendEditMessage = async () => {
setEditMessage('')
const messageIdx = messages.findIndex((msg) => msg.id === message.id)
const newMessages = messages.slice(0, messageIdx)
if (activeThread) {
setMessages(activeThread.id, newMessages)
await extensionManager

Check warning on line 85 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

79-85 lines are not covered with tests
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
?.writeMessages(
activeThread.id,
Expand All @@ -88,22 +90,22 @@
newMessages
)
.then(() => {
sendChatMessage(editPrompt)

Check warning on line 93 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

93 line is not covered with tests
})
}
}

const onKeyDown = async (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault()
if (messages[messages.length - 1]?.status !== MessageStatus.Pending)
sendEditMessage()
else onStopInferenceClick()

Check warning on line 103 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

98-103 lines are not covered with tests
}
}

const onStopInferenceClick = async () => {
stopInference()

Check warning on line 108 in web/screens/Thread/ThreadCenterPanel/EditChatInput/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

107-108 lines are not covered with tests
}

return (
Expand Down
Loading