mirror of
https://github.com/streamwall/streamwall.git
synced 2026-01-30 00:42:48 -05:00
Make stream list scrollable
This commit is contained in:
@@ -7,7 +7,7 @@ import { patch as patchJSON } from 'jsondiffpatch'
|
|||||||
import { h, Fragment, render } from 'preact'
|
import { h, Fragment, render } from 'preact'
|
||||||
import { useEffect, useState, useCallback, useRef } from 'preact/hooks'
|
import { useEffect, useState, useCallback, useRef } from 'preact/hooks'
|
||||||
import { State } from 'xstate'
|
import { State } from 'xstate'
|
||||||
import styled, { css } from 'styled-components'
|
import styled, { createGlobalStyle } from 'styled-components'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
|
|
||||||
import '../index.css'
|
import '../index.css'
|
||||||
@@ -42,6 +42,17 @@ const hotkeyTriggers = [
|
|||||||
'p',
|
'p',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const GlobalStyle = createGlobalStyle`
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
function useYDoc(keys) {
|
function useYDoc(keys) {
|
||||||
const [doc, setDoc] = useState(new Y.Doc())
|
const [doc, setDoc] = useState(new Y.Doc())
|
||||||
const [docValue, setDocValue] = useState()
|
const [docValue, setDocValue] = useState()
|
||||||
@@ -376,94 +387,111 @@ function App({ wsEndpoint }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Stack flex="1">
|
||||||
<h1>Streamwall ({location.host})</h1>
|
<Stack>
|
||||||
<div>
|
<h1>Streamwall ({location.host})</h1>
|
||||||
connection status: {isConnected ? 'connected' : 'connecting...'}
|
|
||||||
</div>
|
|
||||||
{delayState && (
|
|
||||||
<StreamDelayBox
|
|
||||||
delayState={delayState}
|
|
||||||
setStreamCensored={setStreamCensored}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<StyledDataContainer isConnected={isConnected}>
|
|
||||||
<div>
|
<div>
|
||||||
{range(0, gridCount).map((y) => (
|
connection status: {isConnected ? 'connected' : 'connecting...'}
|
||||||
<StyledGridLine>
|
|
||||||
{range(0, gridCount).map((x) => {
|
|
||||||
const idx = gridCount * y + x
|
|
||||||
const { isListening = false, isBlurred = false, state } =
|
|
||||||
stateIdxMap.get(idx) || {}
|
|
||||||
const { streamId } = sharedState.views?.[idx] || ''
|
|
||||||
const isDragHighlighted =
|
|
||||||
dragStart !== undefined &&
|
|
||||||
idxInBox(gridCount, dragStart, dragEnd, idx)
|
|
||||||
return (
|
|
||||||
<GridInput
|
|
||||||
idx={idx}
|
|
||||||
spaceValue={streamId}
|
|
||||||
isError={state && state.matches('displaying.error')}
|
|
||||||
isDisplaying={state && state.matches('displaying')}
|
|
||||||
isListening={isListening}
|
|
||||||
isBlurred={isBlurred}
|
|
||||||
isHighlighted={isDragHighlighted}
|
|
||||||
showDebug={showDebug}
|
|
||||||
onMouseDown={handleDragStart}
|
|
||||||
onMouseEnter={setDragEnd}
|
|
||||||
onFocus={handleFocusInput}
|
|
||||||
onBlur={handleBlurInput}
|
|
||||||
onChangeSpace={handleSetView}
|
|
||||||
onSetListening={handleSetListening}
|
|
||||||
onSetBlurred={handleSetBlurred}
|
|
||||||
onReloadView={handleReloadView}
|
|
||||||
onBrowse={handleBrowse}
|
|
||||||
onDevTools={handleDevTools}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</StyledGridLine>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
<label>
|
{delayState && (
|
||||||
<input
|
<StreamDelayBox
|
||||||
type="checkbox"
|
delayState={delayState}
|
||||||
value={showDebug}
|
setStreamCensored={setStreamCensored}
|
||||||
onChange={handleChangeShowDebug}
|
|
||||||
/>
|
/>
|
||||||
Show stream debug tools
|
)}
|
||||||
</label>
|
<StyledDataContainer isConnected={isConnected}>
|
||||||
<div>
|
<div>
|
||||||
{isConnected
|
{range(0, gridCount).map((y) => (
|
||||||
? normalStreams.map((row) => (
|
<StyledGridLine>
|
||||||
<StreamLine id={row._id} row={row} onClickId={handleClickId} />
|
{range(0, gridCount).map((x) => {
|
||||||
))
|
const idx = gridCount * y + x
|
||||||
: 'loading...'}
|
const { isListening = false, isBlurred = false, state } =
|
||||||
</div>
|
stateIdxMap.get(idx) || {}
|
||||||
<h2>Custom Streams</h2>
|
const { streamId } = sharedState.views?.[idx] || ''
|
||||||
<div>
|
const isDragHighlighted =
|
||||||
{/*
|
dragStart !== undefined &&
|
||||||
|
idxInBox(gridCount, dragStart, dragEnd, idx)
|
||||||
|
return (
|
||||||
|
<GridInput
|
||||||
|
idx={idx}
|
||||||
|
spaceValue={streamId}
|
||||||
|
isError={state && state.matches('displaying.error')}
|
||||||
|
isDisplaying={state && state.matches('displaying')}
|
||||||
|
isListening={isListening}
|
||||||
|
isBlurred={isBlurred}
|
||||||
|
isHighlighted={isDragHighlighted}
|
||||||
|
showDebug={showDebug}
|
||||||
|
onMouseDown={handleDragStart}
|
||||||
|
onMouseEnter={setDragEnd}
|
||||||
|
onFocus={handleFocusInput}
|
||||||
|
onBlur={handleBlurInput}
|
||||||
|
onChangeSpace={handleSetView}
|
||||||
|
onSetListening={handleSetListening}
|
||||||
|
onSetBlurred={handleSetBlurred}
|
||||||
|
onReloadView={handleReloadView}
|
||||||
|
onBrowse={handleBrowse}
|
||||||
|
onDevTools={handleDevTools}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</StyledGridLine>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
value={showDebug}
|
||||||
|
onChange={handleChangeShowDebug}
|
||||||
|
/>
|
||||||
|
Show stream debug tools
|
||||||
|
</label>
|
||||||
|
</StyledDataContainer>
|
||||||
|
</Stack>
|
||||||
|
<Stack flex="1" scroll={true}>
|
||||||
|
<StyledDataContainer isConnected={isConnected}>
|
||||||
|
<div>
|
||||||
|
{isConnected
|
||||||
|
? normalStreams.map((row) => (
|
||||||
|
<StreamLine
|
||||||
|
id={row._id}
|
||||||
|
row={row}
|
||||||
|
onClickId={handleClickId}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
: 'loading...'}
|
||||||
|
</div>
|
||||||
|
<h2>Custom Streams</h2>
|
||||||
|
<div>
|
||||||
|
{/*
|
||||||
Include an empty object at the end to create an extra input for a new custom stream.
|
Include an empty object at the end to create an extra input for a new custom stream.
|
||||||
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, { link: '', label: '', kind: 'video' }].map(
|
{[...customStreams, { link: '', label: '', kind: 'video' }].map(
|
||||||
({ link, label, kind }, idx) => (
|
({ link, label, kind }, idx) => (
|
||||||
<CustomStreamInput
|
<CustomStreamInput
|
||||||
key={idx}
|
key={idx}
|
||||||
idx={idx}
|
idx={idx}
|
||||||
link={link}
|
link={link}
|
||||||
label={label}
|
label={label}
|
||||||
kind={kind}
|
kind={kind}
|
||||||
onChange={handleChangeCustomStream}
|
onChange={handleChangeCustomStream}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</StyledDataContainer>
|
</StyledDataContainer>
|
||||||
</div>
|
</Stack>
|
||||||
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Stack = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: ${({ flex }) => flex};
|
||||||
|
${({ scroll }) => scroll && `overflow-y: auto`};
|
||||||
|
`
|
||||||
|
|
||||||
function StreamDelayBox({ delayState, setStreamCensored }) {
|
function StreamDelayBox({ delayState, setStreamCensored }) {
|
||||||
const handleToggleStreamCensored = useCallback(() => {
|
const handleToggleStreamCensored = useCallback(() => {
|
||||||
setStreamCensored(!delayState.isCensored)
|
setStreamCensored(!delayState.isCensored)
|
||||||
@@ -805,7 +833,13 @@ const StyledStreamLine = styled.div`
|
|||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
const script = document.getElementById('main-script')
|
const script = document.getElementById('main-script')
|
||||||
render(<App wsEndpoint={script.dataset.wsEndpoint} />, document.body)
|
render(
|
||||||
|
<>
|
||||||
|
<GlobalStyle />
|
||||||
|
<App wsEndpoint={script.dataset.wsEndpoint} />
|
||||||
|
</>,
|
||||||
|
document.body,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user