mirror of
https://github.com/streamwall/streamwall.git
synced 2026-02-01 01:42:49 -05:00
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.
This commit is contained in:
@@ -465,21 +465,22 @@ function App({ wsEndpoint, role }) {
|
|||||||
[gridCount, sharedState, focusedInputIdx],
|
[gridCount, sharedState, focusedInputIdx],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleChangeCustomStream = useCallback((origLink, customStream) => {
|
const handleChangeCustomStream = useCallback((url, customStream) => {
|
||||||
if (!customStream.label && !customStream.link) {
|
|
||||||
send({
|
|
||||||
type: 'delete-custom-stream',
|
|
||||||
url: origLink,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
send({
|
send({
|
||||||
type: 'update-custom-stream',
|
type: 'update-custom-stream',
|
||||||
url: origLink,
|
url,
|
||||||
data: customStream,
|
data: customStream,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleDeleteCustomStream = useCallback((url) => {
|
||||||
|
send({
|
||||||
|
type: 'delete-custom-stream',
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
const setStreamCensored = useCallback((isCensored) => {
|
const setStreamCensored = useCallback((isCensored) => {
|
||||||
send({
|
send({
|
||||||
type: 'set-stream-censored',
|
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.
|
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) => (
|
{customStreams.map(({ link, label, kind }, idx) => (
|
||||||
<div>
|
<CustomStreamInput
|
||||||
<CustomStreamInput
|
key={idx}
|
||||||
key={idx}
|
link={link}
|
||||||
link={link}
|
label={label}
|
||||||
label={label}
|
kind={kind}
|
||||||
kind={kind}
|
onChange={handleChangeCustomStream}
|
||||||
onChange={handleChangeCustomStream}
|
onDelete={handleDeleteCustomStream}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
<CreateCustomStreamInput onCreate={handleChangeCustomStream} />
|
<CreateCustomStreamInput onCreate={handleChangeCustomStream} />
|
||||||
</div>
|
</div>
|
||||||
@@ -1110,64 +1110,62 @@ function GridControls({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CustomStreamInput({ onChange, ...props }) {
|
function CustomStreamInput({ onChange, onDelete, ...props }) {
|
||||||
const handleChangeLink = useCallback(
|
|
||||||
(value) => {
|
|
||||||
onChange(props.link, { ...props, link: value })
|
|
||||||
},
|
|
||||||
[onChange, props.link],
|
|
||||||
)
|
|
||||||
const handleChangeLabel = useCallback(
|
const handleChangeLabel = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
onChange(props.link, { ...props, label: value })
|
onChange(props.link, { ...props, label: value })
|
||||||
},
|
},
|
||||||
[onChange, props.link],
|
[onChange, props],
|
||||||
)
|
|
||||||
const handleChangeKind = useCallback(
|
|
||||||
(ev) => {
|
|
||||||
onChange(props.link, { ...props, kind: ev.target.value })
|
|
||||||
},
|
|
||||||
[onChange, props.link],
|
|
||||||
)
|
)
|
||||||
|
const handleDeleteClick = useCallback(() => {
|
||||||
|
onDelete(props.link)
|
||||||
|
}, [onDelete, props.link])
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<LazyChangeInput
|
|
||||||
onChange={handleChangeLink}
|
|
||||||
placeholder="https://..."
|
|
||||||
value={props.link}
|
|
||||||
/>
|
|
||||||
<LazyChangeInput
|
<LazyChangeInput
|
||||||
|
value={props.label}
|
||||||
onChange={handleChangeLabel}
|
onChange={handleChangeLabel}
|
||||||
placeholder="Label (optional)"
|
placeholder="Label (optional)"
|
||||||
value={props.label}
|
/>{' '}
|
||||||
|
<a href={props.link}>{props.link}</a> <span>({props.kind})</span>{' '}
|
||||||
|
<button onClick={handleDeleteClick}>x</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<input
|
||||||
|
value={link}
|
||||||
|
onChange={(ev) => setLink(ev.target.value)}
|
||||||
|
placeholder="https://..."
|
||||||
/>
|
/>
|
||||||
<select onChange={handleChangeKind} value={props.kind}>
|
<select onChange={(ev) => setKind(ev.target.value)} value={kind}>
|
||||||
<option value="video">video</option>
|
<option value="video">video</option>
|
||||||
<option value="audio">audio</option>
|
<option value="audio">audio</option>
|
||||||
<option value="web">web</option>
|
<option value="web">web</option>
|
||||||
<option value="overlay">overlay</option>
|
<option value="overlay">overlay</option>
|
||||||
<option value="background">background</option>
|
<option value="background">background</option>
|
||||||
</select>
|
</select>
|
||||||
</>
|
<input
|
||||||
)
|
value={label}
|
||||||
}
|
onChange={(ev) => setLabel(ev.target.value)}
|
||||||
|
placeholder="Label (optional)"
|
||||||
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 (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<CustomStreamInput onChange={handleChangeStream} {...stream} />
|
|
||||||
<button type="submit">add stream</button>
|
<button type="submit">add stream</button>
|
||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user