Compare commits
7 Commits
loewy/bran
...
apple-iap-
| Author | SHA1 | Date | |
|---|---|---|---|
| fe95ab824e | |||
| 079e4e8719 | |||
| af68bc3c60 | |||
| f12d2c5a1b | |||
| 4e3f649a2c | |||
| 7cef75b2ca | |||
| 9358205327 |
205
src/index.tsx
205
src/index.tsx
@@ -331,6 +331,7 @@ export type EditableShotFieldInputGql = {
|
|||||||
export enum EntitlementSourceTypeEnum {
|
export enum EntitlementSourceTypeEnum {
|
||||||
Admin = "ADMIN",
|
Admin = "ADMIN",
|
||||||
AlphaLegacy = "ALPHA_LEGACY",
|
AlphaLegacy = "ALPHA_LEGACY",
|
||||||
|
Apple = "APPLE",
|
||||||
Manual = "MANUAL",
|
Manual = "MANUAL",
|
||||||
Stripe = "STRIPE",
|
Stripe = "STRIPE",
|
||||||
}
|
}
|
||||||
@@ -2429,6 +2430,7 @@ export type Mutation = {
|
|||||||
startChallenge: ChallengeEntry;
|
startChallenge: ChallengeEntry;
|
||||||
submitCancellationFeedback: Scalars["Boolean"]["output"];
|
submitCancellationFeedback: Scalars["Boolean"]["output"];
|
||||||
submitChallengeEntry: ChallengeEntry;
|
submitChallengeEntry: ChallengeEntry;
|
||||||
|
syncAppleSubscription: SyncAppleSubscriptionResultGql;
|
||||||
undismissChallenge: Scalars["Boolean"]["output"];
|
undismissChallenge: Scalars["Boolean"]["output"];
|
||||||
unfollowUser: UserGql;
|
unfollowUser: UserGql;
|
||||||
updateShotAnnotations: UpdateShotAnnotationReturn;
|
updateShotAnnotations: UpdateShotAnnotationReturn;
|
||||||
@@ -2632,6 +2634,10 @@ export type MutationSubmitChallengeEntryArgs = {
|
|||||||
videoId: Scalars["ID"]["input"];
|
videoId: Scalars["ID"]["input"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MutationSyncAppleSubscriptionArgs = {
|
||||||
|
input: SyncAppleSubscriptionInputGql;
|
||||||
|
};
|
||||||
|
|
||||||
export type MutationUndismissChallengeArgs = {
|
export type MutationUndismissChallengeArgs = {
|
||||||
challengeId: Scalars["ID"]["input"];
|
challengeId: Scalars["ID"]["input"];
|
||||||
};
|
};
|
||||||
@@ -2814,6 +2820,7 @@ export type Query = {
|
|||||||
challenges: Array<Challenge>;
|
challenges: Array<Challenge>;
|
||||||
doesUsernameExist: Scalars["Boolean"]["output"];
|
doesUsernameExist: Scalars["Boolean"]["output"];
|
||||||
getAggregatedShotMetrics: Array<AggregateResultGql>;
|
getAggregatedShotMetrics: Array<AggregateResultGql>;
|
||||||
|
getAppleAppAccountToken: Scalars["String"]["output"];
|
||||||
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGql;
|
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGql;
|
||||||
getBucketSet?: Maybe<BucketSetGql>;
|
getBucketSet?: Maybe<BucketSetGql>;
|
||||||
getDeployedConfig: DeployedConfigGql;
|
getDeployedConfig: DeployedConfigGql;
|
||||||
@@ -3377,6 +3384,27 @@ export type SuccessfulAddAddShotAnnotationErrors =
|
|||||||
| AddShotAnnotationErrors
|
| AddShotAnnotationErrors
|
||||||
| SuccessfulAdd;
|
| SuccessfulAdd;
|
||||||
|
|
||||||
|
export type SyncAppleSubscriptionInputGql = {
|
||||||
|
signedRenewalInfo?: InputMaybe<Scalars["String"]["input"]>;
|
||||||
|
signedTransactionInfo: Scalars["String"]["input"];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SyncAppleSubscriptionResultGql = {
|
||||||
|
__typename?: "SyncAppleSubscriptionResultGQL";
|
||||||
|
appleStatus?: Maybe<Scalars["Int"]["output"]>;
|
||||||
|
entitlementEndsAt?: Maybe<Scalars["DateTime"]["output"]>;
|
||||||
|
entitlementSource?: Maybe<EntitlementSourceTypeEnum>;
|
||||||
|
entitlementStartsAt?: Maybe<Scalars["DateTime"]["output"]>;
|
||||||
|
errorCode?: Maybe<Scalars["String"]["output"]>;
|
||||||
|
errorMessage?: Maybe<Scalars["String"]["output"]>;
|
||||||
|
expiresAt?: Maybe<Scalars["DateTime"]["output"]>;
|
||||||
|
hasActiveSubscription: Scalars["Boolean"]["output"];
|
||||||
|
latestTransactionId?: Maybe<Scalars["String"]["output"]>;
|
||||||
|
ok: Scalars["Boolean"]["output"];
|
||||||
|
originalTransactionId?: Maybe<Scalars["String"]["output"]>;
|
||||||
|
productId?: Maybe<Scalars["String"]["output"]>;
|
||||||
|
};
|
||||||
|
|
||||||
export type TableStateGql = {
|
export type TableStateGql = {
|
||||||
__typename?: "TableStateGQL";
|
__typename?: "TableStateGQL";
|
||||||
homography?: Maybe<HomographyInfoGql>;
|
homography?: Maybe<HomographyInfoGql>;
|
||||||
@@ -4919,6 +4947,9 @@ export type GetSubscriptionStatusQuery = {
|
|||||||
getUserSubscriptionStatus: {
|
getUserSubscriptionStatus: {
|
||||||
__typename?: "UserSubscriptionStatusGQL";
|
__typename?: "UserSubscriptionStatusGQL";
|
||||||
hasActiveSubscription: boolean;
|
hasActiveSubscription: boolean;
|
||||||
|
entitlementSource?: EntitlementSourceTypeEnum | null;
|
||||||
|
entitlementStartsAt?: any | null;
|
||||||
|
entitlementEndsAt?: any | null;
|
||||||
subscriptionStatus?: StripeSubscriptionStatusEnum | null;
|
subscriptionStatus?: StripeSubscriptionStatusEnum | null;
|
||||||
currentPeriodStart?: any | null;
|
currentPeriodStart?: any | null;
|
||||||
currentPeriodEnd?: any | null;
|
currentPeriodEnd?: any | null;
|
||||||
@@ -4928,6 +4959,38 @@ export type GetSubscriptionStatusQuery = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GetAppleAppAccountTokenQueryVariables = Exact<{
|
||||||
|
[key: string]: never;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type GetAppleAppAccountTokenQuery = {
|
||||||
|
__typename?: "Query";
|
||||||
|
getAppleAppAccountToken: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SyncAppleSubscriptionMutationVariables = Exact<{
|
||||||
|
signedTransactionInfo: Scalars["String"]["input"];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type SyncAppleSubscriptionMutation = {
|
||||||
|
__typename?: "Mutation";
|
||||||
|
syncAppleSubscription: {
|
||||||
|
__typename?: "SyncAppleSubscriptionResultGQL";
|
||||||
|
ok: boolean;
|
||||||
|
errorCode?: string | null;
|
||||||
|
errorMessage?: string | null;
|
||||||
|
hasActiveSubscription: boolean;
|
||||||
|
entitlementSource?: EntitlementSourceTypeEnum | null;
|
||||||
|
entitlementStartsAt?: any | null;
|
||||||
|
entitlementEndsAt?: any | null;
|
||||||
|
appleStatus?: number | null;
|
||||||
|
originalTransactionId?: string | null;
|
||||||
|
latestTransactionId?: string | null;
|
||||||
|
productId?: string | null;
|
||||||
|
expiresAt?: any | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type CancelSubscriptionMutationVariables = Exact<{
|
export type CancelSubscriptionMutationVariables = Exact<{
|
||||||
[key: string]: never;
|
[key: string]: never;
|
||||||
}>;
|
}>;
|
||||||
@@ -4937,6 +5000,9 @@ export type CancelSubscriptionMutation = {
|
|||||||
cancelSubscription: {
|
cancelSubscription: {
|
||||||
__typename?: "UserSubscriptionStatusGQL";
|
__typename?: "UserSubscriptionStatusGQL";
|
||||||
hasActiveSubscription: boolean;
|
hasActiveSubscription: boolean;
|
||||||
|
entitlementSource?: EntitlementSourceTypeEnum | null;
|
||||||
|
entitlementStartsAt?: any | null;
|
||||||
|
entitlementEndsAt?: any | null;
|
||||||
subscriptionStatus?: StripeSubscriptionStatusEnum | null;
|
subscriptionStatus?: StripeSubscriptionStatusEnum | null;
|
||||||
currentPeriodStart?: any | null;
|
currentPeriodStart?: any | null;
|
||||||
currentPeriodEnd?: any | null;
|
currentPeriodEnd?: any | null;
|
||||||
@@ -10361,6 +10427,9 @@ export const GetSubscriptionStatusDocument = gql`
|
|||||||
query GetSubscriptionStatus {
|
query GetSubscriptionStatus {
|
||||||
getUserSubscriptionStatus {
|
getUserSubscriptionStatus {
|
||||||
hasActiveSubscription
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
subscriptionStatus
|
subscriptionStatus
|
||||||
currentPeriodStart
|
currentPeriodStart
|
||||||
currentPeriodEnd
|
currentPeriodEnd
|
||||||
@@ -10435,10 +10504,146 @@ export type GetSubscriptionStatusQueryResult = Apollo.QueryResult<
|
|||||||
GetSubscriptionStatusQuery,
|
GetSubscriptionStatusQuery,
|
||||||
GetSubscriptionStatusQueryVariables
|
GetSubscriptionStatusQueryVariables
|
||||||
>;
|
>;
|
||||||
|
export const GetAppleAppAccountTokenDocument = gql`
|
||||||
|
query GetAppleAppAccountToken {
|
||||||
|
getAppleAppAccountToken
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useGetAppleAppAccountTokenQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useGetAppleAppAccountTokenQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useGetAppleAppAccountTokenQuery` 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 } = useGetAppleAppAccountTokenQuery({
|
||||||
|
* variables: {
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useGetAppleAppAccountTokenQuery(
|
||||||
|
baseOptions?: Apollo.QueryHookOptions<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const options = { ...defaultOptions, ...baseOptions };
|
||||||
|
return Apollo.useQuery<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>(GetAppleAppAccountTokenDocument, options);
|
||||||
|
}
|
||||||
|
export function useGetAppleAppAccountTokenLazyQuery(
|
||||||
|
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const options = { ...defaultOptions, ...baseOptions };
|
||||||
|
return Apollo.useLazyQuery<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>(GetAppleAppAccountTokenDocument, options);
|
||||||
|
}
|
||||||
|
export function useGetAppleAppAccountTokenSuspenseQuery(
|
||||||
|
baseOptions?: Apollo.SuspenseQueryHookOptions<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const options = { ...defaultOptions, ...baseOptions };
|
||||||
|
return Apollo.useSuspenseQuery<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>(GetAppleAppAccountTokenDocument, options);
|
||||||
|
}
|
||||||
|
export type GetAppleAppAccountTokenQueryHookResult = ReturnType<
|
||||||
|
typeof useGetAppleAppAccountTokenQuery
|
||||||
|
>;
|
||||||
|
export type GetAppleAppAccountTokenLazyQueryHookResult = ReturnType<
|
||||||
|
typeof useGetAppleAppAccountTokenLazyQuery
|
||||||
|
>;
|
||||||
|
export type GetAppleAppAccountTokenSuspenseQueryHookResult = ReturnType<
|
||||||
|
typeof useGetAppleAppAccountTokenSuspenseQuery
|
||||||
|
>;
|
||||||
|
export type GetAppleAppAccountTokenQueryResult = Apollo.QueryResult<
|
||||||
|
GetAppleAppAccountTokenQuery,
|
||||||
|
GetAppleAppAccountTokenQueryVariables
|
||||||
|
>;
|
||||||
|
export const SyncAppleSubscriptionDocument = gql`
|
||||||
|
mutation SyncAppleSubscription($signedTransactionInfo: String!) {
|
||||||
|
syncAppleSubscription(
|
||||||
|
input: { signedTransactionInfo: $signedTransactionInfo }
|
||||||
|
) {
|
||||||
|
ok
|
||||||
|
errorCode
|
||||||
|
errorMessage
|
||||||
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
|
appleStatus
|
||||||
|
originalTransactionId
|
||||||
|
latestTransactionId
|
||||||
|
productId
|
||||||
|
expiresAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type SyncAppleSubscriptionMutationFn = Apollo.MutationFunction<
|
||||||
|
SyncAppleSubscriptionMutation,
|
||||||
|
SyncAppleSubscriptionMutationVariables
|
||||||
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useSyncAppleSubscriptionMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useSyncAppleSubscriptionMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useSyncAppleSubscriptionMutation` 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 [syncAppleSubscriptionMutation, { data, loading, error }] = useSyncAppleSubscriptionMutation({
|
||||||
|
* variables: {
|
||||||
|
* signedTransactionInfo: // value for 'signedTransactionInfo'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useSyncAppleSubscriptionMutation(
|
||||||
|
baseOptions?: Apollo.MutationHookOptions<
|
||||||
|
SyncAppleSubscriptionMutation,
|
||||||
|
SyncAppleSubscriptionMutationVariables
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
const options = { ...defaultOptions, ...baseOptions };
|
||||||
|
return Apollo.useMutation<
|
||||||
|
SyncAppleSubscriptionMutation,
|
||||||
|
SyncAppleSubscriptionMutationVariables
|
||||||
|
>(SyncAppleSubscriptionDocument, options);
|
||||||
|
}
|
||||||
|
export type SyncAppleSubscriptionMutationHookResult = ReturnType<
|
||||||
|
typeof useSyncAppleSubscriptionMutation
|
||||||
|
>;
|
||||||
|
export type SyncAppleSubscriptionMutationResult =
|
||||||
|
Apollo.MutationResult<SyncAppleSubscriptionMutation>;
|
||||||
|
export type SyncAppleSubscriptionMutationOptions = Apollo.BaseMutationOptions<
|
||||||
|
SyncAppleSubscriptionMutation,
|
||||||
|
SyncAppleSubscriptionMutationVariables
|
||||||
|
>;
|
||||||
export const CancelSubscriptionDocument = gql`
|
export const CancelSubscriptionDocument = gql`
|
||||||
mutation CancelSubscription {
|
mutation CancelSubscription {
|
||||||
cancelSubscription {
|
cancelSubscription {
|
||||||
hasActiveSubscription
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
subscriptionStatus
|
subscriptionStatus
|
||||||
currentPeriodStart
|
currentPeriodStart
|
||||||
currentPeriodEnd
|
currentPeriodEnd
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ query GetAvailableSubscriptionOptions {
|
|||||||
query GetSubscriptionStatus {
|
query GetSubscriptionStatus {
|
||||||
getUserSubscriptionStatus {
|
getUserSubscriptionStatus {
|
||||||
hasActiveSubscription
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
subscriptionStatus
|
subscriptionStatus
|
||||||
currentPeriodStart
|
currentPeriodStart
|
||||||
currentPeriodEnd
|
currentPeriodEnd
|
||||||
@@ -59,9 +62,35 @@ query GetSubscriptionStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query GetAppleAppAccountToken {
|
||||||
|
getAppleAppAccountToken
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation SyncAppleSubscription($signedTransactionInfo: String!) {
|
||||||
|
syncAppleSubscription(
|
||||||
|
input: { signedTransactionInfo: $signedTransactionInfo }
|
||||||
|
) {
|
||||||
|
ok
|
||||||
|
errorCode
|
||||||
|
errorMessage
|
||||||
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
|
appleStatus
|
||||||
|
originalTransactionId
|
||||||
|
latestTransactionId
|
||||||
|
productId
|
||||||
|
expiresAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutation CancelSubscription {
|
mutation CancelSubscription {
|
||||||
cancelSubscription {
|
cancelSubscription {
|
||||||
hasActiveSubscription
|
hasActiveSubscription
|
||||||
|
entitlementSource
|
||||||
|
entitlementStartsAt
|
||||||
|
entitlementEndsAt
|
||||||
subscriptionStatus
|
subscriptionStatus
|
||||||
currentPeriodStart
|
currentPeriodStart
|
||||||
currentPeriodEnd
|
currentPeriodEnd
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ type Query {
|
|||||||
): UserRelationshipsResult!
|
): UserRelationshipsResult!
|
||||||
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGQL!
|
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGQL!
|
||||||
getUserSubscriptionStatus: UserSubscriptionStatusGQL!
|
getUserSubscriptionStatus: UserSubscriptionStatusGQL!
|
||||||
|
getAppleAppAccountToken: String!
|
||||||
getQuotaStatus: QuotaStatusGQL!
|
getQuotaStatus: QuotaStatusGQL!
|
||||||
getPlayTime(userId: Int!, filters: VideoFilterInput = null): UserPlayTimeGQL!
|
getPlayTime(userId: Int!, filters: VideoFilterInput = null): UserPlayTimeGQL!
|
||||||
getUserVideos(
|
getUserVideos(
|
||||||
@@ -1020,6 +1021,7 @@ enum EntitlementSourceTypeEnum {
|
|||||||
ADMIN
|
ADMIN
|
||||||
MANUAL
|
MANUAL
|
||||||
STRIPE
|
STRIPE
|
||||||
|
APPLE
|
||||||
ALPHA_LEGACY
|
ALPHA_LEGACY
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1175,6 +1177,9 @@ type Mutation {
|
|||||||
retireTags(tagIds: [Int!]!): Boolean!
|
retireTags(tagIds: [Int!]!): Boolean!
|
||||||
ensureStripeCustomerExists: UserGQL!
|
ensureStripeCustomerExists: UserGQL!
|
||||||
deleteUser: Boolean!
|
deleteUser: Boolean!
|
||||||
|
syncAppleSubscription(
|
||||||
|
input: SyncAppleSubscriptionInputGQL!
|
||||||
|
): SyncAppleSubscriptionResultGQL!
|
||||||
createSubscription(priceId: String!): CreateSubscriptionResultGQL!
|
createSubscription(priceId: String!): CreateSubscriptionResultGQL!
|
||||||
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
|
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
|
||||||
cancelSubscription: UserSubscriptionStatusGQL!
|
cancelSubscription: UserSubscriptionStatusGQL!
|
||||||
@@ -1328,6 +1333,26 @@ input EditUserInputGQL {
|
|||||||
agreesToMarketing: Boolean = null
|
agreesToMarketing: Boolean = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SyncAppleSubscriptionResultGQL {
|
||||||
|
ok: Boolean!
|
||||||
|
errorCode: String
|
||||||
|
errorMessage: String
|
||||||
|
hasActiveSubscription: Boolean!
|
||||||
|
entitlementSource: EntitlementSourceTypeEnum
|
||||||
|
entitlementStartsAt: DateTime
|
||||||
|
entitlementEndsAt: DateTime
|
||||||
|
appleStatus: Int
|
||||||
|
originalTransactionId: String
|
||||||
|
latestTransactionId: String
|
||||||
|
productId: String
|
||||||
|
expiresAt: DateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
input SyncAppleSubscriptionInputGQL {
|
||||||
|
signedTransactionInfo: String!
|
||||||
|
signedRenewalInfo: String = null
|
||||||
|
}
|
||||||
|
|
||||||
type CreateSubscriptionResultGQL {
|
type CreateSubscriptionResultGQL {
|
||||||
checkoutUrl: String!
|
checkoutUrl: String!
|
||||||
sessionId: String!
|
sessionId: String!
|
||||||
|
|||||||
Reference in New Issue
Block a user