Files
Barış Keser 751b85a807 v1.0.4: playlist toplu indirme + arayuz duzeltmeleri + Dependabot + belgeler
Ozellikler:
- Playlist toplu indirme (onizle-ve-sec): YouTube playlist URL'si yapistir ->
  tum parcalar arama sonucu gibi listelenir (SearchThread playlist modu,
  noplaylist=False + extract_flat), checkbox'la sec, toplu indir. Yeni bridge
  slotu importPlaylist(url). Indirme pill'i "X/Y" sayaci gosterir (download_total).
- Geri/Ileri gezinme: ust bardaki oklar artik gercek gorunum-gecmisi yiginiyla
  calisir (recordHistory/navBack/navFwd, wireEvents'te baglandi).

Duzeltmeler (alt-ajan taramasindan):
- Komut paletinden karaoke menusu flash-kapaniyordu -> palet ogesi onclick'i
  stopPropagation (global tikla-kapat menuyu silmesin).
- Arama/akilli-liste gorunumunde surukle-sirala gercek listeyi bozup
  kaydediyordu -> trackRow(reorderable): yalniz gercek tam-liste suruklenebilir.
- dl-pill/sep-pill/mini-klip ayni sag-alt kosede biniyordu -> pill'ler sol-alta,
  sepPill dl'nin ustune; ayrica sepPill .show sinifi eksikti (gorunmuyordu) -> fix.
- trackChanged JSON.parse guard'siz -> try/catch.
- repeat_mode trackChanged payload'inda yoktu -> eklendi + okundu (3 durumlu
  tekrar dugmesi parca degisince dogru).
- Eski YouTube sonuclari sorgu degisince temizleniyor.

Altyapi:
- Dependabot (.github/dependabot.yml): pip + github-actions haftalik.
- docs/: ARCHITECTURE, BRIDGE-SIGNALS, KNOWN-ISSUES, DEV (+ TR->EN sozluk) —
  proje kendini belgeliyor. graphify grafigi guncellendi.
- README + GitHub about + Pages: banner (OpenRouter/Nano Banana Pro ile uretildi),
  rozetler, v1.0.4 notlari.
2026-09-19 21:50:15 +03:00

