From bfebd88e4c97be9927c4741564c28aae93c9de65 Mon Sep 17 00:00:00 2001 From: Max Goodhart Date: Tue, 10 Nov 2020 23:22:28 -0800 Subject: [PATCH] Further simplify custom streams UI to prevent jank Editing URLs and stream kind after the fact doesn't update properly, and can lead to janky behavior when the URL duplicates another stream, because the stream datas get merged together and the row disappears. Moving to larger more atomic editing operations removes these corner cases. --- src/web/control.js | 118 ++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/src/web/control.js b/src/web/control.js index 4e30cda..f516214 100644 --- a/src/web/control.js +++ b/src/web/control.js @@ -465,21 +465,22 @@ function App({ wsEndpoint, role }) { [gridCount, sharedState, focusedInputIdx], ) - const handleChangeCustomStream = useCallback((origLink, customStream) => { - if (!customStream.label && !customStream.link) { - send({ - type: 'delete-custom-stream', - url: origLink, - }) - return - } + const handleChangeCustomStream = useCallback((url, customStream) => { send({ type: 'update-custom-stream', - url: origLink, + url, data: customStream, }) }) + const handleDeleteCustomStream = useCallback((url) => { + send({ + type: 'delete-custom-stream', + url, + }) + return + }) + const setStreamCensored = useCallback((isCensored) => { send({ type: 'set-stream-censored', @@ -730,15 +731,14 @@ function App({ wsEndpoint, role }) { We need it to be part of the array (rather than JSX below) for DOM diffing to match the key and retain focus. */} {customStreams.map(({ link, label, kind }, idx) => ( -
- -
+ ))} @@ -1110,64 +1110,62 @@ function GridControls({ ) } -function CustomStreamInput({ onChange, ...props }) { - const handleChangeLink = useCallback( - (value) => { - onChange(props.link, { ...props, link: value }) - }, - [onChange, props.link], - ) +function CustomStreamInput({ onChange, onDelete, ...props }) { const handleChangeLabel = useCallback( (value) => { onChange(props.link, { ...props, label: value }) }, - [onChange, props.link], - ) - const handleChangeKind = useCallback( - (ev) => { - onChange(props.link, { ...props, kind: ev.target.value }) - }, - [onChange, props.link], + [onChange, props], ) + const handleDeleteClick = useCallback(() => { + onDelete(props.link) + }, [onDelete, props.link]) return ( - <> - +
{' '} + {props.link} ({props.kind}){' '} + +
+ ) +} + +function CreateCustomStreamInput({ onCreate }) { + const [link, setLink] = useState('') + const [kind, setKind] = useState('video') + const [label, setLabel] = useState('') + const handleSubmit = useCallback( + (ev) => { + ev.preventDefault() + onCreate(link, { link, kind, label }) + setLink('') + setKind('video') + setLabel('') + }, + [onCreate, link, kind, label], + ) + return ( +
+ setLink(ev.target.value)} + placeholder="https://..." /> - setKind(ev.target.value)} value={kind}> - - ) -} - -function CreateCustomStreamInput({ onCreate }) { - const [stream, setStream] = useState({ link: '' }) - const handleChangeStream = useCallback((oldLink, stream) => { - setStream(stream) - }) - const handleSubmit = useCallback( - (ev) => { - ev.preventDefault() - onCreate(stream.link, stream) - setStream({ link: '' }) - }, - [onCreate, stream], - ) - return ( - - + setLabel(ev.target.value)} + placeholder="Label (optional)" + /> )