@streamlayer/feature-gamification 1.13.4 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/advertisement/index.js +23 -22
- package/lib/background.d.ts +1 -0
- package/lib/background.js +29 -0
- package/lib/gamification.d.ts +3 -0
- package/lib/gamification.js +30 -0
- package/lib/queries/index.d.ts +19 -0
- package/lib/queries/index.js +29 -0
- package/package.json +9 -9
|
@@ -51,30 +51,31 @@ export const advertisement = ($slStreamId, $feedSubscription, instance) => {
|
|
|
51
51
|
const $store = createMapStore({});
|
|
52
52
|
const $activeAdvertisement = $activePromotionId($slStreamId, transport);
|
|
53
53
|
const open = (options) => {
|
|
54
|
+
const payload = $store.get();
|
|
55
|
+
const id = payload.data?.question.id;
|
|
56
|
+
const type = payload.data?.promotion?.type;
|
|
57
|
+
if (!id) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
eventBus.emit('advertisement', {
|
|
61
|
+
action: 'opened',
|
|
62
|
+
payload: {
|
|
63
|
+
id,
|
|
64
|
+
type,
|
|
65
|
+
hasBanner: adHasBanner(payload.data),
|
|
66
|
+
openedFrom: options?.fromNotification ? 'notification' : 'auto',
|
|
67
|
+
},
|
|
68
|
+
});
|
|
54
69
|
if (options?.fromNotification) {
|
|
55
70
|
$store.setKey('hasNotification', false);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
type,
|
|
65
|
-
hasBanner: adHasBanner(payload.data),
|
|
66
|
-
openedFrom: 'notification',
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
eventBus.emit('advertisement', {
|
|
70
|
-
action: 'notification-opened',
|
|
71
|
-
payload: {
|
|
72
|
-
id,
|
|
73
|
-
type,
|
|
74
|
-
hasBanner: adHasBanner(payload.data),
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
}
|
|
71
|
+
eventBus.emit('advertisement', {
|
|
72
|
+
action: 'notification-opened',
|
|
73
|
+
payload: {
|
|
74
|
+
id,
|
|
75
|
+
type,
|
|
76
|
+
hasBanner: adHasBanner(payload.data),
|
|
77
|
+
},
|
|
78
|
+
});
|
|
78
79
|
}
|
|
79
80
|
};
|
|
80
81
|
const markAsViewed = () => {
|
package/lib/background.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export declare class GamificationBackground {
|
|
|
37
37
|
/** last active question in feed */
|
|
38
38
|
activeQuestionId: ReturnType<typeof queries.$activeQuestion>;
|
|
39
39
|
feedList: ApiStore<GetApiResponseType<typeof queries.$feedList>>;
|
|
40
|
+
betPack: ApiStore<GetApiResponseType<typeof queries.$betPack>>;
|
|
40
41
|
/** moderation id */
|
|
41
42
|
moderationId: ReadableAtom<string | undefined>;
|
|
42
43
|
/** moderation */
|
package/lib/background.js
CHANGED
|
@@ -32,6 +32,7 @@ export class GamificationBackground {
|
|
|
32
32
|
/** last active question in feed */
|
|
33
33
|
activeQuestionId;
|
|
34
34
|
feedList;
|
|
35
|
+
betPack;
|
|
35
36
|
/** moderation id */
|
|
36
37
|
moderationId;
|
|
37
38
|
/** moderation */
|
|
@@ -57,6 +58,7 @@ export class GamificationBackground {
|
|
|
57
58
|
this.notifications = instance.notifications;
|
|
58
59
|
this.moderation = new ApiStore(queries.$moderation(this.slStreamId, instance.transport), 'gamification:moderation');
|
|
59
60
|
this.feedList = new ApiStore(queries.$feedList(this.slStreamId, this.interactiveAllowed, instance.transport), 'gamification:feedList');
|
|
61
|
+
this.betPack = new ApiStore(queries.$betPack(this.slStreamId, instance.transport), 'gamification:betPack');
|
|
60
62
|
this.activeQuestionId = queries.$activeQuestion(this.slStreamId, instance.transport);
|
|
61
63
|
this.openedQuestion = detail(instance.transport, this.openedQuestionId, this.feedList.getStore());
|
|
62
64
|
this.cancels.add(this.openedQuestionId.listen((item) => {
|
|
@@ -78,6 +80,33 @@ export class GamificationBackground {
|
|
|
78
80
|
}
|
|
79
81
|
}));
|
|
80
82
|
this.feedSubscription = queries.feedSubscription(this.slStreamId, instance.transport);
|
|
83
|
+
this.cancels.add(this.feedSubscription.addListener('bet-pack-update', async (response) => {
|
|
84
|
+
const question = response.data?.attributes?.question;
|
|
85
|
+
if (question?.type === QuestionType.PREDICTION) {
|
|
86
|
+
const betPackData = this.betPack.getValues().data || {};
|
|
87
|
+
const betPackItem = betPackData?.[question.id];
|
|
88
|
+
if (betPackItem || Object.keys(betPackData).length < 5) {
|
|
89
|
+
const data = queries.$questionByUser(question.id, this.transport);
|
|
90
|
+
// order of operations is important here
|
|
91
|
+
const cancel = data.subscribe(() => { });
|
|
92
|
+
await data.get().promise;
|
|
93
|
+
// if question is not in the feed list, get extended question data from the server
|
|
94
|
+
let extendedQuestion = data.get().data;
|
|
95
|
+
if (!extendedQuestion) {
|
|
96
|
+
extendedQuestion = await queries.questionByUser(question.id, this.transport);
|
|
97
|
+
}
|
|
98
|
+
cancel();
|
|
99
|
+
window.requestAnimationFrame(() => {
|
|
100
|
+
data.invalidate();
|
|
101
|
+
});
|
|
102
|
+
// get extended question data and mark as dirty
|
|
103
|
+
this.betPack.getStore().mutate({
|
|
104
|
+
...betPackData,
|
|
105
|
+
[question.id]: extendedQuestion,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}));
|
|
81
110
|
this.cancels.add(this.feedSubscription.addListener('feed-subscription-active-question', (response) => {
|
|
82
111
|
const activeQuestionId = this.activeQuestionId.get().data?.question?.id;
|
|
83
112
|
const question = response.data?.attributes?.question;
|
package/lib/gamification.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class Gamification extends AbstractFeature<'games', PlainMessage<
|
|
|
25
25
|
userSummary: ReturnType<typeof summary>;
|
|
26
26
|
/** feed list (pick history) */
|
|
27
27
|
feedList: ApiStore<GetApiResponseType<typeof queries.$feedList>>;
|
|
28
|
+
/** list (pack) of predefined questions */
|
|
29
|
+
betPack: ApiStore<GetApiResponseType<typeof queries.$betPack>>;
|
|
28
30
|
/** friends list */
|
|
29
31
|
friends: ApiStore<GetApiResponseType<typeof queries.$friends>>;
|
|
30
32
|
/** pinned leaderboard id */
|
|
@@ -65,6 +67,7 @@ export declare class Gamification extends AbstractFeature<'games', PlainMessage<
|
|
|
65
67
|
checkInteractiveFlag: () => void;
|
|
66
68
|
connect: () => void;
|
|
67
69
|
disconnect: () => void;
|
|
70
|
+
betPackVote: (questionId: string, answerId: string) => Promise<void>;
|
|
68
71
|
submitAnswer: (questionId: string, answerId: string) => Promise<void>;
|
|
69
72
|
openQuestion: (questionId?: string, question?: FeedItem & {
|
|
70
73
|
openedFrom?: "list" | "notification";
|
package/lib/gamification.js
CHANGED
|
@@ -29,6 +29,8 @@ export class Gamification extends AbstractFeature {
|
|
|
29
29
|
userSummary;
|
|
30
30
|
/** feed list (pick history) */
|
|
31
31
|
feedList;
|
|
32
|
+
/** list (pack) of predefined questions */
|
|
33
|
+
betPack;
|
|
32
34
|
/** friends list */
|
|
33
35
|
friends;
|
|
34
36
|
/** pinned leaderboard id */
|
|
@@ -71,6 +73,7 @@ export class Gamification extends AbstractFeature {
|
|
|
71
73
|
this.openedQuestionId = this.background.openedQuestionId;
|
|
72
74
|
this.storage = new GamificationStorage();
|
|
73
75
|
this.feedList = this.background.feedList;
|
|
76
|
+
this.betPack = this.background.betPack;
|
|
74
77
|
this.friends = new ApiStore(queries.$friends(this.background.userId, instance.transport), 'gamification:friends');
|
|
75
78
|
this.currentUserId = this.background.userId;
|
|
76
79
|
this.openedUser = createSingleStore(undefined);
|
|
@@ -325,6 +328,33 @@ export class Gamification extends AbstractFeature {
|
|
|
325
328
|
this.background.feedSubscription.removeListener('feed-subscription-prediction-close');
|
|
326
329
|
this.background.feedSubscription.removeListener('feed-subscription-questions-list');
|
|
327
330
|
};
|
|
331
|
+
betPackVote = async (questionId, answerId) => {
|
|
332
|
+
await this.submitAnswer(questionId, answerId);
|
|
333
|
+
const betPackList = { ...this.betPack.getValues().data };
|
|
334
|
+
const question = betPackList?.[questionId];
|
|
335
|
+
if (question) {
|
|
336
|
+
question.answers = betPackList[questionId].answers.map((answer) => {
|
|
337
|
+
if (answer.id === answerId) {
|
|
338
|
+
return {
|
|
339
|
+
...answer,
|
|
340
|
+
youVoted: true,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
return answer;
|
|
344
|
+
});
|
|
345
|
+
eventBus.emit('poll', {
|
|
346
|
+
action: 'voted',
|
|
347
|
+
payload: {
|
|
348
|
+
questionId,
|
|
349
|
+
questionType: question.type,
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
this.betPack.getStore().mutate({
|
|
353
|
+
...betPackList,
|
|
354
|
+
[questionId]: question,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
};
|
|
328
358
|
submitAnswer = async (questionId, answerId) => {
|
|
329
359
|
const data = $questionByUser(questionId, this.transport);
|
|
330
360
|
const cancel = data.subscribe(() => { });
|
package/lib/queries/index.d.ts
CHANGED
|
@@ -116,6 +116,12 @@ export declare const feedSubscription: ($slStreamId: ReadableAtom<string | undef
|
|
|
116
116
|
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse;
|
|
117
117
|
readonly kind: import("@bufbuild/protobuf").MethodKind.ServerStreaming;
|
|
118
118
|
};
|
|
119
|
+
readonly betPack: {
|
|
120
|
+
readonly name: "BetPack";
|
|
121
|
+
readonly I: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackRequest;
|
|
122
|
+
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackResponse;
|
|
123
|
+
readonly kind: import("@bufbuild/protobuf").MethodKind.Unary;
|
|
124
|
+
};
|
|
119
125
|
};
|
|
120
126
|
}, SubscriptionRequest, SubscriptionResponse, "subscription" | "votingSubscription" | "questionSubscription" | "feedSubscription", ((request: import("@bufbuild/protobuf").PartialMessage<SubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<SubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<VotingSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<VotingSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<QuestionSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<QuestionSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse>)>;
|
|
121
127
|
export declare const votingSubscription: (params: {
|
|
@@ -232,6 +238,12 @@ export declare const votingSubscription: (params: {
|
|
|
232
238
|
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse;
|
|
233
239
|
readonly kind: import("@bufbuild/protobuf").MethodKind.ServerStreaming;
|
|
234
240
|
};
|
|
241
|
+
readonly betPack: {
|
|
242
|
+
readonly name: "BetPack";
|
|
243
|
+
readonly I: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackRequest;
|
|
244
|
+
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackResponse;
|
|
245
|
+
readonly kind: import("@bufbuild/protobuf").MethodKind.Unary;
|
|
246
|
+
};
|
|
235
247
|
};
|
|
236
248
|
}, VotingSubscriptionRequest, VotingSubscriptionResponse, "subscription" | "votingSubscription" | "questionSubscription" | "feedSubscription", ((request: import("@bufbuild/protobuf").PartialMessage<SubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<SubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<VotingSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<VotingSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<QuestionSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<QuestionSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse>)>;
|
|
237
249
|
export declare const questionSubscription: (questionId: string, transport: Transport) => import("packages/sdk-web-api/lib/grpc/subscription").ServerStreamSubscription<import("@bufbuild/protobuf").ServiceType, import("@bufbuild/protobuf").Message<import("@bufbuild/protobuf").AnyMessage>, import("@bufbuild/protobuf").Message<import("@bufbuild/protobuf").AnyMessage>, never, never> | import("packages/sdk-web-api/lib/grpc/subscription").ServerStreamSubscription<{
|
|
@@ -345,6 +357,12 @@ export declare const questionSubscription: (questionId: string, transport: Trans
|
|
|
345
357
|
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse;
|
|
346
358
|
readonly kind: import("@bufbuild/protobuf").MethodKind.ServerStreaming;
|
|
347
359
|
};
|
|
360
|
+
readonly betPack: {
|
|
361
|
+
readonly name: "BetPack";
|
|
362
|
+
readonly I: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackRequest;
|
|
363
|
+
readonly O: typeof import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").BetPackResponse;
|
|
364
|
+
readonly kind: import("@bufbuild/protobuf").MethodKind.Unary;
|
|
365
|
+
};
|
|
348
366
|
};
|
|
349
367
|
}, QuestionSubscriptionRequest, QuestionSubscriptionResponse, "subscription" | "votingSubscription" | "questionSubscription" | "feedSubscription", ((request: import("@bufbuild/protobuf").PartialMessage<SubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<SubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<VotingSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<VotingSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<QuestionSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<QuestionSubscriptionResponse>) | ((request: import("@bufbuild/protobuf").PartialMessage<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionRequest>, options?: import("@connectrpc/connect").CallOptions) => AsyncIterable<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedSubscriptionResponse>)>;
|
|
350
368
|
export declare const getQuestionByUser: (questionId: string, transport: Transport) => Promise<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").ExtendedQuestion | undefined>;
|
|
@@ -416,3 +434,4 @@ export declare const $activePromotionId: ($slStreamId: ReadableAtom<string | und
|
|
|
416
434
|
export { $userSummary, $leaderboardList } from './leaderboard';
|
|
417
435
|
export { $friends } from './friends';
|
|
418
436
|
export { $moderation } from './moderation';
|
|
437
|
+
export declare const $betPack: ($slStreamId: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<Record<string, import("@bufbuild/protobuf").PlainMessage<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").ExtendedQuestion>> | null, any>;
|
package/lib/queries/index.js
CHANGED
|
@@ -170,3 +170,32 @@ export const $activePromotionId = ($slStreamId, transport) => {
|
|
|
170
170
|
export { $userSummary, $leaderboardList } from './leaderboard';
|
|
171
171
|
export { $friends } from './friends';
|
|
172
172
|
export { $moderation } from './moderation';
|
|
173
|
+
export const $betPack = ($slStreamId, transport) => {
|
|
174
|
+
const { client, queryKey } = transport.createPromiseClient(Feed, {
|
|
175
|
+
method: 'betPack',
|
|
176
|
+
params: [$slStreamId],
|
|
177
|
+
});
|
|
178
|
+
return transport.nanoquery.createFetcherStore(queryKey, {
|
|
179
|
+
fetcher: async (_, __, slStreamId) => {
|
|
180
|
+
if (!slStreamId) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const res = await client.betPack({
|
|
184
|
+
eventId: slStreamId,
|
|
185
|
+
types: [QuestionType.PREDICTION],
|
|
186
|
+
statuses: [QuestionStatus.ACTIVE, QuestionStatus.RESOLVED],
|
|
187
|
+
limit: 5,
|
|
188
|
+
sort: {
|
|
189
|
+
field: 'activated_at',
|
|
190
|
+
order: 'asc',
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
if (!res.data || !res.data.length) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return res.data?.reduce((acc, item) => item?.attributes?.question?.id ? { ...acc, [item.attributes.question.id]: item.attributes.question } : acc, {});
|
|
197
|
+
},
|
|
198
|
+
dedupeTime: 0,
|
|
199
|
+
refetchInterval: 0,
|
|
200
|
+
});
|
|
201
|
+
};
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamlayer/feature-gamification",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.1",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@bufbuild/protobuf": "^1.10.0",
|
|
6
6
|
"@fastify/deepmerge": "^2.0.0",
|
|
7
|
-
"@streamlayer/sl-eslib": "^5.
|
|
7
|
+
"@streamlayer/sl-eslib": "^5.149.1",
|
|
8
8
|
"nanostores": "^0.10.3",
|
|
9
|
-
"@streamlayer/sdk-web-api": "^1.
|
|
10
|
-
"@streamlayer/sdk-web-interfaces": "^1.4.
|
|
11
|
-
"@streamlayer/sdk-web-
|
|
12
|
-
"@streamlayer/sdk-web-
|
|
13
|
-
"@streamlayer/sdk-web-notifications": "^1.3.
|
|
14
|
-
"@streamlayer/sdk-web-storage": "^1.0.
|
|
15
|
-
"@streamlayer/sdk-web-types": "^1.
|
|
9
|
+
"@streamlayer/sdk-web-api": "^1.7.1",
|
|
10
|
+
"@streamlayer/sdk-web-interfaces": "^1.4.10",
|
|
11
|
+
"@streamlayer/sdk-web-core": "^1.10.1",
|
|
12
|
+
"@streamlayer/sdk-web-logger": "^1.0.44",
|
|
13
|
+
"@streamlayer/sdk-web-notifications": "^1.3.6",
|
|
14
|
+
"@streamlayer/sdk-web-storage": "^1.0.44",
|
|
15
|
+
"@streamlayer/sdk-web-types": "^1.10.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"tslib": "^2.7.0"
|