From 4bc271208e9e1aaff8ca1db99aa4520dcf3f270c Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Tue, 15 Apr 2025 13:16:27 +0200 Subject: [PATCH] refactor: improve synchronisation of external text --- .../src/features/control/message/InputRow.tsx | 39 ++++++++++--------- .../control/message/MessageControl.tsx | 30 ++++++++++++-- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/apps/client/src/features/control/message/InputRow.tsx b/apps/client/src/features/control/message/InputRow.tsx index 56677f526..23bdf59cc 100644 --- a/apps/client/src/features/control/message/InputRow.tsx +++ b/apps/client/src/features/control/message/InputRow.tsx @@ -1,9 +1,7 @@ -import { useEffect, useRef } from 'react'; -import { IoEye, IoEyeOffOutline } from 'react-icons/io5'; +import { PropsWithChildren, useEffect, useRef, useState } from 'react'; import { Input } from '@chakra-ui/react'; -import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; -import { tooltipDelayMid } from '../../../ontimeConfig'; +import { cx } from '../../../common/utils/styleUtils'; import style from './InputRow.module.scss'; @@ -12,50 +10,53 @@ interface InputRowProps { placeholder: string; text: string; visible: boolean; - actionHandler: () => void; changeHandler: (newValue: string) => void; } -export default function InputRow(props: InputRowProps) { - const { label, placeholder, text, visible, actionHandler, changeHandler } = props; +export default function InputRow(props: PropsWithChildren) { + const { label, placeholder, text, visible, changeHandler, children } = props; + const [value, setValue] = useState(text); const inputRef = useRef(null); const cursorPositionRef = useRef(0); // sync cursor position with text useEffect(() => { - if (inputRef.current) { + if (inputRef.current && inputRef.current !== document.activeElement) { inputRef.current.selectionStart = cursorPositionRef.current; inputRef.current.selectionEnd = cursorPositionRef.current; } }, [text]); + // synchronise external text + useEffect(() => { + if (inputRef.current !== document.activeElement) { + setValue(text); + } + }, [text]); + const handleInputChange = (event: React.ChangeEvent) => { cursorPositionRef.current = event.target.selectionStart ?? 0; + setValue(event.target.value); changeHandler(event.target.value); }; return (
- +
- : } - variant={visible ? 'ontime-filled' : 'ontime-subtle'} - size='sm' - /> + {children}
); diff --git a/apps/client/src/features/control/message/MessageControl.tsx b/apps/client/src/features/control/message/MessageControl.tsx index 2c1118a5e..41dc4ab56 100644 --- a/apps/client/src/features/control/message/MessageControl.tsx +++ b/apps/client/src/features/control/message/MessageControl.tsx @@ -1,4 +1,8 @@ +import { IoEye, IoEyeOffOutline } from 'react-icons/io5'; + +import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; import { setMessage, useExternalMessageInput, useTimerMessageInput } from '../../../common/hooks/useSocket'; +import { tooltipDelayMid } from '../../../ontimeConfig'; import InputRow from './InputRow'; import TimerControlsPreview from './TimerViewControl'; @@ -23,8 +27,17 @@ function TimerMessageInput() { text={text} visible={visible} changeHandler={(newValue) => setMessage.timerText(newValue)} - actionHandler={() => setMessage.timerVisible(!visible)} - /> + > + setMessage.timerVisible(!visible)} + tooltip={visible ? 'Make invisible' : 'Make visible'} + aria-label='Toggle timer message visibility' + openDelay={tooltipDelayMid} + icon={visible ? : } + variant={visible ? 'ontime-filled' : 'ontime-subtle'} + size='sm' + /> + ); } @@ -46,7 +59,16 @@ function ExternalInput() { text={text} visible={visible} changeHandler={(newValue) => setMessage.externalText(newValue)} - actionHandler={toggleExternal} - /> + > + : } + variant={visible ? 'ontime-filled' : 'ontime-subtle'} + size='sm' + /> + ); }