Teal.fm frontend powered by slices.network tealfm-slices.wisp.place
tealfm slices

add daily, weekly, monthly tops

+329 -55
schema.graphql
···
joinedViaStarterPack: JSON
labels: JSON
pinnedPost: JSON
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyActorProfileAggregated {
···
cursor: String!
}
type AppBskyEmbedExternal {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
external: JSON!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyEmbedExternalAggregated {
···
cursor: String!
}
type AppBskyEmbedImages {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
images: JSON!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyEmbedImagesAggregated {
···
cursor: String!
}
type AppBskyEmbedRecord {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
record: JSON!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyEmbedRecordAggregated {
···
cursor: String!
}
type AppBskyEmbedRecordWithMedia {
uri: String!
cid: String!
···
actorHandle: String
media: JSON!
record: JSON!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyEmbedRecordWithMediaAggregated {
···
cursor: String!
}
type AppBskyEmbedVideo {
uri: String!
cid: String!
···
aspectRatio: JSON
captions: JSON
video: Blob!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyEmbedVideoAggregated {
···
cursor: String!
}
type AppBskyFeedPostgate {
uri: String!
cid: String!
···
detachedEmbeddingUris: [String]
embeddingRules: JSON
post: String!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyFeedPostgateAggregated {
···
cursor: String!
}
type AppBskyFeedThreadgate {
uri: String!
cid: String!
···
createdAt: String!
hiddenReplies: [String]
post: String!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyFeedThreadgateAggregated {
···
type AppBskyFeedThreadgateEdge {
node: AppBskyFeedThreadgate!
cursor: String!
}
type AppBskyRichtextFacet {
···
actorHandle: String
features: JSON!
index: JSON!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type AppBskyRichtextFacetAggregated {
···
type AppBskyRichtextFacetEdge {
node: AppBskyRichtextFacet!
cursor: String!
}
type Blob {
···
actorHandle: String
cid: String!
uri: String!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type ComAtprotoRepoStrongRefAggregated {
···
cursor: String!
}
type FmTealAlphaFeedPlay {
uri: String!
cid: String!
···
submissionClientAgent: String
trackMbId: String
trackName: String!
-
appBskyFeedPostgate(limit: Int): [AppBskyFeedPostgate!]!
-
appBskyFeedThreadgate(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfile: AppBskyActorProfile
-
fmTealAlphaFeedPlay(limit: Int): [FmTealAlphaFeedPlay!]!
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
}
type FmTealAlphaFeedPlayAggregated {
···
cursor: String!
}
scalar JSON
type Mutation {
···
type Query {
"""Query app.bsky.embed.record records"""
-
appBskyEmbedRecords(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyEmbedRecordConnection!
"""
Aggregated query for app.bsky.embed.record records with GROUP BY support
"""
-
appBskyEmbedRecordsAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordAggregated!]!
"""Query app.bsky.embed.images records"""
-
appBskyEmbedImageses(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyEmbedImagesConnection!
"""
Aggregated query for app.bsky.embed.images records with GROUP BY support
"""
-
appBskyEmbedImagesesAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedImagesAggregated!]!
"""Query app.bsky.embed.video records"""
-
appBskyEmbedVideos(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyEmbedVideoConnection!
"""
Aggregated query for app.bsky.embed.video records with GROUP BY support
"""
-
appBskyEmbedVideosAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedVideoAggregated!]!
"""Query app.bsky.embed.recordWithMedia records"""
-
appBskyEmbedRecordWithMedias(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyEmbedRecordWithMediaConnection!
"""
Aggregated query for app.bsky.embed.recordWithMedia records with GROUP BY support
"""
-
appBskyEmbedRecordWithMediasAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordWithMediaAggregated!]!
"""Query app.bsky.embed.external records"""
-
appBskyEmbedExternals(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyEmbedExternalConnection!
"""
Aggregated query for app.bsky.embed.external records with GROUP BY support
"""
-
appBskyEmbedExternalsAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedExternalAggregated!]!
"""Query app.bsky.feed.postgate records"""
-
appBskyFeedPostgates(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyFeedPostgateConnection!
"""
Aggregated query for app.bsky.feed.postgate records with GROUP BY support
"""
-
appBskyFeedPostgatesAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedPostgateAggregated!]!
"""Query app.bsky.feed.threadgate records"""
-
appBskyFeedThreadgates(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyFeedThreadgateConnection!
"""
Aggregated query for app.bsky.feed.threadgate records with GROUP BY support
"""
-
appBskyFeedThreadgatesAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedThreadgateAggregated!]!
"""Query app.bsky.richtext.facet records"""
-
appBskyRichtextFacets(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyRichtextFacetConnection!
"""
Aggregated query for app.bsky.richtext.facet records with GROUP BY support
"""
-
appBskyRichtextFacetsAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyRichtextFacetAggregated!]!
"""Query app.bsky.actor.profile records"""
-
appBskyActorProfiles(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): AppBskyActorProfileConnection!
"""
Aggregated query for app.bsky.actor.profile records with GROUP BY support
"""
-
appBskyActorProfilesAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [AppBskyActorProfileAggregated!]!
"""Query com.atproto.repo.strongRef records"""
-
comAtprotoRepoStrongRefs(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): ComAtprotoRepoStrongRefConnection!
"""
Aggregated query for com.atproto.repo.strongRef records with GROUP BY support
"""
-
comAtprotoRepoStrongRefsAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [ComAtprotoRepoStrongRefAggregated!]!
"""Query fm.teal.alpha.feed.play records"""
-
fmTealAlphaFeedPlays(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: JSON): FmTealAlphaFeedPlayConnection!
"""
Aggregated query for fm.teal.alpha.feed.play records with GROUP BY support
"""
-
fmTealAlphaFeedPlaysAggregated(groupBy: [String!]!, where: JSON, orderBy: AggregationOrderBy, limit: Int): [FmTealAlphaFeedPlayAggregated!]!
}
enum SortDirection {
···
input SortField {
field: String!
direction: SortDirection!
}
type Subscription {
···
joinedViaStarterPack: JSON
labels: JSON
pinnedPost: JSON
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyActorProfileAggregated {
···
cursor: String!
}
+
enum AppBskyActorProfileGroupByField {
+
indexedAt
+
avatar
+
banner
+
createdAt
+
description
+
displayName
+
joinedViaStarterPack
+
labels
+
pinnedPost
+
}
+
+
input AppBskyActorProfileWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
avatar: StringFilter
+
banner: StringFilter
+
createdAt: StringFilter
+
description: StringFilter
+
displayName: StringFilter
+
joinedViaStarterPack: StringFilter
+
labels: StringFilter
+
pinnedPost: StringFilter
+
}
+
type AppBskyEmbedExternal {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
external: JSON!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyEmbedExternalAggregated {
···
cursor: String!
}
+
enum AppBskyEmbedExternalGroupByField {
+
indexedAt
+
external
+
}
+
+
input AppBskyEmbedExternalWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
external: StringFilter
+
}
+
type AppBskyEmbedImages {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
images: JSON!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyEmbedImagesAggregated {
···
cursor: String!
}
+
enum AppBskyEmbedImagesGroupByField {
+
indexedAt
+
images
+
}
+
+
input AppBskyEmbedImagesWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
images: StringFilter
+
}
+
type AppBskyEmbedRecord {
uri: String!
cid: String!
···
indexedAt: String!
actorHandle: String
record: JSON!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyEmbedRecordAggregated {
···
cursor: String!
}
+
enum AppBskyEmbedRecordGroupByField {
+
indexedAt
+
record
+
}
+
+
input AppBskyEmbedRecordWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
record: StringFilter
+
}
+
type AppBskyEmbedRecordWithMedia {
uri: String!
cid: String!
···
actorHandle: String
media: JSON!
record: JSON!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyEmbedRecordWithMediaAggregated {
···
cursor: String!
}
+
enum AppBskyEmbedRecordWithMediaGroupByField {
+
indexedAt
+
media
+
record
+
}
+
+
input AppBskyEmbedRecordWithMediaWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
media: StringFilter
+
record: StringFilter
+
}
+
type AppBskyEmbedVideo {
uri: String!
cid: String!
···
aspectRatio: JSON
captions: JSON
video: Blob!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyEmbedVideoAggregated {
···
cursor: String!
}
+
enum AppBskyEmbedVideoGroupByField {
+
indexedAt
+
alt
+
aspectRatio
+
captions
+
video
+
}
+
+
input AppBskyEmbedVideoWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
alt: StringFilter
+
aspectRatio: StringFilter
+
captions: StringFilter
+
video: StringFilter
+
}
+
type AppBskyFeedPostgate {
uri: String!
cid: String!
···
detachedEmbeddingUris: [String]
embeddingRules: JSON
post: String!
+
appBskyFeedPostgate: AppBskyFeedPostgate
+
appBskyFeedThreadgate: AppBskyFeedThreadgate
appBskyActorProfile: AppBskyActorProfile
+
fmTealAlphaFeedPlay: FmTealAlphaFeedPlay
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyFeedPostgateAggregated {
···
cursor: String!
}
+
enum AppBskyFeedPostgateGroupByField {
+
indexedAt
+
createdAt
+
detachedEmbeddingUris
+
embeddingRules
+
post
+
}
+
+
input AppBskyFeedPostgateWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
createdAt: StringFilter
+
detachedEmbeddingUris: StringFilter
+
embeddingRules: StringFilter
+
post: StringFilter
+
}
+
type AppBskyFeedThreadgate {
uri: String!
cid: String!
···
createdAt: String!
hiddenReplies: [String]
post: String!
+
appBskyFeedPostgate: AppBskyFeedPostgate
+
appBskyFeedThreadgate: AppBskyFeedThreadgate
appBskyActorProfile: AppBskyActorProfile
+
fmTealAlphaFeedPlay: FmTealAlphaFeedPlay
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyFeedThreadgateAggregated {
···
type AppBskyFeedThreadgateEdge {
node: AppBskyFeedThreadgate!
cursor: String!
+
}
+
+
enum AppBskyFeedThreadgateGroupByField {
+
indexedAt
+
allow
+
createdAt
+
hiddenReplies
+
post
+
}
+
+
input AppBskyFeedThreadgateWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
allow: StringFilter
+
createdAt: StringFilter
+
hiddenReplies: StringFilter
+
post: StringFilter
}
type AppBskyRichtextFacet {
···
actorHandle: String
features: JSON!
index: JSON!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type AppBskyRichtextFacetAggregated {
···
type AppBskyRichtextFacetEdge {
node: AppBskyRichtextFacet!
cursor: String!
+
}
+
+
enum AppBskyRichtextFacetGroupByField {
+
indexedAt
+
features
+
index
+
}
+
+
input AppBskyRichtextFacetWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
features: StringFilter
+
index: StringFilter
}
type Blob {
···
actorHandle: String
cid: String!
uri: String!
+
appBskyFeedPostgate: AppBskyFeedPostgate
+
appBskyFeedThreadgate: AppBskyFeedThreadgate
appBskyActorProfile: AppBskyActorProfile
+
fmTealAlphaFeedPlay: FmTealAlphaFeedPlay
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type ComAtprotoRepoStrongRefAggregated {
···
cursor: String!
}
+
enum ComAtprotoRepoStrongRefGroupByField {
+
indexedAt
+
cid
+
uri
+
}
+
+
input ComAtprotoRepoStrongRefWhereInput {
+
indexedAt: DateTimeFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
cid: StringFilter
+
uri: StringFilter
+
}
+
+
input DateTimeFilter {
+
eq: String
+
gt: String
+
gte: String
+
lt: String
+
lte: String
+
}
+
type FmTealAlphaFeedPlay {
uri: String!
cid: String!
···
submissionClientAgent: String
trackMbId: String
trackName: String!
appBskyActorProfile: AppBskyActorProfile
appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]!
+
appBskyFeedPostgatesCount: Int!
appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]!
+
appBskyFeedThreadgatesCount: Int!
appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]!
+
appBskyActorProfilesCount: Int!
fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]!
+
fmTealAlphaFeedPlaysCount: Int!
}
type FmTealAlphaFeedPlayAggregated {
···
cursor: String!
}
+
enum FmTealAlphaFeedPlayGroupByField {
+
indexedAt
+
artistMbIds
+
artistNames
+
artists
+
duration
+
isrc
+
musicServiceBaseDomain
+
originUrl
+
playedTime
+
recordingMbId
+
releaseMbId
+
releaseName
+
submissionClientAgent
+
trackMbId
+
trackName
+
}
+
+
input FmTealAlphaFeedPlayWhereInput {
+
indexedAt: DateTimeFilter
+
uri: StringFilter
+
cid: StringFilter
+
did: StringFilter
+
collection: StringFilter
+
actorHandle: StringFilter
+
artistMbIds: StringFilter
+
artistNames: StringFilter
+
artists: StringFilter
+
duration: IntFilter
+
isrc: StringFilter
+
musicServiceBaseDomain: StringFilter
+
originUrl: StringFilter
+
playedTime: StringFilter
+
recordingMbId: StringFilter
+
releaseMbId: StringFilter
+
releaseName: StringFilter
+
submissionClientAgent: StringFilter
+
trackMbId: StringFilter
+
trackName: StringFilter
+
}
+
+
input IntFilter {
+
eq: Int
+
in: [Int]
+
gt: Int
+
gte: Int
+
lt: Int
+
lte: Int
+
}
+
scalar JSON
type Mutation {
···
type Query {
"""Query app.bsky.embed.record records"""
+
appBskyEmbedRecords(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyEmbedRecordWhereInput): AppBskyEmbedRecordConnection!
"""
Aggregated query for app.bsky.embed.record records with GROUP BY support
"""
+
appBskyEmbedRecordsAggregated(groupBy: [AppBskyEmbedRecordGroupByField!], where: AppBskyEmbedRecordWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordAggregated!]!
"""Query app.bsky.embed.images records"""
+
appBskyEmbedImageses(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyEmbedImagesWhereInput): AppBskyEmbedImagesConnection!
"""
Aggregated query for app.bsky.embed.images records with GROUP BY support
"""
+
appBskyEmbedImagesesAggregated(groupBy: [AppBskyEmbedImagesGroupByField!], where: AppBskyEmbedImagesWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedImagesAggregated!]!
"""Query app.bsky.embed.video records"""
+
appBskyEmbedVideos(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyEmbedVideoWhereInput): AppBskyEmbedVideoConnection!
"""
Aggregated query for app.bsky.embed.video records with GROUP BY support
"""
+
appBskyEmbedVideosAggregated(groupBy: [AppBskyEmbedVideoGroupByField!], where: AppBskyEmbedVideoWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedVideoAggregated!]!
"""Query app.bsky.embed.recordWithMedia records"""
+
appBskyEmbedRecordWithMedias(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyEmbedRecordWithMediaWhereInput): AppBskyEmbedRecordWithMediaConnection!
"""
Aggregated query for app.bsky.embed.recordWithMedia records with GROUP BY support
"""
+
appBskyEmbedRecordWithMediasAggregated(groupBy: [AppBskyEmbedRecordWithMediaGroupByField!], where: AppBskyEmbedRecordWithMediaWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordWithMediaAggregated!]!
"""Query app.bsky.embed.external records"""
+
appBskyEmbedExternals(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyEmbedExternalWhereInput): AppBskyEmbedExternalConnection!
"""
Aggregated query for app.bsky.embed.external records with GROUP BY support
"""
+
appBskyEmbedExternalsAggregated(groupBy: [AppBskyEmbedExternalGroupByField!], where: AppBskyEmbedExternalWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedExternalAggregated!]!
"""Query app.bsky.feed.postgate records"""
+
appBskyFeedPostgates(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyFeedPostgateWhereInput): AppBskyFeedPostgateConnection!
"""
Aggregated query for app.bsky.feed.postgate records with GROUP BY support
"""
+
appBskyFeedPostgatesAggregated(groupBy: [AppBskyFeedPostgateGroupByField!], where: AppBskyFeedPostgateWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedPostgateAggregated!]!
"""Query app.bsky.feed.threadgate records"""
+
appBskyFeedThreadgates(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyFeedThreadgateWhereInput): AppBskyFeedThreadgateConnection!
"""
Aggregated query for app.bsky.feed.threadgate records with GROUP BY support
"""
+
appBskyFeedThreadgatesAggregated(groupBy: [AppBskyFeedThreadgateGroupByField!], where: AppBskyFeedThreadgateWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedThreadgateAggregated!]!
"""Query app.bsky.richtext.facet records"""
+
appBskyRichtextFacets(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyRichtextFacetWhereInput): AppBskyRichtextFacetConnection!
"""
Aggregated query for app.bsky.richtext.facet records with GROUP BY support
"""
+
appBskyRichtextFacetsAggregated(groupBy: [AppBskyRichtextFacetGroupByField!], where: AppBskyRichtextFacetWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyRichtextFacetAggregated!]!
"""Query app.bsky.actor.profile records"""
+
appBskyActorProfiles(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: AppBskyActorProfileWhereInput): AppBskyActorProfileConnection!
"""
Aggregated query for app.bsky.actor.profile records with GROUP BY support
"""
+
appBskyActorProfilesAggregated(groupBy: [AppBskyActorProfileGroupByField!], where: AppBskyActorProfileWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyActorProfileAggregated!]!
"""Query com.atproto.repo.strongRef records"""
+
comAtprotoRepoStrongRefs(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: ComAtprotoRepoStrongRefWhereInput): ComAtprotoRepoStrongRefConnection!
"""
Aggregated query for com.atproto.repo.strongRef records with GROUP BY support
"""
+
comAtprotoRepoStrongRefsAggregated(groupBy: [ComAtprotoRepoStrongRefGroupByField!], where: ComAtprotoRepoStrongRefWhereInput, orderBy: AggregationOrderBy, limit: Int): [ComAtprotoRepoStrongRefAggregated!]!
"""Query fm.teal.alpha.feed.play records"""
+
fmTealAlphaFeedPlays(first: Int, after: String, last: Int, before: String, sortBy: [SortField], where: FmTealAlphaFeedPlayWhereInput): FmTealAlphaFeedPlayConnection!
"""
Aggregated query for fm.teal.alpha.feed.play records with GROUP BY support
"""
+
fmTealAlphaFeedPlaysAggregated(groupBy: [FmTealAlphaFeedPlayGroupByField!], where: FmTealAlphaFeedPlayWhereInput, orderBy: AggregationOrderBy, limit: Int): [FmTealAlphaFeedPlayAggregated!]!
}
enum SortDirection {
···
input SortField {
field: String!
direction: SortDirection!
+
}
+
+
input StringFilter {
+
eq: String
+
in: [String]
+
contains: String
+
gt: String
+
gte: String
+
lt: String
+
lte: String
}
type Subscription {
+115 -19
src/Layout.tsx
···
export default function Layout({ children }: LayoutProps) {
const location = useLocation();
return (
<div className="min-h-screen bg-zinc-950 text-zinc-300 font-mono">
<div className="max-w-4xl mx-auto px-6 py-12">
-
<div className="mb-12 flex items-end justify-between border-b border-zinc-800 pb-6">
-
<div>
-
<h1 className="text-xs font-medium uppercase tracking-wider text-zinc-500">Listening History</h1>
-
<p className="text-xs text-zinc-600 mt-1">fm.teal.alpha.feed.play</p>
</div>
-
<div className="flex gap-4 text-xs">
<Link
-
to="/"
className={`px-2 py-1 transition-colors ${
-
location.pathname === "/"
-
? "text-zinc-400"
-
: "text-zinc-500 hover:text-zinc-300"
}`}
>
-
Recent
</Link>
<Link
-
to="/tracks"
className={`px-2 py-1 transition-colors ${
-
location.pathname === "/tracks"
-
? "text-zinc-400"
-
: "text-zinc-500 hover:text-zinc-300"
}`}
>
-
Top Tracks
</Link>
<Link
to="/albums"
className={`px-2 py-1 transition-colors ${
location.pathname === "/albums"
-
? "text-zinc-400"
-
: "text-zinc-500 hover:text-zinc-300"
}`}
>
-
Top Albums
</Link>
</div>
-
</div>
{children}
</div>
···
export default function Layout({ children }: LayoutProps) {
const location = useLocation();
+
const isTracksPage = location.pathname.startsWith("/tracks");
+
const isAlbumsPage = location.pathname.startsWith("/albums");
return (
<div className="min-h-screen bg-zinc-950 text-zinc-300 font-mono">
<div className="max-w-4xl mx-auto px-6 py-12">
+
<div className="mb-4 border-b border-zinc-800 pb-4">
+
<div className="flex items-end justify-between">
+
<div>
+
<h1 className="text-xs font-medium uppercase tracking-wider text-zinc-500">Listening History</h1>
+
<p className="text-xs text-zinc-600 mt-1">fm.teal.alpha.feed.play</p>
+
</div>
+
+
<div className="flex gap-4 text-xs">
+
<Link
+
to="/"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/"
+
? "text-zinc-400"
+
: "text-zinc-500 hover:text-zinc-300"
+
}`}
+
>
+
Recent
+
</Link>
+
<Link
+
to="/tracks"
+
className={`px-2 py-1 transition-colors ${
+
isTracksPage
+
? "text-zinc-400"
+
: "text-zinc-500 hover:text-zinc-300"
+
}`}
+
>
+
Top Tracks
+
</Link>
+
<Link
+
to="/albums"
+
className={`px-2 py-1 transition-colors ${
+
isAlbumsPage
+
? "text-zinc-400"
+
: "text-zinc-500 hover:text-zinc-300"
+
}`}
+
>
+
Top Albums
+
</Link>
+
</div>
</div>
+
</div>
+
{isTracksPage && (
+
<div className="flex gap-3 text-xs mb-8 pb-4 border-b border-zinc-800">
<Link
+
to="/tracks"
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/tracks"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
}`}
>
+
All Time
</Link>
<Link
+
to="/tracks/daily"
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/tracks/daily"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
}`}
>
+
Daily
+
</Link>
+
<Link
+
to="/tracks/weekly"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/tracks/weekly"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
+
}`}
+
>
+
Weekly
</Link>
<Link
+
to="/tracks/monthly"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/tracks/monthly"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
+
}`}
+
>
+
Monthly
+
</Link>
+
</div>
+
)}
+
+
{isAlbumsPage && (
+
<div className="flex gap-3 text-xs mb-8 pb-4 border-b border-zinc-800">
+
<Link
to="/albums"
className={`px-2 py-1 transition-colors ${
location.pathname === "/albums"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
+
}`}
+
>
+
All Time
+
</Link>
+
<Link
+
to="/albums/daily"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/albums/daily"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
+
}`}
+
>
+
Daily
+
</Link>
+
<Link
+
to="/albums/weekly"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/albums/weekly"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
+
}`}
+
>
+
Weekly
+
</Link>
+
<Link
+
to="/albums/monthly"
+
className={`px-2 py-1 transition-colors ${
+
location.pathname === "/albums/monthly"
+
? "text-zinc-300"
+
: "text-zinc-600 hover:text-zinc-400"
}`}
>
+
Monthly
</Link>
</div>
+
)}
+
+
{!isTracksPage && !isAlbumsPage && <div className="mb-8"></div>}
{children}
</div>
+2 -2
src/Profile.tsx
···
const queryData = useLazyLoadQuery<ProfileQueryType>(
graphql`
-
query ProfileQuery($where: JSON!) {
...Profile_plays @arguments(where: $where)
}
`,
···
@argumentDefinitions(
cursor: { type: "String" }
count: { type: "Int", defaultValue: 20 }
-
where: { type: "JSON!" }
) {
fmTealAlphaFeedPlays(
first: $count
···
const queryData = useLazyLoadQuery<ProfileQueryType>(
graphql`
+
query ProfileQuery($where: FmTealAlphaFeedPlayWhereInput!) {
...Profile_plays @arguments(where: $where)
}
`,
···
@argumentDefinitions(
cursor: { type: "String" }
count: { type: "Int", defaultValue: 20 }
+
where: { type: "FmTealAlphaFeedPlayWhereInput!" }
) {
fmTealAlphaFeedPlays(
first: $count
+10 -3
src/TopAlbums.tsx
···
import { graphql, useLazyLoadQuery } from "react-relay";
import type { TopAlbumsQuery } from "./__generated__/TopAlbumsQuery.graphql";
import AlbumItem from "./AlbumItem";
import Layout from "./Layout";
export default function TopAlbums() {
const data = useLazyLoadQuery<TopAlbumsQuery>(
graphql`
-
query TopAlbumsQuery {
fmTealAlphaFeedPlaysAggregated(
-
groupBy: ["releaseMbId", "releaseName", "artists"]
orderBy: { count: desc }
limit: 100
) {
releaseMbId
releaseName
···
}
}
`,
-
{}
);
const albums = [...(data.fmTealAlphaFeedPlaysAggregated || [])];
···
import { graphql, useLazyLoadQuery } from "react-relay";
+
import { useParams } from "react-router-dom";
import type { TopAlbumsQuery } from "./__generated__/TopAlbumsQuery.graphql";
import AlbumItem from "./AlbumItem";
import Layout from "./Layout";
+
import { useDateRangeFilter } from "./useDateRangeFilter";
export default function TopAlbums() {
+
const { period } = useParams<{ period?: string }>();
+
const queryVariables = useDateRangeFilter(period);
+
const data = useLazyLoadQuery<TopAlbumsQuery>(
graphql`
+
query TopAlbumsQuery($where: FmTealAlphaFeedPlayWhereInput) {
fmTealAlphaFeedPlaysAggregated(
+
groupBy: [releaseMbId, releaseName, artists]
orderBy: { count: desc }
limit: 100
+
where: $where
) {
releaseMbId
releaseName
···
}
}
`,
+
queryVariables,
+
{ fetchKey: period || "all", fetchPolicy: "store-or-network" }
);
const albums = [...(data.fmTealAlphaFeedPlaysAggregated || [])];
+10 -3
src/TopTracks.tsx
···
import { graphql, useLazyLoadQuery } from "react-relay";
import type { TopTracksQuery } from "./__generated__/TopTracksQuery.graphql";
import TopTrackItem from "./TopTrackItem";
import Layout from "./Layout";
export default function TopTracks() {
const data = useLazyLoadQuery<TopTracksQuery>(
graphql`
-
query TopTracksQuery {
fmTealAlphaFeedPlaysAggregated(
-
groupBy: ["trackName", "releaseMbId", "artists"]
orderBy: { count: desc }
limit: 50
) {
trackName
releaseMbId
···
}
}
`,
-
{}
);
const tracks = data.fmTealAlphaFeedPlaysAggregated || [];
···
import { graphql, useLazyLoadQuery } from "react-relay";
+
import { useParams } from "react-router-dom";
import type { TopTracksQuery } from "./__generated__/TopTracksQuery.graphql";
import TopTrackItem from "./TopTrackItem";
import Layout from "./Layout";
+
import { useDateRangeFilter } from "./useDateRangeFilter";
export default function TopTracks() {
+
const { period } = useParams<{ period?: string }>();
+
const queryVariables = useDateRangeFilter(period);
+
const data = useLazyLoadQuery<TopTracksQuery>(
graphql`
+
query TopTracksQuery($where: FmTealAlphaFeedPlayWhereInput) {
fmTealAlphaFeedPlaysAggregated(
+
groupBy: [trackName, releaseMbId, artists]
orderBy: { count: desc }
limit: 50
+
where: $where
) {
trackName
releaseMbId
···
}
}
`,
+
queryVariables,
+
{ fetchKey: period || "all", fetchPolicy: "store-or-network" }
);
const tracks = data.fmTealAlphaFeedPlaysAggregated || [];
+51 -5
src/__generated__/ProfilePaginationQuery.graphql.ts
···
/**
-
* @generated SignedSource<<a103b609fd81848d14264d18e76ece37>>
* @lightSyntaxTransform
* @nogrep
*/
···
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type ProfilePaginationQuery$variables = {
count?: number | null | undefined;
cursor?: string | null | undefined;
-
where: any;
};
export type ProfilePaginationQuery$data = {
readonly " $fragmentSpreads": FragmentRefs<"Profile_plays">;
···
]
},
"params": {
-
"cacheID": "b6789cc8edc0cedfd5de86eadfba8b9e",
"id": null,
"metadata": {},
"name": "ProfilePaginationQuery",
"operationKind": "query",
-
"text": "query ProfilePaginationQuery(\n $count: Int = 20\n $cursor: String\n $where: JSON!\n) {\n ...Profile_plays_mjR8k\n}\n\nfragment Profile_plays_mjR8k on Query {\n fmTealAlphaFeedPlays(first: $count, after: $cursor, sortBy: [{field: \"playedTime\", direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n }\n}\n"
}
};
})();
-
(node as any).hash = "474168bb0d13417c1b7067c09a82f7a2";
export default node;
···
/**
+
* @generated SignedSource<<9824b6fa6724ec81721b89464e18ee4f>>
* @lightSyntaxTransform
* @nogrep
*/
···
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
+
export type FmTealAlphaFeedPlayWhereInput = {
+
actorHandle?: StringFilter | null | undefined;
+
artistMbIds?: StringFilter | null | undefined;
+
artistNames?: StringFilter | null | undefined;
+
artists?: StringFilter | null | undefined;
+
cid?: StringFilter | null | undefined;
+
collection?: StringFilter | null | undefined;
+
did?: StringFilter | null | undefined;
+
duration?: IntFilter | null | undefined;
+
indexedAt?: DateTimeFilter | null | undefined;
+
isrc?: StringFilter | null | undefined;
+
musicServiceBaseDomain?: StringFilter | null | undefined;
+
originUrl?: StringFilter | null | undefined;
+
playedTime?: StringFilter | null | undefined;
+
recordingMbId?: StringFilter | null | undefined;
+
releaseMbId?: StringFilter | null | undefined;
+
releaseName?: StringFilter | null | undefined;
+
submissionClientAgent?: StringFilter | null | undefined;
+
trackMbId?: StringFilter | null | undefined;
+
trackName?: StringFilter | null | undefined;
+
uri?: StringFilter | null | undefined;
+
};
+
export type DateTimeFilter = {
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type StringFilter = {
+
contains?: string | null | undefined;
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
in?: ReadonlyArray<string | null | undefined> | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type IntFilter = {
+
eq?: number | null | undefined;
+
gt?: number | null | undefined;
+
gte?: number | null | undefined;
+
in?: ReadonlyArray<number | null | undefined> | null | undefined;
+
lt?: number | null | undefined;
+
lte?: number | null | undefined;
+
};
export type ProfilePaginationQuery$variables = {
count?: number | null | undefined;
cursor?: string | null | undefined;
+
where: FmTealAlphaFeedPlayWhereInput;
};
export type ProfilePaginationQuery$data = {
readonly " $fragmentSpreads": FragmentRefs<"Profile_plays">;
···
]
},
"params": {
+
"cacheID": "6d52a3e02fe71c3ad54ec2006fc2ac45",
"id": null,
"metadata": {},
"name": "ProfilePaginationQuery",
"operationKind": "query",
+
"text": "query ProfilePaginationQuery(\n $count: Int = 20\n $cursor: String\n $where: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_mjR8k\n}\n\nfragment Profile_plays_mjR8k on Query {\n fmTealAlphaFeedPlays(first: $count, after: $cursor, sortBy: [{field: \"playedTime\", direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n }\n}\n"
}
};
})();
+
(node as any).hash = "86bf47e8cb24c938b0b5d7ad6f5cb916";
export default node;
+51 -5
src/__generated__/ProfileQuery.graphql.ts
···
/**
-
* @generated SignedSource<<706478869815c293b78f1ace532431f2>>
* @lightSyntaxTransform
* @nogrep
*/
···
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type ProfileQuery$variables = {
-
where: any;
};
export type ProfileQuery$data = {
readonly " $fragmentSpreads": FragmentRefs<"Profile_plays">;
···
]
},
"params": {
-
"cacheID": "f6cf8b245658eb5d028de7fafcc457c9",
"id": null,
"metadata": {},
"name": "ProfileQuery",
"operationKind": "query",
-
"text": "query ProfileQuery(\n $where: JSON!\n) {\n ...Profile_plays_3FC4Qo\n}\n\nfragment Profile_plays_3FC4Qo on Query {\n fmTealAlphaFeedPlays(first: 20, sortBy: [{field: \"playedTime\", direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n }\n}\n"
}
};
})();
-
(node as any).hash = "267039e382b3b95a739ff3cdced3211e";
export default node;
···
/**
+
* @generated SignedSource<<0920331f4eccd3551cbc3ca8646596f0>>
* @lightSyntaxTransform
* @nogrep
*/
···
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
+
export type FmTealAlphaFeedPlayWhereInput = {
+
actorHandle?: StringFilter | null | undefined;
+
artistMbIds?: StringFilter | null | undefined;
+
artistNames?: StringFilter | null | undefined;
+
artists?: StringFilter | null | undefined;
+
cid?: StringFilter | null | undefined;
+
collection?: StringFilter | null | undefined;
+
did?: StringFilter | null | undefined;
+
duration?: IntFilter | null | undefined;
+
indexedAt?: DateTimeFilter | null | undefined;
+
isrc?: StringFilter | null | undefined;
+
musicServiceBaseDomain?: StringFilter | null | undefined;
+
originUrl?: StringFilter | null | undefined;
+
playedTime?: StringFilter | null | undefined;
+
recordingMbId?: StringFilter | null | undefined;
+
releaseMbId?: StringFilter | null | undefined;
+
releaseName?: StringFilter | null | undefined;
+
submissionClientAgent?: StringFilter | null | undefined;
+
trackMbId?: StringFilter | null | undefined;
+
trackName?: StringFilter | null | undefined;
+
uri?: StringFilter | null | undefined;
+
};
+
export type DateTimeFilter = {
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type StringFilter = {
+
contains?: string | null | undefined;
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
in?: ReadonlyArray<string | null | undefined> | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type IntFilter = {
+
eq?: number | null | undefined;
+
gt?: number | null | undefined;
+
gte?: number | null | undefined;
+
in?: ReadonlyArray<number | null | undefined> | null | undefined;
+
lt?: number | null | undefined;
+
lte?: number | null | undefined;
+
};
export type ProfileQuery$variables = {
+
where: FmTealAlphaFeedPlayWhereInput;
};
export type ProfileQuery$data = {
readonly " $fragmentSpreads": FragmentRefs<"Profile_plays">;
···
]
},
"params": {
+
"cacheID": "0592d86db07d88ab11657ea4cd107231",
"id": null,
"metadata": {},
"name": "ProfileQuery",
"operationKind": "query",
+
"text": "query ProfileQuery(\n $where: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_3FC4Qo\n}\n\nfragment Profile_plays_3FC4Qo on Query {\n fmTealAlphaFeedPlays(first: 20, sortBy: [{field: \"playedTime\", direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n }\n}\n"
}
};
})();
+
(node as any).hash = "4a0ecbad0ab4453246cdcdd753b1f84f";
export default node;
+2 -2
src/__generated__/Profile_plays.graphql.ts
···
/**
-
* @generated SignedSource<<bd63c9e74b05810076b60ad0e51cb230>>
* @lightSyntaxTransform
* @nogrep
*/
···
};
})();
-
(node as any).hash = "474168bb0d13417c1b7067c09a82f7a2";
export default node;
···
/**
+
* @generated SignedSource<<0e69127350e3dc66273c2ea60929dc92>>
* @lightSyntaxTransform
* @nogrep
*/
···
};
})();
+
(node as any).hash = "86bf47e8cb24c938b0b5d7ad6f5cb916";
export default node;
+70 -10
src/__generated__/TopAlbumsQuery.graphql.ts
···
/**
-
* @generated SignedSource<<e2bf0d16ddd996a8b44b47387dd220b3>>
* @lightSyntaxTransform
* @nogrep
*/
···
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
-
export type TopAlbumsQuery$variables = Record<PropertyKey, never>;
export type TopAlbumsQuery$data = {
readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{
readonly artists: any | null | undefined;
···
const node: ConcreteRequest = (function(){
var v0 = [
{
"alias": null,
"args": [
{
···
"value": {
"count": "desc"
}
}
],
"concreteType": "FmTealAlphaFeedPlayAggregated",
···
"storageKey": null
}
],
-
"storageKey": "fmTealAlphaFeedPlaysAggregated(groupBy:[\"releaseMbId\",\"releaseName\",\"artists\"],limit:100,orderBy:{\"count\":\"desc\"})"
}
];
return {
"fragment": {
-
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TopAlbumsQuery",
-
"selections": (v0/*: any*/),
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
-
"argumentDefinitions": [],
"kind": "Operation",
"name": "TopAlbumsQuery",
-
"selections": (v0/*: any*/)
},
"params": {
-
"cacheID": "65b42ff33b8a5de6eb4785e764ae70fc",
"id": null,
"metadata": {},
"name": "TopAlbumsQuery",
"operationKind": "query",
-
"text": "query TopAlbumsQuery {\n fmTealAlphaFeedPlaysAggregated(groupBy: [\"releaseMbId\", \"releaseName\", \"artists\"], orderBy: {count: desc}, limit: 100) {\n releaseMbId\n releaseName\n artists\n count\n }\n}\n"
}
};
})();
-
(node as any).hash = "b5748a3a4af3140d3cff228e7462f73d";
export default node;
···
/**
+
* @generated SignedSource<<8cf8cec6835334168002a2939635c9d5>>
* @lightSyntaxTransform
* @nogrep
*/
···
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
+
export type FmTealAlphaFeedPlayWhereInput = {
+
actorHandle?: StringFilter | null | undefined;
+
artistMbIds?: StringFilter | null | undefined;
+
artistNames?: StringFilter | null | undefined;
+
artists?: StringFilter | null | undefined;
+
cid?: StringFilter | null | undefined;
+
collection?: StringFilter | null | undefined;
+
did?: StringFilter | null | undefined;
+
duration?: IntFilter | null | undefined;
+
indexedAt?: DateTimeFilter | null | undefined;
+
isrc?: StringFilter | null | undefined;
+
musicServiceBaseDomain?: StringFilter | null | undefined;
+
originUrl?: StringFilter | null | undefined;
+
playedTime?: StringFilter | null | undefined;
+
recordingMbId?: StringFilter | null | undefined;
+
releaseMbId?: StringFilter | null | undefined;
+
releaseName?: StringFilter | null | undefined;
+
submissionClientAgent?: StringFilter | null | undefined;
+
trackMbId?: StringFilter | null | undefined;
+
trackName?: StringFilter | null | undefined;
+
uri?: StringFilter | null | undefined;
+
};
+
export type DateTimeFilter = {
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type StringFilter = {
+
contains?: string | null | undefined;
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
in?: ReadonlyArray<string | null | undefined> | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type IntFilter = {
+
eq?: number | null | undefined;
+
gt?: number | null | undefined;
+
gte?: number | null | undefined;
+
in?: ReadonlyArray<number | null | undefined> | null | undefined;
+
lt?: number | null | undefined;
+
lte?: number | null | undefined;
+
};
+
export type TopAlbumsQuery$variables = {
+
where?: FmTealAlphaFeedPlayWhereInput | null | undefined;
+
};
export type TopAlbumsQuery$data = {
readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{
readonly artists: any | null | undefined;
···
const node: ConcreteRequest = (function(){
var v0 = [
{
+
"defaultValue": null,
+
"kind": "LocalArgument",
+
"name": "where"
+
}
+
],
+
v1 = [
+
{
"alias": null,
"args": [
{
···
"value": {
"count": "desc"
}
+
},
+
{
+
"kind": "Variable",
+
"name": "where",
+
"variableName": "where"
}
],
"concreteType": "FmTealAlphaFeedPlayAggregated",
···
"storageKey": null
}
],
+
"storageKey": null
}
];
return {
"fragment": {
+
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "TopAlbumsQuery",
+
"selections": (v1/*: any*/),
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
+
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "TopAlbumsQuery",
+
"selections": (v1/*: any*/)
},
"params": {
+
"cacheID": "bb227295300710370e7e5c2492532c01",
"id": null,
"metadata": {},
"name": "TopAlbumsQuery",
"operationKind": "query",
+
"text": "query TopAlbumsQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlaysAggregated(groupBy: [releaseMbId, releaseName, artists], orderBy: {count: desc}, limit: 100, where: $where) {\n releaseMbId\n releaseName\n artists\n count\n }\n}\n"
}
};
})();
+
(node as any).hash = "6e30827615eb8acfde3c0c80598b6627";
export default node;
+70 -10
src/__generated__/TopTracksQuery.graphql.ts
···
/**
-
* @generated SignedSource<<58e8aa653524405ace1405d28bd8f19e>>
* @lightSyntaxTransform
* @nogrep
*/
···
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
-
export type TopTracksQuery$variables = Record<PropertyKey, never>;
export type TopTracksQuery$data = {
readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{
readonly artists: any | null | undefined;
···
const node: ConcreteRequest = (function(){
var v0 = [
{
"alias": null,
"args": [
{
···
"value": {
"count": "desc"
}
}
],
"concreteType": "FmTealAlphaFeedPlayAggregated",
···
"storageKey": null
}
],
-
"storageKey": "fmTealAlphaFeedPlaysAggregated(groupBy:[\"trackName\",\"releaseMbId\",\"artists\"],limit:50,orderBy:{\"count\":\"desc\"})"
}
];
return {
"fragment": {
-
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TopTracksQuery",
-
"selections": (v0/*: any*/),
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
-
"argumentDefinitions": [],
"kind": "Operation",
"name": "TopTracksQuery",
-
"selections": (v0/*: any*/)
},
"params": {
-
"cacheID": "61e9f7886dfe9eaeb599b939f2d636e5",
"id": null,
"metadata": {},
"name": "TopTracksQuery",
"operationKind": "query",
-
"text": "query TopTracksQuery {\n fmTealAlphaFeedPlaysAggregated(groupBy: [\"trackName\", \"releaseMbId\", \"artists\"], orderBy: {count: desc}, limit: 50) {\n trackName\n releaseMbId\n artists\n count\n }\n}\n"
}
};
})();
-
(node as any).hash = "536f8ddb64daa09017abff121d7ea8ce";
export default node;
···
/**
+
* @generated SignedSource<<2c2f4cf7a049eff39002109dffd04288>>
* @lightSyntaxTransform
* @nogrep
*/
···
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
+
export type FmTealAlphaFeedPlayWhereInput = {
+
actorHandle?: StringFilter | null | undefined;
+
artistMbIds?: StringFilter | null | undefined;
+
artistNames?: StringFilter | null | undefined;
+
artists?: StringFilter | null | undefined;
+
cid?: StringFilter | null | undefined;
+
collection?: StringFilter | null | undefined;
+
did?: StringFilter | null | undefined;
+
duration?: IntFilter | null | undefined;
+
indexedAt?: DateTimeFilter | null | undefined;
+
isrc?: StringFilter | null | undefined;
+
musicServiceBaseDomain?: StringFilter | null | undefined;
+
originUrl?: StringFilter | null | undefined;
+
playedTime?: StringFilter | null | undefined;
+
recordingMbId?: StringFilter | null | undefined;
+
releaseMbId?: StringFilter | null | undefined;
+
releaseName?: StringFilter | null | undefined;
+
submissionClientAgent?: StringFilter | null | undefined;
+
trackMbId?: StringFilter | null | undefined;
+
trackName?: StringFilter | null | undefined;
+
uri?: StringFilter | null | undefined;
+
};
+
export type DateTimeFilter = {
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type StringFilter = {
+
contains?: string | null | undefined;
+
eq?: string | null | undefined;
+
gt?: string | null | undefined;
+
gte?: string | null | undefined;
+
in?: ReadonlyArray<string | null | undefined> | null | undefined;
+
lt?: string | null | undefined;
+
lte?: string | null | undefined;
+
};
+
export type IntFilter = {
+
eq?: number | null | undefined;
+
gt?: number | null | undefined;
+
gte?: number | null | undefined;
+
in?: ReadonlyArray<number | null | undefined> | null | undefined;
+
lt?: number | null | undefined;
+
lte?: number | null | undefined;
+
};
+
export type TopTracksQuery$variables = {
+
where?: FmTealAlphaFeedPlayWhereInput | null | undefined;
+
};
export type TopTracksQuery$data = {
readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{
readonly artists: any | null | undefined;
···
const node: ConcreteRequest = (function(){
var v0 = [
{
+
"defaultValue": null,
+
"kind": "LocalArgument",
+
"name": "where"
+
}
+
],
+
v1 = [
+
{
"alias": null,
"args": [
{
···
"value": {
"count": "desc"
}
+
},
+
{
+
"kind": "Variable",
+
"name": "where",
+
"variableName": "where"
}
],
"concreteType": "FmTealAlphaFeedPlayAggregated",
···
"storageKey": null
}
],
+
"storageKey": null
}
];
return {
"fragment": {
+
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "TopTracksQuery",
+
"selections": (v1/*: any*/),
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
+
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "TopTracksQuery",
+
"selections": (v1/*: any*/)
},
"params": {
+
"cacheID": "cbf23694acc55e8dfbe9296500193932",
"id": null,
"metadata": {},
"name": "TopTracksQuery",
"operationKind": "query",
+
"text": "query TopTracksQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlaysAggregated(groupBy: [trackName, releaseMbId, artists], orderBy: {count: desc}, limit: 50, where: $where) {\n trackName\n releaseMbId\n artists\n count\n }\n}\n"
}
};
})();
+
(node as any).hash = "6b649e9c39df41d4ce995e69e6dc6f35";
export default node;
+4 -2
src/main.tsx
···
import { createClient } from "graphql-ws";
const HTTP_ENDPOINT =
-
"https://api.slices.network/graphql?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a";
const WS_ENDPOINT =
-
"wss://api.slices.network/graphql/ws?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a";
const fetchGraphQL: FetchFunction = async (request, variables) => {
const resp = await fetch(HTTP_ENDPOINT, {
···
<Routes>
<Route path="/" element={<App />} />
<Route path="/tracks" element={<TopTracks />} />
<Route path="/albums" element={<TopAlbums />} />
<Route path="/profile/:handle" element={<Profile />} />
</Routes>
</Suspense>
···
import { createClient } from "graphql-ws";
const HTTP_ENDPOINT =
+
"http://localhost:3000/graphql?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a";
const WS_ENDPOINT =
+
"ws://localhost:3000/graphql/ws?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a";
const fetchGraphQL: FetchFunction = async (request, variables) => {
const resp = await fetch(HTTP_ENDPOINT, {
···
<Routes>
<Route path="/" element={<App />} />
<Route path="/tracks" element={<TopTracks />} />
+
<Route path="/tracks/:period" element={<TopTracks />} />
<Route path="/albums" element={<TopAlbums />} />
+
<Route path="/albums/:period" element={<TopAlbums />} />
<Route path="/profile/:handle" element={<Profile />} />
</Routes>
</Suspense>
+31
src/useDateRangeFilter.ts
···
···
+
import { useMemo } from "react";
+
+
export function useDateRangeFilter(period: string | undefined) {
+
return useMemo(() => {
+
if (!period || period === "all") {
+
return { where: undefined };
+
}
+
+
// Round to start of current day to keep the timestamp stable
+
const now = new Date();
+
now.setHours(0, 0, 0, 0);
+
+
let daysAgo = 0;
+
switch (period) {
+
case "daily":
+
daysAgo = 1;
+
break;
+
case "weekly":
+
daysAgo = 7;
+
break;
+
case "monthly":
+
daysAgo = 30;
+
break;
+
default:
+
return { where: undefined };
+
}
+
+
const startDate = new Date(now.getTime() - daysAgo * 24 * 60 * 60 * 1000);
+
return { where: { playedTime: { gte: startDate.toISOString() } } };
+
}, [period]);
+
}