polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
404 lines • 14.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.GridManager = void 0;
const contrib = __importStar(require("blessed-contrib"));
class GridManager {
constructor(screen, eventBus, rows = 12, cols = 12) {
this.cells = [];
this.layouts = new Map();
this.screen = screen;
this.eventBus = eventBus;
this.rows = rows;
this.cols = cols;
this.currentLayout = 'default';
this.initializeGrid();
this.initializeCells();
this.setupEventListeners();
this.registerDefaultLayouts();
}
initializeGrid() {
this.grid = contrib.grid({
rows: this.rows,
cols: this.cols,
screen: this.screen,
});
}
initializeCells() {
this.cells = [];
for (let row = 0; row < this.rows; row++) {
this.cells[row] = [];
for (let col = 0; col < this.cols; col++) {
if (this.cells[row]) {
this.cells[row][col] = {
position: { x: col, y: row, width: 1, height: 1 },
occupied: false,
};
}
}
}
}
setupEventListeners() {
if (this.screen?.on) {
this.screen.on('resize', () => {
this.handleResize();
});
}
this.eventBus.on('layout:change', (data) => {
this.setLayout(data.layout);
});
this.eventBus.on('component:created', (_data) => {
this.handleComponentCreated();
});
this.eventBus.on('component:destroyed', (data) => {
this.handleComponentDestroyed(data);
});
}
handleResize() {
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.resizeTimeout = setTimeout(() => {
this.recalculateLayout();
const envWidth = process.env['POLYV_TERMINAL_WIDTH'];
const envHeight = process.env['POLYV_TERMINAL_HEIGHT'];
let width = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
let height = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
if (envWidth && parseInt(envWidth) > 0) {
width = parseInt(envWidth);
}
if (envHeight && parseInt(envHeight) > 0) {
height = parseInt(envHeight);
}
if (this.screen?.width && this.screen.width > 1) {
width = this.screen.width;
}
if (this.screen?.height && this.screen.height > 1) {
height = this.screen.height;
}
this.eventBus.emit('terminal:resize', {
width,
height,
});
}, 100);
}
handleComponentCreated() {
}
handleComponentDestroyed(data) {
this.removeComponentFromGrid(data.componentId);
}
registerDefaultLayouts() {
this.layouts.set('default', {
id: 'default',
name: 'default',
isBuiltIn: true,
grid: { cols: 12, rows: 12, cellWidth: 10, cellHeight: 3, padding: 1 },
responsive: true,
minTerminalSize: { width: 120, height: 30 },
components: [
{
type: 'stream-metrics',
position: { x: 0, y: 0, width: 8, height: 6 },
size: { minWidth: 40, minHeight: 15 },
config: {},
},
{
type: 'channel-status',
position: { x: 8, y: 0, width: 4, height: 6 },
size: { minWidth: 30, minHeight: 15 },
config: {},
},
{
type: 'system-resources',
position: { x: 0, y: 6, width: 6, height: 6 },
size: { minWidth: 30, minHeight: 15 },
config: {},
},
{
type: 'activity-log',
position: { x: 6, y: 6, width: 6, height: 6 },
size: { minWidth: 30, minHeight: 15 },
config: {},
},
],
});
this.layouts.set('compact', {
id: 'compact',
name: 'compact',
isBuiltIn: true,
grid: { cols: 12, rows: 12, cellWidth: 8, cellHeight: 2, padding: 1 },
responsive: true,
minTerminalSize: { width: 80, height: 24 },
components: [
{
type: 'stream-metrics',
position: { x: 0, y: 0, width: 12, height: 8 },
size: { minWidth: 40, minHeight: 15 },
config: {},
},
{
type: 'channel-status',
position: { x: 0, y: 8, width: 12, height: 4 },
size: { minWidth: 30, minHeight: 8 },
config: {},
},
],
});
this.layouts.set('single', {
id: 'single',
name: 'single',
isBuiltIn: true,
grid: { cols: 12, rows: 12, cellWidth: 6, cellHeight: 2, padding: 1 },
responsive: true,
minTerminalSize: { width: 60, height: 20 },
components: [
{
type: 'stream-metrics',
position: { x: 0, y: 0, width: 12, height: 12 },
size: { minWidth: 40, minHeight: 15 },
config: {},
},
],
});
}
setLayout(layoutName) {
const layout = this.layouts.get(layoutName);
if (!layout) {
throw new Error(`Layout '${layoutName}' not found`);
}
const envWidth = process.env['POLYV_TERMINAL_WIDTH'];
const envHeight = process.env['POLYV_TERMINAL_HEIGHT'];
let width = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
let height = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
if (envWidth && parseInt(envWidth) > 0) {
width = parseInt(envWidth);
}
if (envHeight && parseInt(envHeight) > 0) {
height = parseInt(envHeight);
}
if (this.screen.width && this.screen.width > 1) {
width = this.screen.width;
}
if (this.screen.height && this.screen.height > 1) {
height = this.screen.height;
}
const terminalSize = { width, height };
if (terminalSize.width < layout.minTerminalSize.width ||
terminalSize.height < layout.minTerminalSize.height) {
throw new Error(`Terminal size too small for layout '${layoutName}'. ` +
`Required: ${layout.minTerminalSize.width}x${layout.minTerminalSize.height}, ` +
`Current: ${terminalSize.width}x${terminalSize.height}`);
}
this.currentLayout = layoutName;
this.clearGrid();
this.eventBus.emit('layout:changed', {
layout: layoutName,
config: layout,
timestamp: new Date(),
});
}
addComponent(component, position) {
if (!this.canPlaceComponent(position)) {
throw new Error(`Cannot place component at position ${JSON.stringify(position)}`);
}
if (!this.grid) {
throw new Error('Grid is not initialized. Make sure blessed-contrib is properly imported and initialized.');
}
const widget = this.grid.set(position.y, position.x, position.height, position.width, component.getWidget(), {});
this.markCellsOccupied(position, component);
this.eventBus.emit('grid:componentAdded', {
componentId: component.getState().id,
position,
timestamp: new Date(),
});
return widget;
}
removeComponent(componentId) {
const component = this.findComponentById(componentId);
if (!component) {
return false;
}
this.markCellsUnoccupied(component.position);
this.eventBus.emit('grid:componentRemoved', {
componentId,
timestamp: new Date(),
});
return true;
}
canPlaceComponent(position) {
if (position.x < 0 || position.y < 0 ||
position.x + position.width > this.cols ||
position.y + position.height > this.rows) {
return false;
}
for (let row = position.y; row < position.y + position.height; row++) {
for (let col = position.x; col < position.x + position.width; col++) {
if (this.cells[row]?.[col]?.occupied) {
return false;
}
}
}
return true;
}
getOptimalPosition(size) {
const width = Math.min(size.maxWidth || size.minWidth, this.cols);
const height = Math.min(size.maxHeight || size.minHeight, this.rows);
for (let row = 0; row <= this.rows - height; row++) {
for (let col = 0; col <= this.cols - width; col++) {
const position = { x: col, y: row, width, height };
if (this.canPlaceComponent(position)) {
return position;
}
}
}
return null;
}
getAvailableLayouts() {
return Array.from(this.layouts.keys());
}
getCurrentLayout() {
return this.currentLayout;
}
getLayoutConfig(layoutName) {
return this.layouts.get(layoutName);
}
registerLayout(layout) {
this.layouts.set(layout.name, layout);
}
getGrid() {
return this.grid;
}
getGridSize() {
return { rows: this.rows, cols: this.cols };
}
getOccupiedCells() {
const occupied = [];
for (let row = 0; row < this.rows; row++) {
for (let col = 0; col < this.cols; col++) {
const cell = this.cells[row]?.[col];
if (cell?.occupied) {
occupied.push(cell.position);
}
}
}
return occupied;
}
findComponentById(componentId) {
for (let row = 0; row < this.rows; row++) {
for (let col = 0; col < this.cols; col++) {
const cell = this.cells[row]?.[col];
if (cell?.component && cell.component.getState().id === componentId) {
return cell;
}
}
}
return undefined;
}
markCellsOccupied(position, component) {
for (let row = position.y; row < position.y + position.height; row++) {
for (let col = position.x; col < position.x + position.width; col++) {
const cell = this.cells[row]?.[col];
if (cell) {
cell.occupied = true;
cell.component = component;
}
}
}
}
markCellsUnoccupied(position) {
for (let row = position.y; row < position.y + position.height; row++) {
for (let col = position.x; col < position.x + position.width; col++) {
const cell = this.cells[row]?.[col];
if (cell) {
cell.occupied = false;
cell.component = undefined;
}
}
}
}
removeComponentFromGrid(componentId) {
const component = this.findComponentById(componentId);
if (component) {
this.markCellsUnoccupied(component.position);
}
}
clearGrid() {
for (let row = 0; row < this.rows; row++) {
for (let col = 0; col < this.cols; col++) {
const cell = this.cells[row]?.[col];
if (cell) {
cell.occupied = false;
cell.component = undefined;
}
}
}
}
recalculateLayout() {
const layout = this.layouts.get(this.currentLayout);
if (!layout)
return;
const envWidth = process.env['POLYV_TERMINAL_WIDTH'];
const envHeight = process.env['POLYV_TERMINAL_HEIGHT'];
let width = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
let height = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
if (envWidth && parseInt(envWidth) > 0) {
width = parseInt(envWidth);
}
if (envHeight && parseInt(envHeight) > 0) {
height = parseInt(envHeight);
}
if (this.screen.width && this.screen.width > 1) {
width = this.screen.width;
}
if (this.screen.height && this.screen.height > 1) {
height = this.screen.height;
}
this.eventBus.emit('grid:recalculated', {
layout: this.currentLayout,
terminalSize: { width, height },
timestamp: new Date(),
});
}
destroy() {
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.clearGrid();
this.layouts.clear();
this.screen.removeAllListeners('resize');
}
}
exports.GridManager = GridManager;
//# sourceMappingURL=grid-manager.js.map