Merge pull request #151 from streamwall/bump-dependencies

Bump-dependencies
This commit is contained in:
Ben Menesini
2024-10-05 14:51:39 -07:00
committed by GitHub
5 changed files with 4681 additions and 2450 deletions

View File

@@ -7,10 +7,12 @@ module.exports = {
'\\.(css|less)$': 'identity-obj-proxy',
"^preact(/(.*)|$)": "preact$1"
},
testEnvironment: 'node',
transform: {
'^.+\\.jsx?$': 'babel-jest',
},
transformIgnorePatterns: [
'node_modules/(?!(jsondiffpatch)/)',
],
testPathIgnorePatterns: ['/node_modules/'],
coveragePathIgnorePatterns: ['/node_modules/'],
collectCoverage: true,

6645
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,62 +16,63 @@
"license": "MIT",
"dependencies": {
"@iarna/toml": "^2.2.5",
"@repeaterjs/repeater": "^3.0.4",
"@sentry/electron": "^4.4.0",
"base-x": "^4.0.0",
"chokidar": "^3.5.3",
"@repeaterjs/repeater": "^3.0.6",
"@sentry/electron": "^5.3.0",
"base-x": "^5.0.0",
"chokidar": "^3.6.0",
"color": "^4.2.3",
"dank-twitch-irc": "^3.3.0",
"ejs": "^3.1.9",
"electron": "^24.1.2",
"hls.js": "^1.4.0",
"jsondiffpatch": "^0.4.1",
"koa": "^2.14.2",
"dank-twitch-irc": "^4.3.0",
"ejs": "^3.1.10",
"electron": "^31.3.1",
"hls.js": "^1.5.14",
"jsondiffpatch": "^0.6.0",
"koa": "^2.15.3",
"koa-basic-auth": "^4.0.0",
"koa-easy-ws": "^2.1.0",
"koa-route": "^3.2.0",
"koa-route": "^4.0.1",
"koa-static": "^5.0.0",
"koa-views": "^8.0.0",
"koa-views": "^8.1.0",
"lodash": "^4.17.21",
"luxon": "^3.3.0",
"node-fetch": "^3.3.1",
"luxon": "^3.5.0",
"node-fetch": "^3.3.2",
"node-simple-cert": "0.0.1",
"preact": "^10.13.2",
"react-hotkeys-hook": "^4.4.0",
"preact": "^10.23.1",
"react-hotkeys-hook": "^4.5.0",
"reconnecting-websocket": "^4.4.0",
"styled-components": "^5.3.9",
"styled-components": "^6.1.12",
"svg-loaders-react": "^2.2.1",
"webpack-dev-server": "^4.13.2",
"ws": "^8.13.0",
"webpack-dev-server": "^5.0.4",
"ws": "^8.18.0",
"xstate": "^4.37.1",
"yargs": "^17.7.1",
"yjs": "^13.5.52"
"yargs": "^17.7.2",
"yjs": "^13.6.18"
},
"devDependencies": {
"@babel/core": "^7.21.4",
"@babel/plugin-proposal-decorators": "^7.24.1",
"@babel/core": "^7.25.2",
"@babel/plugin-proposal-decorators": "^7.24.7",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-transform-react-jsx": "^7.21.0",
"@babel/preset-env": "^7.24.5",
"@svgr/webpack": "^7.0.0",
"@babel/plugin-transform-react-jsx": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@svgr/webpack": "^8.1.0",
"babel-jest": "^29.7.0",
"babel-loader": "^9.1.2",
"babel-plugin-styled-components": "^2.1.1",
"babel-loader": "^9.1.3",
"babel-plugin-styled-components": "^2.1.4",
"bufferutil": "^4.0.8",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.3",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"file-loader": "^6.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.5.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-junit": "^16.0.0",
"prettier": "2.8.7",
"style-loader": "^3.3.2",
"supertest": "^6.3.3",
"utf-8-validate": "^5.0.10",
"webpack": "^5.79.0",
"webpack-cli": "^5.0.1"
"npm-check-updates": "^17.0.6",
"prettier": "3.3.3",
"style-loader": "^4.0.0",
"supertest": "^7.0.0",
"utf-8-validate": "^6.0.4",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4"
},
"browserslist": [
"electron 9.0"

View File

@@ -6,7 +6,8 @@ import { validRoles } from '../roles'
const scrypt = promisify(scryptCb)
const base62 = require('base-x')(
import baseX from 'base-x'
const base62 = baseX(
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
)

View File

@@ -13,6 +13,8 @@ import {
useRef,
} from 'preact/hooks'
import { State } from 'xstate'
import isPropValid from '@emotion/is-prop-valid';
import { StyleSheetManager } from 'styled-components';
import styled, { createGlobalStyle } from 'styled-components'
import { useHotkeys } from 'react-hotkeys-hook'
import Color from 'color'
@@ -580,214 +582,216 @@ function App({ wsEndpoint, role }) {
}
return (
<Stack flex="1">
<Stack>
<StyledHeader>
<h1>Streamwall ({location.host})</h1>
<div>
connection status: {isConnected ? 'connected' : 'connecting...'}
</div>
<div>role: {role}</div>
</StyledHeader>
{delayState && (
<StreamDelayBox
role={role}
delayState={delayState}
setStreamCensored={setStreamCensored}
setStreamRunning={setStreamRunning}
/>
)}
<StyledDataContainer isConnected={isConnected}>
{gridCount && (
<StyledGridContainer
onMouseMove={updateHoveringIdx}
windowWidth={windowWidth}
windowHeight={windowHeight}
>
<StyledGridInputs>
{range(0, gridCount).map((y) =>
range(0, gridCount).map((x) => {
const idx = gridCount * y + x
const { state } = stateIdxMap.get(idx) || {}
const { streamId } = sharedState.views?.[idx] ?? {}
const isDragHighlighted =
dragStart !== undefined &&
idxInBox(gridCount, dragStart, hoveringIdx, idx)
<StyleSheetManager shouldForwardProp={(prop) => isPropValid(prop) && !prop.startsWith('$')}>
<Stack flex="1">
<Stack>
<StyledHeader>
<h1>Streamwall ({location.host})</h1>
<div>
connection status: {isConnected ? 'connected' : 'connecting...'}
</div>
<div>role: {role}</div>
</StyledHeader>
{delayState && (
<StreamDelayBox
role={role}
delayState={delayState}
setStreamCensored={setStreamCensored}
setStreamRunning={setStreamRunning}
/>
)}
<StyledDataContainer isConnected={isConnected}>
{gridCount && (
<StyledGridContainer
onMouseMove={updateHoveringIdx}
windowWidth={windowWidth}
windowHeight={windowHeight}
>
<StyledGridInputs>
{range(0, gridCount).map((y) =>
range(0, gridCount).map((x) => {
const idx = gridCount * y + x
const { state } = stateIdxMap.get(idx) || {}
const { streamId } = sharedState.views?.[idx] ?? {}
const isDragHighlighted =
dragStart !== undefined &&
idxInBox(gridCount, dragStart, hoveringIdx, idx)
return (
<GridInput
style={{
width: `${100 / gridCount}%`,
height: `${100 / gridCount}%`,
left: `${(100 * x) / gridCount}%`,
top: `${(100 * y) / gridCount}%`,
}}
idx={idx}
spaceValue={streamId}
onChangeSpace={handleSetView}
isHighlighted={isDragHighlighted}
role={role}
onMouseDown={handleDragStart}
onFocus={handleFocusInput}
onBlur={handleBlurInput}
/>
)
}),
)}
</StyledGridInputs>
<StyledGridPreview>
{views.map(({ state, isListening }) => {
const { pos } = state.context
const { streamId } = sharedState.views[pos.spaces[0]] ?? {}
const data = streams.find((d) => d._id === streamId)
return (
<GridInput
<StyledGridPreviewBox
color={idColor(streamId)}
style={{
width: `${100 / gridCount}%`,
height: `${100 / gridCount}%`,
left: `${(100 * x) / gridCount}%`,
top: `${(100 * y) / gridCount}%`,
left: `${(100 * pos.x) / windowWidth}%`,
top: `${(100 * pos.y) / windowHeight}%`,
width: `${(100 * pos.width) / windowWidth}%`,
height: `${(100 * pos.height) / windowHeight}%`,
}}
idx={idx}
spaceValue={streamId}
onChangeSpace={handleSetView}
isHighlighted={isDragHighlighted}
pos={pos}
windowWidth={windowWidth}
windowHeight={windowHeight}
isListening={isListening}
isError={state && state.matches('displaying.error')}
>
<StyledGridInfo>
<StyledGridLabel>{streamId}</StyledGridLabel>
<div>{data?.source}</div>
</StyledGridInfo>
</StyledGridPreviewBox>
)
})}
</StyledGridPreview>
{views.map(
({ state, isListening, isBackgroundListening, isBlurred }) => {
const { pos } = state.context
const { streamId } = sharedState.views[pos.spaces[0]] ?? {}
return (
<GridControls
idx={pos.spaces[0]}
streamId={streamId}
style={{
left: `${(100 * pos.x) / windowWidth}%`,
top: `${(100 * pos.y) / windowHeight}%`,
width: `${(100 * pos.width) / windowWidth}%`,
height: `${(100 * pos.height) / windowHeight}%`,
}}
isDisplaying={state && state.matches('displaying')}
isListening={isListening}
isBackgroundListening={isBackgroundListening}
isBlurred={isBlurred}
isSwapping={pos.spaces.includes(swapStartIdx)}
showDebug={showDebug}
role={role}
onSetListening={handleSetListening}
onSetBackgroundListening={handleSetBackgroundListening}
onSetBlurred={handleSetBlurred}
onReloadView={handleReloadView}
onSwapView={handleSwapView}
onRotateView={handleRotateStream}
onBrowse={handleBrowse}
onDevTools={handleDevTools}
onMouseDown={handleDragStart}
onFocus={handleFocusInput}
onBlur={handleBlurInput}
/>
)
}),
},
)}
</StyledGridInputs>
<StyledGridPreview>
{views.map(({ state, isListening }) => {
const { pos } = state.context
const { streamId } = sharedState.views[pos.spaces[0]] ?? {}
const data = streams.find((d) => d._id === streamId)
return (
<StyledGridPreviewBox
color={idColor(streamId)}
style={{
left: `${(100 * pos.x) / windowWidth}%`,
top: `${(100 * pos.y) / windowHeight}%`,
width: `${(100 * pos.width) / windowWidth}%`,
height: `${(100 * pos.height) / windowHeight}%`,
}}
pos={pos}
windowWidth={windowWidth}
windowHeight={windowHeight}
isListening={isListening}
isError={state && state.matches('displaying.error')}
>
<StyledGridInfo>
<StyledGridLabel>{streamId}</StyledGridLabel>
<div>{data?.source}</div>
</StyledGridInfo>
</StyledGridPreviewBox>
)
})}
</StyledGridPreview>
{views.map(
({ state, isListening, isBackgroundListening, isBlurred }) => {
const { pos } = state.context
const { streamId } = sharedState.views[pos.spaces[0]] ?? {}
return (
<GridControls
idx={pos.spaces[0]}
streamId={streamId}
style={{
left: `${(100 * pos.x) / windowWidth}%`,
top: `${(100 * pos.y) / windowHeight}%`,
width: `${(100 * pos.width) / windowWidth}%`,
height: `${(100 * pos.height) / windowHeight}%`,
}}
isDisplaying={state && state.matches('displaying')}
isListening={isListening}
isBackgroundListening={isBackgroundListening}
isBlurred={isBlurred}
isSwapping={pos.spaces.includes(swapStartIdx)}
showDebug={showDebug}
role={role}
onSetListening={handleSetListening}
onSetBackgroundListening={handleSetBackgroundListening}
onSetBlurred={handleSetBlurred}
onReloadView={handleReloadView}
onSwapView={handleSwapView}
onRotateView={handleRotateStream}
onBrowse={handleBrowse}
onDevTools={handleDevTools}
onMouseDown={handleDragStart}
</StyledGridContainer>
)}
{(roleCan(role, 'dev-tools') || roleCan(role, 'browse')) && (
<label>
<input
type="checkbox"
value={showDebug}
onChange={handleChangeShowDebug}
/>
Show stream debug tools
</label>
)}
<Facts />
</StyledDataContainer>
</Stack>
<Stack flex="1" scroll={true} minHeight={200}>
<StyledDataContainer isConnected={isConnected}>
{isConnected ? (
<div>
<h3>Live</h3>
<StreamList rows={liveStreams} />
<h3>Offline / Unknown</h3>
<StreamList rows={otherStreams} />
</div>
) : (
<div>loading...</div>
)}
{roleCan(role, 'update-custom-stream') &&
roleCan(role, 'delete-custom-stream') && (
<>
<h2>Custom Streams</h2>
<div>
{/*
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.
*/}
{customStreams.map(({ link, label, kind }, idx) => (
<CustomStreamInput
key={idx}
link={link}
label={label}
kind={kind}
onChange={handleChangeCustomStream}
onDelete={handleDeleteCustomStream}
/>
))}
<CreateCustomStreamInput
onCreate={handleChangeCustomStream}
/>
)
},
</div>
</>
)}
</StyledGridContainer>
)}
{(roleCan(role, 'dev-tools') || roleCan(role, 'browse')) && (
<label>
<input
type="checkbox"
value={showDebug}
onChange={handleChangeShowDebug}
/>
Show stream debug tools
</label>
)}
<Facts />
</StyledDataContainer>
</Stack>
<Stack flex="1" scroll={true} minHeight={200}>
<StyledDataContainer isConnected={isConnected}>
{isConnected ? (
<div>
<h3>Live</h3>
<StreamList rows={liveStreams} />
<h3>Offline / Unknown</h3>
<StreamList rows={otherStreams} />
</div>
) : (
<div>loading...</div>
)}
{roleCan(role, 'update-custom-stream') &&
roleCan(role, 'delete-custom-stream') && (
{roleCan(role, 'edit-tokens') && authState && (
<>
<h2>Custom Streams</h2>
<h2>Access</h2>
<div>
{/*
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.
*/}
{customStreams.map(({ link, label, kind }, idx) => (
<CustomStreamInput
key={idx}
link={link}
label={label}
kind={kind}
onChange={handleChangeCustomStream}
onDelete={handleDeleteCustomStream}
<CreateInviteInput onCreateInvite={handleCreateInvite} />
<h3>Invites</h3>
{newInvite && (
<StyledNewInviteBox>
Invite link created:{' '}
<a
href={`/invite/${newInvite.secret}`}
onClick={preventLinkClick}
>
"{newInvite.name}"
</a>
</StyledNewInviteBox>
)}
{authState.invites.map(({ id, name, role }) => (
<AuthTokenLine
id={id}
name={name}
role={role}
onDelete={handleDeleteToken}
/>
))}
<h3>Sessions</h3>
{authState.sessions.map(({ id, name, role }) => (
<AuthTokenLine
id={id}
name={name}
role={role}
onDelete={handleDeleteToken}
/>
))}
<CreateCustomStreamInput
onCreate={handleChangeCustomStream}
/>
</div>
</>
)}
{roleCan(role, 'edit-tokens') && authState && (
<>
<h2>Access</h2>
<div>
<CreateInviteInput onCreateInvite={handleCreateInvite} />
<h3>Invites</h3>
{newInvite && (
<StyledNewInviteBox>
Invite link created:{' '}
<a
href={`/invite/${newInvite.secret}`}
onClick={preventLinkClick}
>
"{newInvite.name}"
</a>
</StyledNewInviteBox>
)}
{authState.invites.map(({ id, name, role }) => (
<AuthTokenLine
id={id}
name={name}
role={role}
onDelete={handleDeleteToken}
/>
))}
<h3>Sessions</h3>
{authState.sessions.map(({ id, name, role }) => (
<AuthTokenLine
id={id}
name={name}
role={role}
onDelete={handleDeleteToken}
/>
))}
</div>
</>
)}
</StyledDataContainer>
</StyledDataContainer>
</Stack>
</Stack>
</Stack>
</StyleSheetManager>
)
}
@@ -888,9 +892,9 @@ function StreamLine({
return (
<StyledStreamLine>
<StyledId
disabled={disabled}
$disabled={disabled}
onMouseDown={disabled ? null : handleMouseDownId}
color={idColor(id)}
$color={idColor(id)}
>
{id}
</StyledId>
@@ -1120,7 +1124,7 @@ function GridControls({
{roleCan(role, 'set-listening-view') && (
<StyledButton
isActive={isListening || isBackgroundListening}
activeColor={isListening ? 'red' : Color('red').desaturate(0.5)}
activeColor={isListening ? 'red' : Color('red').desaturate(0.5).hsl().string()}
onClick={handleListeningClick}
tabIndex={1}
>
@@ -1234,8 +1238,8 @@ const StyledButton = styled.button`
${({ isActive, activeColor = 'red' }) =>
isActive &&
`
border-color: ${activeColor};
background: ${Color(activeColor).desaturate(0.5).lighten(0.5)};
border-color: ${Color(activeColor).hsl().string()};
background: ${Color(activeColor).desaturate(0.5).lighten(0.5).hsl().string()};
`};
&:focus {
@@ -1271,8 +1275,8 @@ const StyledGridPreviewBox = styled.div.attrs((props) => ({
align-items: center;
justify-content: center;
position: absolute;
background: ${({ color }) => color.lightness(50) || '#333'};
border: 0 solid ${({ isError }) => (isError ? 'red' : 'black')};
background: ${({ color }) => Color(color).lightness(50).hsl().string() || '#333'};
border: 0 solid ${({ isError }) => (isError ? Color('red').hsl().string() : Color('black').hsl().string() )};
border-left-width: ${({ pos, borderWidth }) =>
pos.x === 0 ? 0 : borderWidth}px;
border-right-width: ${({ pos, borderWidth, windowWidth }) =>
@@ -1331,7 +1335,7 @@ const StyledGridInput = styled(LazyChangeInput)`
border: none;
padding: 0;
background: ${({ color, isHighlighted }) =>
isHighlighted ? color.lightness(90) : color.lightness(75)};
isHighlighted ? Color(color).lightness(90).hsl().string() : Color(color).lightness(75).hsl().string() };
font-size: 20px;
text-align: center;
@@ -1368,13 +1372,13 @@ const StyledGridContainer = styled.div.attrs((props) => ({
const StyledId = styled.div`
flex-shrink: 0;
margin-right: 5px;
background: ${({ color }) => color.lightness(50) || '#333'};
background: ${({ $color }) => Color($color).lightness(50).hsl().string() || '#333'};
color: white;
padding: 3px;
border-radius: 5px;
width: 3em;
text-align: center;
cursor: ${({ disabled }) => (disabled ? 'normal' : 'pointer')};
cursor: ${({ $disabled }) => ($disabled ? 'normal' : 'pointer')};
`
const StyledStreamLine = styled.div`