From 9b6b08c1ecb9190236e3dab3f1d1d20254dbd933 Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Thu, 6 Aug 2026 09:53:12 -0700 Subject: [PATCH] Return the shot's start frame image from getShotTableState Shot Lab was showing the video's single thumbnail next to every shot's layout. The backend now returns the frame the layout was detected in as a base64 JPEG (frameImage), selected by the GetShotTableState operation. Also dedupes ShareLinkGQL/CreateShotShareLinkInput, which appeared twice in the committed schema after a bad merge. Co-Authored-By: Claude Fable 5 --- src/index.tsx | 3 +++ src/operations/shot_simulation.gql | 10 +++++++--- src/schema.gql | 11 +---------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index f268c40..b0a5bd8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3882,6 +3882,7 @@ export type ShotProjectionGql = { export type ShotTableStateGql = { __typename?: "ShotTableStateGQL"; + frameImage?: Maybe; frameIndex: Scalars["Int"]["output"]; shotId: Scalars["Int"]["output"]; tableState: TableStateGql; @@ -7735,6 +7736,7 @@ export type GetShotTableStateQuery = { shotId: number; videoId: number; frameIndex: number; + frameImage?: string | null; tableState: { __typename?: "TableStateGQL"; identifierToPosition: Array>; @@ -16515,6 +16517,7 @@ export const GetShotTableStateDocument = gql` shotId videoId frameIndex + frameImage tableState { ...TableStateLayoutFields } diff --git a/src/operations/shot_simulation.gql b/src/operations/shot_simulation.gql index a4604c8..c513b1b 100644 --- a/src/operations/shot_simulation.gql +++ b/src/operations/shot_simulation.gql @@ -44,9 +44,10 @@ fragment DetectionPocketPointFields on PocketPointsGQL { # positions. Boxes, pocket boxes, and source points share the crop's # coordinate space; the crop locates that space in the full frame. # -# Only the photo query selects this. The live and shot queries read a -# frame out of a video the app never holds, so there is no image to -# overlay, and getLiveTableState is polled every five seconds. +# Only the photo query selects this. The shot query returns its source +# frame (frameImage) but positions there come from the stored homography, +# so there are no fresh boxes to draw; the live query returns no image at +# all and is polled every five seconds. fragment TableStateDetectionFields on TableStateGQL { identifierToBox { ...DetectionBoxFields @@ -97,6 +98,9 @@ query GetShotTableState($shotId: Int!) { shotId videoId frameIndex + # The b64 JPEG frame the layout was detected in, so the client can show + # the shot's actual starting frame instead of the video's thumbnail. + frameImage tableState { ...TableStateLayoutFields } diff --git a/src/schema.gql b/src/schema.gql index c46b2b5..5b04dcb 100644 --- a/src/schema.gql +++ b/src/schema.gql @@ -250,11 +250,6 @@ input CreatePoolHallCameraInput { claimTermsText: String = null } -input CreateShotShareLinkInput { - shotIds: [Int!]! - paddingSeconds: Float = null -} - input CreatePoolHallInput { name: String! address: String = null @@ -1573,6 +1568,7 @@ type ShotTableStateGQL { videoId: Int! frameIndex: Int! tableState: TableStateGQL! + frameImage: String } input ShotsOrderingComponent @oneOf { @@ -1966,11 +1962,6 @@ type UserSubscriptionStatusGQL { stripeSubscriptionId: String } -type ShareLinkGQL { - slug: String! - url: String! -} - type VideoExportJobGQL { id: Int! videoId: Int! -- 2.49.1