53 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Just Music Premium — Known Issues & Gotchas
A defect + gotcha log so future work doesn't re-discover the same traps.
Line numbers are approximate — grep the symbol, don't trust the number after edits.
Files that matter most: `justmusic/web/app.js`, `justmusic/web/app.css`, `justmusic/bridge.py`, `justmusic/config.py`.
---
## Part 1 — Fixed in v1.0.4
- [x] **1. Top-bar Back/Forward arrows were dead** (never wired). ✅ FIXED — real view-history stack: `recordHistory` / `navBack` / `navFwd` (app.js ~223–246), wired in `wireEvents` (`$('#navBack').onclick=navBack; $('#navFwd').onclick=navFwd;`, ~app.js:755). `recordHistory` skips clip mode and de-dupes the current location; `navLock` guards replays.
- [x] **2. Karaoke menu from the Ctrl+K command palette flash-closed.** Root cause: the global `document.addEventListener('click', … remove .ctx-menu)` (app.js ~39) removes any left-click-opened menu on the *same* click's bubble. ✅ FIXED — the palette item `onclick` now calls `e.stopPropagation()` before running the command (app.js ~1240). The direct `#pKaraoke` button already had this guard (app.js ~780).
- [x] **3. Drag-to-reorder from Search / Smart-list views corrupted the real playlist** (filtered index applied to the real array, then persisted). ✅ FIXED — `trackRow(s, i, pl, reorderable)` (app.js ~340) makes rows `draggable` only when `reorderable` is true. Only the real full-list `renderPlaylist` passes `true` (~app.js:336); Search (~410) and Smart (~1219) pass nothing → drag off. Drop also requires `playlistSort==='default'` (~app.js:367).
- [x] **4. Download pill, separation pill and mini-clip player all pinned bottom-right and overlapped.** ✅ FIXED — pills moved to bottom-**LEFT**; `#sepPill` stacks *above* `#dlPill` (`.dl-pill{left:20px; bottom:calc(var(--player-h)+18px)}`, `#sepPill{bottom:calc(var(--player-h)+78px)}`, app.css ~396–398). Mini-clip stays bottom-right (`.clip-mini{right:20px}`, app.css ~480). Also the separation pill never appeared because `updateSepPill` didn't add `.show` — ✅ FIXED (app.js ~1058).
- [x] **5. `trackChanged` handler had no try/catch around `JSON.parse`** (every other signal did). ✅ FIXED — `bridge.trackChanged.connect(j=>{try{track=JSON.parse(j);}catch(e){return;}onTrackChanged();})` (app.js ~712).
- [x] **6. `repeat_mode` was missing from the `trackChanged` payload**, so the 3-state repeat glyph could drift. ✅ FIXED — added to `_track_json()` (bridge.py ~369) and read in `onTrackChanged` (`if(track.repeat_mode!=null)active.repeat_mode=track.repeat_mode;`, app.js ~644).
- [x] **7. Stale YouTube results lingered when the search box was narrowed/cleared.** ✅ FIXED — `searchRows=[]` on every `#topSearch` input change (app.js ~758).
---
## Part 2 — Known / open (not yet fixed)
- [ ] **`showView('playlist')` with a null `viewPlaylist` leaves `view` lying.** `view=v` is set at the top of `showView` (app.js ~208) *before* the `v==='playlist' && viewPlaylist` guard fails and falls through to `renderHome()` (~217). Result: global `view` says `'playlist'` while Home is on screen. app.js ~207–217.
- [ ] **Heart "burst" like-animation never triggers.** `.icon-btn.fav.burst` + `@keyframes burst` exist in CSS (app.css ~428–429) but no JS ever adds `.burst` — `updatePlayer` only toggles `.on` on `#pFav` (app.js ~619). The animation is dead until something adds/removes the class on like.
- [ ] **Visualizer hot path forces a style recalc every frame.** `vizLoop` (app.js ~657) runs `drawPlayerViz` + `drawWaveforms` + `updateAmbient` on *every* `requestAnimationFrame` with no early-out when paused, and each of `vizLoop` / `drawPlayerViz` / `drawWaveforms` calls `getComputedStyle(document.documentElement)` per frame (app.js ~663, ~674, ~940, ~994) to read `--accent-rgb`. That's a forced synchronous style/layout read in the hot path. Suggested: cache the accent color, refresh only on accent/cover change; and bail early when `!active.playing`.
- [ ] **Dead code.** `confirmBox` (app.js ~66) is an unused wrapper around `modalConfirm`. The seek handler computes an unused `dur` local (`const dur=parseFloat($('#pDur')…)`, app.js ~793) and then uses `lastDur` instead — remove it.
- [ ] **yt-dlp goes stale every few weeks** (YouTube changes its player). Symptom: downloads start returning **HTTP 403** while *search still works*. Fix: bump the pinned `yt-dlp` and rebuild (see the v1.0.3 commit). Future idea: a runtime yt-dlp self-updater would avoid shipping a full ~490 MB app update each time.
---
## Traps / invariants
Read these before touching menus, drag-reorder, the clip player, or playlist names.
- **(a) ctx-menu + global click-closer.** Any `.ctx-menu` opened by a **left-click** MUST call `e.stopPropagation()` in that click's handler, or the global `document`-level click listener (app.js ~39) removes it on the same bubble. Right-click (`contextmenu`) opens are safe. See `#pKaraoke` (~780) and the palette item (~1240) for the pattern.
- **(b) `trackRow` drag index is only valid in the default full-list view.** The `idx` stored on dragstart indexes the *displayed* array. It is only equal to the real playlist index in `renderPlaylist` with `playlistSort==='default'`. Never enable reorder drag from filtered/sorted/smart/search views — pass `reorderable=false` (the default) and the drop guard also checks `playlistSort==='default'`.
- **(c) The clip `<video>` MUST be removed from the DOM on stop.** Pausing alone keeps network traffic alive AND a live `<video>` left in the DOM **crashes QtWebEngine on app close**. `stopClip` (app.js ~1120) does `v.pause(); v.removeAttribute('src'); v.load();` then `host.remove()`. Keep all three steps. The audio engine is separate — don't touch it here.
- **(d) Protected playlist names are stored dict keys, not display labels.** `"Kütüphanem"`, `"Beğenilen Şarkılar"`, `"İndirilenler"` are `config.PROTECTED_PLAYLISTS` (config.py ~88–91) and used as literal keys in the library/state dicts and download routing (bridge.py ~1343). Do **not** rename, translate, or "prettify" them — renaming a key silently orphans its songs. The UI already hides rename/delete for `S.protected` (app.js ~198).