wrdler / specs /settings.md
Surn's picture
v0.2.8 Settings Page fixed
f0df64e

A newer version of the Streamlit SDK is available: 1.52.2

Upgrade

Settings Page Refactoring Plan

Goal

Move the sidebar configuration controls (_render_sidebar) from wrdler/ui.py to a dedicated Settings page (wrdler/settings_page.py), accessible via the footer navigation.

Files to Create

  1. wrdler/settings_page.py

Files to Modify

  1. wrdler/ui.py

Detailed Steps

1. Create wrdler/settings_page.py

This file will encapsulate the rendering logic for the settings.

  • Imports:

    • streamlit as st
    • os
    • time
    • From wrdler.word_loader: get_wordlist_files, get_wordlist_info
    • From wrdler.generator: sort_word_file, filter_word_file
    • From wrdler.audio: get_audio_tracks, _inject_audio_control_sync
    • From wrdler.version_info: versions_html
  • Functions:

    • render_settings_page(new_game_callback):
      • Renders the title "Settings".
      • Contains the logic previously in _render_sidebar (Game Mode, Wordlist Controls, Grid Options, Audio Controls).
      • Important: Does not include _mount_background_audio (this will be global).
      • Uses st.container or main layout instead of st.sidebar.
      • Accepts new_game_callback to trigger a game reset when settings change.
    • _sort_wordlist(filename): Moved from ui.py.
    • _filter_wordlist(filename): Moved from ui.py.
    • _filter_results_dialog: Moved from ui.py (if used by _filter_wordlist).
    • Local callbacks _on_wordlist_change and _on_ai_generate that utilize new_game_callback.

2. Modify wrdler/ui.py

  • Extract Audio Logic:

    • Create a helper function _handle_audio() that contains the audio initialization and mounting logic previously in _render_sidebar.
    • This ensures audio persists across pages.
  • Update run_app():

    • Call _handle_audio() at the top level (before page routing).
    • Add routing logic for page="settings":
      • Import render_settings_page.
      • Render background.
      • Call render_settings_page(_on_game_option_change).
      • Render footer with current_page="settings".
      • Return (stop execution of main game).
    • Remove _render_sidebar() call.
  • Update _render_footer():

    • Add a link to ?page=settings with label "?? Settings".
    • Highlight it when current_page="settings".
  • Cleanup:

    • Remove _render_sidebar function.
    • Remove _sort_wordlist, _filter_wordlist (moved to settings page).

Implementation Notes

  • Audio: The audio controls (volume, track) will be in the Settings page, but the audio player (hidden HTML/JS) must be mounted on every page load via _handle_audio() in run_app to ensure continuous playback or proper state.
  • Callbacks: _on_game_option_change in ui.py calls _new_game. This callback will be passed to render_settings_page so that changing settings triggers the necessary state resets.
  • Navigation: The footer will serve as the primary navigation between "Play", "Leaderboard", and "Settings".

Settings Persistence Guidance (UPDATED)

  • Each settings configuration is saved as a separate JSON file in wrdler/settings/, not as a single large file.
  • File naming convention: Use a unique, human-readable key based on the main settings (e.g., classic-classic-0.json).
    • Example: wrdler/settings/classic-classic-0.json
    • This mirrors the leaderboard's convention (e.g., weekly/2025-W51/classic-classic-0/settings.json), but is local and not required to match challenge/leaderboard config structure.
  • Settings files should use the same layout as the current settings.json, but each file only contains one configuration.
  • No need to match leaderboard or challenge settings.json structure exactly.
  • When saving settings, only the relevant configuration for that file is written.
  • When loading, look up the file by its unique key.
  • This approach supports local wordlists and ensures settings are unique per instance.

Plan: Local Settings File Storage and Loading (Implemented in v0.2.8)

  1. Settings File Naming

    • For each unique settings configuration, generate a filename like classic-classic-0.json based on the main settings (e.g., game mode, wordlist, spacer).
    • Store these files in wrdler/settings/.
  2. Saving Settings

    • When the user clicks "Save Settings" in the settings page:
      • Gather all relevant settings from st.session_state.
      • Generate the unique filename for the current configuration.
      • Save the settings as a JSON file in wrdler/settings/ using the generated filename.
      • Use the same JSON structure as the current settings.json, but only for this configuration.
  3. Loading Settings in wrdler/ui.py

    • On app startup (in _init_session() or before applying defaults):
      • Determine the intended settings file (e.g., from defaults or user selection).
      • If the file exists in wrdler/settings/, load it and update st.session_state with its values (only for keys not already set).
      • If not, proceed with defaults.
  4. Settings Page Integration

    • The settings page should allow users to select, save, and load settings configurations by their unique keys.
    • Optionally, provide a dropdown or list of available settings files for quick switching.
  5. Directory Management

    • Ensure the wrdler/settings/ directory is created if it does not exist.
    • Handle file I/O errors gracefully and inform the user if saving/loading fails.
  6. Extensibility

    • When new settings are added, include them in the filename generation and JSON structure as needed.
    • This approach allows for easy expansion as more settings or wordlists are introduced.