From 27b04267d104e784b029e700c126c3d3cb580119 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 20 Feb 2026 19:42:51 -0500 Subject: [PATCH 1/3] feat(scoreboards): add scroll mode config to baseball, football, basketball MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `live_display_mode`, `recent_display_mode`, and `upcoming_display_mode` fields (enum: switch|scroll, default: switch) to each league's display_modes block in config_schema.json, plus a `scroll_settings` block with scroll_speed, scroll_delay, gap_between_games, show_league_separators, and dynamic_duration. All three plugins already had full scroll mode code infrastructure in manager.py; this change exposes those settings in the web UI so users can enable scroll mode on large displays where switch mode leaves excessive blank space. Hockey and soccer scoreboards were already complete (unchanged). Bumped versions: baseball 1.3.1→1.3.2, football 2.1.1→2.1.2, basketball 1.1.1→1.1.2 Co-Authored-By: Claude Sonnet 4.6 --- plugins.json | 12 +- .../baseball-scoreboard/config_schema.json | 168 +++++++++++++ plugins/baseball-scoreboard/manifest.json | 9 +- .../basketball-scoreboard/config_schema.json | 224 ++++++++++++++++++ plugins/basketball-scoreboard/manifest.json | 2 +- .../football-scoreboard/config_schema.json | 112 +++++++++ plugins/football-scoreboard/manifest.json | 9 +- 7 files changed, 525 insertions(+), 11 deletions(-) diff --git a/plugins.json b/plugins.json index 2e95f79..8594fa5 100644 --- a/plugins.json +++ b/plugins.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "last_updated": "2026-02-18", + "last_updated": "2026-02-20", "plugins": [ { "id": "hello-world", @@ -221,10 +221,10 @@ "plugin_path": "plugins/football-scoreboard", "stars": 0, "downloads": 0, - "last_updated": "2026-02-15", + "last_updated": "2026-02-20", "verified": true, "screenshot": "", - "latest_version": "2.1.1" + "latest_version": "2.1.2" }, { "id": "ufc-scoreboard", @@ -270,7 +270,7 @@ "plugin_path": "plugins/basketball-scoreboard", "stars": 0, "downloads": 0, - "last_updated": "2026-02-16", + "last_updated": "2026-02-20", "verified": true, "screenshot": "", "latest_version": "1.3.0" @@ -296,10 +296,10 @@ "plugin_path": "plugins/baseball-scoreboard", "stars": 0, "downloads": 0, - "last_updated": "2026-02-17", + "last_updated": "2026-02-20", "verified": true, "screenshot": "", - "latest_version": "1.3.1" + "latest_version": "1.3.2" }, { "id": "soccer-scoreboard", diff --git a/plugins/baseball-scoreboard/config_schema.json b/plugins/baseball-scoreboard/config_schema.json index 0f2576b..8f48d77 100644 --- a/plugins/baseball-scoreboard/config_schema.json +++ b/plugins/baseball-scoreboard/config_schema.json @@ -69,6 +69,62 @@ "type": "boolean", "default": true, "description": "Show upcoming MLB games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons (MLB shield, NCAA logos) between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -344,6 +400,62 @@ "type": "boolean", "default": true, "description": "Show upcoming MiLB games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -619,6 +731,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NCAA Baseball games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, diff --git a/plugins/baseball-scoreboard/manifest.json b/plugins/baseball-scoreboard/manifest.json index 808fa83..f8f62ba 100644 --- a/plugins/baseball-scoreboard/manifest.json +++ b/plugins/baseball-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "baseball-scoreboard", "name": "Baseball Scoreboard", - "version": "1.3.1", + "version": "1.3.2", "author": "ChuckBuilds", "description": "Live, recent, and upcoming baseball games across MLB, MiLB, and NCAA Baseball with real-time scores and schedules", "category": "sports", @@ -30,6 +30,11 @@ "branch": "main", "plugin_path": "plugins/baseball-scoreboard", "versions": [ + { + "released": "2026-02-20", + "version": "1.3.2", + "ledmatrix_min": "2.0.0" + }, { "released": "2026-02-17", "version": "1.3.1", @@ -71,7 +76,7 @@ "ledmatrix_min": "2.0.0" } ], - "last_updated": "2026-02-14", + "last_updated": "2026-02-20", "stars": 0, "downloads": 0, "verified": true, diff --git a/plugins/basketball-scoreboard/config_schema.json b/plugins/basketball-scoreboard/config_schema.json index 37c7619..3dcd341 100644 --- a/plugins/basketball-scoreboard/config_schema.json +++ b/plugins/basketball-scoreboard/config_schema.json @@ -95,6 +95,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NBA games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -351,6 +407,62 @@ "type": "boolean", "default": true, "description": "Show upcoming WNBA games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -607,6 +719,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NCAA Men's Basketball games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -896,6 +1064,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NCAA Women's Basketball games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, diff --git a/plugins/basketball-scoreboard/manifest.json b/plugins/basketball-scoreboard/manifest.json index 90d6bf8..25b3b11 100644 --- a/plugins/basketball-scoreboard/manifest.json +++ b/plugins/basketball-scoreboard/manifest.json @@ -41,7 +41,7 @@ ], "stars": 0, "downloads": 0, - "last_updated": "2026-02-17", + "last_updated": "2026-02-20", "verified": true, "screenshot": "", "display_modes": [ diff --git a/plugins/football-scoreboard/config_schema.json b/plugins/football-scoreboard/config_schema.json index 644adff..11d1719 100644 --- a/plugins/football-scoreboard/config_schema.json +++ b/plugins/football-scoreboard/config_schema.json @@ -67,6 +67,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NFL games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, @@ -296,6 +352,62 @@ "type": "boolean", "default": true, "description": "Show upcoming NCAA FB games" + }, + "live_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for live games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "recent_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for recent games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + }, + "upcoming_display_mode": { + "type": "string", + "enum": ["switch", "scroll"], + "default": "switch", + "description": "Display mode for upcoming games: 'switch' shows one game at a time, 'scroll' scrolls all games horizontally" + } + } + }, + "scroll_settings": { + "type": "object", + "title": "Scroll Settings", + "description": "Settings for scroll display mode (when display mode is set to 'scroll')", + "properties": { + "scroll_speed": { + "type": "number", + "default": 50.0, + "minimum": 1.0, + "maximum": 200.0, + "description": "Scroll speed in pixels per second (default: 50). Higher values scroll faster." + }, + "scroll_delay": { + "type": "number", + "default": 0.01, + "minimum": 0.001, + "maximum": 0.1, + "description": "Delay between scroll frames in seconds (default: 0.01 = 100 FPS). Lower values = smoother scrolling." + }, + "gap_between_games": { + "type": "integer", + "default": 48, + "minimum": 8, + "maximum": 128, + "description": "Gap in pixels between game cards when scrolling" + }, + "show_league_separators": { + "type": "boolean", + "default": true, + "description": "Show league icons between different leagues" + }, + "dynamic_duration": { + "type": "boolean", + "default": true, + "description": "Automatically calculate display duration based on content width" } } }, diff --git a/plugins/football-scoreboard/manifest.json b/plugins/football-scoreboard/manifest.json index 01b3cfb..a461a51 100644 --- a/plugins/football-scoreboard/manifest.json +++ b/plugins/football-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "football-scoreboard", "name": "Football Scoreboard", - "version": "2.1.1", + "version": "2.1.2", "author": "ChuckBuilds", "class_name": "FootballScoreboardPlugin", "description": "Standalone plugin for live, recent, and upcoming football games across NFL and NCAA Football with real-time scores, down/distance, possession, and game status. Now with organized nested config!", @@ -24,6 +24,11 @@ "ncaa_fb_live" ], "versions": [ + { + "version": "2.1.2", + "ledmatrix_min": "2.0.0", + "released": "2026-02-20" + }, { "version": "2.1.1", "ledmatrix_min": "2.0.0", @@ -210,7 +215,7 @@ "ledmatrix_min": "2.0.0" } ], - "last_updated": "2026-02-15", + "last_updated": "2026-02-20", "stars": 0, "downloads": 0, "verified": true, From 96db478e1e5cdcf548be26edc54e7f45170cb03b Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 20 Feb 2026 20:31:15 -0500 Subject: [PATCH 2/3] fix(scoreboards): address PR review - minor version bumps, schema fix, f1 cleanup - Bump baseball/football/basketball to minor versions (1.4.0, 2.2.0, 1.2.0) since adding new config fields is a backward-compatible feature addition - Fix football config_schema.json: move 'customization' block from top-level into 'properties' so it is recognized under additionalProperties:false - Remove unused next_session_dt variable in f1-scoreboard manager.py - Fix f1-scoreboard manifest: correct last_updated date (2026-02-17 -> 2026-02-18) and add missing repo/branch/plugin_path fields for registry consistency Co-Authored-By: Claude Sonnet 4.6 --- plugins.json | 6 +++--- plugins/baseball-scoreboard/manifest.json | 4 ++-- plugins/basketball-scoreboard/manifest.json | 7 ++++++- plugins/f1-scoreboard/manager.py | 2 -- plugins/f1-scoreboard/manifest.json | 5 ++++- plugins/football-scoreboard/config_schema.json | 6 +++--- plugins/football-scoreboard/manifest.json | 4 ++-- 7 files changed, 20 insertions(+), 14 deletions(-) diff --git a/plugins.json b/plugins.json index 8594fa5..6f02ee2 100644 --- a/plugins.json +++ b/plugins.json @@ -224,7 +224,7 @@ "last_updated": "2026-02-20", "verified": true, "screenshot": "", - "latest_version": "2.1.2" + "latest_version": "2.2.0" }, { "id": "ufc-scoreboard", @@ -273,7 +273,7 @@ "last_updated": "2026-02-20", "verified": true, "screenshot": "", - "latest_version": "1.3.0" + "latest_version": "1.4.0" }, { "id": "baseball-scoreboard", @@ -299,7 +299,7 @@ "last_updated": "2026-02-20", "verified": true, "screenshot": "", - "latest_version": "1.3.2" + "latest_version": "1.4.0" }, { "id": "soccer-scoreboard", diff --git a/plugins/baseball-scoreboard/manifest.json b/plugins/baseball-scoreboard/manifest.json index f8f62ba..c043e32 100644 --- a/plugins/baseball-scoreboard/manifest.json +++ b/plugins/baseball-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "baseball-scoreboard", "name": "Baseball Scoreboard", - "version": "1.3.2", + "version": "1.4.0", "author": "ChuckBuilds", "description": "Live, recent, and upcoming baseball games across MLB, MiLB, and NCAA Baseball with real-time scores and schedules", "category": "sports", @@ -32,7 +32,7 @@ "versions": [ { "released": "2026-02-20", - "version": "1.3.2", + "version": "1.4.0", "ledmatrix_min": "2.0.0" }, { diff --git a/plugins/basketball-scoreboard/manifest.json b/plugins/basketball-scoreboard/manifest.json index 25b3b11..62fe4f3 100644 --- a/plugins/basketball-scoreboard/manifest.json +++ b/plugins/basketball-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "basketball-scoreboard", "name": "Basketball Scoreboard", - "version": "1.3.0", + "version": "1.4.0", "description": "Live, recent, and upcoming basketball games across NBA, NCAA Men's, NCAA Women's, and WNBA with real-time scores, schedules, and March Madness tournament support", "author": "ChuckBuilds", "category": "sports", @@ -18,6 +18,11 @@ "branch": "main", "plugin_path": "plugins/basketball-scoreboard", "versions": [ + { + "version": "1.4.0", + "ledmatrix_min": "2.0.0", + "released": "2026-02-20" + }, { "version": "1.3.0", "ledmatrix_min": "2.0.0", diff --git a/plugins/f1-scoreboard/manager.py b/plugins/f1-scoreboard/manager.py index c172d51..ffdac68 100644 --- a/plugins/f1-scoreboard/manager.py +++ b/plugins/f1-scoreboard/manager.py @@ -453,7 +453,6 @@ def _display_upcoming(self, force_clear: bool) -> bool: upcoming["countdown_seconds"] = None now = datetime.now(timezone.utc) - next_session_dt = None for session in upcoming.get("sessions", []): if session.get("status_state") == "pre" and session.get("date"): @@ -461,7 +460,6 @@ def _display_upcoming(self, force_clear: bool) -> bool: parsed_dt = datetime.fromisoformat( session["date"].replace("Z", "+00:00")) if parsed_dt > now: - next_session_dt = parsed_dt upcoming["countdown_seconds"] = max( 0, (parsed_dt - now).total_seconds()) upcoming["next_session_type"] = session.get( diff --git a/plugins/f1-scoreboard/manifest.json b/plugins/f1-scoreboard/manifest.json index 326d66d..541ae01 100644 --- a/plugins/f1-scoreboard/manifest.json +++ b/plugins/f1-scoreboard/manifest.json @@ -5,6 +5,9 @@ "author": "ChuckBuilds", "class_name": "F1ScoreboardPlugin", "entry_point": "manager.py", + "repo": "https://github.com/ChuckBuilds/ledmatrix-plugins", + "branch": "main", + "plugin_path": "plugins/f1-scoreboard", "description": "Formula 1 racing plugin showing driver/constructor standings, race results, qualifying breakdowns, practice standings, sprint results, upcoming races, and race calendar with team-colored displays and favorite driver/team support", "category": "sports", "tags": ["f1", "formula1", "racing", "motorsport", "sports", "scoreboard"], @@ -25,7 +28,7 @@ "released": "2026-02-17" } ], - "last_updated": "2026-02-17", + "last_updated": "2026-02-18", "stars": 0, "downloads": 0, "verified": true, diff --git a/plugins/football-scoreboard/config_schema.json b/plugins/football-scoreboard/config_schema.json index 11d1719..591909b 100644 --- a/plugins/football-scoreboard/config_schema.json +++ b/plugins/football-scoreboard/config_schema.json @@ -599,9 +599,8 @@ } } } - } - }, - "customization": { + }, + "customization": { "type": "object", "title": "Display Customization", "description": "Customize fonts for different text elements on the scoreboard", @@ -996,6 +995,7 @@ }, "x-propertyOrder": ["score_text", "period_text", "team_name", "status_text", "detail_text", "rank_text", "layout"], "additionalProperties": false + } }, "additionalProperties": false, "required": ["enabled"] diff --git a/plugins/football-scoreboard/manifest.json b/plugins/football-scoreboard/manifest.json index a461a51..be94ac8 100644 --- a/plugins/football-scoreboard/manifest.json +++ b/plugins/football-scoreboard/manifest.json @@ -1,7 +1,7 @@ { "id": "football-scoreboard", "name": "Football Scoreboard", - "version": "2.1.2", + "version": "2.2.0", "author": "ChuckBuilds", "class_name": "FootballScoreboardPlugin", "description": "Standalone plugin for live, recent, and upcoming football games across NFL and NCAA Football with real-time scores, down/distance, possession, and game status. Now with organized nested config!", @@ -25,7 +25,7 @@ ], "versions": [ { - "version": "2.1.2", + "version": "2.2.0", "ledmatrix_min": "2.0.0", "released": "2026-02-20" }, From 1ddca61d2f549f5e2f8080d30925be8397c9baef Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 20 Feb 2026 20:40:00 -0500 Subject: [PATCH 3/3] fix(f1-scoreboard): ensure Vegas upcoming card has fresh countdown get_vegas_content was passing raw self._upcoming_race directly to render_upcoming_race, bypassing the countdown computation in _display_upcoming. Extract the countdown logic into _enrich_upcoming_with_countdown and call it from both _display_upcoming and get_vegas_content so the rendered card always reflects the current time-to-next-session. Co-Authored-By: Claude Sonnet 4.6 --- plugins/f1-scoreboard/manager.py | 35 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/plugins/f1-scoreboard/manager.py b/plugins/f1-scoreboard/manager.py index ffdac68..95f4482 100644 --- a/plugins/f1-scoreboard/manager.py +++ b/plugins/f1-scoreboard/manager.py @@ -436,20 +436,10 @@ def display(self, force_clear=False, display_mode=None) -> bool: self.logger.warning("Unknown display mode: %s", display_mode) return False - def _display_upcoming(self, force_clear: bool) -> bool: - """Display the upcoming race card (static).""" - if not self._upcoming_race: - return False - - if force_clear: - self.display_manager.image.paste( - Image.new("RGB", - (self.display_width, self.display_height), - (0, 0, 0)), - (0, 0)) - - # Work on a shallow copy to avoid mutating cached data - upcoming = dict(self._upcoming_race) + def _enrich_upcoming_with_countdown(self, + race: Dict) -> Dict: + """Return a shallow copy of race with fresh countdown_seconds set.""" + upcoming = dict(race) upcoming["countdown_seconds"] = None now = datetime.now(timezone.utc) @@ -468,6 +458,21 @@ def _display_upcoming(self, force_clear: bool) -> bool: except (ValueError, TypeError): continue + return upcoming + + def _display_upcoming(self, force_clear: bool) -> bool: + """Display the upcoming race card (static).""" + if not self._upcoming_race: + return False + + if force_clear: + self.display_manager.image.paste( + Image.new("RGB", + (self.display_width, self.display_height), + (0, 0, 0)), + (0, 0)) + + upcoming = self._enrich_upcoming_with_countdown(self._upcoming_race) card = self.renderer.render_upcoming_race(upcoming) self.display_manager.image.paste(card, (0, 0)) self.display_manager.update_display() @@ -511,7 +516,7 @@ def get_vegas_content(self) -> Optional[List[Image.Image]]: # Add upcoming race card if available if self._upcoming_race: upcoming_card = self.renderer.render_upcoming_race( - self._upcoming_race) + self._enrich_upcoming_with_countdown(self._upcoming_race)) images.insert(0, upcoming_card) return images if images else None