feat(files): the Files page — the library in one aligned list, its folders in a rail
Files is the one library: every done file, the ones shared with me, or one folder's, picked in a side rail (sources, own folders, the storage meter) and mirrored to ?folder=. One table with every kind of value in its own column; Copy link, Share and Save in sight, every action on a right click: play, cut, rename in the row, move to an own folder or back home, keep, details, re-download, delete. The Downloads page keeps only the queue until the tray replaces it. The old /api/downloads library routes are gone: list shared, upload, the details PATCH, delete, the file and the usage now live under /api/files, and a listed file says which source it came from. The job's "expired" flag is gone with the state it described.
This commit is contained in:
@@ -9,13 +9,26 @@ cannot reach, is ever read or written. DB-backed (real Postgres).
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.models import DownloadJob, DownloadShare, LibraryState
|
||||
from app.models import DownloadJob, DownloadShare, LibraryState, MediaAsset
|
||||
from app.routes._common import ProgressIn, kept_position
|
||||
|
||||
|
||||
def _done_job(db, user) -> DownloadJob:
|
||||
asset = MediaAsset(
|
||||
source_kind="url",
|
||||
source_ref="https://example.com/a.mp4",
|
||||
format_sig=f"sig-{user.id}",
|
||||
status="ready",
|
||||
rel_path=f"a-{user.id}.mp4",
|
||||
ref_count=1,
|
||||
media_kind="video",
|
||||
container="mp4",
|
||||
)
|
||||
db.add(asset)
|
||||
db.flush()
|
||||
job = DownloadJob(
|
||||
user_id=user.id,
|
||||
asset_id=asset.id,
|
||||
source_kind="url",
|
||||
source_ref="https://example.com/a.mp4",
|
||||
status="done",
|
||||
@@ -59,7 +72,7 @@ def test_a_checkpoint_is_listed_back_on_the_item(db, make_user, as_user):
|
||||
"position_seconds": 754,
|
||||
}
|
||||
|
||||
[item] = c.get("/api/downloads").json()
|
||||
[item] = c.get("/api/files").json()
|
||||
assert item["position_seconds"] == 754
|
||||
# A second checkpoint moves it rather than adding a row.
|
||||
assert _checkpoint(c, job.id, 900) == 900
|
||||
@@ -69,7 +82,7 @@ def test_a_checkpoint_is_listed_back_on_the_item(db, make_user, as_user):
|
||||
def test_an_item_never_played_lists_zero(db, make_user, as_user):
|
||||
me = make_user()
|
||||
_done_job(db, me)
|
||||
[item] = as_user(me).get("/api/downloads").json()
|
||||
[item] = as_user(me).get("/api/files").json()
|
||||
assert item["position_seconds"] == 0
|
||||
|
||||
|
||||
@@ -110,8 +123,11 @@ def test_a_recipient_keeps_their_own_place_in_a_shared_item(db, make_user, as_us
|
||||
assert _checkpoint(as_user(owner), job.id, 100) == 100
|
||||
assert _checkpoint(as_user(friend), job.id, 2000) == 2000
|
||||
|
||||
assert as_user(owner).get("/api/downloads").json()[0]["position_seconds"] == 100
|
||||
assert as_user(friend).get("/api/downloads/shared").json()[0]["position_seconds"] == 2000
|
||||
assert as_user(owner).get("/api/files").json()[0]["position_seconds"] == 100
|
||||
assert (
|
||||
as_user(friend).get("/api/files", params={"scope": "shared"}).json()[0]["position_seconds"]
|
||||
== 2000
|
||||
)
|
||||
|
||||
|
||||
def test_an_item_the_caller_cannot_play_is_a_404_and_writes_nothing(db, make_user, as_user):
|
||||
|
||||
Reference in New Issue
Block a user