From 388581d75ee66ea180ea19301644b8032b0ca294 Mon Sep 17 00:00:00 2001 From: xmk23333 Date: Mon, 19 Jan 2026 13:04:34 +0800 Subject: [PATCH] - fix: fix IME composition input causing character duplication Handle onCompositionStart/End events to prevent repeated characters when typing Chinese in proxy group filter --- .../src/components/base/collapse-input.tsx | 46 +++++++++++++++++-- .../src/components/sider/conn-card.tsx | 2 +- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/components/base/collapse-input.tsx b/src/renderer/src/components/base/collapse-input.tsx index c9e4545..fcad365 100644 --- a/src/renderer/src/components/base/collapse-input.tsx +++ b/src/renderer/src/components/base/collapse-input.tsx @@ -1,20 +1,60 @@ -import React, { useRef } from 'react' +import React, { useRef, useState, useCallback } from 'react' import { Input, InputProps } from '@heroui/react' import { FaSearch } from 'react-icons/fa' -interface CollapseInputProps extends InputProps { +interface CollapseInputProps extends Omit { title: string + onValueChange?: (value: string) => void } const CollapseInput: React.FC = (props) => { - const { title, ...inputProps } = props + const { title, value, onValueChange, ...inputProps } = props const inputRef = useRef(null) + const isComposingRef = useRef(false) + const [localValue, setLocalValue] = useState(value || '') + + // 同步外部 value 变化 + React.useEffect(() => { + if (!isComposingRef.current) { + setLocalValue(value || '') + } + }, [value]) + + const handleChange = useCallback( + (e: React.ChangeEvent) => { + const newValue = e.target.value + setLocalValue(newValue) + // 只在非组合输入时触发外部更新 + if (!isComposingRef.current) { + onValueChange?.(newValue) + } + }, + [onValueChange] + ) + + const handleCompositionStart = useCallback(() => { + isComposingRef.current = true + }, []) + + const handleCompositionEnd = useCallback( + (e: React.CompositionEvent) => { + isComposingRef.current = false + // 组合输入结束后,触发一次更新 + onValueChange?.(e.currentTarget.value) + }, + [onValueChange] + ) + return (
${calcTraffic(upload)}/s${calcTraffic(download)}/s` + const svg = `data:image/svg+xml;utf8,${calcTraffic(upload)}/s${calcTraffic(download)}/s` const image = await loadImage(svg) window.electron.ipcRenderer.send('trayIconUpdate', image, true) }