Compare commits
11 Commits
mk/extend-
...
5efd8ef8e5
Author | SHA1 | Date | |
---|---|---|---|
5efd8ef8e5 | |||
6ad3d449d8 | |||
8fe20d1c41 | |||
e151f39582 | |||
f136ddb9ca | |||
5d05614e07 | |||
c4c3ccde00 | |||
e137ce8ad1 | |||
bd5bebb747 | |||
034facebf3 | |||
ac1fceb648 |
158
src/index.tsx
158
src/index.tsx
@@ -186,12 +186,29 @@ export type DoesNotOwnShotErrOtherErrorNeedsNote =
|
|||||||
| DoesNotOwnShotErr
|
| DoesNotOwnShotErr
|
||||||
| OtherErrorNeedsNote;
|
| OtherErrorNeedsNote;
|
||||||
|
|
||||||
|
export type EditShotReturn = {
|
||||||
|
__typename?: "EditShotReturn";
|
||||||
|
error?: Maybe<DoesNotOwnShotErr>;
|
||||||
|
shot?: Maybe<ShotGql>;
|
||||||
|
};
|
||||||
|
|
||||||
export type EditUserInputGql = {
|
export type EditUserInputGql = {
|
||||||
fargoRating?: InputMaybe<Scalars["Int"]["input"]>;
|
fargoRating?: InputMaybe<Scalars["Int"]["input"]>;
|
||||||
username?: InputMaybe<Scalars["String"]["input"]>;
|
username?: InputMaybe<Scalars["String"]["input"]>;
|
||||||
videosPrivateByDefault?: InputMaybe<Scalars["Boolean"]["input"]>;
|
videosPrivateByDefault?: InputMaybe<Scalars["Boolean"]["input"]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EditableShotFieldInputGql = {
|
||||||
|
backcut?: InputMaybe<Scalars["Boolean"]["input"]>;
|
||||||
|
excludeFromStats?: InputMaybe<Scalars["Boolean"]["input"]>;
|
||||||
|
intendedPocketType?: InputMaybe<PocketEnum>;
|
||||||
|
make?: InputMaybe<Scalars["Boolean"]["input"]>;
|
||||||
|
notes?: InputMaybe<Scalars["String"]["input"]>;
|
||||||
|
shotDirection?: InputMaybe<ShotDirectionEnum>;
|
||||||
|
spinType?: InputMaybe<SpinTypeEnum>;
|
||||||
|
targetPocketAngleDirection?: InputMaybe<ShotDirectionEnum>;
|
||||||
|
};
|
||||||
|
|
||||||
export type EnumAggregation = {
|
export type EnumAggregation = {
|
||||||
feature: Scalars["String"]["input"];
|
feature: Scalars["String"]["input"];
|
||||||
};
|
};
|
||||||
@@ -1999,8 +2016,17 @@ export type MedalGql = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type MedalScope =
|
export type MedalScope =
|
||||||
| { interval: TimeInterval; videoId?: never }
|
| {
|
||||||
| { interval?: never; videoId: Scalars["Int"]["input"] };
|
datetimeRange: DatetimeRangeAggregationInput;
|
||||||
|
interval?: never;
|
||||||
|
videoId?: never;
|
||||||
|
} /** @deprecated NO LONGER SUPPORTED, USE DATETIME_RANGE */
|
||||||
|
| { datetimeRange?: never; interval: TimeInterval; videoId?: never }
|
||||||
|
| {
|
||||||
|
datetimeRange?: never;
|
||||||
|
interval?: never;
|
||||||
|
videoId: Scalars["Int"]["input"];
|
||||||
|
};
|
||||||
|
|
||||||
export type MustHaveSetForUploadLinkErr = {
|
export type MustHaveSetForUploadLinkErr = {
|
||||||
__typename?: "MustHaveSetForUploadLinkErr";
|
__typename?: "MustHaveSetForUploadLinkErr";
|
||||||
@@ -2025,6 +2051,7 @@ export type Mutation = {
|
|||||||
createUploadStream: CreateUploadStreamReturn;
|
createUploadStream: CreateUploadStreamReturn;
|
||||||
deleteVideo: Scalars["Boolean"]["output"];
|
deleteVideo: Scalars["Boolean"]["output"];
|
||||||
editProfileImageUri: UserGql;
|
editProfileImageUri: UserGql;
|
||||||
|
editShot: EditShotReturn;
|
||||||
editUploadStream: Scalars["Boolean"]["output"];
|
editUploadStream: Scalars["Boolean"]["output"];
|
||||||
editUser: UserGql;
|
editUser: UserGql;
|
||||||
findPrerecordTableLayout?: Maybe<HomographyInfoGql>;
|
findPrerecordTableLayout?: Maybe<HomographyInfoGql>;
|
||||||
@@ -2060,6 +2087,11 @@ export type MutationEditProfileImageUriArgs = {
|
|||||||
profileImageUri: Scalars["String"]["input"];
|
profileImageUri: Scalars["String"]["input"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MutationEditShotArgs = {
|
||||||
|
fieldsToEdit: EditableShotFieldInputGql;
|
||||||
|
shotId: Scalars["Int"]["input"];
|
||||||
|
};
|
||||||
|
|
||||||
export type MutationEditUploadStreamArgs = {
|
export type MutationEditUploadStreamArgs = {
|
||||||
videoId: Scalars["Int"]["input"];
|
videoId: Scalars["Int"]["input"];
|
||||||
videoMetadata: VideoMetadataInput;
|
videoMetadata: VideoMetadataInput;
|
||||||
@@ -2999,6 +3031,12 @@ export type GetVideoMakePercentageIntervalsQuery = {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MedalFieldsFragment = {
|
||||||
|
__typename?: "MedalGQL";
|
||||||
|
count: number;
|
||||||
|
nickname?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type GetMedalsQueryVariables = Exact<{
|
export type GetMedalsQueryVariables = Exact<{
|
||||||
scope: MedalScope;
|
scope: MedalScope;
|
||||||
userId?: InputMaybe<Scalars["Int"]["input"]>;
|
userId?: InputMaybe<Scalars["Int"]["input"]>;
|
||||||
@@ -3008,11 +3046,6 @@ export type GetMedalsQuery = {
|
|||||||
__typename?: "Query";
|
__typename?: "Query";
|
||||||
getMedals: {
|
getMedals: {
|
||||||
__typename?: "RequestedMedalsGQL";
|
__typename?: "RequestedMedalsGQL";
|
||||||
distanceOver66?: {
|
|
||||||
__typename?: "MedalGQL";
|
|
||||||
count: number;
|
|
||||||
nickname?: string | null;
|
|
||||||
} | null;
|
|
||||||
distanceOver78?: {
|
distanceOver78?: {
|
||||||
__typename?: "MedalGQL";
|
__typename?: "MedalGQL";
|
||||||
count: number;
|
count: number;
|
||||||
@@ -3073,37 +3106,27 @@ export type GetMedalsQuery = {
|
|||||||
count: number;
|
count: number;
|
||||||
nickname?: string | null;
|
nickname?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
totalMakes25?: {
|
|
||||||
__typename?: "MedalGQL";
|
|
||||||
count: number;
|
|
||||||
nickname?: string | null;
|
|
||||||
} | null;
|
|
||||||
totalMakes50?: {
|
|
||||||
__typename?: "MedalGQL";
|
|
||||||
count: number;
|
|
||||||
nickname?: string | null;
|
|
||||||
} | null;
|
|
||||||
totalMakes75?: {
|
|
||||||
__typename?: "MedalGQL";
|
|
||||||
count: number;
|
|
||||||
nickname?: string | null;
|
|
||||||
} | null;
|
|
||||||
totalMakes100?: {
|
totalMakes100?: {
|
||||||
__typename?: "MedalGQL";
|
__typename?: "MedalGQL";
|
||||||
count: number;
|
count: number;
|
||||||
nickname?: string | null;
|
nickname?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
totalMakes200?: {
|
dailyMakes50?: {
|
||||||
__typename?: "MedalGQL";
|
__typename?: "MedalGQL";
|
||||||
count: number;
|
count: number;
|
||||||
nickname?: string | null;
|
nickname?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
totalMakes300?: {
|
dailyMakes100?: {
|
||||||
__typename?: "MedalGQL";
|
__typename?: "MedalGQL";
|
||||||
count: number;
|
count: number;
|
||||||
nickname?: string | null;
|
nickname?: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
totalMakes400?: {
|
dailyMakes150?: {
|
||||||
|
__typename?: "MedalGQL";
|
||||||
|
count: number;
|
||||||
|
nickname?: string | null;
|
||||||
|
} | null;
|
||||||
|
dailyMakes200?: {
|
||||||
__typename?: "MedalGQL";
|
__typename?: "MedalGQL";
|
||||||
count: number;
|
count: number;
|
||||||
nickname?: string | null;
|
nickname?: string | null;
|
||||||
@@ -3674,6 +3697,7 @@ export type GetStreamMonitoringDetailsQuery = {
|
|||||||
elapsedTime?: number | null;
|
elapsedTime?: number | null;
|
||||||
currentHomography?: {
|
currentHomography?: {
|
||||||
__typename?: "HomographyInfoGQL";
|
__typename?: "HomographyInfoGQL";
|
||||||
|
id: number;
|
||||||
frameIndex: number;
|
frameIndex: number;
|
||||||
crop: {
|
crop: {
|
||||||
__typename?: "BoundingBoxGQL";
|
__typename?: "BoundingBoxGQL";
|
||||||
@@ -3889,6 +3913,7 @@ export type GetVideoQuery = {
|
|||||||
} | null;
|
} | null;
|
||||||
homographyHistory: Array<{
|
homographyHistory: Array<{
|
||||||
__typename?: "HomographyInfoGQL";
|
__typename?: "HomographyInfoGQL";
|
||||||
|
id: number;
|
||||||
frameIndex: number;
|
frameIndex: number;
|
||||||
crop: {
|
crop: {
|
||||||
__typename?: "BoundingBoxGQL";
|
__typename?: "BoundingBoxGQL";
|
||||||
@@ -4099,6 +4124,7 @@ export type FindPrerecordTableLayoutMutation = {
|
|||||||
__typename?: "Mutation";
|
__typename?: "Mutation";
|
||||||
findPrerecordTableLayout?: {
|
findPrerecordTableLayout?: {
|
||||||
__typename?: "HomographyInfoGQL";
|
__typename?: "HomographyInfoGQL";
|
||||||
|
id: number;
|
||||||
frameIndex: number;
|
frameIndex: number;
|
||||||
crop: {
|
crop: {
|
||||||
__typename?: "BoundingBoxGQL";
|
__typename?: "BoundingBoxGQL";
|
||||||
@@ -4128,6 +4154,7 @@ export type FindPrerecordTableLayoutMutation = {
|
|||||||
|
|
||||||
export type HomographyInfoFragment = {
|
export type HomographyInfoFragment = {
|
||||||
__typename?: "HomographyInfoGQL";
|
__typename?: "HomographyInfoGQL";
|
||||||
|
id: number;
|
||||||
frameIndex: number;
|
frameIndex: number;
|
||||||
crop: {
|
crop: {
|
||||||
__typename?: "BoundingBoxGQL";
|
__typename?: "BoundingBoxGQL";
|
||||||
@@ -4369,6 +4396,12 @@ export const VideoCardFieldsFragmentDoc = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const MedalFieldsFragmentDoc = gql`
|
||||||
|
fragment MedalFields on MedalGQL {
|
||||||
|
count
|
||||||
|
nickname
|
||||||
|
}
|
||||||
|
`;
|
||||||
export const ShotWithAllFeaturesFragmentDoc = gql`
|
export const ShotWithAllFeaturesFragmentDoc = gql`
|
||||||
fragment ShotWithAllFeatures on ShotGQL {
|
fragment ShotWithAllFeatures on ShotGQL {
|
||||||
id
|
id
|
||||||
@@ -4490,6 +4523,7 @@ export const VideoDurationDataFragmentDoc = gql`
|
|||||||
`;
|
`;
|
||||||
export const HomographyInfoFragmentDoc = gql`
|
export const HomographyInfoFragmentDoc = gql`
|
||||||
fragment HomographyInfo on HomographyInfoGQL {
|
fragment HomographyInfo on HomographyInfoGQL {
|
||||||
|
id
|
||||||
frameIndex
|
frameIndex
|
||||||
crop {
|
crop {
|
||||||
left
|
left
|
||||||
@@ -4943,88 +4977,60 @@ export type GetVideoMakePercentageIntervalsQueryResult = Apollo.QueryResult<
|
|||||||
export const GetMedalsDocument = gql`
|
export const GetMedalsDocument = gql`
|
||||||
query getMedals($scope: MedalScope!, $userId: Int) {
|
query getMedals($scope: MedalScope!, $userId: Int) {
|
||||||
getMedals(scope: $scope, userId: $userId) {
|
getMedals(scope: $scope, userId: $userId) {
|
||||||
distanceOver66 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
distanceOver78 {
|
distanceOver78 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
distanceOver90 {
|
distanceOver90 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength3 {
|
runLength3 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength5 {
|
runLength5 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength8 {
|
runLength8 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength10 {
|
runLength10 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength15 {
|
runLength15 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength20 {
|
runLength20 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength25 {
|
runLength25 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength30 {
|
runLength30 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength40 {
|
runLength40 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength50 {
|
runLength50 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes25 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes50 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes75 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes100 {
|
totalMakes100 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes200 {
|
dailyMakes50 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes300 {
|
dailyMakes100 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes400 {
|
dailyMakes150 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
}
|
||||||
|
dailyMakes200 {
|
||||||
|
...MedalFields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
${MedalFieldsFragmentDoc}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,84 +1,77 @@
|
|||||||
|
fragment MedalFields on MedalGQL {
|
||||||
|
count
|
||||||
|
nickname
|
||||||
|
}
|
||||||
|
|
||||||
query getMedals($scope: MedalScope!, $userId: Int) {
|
query getMedals($scope: MedalScope!, $userId: Int) {
|
||||||
getMedals(scope: $scope, userId: $userId) {
|
getMedals(scope: $scope, userId: $userId) {
|
||||||
distanceOver66 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
distanceOver78 {
|
distanceOver78 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
distanceOver90 {
|
distanceOver90 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength3 {
|
runLength3 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength5 {
|
runLength5 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength8 {
|
runLength8 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength10 {
|
runLength10 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength15 {
|
runLength15 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength20 {
|
runLength20 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength25 {
|
runLength25 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength30 {
|
runLength30 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength40 {
|
runLength40 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
runLength50 {
|
runLength50 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes25 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes50 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
|
||||||
totalMakes75 {
|
|
||||||
count
|
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes100 {
|
totalMakes100 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes200 {
|
# missing assets
|
||||||
count
|
# totalMakes500 {
|
||||||
nickname
|
# ...MedalFields
|
||||||
|
# }
|
||||||
|
# totalMakes1000 {
|
||||||
|
# ...MedalFields
|
||||||
|
# }
|
||||||
|
# totalMakes5000 {
|
||||||
|
# ...MedalFields
|
||||||
|
# }
|
||||||
|
# totalMakes10000 {
|
||||||
|
# ...MedalFields
|
||||||
|
# }
|
||||||
|
dailyMakes50 {
|
||||||
|
...MedalFields
|
||||||
}
|
}
|
||||||
totalMakes300 {
|
dailyMakes100 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
totalMakes400 {
|
dailyMakes150 {
|
||||||
count
|
...MedalFields
|
||||||
nickname
|
|
||||||
}
|
}
|
||||||
|
dailyMakes200 {
|
||||||
|
...MedalFields
|
||||||
|
}
|
||||||
|
# missing asset
|
||||||
|
# dailyMakes250 {
|
||||||
|
# ...MedalFields
|
||||||
|
# }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -222,6 +222,7 @@ mutation FindPrerecordTableLayout($b64Image: String!, $videoId: Int!) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fragment HomographyInfo on HomographyInfoGQL {
|
fragment HomographyInfo on HomographyInfoGQL {
|
||||||
|
id
|
||||||
frameIndex
|
frameIndex
|
||||||
crop {
|
crop {
|
||||||
left
|
left
|
||||||
|
@@ -320,6 +320,8 @@ type MedalGQL {
|
|||||||
input MedalScope @oneOf {
|
input MedalScope @oneOf {
|
||||||
videoId: Int
|
videoId: Int
|
||||||
interval: TimeInterval
|
interval: TimeInterval
|
||||||
|
@deprecated(reason: "NO LONGER SUPPORTED, USE DATETIME_RANGE")
|
||||||
|
datetimeRange: DatetimeRangeAggregationInput
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetRunsResult {
|
type GetRunsResult {
|
||||||
@@ -705,6 +707,10 @@ scalar JSON
|
|||||||
type Mutation {
|
type Mutation {
|
||||||
createBucketSet(params: CreateBucketSetInput!): BucketSetGQL!
|
createBucketSet(params: CreateBucketSetInput!): BucketSetGQL!
|
||||||
setLoggerLevel(path: String!, level: String!): Boolean!
|
setLoggerLevel(path: String!, level: String!): Boolean!
|
||||||
|
editShot(
|
||||||
|
shotId: Int!
|
||||||
|
fieldsToEdit: EditableShotFieldInputGQL!
|
||||||
|
): EditShotReturn!
|
||||||
addAnnotationToShot(
|
addAnnotationToShot(
|
||||||
shotId: Int!
|
shotId: Int!
|
||||||
annotationName: String!
|
annotationName: String!
|
||||||
@@ -742,6 +748,27 @@ input CreateBucketSetInput {
|
|||||||
buckets: [BucketInputGQL!]!
|
buckets: [BucketInputGQL!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EditShotReturn {
|
||||||
|
shot: ShotGQL
|
||||||
|
error: DoesNotOwnShotErr
|
||||||
|
}
|
||||||
|
|
||||||
|
type DoesNotOwnShotErr {
|
||||||
|
shotId: Int!
|
||||||
|
msg: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input EditableShotFieldInputGQL {
|
||||||
|
intendedPocketType: PocketEnum
|
||||||
|
shotDirection: ShotDirectionEnum
|
||||||
|
spinType: SpinTypeEnum
|
||||||
|
targetPocketAngleDirection: ShotDirectionEnum
|
||||||
|
make: Boolean
|
||||||
|
backcut: Boolean
|
||||||
|
excludeFromStats: Boolean
|
||||||
|
notes: String
|
||||||
|
}
|
||||||
|
|
||||||
type AddShotAnnotationReturn {
|
type AddShotAnnotationReturn {
|
||||||
value: SuccessfulAddAddShotAnnotationErrors!
|
value: SuccessfulAddAddShotAnnotationErrors!
|
||||||
}
|
}
|
||||||
@@ -762,11 +789,6 @@ union DoesNotOwnShotErrOtherErrorNeedsNote =
|
|||||||
DoesNotOwnShotErr
|
DoesNotOwnShotErr
|
||||||
| OtherErrorNeedsNote
|
| OtherErrorNeedsNote
|
||||||
|
|
||||||
type DoesNotOwnShotErr {
|
|
||||||
shotId: Int!
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type OtherErrorNeedsNote {
|
type OtherErrorNeedsNote {
|
||||||
msg: String
|
msg: String
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user