Compare commits

..

3 Commits

Author SHA1 Message Date
5030ff560d index change from just gql
All checks were successful
Tests / Tests (pull_request) Successful in 10s
2026-02-18 16:50:20 -08:00
1c6fef9de0 add expectedDurationSeconds to create upload stream mutation 2026-02-18 16:46:11 -08:00
d31d171ac3 getQuotaStatus, expectedDurationSeconds in createUploadStream
All checks were successful
Tests / Tests (pull_request) Successful in 40s
2026-02-03 16:30:56 -08:00
10 changed files with 65 additions and 1615 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -31,32 +31,41 @@ fragment VideoCardFields on VideoGQL {
} }
name name
screenshotUri screenshotUri
totalShotsMade
totalShots totalShots
makePercentage makePercentage
averageTimeBetweenShots averageTimeBetweenShots
averageDifficulty averageDifficulty
createdAt
updatedAt
startTime startTime
endTime
private private
elapsedTime elapsedTime
screenshotUri
stream { stream {
id id
lastIntendedSegmentBound lastIntendedSegmentBound
isCompleted
streamSegmentType streamSegmentType
} }
tableSize tableSize
pocketSize pocketSize
tags { tags {
name
tagClasses { tagClasses {
name name
} }
} name
playerSummaries {
...PlayerSummaryFields
} }
currentProcessing { currentProcessing {
id id
errors {
message
}
status status
statuses {
status
}
} }
reactions { reactions {
videoId videoId
@@ -101,27 +110,6 @@ query GetVideoFeedSessionCount(
} }
} }
# Minimal query for the Home recency nudge ("you haven't recorded in N days").
# Only the most recent session's start time — avoids pulling the full
# VideoCardFields payload (reactions, comments, player summaries, etc.).
query GetLastSessionDate(
$filters: VideoFilterInput = null
$includePrivate: IncludePrivateEnum = MINE
$feedInput: VideoFeedInputGQL = null
) {
getFeedVideos(
limit: 1
filters: $filters
includePrivate: $includePrivate
feedInput: $feedInput
) {
videos {
id
startTime
}
}
}
query GetVideoFeed( query GetVideoFeed(
$limit: Int! = 5 $limit: Int! = 5
$after: String = null $after: String = null

View File

@@ -20,15 +20,8 @@ mutation CreateSubscription($priceId: String!) {
} }
} }
mutation CreateCustomerPortalSession {
createCustomerPortalSession {
portalUrl
}
}
query GetAvailableSubscriptionOptions { query GetAvailableSubscriptionOptions {
getAvailableSubscriptionOptions { getAvailableSubscriptionOptions {
trialPeriodDays
products { products {
id id
name name

View File

@@ -1,52 +0,0 @@
fragment PlayerSummaryFields on PlayerSummaryGQL {
clusterId
userId
username
profileImageUri
representativeFullFrameUrl
totalShots
totalShotsMade
makePercentage
score
longestRun
averageDifficulty
averageTimeBetweenShots
}
fragment PlayerClusterShotFields on PlayerClusterShotGQL {
shotId
bboxX1
bboxY1
bboxX2
bboxY2
confidence
isConfirmed
cropUrl
fullFrameUrl
}
fragment PlayerClusterFields on PlayerClusterGQL {
videoId
clusterId
nShots
userId
username
profileImageUri
confirmed
score
shots {
...PlayerClusterShotFields
}
}
query VideoPlayerClusters($videoId: Int!) {
videoPlayerClusters(videoId: $videoId) {
...PlayerClusterFields
}
}
mutation FinalizePlayerAssignments($input: FinalizePlayerAssignmentsInput!) {
finalizePlayerAssignments(input: $input) {
...PlayerClusterFields
}
}

View File

@@ -132,38 +132,6 @@ query GetShotsByIds($ids: [Int!]!) {
} }
} }
# Lightweight clip boundaries for condensed session playback. The inline
# session player only needs each shot's frame/time window to seek between
# shots — this skips the heavy ShotWithAllFeatures payload (cue/pocketing
# features, serialized shot paths, annotations, nested video/playlist). The
# startTime/endTime @client resolvers derive their values from the frame
# fields + the video (looked up internally), so this is all they require.
fragment ShotClipRange on ShotGQL {
id
videoId
startFrame
endFrame
startTime @client
endTime @client
}
query GetShotClipRanges(
$filterInput: FilterInput!
$shotsOrdering: GetShotsOrdering
$limit: Int
) {
getOrderedShots(
filterInput: $filterInput
shotsOrdering: $shotsOrdering
limit: $limit
) {
count
shots {
...ShotClipRange
}
}
}
fragment ShotWithAllFeatures on ShotGQL { fragment ShotWithAllFeatures on ShotGQL {
id id
videoId videoId

View File

@@ -49,39 +49,6 @@ query GetUserPlayTime($userId: Int!, $filters: VideoFilterInput) {
} }
} }
query GetUploadQuotaStatus {
getQuotaStatus {
tierName
periodStart
periodEnd
durationUsedSeconds
durationLimitSeconds
maxVideoDurationSeconds
durationRemainingSeconds
canUpload
importQuotaBuckets {
quotaKey
appliesToUploadKind
periodStart
periodEnd
durationUsedSeconds
durationLimitSeconds
durationRemainingSeconds
canUpload
}
recordingQuotaBuckets {
quotaKey
appliesToUploadKind
periodStart
periodEnd
durationUsedSeconds
durationLimitSeconds
durationRemainingSeconds
canUpload
}
}
}
query getUsernames( query getUsernames(
$matchString: String! $matchString: String!
$limit: Int = null $limit: Int = null
@@ -125,17 +92,6 @@ query GetUserTags {
} }
} }
query GetGameTypeTagMetrics($input: GameTypeTagMetricsInput!) {
getGameTypeTagMetrics(input: $input) {
tagName
tagLabel
tableSize
shotCount
madeShots
makeRate
}
}
mutation followUser($followedUserId: Int!) { mutation followUser($followedUserId: Int!) {
followUser(followedUserId: $followedUserId) { followUser(followedUserId: $followedUserId) {
id id

View File

@@ -10,7 +10,6 @@ query GetStreamMonitoringDetails($videoId: Int!, $debuggingJson: JSON) {
stream { stream {
id id
linksRequested linksRequested
lowestUnuploadedSegmentIndex
uploadsCompleted uploadsCompleted
segmentProcessingCursor segmentProcessingCursor
isCompleted isCompleted
@@ -83,9 +82,6 @@ query GetVideoDetails($videoId: Int!) {
} }
name name
} }
playerSummaries {
...PlayerSummaryFields
}
} }
} }
@@ -139,15 +135,6 @@ query GetVideoSocialDetailsById($videoId: Int!) {
} }
} }
# Full card payload for a single video — reuses the same VideoCardFields
# fragment the feed list uses, so the session-detail meta header shares one
# source of truth (and the normalized Apollo cache) with the feed card.
query GetVideoCard($videoId: Int!) {
getVideo(videoId: $videoId) {
...VideoCardFields
}
}
query GetVideos($videoIds: [Int!]!) { query GetVideos($videoIds: [Int!]!) {
getVideos(videoIds: $videoIds) { getVideos(videoIds: $videoIds) {
...VideoStreamMetadata ...VideoStreamMetadata

View File

@@ -1,6 +1,6 @@
mutation CreateUploadStream( mutation CreateUploadStream(
$videoMetadataInput: VideoMetadataInput! $videoMetadataInput: VideoMetadataInput!
$expectedDurationSeconds: Float = null $expectedDurationSeconds: Float
) { ) {
createUploadStream( createUploadStream(
videoMetadata: $videoMetadataInput videoMetadata: $videoMetadataInput

View File

@@ -11,8 +11,6 @@ type Query {
myChallengeInvitations: [ChallengeInvitation!]! myChallengeInvitations: [ChallengeInvitation!]!
ruleSets: [RuleSet!]! ruleSets: [RuleSet!]!
myChallengeEntries: [ChallengeEntry!]! myChallengeEntries: [ChallengeEntry!]!
getVenues: [VenueGQL!]!
getActiveClaim: CameraClaimGQL
getDeployedConfig: DeployedConfigGQL! getDeployedConfig: DeployedConfigGQL!
waitFor(duration: Float!): Float! waitFor(duration: Float!): Float!
getFeedVideos( getFeedVideos(
@@ -30,7 +28,7 @@ type Query {
getLongestRunsLeaderboard( getLongestRunsLeaderboard(
interval: TimeInterval = null interval: TimeInterval = null
when: DateTime = null when: DateTime = null
limit: Int! = 50 limit: Int! = 100
requiredTags: [String!] = null requiredTags: [String!] = null
): RunLeaderboardGQL! ): RunLeaderboardGQL!
getMakesLeaderboard( getMakesLeaderboard(
@@ -51,7 +49,6 @@ type Query {
limit: Int! = 500 limit: Int! = 500
countRespectsLimit: Boolean! = false countRespectsLimit: Boolean! = false
): GetRunsResult! ): GetRunsResult!
videoPlayerClusters(videoId: Int!): [PlayerClusterGQL!]!
getShotAnnotationTypes(errorTypes: Boolean = false): [ShotAnnotationTypeGQL!]! getShotAnnotationTypes(errorTypes: Boolean = false): [ShotAnnotationTypeGQL!]!
getTableState( getTableState(
b64Image: String! b64Image: String!
@@ -109,7 +106,6 @@ type Query {
filters: VideoFilterInput = null filters: VideoFilterInput = null
): VideoHistoryGQL! ): VideoHistoryGQL!
getUserTags(includeRetiredTags: Boolean = false): [TagGQL!]! getUserTags(includeRetiredTags: Boolean = false): [TagGQL!]!
getGameTypeTagMetrics(input: GameTypeTagMetricsInput!): [GameTypeTagMetric!]!
getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL! getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL!
getVideos(videoIds: [Int!]!): [VideoGQL!]! getVideos(videoIds: [Int!]!): [VideoGQL!]!
} }
@@ -408,7 +404,6 @@ type VideoGQL {
currentProcessing: VideoProcessingGQL currentProcessing: VideoProcessingGQL
reactions: [ReactionGQL!]! reactions: [ReactionGQL!]!
comments: [CommentGQL!]! comments: [CommentGQL!]!
playerSummaries: [PlayerSummaryGQL!]!
} }
type ShotGQL { type ShotGQL {
@@ -611,8 +606,6 @@ type IntPoint2D {
type VideoProcessingGQL { type VideoProcessingGQL {
id: Int! id: Int!
parentProcessingId: Int
labels: [String!]!
errors: [VideoProcessingErrorGQL!]! errors: [VideoProcessingErrorGQL!]!
status: ProcessingStatusEnum! status: ProcessingStatusEnum!
statuses: [VideoProcessingStatusGQL!]! statuses: [VideoProcessingStatusGQL!]!
@@ -668,63 +661,6 @@ type CommentGQL {
replies: [CommentGQL!]! replies: [CommentGQL!]!
} }
type PlayerSummaryGQL {
clusterId: Int!
userId: Int
username: String
profileImageUri: String
representativeFullFrameUrl: String
totalShots: Int!
totalShotsMade: Int!
makePercentage: Float!
score: Int
longestRun: Int!
averageDifficulty: Float
averageTimeBetweenShots: Float
}
type VenueGQL {
id: Int!
name: String!
latitude: Float
longitude: Float
cameras: [VenueCameraGQL!]!
}
type VenueCameraGQL {
id: Int!
venueId: Int!
tableLabel: String!
enabled: Boolean!
isAvailable: Boolean!
}
type CameraClaimGQL {
id: Int!
cameraId: Int!
userId: Int!
videoId: Int
status: ClaimStatusEnum!
expiresAt: DateTime
endedAt: DateTime
createdAt: DateTime!
}
enum ClaimStatusEnum {
REQUESTED
CODE_ISSUED
SCANNING
SCAN_CONFIRMED
INGESTING
ACTIVE
ENDED_BY_USER
EXPIRED
STREAM_LOST
STREAM_UNREACHABLE
CODE_EXPIRED
RELEASED_INACTIVE
}
type DeployedConfigGQL { type DeployedConfigGQL {
allowNewUsers: Boolean! allowNewUsers: Boolean!
firebase: Boolean! firebase: Boolean!
@@ -732,7 +668,6 @@ type DeployedConfigGQL {
environment: String! environment: String!
minimumAllowedAppVersion: String! minimumAllowedAppVersion: String!
subscriptionGatingEnabled: Boolean! subscriptionGatingEnabled: Boolean!
quotaEnforcementEnabled: Boolean!
bannerMessages: [BannerGQL!]! bannerMessages: [BannerGQL!]!
defaultAndroidRecordingFormat: StreamSegmentTypeEnum! defaultAndroidRecordingFormat: StreamSegmentTypeEnum!
bucketUrl: String! bucketUrl: String!
@@ -922,30 +857,6 @@ input DatetimeOrdering {
startingAt: DateTime = null startingAt: DateTime = null
} }
type PlayerClusterGQL {
videoId: Int!
clusterId: Int!
nShots: Int!
userId: Int
username: String
profileImageUri: String
confirmed: Boolean!
score: Int
shots: [PlayerClusterShotGQL!]!
}
type PlayerClusterShotGQL {
shotId: Int!
bboxX1: Int!
bboxY1: Int!
bboxX2: Int!
bboxY2: Int!
confidence: Float!
isConfirmed: Boolean!
cropUrl: String
fullFrameUrl: String
}
type TableStateGQL { type TableStateGQL {
identifierToPosition: [[Float!]!]! identifierToPosition: [[Float!]!]!
homography: HomographyInfoGQL homography: HomographyInfoGQL
@@ -1026,7 +937,6 @@ type UserRelationship {
type StripeSubscriptionOptionsGQL { type StripeSubscriptionOptionsGQL {
products: [StripeProductGQL!]! products: [StripeProductGQL!]!
trialPeriodDays: Int
} }
type StripeProductGQL { type StripeProductGQL {
@@ -1049,9 +959,6 @@ type StripePriceGQL {
type UserSubscriptionStatusGQL { type UserSubscriptionStatusGQL {
hasActiveSubscription: Boolean! hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum
entitlementStartsAt: DateTime
entitlementEndsAt: DateTime
subscriptionStatus: StripeSubscriptionStatusEnum subscriptionStatus: StripeSubscriptionStatusEnum
currentPeriodStart: DateTime currentPeriodStart: DateTime
currentPeriodEnd: DateTime currentPeriodEnd: DateTime
@@ -1060,13 +967,6 @@ type UserSubscriptionStatusGQL {
stripeSubscriptionId: String stripeSubscriptionId: String
} }
enum EntitlementSourceTypeEnum {
ADMIN
MANUAL
STRIPE
ALPHA_LEGACY
}
enum StripeSubscriptionStatusEnum { enum StripeSubscriptionStatusEnum {
INCOMPLETE INCOMPLETE
INCOMPLETE_EXPIRED INCOMPLETE_EXPIRED
@@ -1085,19 +985,6 @@ type QuotaStatusGQL {
durationUsedSeconds: Float! durationUsedSeconds: Float!
durationLimitSeconds: Int durationLimitSeconds: Int
maxVideoDurationSeconds: Int maxVideoDurationSeconds: Int
importQuotaBuckets: [QuotaBucketStatusGQL!]!
recordingQuotaBuckets: [QuotaBucketStatusGQL!]!
durationRemainingSeconds: Float
canUpload: Boolean!
}
type QuotaBucketStatusGQL {
quotaKey: String!
appliesToUploadKind: String!
periodStart: DateTime!
periodEnd: DateTime!
durationUsedSeconds: Float!
durationLimitSeconds: Int
durationRemainingSeconds: Float durationRemainingSeconds: Float
canUpload: Boolean! canUpload: Boolean!
} }
@@ -1118,25 +1005,6 @@ type TagClassGQL {
name: String! name: String!
} }
type GameTypeTagMetric {
tagName: String!
tagLabel: String!
tableSize: Float
shotCount: Int!
madeShots: Int!
makeRate: Float!
}
input GameTypeTagMetricsInput {
userId: Int!
createdAt: DateRangeFilter = null
maxTags: Int = null
groupByTableSize: Boolean! = true
includeUnknown: Boolean! = true
tagClass: String = "game_type"
includePrivate: IncludePrivateEnum! = MINE
}
""" """
The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf).
""" """
@@ -1173,9 +1041,6 @@ type Mutation {
submitChallengeEntry(entryId: ID!, videoId: ID!): ChallengeEntry! submitChallengeEntry(entryId: ID!, videoId: ID!): ChallengeEntry!
dismissChallenge(challengeId: ID!): Boolean! dismissChallenge(challengeId: ID!): Boolean!
undismissChallenge(challengeId: ID!): Boolean! undismissChallenge(challengeId: ID!): Boolean!
claimCamera(cameraId: Int!, durationMinutes: Int! = 60): CameraClaimGQL!
endClaim(claimId: Int!): CameraClaimGQL!
extendClaim(claimId: Int!, additionalMinutes: Int! = 60): CameraClaimGQL!
setLoggerLevel(path: String!, level: String!): Boolean! setLoggerLevel(path: String!, level: String!): Boolean!
reactToVideo(videoId: Int!, reaction: ReactionEnum): Boolean! reactToVideo(videoId: Int!, reaction: ReactionEnum): Boolean!
commentOnVideo( commentOnVideo(
@@ -1196,9 +1061,6 @@ type Mutation {
markAllNotificationsAsRead: Boolean! markAllNotificationsAsRead: Boolean!
markNotificationsAsRead(notificationIds: [Int!]!): Boolean! markNotificationsAsRead(notificationIds: [Int!]!): Boolean!
deleteNotification(notificationId: Int!): Boolean! deleteNotification(notificationId: Int!): Boolean!
finalizePlayerAssignments(
input: FinalizePlayerAssignmentsInput!
): [PlayerClusterGQL!]!
addAnnotationToShot( addAnnotationToShot(
shotId: Int! shotId: Int!
annotationName: String! annotationName: String!
@@ -1223,16 +1085,7 @@ type Mutation {
ensureStripeCustomerExists: UserGQL! ensureStripeCustomerExists: UserGQL!
deleteUser: Boolean! deleteUser: Boolean!
createSubscription(priceId: String!): CreateSubscriptionResultGQL! createSubscription(priceId: String!): CreateSubscriptionResultGQL!
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL! cancelSubscription: UserSubscriptionStatusGQL!
grantManualEntitlement(
userId: Int!
tierName: String! = "pro"
startsAt: DateTime = null
endsAt: DateTime = null
reason: String = null
): UserSubscriptionStatusGQL!
revokeManualEntitlement(userId: Int!): UserSubscriptionStatusGQL!
submitCancellationFeedback( submitCancellationFeedback(
reasons: [CancellationReasonEnum!] = null reasons: [CancellationReasonEnum!] = null
feedback: String = null feedback: String = null
@@ -1270,23 +1123,6 @@ enum ReportReasonEnum {
OTHER OTHER
} }
input FinalizePlayerAssignmentsInput {
videoId: Int!
clusterAssignments: [ClusterAssignmentInput!]! = []
shotMoves: [ShotMoveInput!]! = []
}
input ClusterAssignmentInput {
clusterId: Int!
userId: Int = null
score: Int = null
}
input ShotMoveInput {
shotId: Int!
newClusterId: Int!
}
type AddShotAnnotationReturn { type AddShotAnnotationReturn {
value: SuccessfulAddAddShotAnnotationErrors! value: SuccessfulAddAddShotAnnotationErrors!
} }
@@ -1380,10 +1216,6 @@ type CreateSubscriptionResultGQL {
sessionId: String! sessionId: String!
} }
type CreateCustomerPortalSessionResultGQL {
portalUrl: String!
}
enum CancellationReasonEnum { enum CancellationReasonEnum {
DONT_PLAY_ENOUGH DONT_PLAY_ENOUGH
TOO_EXPENSIVE TOO_EXPENSIVE