From b4475152a961eed0892b171dde3f8a1c378a08ba Mon Sep 17 00:00:00 2001
From: Broque Thomas <26755000+Nezreka@users.noreply.github.com>
Date: Sat, 18 Apr 2026 01:14:54 -0700
Subject: [PATCH] Hide all sync buttons in standalone mode, bump UI to v2.31
All sync-related buttons hidden when active server is SoulSync
Standalone. Covers static buttons (querySelectorAll on status update)
and dynamic modal buttons (_isSoulsyncStandalone flag).
UI version bumped to 2.31 (Docker stays at 2.3).
---
web_server.py | 4 ++--
webui/static/helper.js | 6 +++---
webui/static/script.js | 26 +++++++++++++++++++-------
3 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/web_server.py b/web_server.py
index f9930be3..30e584e3 100644
--- a/web_server.py
+++ b/web_server.py
@@ -34,7 +34,7 @@ _log_path = config_manager.get('logging.path', 'logs/app.log')
logger = setup_logging(_log_level, _log_path)
# App version — single source of truth for backup metadata, version-info endpoint, etc.
-SOULSYNC_VERSION = "2.3"
+SOULSYNC_VERSION = "2.31"
# Dedicated source reuse logger — writes to logs/source_reuse.log
import logging as _logging
@@ -22585,7 +22585,7 @@ def get_version_info():
],
},
{
- "title": "Earlier in v2.2",
+ "title": "Earlier in v2.3",
"description": "Major features from earlier in this release cycle",
"features": [
"• Centralized Downloads page with live-updating list and filter pills",
diff --git a/webui/static/helper.js b/webui/static/helper.js
index d996cd1f..beaab24f 100644
--- a/webui/static/helper.js
+++ b/webui/static/helper.js
@@ -3599,7 +3599,7 @@ function closeHelperSearch() {
// ═══════════════════════════════════════════════════════════════════════════
const WHATS_NEW = {
- '2.2': [
+ '2.31': [
// --- April 17, 2026 ---
{ date: 'April 17, 2026' },
{ title: 'Auto-Import', desc: 'Background staging folder watcher that automatically identifies and imports music. Three strategies: audio tags, folder name parsing, and AcoustID fingerprinting. Confidence-gated: 90%+ auto-imports, 70-90% queued for review, below 70% left for manual. Enable on the Import page Auto tab', page: 'import' },
@@ -3695,12 +3695,12 @@ const WHATS_NEW = {
function _getCurrentVersion() {
const btn = document.querySelector('.version-button');
- return btn ? btn.textContent.trim().replace('v', '') : '2.2';
+ return btn ? btn.textContent.trim().replace('v', '') : '2.31';
}
function _getLatestWhatsNewVersion() {
const versions = Object.keys(WHATS_NEW).sort((a, b) => parseFloat(b) - parseFloat(a));
- return versions[0] || '2.2';
+ return versions[0] || '2.31';
}
function openWhatsNew() {
diff --git a/webui/static/script.js b/webui/static/script.js
index 6cb2ad14..a9e48260 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -396,9 +396,15 @@ function handleServiceStatusUpdate(data) {
// Update downloads nav badge from status push
if (data.active_downloads !== undefined) _updateDlNavBadge(data.active_downloads);
- // Hide sync nav button for standalone mode (no server to sync playlists to)
+ // Hide sync-related UI for standalone mode (no server to sync playlists to)
+ const isSoulsyncStandalone = data.media_server?.type === 'soulsync';
+ _isSoulsyncStandalone = isSoulsyncStandalone;
const syncNav = document.querySelector('[data-page="sync"]');
- if (syncNav) syncNav.style.display = (data.media_server?.type === 'soulsync') ? 'none' : '';
+ if (syncNav) syncNav.style.display = isSoulsyncStandalone ? 'none' : '';
+ // Hide all sync buttons across the app
+ document.querySelectorAll('.sync-to-server-btn, [id$="-sync-btn"], [onclick*="startPlaylistSync"], [onclick*="syncPlaylistToServer"], [onclick*="startDecadeSync"]').forEach(btn => {
+ btn.style.display = isSoulsyncStandalone ? 'none' : '';
+ });
// Update enrichment service cards
if (data.enrichment) renderEnrichmentCards(data.enrichment);
@@ -11839,7 +11845,7 @@ function showPlaylistDetailsModal(playlist) {
? '📊 View Download Results'
: '📥 Download Missing Tracks'}
-
+
`;
@@ -25417,6 +25423,7 @@ function updateLibraryStatusCard(dbStats) {
// Track last service status for library card
let _lastServiceStatus = null;
+let _isSoulsyncStandalone = false; // Global flag: true when no media server (sync buttons hidden)
const _origFetchServiceStatus = typeof fetchAndUpdateServiceStatus === 'function' ? fetchAndUpdateServiceStatus : null;
function _capitalize(s) { return s ? s.charAt(0).toUpperCase() + s.slice(1) : ''; }
@@ -27581,7 +27588,7 @@ function showDeezerArlPlaylistDetailsModal(playlist, originalDeezerPlaylistId) {
-
+
`;
@@ -37227,7 +37234,7 @@ async function openDownloadMissingModalForArtistAlbum(virtualPlaylistId, playlis
Begin Analysis
${_isBeatportPlaylistId(virtualPlaylistId) ? `
-