Commit Graph

26 Commits

Author SHA1 Message Date
twotalesanimation 9660cdc21c feat(review): High quality playback switch and per-version ProRes download
Deploy / deploy (push) Successful in 3m23s
Worker 1.7.0 (preview.highQuality, default on) now, after the AE render:
- encodes a High quality MP4 from the delivery MOV (full-res H.264 High,
  CRF 14 capped at 100 Mbps) -> Version.hqFileUrl
- uploads the MOV itself -> Version.highResKey/Filename/Size
Both best-effort (the preview never fails over them), with a lease
keep-alive during the long encode/uploads; the export timeline records
what was attached.

Player: HQ switch when a High quality source exists; keeps frame, play
state, speed and zoom, remembered per browser, falls back to Standard if
the file won't load. ProRes itself stays download-only (browser support).

Downloads: the client portal's High Res button serves the version's
ProRes (client-code filename), falling back to the shot's manual file;
staff get a ProRes button on the review page.

Housekeeping (lib/render-pipeline/high-res.ts): HQ MP4 + ProRes are kept
while a version is latest, client-shared, approved or younger than
preview.highResRetentionDays (14); otherwise deleted from storage. Runs
per task after finalize and hourly from the reaper; deleting a version or
a reslate removes its files. The Standard MP4 is never touched.

Also: ProRes/Handles top-bar buttons go icon-only below lg so they don't
overlap the version selector.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:32:18 +02:00
twotalesanimation 2e9fa45580 feat(review): flag handles in the review player (metadata only)
Deploy / deploy (push) Successful in 3m31s
Renders run 8 frames past the cut at each end. Directors were flagging
glitches in unfixed handles as shot problems, so the player now marks
them — without trimming or burning anything into the EXRs/MOV/MP4.

- Version.handleHead/handleTail/pictureStartFrame, Export.handleHead/
  handleTail; migration backfills pipeline exports and their preview
  versions from the manifest's handleFrames (else 8)
- AE panel: "Includes handles [8] frames each end" -> manifest.review;
  older manifests fall back to source.handleFrames
- finalize copies handles onto the Version; worker 1.6.4 reports the
  head slate length (pictureStartSeconds), else the player infers it
  as MP4 frames - EXR frameCount
- Player: hatched HANDLE / SLATE regions and cut marks on the timeline,
  "HEAD/TAIL HANDLE · NOT IN EDIT" overlay on handle frames, HANDLE badge
  on notes, "Edit range only" toggle (default on in the client portal)
- Staff Handles editor on the review page for manual uploads/corrections

Also fixes two player bugs found while testing: timeToFrame floored
float error (every seek landed a frame early), and J/reverse never ran
(the keyboard effect's cleanup stopped it on the next render).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:07:29 +02:00
twotalesanimation 2b373737d8 feat(review): review players usable on phones
Deploy / deploy (push) Successful in 3m11s
Internal review: the comments panel stayed a 320px sidebar on phones,
leaving the video a 55px strip. Below md it now sits under the video
(collapsible, arrow pointing down/up), and the top bar puts shot + version
on one row with the share and approval actions on a second.

Client review: the header's three-column grid overlapped on phones
(Approve drawn over the shot code). Below md it is two rows: back, shot and
prev/next, then status and the decision buttons. The status badge now shows
on phones, and the notes toggle points down/up to match its position.

Desktop is unchanged on both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 08:13:14 +02:00
twotalesanimation 0c4f94d56a feat(client-portal): readable shot list on phones
Deploy / deploy (push) Successful in 3m14s
On a phone the approval badge was drawn over the version name on every row,
the TWO TALES logo broke over two lines, and in "recent" sort the date
wrapped onto three. Below sm the version name now takes its own line with
the badge under it, the logo stays on one line and a long link label is
truncated, and the date no longer wraps. Hover-only copy buttons are hidden
on phones, where they were invisible but still took space.

Desktop is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 07:01:05 +02:00
twotalesanimation 33bc6a935c feat(ui): shot status, projects and client portal keep their place
Deploy / deploy (push) Successful in 3m31s
Coming back from a shot left the shot status page at the top with its
sections reset. The scroll restore saved window.scrollY, but dashboard pages
scroll the layout's <main>, so it always saved 0; the Projects page had the
same bug. Only episode expansion was remembered — scene and group sections
came back fully collapsed.

A shared useScrollMemory hook saves the real scroll container's position as
the user scrolls (so any way of leaving keeps it) and restores it once the
content that sets the page height is back. It ignores the scroll the shared
<main> fires when the next page replaces this one, which otherwise
overwrote the saved position.

Shot status now remembers episode, scene and group expansion per project.
The client portal already kept its filters and collapsed episodes but
restored scroll before they were applied; it now uses the hook too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 05:52:13 +02:00
twotalesanimation 28e8c47907 feat(client-portal): let a reviewer edit and delete their own notes
Notes left through a review link were write-once. A client who mistyped a
timecode or changed their mind had no way to correct it and had to add a second
note contradicting the first, which the studio then had to reconcile by hand.

PATCH and DELETE on comment/[commentId] cover both. Only the reviewer's own
notes are touchable: the studio's comments and those of every other review
session are read-only through a link, whatever the holder sends. Ownership is
re-checked server-side on every write, so the canEdit flag now returned by the
versions route only decides whether to offer the controls and grants nothing.

Refusals are 404 rather than 403 throughout, since a link holder has no business
learning which comment ids exist outside their own notes.

Only the text is editable. The frame a note is pinned to is what the studio
works from, so moving it would silently repoint feedback someone may already
have actioned; a note about a different frame is a new note. Deleting a drawing
note also removes its strokes, mirroring deleteComment in actions/comments.ts,
and the page reloads the player afterwards so the frame does not keep showing
marks that no longer exist. Delete goes through a confirmation that shows the
note and says plainly that it disappears for the studio too.

Worth knowing before this reaches a show: everyone holding the same review link
is the same author. A ReviewSession with no email resolves to a token-derived
guest user, so one link sent to three people gives all three one identity and
any of them can now edit or delete the others' notes. That model is not new,
which is why their comments already showed as one name, but edit and delete is
the first feature where it grants real power rather than muddling attribution.
Per-reviewer links with email set are the fix if that is not wanted, and that is
a change to how links are issued rather than to this code. The scope is
documented on reviewClientEmail so the next reader meets it before it surprises
them.

getOrCreateClientUser was copy-pasted into the comment and approve routes with
the fallback-email expression spelled out in three places. It is one set of
helpers in review-auth.ts now, including findReviewUser, a read-only variant so
that merely opening a review link does not conjure a User row just to answer
"is this theirs?", and ownsComment, the single rule shared by the route that
offers the controls and the route that enforces them.

Nine tests cover that rule directly: internal users' notes stay read-only, a
session that has never posted owns nothing, and an authorless comment — one
whose User was deleted, since Comment.authorId is SetNull — cannot be claimed by
anyone. The routes themselves are not covered, so exercise edit and delete
against a real review link before handing one to a client.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 18:17:40 +02:00
twotalesanimation cf55a53c06 fix(client): remove version notes from the client shot-list page
Deploy / deploy (push) Failing after 2s
Removes the three spots on the client review shot-list page that showed
a version's notes under the task title (flat task list, shot-grouped
list, asset list) — one of the three was already commented out by hand,
uncommitted, as a stopgap for the same issue.

