feat (ui): series onthouden

This commit is contained in:
kodi
2026-03-09 14:45:24 +01:00
parent c5aaa20ce2
commit 0a294e9bd5
7 changed files with 410 additions and 26 deletions
+118 -1
View File
@@ -12,7 +12,9 @@ from app.config import APP_DATA_DIR
class SessionService:
FILE_DATE_SETTING_KEY = "set_file_date_to_first_aired_date"
DEFAULT_ROOT_SETTING_KEY = "default_media_root_path"
REMEMBER_MAX_SERIES_KEY = "remember_max_series"
MAX_FILENAME_LEN = 220
DEFAULT_REMEMBER_MAX_SERIES = 10
def __init__(self) -> None:
self._db_path = Path(APP_DATA_DIR) / "session_state.sqlite3"
@@ -123,6 +125,21 @@ class SessionService:
)
"""
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS remembered_series (
series_id TEXT PRIMARY KEY,
payload_json TEXT NOT NULL,
last_selected_at TEXT NOT NULL
)
"""
)
conn.execute(
"""
CREATE INDEX IF NOT EXISTS idx_remembered_series_last_selected
ON remembered_series(last_selected_at DESC)
"""
)
def get_settings(self) -> dict:
with self._connect() as conn:
@@ -134,16 +151,27 @@ class SessionService:
).fetchall()
values = {str(row["key"]): str(row["value"]) for row in rows}
remember_max_raw = values.get(self.REMEMBER_MAX_SERIES_KEY, str(self.DEFAULT_REMEMBER_MAX_SERIES))
try:
remember_max = int(remember_max_raw)
except ValueError:
remember_max = self.DEFAULT_REMEMBER_MAX_SERIES
remember_max = max(1, min(100, remember_max))
return {
self.FILE_DATE_SETTING_KEY: values.get(self.FILE_DATE_SETTING_KEY, "0") == "1",
self.DEFAULT_ROOT_SETTING_KEY: values.get(self.DEFAULT_ROOT_SETTING_KEY) or None,
self.REMEMBER_MAX_SERIES_KEY: remember_max,
}
def update_settings(self, settings: dict) -> dict:
updated_at = datetime.now(timezone.utc).isoformat()
current = self.get_settings()
allowed_keys = {self.FILE_DATE_SETTING_KEY, self.DEFAULT_ROOT_SETTING_KEY}
allowed_keys = {
self.FILE_DATE_SETTING_KEY,
self.DEFAULT_ROOT_SETTING_KEY,
self.REMEMBER_MAX_SERIES_KEY,
}
unknown_keys = [key for key in settings.keys() if key not in allowed_keys]
if unknown_keys:
raise ValueError(f"unknown setting key: {unknown_keys[0]}")
@@ -160,6 +188,12 @@ class SessionService:
raise ValueError(f"{self.DEFAULT_ROOT_SETTING_KEY} must be string or null")
default_root_path = (default_root_path or "").strip() or None
remember_max_value = merged.get(self.REMEMBER_MAX_SERIES_KEY, self.DEFAULT_REMEMBER_MAX_SERIES)
if not isinstance(remember_max_value, int):
raise ValueError(f"{self.REMEMBER_MAX_SERIES_KEY} must be integer")
if remember_max_value < 1 or remember_max_value > 100:
raise ValueError(f"{self.REMEMBER_MAX_SERIES_KEY} must be between 1 and 100")
with self._connect() as conn:
conn.execute(
"""
@@ -181,9 +215,92 @@ class SessionService:
""",
(self.DEFAULT_ROOT_SETTING_KEY, default_root_path or "", updated_at),
)
conn.execute(
"""
INSERT INTO app_settings (key, value, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(key) DO UPDATE SET
value = excluded.value,
updated_at = excluded.updated_at
""",
(self.REMEMBER_MAX_SERIES_KEY, str(remember_max_value), updated_at),
)
self._enforce_remembered_series_limit(remember_max_value)
return self.get_settings()
def list_remembered_series(self) -> list[dict]:
with self._connect() as conn:
rows = conn.execute(
"""
SELECT series_id, payload_json, last_selected_at
FROM remembered_series
ORDER BY last_selected_at DESC
"""
).fetchall()
items = []
for row in rows:
payload = json.loads(row["payload_json"])
items.append(
{
"series_id": row["series_id"],
"last_selected_at": row["last_selected_at"],
"series": payload,
}
)
return items
def remember_series(self, item: dict) -> list[dict]:
series_id = str(item.get("id") or "").strip()
if not series_id:
raise ValueError("series id is required")
# Preserve only expected display fields plus raw payload.
payload = {
"id": item.get("id"),
"name": item.get("name"),
"year": item.get("year"),
"display_name": item.get("display_name"),
"raw": item.get("raw", {}),
}
now = datetime.now(timezone.utc).isoformat()
with self._connect() as conn:
conn.execute(
"""
INSERT INTO remembered_series (series_id, payload_json, last_selected_at)
VALUES (?, ?, ?)
ON CONFLICT(series_id) DO UPDATE SET
payload_json = excluded.payload_json,
last_selected_at = excluded.last_selected_at
""",
(series_id, json.dumps(payload, ensure_ascii=True), now),
)
remember_max = int(self.get_settings().get(self.REMEMBER_MAX_SERIES_KEY, self.DEFAULT_REMEMBER_MAX_SERIES))
self._enforce_remembered_series_limit(remember_max)
return self.list_remembered_series()
def clear_remembered_series(self) -> None:
with self._connect() as conn:
conn.execute("DELETE FROM remembered_series")
def _enforce_remembered_series_limit(self, limit: int) -> None:
with self._connect() as conn:
conn.execute(
"""
DELETE FROM remembered_series
WHERE series_id NOT IN (
SELECT series_id
FROM remembered_series
ORDER BY last_selected_at DESC
LIMIT ?
)
""",
(int(limit),),
)
def list_selected_episodes(self, session_id: str) -> list[dict]:
with self._connect() as conn:
rows = conn.execute(