From 51832535674c8ec0bc96471ac1432ed688a58ec1 Mon Sep 17 00:00:00 2001 From: Dean Wenstrand Date: Wed, 22 Jul 2026 22:47:20 -0700 Subject: [PATCH] Re-add legacy shot-sim operations alongside GetShotLabVideos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mobile master's shot-simulation-screen still uses LiveStreamPicker and RecordedShotPicker (GetLiveStreams / GetRecordedShots) while ALSO using the video-first GetShotLabVideos picker — a transitional state. 1a95439 replaced the old operations, so no gql commit carried the union, which left mobile master's submodule pointer unable to satisfy its own code (master pinned an old pointer and typechecks silently broke — CI only runs on PRs). Additive and operation-only; drop these again when the old pickers are deleted. Co-Authored-By: Claude Opus 4.8 --- src/index.tsx | 258 ++++++++++++++++++++++++------ src/operations/live_streams.gql | 34 ++++ src/operations/recorded_shots.gql | 30 ++-- 3 files changed, 259 insertions(+), 63 deletions(-) create mode 100644 src/operations/live_streams.gql diff --git a/src/index.tsx b/src/index.tsx index dfec50c..1046f0e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -5414,6 +5414,43 @@ export type GetMyDrillRunsQuery = { }>; }; +export type GetLiveStreamsQueryVariables = Exact<{ + limit?: Scalars["Int"]["input"]; +}>; + +export type GetLiveStreamsQuery = { + __typename?: "Query"; + getFeedVideos: { + __typename?: "VideoHistoryGQL"; + videos: Array<{ + __typename?: "VideoGQL"; + id: number; + name?: string | null; + startTime?: any | null; + createdAt?: any | null; + screenshotUri?: string | null; + elapsedTime?: number | null; + owner?: { + __typename?: "UserGQL"; + id: number; + username: string; + profileImageUri?: string | null; + } | null; + stream?: { + __typename?: "UploadStreamGQL"; + id: string; + isCompleted: boolean; + lastSegmentUploadedAt?: any | null; + } | null; + }>; + pageInfo: { + __typename?: "PageInfoGQL"; + hasNextPage: boolean; + endCursor?: string | null; + }; + }; +}; + export type GetVideoMakePercentageIntervalsQueryVariables = Exact<{ videoId: Scalars["ID"]["input"]; intervalDuration: Scalars["Int"]["input"]; @@ -6755,12 +6792,11 @@ export type ReactToVideoMutation = { reactToVideo: boolean; }; -export type GetShotLabVideosQueryVariables = Exact<{ - userId: Scalars["Int"]["input"]; +export type GetRecordedStreamsQueryVariables = Exact<{ limit?: Scalars["Int"]["input"]; }>; -export type GetShotLabVideosQuery = { +export type GetRecordedStreamsQuery = { __typename?: "Query"; getFeedVideos: { __typename?: "VideoHistoryGQL"; @@ -6778,12 +6814,6 @@ export type GetShotLabVideosQuery = { username: string; profileImageUri?: string | null; } | null; - stream?: { - __typename?: "UploadStreamGQL"; - id: string; - isCompleted: boolean; - lastSegmentUploadedAt?: any | null; - } | null; }>; }; }; @@ -6807,13 +6837,29 @@ export type GetRecordedStreamShotsQuery = { __typename?: "SerializedShotPathsGQL"; b64EncodedBuffer?: string | null; } | null; + cueObjectFeatures?: { + __typename?: "CueObjectFeaturesGQL"; + cueObjectDistance?: number | null; + cueObjectAngle?: number | null; + cueBallSpeed?: number | null; + shotDirection?: ShotDirectionEnum | null; + spinType?: SpinTypeEnum | null; + } | null; pocketingIntentionFeatures?: { __typename?: "PocketingIntentionFeaturesGQL"; make?: boolean | null; + targetPocketDistance?: number | null; + targetPocketAngle?: number | null; + targetPocketAngleDirection?: ShotDirectionEnum | null; + marginOfErrorInDegrees?: number | null; + intendedPocketType?: PocketEnum | null; + difficulty?: number | null; } | null; pocketingIntentionInfo?: { __typename?: "PocketingIntentionInfoGQL"; + ballId: number; pocketId: PocketIdentifier; + pathMetadataIndex: number; } | null; }>; }; @@ -12385,6 +12431,105 @@ export type GetMyDrillRunsQueryResult = Apollo.QueryResult< GetMyDrillRunsQuery, GetMyDrillRunsQueryVariables >; +export const GetLiveStreamsDocument = gql` + query GetLiveStreams($limit: Int! = 25) { + getFeedVideos( + limit: $limit + filters: { isStreamCompleted: false, requireCursorCompletion: false } + includePrivate: MINE + feedInput: { allUsers: true } + ) { + videos { + id + name + startTime + createdAt + screenshotUri + elapsedTime + owner { + id + username + profileImageUri + } + stream { + id + isCompleted + lastSegmentUploadedAt + } + } + pageInfo { + hasNextPage + endCursor + } + } + } +`; + +/** + * __useGetLiveStreamsQuery__ + * + * To run a query within a React component, call `useGetLiveStreamsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetLiveStreamsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetLiveStreamsQuery({ + * variables: { + * limit: // value for 'limit' + * }, + * }); + */ +export function useGetLiveStreamsQuery( + baseOptions?: Apollo.QueryHookOptions< + GetLiveStreamsQuery, + GetLiveStreamsQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useQuery( + GetLiveStreamsDocument, + options, + ); +} +export function useGetLiveStreamsLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions< + GetLiveStreamsQuery, + GetLiveStreamsQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useLazyQuery( + GetLiveStreamsDocument, + options, + ); +} +export function useGetLiveStreamsSuspenseQuery( + baseOptions?: Apollo.SuspenseQueryHookOptions< + GetLiveStreamsQuery, + GetLiveStreamsQueryVariables + >, +) { + const options = { ...defaultOptions, ...baseOptions }; + return Apollo.useSuspenseQuery< + GetLiveStreamsQuery, + GetLiveStreamsQueryVariables + >(GetLiveStreamsDocument, options); +} +export type GetLiveStreamsQueryHookResult = ReturnType< + typeof useGetLiveStreamsQuery +>; +export type GetLiveStreamsLazyQueryHookResult = ReturnType< + typeof useGetLiveStreamsLazyQuery +>; +export type GetLiveStreamsSuspenseQueryHookResult = ReturnType< + typeof useGetLiveStreamsSuspenseQuery +>; +export type GetLiveStreamsQueryResult = Apollo.QueryResult< + GetLiveStreamsQuery, + GetLiveStreamsQueryVariables +>; export const GetVideoMakePercentageIntervalsDocument = gql` query GetVideoMakePercentageIntervals( $videoId: ID! @@ -14683,13 +14828,13 @@ export type ReactToVideoMutationOptions = Apollo.BaseMutationOptions< ReactToVideoMutation, ReactToVideoMutationVariables >; -export const GetShotLabVideosDocument = gql` - query GetShotLabVideos($userId: Int!, $limit: Int! = 25) { +export const GetRecordedStreamsDocument = gql` + query GetRecordedStreams($limit: Int! = 25) { getFeedVideos( limit: $limit - includeCallersVideos: false + filters: { isStreamCompleted: true, excludeVideosWithNoShots: true } includePrivate: MINE - feedInput: { userId: $userId } + feedInput: { allUsers: true } ) { videos { id @@ -14703,81 +14848,75 @@ export const GetShotLabVideosDocument = gql` username profileImageUri } - stream { - id - isCompleted - lastSegmentUploadedAt - } } } } `; /** - * __useGetShotLabVideosQuery__ + * __useGetRecordedStreamsQuery__ * - * To run a query within a React component, call `useGetShotLabVideosQuery` and pass it any options that fit your needs. - * When your component renders, `useGetShotLabVideosQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useGetRecordedStreamsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetRecordedStreamsQuery` returns an object from Apollo Client that contains loading, error, and data properties * you can use to render your UI. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useGetShotLabVideosQuery({ + * const { data, loading, error } = useGetRecordedStreamsQuery({ * variables: { - * userId: // value for 'userId' * limit: // value for 'limit' * }, * }); */ -export function useGetShotLabVideosQuery( - baseOptions: Apollo.QueryHookOptions< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables +export function useGetRecordedStreamsQuery( + baseOptions?: Apollo.QueryHookOptions< + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables >, ) { const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery( - GetShotLabVideosDocument, - options, - ); + return Apollo.useQuery< + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables + >(GetRecordedStreamsDocument, options); } -export function useGetShotLabVideosLazyQuery( +export function useGetRecordedStreamsLazyQuery( baseOptions?: Apollo.LazyQueryHookOptions< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables >, ) { const options = { ...defaultOptions, ...baseOptions }; return Apollo.useLazyQuery< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables - >(GetShotLabVideosDocument, options); + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables + >(GetRecordedStreamsDocument, options); } -export function useGetShotLabVideosSuspenseQuery( +export function useGetRecordedStreamsSuspenseQuery( baseOptions?: Apollo.SuspenseQueryHookOptions< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables >, ) { const options = { ...defaultOptions, ...baseOptions }; return Apollo.useSuspenseQuery< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables - >(GetShotLabVideosDocument, options); + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables + >(GetRecordedStreamsDocument, options); } -export type GetShotLabVideosQueryHookResult = ReturnType< - typeof useGetShotLabVideosQuery +export type GetRecordedStreamsQueryHookResult = ReturnType< + typeof useGetRecordedStreamsQuery >; -export type GetShotLabVideosLazyQueryHookResult = ReturnType< - typeof useGetShotLabVideosLazyQuery +export type GetRecordedStreamsLazyQueryHookResult = ReturnType< + typeof useGetRecordedStreamsLazyQuery >; -export type GetShotLabVideosSuspenseQueryHookResult = ReturnType< - typeof useGetShotLabVideosSuspenseQuery +export type GetRecordedStreamsSuspenseQueryHookResult = ReturnType< + typeof useGetRecordedStreamsSuspenseQuery >; -export type GetShotLabVideosQueryResult = Apollo.QueryResult< - GetShotLabVideosQuery, - GetShotLabVideosQueryVariables +export type GetRecordedStreamsQueryResult = Apollo.QueryResult< + GetRecordedStreamsQuery, + GetRecordedStreamsQueryVariables >; export const GetRecordedStreamShotsDocument = gql` query GetRecordedStreamShots($videoId: Int!, $limit: Int! = 200) { @@ -14794,11 +14933,26 @@ export const GetRecordedStreamShotsDocument = gql` serializedShotPaths { b64EncodedBuffer } + cueObjectFeatures { + cueObjectDistance + cueObjectAngle + cueBallSpeed + shotDirection + spinType + } pocketingIntentionFeatures { make + targetPocketDistance + targetPocketAngle + targetPocketAngleDirection + marginOfErrorInDegrees + intendedPocketType + difficulty } pocketingIntentionInfo { + ballId pocketId + pathMetadataIndex } } } diff --git a/src/operations/live_streams.gql b/src/operations/live_streams.gql new file mode 100644 index 0000000..45e4167 --- /dev/null +++ b/src/operations/live_streams.gql @@ -0,0 +1,34 @@ +# Lightweight listing of live (in-progress) streams for pickers like the +# Shot Lab "follow a live stream" flow. Selects only what a picker card +# needs; intentionally avoids the heavy VideoCardFields fragment. +query GetLiveStreams($limit: Int! = 25) { + getFeedVideos( + limit: $limit + filters: { isStreamCompleted: false, requireCursorCompletion: false } + includePrivate: MINE + feedInput: { allUsers: true } + ) { + videos { + id + name + startTime + createdAt + screenshotUri + elapsedTime + owner { + id + username + profileImageUri + } + stream { + id + isCompleted + lastSegmentUploadedAt + } + } + pageInfo { + hasNextPage + endCursor + } + } +} diff --git a/src/operations/recorded_shots.gql b/src/operations/recorded_shots.gql index c302b3c..2ae77bf 100644 --- a/src/operations/recorded_shots.gql +++ b/src/operations/recorded_shots.gql @@ -1,12 +1,10 @@ -# Lightweight two-step picker data for Shot Lab's video-first source: the -# caller's recent videos (completed or still uploading), then that video's -# shots. The stream fields hint at "actively updating" without gating. -query GetShotLabVideos($userId: Int!, $limit: Int! = 25) { +# Lightweight two-step picker data for loading a recorded shot into Shot Lab. +query GetRecordedStreams($limit: Int! = 25) { getFeedVideos( limit: $limit - includeCallersVideos: false + filters: { isStreamCompleted: true, excludeVideosWithNoShots: true } includePrivate: MINE - feedInput: { userId: $userId } + feedInput: { allUsers: true } ) { videos { id @@ -20,11 +18,6 @@ query GetShotLabVideos($userId: Int!, $limit: Int! = 25) { username profileImageUri } - stream { - id - isCompleted - lastSegmentUploadedAt - } } } } @@ -43,11 +36,26 @@ query GetRecordedStreamShots($videoId: Int!, $limit: Int! = 200) { serializedShotPaths { b64EncodedBuffer } + cueObjectFeatures { + cueObjectDistance + cueObjectAngle + cueBallSpeed + shotDirection + spinType + } pocketingIntentionFeatures { make + targetPocketDistance + targetPocketAngle + targetPocketAngleDirection + marginOfErrorInDegrees + intendedPocketType + difficulty } pocketingIntentionInfo { + ballId pocketId + pathMetadataIndex } } }