The API route backing this page no longer selects notes at all, so it
stops being sent to the client rather than only going unrendered — the
same treatment as removing the pipeline's internal-only notes text in
53fc8dc.

The individual review player (app/client/[token]/review/[versionId]/)
has its own separate notes field and fetch and is untouched: this was
scoped to the shot-list overview only, per what was asked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:57:58 +02:00
twotalesanimation 87332cdae3 Collapseable Comments section
Deploy / deploy (push) Successful in 2m46s
2026-07-16 19:17:17 +02:00
twotalesanimation 6fc818a3db Client View updates
Deploy / deploy (push) Successful in 2m47s
2026-07-09 14:52:50 +02:00
twotalesanimation 7026a5342b fixed client review player annotations
Deploy / deploy (push) Successful in 2m46s
2026-07-02 15:58:20 +02:00
twotalesanimation 13d47315dd download link updated
Deploy / deploy (push) Successful in 2m38s
2026-06-25 18:29:58 +02:00
twotalesanimation b683976cc6 High res uploads
Deploy / deploy (push) Successful in 3m16s
2026-06-25 09:56:41 +02:00
twotalesanimation 1a5a56cf4c updated client review page2
Deploy / deploy (push) Successful in 2m32s
2026-06-22 08:03:00 +02:00
twotalesanimation ab062a589a updated client review page
Deploy / deploy (push) Successful in 2m35s
2026-06-22 07:48:27 +02:00
twotalesanimation ef6e41f8e0 futher client page updates2
Deploy / deploy (push) Successful in 2m27s
2026-06-19 12:36:04 +02:00
twotalesanimation 0f403f13aa futher client page updates
Deploy / deploy (push) Failing after 45s
2026-06-19 12:19:58 +02:00
twotalesanimation d04e0252f1 copy shot names
Deploy / deploy (push) Successful in 2m28s
2026-06-19 12:00:04 +02:00
twotalesanimation 4c64842be6 Client review page updates
Deploy / deploy (push) Successful in 2m36s
2026-06-19 11:36:42 +02:00
twotalesanimation 874a1a98f2 removed version numbers from client review
Deploy / deploy (push) Successful in 2m34s
2026-06-12 12:47:57 +02:00
twotalesanimation 23f0ceca3f client passwords
Deploy / deploy (push) Successful in 2m57s
2026-06-12 12:37:57 +02:00
twotalesanimation 5bfaf49fa1 mobile client player layoout updates
Deploy / deploy (push) Successful in 2m45s
2026-06-12 11:01:00 +02:00
twotalesanimation 01474084fa mobile support for client review player3
Deploy / deploy (push) Successful in 2m27s
2026-06-12 09:49:37 +02:00
twotalesanimation 72ce7af1ec mobile support for client review player2
Deploy / deploy (push) Successful in 2m31s
2026-06-12 09:33:54 +02:00
twotalesanimation 289e0c367a mobile support for client review player
Deploy / deploy (push) Failing after 5m17s
2026-06-12 09:01:28 +02:00
twotalesanimation 7788907a4a task approval updates
Deploy / deploy (push) Successful in 2m38s
2026-06-11 15:55:57 +02:00
twotalesanimation 0fbe856dce Initial commit 2026-05-19 22:20:29 +02:00