Compare commits

...

8 Commits

Author SHA1 Message Date
494745df9d Select storage limit fields for upload links
All checks were successful
Tests / Tests (pull_request) Successful in 10s
2026-07-02 17:46:14 -07:00
c3b79bc503 Select storage limit config flag 2026-07-02 17:46:14 -07:00
5b20b644de Add resolved tier query 2026-07-02 17:46:14 -07:00
8fef7e5543 Add storage status readiness query fields 2026-07-02 17:46:14 -07:00
0fd7be2a99 Add storage status query 2026-07-02 17:46:14 -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
5 changed files with 387 additions and 1 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"]>;
@@ -2893,6 +2907,7 @@ export type Query = {
myVideoExports: Array<VideoExportJobGql>;
notifications: NotificationConnection;
ruleSets: Array<RuleSet>;
simulateShot: ShotProjectionGql;
unreadNotificationCount: Scalars["Int"]["output"];
videoExportJob?: Maybe<VideoExportJobGql>;
videoPlayerClusters: Array<PlayerClusterGql>;
@@ -3082,6 +3097,10 @@ export type QueryNotificationsArgs = {
offset?: Scalars["Int"]["input"];
};
export type QuerySimulateShotArgs = {
simulationInput: SimulateShotInputGql;
};
export type QueryVideoExportJobArgs = {
jobId: Scalars["Int"]["input"];
};
@@ -3345,6 +3364,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;
@@ -3395,6 +3422,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"];
@@ -3571,6 +3634,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"]>;
@@ -4313,6 +4382,7 @@ export type GetDeployedConfigQuery = {
minimumAllowedAppVersion: string;
subscriptionGatingEnabled: boolean;
quotaEnforcementEnabled: boolean;
storageLimitEnforcementEnabled: boolean;
defaultAndroidRecordingFormat: StreamSegmentTypeEnum;
bucketUrl: string;
bannerMessages: Array<{
@@ -5202,6 +5272,45 @@ export type GetSubscriptionStatusQuery = {
};
};
export type GetResolvedTierQueryVariables = Exact<{ [key: string]: never }>;
export type GetResolvedTierQuery = {
__typename?: "Query";
getResolvedTier: {
__typename?: "ResolvedTierGQL";
tierName: string;
tierDisplayName: string;
hasActiveSubscription: boolean;
entitlementSource?: EntitlementSourceTypeEnum | null;
entitlementStatus?: string | null;
entitlementStartsAt?: any | null;
entitlementEndsAt?: any | null;
capabilities: Array<string>;
};
};
export type GetStorageStatusQueryVariables = Exact<{ [key: string]: never }>;
export type GetStorageStatusQuery = {
__typename?: "Query";
getStorageStatus?: {
__typename?: "StorageStatusGQL";
userId: number;
tierName: string;
retainedStorageUsedBytes: any;
retainedStorageLimitBytes?: any | null;
isUnlimited: boolean;
policyConfigured: boolean;
remainingStorageBytes?: any | null;
storageUsageRatio?: number | null;
isNearLimit: boolean;
isOverLimit: boolean;
usageCalculated: boolean;
usageSource?: string | null;
lastCalculatedAt?: any | null;
} | null;
};
export type GetAppleAppAccountTokenQueryVariables = Exact<{
[key: string]: never;
}>;
@@ -7226,7 +7335,14 @@ export type GetUploadLinkMutation = {
};
}
| { __typename?: "SegmentAlreadyUploadedErr"; segmentId: number }
| { __typename?: "StorageLimitExceededErr" }
| {
__typename?: "StorageLimitExceededErr";
reason: string;
tierName: string;
retainedStorageUsedBytes: any;
retainedStorageLimitBytes?: any | null;
remainingStorageBytes?: any | null;
}
| { __typename?: "TooManyInitUploadsErr" }
| { __typename?: "TooManyProfileImageUploadsErr" };
}
@@ -9260,6 +9376,7 @@ export const GetDeployedConfigDocument = gql`
minimumAllowedAppVersion
subscriptionGatingEnabled
quotaEnforcementEnabled
storageLimitEnforcementEnabled
bannerMessages {
color
dismissible
@@ -11107,6 +11224,169 @@ export type GetSubscriptionStatusQueryResult = Apollo.QueryResult<
GetSubscriptionStatusQuery,
GetSubscriptionStatusQueryVariables
>;
export const GetResolvedTierDocument = gql`
query GetResolvedTier {
getResolvedTier {
tierName
tierDisplayName
hasActiveSubscription
entitlementSource
entitlementStatus
entitlementStartsAt
entitlementEndsAt
capabilities
}
}
`;
/**
* __useGetResolvedTierQuery__
*
* To run a query within a React component, call `useGetResolvedTierQuery` and pass it any options that fit your needs.
* When your component renders, `useGetResolvedTierQuery` 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 } = useGetResolvedTierQuery({
* variables: {
* },
* });
*/
export function useGetResolvedTierQuery(
baseOptions?: Apollo.QueryHookOptions<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetResolvedTierQuery, GetResolvedTierQueryVariables>(
GetResolvedTierDocument,
options,
);
}
export function useGetResolvedTierLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>(GetResolvedTierDocument, options);
}
export function useGetResolvedTierSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>(GetResolvedTierDocument, options);
}
export type GetResolvedTierQueryHookResult = ReturnType<
typeof useGetResolvedTierQuery
>;
export type GetResolvedTierLazyQueryHookResult = ReturnType<
typeof useGetResolvedTierLazyQuery
>;
export type GetResolvedTierSuspenseQueryHookResult = ReturnType<
typeof useGetResolvedTierSuspenseQuery
>;
export type GetResolvedTierQueryResult = Apollo.QueryResult<
GetResolvedTierQuery,
GetResolvedTierQueryVariables
>;
export const GetStorageStatusDocument = gql`
query GetStorageStatus {
getStorageStatus {
userId
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
isUnlimited
policyConfigured
remainingStorageBytes
storageUsageRatio
isNearLimit
isOverLimit
usageCalculated
usageSource
lastCalculatedAt
}
}
`;
/**
* __useGetStorageStatusQuery__
*
* To run a query within a React component, call `useGetStorageStatusQuery` and pass it any options that fit your needs.
* When your component renders, `useGetStorageStatusQuery` 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 } = useGetStorageStatusQuery({
* variables: {
* },
* });
*/
export function useGetStorageStatusQuery(
baseOptions?: Apollo.QueryHookOptions<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<GetStorageStatusQuery, GetStorageStatusQueryVariables>(
GetStorageStatusDocument,
options,
);
}
export function useGetStorageStatusLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>(GetStorageStatusDocument, options);
}
export function useGetStorageStatusSuspenseQuery(
baseOptions?: Apollo.SuspenseQueryHookOptions<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>,
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useSuspenseQuery<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>(GetStorageStatusDocument, options);
}
export type GetStorageStatusQueryHookResult = ReturnType<
typeof useGetStorageStatusQuery
>;
export type GetStorageStatusLazyQueryHookResult = ReturnType<
typeof useGetStorageStatusLazyQuery
>;
export type GetStorageStatusSuspenseQueryHookResult = ReturnType<
typeof useGetStorageStatusSuspenseQuery
>;
export type GetStorageStatusQueryResult = Apollo.QueryResult<
GetStorageStatusQuery,
GetStorageStatusQueryVariables
>;
export const GetAppleAppAccountTokenDocument = gql`
query GetAppleAppAccountToken {
getAppleAppAccountToken
@@ -15515,6 +15795,13 @@ export const GetUploadLinkDocument = gql`
}
}
}
... on StorageLimitExceededErr {
reason
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
remainingStorageBytes
}
}
}
}

View File

@@ -7,6 +7,7 @@ query getDeployedConfig {
minimumAllowedAppVersion
subscriptionGatingEnabled
quotaEnforcementEnabled
storageLimitEnforcementEnabled
bannerMessages {
color
dismissible

View File

@@ -67,6 +67,37 @@ query GetSubscriptionStatus {
}
}
query GetResolvedTier {
getResolvedTier {
tierName
tierDisplayName
hasActiveSubscription
entitlementSource
entitlementStatus
entitlementStartsAt
entitlementEndsAt
capabilities
}
}
query GetStorageStatus {
getStorageStatus {
userId
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
isUnlimited
policyConfigured
remainingStorageBytes
storageUsageRatio
isNearLimit
isOverLimit
usageCalculated
usageSource
lastCalculatedAt
}
}
query GetAppleAppAccountToken {
getAppleAppAccountToken
}

View File

@@ -37,6 +37,13 @@ mutation GetUploadLink($videoId: Int!, $segmentIndex: Int!) {
}
}
}
... on StorageLimitExceededErr {
reason
tierName
retainedStorageUsedBytes
retainedStorageLimitBytes
remainingStorageBytes
}
}
}
}

View File

@@ -66,6 +66,7 @@ type Query {
tableSize: Float = 100
useHomography: HomographyInputGQL = null
): TableStateGQL!
simulateShot(simulationInput: SimulateShotInputGQL!): ShotProjectionGQL!
getOrderedShots(
filterInput: FilterInput!
ids: [Int!] = null
@@ -970,6 +971,65 @@ 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 GetShotsResult {
shots: [ShotGQL!]!
count: Int