Wire up automatic first-run detection for setup wizard

Wizard now shows automatically on fresh installs. Detection uses a
server-side flag (setup.completed) plus download_source.mode as a
fallback for existing users who configured settings before the wizard
existed. Config.json template defaults no longer fool the check.

Script load order fixed — setup-wizard.js loads before script.js so
openSetupWizard exists when DOMContentLoaded fires. Both finish and
skip paths set the server flag and localStorage, then continue app
initialization via callback.
pull/283/head
Broque Thomas 1 month ago
parent 08de91685d
commit eff22f55d7

@ -6125,18 +6125,22 @@ def get_mirrored_playlists_list():
@app.route('/api/setup/status', methods=['GET'])
def setup_status_endpoint():
"""Check if first-run setup has been completed."""
# Consider setup incomplete if no slskd URL and no download source configured
slskd_url = config_manager.get('soulseek.slskd_url', '')
# The setup wizard sets this flag when completed. download_source.mode is only
# set by user action (wizard or settings page), never by config.json defaults.
setup_done = config_manager.get('setup.completed', False)
download_mode = config_manager.get('download_source.mode', '')
transfer_path = config_manager.get('soulseek.transfer_path', '')
has_any_config = bool(slskd_url) or bool(download_mode) or bool(transfer_path)
# Either the explicit flag or a user-configured download source means setup is done
has_user_config = bool(setup_done) or bool(download_mode)
return jsonify({
"setup_complete": has_any_config,
"has_download_source": bool(download_mode),
"has_slskd": bool(slskd_url),
"has_transfer_path": bool(transfer_path),
"setup_complete": has_user_config,
})
@app.route('/api/setup/complete', methods=['POST'])
def setup_complete_endpoint():
"""Mark first-run setup as completed."""
config_manager.set('setup.completed', True)
return jsonify({"success": True})
@app.route('/api/test-connection', methods=['POST'])
def test_connection_endpoint():
data = request.get_json()

@ -7351,6 +7351,7 @@
<script src="{{ url_for('static', filename='vendor/socket.io.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
<script src="{{ url_for('static', filename='setup-wizard.js') }}"></script>
<script src="{{ url_for('static', filename='script.js') }}"></script>
<!-- Notification bell + floating helper toggle — always accessible above modals -->
<!-- Global Search Bar — Spotlight-style search from anywhere -->
@ -7376,7 +7377,6 @@
<script src="{{ url_for('static', filename='helper.js') }}"></script>
<script src="{{ url_for('static', filename='particles.js') }}"></script>
<script src="{{ url_for('static', filename='worker-orbs.js') }}"></script>
<script src="{{ url_for('static', filename='setup-wizard.js') }}"></script>
</body>
</html>

@ -2616,6 +2616,36 @@ async function checkAdminPinRequired() {
document.addEventListener('DOMContentLoaded', async function () {
console.log('SoulSync WebUI initializing...');
// Check if first-run setup wizard should be shown
const params = new URLSearchParams(window.location.search);
const forceSetup = params.get('setup') === '1';
let showWizard = forceSetup;
if (!forceSetup) {
try {
const setupResp = await fetch('/api/setup/status');
const setupData = await setupResp.json();
if (!setupData.setup_complete) {
showWizard = true;
localStorage.removeItem('soulsync_setup_complete');
}
} catch (e) {
console.warn('Setup status check failed, continuing normal init:', e);
}
}
if (showWizard && typeof openSetupWizard === 'function') {
window._onSetupWizardComplete = function () {
_continueAppInit();
};
openSetupWizard();
return; // Defer init until wizard closes
}
_continueAppInit();
});
async function _continueAppInit() {
// Initialize profile management UI handlers
initProfileManagement();
@ -2627,7 +2657,7 @@ document.addEventListener('DOMContentLoaded', async function () {
}
initApp();
});
}
function initApp() {
// Initialize components

@ -62,6 +62,16 @@ function openSetupWizard() {
function closeSetupWizard() {
const overlay = document.getElementById('setup-wizard-overlay');
if (overlay) overlay.style.display = 'none';
// Mark as complete so it doesn't show again (server + client)
localStorage.setItem('soulsync_setup_complete', 'true');
fetch('/api/setup/complete', { method: 'POST' }).catch(() => {});
// Continue app initialization if wizard was shown on first run
if (typeof window._onSetupWizardComplete === 'function') {
window._onSetupWizardComplete();
window._onSetupWizardComplete = null;
}
}
// ---- Navigation ----
@ -957,12 +967,26 @@ async function _wizardFinish() {
console.error('Wizard final save error:', e);
}
// Mark setup complete on both server and client
try {
await fetch('/api/setup/complete', { method: 'POST' });
} catch (e) {
console.error('Failed to mark setup complete on server:', e);
}
localStorage.setItem('soulsync_setup_complete', 'true');
closeSetupWizard();
const overlay = document.getElementById('setup-wizard-overlay');
if (overlay) overlay.style.display = 'none';
// Reload settings into the main UI
if (typeof loadSettings === 'function') loadSettings();
if (typeof showToast === 'function') showToast('Setup complete — welcome to SoulSync!', 'success');
// Continue app initialization if wizard was shown on first run
if (typeof window._onSetupWizardComplete === 'function') {
window._onSetupWizardComplete();
window._onSetupWizardComplete = null;
}
}
// ---- Utility ----
@ -973,18 +997,8 @@ function _escHtml(str) {
}
// ---- Dev Trigger ----
// Open wizard with: openSetupWizard() from console, or ?setup=1 URL param
(function _checkWizardAutoOpen() {
const params = new URLSearchParams(window.location.search);
if (params.get('setup') === '1') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => setTimeout(openSetupWizard, 300));
} else {
setTimeout(openSetupWizard, 300);
}
}
})();
// Open wizard manually: openSetupWizard() from console, or ?setup=1 URL param
// First-run auto-detection is handled in script.js DOMContentLoaded
// Expose globally
window.openSetupWizard = openSetupWizard;

Loading…
Cancel
Save