polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
858 lines • 31.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelStatusPanel = void 0;
const blessed_1 = __importDefault(require("blessed"));
const blessed_contrib_1 = require("blessed-contrib");
const base_component_1 = require("./base.component");
const channel_details_popup_1 = require("./channel-details.popup");
const batch_operations_dialog_1 = require("./batch-operations.dialog");
class ChannelStatusPanel extends base_component_1.BaseComponent {
constructor(config, eventBus) {
super(config, eventBus);
this.channels = [];
this.filteredChannels = [];
this.selectedChannels = new Set();
this.currentIndex = 0;
this.selectionStartIndex = -1;
this.isRangeSelecting = false;
this.lastJumpPosition = 0;
this.navigationHistory = [];
this.sortConfig = {
field: config.sortField || 'name',
order: config.sortOrder || 'asc'
};
this.filterConfig = config.filters || {};
this.lastUpdateTime = new Date();
}
createWidget() {
this.container = blessed_1.default.box({
label: ' Channel Status Monitor ',
border: { type: 'line' },
style: {
fg: 'white',
bg: 'black',
border: { fg: 'cyan' }
},
top: this.config.position.y,
left: this.config.position.x,
width: this.config.position.width,
height: this.config.position.height,
scrollable: false,
mouse: true,
keys: true,
vi: true,
tags: true
});
this.headerBox = blessed_1.default.box({
parent: this.container,
top: 0,
left: 0,
width: '100%',
height: 2,
content: this.getHeaderContent(),
style: { fg: 'yellow' },
tags: true
});
this.footerBox = blessed_1.default.box({
parent: this.container,
bottom: 0,
left: 0,
width: '100%',
height: 2,
content: this.getFooterContent(),
style: { fg: 'gray' },
tags: true
});
const tableConfig = {
keys: true,
interactive: true,
columnSpacing: 2,
columnWidth: this.getConfig().columnWidths || [20, 12, 10, 10, 15, 15],
style: {
fg: 'white',
bg: 'black',
border: { fg: 'gray' },
header: { fg: 'cyan', bold: true },
cell: { fg: 'white' },
selected: { bg: 'blue', fg: 'white' }
}
};
this.table = (0, blessed_contrib_1.table)(tableConfig);
this.table.parent = this.container;
this.table.top = 2;
this.table.left = 0;
this.table.width = '100%';
this.table.height = 'bottom-2';
this.noDataBox = blessed_1.default.box({
parent: this.container,
top: 'center',
left: 'center',
width: 'shrink',
height: 'shrink',
content: this.getNoDataMessage(),
style: { fg: 'gray' },
tags: true,
hidden: true
});
this.widget = this.container;
this.initializeDetailsPopup();
this.initializeBatchDialog();
this.setupKeyBindings();
this.updateTableDisplay();
}
initializeDetailsPopup() {
this.detailsPopup = new channel_details_popup_1.ChannelDetailsPopup({
screen: this.widget.screen,
eventBus: this.eventBus,
showColors: this.getConfig().showColors,
refreshInterval: this.getConfig().refreshInterval
});
}
initializeBatchDialog() {
this.batchDialog = new batch_operations_dialog_1.BatchOperationsDialog({
screen: this.widget.screen,
eventBus: this.eventBus,
showColors: this.getConfig().showColors
});
}
setupKeyBindings() {
this.container.key(['up', 'k'], () => {
this.moveSelection(-1);
});
this.container.key(['down', 'j'], () => {
this.moveSelection(1);
});
this.container.key(['pageup'], () => {
this.moveSelection(-10);
});
this.container.key(['pagedown'], () => {
this.moveSelection(10);
});
this.container.key(['home'], () => {
this.moveToTop();
});
this.container.key(['end'], () => {
this.moveToBottom();
});
this.container.key(['space'], () => {
this.toggleSelection();
});
this.container.key(['enter'], () => {
this.showChannelDetails();
});
this.container.key(['s'], () => {
this.cycleSortField();
});
this.container.key(['S'], () => {
this.toggleSortOrder();
});
this.container.key(['f'], () => {
this.showFilterDialog();
});
this.container.key(['F'], () => {
this.showAdvancedFilterDialog();
});
this.container.key(['c'], () => {
this.clearFilters();
});
this.container.key(['1'], () => {
this.quickFilterByStatus('live');
});
this.container.key(['2'], () => {
this.quickFilterByStatus('waiting');
});
this.container.key(['3'], () => {
this.quickFilterByStatus('end');
});
this.container.key(['4'], () => {
this.quickFilterByStatus('banpush');
});
this.container.key(['r', 'R', 'f5'], () => {
this.requestUpdate();
});
this.container.key(['a'], () => {
this.selectAll();
});
this.container.key(['A'], () => {
this.deselectAll();
});
this.container.key(['d'], () => {
this.showBatchOperations();
});
this.container.key(['g'], () => {
this.moveToTop();
});
this.container.key(['G'], () => {
this.moveToBottom();
});
this.container.key(['ctrl+f'], () => {
this.showQuickJumpDialog();
});
this.container.key(['ctrl+g'], () => {
this.showGoToLineDialog();
});
this.container.key(['shift+up', 'shift+k'], () => {
this.extendSelectionUp();
});
this.container.key(['shift+down', 'shift+j'], () => {
this.extendSelectionDown();
});
this.container.key(['ctrl+c'], () => {
this.copySelectionInfo();
});
}
render() {
if (this.isDestroyed || !this.widget)
return;
try {
this.updateHeader();
this.updateFooter();
this.updateTableDisplay();
this.widget.screen?.render();
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Unknown render error'));
}
}
update(data) {
if (this.isDestroyed)
return;
try {
let channelsArray;
if (Array.isArray(data)) {
channelsArray = data;
}
else if ('channels' in data && Array.isArray(data.channels)) {
channelsArray = data.channels;
}
else {
channelsArray = [data];
}
this.channels = channelsArray.map(channel => this.convertToStatusInfo(channel));
this.applyFiltersAndSort();
this.lastUpdateTime = new Date();
this.updateState({ lastUpdate: this.lastUpdateTime });
if (this.channels.length === 0) {
this.noDataBox.show();
this.table.hide();
}
else {
this.noDataBox.hide();
this.table.show();
}
this.updateStatusColors();
}
catch (error) {
this.handleError(error instanceof Error ? error : new Error('Failed to update channel status'));
}
}
convertToStatusInfo(channel) {
const selectedChannels = this.selectedChannels || new Set();
return {
channelId: channel.channelId.toString(),
name: channel.name,
status: channel.watchStatus,
statusText: channel.watchStatusText,
viewerCount: channel.pageView || 0,
maxViewer: channel.maxViewer || 0,
publisher: channel.publisher || '',
startTime: channel.startTime || 0,
endTime: channel.endTime || 0,
createdTime: channel.createdTime || 0,
selected: selectedChannels.has(channel.channelId.toString())
};
}
compareValues(a, b) {
if (a === undefined && b === undefined)
return 0;
if (a === undefined)
return 1;
if (b === undefined)
return -1;
if (typeof a === 'string' && typeof b === 'string') {
return a.localeCompare(b);
}
if (typeof a === 'number' && typeof b === 'number') {
return a - b;
}
return String(a).localeCompare(String(b));
}
applyFiltersAndSort() {
const channels = this.channels || [];
this.filteredChannels = channels.filter(channel => {
if (this.filterConfig.status && this.filterConfig.status.length > 0) {
if (!this.filterConfig.status.includes(channel.status)) {
return false;
}
}
if (this.filterConfig.searchTerm) {
const searchTerms = this.filterConfig.searchTerm.toLowerCase().split(' ').filter(term => term.length > 0);
const searchableText = `${channel.name} ${channel.channelId} ${channel.publisher} ${channel.statusText}`.toLowerCase();
const allTermsMatch = searchTerms.every(term => searchableText.includes(term));
if (!allTermsMatch) {
return false;
}
}
if (this.filterConfig.viewerCountMin !== undefined && channel.viewerCount < this.filterConfig.viewerCountMin) {
return false;
}
if (this.filterConfig.viewerCountMax !== undefined && channel.viewerCount > this.filterConfig.viewerCountMax) {
return false;
}
if (this.filterConfig.publisherFilter) {
const publisherFilter = this.filterConfig.publisherFilter.toLowerCase();
if (!channel.publisher.toLowerCase().includes(publisherFilter)) {
return false;
}
}
if (this.filterConfig.dateRange) {
const channelDate = new Date(channel.createdTime);
if (this.filterConfig.dateRange.startDate && channelDate < this.filterConfig.dateRange.startDate) {
return false;
}
if (this.filterConfig.dateRange.endDate && channelDate > this.filterConfig.dateRange.endDate) {
return false;
}
}
return true;
});
this.filteredChannels.sort((a, b) => {
const aVal = a[this.sortConfig.field];
const bVal = b[this.sortConfig.field];
let comparison = this.compareValues(aVal, bVal);
if (comparison === 0 && this.sortConfig.secondaryField) {
const aSecVal = a[this.sortConfig.secondaryField];
const bSecVal = b[this.sortConfig.secondaryField];
comparison = this.compareValues(aSecVal, bSecVal);
if (this.sortConfig.secondaryOrder === 'desc') {
comparison = -comparison;
}
}
return this.sortConfig.order === 'asc' ? comparison : -comparison;
});
const filteredChannels = this.filteredChannels || [];
if (this.currentIndex >= filteredChannels.length) {
this.currentIndex = Math.max(0, filteredChannels.length - 1);
}
}
updateTableDisplay() {
if (!this.table)
return;
const headers = ['Channel Name', 'Status', 'Viewers', 'Max', 'Publisher', 'Created'];
const data = [];
const channels = this.filteredChannels || [];
const selectedChannels = this.selectedChannels || new Set();
for (let i = 0; i < channels.length; i++) {
const channel = channels[i];
if (!channel)
continue;
const isSelected = selectedChannels.has(channel.channelId);
const isCurrent = i === this.currentIndex;
const row = [
this.formatCellValue(channel.name, isSelected, isCurrent),
this.formatStatusCell(channel.status, channel.statusText, isSelected, isCurrent),
this.formatCellValue(channel.viewerCount.toString(), isSelected, isCurrent),
this.formatCellValue(channel.maxViewer.toString(), isSelected, isCurrent),
this.formatCellValue(channel.publisher, isSelected, isCurrent),
this.formatCellValue(this.formatDate(new Date(channel.createdTime)), isSelected, isCurrent)
];
data.push(row);
}
this.table.setData({
headers,
data
});
}
formatCellValue(value, isSelected, isCurrent) {
if (isCurrent) {
return `{inverse}${isSelected ? '✓ ' : ''}${value}{/inverse}`;
}
return isSelected ? `{cyan-fg}✓ ${value}{/cyan-fg}` : value;
}
formatStatusCell(status, statusText, isSelected, isCurrent) {
const colors = this.getStatusColors(status);
const safeColor = this.getTerminalSafeColor(colors.fg);
const prefix = isCurrent ? '{inverse}' : '';
const suffix = isCurrent ? '{/inverse}' : '';
const checkmark = isSelected ? '✓ ' : '';
const icon = colors.icon || '';
const healthLevel = this.getStatusHealthLevel(status);
let statusDisplay = statusText;
switch (healthLevel) {
case 'healthy':
statusDisplay = `${icon} ${statusText}`;
break;
case 'warning':
statusDisplay = `${icon} ${statusText}`;
break;
case 'error':
statusDisplay = `${icon} ${statusText}`;
break;
}
return `${prefix}{${safeColor}-fg}${checkmark}${statusDisplay}{/${safeColor}-fg}${suffix}`;
}
updateStatusColors() {
this.throttledRender();
this.emit('component:statusChanged', {
componentId: this.state.id,
healthSummary: this.getChannelHealthSummary(),
timestamp: new Date()
});
}
getChannelHealthSummary() {
const channels = this.filteredChannels || [];
const summary = { healthy: 0, warning: 0, error: 0 };
channels.forEach(channel => {
const healthLevel = this.getStatusHealthLevel(channel.status);
summary[healthLevel]++;
});
return summary;
}
getStatusColors(status) {
switch (status) {
case 'live':
return { fg: 'green', icon: '●' };
case 'waiting':
return { fg: 'yellow', icon: '◯' };
case 'end':
return { fg: 'gray', icon: '◦' };
case 'unStart':
return { fg: 'gray', icon: '◦' };
case 'banpush':
return { fg: 'red', icon: '✖' };
case 'playback':
return { fg: 'blue', icon: '▶' };
default:
return { fg: 'white', icon: '?' };
}
}
getTerminalSafeColor(color) {
const config = this.getConfig();
if (!config.showColors) {
return 'white';
}
const colorMapping = {
'green': 'green',
'yellow': 'yellow',
'red': 'red',
'blue': 'blue',
'gray': 'gray',
'white': 'white'
};
return colorMapping[color] || 'white';
}
getStatusHealthLevel(status) {
switch (status) {
case 'live':
return 'healthy';
case 'waiting':
case 'playback':
return 'warning';
case 'banpush':
return 'error';
case 'end':
case 'unStart':
default:
return 'warning';
}
}
formatDate(date) {
return date.toLocaleDateString();
}
updateHeader() {
this.headerBox.setContent(this.getHeaderContent());
}
updateFooter() {
this.footerBox.setContent(this.getFooterContent());
}
getHeaderContent() {
const total = this.channels?.length || 0;
const filtered = this.filteredChannels?.length || 0;
const selected = this.selectedChannels?.size || 0;
const lastUpdate = this.lastUpdateTime?.toLocaleTimeString() || 'Never';
const health = this.getChannelHealthSummary();
const healthDisplay = `{green-fg}●${health.healthy}{/green-fg} {yellow-fg}◯${health.warning}{/yellow-fg} {red-fg}✖${health.error}{/red-fg}`;
return `Total: {bold}${total}{/bold} | Displayed: {bold}${filtered}{/bold} | Selected: {cyan-fg}${selected}{/cyan-fg} | Health: ${healthDisplay} | Updated: {gray-fg}${lastUpdate}{/gray-fg}`;
}
getFooterContent() {
const activeFilters = this.filterConfig ? Object.keys(this.filterConfig).length : 0;
const filterInfo = activeFilters > 0 ? `{yellow-fg}[${activeFilters} filters]{/yellow-fg}` : '';
const sortInfo = this.sortConfig?.secondaryField ? `{cyan-fg}[Multi-sort]{/cyan-fg}` : '';
return `{gray-fg}↑↓: Navigate | Space: Select | Enter: Details | S: Sort | Shift+S: Order | F: Filter | Shift+F: Advanced | 1-4: Quick Filter | C: Clear | R: Refresh{/gray-fg} ${filterInfo} ${sortInfo}`;
}
getNoDataMessage() {
return '{center}{gray-fg}No channel data available{/gray-fg}\n{center}{gray-fg}Waiting for channel information...{/gray-fg}{/center}';
}
moveSelection(delta) {
const channels = this.filteredChannels || [];
if (channels.length === 0)
return;
this.currentIndex = Math.max(0, Math.min(channels.length - 1, this.currentIndex + delta));
this.throttledRender();
}
moveToTop() {
this.saveNavigationHistory();
this.currentIndex = 0;
this.isRangeSelecting = false;
this.throttledRender();
this.emitNavigationEvent('moveToTop');
}
moveToBottom() {
const channels = this.filteredChannels || [];
this.saveNavigationHistory();
this.currentIndex = Math.max(0, channels.length - 1);
this.isRangeSelecting = false;
this.throttledRender();
this.emitNavigationEvent('moveToBottom');
}
showQuickJumpDialog() {
this.emit('component:quickJumpDialog', {
componentId: this.state.id,
currentIndex: this.currentIndex,
totalItems: this.filteredChannels?.length || 0,
timestamp: new Date()
});
}
showGoToLineDialog() {
this.emit('component:goToLineDialog', {
componentId: this.state.id,
currentLine: this.currentIndex + 1,
totalLines: this.filteredChannels?.length || 0,
timestamp: new Date()
});
}
extendSelectionUp() {
const channels = this.filteredChannels || [];
if (channels.length === 0)
return;
if (!this.isRangeSelecting) {
this.selectionStartIndex = this.currentIndex;
this.isRangeSelecting = true;
}
const newIndex = Math.max(0, this.currentIndex - 1);
this.updateRangeSelection(newIndex);
}
extendSelectionDown() {
const channels = this.filteredChannels || [];
if (channels.length === 0)
return;
if (!this.isRangeSelecting) {
this.selectionStartIndex = this.currentIndex;
this.isRangeSelecting = true;
}
const newIndex = Math.min(channels.length - 1, this.currentIndex + 1);
this.updateRangeSelection(newIndex);
}
updateRangeSelection(newIndex) {
const channels = this.filteredChannels || [];
const selectedChannels = this.selectedChannels || new Set();
if (this.selectionStartIndex === -1)
return;
this.clearRangeSelection();
const startIndex = Math.min(this.selectionStartIndex, newIndex);
const endIndex = Math.max(this.selectionStartIndex, newIndex);
for (let i = startIndex; i <= endIndex; i++) {
const channel = channels[i];
if (channel) {
selectedChannels.add(channel.channelId);
}
}
this.currentIndex = newIndex;
this.throttledRender();
}
clearRangeSelection() {
}
copySelectionInfo() {
const selectedChannels = this.selectedChannels || new Set();
const channels = this.filteredChannels || [];
if (selectedChannels.size === 0 && this.currentIndex < channels.length) {
const currentChannel = channels[this.currentIndex];
if (currentChannel) {
this.copyChannelInfo(currentChannel);
}
}
else {
const selectedChannelData = channels.filter(c => selectedChannels.has(c.channelId));
this.copyMultipleChannelsInfo(selectedChannelData);
}
}
copyChannelInfo(channel) {
const info = `${channel.name} (${channel.channelId}) - ${channel.statusText} - ${channel.viewerCount} viewers`;
this.emit('component:copyToClipboard', {
componentId: this.state.id,
content: info,
type: 'singleChannel',
channel,
timestamp: new Date()
});
}
copyMultipleChannelsInfo(channels) {
const info = channels.map(c => `${c.name} (${c.channelId}) - ${c.statusText} - ${c.viewerCount} viewers`).join('\n');
this.emit('component:copyToClipboard', {
componentId: this.state.id,
content: info,
type: 'multipleChannels',
channels,
count: channels.length,
timestamp: new Date()
});
}
saveNavigationHistory() {
if (this.currentIndex !== this.lastJumpPosition) {
this.navigationHistory.push(this.lastJumpPosition);
if (this.navigationHistory.length > 10) {
this.navigationHistory.shift();
}
this.lastJumpPosition = this.currentIndex;
}
}
emitNavigationEvent(action) {
this.emit('component:navigation', {
componentId: this.state.id,
action,
currentIndex: this.currentIndex,
totalItems: this.filteredChannels?.length || 0,
timestamp: new Date()
});
}
jumpToLine(lineNumber) {
const channels = this.filteredChannels || [];
const targetIndex = lineNumber - 1;
if (targetIndex >= 0 && targetIndex < channels.length) {
this.saveNavigationHistory();
this.currentIndex = targetIndex;
this.isRangeSelecting = false;
this.throttledRender();
this.emitNavigationEvent('jumpToLine');
return true;
}
return false;
}
jumpToChannel(searchTerm) {
const channels = this.filteredChannels || [];
const lowerSearchTerm = searchTerm.toLowerCase();
const targetIndex = channels.findIndex(channel => channel.channelId.toLowerCase().includes(lowerSearchTerm) ||
channel.name.toLowerCase().includes(lowerSearchTerm));
if (targetIndex !== -1) {
this.saveNavigationHistory();
this.currentIndex = targetIndex;
this.isRangeSelecting = false;
this.throttledRender();
this.emitNavigationEvent('jumpToChannel');
return true;
}
return false;
}
toggleSelection() {
const channels = this.filteredChannels || [];
const selectedChannels = this.selectedChannels || new Set();
if (channels.length === 0)
return;
const currentChannel = channels[this.currentIndex];
if (!currentChannel)
return;
if (selectedChannels.has(currentChannel.channelId)) {
selectedChannels.delete(currentChannel.channelId);
}
else {
selectedChannels.add(currentChannel.channelId);
}
this.throttledRender();
}
selectAll() {
const channels = this.filteredChannels || [];
const selectedChannels = this.selectedChannels || new Set();
channels.forEach(channel => {
selectedChannels.add(channel.channelId);
});
this.throttledRender();
}
deselectAll() {
const selectedChannels = this.selectedChannels || new Set();
selectedChannels.clear();
this.throttledRender();
}
cycleSortField() {
const fields = ['name', 'status', 'viewerCount', 'maxViewer', 'publisher', 'createdTime'];
const currentIndex = fields.indexOf(this.sortConfig.field);
const nextIndex = (currentIndex + 1) % fields.length;
const nextField = fields[nextIndex];
if (nextField) {
if (this.sortConfig.secondaryField) {
this.sortConfig.field = this.sortConfig.secondaryField;
this.sortConfig.order = this.sortConfig.secondaryOrder || 'asc';
delete this.sortConfig.secondaryField;
delete this.sortConfig.secondaryOrder;
}
else {
this.sortConfig.field = nextField;
}
}
this.applyFiltersAndSort();
this.throttledRender();
this.emit('component:sortChanged', {
componentId: this.state.id,
sortConfig: this.sortConfig,
timestamp: new Date()
});
}
toggleSortOrder() {
this.sortConfig.order = this.sortConfig.order === 'asc' ? 'desc' : 'asc';
this.applyFiltersAndSort();
this.throttledRender();
this.emit('component:sortChanged', {
componentId: this.state.id,
sortConfig: this.sortConfig,
timestamp: new Date()
});
}
setMultiFieldSort(primary, primaryOrder, secondary, secondaryOrder) {
const newConfig = {
field: primary,
order: primaryOrder
};
if (secondary !== undefined) {
newConfig.secondaryField = secondary;
}
if (secondaryOrder !== undefined) {
newConfig.secondaryOrder = secondaryOrder;
}
this.sortConfig = newConfig;
this.applyFiltersAndSort();
this.throttledRender();
this.emit('component:sortChanged', {
componentId: this.state.id,
sortConfig: this.sortConfig,
changeType: 'multiField',
timestamp: new Date()
});
}
showFilterDialog() {
this.emit('component:filterDialog', {
componentId: this.state.id,
currentFilter: this.filterConfig,
type: 'basic',
timestamp: new Date()
});
}
showAdvancedFilterDialog() {
this.emit('component:advancedFilterDialog', {
componentId: this.state.id,
currentFilter: this.filterConfig,
availableFields: ['viewerCount', 'publisher', 'createdTime'],
timestamp: new Date()
});
}
quickFilterByStatus(status) {
if (this.filterConfig.status?.includes(status)) {
this.filterConfig.status = this.filterConfig.status.filter(s => s !== status);
if (this.filterConfig.status.length === 0) {
delete this.filterConfig.status;
}
}
else {
if (!this.filterConfig.status) {
this.filterConfig.status = [];
}
this.filterConfig.status.push(status);
}
this.applyFiltersAndSort();
this.throttledRender();
this.emit('component:filterChanged', {
componentId: this.state.id,
filter: this.filterConfig,
changeType: 'quickFilter',
status,
timestamp: new Date()
});
}
clearFilters() {
const hadFilters = Object.keys(this.filterConfig).length > 0;
this.filterConfig = {};
this.applyFiltersAndSort();
this.throttledRender();
if (hadFilters) {
this.emit('component:filtersCleared', {
componentId: this.state.id,
timestamp: new Date()
});
}
}
setAdvancedFilter(filter) {
this.filterConfig = { ...this.filterConfig, ...filter };
this.applyFiltersAndSort();
this.throttledRender();
this.emit('component:filterChanged', {
componentId: this.state.id,
filter: this.filterConfig,
changeType: 'advanced',
timestamp: new Date()
});
}
showChannelDetails() {
const channels = this.filteredChannels || [];
if (channels.length === 0)
return;
const currentChannel = channels[this.currentIndex];
if (!currentChannel)
return;
this.detailsPopup.show(currentChannel);
this.emit('component:showDetails', {
componentId: this.state.id,
channelId: currentChannel.channelId,
channel: currentChannel,
timestamp: new Date()
});
}
showBatchOperations() {
const selectedChannels = this.selectedChannels || new Set();
if (selectedChannels.size === 0)
return;
this.batchDialog.show(Array.from(selectedChannels));
this.emit('component:batchOperations', {
componentId: this.state.id,
selectedChannels: Array.from(selectedChannels),
timestamp: new Date()
});
}
getConfig() {
return this.config;
}
getSelectedChannels() {
return Array.from(this.selectedChannels || new Set());
}
getCurrentChannel() {
const channels = this.filteredChannels || [];
return channels[this.currentIndex] || null;
}
setFilter(filter) {
this.filterConfig = filter;
this.applyFiltersAndSort();
this.throttledRender();
}
setSort(sort) {
this.sortConfig = sort;
this.applyFiltersAndSort();
this.throttledRender();
}
destroy() {
this.stopRefresh();
this.channels = [];
this.filteredChannels = [];
if (this.selectedChannels) {
this.selectedChannels.clear();
}
if (this.detailsPopup) {
this.detailsPopup.destroy();
}
if (this.batchDialog) {
this.batchDialog.destroy();
}
super.destroy();
}
}
exports.ChannelStatusPanel = ChannelStatusPanel;
//# sourceMappingURL=channel-status.panel.js.map