After a grab (manual or Auto) the user now SEES what happened and can follow it: - The chosen result card is spotlighted (Auto scrolls it into view) and grows a live tracker: a progress bar that follows the real download + a 'Track on Downloads ↗' button that closes the modal and jumps to the Downloads page. Polls the new GET /api/video/downloads/status?id= until the download reaches a terminal state. - A movie's detail page shows a live download chip (progress bar + %) for any in-flight download of that title; clicking it jumps to Downloads. Looks up by media identity via /downloads/status?media_id=&media_source=, polls while active, clears on navigate-away. (video-detail.js) - Result CARDS redesigned (the part you didn't like): a column card with a colour resolution badge, a green 'accepted' edge, cleaner hierarchy, and the grab button is now an accent 'Get' pill matching the source Auto button language. Plumbing: new lightweight /downloads/status endpoint (by id, or by media for detail pages); soulsync:video-navigate event in video-side.js to reach a top-level page from anywhere; VideoGet.close exported so the tracker can dismiss the modal. All video-only. Tests: status endpoint (by id + by media + null cases) in test_video_api.py; tracking/detail/nav wiring in test_video_download_tracking.py. node --check clean; isolation guards green.
73 lines
3.1 KiB
Python
73 lines
3.1 KiB
Python
"""Live download tracking wiring: after a grab the user must (a) see WHICH release
|
|
was selected, (b) get a live progress bar on it, and (c) get a button to the
|
|
Downloads page — and a movie's detail page shows live progress for an in-flight
|
|
download that jumps back to Downloads.
|
|
|
|
Backed by GET /api/video/downloads/status (tested in test_video_api.py
|
|
::test_downloads_status_lookup_by_id_and_media). These pin the frontend wiring so
|
|
a refactor can't quietly unhook the tracker, the detail chip, or the navigation.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
_ROOT = Path(__file__).resolve().parent.parent
|
|
_VIEW = (_ROOT / "webui" / "static" / "video" / "video-download-view.js").read_text(encoding="utf-8")
|
|
_DETAIL = (_ROOT / "webui" / "static" / "video" / "video-detail.js").read_text(encoding="utf-8")
|
|
_SIDE = (_ROOT / "webui" / "static" / "video" / "video-side.js").read_text(encoding="utf-8")
|
|
_GETMODAL = (_ROOT / "webui" / "static" / "video" / "video-get-modal.js").read_text(encoding="utf-8")
|
|
_CSS = (_ROOT / "webui" / "static" / "video" / "video-side.css").read_text(encoding="utf-8")
|
|
|
|
|
|
# --- result card: redesign + selected/tracking state ----------------------
|
|
|
|
def test_result_card_redesigned_as_column_with_get_button():
|
|
assert 'vdl-res-main' in _VIEW # row wrapper so a tracker can dock below
|
|
assert 'data-vdl-card="' in _VIEW # addressable card (auto-pick targets it)
|
|
assert 'vdl-res-grab-ic' in _VIEW # the grab button is now a labelled "Get" pill
|
|
assert '.vdl-res-main' in _CSS
|
|
|
|
|
|
def test_grab_begins_live_tracking_on_the_card():
|
|
assert 'function beginTracking(' in _VIEW
|
|
assert 'vdl-res--grabbed' in _VIEW
|
|
assert 'data-vdl-track-fill' in _VIEW # the progress bar fill
|
|
assert "/api/video/downloads/status?id=" in _VIEW
|
|
# both the manual grab and the auto-pick start tracking the chosen card
|
|
assert _VIEW.count('beginTracking(') >= 3 # 1 def + doGrab + _autoPick
|
|
|
|
|
|
def test_track_button_goes_to_downloads_and_closes_modal():
|
|
assert 'Track on Downloads' in _VIEW
|
|
assert 'function gotoDownloads(' in _VIEW
|
|
assert 'VideoGet.close' in _VIEW
|
|
assert "'soulsync:video-navigate'" in _VIEW
|
|
assert '.vdl-res-track' in _CSS
|
|
|
|
|
|
def test_modal_exposes_close():
|
|
assert 'close: closeModal' in _GETMODAL
|
|
|
|
|
|
# --- movie detail page: live download chip --------------------------------
|
|
|
|
def test_detail_page_watches_movie_download():
|
|
assert 'function watchMovieDownload(' in _DETAIL
|
|
assert '/api/video/downloads/status?media_id=' in _DETAIL
|
|
assert 'data-vd-dlchip' in _DETAIL
|
|
# the chip jumps to the Downloads page
|
|
assert "'soulsync:video-navigate'" in _DETAIL
|
|
assert '.vd-dlchip' in _CSS
|
|
|
|
|
|
def test_detail_watch_started_for_library_movies():
|
|
assert 'watchMovieDownload(id)' in _DETAIL
|
|
assert 'stopMovieDownloadWatch()' in _DETAIL # cleared on (re)load / navigate away
|
|
|
|
|
|
# --- navigation plumbing --------------------------------------------------
|
|
|
|
def test_video_side_handles_navigate_event():
|
|
assert "'soulsync:video-navigate'" in _SIDE
|
|
assert 'navigate(pageId)' in _SIDE
|