mirror of
https://github.com/streamwall/streamwall.git
synced 2026-01-24 14:12:48 -05:00
Split gridCount into independent rows and cols configs
This commit is contained in:
@@ -256,10 +256,11 @@ export function ControlUI({
|
|||||||
role,
|
role,
|
||||||
} = connection
|
} = connection
|
||||||
const {
|
const {
|
||||||
gridCount,
|
cols,
|
||||||
|
rows,
|
||||||
width: windowWidth,
|
width: windowWidth,
|
||||||
height: windowHeight,
|
height: windowHeight,
|
||||||
} = config ?? { gridCount: null, width: null, height: null }
|
} = config ?? { cols: null, rows: null, width: null, height: null }
|
||||||
|
|
||||||
const [showDebug, setShowDebug] = useState(false)
|
const [showDebug, setShowDebug] = useState(false)
|
||||||
const handleChangeShowDebug = useCallback<
|
const handleChangeShowDebug = useCallback<
|
||||||
@@ -311,20 +312,24 @@ export function ControlUI({
|
|||||||
const [hoveringIdx, setHoveringIdx] = useState<number>()
|
const [hoveringIdx, setHoveringIdx] = useState<number>()
|
||||||
const updateHoveringIdx = useCallback(
|
const updateHoveringIdx = useCallback(
|
||||||
(ev: MouseEvent) => {
|
(ev: MouseEvent) => {
|
||||||
if (gridCount == null || !(ev.currentTarget instanceof HTMLElement)) {
|
if (
|
||||||
|
cols == null ||
|
||||||
|
rows == null ||
|
||||||
|
!(ev.currentTarget instanceof HTMLElement)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { width, height, left, top } =
|
const { width, height, left, top } =
|
||||||
ev.currentTarget.getBoundingClientRect()
|
ev.currentTarget.getBoundingClientRect()
|
||||||
const x = Math.floor(ev.clientX - left)
|
const x = Math.floor(ev.clientX - left)
|
||||||
const y = Math.floor(ev.clientY - top)
|
const y = Math.floor(ev.clientY - top)
|
||||||
const spaceWidth = width / gridCount
|
const spaceWidth = width / cols
|
||||||
const spaceHeight = height / gridCount
|
const spaceHeight = height / rows
|
||||||
const idx =
|
const idx =
|
||||||
Math.floor(y / spaceHeight) * gridCount + Math.floor(x / spaceWidth)
|
Math.floor(y / spaceHeight) * cols + Math.floor(x / spaceWidth)
|
||||||
setHoveringIdx(idx)
|
setHoveringIdx(idx)
|
||||||
},
|
},
|
||||||
[setHoveringIdx, gridCount],
|
[setHoveringIdx, cols, rows],
|
||||||
)
|
)
|
||||||
const [dragStart, setDragStart] = useState<number | undefined>()
|
const [dragStart, setDragStart] = useState<number | undefined>()
|
||||||
const handleDragStart = useCallback(
|
const handleDragStart = useCallback(
|
||||||
@@ -347,14 +352,19 @@ export function ControlUI({
|
|||||||
)
|
)
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
function endDrag() {
|
function endDrag() {
|
||||||
if (dragStart == null || gridCount == null || hoveringIdx == null) {
|
if (
|
||||||
|
dragStart == null ||
|
||||||
|
cols == null ||
|
||||||
|
rows == null ||
|
||||||
|
hoveringIdx == null
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stateDoc.transact(() => {
|
stateDoc.transact(() => {
|
||||||
const viewsState = stateDoc.getMap<Y.Map<string | undefined>>('views')
|
const viewsState = stateDoc.getMap<Y.Map<string | undefined>>('views')
|
||||||
const streamId = viewsState.get(String(dragStart))?.get('streamId')
|
const streamId = viewsState.get(String(dragStart))?.get('streamId')
|
||||||
for (let idx = 0; idx < gridCount ** 2; idx++) {
|
for (let idx = 0; idx < cols * rows; idx++) {
|
||||||
if (idxInBox(gridCount, dragStart, hoveringIdx, idx)) {
|
if (idxInBox(cols, dragStart, hoveringIdx, idx)) {
|
||||||
viewsState.get(String(idx))?.set('streamId', streamId)
|
viewsState.get(String(idx))?.set('streamId', streamId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,7 +472,7 @@ export function ControlUI({
|
|||||||
|
|
||||||
const handleClickId = useCallback(
|
const handleClickId = useCallback(
|
||||||
(streamId: string) => {
|
(streamId: string) => {
|
||||||
if (gridCount == null || sharedState == null) {
|
if (cols == null || rows == null || sharedState == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +487,7 @@ export function ControlUI({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableIdx = range(gridCount * gridCount).find(
|
const availableIdx = range(cols * rows).find(
|
||||||
(i) => !sharedState.views[i].streamId,
|
(i) => !sharedState.views[i].streamId,
|
||||||
)
|
)
|
||||||
if (availableIdx === undefined) {
|
if (availableIdx === undefined) {
|
||||||
@@ -485,7 +495,7 @@ export function ControlUI({
|
|||||||
}
|
}
|
||||||
handleSetView(availableIdx, streamId)
|
handleSetView(availableIdx, streamId)
|
||||||
},
|
},
|
||||||
[gridCount, sharedState, focusedInputIdx],
|
[cols, rows, sharedState, focusedInputIdx],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleChangeCustomStream = useCallback(
|
const handleChangeCustomStream = useCallback(
|
||||||
@@ -660,7 +670,7 @@ export function ControlUI({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<StyledDataContainer isConnected={isConnected}>
|
<StyledDataContainer isConnected={isConnected}>
|
||||||
{gridCount && (
|
{cols != null && rows != null && (
|
||||||
<StyledGridContainer
|
<StyledGridContainer
|
||||||
className="grid"
|
className="grid"
|
||||||
onMouseMove={updateHoveringIdx}
|
onMouseMove={updateHoveringIdx}
|
||||||
@@ -668,21 +678,21 @@ export function ControlUI({
|
|||||||
windowHeight={windowHeight}
|
windowHeight={windowHeight}
|
||||||
>
|
>
|
||||||
<StyledGridInputs>
|
<StyledGridInputs>
|
||||||
{range(0, gridCount).map((y) =>
|
{range(0, rows).map((y) =>
|
||||||
range(0, gridCount).map((x) => {
|
range(0, cols).map((x) => {
|
||||||
const idx = gridCount * y + x
|
const idx = cols * y + x
|
||||||
const { streamId } = sharedState?.views?.[idx] ?? {}
|
const { streamId } = sharedState?.views?.[idx] ?? {}
|
||||||
const isDragHighlighted =
|
const isDragHighlighted =
|
||||||
dragStart != null &&
|
dragStart != null &&
|
||||||
hoveringIdx != null &&
|
hoveringIdx != null &&
|
||||||
idxInBox(gridCount, dragStart, hoveringIdx, idx)
|
idxInBox(cols, dragStart, hoveringIdx, idx)
|
||||||
return (
|
return (
|
||||||
<GridInput
|
<GridInput
|
||||||
style={{
|
style={{
|
||||||
width: `${100 / gridCount}%`,
|
width: `${100 / cols}%`,
|
||||||
height: `${100 / gridCount}%`,
|
height: `${100 / rows}%`,
|
||||||
left: `${(100 * x) / gridCount}%`,
|
left: `${(100 * x) / cols}%`,
|
||||||
top: `${(100 * y) / gridCount}%`,
|
top: `${(100 * y) / rows}%`,
|
||||||
}}
|
}}
|
||||||
idx={idx}
|
idx={idx}
|
||||||
spaceValue={streamId ?? ''}
|
spaceValue={streamId ?? ''}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ export interface ViewContent {
|
|||||||
export type ViewContentMap = Map<string, ViewContent>
|
export type ViewContentMap = Map<string, ViewContent>
|
||||||
|
|
||||||
export function boxesFromViewContentMap(
|
export function boxesFromViewContentMap(
|
||||||
width: number,
|
cols: number,
|
||||||
height: number,
|
rows: number,
|
||||||
viewContentMap: ViewContentMap,
|
viewContentMap: ViewContentMap,
|
||||||
) {
|
) {
|
||||||
const boxes = []
|
const boxes = []
|
||||||
@@ -28,7 +28,7 @@ export function boxesFromViewContentMap(
|
|||||||
y: number,
|
y: number,
|
||||||
content: ViewContent | undefined,
|
content: ViewContent | undefined,
|
||||||
) {
|
) {
|
||||||
const checkIdx = width * y + x
|
const checkIdx = cols * y + x
|
||||||
return (
|
return (
|
||||||
!visited.has(checkIdx) &&
|
!visited.has(checkIdx) &&
|
||||||
isEqual(viewContentMap.get(String(checkIdx)), content)
|
isEqual(viewContentMap.get(String(checkIdx)), content)
|
||||||
@@ -36,28 +36,28 @@ export function boxesFromViewContentMap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findLargestBox(x: number, y: number) {
|
function findLargestBox(x: number, y: number) {
|
||||||
const idx = width * y + x
|
const idx = cols * y + x
|
||||||
const spaces = [idx]
|
const spaces = [idx]
|
||||||
const content = viewContentMap.get(String(idx))
|
const content = viewContentMap.get(String(idx))
|
||||||
|
|
||||||
let maxY
|
let maxY
|
||||||
for (maxY = y + 1; maxY < height; maxY++) {
|
for (maxY = y + 1; maxY < rows; maxY++) {
|
||||||
if (!isPosContent(x, maxY, content)) {
|
if (!isPosContent(x, maxY, content)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
spaces.push(width * maxY + x)
|
spaces.push(cols * maxY + x)
|
||||||
}
|
}
|
||||||
|
|
||||||
let cx = x
|
let cx = x
|
||||||
let cy = y
|
let cy = y
|
||||||
scan: for (cx = x + 1; cx < width; cx++) {
|
scan: for (cx = x + 1; cx < cols; cx++) {
|
||||||
for (cy = y; cy < maxY; cy++) {
|
for (cy = y; cy < maxY; cy++) {
|
||||||
if (!isPosContent(cx, cy, content)) {
|
if (!isPosContent(cx, cy, content)) {
|
||||||
break scan
|
break scan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let cy = y; cy < maxY; cy++) {
|
for (let cy = y; cy < maxY; cy++) {
|
||||||
spaces.push(width * cy + cx)
|
spaces.push(cols * cy + cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const w = cx - x
|
const w = cx - x
|
||||||
@@ -66,9 +66,9 @@ export function boxesFromViewContentMap(
|
|||||||
return { content, x, y, w, h, spaces }
|
return { content, x, y, w, h, spaces }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let y = 0; y < width; y++) {
|
for (let y = 0; y < rows; y++) {
|
||||||
for (let x = 0; x < height; x++) {
|
for (let x = 0; x < cols; x++) {
|
||||||
const idx = width * y + x
|
const idx = cols * y + x
|
||||||
if (visited.has(idx) || viewContentMap.get(String(idx)) === undefined) {
|
if (visited.has(idx) || viewContentMap.get(String(idx)) === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -84,21 +84,21 @@ export function boxesFromViewContentMap(
|
|||||||
return boxes
|
return boxes
|
||||||
}
|
}
|
||||||
|
|
||||||
export function idxToCoords(gridCount: number, idx: number) {
|
export function idxToCoords(cols: number, idx: number) {
|
||||||
const x = idx % gridCount
|
const x = idx % cols
|
||||||
const y = Math.floor(idx / gridCount)
|
const y = Math.floor(idx / cols)
|
||||||
return { x, y }
|
return { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function idxInBox(
|
export function idxInBox(
|
||||||
gridCount: number,
|
cols: number,
|
||||||
start: number,
|
start: number,
|
||||||
end: number,
|
end: number,
|
||||||
idx: number,
|
idx: number,
|
||||||
) {
|
) {
|
||||||
const { x: startX, y: startY } = idxToCoords(gridCount, start)
|
const { x: startX, y: startY } = idxToCoords(cols, start)
|
||||||
const { x: endX, y: endY } = idxToCoords(gridCount, end)
|
const { x: endX, y: endY } = idxToCoords(cols, end)
|
||||||
const { x, y } = idxToCoords(gridCount, idx)
|
const { x, y } = idxToCoords(cols, idx)
|
||||||
const lowX = Math.min(startX, endX)
|
const lowX = Math.min(startX, endX)
|
||||||
const highX = Math.max(startX, endX)
|
const highX = Math.max(startX, endX)
|
||||||
const lowY = Math.min(startY, endY)
|
const lowY = Math.min(startY, endY)
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import type { ViewContent, ViewPos } from './geometry.ts'
|
|||||||
import type { StreamwallRole } from './roles.ts'
|
import type { StreamwallRole } from './roles.ts'
|
||||||
|
|
||||||
export interface StreamWindowConfig {
|
export interface StreamWindowConfig {
|
||||||
gridCount: number
|
cols: number
|
||||||
|
rows: number
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
x?: number
|
x?: number
|
||||||
|
|||||||
@@ -198,11 +198,11 @@ export default class StreamWindow extends EventEmitter<StreamWindowEventMap> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setViews(viewContentMap: ViewContentMap, streams: StreamList) {
|
setViews(viewContentMap: ViewContentMap, streams: StreamList) {
|
||||||
const { width, height, gridCount } = this.config
|
const { width, height, cols, rows } = this.config
|
||||||
const spaceWidth = Math.floor(width / gridCount)
|
const spaceWidth = Math.floor(width / cols)
|
||||||
const spaceHeight = Math.floor(height / gridCount)
|
const spaceHeight = Math.floor(height / rows)
|
||||||
const { win, views } = this
|
const { win, views } = this
|
||||||
const boxes = boxesFromViewContentMap(gridCount, gridCount, viewContentMap)
|
const boxes = boxesFromViewContentMap(cols, rows, viewContentMap)
|
||||||
const remainingBoxes = new Set(boxes)
|
const remainingBoxes = new Set(boxes)
|
||||||
const unusedViews = new Set(views.values())
|
const unusedViews = new Set(views.values())
|
||||||
const viewsToDisplay = []
|
const viewsToDisplay = []
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ const SENTRY_DSN =
|
|||||||
export interface StreamwallConfig {
|
export interface StreamwallConfig {
|
||||||
help: boolean
|
help: boolean
|
||||||
grid: {
|
grid: {
|
||||||
count: number
|
cols: number
|
||||||
|
rows: number
|
||||||
}
|
}
|
||||||
window: {
|
window: {
|
||||||
x?: number
|
x?: number
|
||||||
@@ -97,8 +98,12 @@ function parseArgs(): StreamwallConfig {
|
|||||||
.config('config', (configPath) => {
|
.config('config', (configPath) => {
|
||||||
return TOML.parse(fs.readFileSync(configPath, 'utf-8'))
|
return TOML.parse(fs.readFileSync(configPath, 'utf-8'))
|
||||||
})
|
})
|
||||||
.group(['grid.count'], 'Grid dimensions')
|
.group(['grid.cols', 'grid.rows'], 'Grid dimensions')
|
||||||
.option('grid.count', {
|
.option('grid.cols', {
|
||||||
|
number: true,
|
||||||
|
default: 3,
|
||||||
|
})
|
||||||
|
.option('grid.rows', {
|
||||||
number: true,
|
number: true,
|
||||||
default: 3,
|
default: 3,
|
||||||
})
|
})
|
||||||
@@ -267,7 +272,8 @@ async function main(argv: ReturnType<typeof parseArgs>) {
|
|||||||
const overlayStreamData = new LocalStreamData()
|
const overlayStreamData = new LocalStreamData()
|
||||||
|
|
||||||
const streamWindowConfig = {
|
const streamWindowConfig = {
|
||||||
gridCount: argv.grid.count,
|
cols: argv.grid.cols,
|
||||||
|
rows: argv.grid.rows,
|
||||||
width: argv.window.width,
|
width: argv.window.width,
|
||||||
height: argv.window.height,
|
height: argv.window.height,
|
||||||
x: argv.window.x,
|
x: argv.window.x,
|
||||||
@@ -337,7 +343,7 @@ async function main(argv: ReturnType<typeof parseArgs>) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
stateDoc.transact(() => {
|
stateDoc.transact(() => {
|
||||||
for (let i = 0; i < argv.grid.count ** 2; i++) {
|
for (let i = 0; i < argv.grid.cols * argv.grid.rows; i++) {
|
||||||
if (viewsState.has(String(i))) {
|
if (viewsState.has(String(i))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user