Compare commits

...

9 Commits

Author SHA1 Message Date
adf05e3c28 Add computePotAim query and shot-simulation operations
All checks were successful
Tests / Tests (pull_request) Successful in 10s
Schema: computePotAim(simulationInput, targetBallId, pocket) ->
PotAimGQL, the spin/throw-compensated aim solver (regenerated from
backend strawberry definitions; reuses the existing PocketIdentifier
enum). Operations: GetTableState, SimulateShot, and ComputePotAim
documents so both clients get generated hooks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 01:44:02 -07:00
5391466e90 Merge pull request 'Add simulateShot query, cue strike and shot projection types' (#277) from shot-simulation-stubs into master
Reviewed-on: #277
2026-07-02 23:35:30 +00:00
4ff2db1ef4 Add simulateShot query, cue strike and shot projection types
All checks were successful
Tests / Tests (pull_request) Successful in 12s
Generated from backend strawberry definitions for the shot simulation
feature (image -> pooltool scenario -> projected outcome). Backend PR:
shot-simulation-stubs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 16:12:11 -07:00
257dcdc31a Merge pull request 'Add DismissVideoExport mutation (soft-hide exports)' (#276) from dean/export-dismiss-gql into master
Reviewed-on: #276
2026-07-02 22:38:02 +00:00
Dean Wenstrand
b41365e99e Add videoName + videoThumbnailUri to VideoExportJobFields
All checks were successful
Tests / Tests (pull_request) Successful in 13s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 14:41:59 -07:00
Dean Wenstrand
0e8233a5d5 Add DismissVideoExport mutation (soft-hide exports)
All checks were successful
Tests / Tests (pull_request) Successful in 17s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 14:18:55 -07:00
b6adae4949 Merge pull request 'Storage limit enforcement schema' (#275) from storage-limit-enforcement-schema into master
Reviewed-on: #275
2026-07-01 22:29:41 +00:00
459e89d8b8 Select storage limit error fields
All checks were successful
Tests / Tests (pull_request) Successful in 11s
2026-07-01 14:50:45 -07:00
fa2ff19572 Add storage limit enforcement schema 2026-07-01 14:41:21 -07:00
5 changed files with 683 additions and 4 deletions

View File

@@ -88,6 +88,12 @@ export type AppleIapSubscriptionOptionsGql = {
productIds: Array<Scalars["String"]["output"]>;
};
export type BallTrajectoryGql = {
__typename?: "BallTrajectoryGQL";
ballId: Scalars["Int"]["output"];
points: Array<TrajectoryPointGql>;
};
export type BankFeaturesGql = {
__typename?: "BankFeaturesGQL";
bankAngle: Scalars["Float"]["output"];
@@ -268,6 +274,14 @@ export type CueObjectFeaturesGql = {
spinType?: Maybe<SpinTypeEnum>;
};
export type CueStrikeInputGql = {
a?: Scalars["Float"]["input"];
b?: Scalars["Float"]["input"];
phi: Scalars["Float"]["input"];
theta?: Scalars["Float"]["input"];
v0: Scalars["Float"]["input"];
};
export type DateRangeFilter = {
greaterThan?: InputMaybe<Scalars["Date"]["input"]>;
greaterThanEqualTo?: InputMaybe<Scalars["Date"]["input"]>;
@@ -300,6 +314,7 @@ export type DeployedConfigGql = {
firebase: Scalars["Boolean"]["output"];
minimumAllowedAppVersion: Scalars["String"]["output"];
quotaEnforcementEnabled: Scalars["Boolean"]["output"];
storageLimitEnforcementEnabled: Scalars["Boolean"]["output"];
subscriptionGatingEnabled: Scalars["Boolean"]["output"];
};
@@ -2287,7 +2302,7 @@ export type GetShotsResult = {
export type GetUploadLinkErrors = {
__typename?: "GetUploadLinkErrors";
error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr;
error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr;
};
export type GetUploadLinkReturn = {
@@ -2391,13 +2406,14 @@ export type MustHaveSetForUploadLinkErr = {
resolution?: Maybe<Scalars["Boolean"]["output"]>;
};
export type MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr =
export type MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr =
| InitUploadAlreadyCompletedErr
| MustHaveSetForUploadLinkErr
| NoInitForChunkedUploadErr
| ProcessingFailedErr
| SegmentAlreadyUploadedErr
| StorageLimitExceededErr
| TooManyInitUploadsErr
| TooManyProfileImageUploadsErr;
@@ -2420,6 +2436,7 @@ export type Mutation = {
deleteUser: Scalars["Boolean"]["output"];
deleteVideo: Scalars["Boolean"]["output"];
dismissChallenge: Scalars["Boolean"]["output"];
dismissVideoExport: Scalars["Boolean"]["output"];
editComment: Scalars["Boolean"]["output"];
editProfileImageUri: UserGql;
editShot: EditShotReturn;
@@ -2528,6 +2545,10 @@ export type MutationDismissChallengeArgs = {
challengeId: Scalars["ID"]["input"];
};
export type MutationDismissVideoExportArgs = {
jobId: Scalars["Int"]["input"];
};
export type MutationEditCommentArgs = {
commentId: Scalars["Int"]["input"];
newMessage: Scalars["String"]["input"];
@@ -2823,6 +2844,18 @@ export type PocketingIntentionInfoGql = {
pocketId: PocketIdentifier;
};
export type PotAimGql = {
__typename?: "PotAimGQL";
converged: Scalars["Boolean"]["output"];
cutAngle: Scalars["Float"]["output"];
feasible: Scalars["Boolean"]["output"];
geometricPhi: Scalars["Float"]["output"];
occludingBallIds: Array<Scalars["Int"]["output"]>;
phi: Scalars["Float"]["output"];
potted: Scalars["Boolean"]["output"];
requiredPrecision: Scalars["Float"]["output"];
};
export type ProcessingFailedErr = {
__typename?: "ProcessingFailedErr";
processing: VideoProcessingGql;
@@ -2844,6 +2877,7 @@ export type Query = {
challenge?: Maybe<Challenge>;
challengeLeaderboard: Array<ChallengeEntry>;
challenges: Array<Challenge>;
computePotAim: PotAimGql;
doesUsernameExist: Scalars["Boolean"]["output"];
getAggregatedShotMetrics: Array<AggregateResultGql>;
getAppleAppAccountToken: Scalars["String"]["output"];
@@ -2886,6 +2920,7 @@ export type Query = {
myVideoExports: Array<VideoExportJobGql>;
notifications: NotificationConnection;
ruleSets: Array<RuleSet>;
simulateShot: ShotProjectionGql;
unreadNotificationCount: Scalars["Int"]["output"];
videoExportJob?: Maybe<VideoExportJobGql>;
videoPlayerClusters: Array<PlayerClusterGql>;
@@ -2905,6 +2940,12 @@ export type QueryChallengesArgs = {
includeDismissed?: Scalars["Boolean"]["input"];
};
export type QueryComputePotAimArgs = {
pocket: PocketIdentifier;
simulationInput: SimulateShotInputGql;
targetBallId: Scalars["Int"]["input"];
};
export type QueryDoesUsernameExistArgs = {
candidateUsername: Scalars["String"]["input"];
};
@@ -3075,6 +3116,10 @@ export type QueryNotificationsArgs = {
offset?: Scalars["Int"]["input"];
};
export type QuerySimulateShotArgs = {
simulationInput: SimulateShotInputGql;
};
export type QueryVideoExportJobArgs = {
jobId: Scalars["Int"]["input"];
};
@@ -3338,6 +3383,14 @@ export type ShotMoveInput = {
shotId: Scalars["Int"]["input"];
};
export type ShotProjectionGql = {
__typename?: "ShotProjectionGQL";
events: Array<SimulationEventGql>;
finalState: Array<SimulationBallStateGql>;
pottedBallIds: Array<Scalars["Int"]["output"]>;
trajectories: Array<BallTrajectoryGql>;
};
export type ShotsOrderingComponent =
| {
difficulty: FloatOrdering;
@@ -3388,6 +3441,42 @@ export type ShotsOrderingComponent =
videoId: IntOrdering;
};
export type SimulateShotInputGql = {
b64Image?: InputMaybe<Scalars["String"]["input"]>;
balls?: InputMaybe<Array<SimulationBallStateInputGql>>;
cueBallId: Scalars["Int"]["input"];
strike: CueStrikeInputGql;
tableSize?: InputMaybe<Scalars["Float"]["input"]>;
useHomography?: InputMaybe<HomographyInputGql>;
};
export type SimulationBallStateGql = {
__typename?: "SimulationBallStateGQL";
ballId: Scalars["Int"]["output"];
position: Array<Scalars["Float"]["output"]>;
};
export type SimulationBallStateInputGql = {
ballId: Scalars["Int"]["input"];
position: Array<Scalars["Float"]["input"]>;
};
export type SimulationEventGql = {
__typename?: "SimulationEventGQL";
ballIds: Array<Scalars["Int"]["output"]>;
eventType: SimulationEventType;
position?: Maybe<Array<Scalars["Float"]["output"]>>;
time: Scalars["Float"]["output"];
};
export enum SimulationEventType {
BallBall = "BALL_BALL",
BallCushion = "BALL_CUSHION",
BallPocket = "BALL_POCKET",
BallStop = "BALL_STOP",
StickBall = "STICK_BALL",
}
export type SpinTypeBreakdownGql = {
__typename?: "SpinTypeBreakdownGQL";
center: Scalars["Int"]["output"];
@@ -3410,6 +3499,15 @@ export enum SpinTypeEnum {
Unknown = "UNKNOWN",
}
export type StorageLimitExceededErr = {
__typename?: "StorageLimitExceededErr";
reason: Scalars["String"]["output"];
remainingStorageBytes?: Maybe<Scalars["BigInt"]["output"]>;
retainedStorageLimitBytes?: Maybe<Scalars["BigInt"]["output"]>;
retainedStorageUsedBytes: Scalars["BigInt"]["output"];
tierName: Scalars["String"]["output"];
};
export type StorageStatusGql = {
__typename?: "StorageStatusGQL";
isNearLimit: Scalars["Boolean"]["output"];
@@ -3555,6 +3653,12 @@ export type TooManyProfileImageUploadsErr = {
linksRequested: Scalars["Int"]["output"];
};
export type TrajectoryPointGql = {
__typename?: "TrajectoryPointGQL";
position: Array<Scalars["Float"]["output"]>;
time: Scalars["Float"]["output"];
};
export type UpdateAnnotationInputGql = {
name: Scalars["String"]["input"];
notes?: InputMaybe<Scalars["String"]["input"]>;
@@ -3684,6 +3788,8 @@ export type VideoExportJobGql = {
shotIds?: Maybe<Array<Scalars["Int"]["output"]>>;
status: VideoExportStatusEnum;
videoId: Scalars["Int"]["output"];
videoName?: Maybe<Scalars["String"]["output"]>;
videoThumbnailUri?: Maybe<Scalars["String"]["output"]>;
};
export enum VideoExportModeEnum {
@@ -5454,6 +5560,74 @@ export type FinalizePlayerAssignmentsMutation = {
}>;
};
export type GetTableStateQueryVariables = Exact<{
b64Image: Scalars["String"]["input"];
tableSize?: InputMaybe<Scalars["Float"]["input"]>;
useHomography?: InputMaybe<HomographyInputGql>;
}>;
export type GetTableStateQuery = {
__typename?: "Query";
getTableState: {
__typename?: "TableStateGQL";
identifierToPosition: Array<Array<number>>;
};
};
export type SimulateShotQueryVariables = Exact<{
simulationInput: SimulateShotInputGql;
}>;
export type SimulateShotQuery = {
__typename?: "Query";
simulateShot: {
__typename?: "ShotProjectionGQL";
pottedBallIds: Array<number>;
trajectories: Array<{
__typename?: "BallTrajectoryGQL";
ballId: number;
points: Array<{
__typename?: "TrajectoryPointGQL";
time: number;
position: Array<number>;
}>;
}>;
events: Array<{
__typename?: "SimulationEventGQL";
eventType: SimulationEventType;
time: number;
ballIds: Array<number>;
position?: Array<number> | null;
}>;
finalState: Array<{
__typename?: "SimulationBallStateGQL";
ballId: number;
position: Array<number>;
}>;
};
};
export type ComputePotAimQueryVariables = Exact<{
simulationInput: SimulateShotInputGql;
targetBallId: Scalars["Int"]["input"];
pocket: PocketIdentifier;
}>;
export type ComputePotAimQuery = {
__typename?: "Query";
computePotAim: {
__typename?: "PotAimGQL";
phi: number;
geometricPhi: number;
cutAngle: number;
requiredPrecision: number;
feasible: boolean;
potted: boolean;
converged: boolean;
occludingBallIds: Array<number>;
};
};
export type GetSerializedShotPathsQueryVariables = Exact<{
filterInput: FilterInput;
}>;
@@ -7074,6 +7248,8 @@ export type VideoExportJobFieldsFragment = {
videoId: number;
mode: VideoExportModeEnum;
status: VideoExportStatusEnum;
videoName?: string | null;
videoThumbnailUri?: string | null;
shotIds?: Array<number> | null;
runId?: number | null;
downloadUrl?: string | null;
@@ -7094,6 +7270,8 @@ export type RequestVideoExportMutation = {
videoId: number;
mode: VideoExportModeEnum;
status: VideoExportStatusEnum;
videoName?: string | null;
videoThumbnailUri?: string | null;
shotIds?: Array<number> | null;
runId?: number | null;
downloadUrl?: string | null;
@@ -7103,6 +7281,15 @@ export type RequestVideoExportMutation = {
};
};
export type DismissVideoExportMutationVariables = Exact<{
jobId: Scalars["Int"]["input"];
}>;
export type DismissVideoExportMutation = {
__typename?: "Mutation";
dismissVideoExport: boolean;
};
export type VideoExportJobQueryVariables = Exact<{
jobId: Scalars["Int"]["input"];
}>;
@@ -7115,6 +7302,8 @@ export type VideoExportJobQuery = {
videoId: number;
mode: VideoExportModeEnum;
status: VideoExportStatusEnum;
videoName?: string | null;
videoThumbnailUri?: string | null;
shotIds?: Array<number> | null;
runId?: number | null;
downloadUrl?: string | null;
@@ -7137,6 +7326,8 @@ export type MyVideoExportsQuery = {
videoId: number;
mode: VideoExportModeEnum;
status: VideoExportStatusEnum;
videoName?: string | null;
videoThumbnailUri?: string | null;
shotIds?: Array<number> | null;
runId?: number | null;
downloadUrl?: string | null;
@@ -7191,6 +7382,7 @@ export type GetUploadLinkMutation = {
};
}
| { __typename?: "SegmentAlreadyUploadedErr"; segmentId: number }
| { __typename?: "StorageLimitExceededErr" }
| { __typename?: "TooManyInitUploadsErr" }
| { __typename?: "TooManyProfileImageUploadsErr" };
}
@@ -7233,6 +7425,14 @@ export type GetHlsInitUploadLinkMutation = {
}
| { __typename?: "ProcessingFailedErr" }
| { __typename?: "SegmentAlreadyUploadedErr" }
| {
__typename?: "StorageLimitExceededErr";
reason: string;
tierName: string;
retainedStorageUsedBytes: any;
retainedStorageLimitBytes?: any | null;
remainingStorageBytes?: any | null;
}
| { __typename?: "TooManyInitUploadsErr"; linksRequested: number }
| { __typename?: "TooManyProfileImageUploadsErr" };
}
@@ -7717,6 +7917,8 @@ export const VideoExportJobFieldsFragmentDoc = gql`
videoId
mode
status
videoName
videoThumbnailUri
shotIds
runId
downloadUrl
@@ -11685,6 +11887,269 @@ export type FinalizePlayerAssignmentsMutationOptions =
FinalizePlayerAssignmentsMutation,
FinalizePlayerAssignmentsMutationVariables
>;
export const GetTableStateDocument = gql`
query GetTableState(
$b64Image: String!
$tableSize: Float
$useHomography: HomographyInputGQL
) {
getTableState(
b64Image: $b64Image
tableSize: $tableSize
useHomography: $useHomography
) {
identifierToPosition
}
}
`;
/**
* __useGetTableStateQuery__
*
* To run a query within a React component, call `useGetTableStateQuery` and pass it any options that fit your needs.
* When your component renders, `useGetTableStateQuery` 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 } = useGetTableStateQuery({
* variables: {
* b64Image: // value for 'b64Image'
* tableSize: // value for 'tableSize'
* useHomography: // value for 'useHomography'
* },
* });
*/
export function useGetTableStateQuery(
baseOptions: Apollo.QueryHookOptions<
GetTableStateQuery,
GetTableStateQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetTableStateQuery, GetTableStateQueryVariables>(
GetTableStateDocument,
options,
);
}
export function useGetTableStateLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
GetTableStateQuery,
GetTableStateQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<GetTableStateQuery, GetTableStateQueryVariables>(
GetTableStateDocument,
options,
);
}
export function useGetTableStateSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
GetTableStateQuery,
GetTableStateQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
GetTableStateQuery,
GetTableStateQueryVariables
>(GetTableStateDocument, options);
}
export type GetTableStateQueryHookResult = ReturnType<
typeof useGetTableStateQuery
>;
export type GetTableStateLazyQueryHookResult = ReturnType<
typeof useGetTableStateLazyQuery
>;
export type GetTableStateSuspenseQueryHookResult = ReturnType<
typeof useGetTableStateSuspenseQuery
>;
export type GetTableStateQueryResult = Apollo.QueryResult<
GetTableStateQuery,
GetTableStateQueryVariables
>;
export const SimulateShotDocument = gql`
query SimulateShot($simulationInput: SimulateShotInputGQL!) {
simulateShot(simulationInput: $simulationInput) {
trajectories {
ballId
points {
time
position
}
}
events {
eventType
time
ballIds
position
}
finalState {
ballId
position
}
pottedBallIds
}
}
`;
/**
* __useSimulateShotQuery__
*
* To run a query within a React component, call `useSimulateShotQuery` and pass it any options that fit your needs.
* When your component renders, `useSimulateShotQuery` 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 } = useSimulateShotQuery({
* variables: {
* simulationInput: // value for 'simulationInput'
* },
* });
*/
export function useSimulateShotQuery(
baseOptions: Apollo.QueryHookOptions<
SimulateShotQuery,
SimulateShotQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<SimulateShotQuery, SimulateShotQueryVariables>(
SimulateShotDocument,
options,
);
}
export function useSimulateShotLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
SimulateShotQuery,
SimulateShotQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<SimulateShotQuery, SimulateShotQueryVariables>(
SimulateShotDocument,
options,
);
}
export function useSimulateShotSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
SimulateShotQuery,
SimulateShotQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<SimulateShotQuery, SimulateShotQueryVariables>(
SimulateShotDocument,
options,
);
}
export type SimulateShotQueryHookResult = ReturnType<
typeof useSimulateShotQuery
>;
export type SimulateShotLazyQueryHookResult = ReturnType<
typeof useSimulateShotLazyQuery
>;
export type SimulateShotSuspenseQueryHookResult = ReturnType<
typeof useSimulateShotSuspenseQuery
>;
export type SimulateShotQueryResult = Apollo.QueryResult<
SimulateShotQuery,
SimulateShotQueryVariables
>;
export const ComputePotAimDocument = gql`
query ComputePotAim(
$simulationInput: SimulateShotInputGQL!
$targetBallId: Int!
$pocket: PocketIdentifier!
) {
computePotAim(
simulationInput: $simulationInput
targetBallId: $targetBallId
pocket: $pocket
) {
phi
geometricPhi
cutAngle
requiredPrecision
feasible
potted
converged
occludingBallIds
}
}
`;
/**
* __useComputePotAimQuery__
*
* To run a query within a React component, call `useComputePotAimQuery` and pass it any options that fit your needs.
* When your component renders, `useComputePotAimQuery` 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 } = useComputePotAimQuery({
* variables: {
* simulationInput: // value for 'simulationInput'
* targetBallId: // value for 'targetBallId'
* pocket: // value for 'pocket'
* },
* });
*/
export function useComputePotAimQuery(
baseOptions: Apollo.QueryHookOptions<
ComputePotAimQuery,
ComputePotAimQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<ComputePotAimQuery, ComputePotAimQueryVariables>(
ComputePotAimDocument,
options,
);
}
export function useComputePotAimLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ComputePotAimQuery,
ComputePotAimQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<ComputePotAimQuery, ComputePotAimQueryVariables>(
ComputePotAimDocument,
options,
);
}
export function useComputePotAimSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
ComputePotAimQuery,
ComputePotAimQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
ComputePotAimQuery,
ComputePotAimQueryVariables
>(ComputePotAimDocument, options);
}
export type ComputePotAimQueryHookResult = ReturnType<
typeof useComputePotAimQuery
>;
export type ComputePotAimLazyQueryHookResult = ReturnType<
typeof useComputePotAimLazyQuery
>;
export type ComputePotAimSuspenseQueryHookResult = ReturnType<
typeof useComputePotAimSuspenseQuery
>;
export type ComputePotAimQueryResult = Apollo.QueryResult<
ComputePotAimQuery,
ComputePotAimQueryVariables
>;
export const GetSerializedShotPathsDocument = gql`
query GetSerializedShotPaths($filterInput: FilterInput!) {
getShots(filterInput: $filterInput) {
@@ -15187,6 +15652,54 @@ export type RequestVideoExportMutationOptions = Apollo.BaseMutationOptions<
RequestVideoExportMutation,
RequestVideoExportMutationVariables
>;
export const DismissVideoExportDocument = gql`
mutation DismissVideoExport($jobId: Int!) {
dismissVideoExport(jobId: $jobId)
}
`;
export type DismissVideoExportMutationFn = Apollo.MutationFunction<
DismissVideoExportMutation,
DismissVideoExportMutationVariables
>;
/**
* __useDismissVideoExportMutation__
*
* To run a mutation, you first call `useDismissVideoExportMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useDismissVideoExportMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [dismissVideoExportMutation, { data, loading, error }] = useDismissVideoExportMutation({
* variables: {
* jobId: // value for 'jobId'
* },
* });
*/
export function useDismissVideoExportMutation(
baseOptions?: Apollo.MutationHookOptions<
DismissVideoExportMutation,
DismissVideoExportMutationVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useMutation<
DismissVideoExportMutation,
DismissVideoExportMutationVariables
>(DismissVideoExportDocument, options);
}
export type DismissVideoExportMutationHookResult = ReturnType<
typeof useDismissVideoExportMutation
>;
export type DismissVideoExportMutationResult =
Apollo.MutationResult<DismissVideoExportMutation>;
export type DismissVideoExportMutationOptions = Apollo.BaseMutationOptions<
DismissVideoExportMutation,
DismissVideoExportMutationVariables
>;
export const VideoExportJobDocument = gql`
query VideoExportJob($jobId: Int!) {
videoExportJob(jobId: $jobId) {
@@ -15496,6 +16009,13 @@ export const GetHlsInitUploadLinkDocument = gql`
... on TooManyInitUploadsErr {
linksRequested
}
... on StorageLimitExceededErr {
reason
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
remainingStorageBytes
}
}
}
}

View File

@@ -0,0 +1,57 @@
query GetTableState(
$b64Image: String!
$tableSize: Float
$useHomography: HomographyInputGQL
) {
getTableState(
b64Image: $b64Image
tableSize: $tableSize
useHomography: $useHomography
) {
identifierToPosition
}
}
query SimulateShot($simulationInput: SimulateShotInputGQL!) {
simulateShot(simulationInput: $simulationInput) {
trajectories {
ballId
points {
time
position
}
}
events {
eventType
time
ballIds
position
}
finalState {
ballId
position
}
pottedBallIds
}
}
query ComputePotAim(
$simulationInput: SimulateShotInputGQL!
$targetBallId: Int!
$pocket: PocketIdentifier!
) {
computePotAim(
simulationInput: $simulationInput
targetBallId: $targetBallId
pocket: $pocket
) {
phi
geometricPhi
cutAngle
requiredPrecision
feasible
potted
converged
occludingBallIds
}
}

View File

@@ -3,6 +3,8 @@ fragment VideoExportJobFields on VideoExportJobGQL {
videoId
mode
status
videoName
videoThumbnailUri
shotIds
runId
downloadUrl
@@ -17,6 +19,10 @@ mutation RequestVideoExport($input: RequestVideoExportInput!) {
}
}
mutation DismissVideoExport($jobId: Int!) {
dismissVideoExport(jobId: $jobId)
}
query VideoExportJob($jobId: Int!) {
videoExportJob(jobId: $jobId) {
...VideoExportJobFields

View File

@@ -67,6 +67,13 @@ mutation GetHlsInitUploadLink($videoId: Int!) {
... on TooManyInitUploadsErr {
linksRequested
}
... on StorageLimitExceededErr {
reason
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
remainingStorageBytes
}
}
}
}

View File

@@ -66,6 +66,12 @@ type Query {
tableSize: Float = 100
useHomography: HomographyInputGQL = null
): TableStateGQL!
simulateShot(simulationInput: SimulateShotInputGQL!): ShotProjectionGQL!
computePotAim(
simulationInput: SimulateShotInputGQL!
targetBallId: Int!
pocket: PocketIdentifier!
): PotAimGQL!
getOrderedShots(
filterInput: FilterInput!
ids: [Int!] = null
@@ -714,6 +720,7 @@ type DeployedConfigGQL {
minimumAllowedAppVersion: String!
subscriptionGatingEnabled: Boolean!
quotaEnforcementEnabled: Boolean!
storageLimitEnforcementEnabled: Boolean!
bannerMessages: [BannerGQL!]!
defaultAndroidRecordingFormat: StreamSegmentTypeEnum!
bucketUrl: String!
@@ -969,6 +976,76 @@ input IntPoint2DInput {
y: Int!
}
type ShotProjectionGQL {
trajectories: [BallTrajectoryGQL!]!
events: [SimulationEventGQL!]!
finalState: [SimulationBallStateGQL!]!
pottedBallIds: [Int!]!
}
type BallTrajectoryGQL {
ballId: Int!
points: [TrajectoryPointGQL!]!
}
type TrajectoryPointGQL {
time: Float!
position: [Float!]!
}
type SimulationEventGQL {
eventType: SimulationEventType!
time: Float!
ballIds: [Int!]!
position: [Float!]
}
enum SimulationEventType {
STICK_BALL
BALL_BALL
BALL_CUSHION
BALL_POCKET
BALL_STOP
}
type SimulationBallStateGQL {
ballId: Int!
position: [Float!]!
}
input SimulateShotInputGQL {
cueBallId: Int!
strike: CueStrikeInputGQL!
balls: [SimulationBallStateInputGQL!] = null
b64Image: String = null
useHomography: HomographyInputGQL = null
tableSize: Float = null
}
input CueStrikeInputGQL {
v0: Float!
phi: Float!
theta: Float! = 0
a: Float! = 0
b: Float! = 0
}
input SimulationBallStateInputGQL {
ballId: Int!
position: [Float!]!
}
type PotAimGQL {
phi: Float!
geometricPhi: Float!
cutAngle: Float!
requiredPrecision: Float!
feasible: Boolean!
potted: Boolean!
converged: Boolean!
occludingBallIds: [Int!]!
}
type GetShotsResult {
shots: [ShotGQL!]!
count: Int
@@ -1172,6 +1249,8 @@ type VideoExportJobGQL {
videoId: Int!
mode: VideoExportModeEnum!
status: VideoExportStatusEnum!
videoName: String
videoThumbnailUri: String
shotIds: [Int!]
runId: Int
downloadUrl: String
@@ -1297,6 +1376,7 @@ type Mutation {
metadata: CancellationFeedbackMetadataInput = null
): Boolean!
requestVideoExport(input: RequestVideoExportInput!): VideoExportJobGQL!
dismissVideoExport(jobId: Int!): Boolean!
findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL
createUploadStream(
videoMetadata: VideoMetadataInput!
@@ -1525,10 +1605,10 @@ type GetUploadLinkReturn {
union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors
type GetUploadLinkErrors {
error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr!
error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr!
}
union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr =
union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr =
MustHaveSetForUploadLinkErr
| SegmentAlreadyUploadedErr
| ProcessingFailedErr
@@ -1536,6 +1616,7 @@ union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoI
| TooManyProfileImageUploadsErr
| InitUploadAlreadyCompletedErr
| TooManyInitUploadsErr
| StorageLimitExceededErr
type MustHaveSetForUploadLinkErr {
resolution: Boolean
@@ -1561,3 +1642,11 @@ type InitUploadAlreadyCompletedErr {
type TooManyInitUploadsErr {
linksRequested: Int!
}
type StorageLimitExceededErr {
reason: String!
tierName: String!
retainedStorageUsedBytes: BigInt!
retainedStorageLimitBytes: BigInt
remainingStorageBytes: BigInt
}