Compare commits

..

1 Commits

Author SHA1 Message Date
Dean Wenstrand
eb5217e070 Add DrillResultGQL + drillResult on VideoCardFields
Session card drill outcome: longest run + owner's personal-best rank
(1/2/3 medal) among their sessions on the same drill + table/pocket setup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:48:21 -07:00
6 changed files with 1791 additions and 2048 deletions

View File

@@ -393,6 +393,16 @@ export type DoesNotOwnShotErrOtherErrorNeedsNote =
| DoesNotOwnShotErr | DoesNotOwnShotErr
| OtherErrorNeedsNote; | OtherErrorNeedsNote;
export type DrillResultGql = {
__typename?: "DrillResultGQL";
attemptCount: Scalars["Int"]["output"];
drillTag: Scalars["String"]["output"];
isPersonalBest: Scalars["Boolean"]["output"];
longestRun: Scalars["Int"]["output"];
longestRunId?: Maybe<Scalars["Int"]["output"]>;
prRank: Scalars["Int"]["output"];
};
export type DrillRunLeaderboardGql = { export type DrillRunLeaderboardGql = {
__typename?: "DrillRunLeaderboardGQL"; __typename?: "DrillRunLeaderboardGQL";
entries: Array<RunGql>; entries: Array<RunGql>;
@@ -2404,11 +2414,6 @@ export type Header = {
value: Scalars["String"]["output"]; value: Scalars["String"]["output"];
}; };
export enum HomographyBackendGql {
Classic = "CLASSIC",
Tablenet = "TABLENET",
}
export type HomographyInfoGql = { export type HomographyInfoGql = {
__typename?: "HomographyInfoGQL"; __typename?: "HomographyInfoGQL";
crop: BoundingBoxGql; crop: BoundingBoxGql;
@@ -3093,7 +3098,6 @@ export type Query = {
getQuotaStatus: QuotaStatusGql; getQuotaStatus: QuotaStatusGql;
getResolvedTier: ResolvedTierGql; getResolvedTier: ResolvedTierGql;
getRuns: GetRunsResult; getRuns: GetRunsResult;
getSessionCoach: SessionCoachGql;
getShotAnnotationTypes: Array<ShotAnnotationTypeGql>; getShotAnnotationTypes: Array<ShotAnnotationTypeGql>;
getShotTableState: ShotTableStateGql; getShotTableState: ShotTableStateGql;
getShots: Array<ShotGql>; getShots: Array<ShotGql>;
@@ -3195,28 +3199,14 @@ export type QueryGetLiveTableStateArgs = {
}; };
export type QueryGetLongestRunsLeaderboardArgs = { export type QueryGetLongestRunsLeaderboardArgs = {
excludeDrills?: Scalars["Boolean"]["input"];
gameType?: InputMaybe<Scalars["String"]["input"]>;
interval?: InputMaybe<TimeInterval>; interval?: InputMaybe<TimeInterval>;
limit?: Scalars["Int"]["input"]; limit?: Scalars["Int"]["input"];
pocketSizeMax?: InputMaybe<Scalars["Float"]["input"]>;
pocketSizeMin?: InputMaybe<Scalars["Float"]["input"]>;
rankedOnly?: Scalars["Boolean"]["input"];
requiredTags?: InputMaybe<Array<Scalars["String"]["input"]>>; requiredTags?: InputMaybe<Array<Scalars["String"]["input"]>>;
tableSizeMax?: InputMaybe<Scalars["Float"]["input"]>;
tableSizeMin?: InputMaybe<Scalars["Float"]["input"]>;
when?: InputMaybe<Scalars["DateTime"]["input"]>; when?: InputMaybe<Scalars["DateTime"]["input"]>;
}; };
export type QueryGetMakesLeaderboardArgs = { export type QueryGetMakesLeaderboardArgs = {
excludeDrills?: Scalars["Boolean"]["input"];
gameType?: InputMaybe<Scalars["String"]["input"]>;
interval?: InputMaybe<TimeInterval>; interval?: InputMaybe<TimeInterval>;
pocketSizeMax?: InputMaybe<Scalars["Float"]["input"]>;
pocketSizeMin?: InputMaybe<Scalars["Float"]["input"]>;
rankedOnly?: Scalars["Boolean"]["input"];
tableSizeMax?: InputMaybe<Scalars["Float"]["input"]>;
tableSizeMin?: InputMaybe<Scalars["Float"]["input"]>;
when?: InputMaybe<Scalars["DateTime"]["input"]>; when?: InputMaybe<Scalars["DateTime"]["input"]>;
}; };
@@ -3251,10 +3241,6 @@ export type QueryGetRunsArgs = {
runsOrdering?: InputMaybe<GetRunsOrdering>; runsOrdering?: InputMaybe<GetRunsOrdering>;
}; };
export type QueryGetSessionCoachArgs = {
videoId: Scalars["Int"]["input"];
};
export type QueryGetShotAnnotationTypesArgs = { export type QueryGetShotAnnotationTypesArgs = {
errorTypes?: InputMaybe<Scalars["Boolean"]["input"]>; errorTypes?: InputMaybe<Scalars["Boolean"]["input"]>;
}; };
@@ -3570,84 +3556,6 @@ export type SerializedShotPathsGql = {
b64EncodedBuffer?: Maybe<Scalars["String"]["output"]>; b64EncodedBuffer?: Maybe<Scalars["String"]["output"]>;
}; };
export enum SessionCoachCandidateFamilyEnum {
Aiming = "AIMING",
BackCut = "BACK_CUT",
CueToObjectDistance = "CUE_TO_OBJECT_DISTANCE",
CutAngle = "CUT_ANGLE",
ObjectToPocketDistance = "OBJECT_TO_POCKET_DISTANCE",
Spin = "SPIN",
}
export type SessionCoachCandidateGql = {
__typename?: "SessionCoachCandidateGQL";
action: Scalars["String"]["output"];
body: Scalars["String"]["output"];
drillId?: Maybe<Scalars["String"]["output"]>;
evidence: SessionCoachEvidenceGql;
family: SessionCoachCandidateFamilyEnum;
id: Scalars["ID"]["output"];
kind: SessionCoachCandidateKindEnum;
limitations: Array<Scalars["String"]["output"]>;
rank: Scalars["Int"]["output"];
supportingShotIds: Array<Scalars["Int"]["output"]>;
title: Scalars["String"]["output"];
};
export enum SessionCoachCandidateKindEnum {
DirectionalMiss = "DIRECTIONAL_MISS",
OutcomePattern = "OUTCOME_PATTERN",
UsagePattern = "USAGE_PATTERN",
}
export type SessionCoachEvidenceGql = {
__typename?: "SessionCoachEvidenceGQL";
attemptCount: Scalars["Int"]["output"];
bucketKey: Scalars["String"]["output"];
bucketLabel: Scalars["String"]["output"];
comparisonAttemptCount: Scalars["Int"]["output"];
comparisonMadeCount: Scalars["Int"]["output"];
comparisonMakePercentage?: Maybe<Scalars["Float"]["output"]>;
madeCount: Scalars["Int"]["output"];
makePercentage: Scalars["Float"]["output"];
missedCount: Scalars["Int"]["output"];
patternShotCount: Scalars["Int"]["output"];
rankReason: Scalars["String"]["output"];
score: Scalars["Float"]["output"];
};
export type SessionCoachGql = {
__typename?: "SessionCoachGQL";
analysisVersion: Scalars["String"]["output"];
analyzedShotCount: Scalars["Int"]["output"];
candidates: Array<SessionCoachCandidateGql>;
generatedAt: Scalars["DateTime"]["output"];
ineligibilityReason?: Maybe<SessionCoachIneligibilityReasonEnum>;
madeCount: Scalars["Int"]["output"];
makePercentage?: Maybe<Scalars["Float"]["output"]>;
missedCount: Scalars["Int"]["output"];
primaryCandidate?: Maybe<SessionCoachCandidateGql>;
processingId?: Maybe<Scalars["Int"]["output"]>;
processingStatus?: Maybe<Scalars["String"]["output"]>;
shotCount: Scalars["Int"]["output"];
state: SessionCoachStateEnum;
summary?: Maybe<Scalars["String"]["output"]>;
unknownOutcomeCount: Scalars["Int"]["output"];
videoId: Scalars["Int"]["output"];
};
export enum SessionCoachIneligibilityReasonEnum {
Multiplayer = "MULTIPLAYER",
}
export enum SessionCoachStateEnum {
Failed = "FAILED",
Ineligible = "INELIGIBLE",
NoTrackedShots = "NO_TRACKED_SHOTS",
Processing = "PROCESSING",
Ready = "READY",
}
export type ShotAnnotationGql = { export type ShotAnnotationGql = {
__typename?: "ShotAnnotationGQL"; __typename?: "ShotAnnotationGQL";
createdAt?: Maybe<Scalars["DateTime"]["output"]>; createdAt?: Maybe<Scalars["DateTime"]["output"]>;
@@ -4257,6 +4165,7 @@ export type VideoGql = {
createdAt?: Maybe<Scalars["DateTime"]["output"]>; createdAt?: Maybe<Scalars["DateTime"]["output"]>;
currentHomography?: Maybe<HomographyInfoGql>; currentHomography?: Maybe<HomographyInfoGql>;
currentProcessing?: Maybe<VideoProcessingGql>; currentProcessing?: Maybe<VideoProcessingGql>;
drillResult?: Maybe<DrillResultGql>;
elapsedTime?: Maybe<Scalars["Float"]["output"]>; elapsedTime?: Maybe<Scalars["Float"]["output"]>;
endTime?: Maybe<Scalars["DateTime"]["output"]>; endTime?: Maybe<Scalars["DateTime"]["output"]>;
framesPerSecond: Scalars["Float"]["output"]; framesPerSecond: Scalars["Float"]["output"];
@@ -4297,7 +4206,6 @@ export type VideoMetadataInput = {
framesPerSecond?: InputMaybe<Scalars["Float"]["input"]>; framesPerSecond?: InputMaybe<Scalars["Float"]["input"]>;
/** @deprecated `game_type` is deprecated. Use `tags` instead. */ /** @deprecated `game_type` is deprecated. Use `tags` instead. */
gameType?: InputMaybe<Scalars["String"]["input"]>; gameType?: InputMaybe<Scalars["String"]["input"]>;
homographyBackend?: InputMaybe<HomographyBackendGql>;
lastIntendedSegmentBound?: InputMaybe<Scalars["Int"]["input"]>; lastIntendedSegmentBound?: InputMaybe<Scalars["Int"]["input"]>;
pocketSize?: InputMaybe<Scalars["Float"]["input"]>; pocketSize?: InputMaybe<Scalars["Float"]["input"]>;
private?: InputMaybe<Scalars["Boolean"]["input"]>; private?: InputMaybe<Scalars["Boolean"]["input"]>;
@@ -4898,6 +4806,15 @@ export type GetFeedQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
drillResult?: {
__typename?: "DrillResultGQL";
drillTag: string;
longestRun: number;
longestRunId?: number | null;
prRank: number;
isPersonalBest: boolean;
attemptCount: number;
} | null;
playerSummaries: Array<{ playerSummaries: Array<{
__typename?: "PlayerSummaryGQL"; __typename?: "PlayerSummaryGQL";
clusterId: number; clusterId: number;
@@ -5013,6 +4930,15 @@ export type VideoCardFieldsFragment = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
drillResult?: {
__typename?: "DrillResultGQL";
drillTag: string;
longestRun: number;
longestRunId?: number | null;
prRank: number;
isPersonalBest: boolean;
attemptCount: number;
} | null;
playerSummaries: Array<{ playerSummaries: Array<{
__typename?: "PlayerSummaryGQL"; __typename?: "PlayerSummaryGQL";
clusterId: number; clusterId: number;
@@ -5161,6 +5087,15 @@ export type GetVideoFeedQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
drillResult?: {
__typename?: "DrillResultGQL";
drillTag: string;
longestRun: number;
longestRunId?: number | null;
prRank: number;
isPersonalBest: boolean;
attemptCount: number;
} | null;
playerSummaries: Array<{ playerSummaries: Array<{
__typename?: "PlayerSummaryGQL"; __typename?: "PlayerSummaryGQL";
clusterId: number; clusterId: number;
@@ -5344,6 +5279,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<{ export type GetVideoMakePercentageIntervalsQueryVariables = Exact<{
videoId: Scalars["ID"]["input"]; videoId: Scalars["ID"]["input"];
intervalDuration: Scalars["Int"]["input"]; intervalDuration: Scalars["Int"]["input"];
@@ -6685,11 +6657,11 @@ export type ReactToVideoMutation = {
reactToVideo: boolean; reactToVideo: boolean;
}; };
export type GetShotLabVideosQueryVariables = Exact<{ export type GetRecordedStreamsQueryVariables = Exact<{
limit?: Scalars["Int"]["input"]; limit?: Scalars["Int"]["input"];
}>; }>;
export type GetShotLabVideosQuery = { export type GetRecordedStreamsQuery = {
__typename?: "Query"; __typename?: "Query";
getFeedVideos: { getFeedVideos: {
__typename?: "VideoHistoryGQL"; __typename?: "VideoHistoryGQL";
@@ -6707,12 +6679,6 @@ export type GetShotLabVideosQuery = {
username: string; username: string;
profileImageUri?: string | null; profileImageUri?: string | null;
} | null; } | null;
stream?: {
__typename?: "UploadStreamGQL";
id: string;
isCompleted: boolean;
lastSegmentUploadedAt?: any | null;
} | null;
}>; }>;
}; };
}; };
@@ -6838,116 +6804,6 @@ export type GetRunsWithTimestampsQuery = {
}; };
}; };
export type GetSessionCoachQueryVariables = Exact<{
videoId: Scalars["Int"]["input"];
}>;
export type GetSessionCoachQuery = {
__typename?: "Query";
getSessionCoach: {
__typename?: "SessionCoachGQL";
videoId: number;
processingId?: number | null;
analysisVersion: string;
state: SessionCoachStateEnum;
generatedAt: any;
processingStatus?: string | null;
ineligibilityReason?: SessionCoachIneligibilityReasonEnum | null;
summary?: string | null;
shotCount: number;
madeCount: number;
missedCount: number;
unknownOutcomeCount: number;
analyzedShotCount: number;
makePercentage?: number | null;
primaryCandidate?: {
__typename?: "SessionCoachCandidateGQL";
id: string;
rank: number;
family: SessionCoachCandidateFamilyEnum;
kind: SessionCoachCandidateKindEnum;
title: string;
body: string;
action: string;
supportingShotIds: Array<number>;
drillId?: string | null;
limitations: Array<string>;
evidence: {
__typename?: "SessionCoachEvidenceGQL";
bucketKey: string;
bucketLabel: string;
attemptCount: number;
madeCount: number;
missedCount: number;
makePercentage: number;
comparisonAttemptCount: number;
comparisonMadeCount: number;
comparisonMakePercentage?: number | null;
patternShotCount: number;
score: number;
rankReason: string;
};
} | null;
candidates: Array<{
__typename?: "SessionCoachCandidateGQL";
id: string;
rank: number;
family: SessionCoachCandidateFamilyEnum;
kind: SessionCoachCandidateKindEnum;
title: string;
body: string;
action: string;
supportingShotIds: Array<number>;
drillId?: string | null;
limitations: Array<string>;
evidence: {
__typename?: "SessionCoachEvidenceGQL";
bucketKey: string;
bucketLabel: string;
attemptCount: number;
madeCount: number;
missedCount: number;
makePercentage: number;
comparisonAttemptCount: number;
comparisonMadeCount: number;
comparisonMakePercentage?: number | null;
patternShotCount: number;
score: number;
rankReason: string;
};
}>;
};
};
export type SessionCoachCandidateFieldsFragment = {
__typename?: "SessionCoachCandidateGQL";
id: string;
rank: number;
family: SessionCoachCandidateFamilyEnum;
kind: SessionCoachCandidateKindEnum;
title: string;
body: string;
action: string;
supportingShotIds: Array<number>;
drillId?: string | null;
limitations: Array<string>;
evidence: {
__typename?: "SessionCoachEvidenceGQL";
bucketKey: string;
bucketLabel: string;
attemptCount: number;
madeCount: number;
missedCount: number;
makePercentage: number;
comparisonAttemptCount: number;
comparisonMadeCount: number;
comparisonMakePercentage?: number | null;
patternShotCount: number;
score: number;
rankReason: string;
};
};
export type PlayerSummaryFieldsFragment = { export type PlayerSummaryFieldsFragment = {
__typename?: "PlayerSummaryGQL"; __typename?: "PlayerSummaryGQL";
clusterId: number; clusterId: number;
@@ -8389,6 +8245,15 @@ export type GetVideoCardQuery = {
name: string; name: string;
tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>; tagClasses: Array<{ __typename?: "VideoTagClass"; name: string }>;
}>; }>;
drillResult?: {
__typename?: "DrillResultGQL";
drillTag: string;
longestRun: number;
longestRunId?: number | null;
prRank: number;
isPersonalBest: boolean;
attemptCount: number;
} | null;
playerSummaries: Array<{ playerSummaries: Array<{
__typename?: "PlayerSummaryGQL"; __typename?: "PlayerSummaryGQL";
clusterId: number; clusterId: number;
@@ -9220,6 +9085,14 @@ export const VideoCardFieldsFragmentDoc = gql`
name name
} }
} }
drillResult {
drillTag
longestRun
longestRunId
prRank
isPersonalBest
attemptCount
}
playerSummaries { playerSummaries {
...PlayerSummaryFields ...PlayerSummaryFields
} }
@@ -9394,34 +9267,6 @@ export const PocketingIntentionFragmentFragmentDoc = gql`
difficulty difficulty
} }
`; `;
export const SessionCoachCandidateFieldsFragmentDoc = gql`
fragment SessionCoachCandidateFields on SessionCoachCandidateGQL {
id
rank
family
kind
title
body
action
supportingShotIds
drillId
limitations
evidence {
bucketKey
bucketLabel
attemptCount
madeCount
missedCount
makePercentage
comparisonAttemptCount
comparisonMadeCount
comparisonMakePercentage
patternShotCount
score
rankReason
}
}
`;
export const PlayerClusterShotFieldsFragmentDoc = gql` export const PlayerClusterShotFieldsFragmentDoc = gql`
fragment PlayerClusterShotFields on PlayerClusterShotGQL { fragment PlayerClusterShotFields on PlayerClusterShotGQL {
shotId shotId
@@ -12117,6 +11962,105 @@ export type GetMyDrillRunsQueryResult = Apollo.QueryResult<
GetMyDrillRunsQuery, GetMyDrillRunsQuery,
GetMyDrillRunsQueryVariables 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<GetLiveStreamsQuery, GetLiveStreamsQueryVariables>(
GetLiveStreamsDocument,
options,
);
}
export function useGetLiveStreamsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
GetLiveStreamsQuery,
GetLiveStreamsQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<GetLiveStreamsQuery, GetLiveStreamsQueryVariables>(
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` export const GetVideoMakePercentageIntervalsDocument = gql`
query GetVideoMakePercentageIntervals( query GetVideoMakePercentageIntervals(
$videoId: ID! $videoId: ID!
@@ -14415,10 +14359,11 @@ export type ReactToVideoMutationOptions = Apollo.BaseMutationOptions<
ReactToVideoMutation, ReactToVideoMutation,
ReactToVideoMutationVariables ReactToVideoMutationVariables
>; >;
export const GetShotLabVideosDocument = gql` export const GetRecordedStreamsDocument = gql`
query GetShotLabVideos($limit: Int! = 25) { query GetRecordedStreams($limit: Int! = 25) {
getFeedVideos( getFeedVideos(
limit: $limit limit: $limit
filters: { isStreamCompleted: true, excludeVideosWithNoShots: true }
includePrivate: MINE includePrivate: MINE
feedInput: { allUsers: true } feedInput: { allUsers: true }
) { ) {
@@ -14434,80 +14379,75 @@ export const GetShotLabVideosDocument = gql`
username username
profileImageUri 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. * To run a query within a React component, call `useGetRecordedStreamsQuery` 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 * 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. * 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; * @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 * @example
* const { data, loading, error } = useGetShotLabVideosQuery({ * const { data, loading, error } = useGetRecordedStreamsQuery({
* variables: { * variables: {
* limit: // value for 'limit' * limit: // value for 'limit'
* }, * },
* }); * });
*/ */
export function useGetShotLabVideosQuery( export function useGetRecordedStreamsQuery(
baseOptions?: Apollo.QueryHookOptions< baseOptions?: Apollo.QueryHookOptions<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>, >,
) { ) {
const options = { ...defaultOptions, ...baseOptions }; const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetShotLabVideosQuery, GetShotLabVideosQueryVariables>( return Apollo.useQuery<
GetShotLabVideosDocument, GetRecordedStreamsQuery,
options, GetRecordedStreamsQueryVariables
); >(GetRecordedStreamsDocument, options);
} }
export function useGetShotLabVideosLazyQuery( export function useGetRecordedStreamsLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions< baseOptions?: Apollo.LazyQueryHookOptions<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>, >,
) { ) {
const options = { ...defaultOptions, ...baseOptions }; const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery< return Apollo.useLazyQuery<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>(GetShotLabVideosDocument, options); >(GetRecordedStreamsDocument, options);
} }
export function useGetShotLabVideosSuspenseQuery( export function useGetRecordedStreamsSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions< baseOptions?: Apollo.SuspenseQueryHookOptions<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>, >,
) { ) {
const options = { ...defaultOptions, ...baseOptions }; const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery< return Apollo.useSuspenseQuery<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>(GetShotLabVideosDocument, options); >(GetRecordedStreamsDocument, options);
} }
export type GetShotLabVideosQueryHookResult = ReturnType< export type GetRecordedStreamsQueryHookResult = ReturnType<
typeof useGetShotLabVideosQuery typeof useGetRecordedStreamsQuery
>; >;
export type GetShotLabVideosLazyQueryHookResult = ReturnType< export type GetRecordedStreamsLazyQueryHookResult = ReturnType<
typeof useGetShotLabVideosLazyQuery typeof useGetRecordedStreamsLazyQuery
>; >;
export type GetShotLabVideosSuspenseQueryHookResult = ReturnType< export type GetRecordedStreamsSuspenseQueryHookResult = ReturnType<
typeof useGetShotLabVideosSuspenseQuery typeof useGetRecordedStreamsSuspenseQuery
>; >;
export type GetShotLabVideosQueryResult = Apollo.QueryResult< export type GetRecordedStreamsQueryResult = Apollo.QueryResult<
GetShotLabVideosQuery, GetRecordedStreamsQuery,
GetShotLabVideosQueryVariables GetRecordedStreamsQueryVariables
>; >;
export const GetRecordedStreamShotsDocument = gql` export const GetRecordedStreamShotsDocument = gql`
query GetRecordedStreamShots($videoId: Int!, $limit: Int! = 200) { query GetRecordedStreamShots($videoId: Int!, $limit: Int! = 200) {
@@ -14815,99 +14755,6 @@ export type GetRunsWithTimestampsQueryResult = Apollo.QueryResult<
GetRunsWithTimestampsQuery, GetRunsWithTimestampsQuery,
GetRunsWithTimestampsQueryVariables GetRunsWithTimestampsQueryVariables
>; >;
export const GetSessionCoachDocument = gql`
query GetSessionCoach($videoId: Int!) {
getSessionCoach(videoId: $videoId) {
videoId
processingId
analysisVersion
state
generatedAt
processingStatus
ineligibilityReason
summary
shotCount
madeCount
missedCount
unknownOutcomeCount
analyzedShotCount
makePercentage
primaryCandidate {
...SessionCoachCandidateFields
}
candidates {
...SessionCoachCandidateFields
}
}
}
${SessionCoachCandidateFieldsFragmentDoc}
`;
/**
* __useGetSessionCoachQuery__
*
* To run a query within a React component, call `useGetSessionCoachQuery` and pass it any options that fit your needs.
* When your component renders, `useGetSessionCoachQuery` 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 } = useGetSessionCoachQuery({
* variables: {
* videoId: // value for 'videoId'
* },
* });
*/
export function useGetSessionCoachQuery(
baseOptions: Apollo.QueryHookOptions<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetSessionCoachQuery, GetSessionCoachQueryVariables>(
GetSessionCoachDocument,
options,
);
}
export function useGetSessionCoachLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>(GetSessionCoachDocument, options);
}
export function useGetSessionCoachSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>(GetSessionCoachDocument, options);
}
export type GetSessionCoachQueryHookResult = ReturnType<
typeof useGetSessionCoachQuery
>;
export type GetSessionCoachLazyQueryHookResult = ReturnType<
typeof useGetSessionCoachLazyQuery
>;
export type GetSessionCoachSuspenseQueryHookResult = ReturnType<
typeof useGetSessionCoachSuspenseQuery
>;
export type GetSessionCoachQueryResult = Apollo.QueryResult<
GetSessionCoachQuery,
GetSessionCoachQueryVariables
>;
export const VideoPlayerClustersDocument = gql` export const VideoPlayerClustersDocument = gql`
query VideoPlayerClusters($videoId: Int!) { query VideoPlayerClusters($videoId: Int!) {
videoPlayerClusters(videoId: $videoId) { videoPlayerClusters(videoId: $videoId) {

View File

@@ -55,6 +55,14 @@ fragment VideoCardFields on VideoGQL {
name name
} }
} }
drillResult {
drillTag
longestRun
longestRunId
prRank
isPersonalBest
attemptCount
}
playerSummaries { playerSummaries {
...PlayerSummaryFields ...PlayerSummaryFields
} }

View File

@@ -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
}
}
}

View File

@@ -1,10 +1,8 @@
# Lightweight two-step picker data for Shot Lab's video-first source: recent # Lightweight two-step picker data for loading a recorded shot into Shot Lab.
# videos (completed or still uploading — no completion gate, so an in-progress query GetRecordedStreams($limit: Int! = 25) {
# recording with no shots yet still appears), then that video's shots. The
# stream fields let the client hint at "actively updating" without gating.
query GetShotLabVideos($limit: Int! = 25) {
getFeedVideos( getFeedVideos(
limit: $limit limit: $limit
filters: { isStreamCompleted: true, excludeVideosWithNoShots: true }
includePrivate: MINE includePrivate: MINE
feedInput: { allUsers: true } feedInput: { allUsers: true }
) { ) {
@@ -20,11 +18,6 @@ query GetShotLabVideos($limit: Int! = 25) {
username username
profileImageUri profileImageUri
} }
stream {
id
isCompleted
lastSegmentUploadedAt
}
} }
} }
} }

View File

@@ -1,51 +0,0 @@
query GetSessionCoach($videoId: Int!) {
getSessionCoach(videoId: $videoId) {
videoId
processingId
analysisVersion
state
generatedAt
processingStatus
ineligibilityReason
summary
shotCount
madeCount
missedCount
unknownOutcomeCount
analyzedShotCount
makePercentage
primaryCandidate {
...SessionCoachCandidateFields
}
candidates {
...SessionCoachCandidateFields
}
}
}
fragment SessionCoachCandidateFields on SessionCoachCandidateGQL {
id
rank
family
kind
title
body
action
supportingShotIds
drillId
limitations
evidence {
bucketKey
bucketLabel
attemptCount
madeCount
missedCount
makePercentage
comparisonAttemptCount
comparisonMadeCount
comparisonMakePercentage
patternShotCount
score
rankReason
}
}

File diff suppressed because it is too large Load Diff