slette lister
This commit is contained in:
@@ -301,6 +301,14 @@ MIGRATIONS: dict[int, list[str]] = {
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (90, 'High Intermediate', 'Stærk intermediate')",
|
||||
"INSERT INTO dance_levels (sort_order, name, description) VALUES (99, 'Advanced', 'Fuld beherskelse af trin og teknik')",
|
||||
],
|
||||
12: [
|
||||
# Tabel til at huske slettede playlister — til sync med serveren
|
||||
"""CREATE TABLE IF NOT EXISTS deleted_playlists (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
deleted_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)""",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ class SyncManager:
|
||||
logger.info(f"Push OK: {len(payload['songs'])} sange")
|
||||
result = self._post("/sync/push", payload)
|
||||
self._save_playlist_ids(result.get("playlist_id_map", {}))
|
||||
# Ryd deleted_playlists nu de er sendt til serveren
|
||||
if payload.get("deleted_playlists"):
|
||||
conn = sqlite3.connect(self._db_path)
|
||||
conn.execute("DELETE FROM deleted_playlists")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
logger.info(f"Push OK: {result.get('songs_synced', '?')} sange synkroniseret")
|
||||
if on_done:
|
||||
on_done(result)
|
||||
@@ -99,19 +105,24 @@ class SyncManager:
|
||||
threading.Thread(target=_run, daemon=True).start()
|
||||
|
||||
def push_and_pull(self, on_done=None, on_error=None):
|
||||
"""Push og derefter pull i samme tråd."""
|
||||
"""Pull FØR push — server er sandhed for playlister."""
|
||||
def _run():
|
||||
try:
|
||||
# 1. Pull FØR push — hent server-data ned lokalt
|
||||
pull_result = self._get("/sync/pull")
|
||||
self._apply_pull(pull_result)
|
||||
|
||||
# 2. Push lokal data op (sange, danse, dans-tags)
|
||||
# — playlister der kom fra serveren pushes IKKE
|
||||
payload = self._build_push_payload()
|
||||
push_result = self._post("/sync/push", payload)
|
||||
pull_result = self._get("/sync/pull")
|
||||
|
||||
pl_count = len(pull_result.get("my_playlists", []))
|
||||
logger.info(
|
||||
f"Sync OK — {len(payload['songs'])} sange, "
|
||||
f"{len(payload['playlists'])} playlister, "
|
||||
f"{pl_count} server-playlister"
|
||||
)
|
||||
self._apply_pull(pull_result)
|
||||
if on_done:
|
||||
on_done({"push": push_result, "pull": pull_result})
|
||||
except Exception as e:
|
||||
@@ -190,11 +201,11 @@ class SyncManager:
|
||||
"note": row["note"] or "",
|
||||
})
|
||||
|
||||
# Playlister (kun navngivne — ikke __aktiv__)
|
||||
# Playlister (kun lokalt oprettede — IKKE dem der kom fra serveren)
|
||||
playlists = []
|
||||
for pl in conn.execute(
|
||||
"SELECT id, name, description, tags FROM playlists "
|
||||
"WHERE name != '__aktiv__'"
|
||||
"SELECT id, name, description, tags, api_project_id FROM playlists "
|
||||
"WHERE name != '__aktiv__' AND (api_project_id IS NULL OR api_project_id = '')"
|
||||
).fetchall():
|
||||
pl_songs = []
|
||||
for ps in conn.execute("""
|
||||
@@ -222,13 +233,21 @@ class SyncManager:
|
||||
"songs": pl_songs,
|
||||
})
|
||||
|
||||
# Slettede playlister — skal fjernes fra serveren
|
||||
deleted = [
|
||||
row["name"] for row in conn.execute(
|
||||
"SELECT name FROM deleted_playlists"
|
||||
).fetchall()
|
||||
]
|
||||
|
||||
conn.close()
|
||||
return {
|
||||
"songs": songs,
|
||||
"dances": dances,
|
||||
"song_dances": song_dances,
|
||||
"song_alts": song_alts,
|
||||
"playlists": playlists,
|
||||
"songs": songs,
|
||||
"dances": dances,
|
||||
"song_dances": song_dances,
|
||||
"song_alts": song_alts,
|
||||
"playlists": playlists,
|
||||
"deleted_playlists": deleted,
|
||||
}
|
||||
|
||||
# ── Anvend pull ───────────────────────────────────────────────────────────
|
||||
@@ -255,42 +274,44 @@ class SyncManager:
|
||||
""", (d.get("choreographer",""), d.get("video_url",""),
|
||||
d.get("stepsheet_url",""), existing["id"]))
|
||||
|
||||
# Importer egne playlister fra server hvis de ikke findes lokalt
|
||||
# Importer/opdater egne playlister fra server — server er sandhed
|
||||
for pl in data.get("my_playlists", []):
|
||||
server_id = pl.get("server_id")
|
||||
name = pl.get("name", "")
|
||||
if not server_id or not name:
|
||||
continue
|
||||
|
||||
# Tjek om listen allerede eksisterer lokalt
|
||||
existing = conn.execute(
|
||||
"SELECT id FROM playlists WHERE api_project_id=?", (server_id,)
|
||||
).fetchone()
|
||||
|
||||
if existing:
|
||||
continue # Allerede importeret — spring over
|
||||
pl_id = existing["id"]
|
||||
# Opdater navn hvis det er ændret på serveren
|
||||
conn.execute(
|
||||
"UPDATE playlists SET name=? WHERE id=?", (name, pl_id)
|
||||
)
|
||||
else:
|
||||
cur = conn.execute(
|
||||
"INSERT INTO playlists (name, description, api_project_id, is_linked, server_permission) "
|
||||
"VALUES (?,?,?,1,'edit')",
|
||||
(name, pl.get("description",""), server_id)
|
||||
)
|
||||
pl_id = cur.lastrowid
|
||||
|
||||
# Opret liste
|
||||
cur = conn.execute(
|
||||
"INSERT INTO playlists (name, description, api_project_id, is_linked, server_permission) "
|
||||
"VALUES (?,?,?,1,'edit')",
|
||||
(name, pl.get("description",""), server_id)
|
||||
)
|
||||
pl_id = cur.lastrowid
|
||||
|
||||
# Indsæt sange — opret dem lokalt hvis de ikke findes endnu
|
||||
# Genindlæs sange fra serveren — server er sandhed
|
||||
conn.execute("DELETE FROM playlist_songs WHERE playlist_id=?", (pl_id,))
|
||||
position = 1
|
||||
for song_data in pl.get("songs", []):
|
||||
title = song_data.get("title", "")
|
||||
artist = song_data.get("artist", "")
|
||||
if not title:
|
||||
continue
|
||||
# Find sangen lokalt
|
||||
local = conn.execute(
|
||||
"SELECT id FROM songs WHERE title=? AND artist=? LIMIT 1",
|
||||
(title, artist)
|
||||
).fetchone()
|
||||
if not local:
|
||||
# Opret som file_missing=1 — kobles til rigtig fil ved næste scan
|
||||
import uuid
|
||||
new_id = str(uuid.uuid4())
|
||||
conn.execute(
|
||||
|
||||
@@ -372,6 +372,12 @@ class MainWindow(QMainWindow):
|
||||
self._sync_debounce.setInterval(5000)
|
||||
self._sync_debounce.timeout.connect(self._auto_sync)
|
||||
|
||||
# Periodisk sync — kører hvert 10. minut
|
||||
self._sync_periodic = QTimer(self)
|
||||
self._sync_periodic.setInterval(10 * 60 * 1000)
|
||||
self._sync_periodic.timeout.connect(self._manual_sync)
|
||||
self._sync_periodic.start()
|
||||
|
||||
self._library_panel = LibraryPanel()
|
||||
self._library_panel.set_preview_player(self._preview_player)
|
||||
|
||||
|
||||
@@ -180,6 +180,10 @@ class PlaylistManagerDialog(QDialog):
|
||||
try:
|
||||
from local.local_db import get_db
|
||||
with get_db() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO deleted_playlists (name) "
|
||||
"SELECT name FROM playlists WHERE id=?", (pl["id"],)
|
||||
)
|
||||
conn.execute("DELETE FROM playlists WHERE id=?", (pl["id"],))
|
||||
self._load_saved_playlists()
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user