"""Preferencias persistentes en settings.json, junto al ejecutable.""" from __future__ import annotations import json from dataclasses import asdict, dataclass, field from pathlib import Path from .paths import base_dir SETTINGS_NAME = "settings.json" _THEMES = ("system", "light", "dark") def _valid_theme(value) -> str: """Normaliza el tema a uno válido; cae a 'system' si es desconocido.""" return value if value in _THEMES else "system" _CONSOLE_MODES = ("show", "auto", "hide") def _valid_console_mode(value) -> str: """Normaliza el modo de consola; cae a 'auto' si es desconocido.""" return value if value in _CONSOLE_MODES else "auto" @dataclass class Settings: hide_not_downloaded: bool = False updates_pending: list[str] = field(default_factory=list) # ids con update pendiente gitea_token: str = "" # token personal de Gitea para repos privados (no se versiona) check_updates_on_start: bool = False # comprobar updates automáticamente al iniciar theme: str = "system" # tema de la UI: "system" | "light" | "dark" console_mode: str = "auto" # consola de log: "show" | "auto" | "hide" # Tolerancia a repos offline/inalcanzables (segundos, salvo stall_limit en bytes/s). git_fetch_timeout: int = 60 # techo para fetch / comprobar update git_clone_timeout: int = 900 # techo para clone (repo grande) http_timeout: int = 15 # techo para la API de Gitea git_stall_limit: int = 1000 # bytes/s: por debajo se considera transferencia estancada git_stall_time: int = 20 # segundos estancado antes de abortar def settings_path() -> Path: return base_dir() / SETTINGS_NAME def load_settings() -> Settings: path = settings_path() if not path.exists(): return Settings() try: data = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError): return Settings() return Settings( hide_not_downloaded=bool(data.get("hide_not_downloaded", False)), updates_pending=list(data.get("updates_pending", [])), gitea_token=str(data.get("gitea_token", "")), check_updates_on_start=bool(data.get("check_updates_on_start", False)), theme=_valid_theme(data.get("theme", "system")), console_mode=_valid_console_mode(data.get("console_mode", "auto")), git_fetch_timeout=int(data.get("git_fetch_timeout", 60)), git_clone_timeout=int(data.get("git_clone_timeout", 900)), http_timeout=int(data.get("http_timeout", 15)), git_stall_limit=int(data.get("git_stall_limit", 1000)), git_stall_time=int(data.get("git_stall_time", 20)), ) def save_settings(settings: Settings) -> None: try: settings_path().write_text( json.dumps(asdict(settings), ensure_ascii=False, indent=2), encoding="utf-8", ) except OSError: pass