mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2026-02-10 19:50:28 +08:00
- fix: fix IME composition input causing character duplication
Handle onCompositionStart/End events to prevent repeated characters when typing Chinese in proxy group filter
This commit is contained in:
parent
3c148f2c01
commit
388581d75e
@ -1,20 +1,60 @@
|
|||||||
import React, { useRef } from 'react'
|
import React, { useRef, useState, useCallback } from 'react'
|
||||||
import { Input, InputProps } from '@heroui/react'
|
import { Input, InputProps } from '@heroui/react'
|
||||||
import { FaSearch } from 'react-icons/fa'
|
import { FaSearch } from 'react-icons/fa'
|
||||||
|
|
||||||
interface CollapseInputProps extends InputProps {
|
interface CollapseInputProps extends Omit<InputProps, 'onValueChange'> {
|
||||||
title: string
|
title: string
|
||||||
|
onValueChange?: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollapseInput: React.FC<CollapseInputProps> = (props) => {
|
const CollapseInput: React.FC<CollapseInputProps> = (props) => {
|
||||||
const { title, ...inputProps } = props
|
const { title, value, onValueChange, ...inputProps } = props
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(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<HTMLInputElement>) => {
|
||||||
|
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<HTMLInputElement>) => {
|
||||||
|
isComposingRef.current = false
|
||||||
|
// 组合输入结束后,触发一次更新
|
||||||
|
onValueChange?.(e.currentTarget.value)
|
||||||
|
},
|
||||||
|
[onValueChange]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<Input
|
<Input
|
||||||
size="sm"
|
size="sm"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
|
value={localValue as string}
|
||||||
|
onChange={handleChange}
|
||||||
|
onCompositionStart={handleCompositionStart}
|
||||||
|
onCompositionEnd={handleCompositionEnd}
|
||||||
style={{ paddingInlineEnd: 0 }}
|
style={{ paddingInlineEnd: 0 }}
|
||||||
classNames={{
|
classNames={{
|
||||||
inputWrapper: 'cursor-pointer bg-transparent p-0 data-[hover=true]:bg-content2',
|
inputWrapper: 'cursor-pointer bg-transparent p-0 data-[hover=true]:bg-content2',
|
||||||
|
|||||||
@ -303,7 +303,7 @@ const drawSvg = async (
|
|||||||
if (upload === currentUploadRef.current && download === currentDownloadRef.current) return
|
if (upload === currentUploadRef.current && download === currentDownloadRef.current) return
|
||||||
currentUploadRef.current = upload
|
currentUploadRef.current = upload
|
||||||
currentDownloadRef.current = download
|
currentDownloadRef.current = download
|
||||||
const svg = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 36"><image height="36" width="36" href="${trayIconBase64}"/><text x="140" y="15" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end">${calcTraffic(upload)}/s</text><text x="140" y="34" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end">${calcTraffic(download)}/s</text></svg>`
|
const svg = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 156 36"><image height="36" width="36" href="${trayIconBase64}"/><text x="156" y="15" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end" fill="black">${calcTraffic(upload)}/s</text><text x="156" y="34" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end" fill="black">${calcTraffic(download)}/s</text></svg>`
|
||||||
const image = await loadImage(svg)
|
const image = await loadImage(svg)
|
||||||
window.electron.ipcRenderer.send('trayIconUpdate', image, true)
|
window.electron.ipcRenderer.send('trayIconUpdate', image, true)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user