Skip to content

Commit

Permalink
fix: performance issue when pasting long content into the chat input …
Browse files Browse the repository at this point in the history
…box (#4240)
  • Loading branch information
urmauur authored Dec 6, 2024
1 parent 3341a3b commit 2138907
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 15 deletions.
27 changes: 26 additions & 1 deletion web/containers/CenterPanelContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
import { PropsWithChildren } from 'react'

import { useMediaQuery } from '@janhq/joi'
import { useAtomValue } from 'jotai'

import { twMerge } from 'tailwind-merge'

import { MainViewState } from '@/constants/screens'

import { LEFT_PANEL_WIDTH } from '../LeftPanelContainer'

import { RIGHT_PANEL_WIDTH } from '../RightPanelContainer'

import {
mainViewStateAtom,
showLeftPanelAtom,
showRightPanelAtom,
} from '@/helpers/atoms/App.atom'
import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'

const CenterPanelContainer = ({ children }: PropsWithChildren) => {
const reduceTransparent = useAtomValue(reduceTransparentAtom)
const matches = useMediaQuery('(max-width: 880px)')
const showLeftPanel = useAtomValue(showLeftPanelAtom)
const showRightPanel = useAtomValue(showRightPanelAtom)
const mainViewState = useAtomValue(mainViewStateAtom)
return (
<div className={twMerge('flex h-full w-full')}>
<div
className={twMerge('flex h-full w-full')}
style={{
maxWidth: matches
? '100%'
: mainViewState === MainViewState.Thread
? `calc(100% - (${showRightPanel ? Number(localStorage.getItem(RIGHT_PANEL_WIDTH)) : 0}px + ${showLeftPanel ? Number(localStorage.getItem(LEFT_PANEL_WIDTH)) : 0}px))`
: '100%',
}}
>
<div
className={twMerge(
'h-full w-full overflow-hidden bg-[hsla(var(--center-panel-bg))]',
Expand Down
2 changes: 1 addition & 1 deletion web/containers/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { useEffect, useMemo } from 'react'
import { useEffect } from 'react'

import { useAtomValue, useSetAtom } from 'jotai'

Expand Down
2 changes: 1 addition & 1 deletion web/containers/LeftPanelContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'
type Props = PropsWithChildren

const DEFAULT_LEFT_PANEL_WIDTH = 200
const LEFT_PANEL_WIDTH = 'leftPanelWidth'
export const LEFT_PANEL_WIDTH = 'leftPanelWidth'

const LeftPanelContainer = ({ children }: Props) => {
const [leftPanelRef, setLeftPanelRef] = useState<HTMLDivElement | null>(null)
Expand Down
2 changes: 1 addition & 1 deletion web/containers/MainViewContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const MainViewContainer = () => {
}

return (
<div className={twMerge('relative flex w-full')}>
<div className={twMerge('relative flex w-[calc(100%-48px)]')}>
<div className="w-full">
<m.div
key={mainViewState}
Expand Down
14 changes: 7 additions & 7 deletions web/containers/RightPanelContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'

type Props = PropsWithChildren

const DEFAULT_RIGTH_PANEL_WIDTH = 280
const RIGHT_PANEL_WIDTH = 'rightPanelWidth'
const DEFAULT_RIGHT_PANEL_WIDTH = 280
export const RIGHT_PANEL_WIDTH = 'rightPanelWidth'

const RightPanelContainer = ({ children }: Props) => {
const [isResizing, setIsResizing] = useState(false)
const [threadRightPanelWidth, setRightPanelWidth] = useState(
Number(localStorage.getItem(RIGHT_PANEL_WIDTH)) || DEFAULT_RIGTH_PANEL_WIDTH
Number(localStorage.getItem(RIGHT_PANEL_WIDTH)) || DEFAULT_RIGHT_PANEL_WIDTH
)
const [rightPanelRef, setRightPanelRef] = useState<HTMLDivElement | null>(
null
Expand Down Expand Up @@ -55,11 +55,11 @@ const RightPanelContainer = ({ children }: Props) => {
mouseMoveEvent.clientX <
200
) {
setRightPanelWidth(DEFAULT_RIGTH_PANEL_WIDTH)
setRightPanelWidth(DEFAULT_RIGHT_PANEL_WIDTH)
setIsResizing(false)
localStorage.setItem(
RIGHT_PANEL_WIDTH,
String(DEFAULT_RIGTH_PANEL_WIDTH)
String(DEFAULT_RIGHT_PANEL_WIDTH)
)
setShowRightPanel(false)
} else {
Expand All @@ -77,8 +77,8 @@ const RightPanelContainer = ({ children }: Props) => {

useEffect(() => {
if (localStorage.getItem(RIGHT_PANEL_WIDTH) === null) {
setRightPanelWidth(DEFAULT_RIGTH_PANEL_WIDTH)
localStorage.setItem(RIGHT_PANEL_WIDTH, String(DEFAULT_RIGTH_PANEL_WIDTH))
setRightPanelWidth(DEFAULT_RIGHT_PANEL_WIDTH)
localStorage.setItem(RIGHT_PANEL_WIDTH, String(DEFAULT_RIGHT_PANEL_WIDTH))
}
window.addEventListener('mousemove', resize)
window.addEventListener('mouseup', stopResizing)
Expand Down
27 changes: 24 additions & 3 deletions web/screens/Thread/ThreadCenterPanel/ChatInput/RichTextEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useCallback, useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useMemo, useRef, ClipboardEvent } from 'react'

import { MessageStatus } from '@janhq/core'
import hljs from 'highlight.js'
Expand Down Expand Up @@ -67,7 +67,7 @@ const RichTextEditor = ({
placeholder,
spellCheck,
}: RichTextEditorProps) => {
const [editor] = useState(() => withHistory(withReact(createEditor())))
const editor = useMemo(() => withHistory(withReact(createEditor())), [])
const currentLanguage = useRef<string>('plaintext')
const hasStartBackticks = useRef<boolean>(false)
const hasEndBackticks = useRef<boolean>(false)
Expand All @@ -80,6 +80,8 @@ const RichTextEditor = ({
const { sendChatMessage } = useSendChatMessage()
const { stopInference } = useActiveModel()

const largeContentThreshold = 1000

// The decorate function identifies code blocks and marks the ranges
const decorate = useCallback(
(entry: [any, any]) => {
Expand Down Expand Up @@ -324,6 +326,16 @@ const RichTextEditor = ({
[currentPrompt, editor, messages]
)

const handlePaste = (event: ClipboardEvent<HTMLDivElement>) => {
const clipboardData = event.clipboardData || (window as any).clipboardData
const pastedData = clipboardData.getData('text')

if (pastedData.length > largeContentThreshold) {
event.preventDefault() // Prevent the default paste behavior
Transforms.insertText(editor, pastedData) // Insert the content directly into the editor
}
}

return (
<Slate
editor={editor}
Expand Down Expand Up @@ -362,9 +374,18 @@ const RichTextEditor = ({
>
<Editable
ref={textareaRef}
decorate={decorate} // Pass the decorate function
decorate={(entry) => {
// Skip decorate if content exceeds threshold
if (
currentPrompt.length > largeContentThreshold ||
!currentPrompt.length
)
return []
return decorate(entry)
}}
renderLeaf={renderLeaf} // Pass the renderLeaf function
onKeyDown={handleKeyDown}
onPaste={handlePaste} // Add the custom paste handler
className={twMerge(
className,
disabled &&
Expand Down
2 changes: 1 addition & 1 deletion web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ const ChatInput = () => {
{activeSettingInputBox && (
<div
className={twMerge(
'absolute bottom-[6px] left-[1px] flex w-[calc(100%-10px)] items-center justify-between rounded-b-lg bg-[hsla(var(--center-panel-bg))] p-3 pr-0',
'absolute bottom-[5px] left-[1px] flex w-[calc(100%-10px)] items-center justify-between rounded-b-lg bg-[hsla(var(--center-panel-bg))] p-3 pr-0',
!activeThread && 'bg-transparent',
stateModel.loading && 'bg-transparent'
)}
Expand Down

0 comments on commit 2138907

Please sign in to comment.