feat(vegas): one declared participation per plugin (scroll | pause | exclude) (#682)

A plugin takes part in Vegas mode in one declared way: 'scroll', 'pause'
or 'exclude', resolved from the user's vegas_participation setting, the
manifest field, then the legacy hooks, so no plugin changes behaviour.
The stream manager decides inclusion and pauses through it; the installed
plugins API and the Vegas plugin-order list report it. Deprecates
get_supported_vegas_modes, get_vegas_segment_width and vegas_panel_count
for removal in 3.9.0, and regenerates docs/DEPRECATIONS_3.8.md to include
them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-30 09:30:37 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent b2df0fda1b
commit 1c928b2033
19 changed files with 1094 additions and 244 deletions
@@ -10,6 +10,9 @@ from web_interface.blueprints.api_v3 import (
jsonify, logger, os, request, subprocess, success_response,
)
from src.common.path_safety import safe_path_component
from src.plugin_system.base_plugin import (
configured_vegas_participation, resolve_vegas_participation,
)
import web_interface.blueprints.api_v3 as _pkg
# Read through the module rather than bound by value: tests patch these
# as module attributes, and a value binding would not see the patch.
@@ -129,6 +132,14 @@ def get_installed_plugins():
if 'vegas_mode' in plugin_config:
vegas_mode = plugin_config['vegas_mode']
# What Vegas actually does with the plugin: 'scroll', 'pause' or
# 'exclude'. The same resolution the ticker uses; without a loaded
# instance only the user's own setting is known.
if plugin_instance is not None:
vegas_participation = resolve_vegas_participation(plugin_instance, plugin_id)
else:
vegas_participation = configured_vegas_participation(plugin_id, plugin_config)
return {
'id': plugin_id,
'name': plugin_info.get('name', plugin_id),
@@ -154,6 +165,7 @@ def get_installed_plugins():
'web_ui_actions': plugin_info.get('web_ui_actions', []),
'vegas_mode': vegas_mode,
'vegas_content_type': vegas_content_type,
'vegas_participation': vegas_participation,
}
from concurrent.futures import ThreadPoolExecutor
@@ -12,7 +12,7 @@
* orderInputId: 'vegas_plugin_order_value', // hidden input, JSON array of ids
* excludedInputId: 'vegas_excluded_plugins_value', // optional: adds an
* // include-checkbox per row; unchecked ids collect here (JSON array)
* showVegasModeBadge: true // optional: Scroll/Fixed/Static badge
* showVegasModeBadge: true // optional: Scroll/Pause/Excluded badge
* });
*
* The container re-renders from /api/v3/plugins/installed each init; the
@@ -21,10 +21,14 @@
(function() {
'use strict';
// Keyed by Vegas participation ('scroll' | 'pause' | 'exclude'); 'fixed'
// and 'static' are the legacy vegas_mode values, for an older API.
const MODE_LABELS = new Map([
['scroll', { label: 'Scroll', icon: 'fa-scroll', color: 'text-blue-600' }],
['fixed', { label: 'Fixed', icon: 'fa-square', color: 'text-green-600' }],
['static', { label: 'Static', icon: 'fa-pause', color: 'text-orange-600' }]
['scroll', { label: 'Scroll', icon: 'fa-scroll', color: 'text-blue-600' }],
['pause', { label: 'Pause', icon: 'fa-pause', color: 'text-orange-600' }],
['exclude', { label: 'Excluded', icon: 'fa-ban', color: 'text-gray-500' }],
['fixed', { label: 'Scroll', icon: 'fa-scroll', color: 'text-blue-600' }],
['static', { label: 'Pause', icon: 'fa-pause', color: 'text-orange-600' }]
]);
function init(options) {
@@ -165,11 +169,11 @@
}
if (options.showVegasModeBadge) {
const vegasMode = plugin.vegas_mode || plugin.vegas_content_type || 'fixed';
const modeInfo = MODE_LABELS.get(vegasMode) || MODE_LABELS.get('fixed');
const vegasMode = plugin.vegas_participation || plugin.vegas_mode || 'scroll';
const modeInfo = MODE_LABELS.get(vegasMode) || MODE_LABELS.get('scroll');
const badge = document.createElement('span');
badge.className = `text-xs ${modeInfo.color} ml-2`;
badge.title = `Vegas display mode: ${modeInfo.label}`;
badge.title = `Vegas participation: ${modeInfo.label}`;
const badgeIcon = document.createElement('i');
badgeIcon.className = `fas ${modeInfo.icon} mr-1`;
badge.appendChild(badgeIcon);