@streamlayer/feature-gamification 1.15.1 → 1.16.0

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.
@@ -1,15 +1,3 @@
1
1
  import { AdCampaigns } from '@streamlayer/sdk-web-types';
2
2
  export declare const processGamAdvertisement: ({ gamOptions, gamBaseUrl }: AdCampaigns) => string;
3
- type GamHandlers = {
4
- onPlay?: () => void;
5
- onStop?: () => void;
6
- onProgress?: (opts: {
7
- adBreakDuration: number;
8
- adPosition: number;
9
- currentTime: number;
10
- duration: number;
11
- totalAds: number;
12
- }) => void;
13
- };
14
- export declare const gam: (adContainer: HTMLDivElement, url: string, { onPlay, onStop, onProgress }: GamHandlers) => () => () => void;
15
- export {};
3
+ export declare const gam: (adContainer: HTMLDivElement, url: string) => () => Promise<URL | undefined>;
@@ -1,3 +1,4 @@
1
+ import { validate as uuidValidate, v5 as uuid5, v4 as uuid4 } from 'uuid';
1
2
  const encodeUrl = (urlStr) => {
2
3
  const isUrl = urlStr.startsWith('http://') || urlStr.startsWith('https://');
3
4
  if (!isUrl) {
@@ -42,65 +43,54 @@ export const processGamAdvertisement = ({ gamOptions, gamBaseUrl }) => {
42
43
  }
43
44
  return url + params.join('&');
44
45
  };
45
- export const gam = (adContainer, url, { onPlay, onStop, onProgress }) => {
46
+ export const gam = (adContainer, url) => {
46
47
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
47
48
  // @ts-expect-error
48
- const ima = google.ima;
49
- let adDisplayContainer = new ima.AdDisplayContainer(adContainer);
50
- let adsLoader = new ima.AdsLoader(adDisplayContainer);
51
- let adsRequest = new ima.AdsRequest();
52
- let adsManager;
53
- adsLoader.addEventListener(ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, (adsManagerLoadedEvent) => {
54
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
- adsManager = adsManagerLoadedEvent.getAdsManager(adContainer);
56
- if (onPlay) {
57
- adsManager.addEventListener(ima.AdEvent.Type.STARTED, onPlay);
58
- }
59
- if (onStop) {
60
- adsManager.addEventListener(ima.AdEvent.Type.COMPLETE, onStop);
61
- }
62
- if (onProgress) {
63
- adsManager.addEventListener(ima.AdEvent.Type.AD_PROGRESS, (d) => onProgress(d.getAdData()));
64
- }
65
- adsManager.init(adContainer.clientWidth, adContainer.clientHeight, ima.ViewMode.NORMAL);
66
- adsManager.start();
67
- }, false);
68
- adsLoader.addEventListener(ima.AdErrorEvent.Type.AD_ERROR, () => {
69
- console.log('ad error');
70
- onStop?.();
71
- }, false);
72
- adsRequest.linearAdSlotWidth = adContainer.clientWidth;
73
- adsRequest.linearAdSlotHeight = adContainer.clientHeight;
74
- // adsRequest.nonLinearAdSlotWidth = adContainer.clientWidth ??
75
- // adsRequest.nonLinearAdSlotHeight = adContainer.clientHeight / 3 ??
76
- adsRequest.adTagUrl = url;
77
- adsLoader.requestAds(adsRequest);
78
- const destroy = () => {
79
- adsManager?.destroy();
80
- adsLoader?.destroy();
81
- adDisplayContainer?.destroy();
82
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
83
- // @ts-expect-error
84
- adDisplayContainer = undefined;
85
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
86
- // @ts-expect-error
87
- adsLoader = undefined;
88
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
89
- // @ts-expect-error
90
- adsRequest = undefined;
91
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
92
- // @ts-expect-error
93
- adsManager = undefined;
94
- };
95
- const play = () => {
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ const pal = goog.pal;
51
+ const consentSettings = new pal.ConsentSettings();
52
+ consentSettings.allowStorage = false;
53
+ const nonceLoader = new pal.NonceLoader(consentSettings);
54
+ const generateUrl = async () => {
96
55
  try {
97
- adDisplayContainer.initialize();
56
+ const parsedUrl = new URL(url);
57
+ const request = new pal.NonceRequest();
58
+ let deviceId = localStorage.getItem('sl-device-id') || uuid4();
59
+ let sessionId = sessionStorage.getItem('sl-ad-session-id');
60
+ if (!sessionId) {
61
+ sessionId = uuid4();
62
+ sessionStorage.setItem('sl-ad-session-id', sessionId);
63
+ }
64
+ if (!uuidValidate(deviceId)) {
65
+ deviceId = uuid5(`https://${deviceId}`, uuid5.URL);
66
+ }
67
+ request.adWillAutoPlay = parsedUrl.searchParams.get('vpa') === 'auto';
68
+ request.adWillPlayMuted = parsedUrl.searchParams.get('vpmute') === '1';
69
+ request.continuousPlayback = true;
70
+ request.descriptionUrl = parsedUrl.searchParams.get('description_url') || '';
71
+ request.iconsSupported = true;
72
+ request.sessionId = deviceId;
73
+ // Player support for VPAID 2.0, OMID 1.0, and SIMID 1.1
74
+ request.supportedApiFrameworks = '2,7,9';
75
+ request.videoHeight = adContainer.clientHeight;
76
+ request.videoWidth = adContainer.clientWidth;
77
+ const nonceManager = await nonceLoader.loadNonceManager(request);
78
+ parsedUrl.searchParams.set('givn', nonceManager.getNonce());
79
+ if (parsedUrl.searchParams.get('is_lat') === '[placeholder]') {
80
+ parsedUrl.searchParams.set('is_lat', '1');
81
+ }
82
+ if (parsedUrl.searchParams.get('rdid') === '[placeholder]') {
83
+ parsedUrl.searchParams.set('rdid', deviceId);
84
+ }
85
+ if (parsedUrl.searchParams.get('correlator') === '[placeholder]') {
86
+ parsedUrl.searchParams.set('correlator', sessionId);
87
+ }
88
+ return parsedUrl;
98
89
  }
99
90
  catch (adError) {
100
- onStop?.();
101
91
  console.log('AdsManager could not be started', adError);
92
+ return undefined;
102
93
  }
103
- return destroy;
104
94
  };
105
- return play;
95
+ return generateUrl;
106
96
  };
@@ -39,6 +39,6 @@ export declare const advertisement: ($slStreamId: GamificationBackground["slStre
39
39
  fromNotification?: boolean;
40
40
  }) => void;
41
41
  markAsViewed: () => void;
42
- $store: import("nanostores").MapStore<Advertisement>;
42
+ $store: import("nanostores").PreinitializedMapStore<Advertisement> & object;
43
43
  };
44
44
  export {};
@@ -6,28 +6,6 @@ import { $activePromotionId, getPromotionDetail } from '../queries';
6
6
  import { AdvertisementStorage } from './storage';
7
7
  import { parsePromotion } from './utils';
8
8
  import { processGamAdvertisement } from './externalAd';
9
- // async function generateNonce() {
10
- // const request = new goog.pal.NonceRequest()
11
- // request.adWillAutoPlay = true
12
- // request.adWillPlayMuted = false
13
- // request.continuousPlayback = false
14
- // request.descriptionUrl = 'https://example.com'
15
- // request.iconsSupported = true
16
- // request.playerType = 'Sample Player Type'
17
- // request.playerVersion = '1.0'
18
- // request.ppid = 'Sample PPID'
19
- // request.sessionId = 'Sample SID'
20
- // // Player support for VPAID 2.0, OMID 1.0, and SIMID 1.1
21
- // request.supportedApiFrameworks = '2,7,9'
22
- // request.url = 'https://developers.google.com/ad-manager/pal/html5'
23
- // request.videoHeight = 480
24
- // request.videoWidth = 640
25
- // const consentSettings = new goog.pal.ConsentSettings()
26
- // consentSettings.allowStorage = true
27
- // const nonceLoader = new goog.pal.NonceLoader(consentSettings)
28
- // const manager = await nonceLoader.loadNonceManager(request)
29
- // return manager.getNonce()
30
- // }
31
9
  const adHasBanner = (data) => (data?.promotion?.type === PromotionType.INGAME_IAB11_LBAR ||
32
10
  data?.promotion?.type === PromotionType.INGAME_IAB21_LBAR) &&
33
11
  !!data.promotion.additionalBanner?.imageUrl;
@@ -47,7 +47,7 @@ export declare class GamificationBackground {
47
47
  feedSubscription: ReturnType<typeof queries.feedSubscription>;
48
48
  /** subscription to opened question (vote percentage) */
49
49
  questionSubscription?: ReturnType<typeof queries.questionSubscription>;
50
- advertisement: ReturnType<typeof advertisement>;
50
+ advertisement?: ReturnType<typeof advertisement>;
51
51
  storage: GamificationStorage;
52
52
  private notifications;
53
53
  private log;
package/lib/background.js CHANGED
@@ -60,9 +60,10 @@ export class GamificationBackground {
60
60
  this.openedQuestionId = new SingleStore(createSingleStore(undefined), 'openedQuestionId').getStore();
61
61
  this.notifications = instance.notifications;
62
62
  this.moderation = new ApiStore(queries.$moderation(this.slStreamId, instance.transport), 'gamification:moderation');
63
- this.feedList = new ApiStore(queries.$feedList(this.slStreamId, this.interactiveAllowed, instance.transport), 'gamification:feedList');
63
+ const onlyBetPack = !!instance.sdk.options.get().betPack;
64
+ this.feedList = new ApiStore(queries.$feedList(this.slStreamId, this.interactiveAllowed, onlyBetPack, instance.transport), 'gamification:feedList');
64
65
  this.betPack = new ApiStore(queries.$betPack(this.slStreamId, this.userId, this.organizationId, this.storage, instance.transport), 'gamification:betPack');
65
- this.activeQuestionId = queries.$activeQuestion(this.slStreamId, instance.transport);
66
+ this.activeQuestionId = queries.$activeQuestion(this.slStreamId, onlyBetPack, instance.transport);
66
67
  this.openedQuestion = detail(instance.transport, this.openedQuestionId, this.feedList.getStore());
67
68
  this.cancels.add(this.openedQuestionId.listen((item) => {
68
69
  this.log.debug({ item }, 'received question');
@@ -71,14 +72,19 @@ export class GamificationBackground {
71
72
  this.questionSubscription.addListener('feed-subscription-opened-question', async (response) => {
72
73
  const question = response.data?.attributes?.question;
73
74
  this.openedQuestion.updateExtendedQuestion(question);
74
- if (question?.type === QuestionType.PREDICTION) {
75
+ if (question?.type === QuestionType.PREDICTION &&
76
+ (question.status === QuestionStatus.ACTIVE || question.status === QuestionStatus.RESOLVED)) {
75
77
  const betPackData = this.betPack.getValues().data || {};
76
78
  const betPackItem = betPackData?.[question.id];
77
79
  if (betPackItem || Object.keys(betPackData).length < 5) {
78
80
  const data = queries.$questionByUser(question.id, this.transport);
79
81
  const cancel = data.subscribe(() => { });
80
82
  await data.get().promise;
81
- const extendedQuestion = await queries.questionByUser(question.id, this.transport);
83
+ // if question is not in the feed list, get extended question data from the server
84
+ let extendedQuestion = data.get().data;
85
+ if (!extendedQuestion) {
86
+ extendedQuestion = await queries.questionByUser(question.id, this.transport);
87
+ }
82
88
  cancel();
83
89
  window.requestAnimationFrame(() => {
84
90
  data.invalidate();
@@ -104,7 +110,8 @@ export class GamificationBackground {
104
110
  this.feedSubscription = queries.feedSubscription(this.slStreamId, instance.transport);
105
111
  this.cancels.add(this.feedSubscription.addListener('bet-pack-update', async (response) => {
106
112
  const question = response.data?.attributes?.question;
107
- if (question?.type === QuestionType.PREDICTION) {
113
+ if (question?.type === QuestionType.PREDICTION &&
114
+ (question.status === QuestionStatus.ACTIVE || question.status === QuestionStatus.RESOLVED)) {
108
115
  const betPackData = this.betPack.getValues().data || {};
109
116
  const betPackItem = betPackData?.[question.id];
110
117
  if (betPackItem || Object.keys(betPackData).length < 5) {
@@ -201,7 +208,9 @@ export class GamificationBackground {
201
208
  }
202
209
  };
203
210
  });
204
- this.advertisement = advertisement(this.slStreamId, this.feedSubscription, instance);
211
+ if (!onlyBetPack) {
212
+ this.advertisement = advertisement(this.slStreamId, this.feedSubscription, instance);
213
+ }
205
214
  }
206
215
  /**
207
216
  * Get id for notifications and link with current session
package/lib/deepLink.d.ts CHANGED
@@ -6,7 +6,7 @@ type DeepLinkData = {
6
6
  error?: string;
7
7
  };
8
8
  export declare const deepLink: (transport: Transport, $eventId: ReadableAtom<string | undefined>, $externalEventId: ReadableAtom<string | undefined>, $userId: ReadableAtom<string | undefined>) => {
9
- $store: import("nanostores").MapStore<DeepLinkData>;
9
+ $store: import("nanostores").PreinitializedMapStore<DeepLinkData> & object;
10
10
  fetch: typeof fetch;
11
11
  };
12
12
  export {};
@@ -53,6 +53,7 @@ export declare class Gamification extends AbstractFeature<'games', PlainMessage<
53
53
  advertisement: GamificationBackground['advertisement'];
54
54
  onboardingProcessed: WritableAtom<boolean>;
55
55
  friendsTabEnabled: WritableAtom<boolean>;
56
+ skipOnboarding: boolean;
56
57
  private notifications;
57
58
  private transport;
58
59
  /** gamification background class, handle subscriptions and notifications for closed overlay */
@@ -70,7 +71,7 @@ export declare class Gamification extends AbstractFeature<'games', PlainMessage<
70
71
  betPackVote: (questionId: string, answerId: string) => Promise<void>;
71
72
  submitAnswer: (questionId: string, answerId: string) => Promise<void>;
72
73
  openQuestion: (questionId?: string, question?: FeedItem & {
73
- openedFrom?: "list" | "notification";
74
+ openedFrom?: "list" | "notification" | "bet-pack";
74
75
  }) => void | (() => void);
75
76
  getFeedItem: (id: string) => Promise<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedItem | undefined>;
76
77
  isOpenedQuestion: (questionId: string) => boolean;
@@ -53,6 +53,7 @@ export class Gamification extends AbstractFeature {
53
53
  advertisement;
54
54
  onboardingProcessed;
55
55
  friendsTabEnabled;
56
+ skipOnboarding;
56
57
  notifications;
57
58
  transport;
58
59
  /** gamification background class, handle subscriptions and notifications for closed overlay */
@@ -76,9 +77,6 @@ export class Gamification extends AbstractFeature {
76
77
  this.currentUserId = this.background.userId;
77
78
  this.onboardingProcessed = createSingleStore(!instance.sdk.withAuth);
78
79
  this.leaderboardId = new SingleStore(createSingleStore(this.settings.getValue('pinnedLeaderboardId')), 'pinnedLeaderboardId').getStore();
79
- this.onboardingStatus = onboarding(this, this.background, instance.transport, instance.notifications, {
80
- skipOnboarding: instance.sdk.options.get().skipOnboarding,
81
- });
82
80
  this.notifications = instance.notifications;
83
81
  this.transport = instance.transport;
84
82
  this.closeFeature = (destroy = true) => instance.sdk.closeFeature(destroy);
@@ -98,6 +96,15 @@ export class Gamification extends AbstractFeature {
98
96
  }));
99
97
  }
100
98
  this.connect();
99
+ this.skipOnboarding = !!instance.sdk.options.get().skipOnboarding;
100
+ this.onboardingStatus = onboarding(this, this.background, instance.transport, instance.notifications, {
101
+ skipOnboarding: instance.sdk.options.get().skipOnboarding,
102
+ });
103
+ if (!instance.sdk.options.get().skipOnboarding) {
104
+ this.onboardingStatus = onboarding(this, this.background, instance.transport, instance.notifications, {
105
+ skipOnboarding: instance.sdk.options.get().skipOnboarding,
106
+ });
107
+ }
101
108
  /**
102
109
  * listen for onboarding status, moderation onboarding changes and opt-in settings
103
110
  */
@@ -137,16 +144,21 @@ export class Gamification extends AbstractFeature {
137
144
  return this.background.interactiveAllowed.get() === InteractiveAllowed.ALLOWED;
138
145
  }
139
146
  checkInteractiveFlag = () => {
140
- const onboardingStatus = this.onboardingStatus.$store.get();
141
- const onboardingEnabled = this.background.moderation.getStore().value?.data?.options?.onboardingEnabled;
142
- const optInEnabled = this.settings.getValues().inplayGame?.titleCard?.optIn;
143
- const onboardingCompleted = onboardingStatus === OnboardingStatus.Completed;
144
- const allowed = !onboardingEnabled || onboardingCompleted || optInEnabled !== true;
145
- this.background.interactiveAllowed.set(allowed ? InteractiveAllowed.ALLOWED : InteractiveAllowed.DISALLOWED);
147
+ if (this.skipOnboarding) {
148
+ this.background.interactiveAllowed.set(InteractiveAllowed.ALLOWED);
149
+ }
150
+ else {
151
+ const onboardingStatus = this.onboardingStatus.$store.get();
152
+ const onboardingEnabled = this.background.moderation.getStore().value?.data?.options?.onboardingEnabled;
153
+ const optInEnabled = this.settings.getValues().inplayGame?.titleCard?.optIn;
154
+ const onboardingCompleted = onboardingStatus === OnboardingStatus.Completed;
155
+ const allowed = !onboardingEnabled || onboardingCompleted || optInEnabled !== true;
156
+ this.background.interactiveAllowed.set(allowed ? InteractiveAllowed.ALLOWED : InteractiveAllowed.DISALLOWED);
157
+ }
146
158
  };
147
159
  connect = () => {
148
160
  this.onboardingProcessed.subscribe((status) => {
149
- if (status) {
161
+ if (status && this.advertisement) {
150
162
  this.advertisement.connect();
151
163
  }
152
164
  });
@@ -332,7 +344,7 @@ export class Gamification extends AbstractFeature {
332
344
  this.background.feedSubscription.removeListener('feed-subscription-questions-list');
333
345
  };
334
346
  betPackVote = async (questionId, answerId) => {
335
- await this.submitAnswer(questionId, answerId);
347
+ await actions.submitAnswer(this.transport, { questionId, answerId });
336
348
  const betPackList = { ...this.betPack.getValues().data };
337
349
  const question = betPackList?.[questionId];
338
350
  if (question) {
@@ -343,6 +355,16 @@ export class Gamification extends AbstractFeature {
343
355
  questionType: question.type,
344
356
  },
345
357
  });
358
+ question.answers = question.answers.map((answer) => {
359
+ if (answer.id === answerId) {
360
+ return {
361
+ ...answer,
362
+ youVoted: true,
363
+ };
364
+ }
365
+ return answer;
366
+ });
367
+ this.betPack.getStore().mutate(betPackList);
346
368
  }
347
369
  };
348
370
  submitAnswer = async (questionId, answerId) => {
@@ -423,14 +445,17 @@ export class Gamification extends AbstractFeature {
423
445
  if (!questionId) {
424
446
  return () => { };
425
447
  }
426
- this.notifications.close(this.background.getCurrentSessionId({
427
- prefix: 'notification',
428
- entity: questionId,
429
- }), {
430
- animateHiding: false,
431
- });
448
+ const openedFromBetPack = question?.openedFrom === 'bet-pack';
449
+ if (openedFromBetPack) {
450
+ this.notifications.close(this.background.getCurrentSessionId({
451
+ prefix: 'notification',
452
+ entity: questionId,
453
+ }), {
454
+ animateHiding: false,
455
+ });
456
+ }
432
457
  let questionType = question?.attributes?.type;
433
- if (!questionType) {
458
+ if (!questionType && !openedFromBetPack) {
434
459
  const feedList = this.feedList.getStore().value?.data || [];
435
460
  questionType = feedList.find((item) => item.id === questionId)?.attributes?.type;
436
461
  }
@@ -445,13 +470,20 @@ export class Gamification extends AbstractFeature {
445
470
  payload: {
446
471
  questionId,
447
472
  questionType,
448
- questionOpenedFrom: question?.openedFrom,
473
+ questionOpenedFrom: question?.openedFrom === 'bet-pack' ? 'list' : question?.openedFrom,
449
474
  },
450
475
  });
451
476
  this.storage.saveQuestionOpened(flags, questionId);
452
477
  }
453
- this.openFeature();
454
- return this.background.openQuestion(questionId, question);
478
+ if (!openedFromBetPack) {
479
+ this.openFeature();
480
+ }
481
+ return this.background.openQuestion(questionId, question
482
+ ? {
483
+ ...question,
484
+ openedFrom: question?.openedFrom === 'bet-pack' ? 'list' : question?.openedFrom,
485
+ }
486
+ : undefined);
455
487
  };
456
488
  getFeedItem = (id) => {
457
489
  return queries.getFeedItem(id, this.transport);
@@ -578,7 +610,7 @@ export class Gamification extends AbstractFeature {
578
610
  questionType: question.data.question.type,
579
611
  insight: instantView,
580
612
  inApp: {
581
- useMediaFromContent: optionsValue.useAsNotification === UseAsNotification.ENABLED,
613
+ useMediaFromContent: optionsValue?.useAsNotification === UseAsNotification.ENABLED,
582
614
  notification: question.data.question.notification,
583
615
  appearance: question.data.question.appearance,
584
616
  sponsorship: question.data.question.sponsorship,
@@ -15,7 +15,7 @@ type LeaderboardStore = {
15
15
  error?: string;
16
16
  };
17
17
  export declare const leaderboard: (transport: Transport, $eventId: ReadableAtom<string | undefined>, $userId: ReadableAtom<string | undefined>, $friends: Gamification["friends"], options?: LeaderboardOptions) => {
18
- $store: import("nanostores").MapStore<LeaderboardStore>;
18
+ $store: import("nanostores").PreinitializedMapStore<LeaderboardStore> & object;
19
19
  fetchMore: (page?: number) => void;
20
20
  invalidate: () => void;
21
21
  };
@@ -20,6 +20,6 @@ export declare enum OnboardingStatus {
20
20
  export declare const onboarding: (service: Gamification, background: GamificationBackground, transport: Transport, notifications: Notifications, options?: {
21
21
  skipOnboarding?: boolean;
22
22
  }) => {
23
- $store: import("nanostores").WritableAtom<OnboardingStatus>;
23
+ $store: import("nanostores").PreinitializedWritableAtom<OnboardingStatus> & object;
24
24
  submitInplay: () => Promise<void>;
25
25
  };
package/lib/onboarding.js CHANGED
@@ -75,7 +75,7 @@ const onboardingProcess = ($store, background, service, notifications, storage,
75
75
  userId,
76
76
  eventId,
77
77
  }, OnboardingStatus.Completed);
78
- void submitInplayApi(transport, background.slStreamId.get() || '');
78
+ void submitInplayApi(transport, eventId);
79
79
  }
80
80
  return;
81
81
  }
@@ -4,7 +4,7 @@ import { ReadableAtom } from 'nanostores';
4
4
  import type { SubscriptionRequest, SubscriptionResponse, VotingSubscriptionRequest, VotingSubscriptionResponse, QuestionSubscriptionRequest, QuestionSubscriptionResponse } from '@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb';
5
5
  import { InteractiveAllowed } from '../background';
6
6
  import { GamificationStorage } from '../storage';
7
- export declare const $activeQuestion: (slStreamId: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedQuestion | undefined, any>;
7
+ export declare const $activeQuestion: (slStreamId: ReadableAtom<string | undefined>, onlyBetPack: boolean, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedQuestion | undefined, any>;
8
8
  export declare const getFeedItem: (questionId: string, transport: Transport) => Promise<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedItem | undefined>;
9
9
  export declare const feedSubscription: ($slStreamId: ReadableAtom<string | undefined>, 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<{
10
10
  readonly typeName: "streamlayer.interactive.feed.Feed";
@@ -366,7 +366,6 @@ export declare const questionSubscription: (questionId: string, transport: Trans
366
366
  };
367
367
  };
368
368
  }, 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>)>;
369
- export declare const getQuestionByUser: (questionId: string, transport: Transport) => Promise<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").ExtendedQuestion | undefined>;
370
369
  export declare const getQuestionDetail: (questionId: string, transport: Transport) => Promise<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").Question | undefined>;
371
370
  export declare const questionByUser: ($questionId: string, transport: Transport) => Promise<import("@bufbuild/protobuf").PlainMessage<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").ExtendedQuestion>>;
372
371
  export declare const $questionByUser: ($questionId: ReadableAtom<string | undefined> | string, transport: Transport) => import("@nanostores/query").FetcherStore<import("@bufbuild/protobuf").PlainMessage<import("@streamlayer/sl-eslib/interactive/interactive.common_pb").ExtendedQuestion>, any>;
@@ -401,7 +400,7 @@ export declare const getPromotionDetail: (promoId: string, transport: Transport)
401
400
  notification: import("@streamlayer/sl-eslib/interactive/interactive.common_pb").QuestionNotification | undefined;
402
401
  } | undefined>;
403
402
  export declare const $pickHistory: (slStreamId: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<(import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").PickHistory | undefined)[], any>;
404
- export declare const $feedList: ($slStreamId: ReadableAtom<string | undefined>, $interactiveAllowed: ReadableAtom<InteractiveAllowed>, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedItem[], any>;
403
+ export declare const $feedList: ($slStreamId: ReadableAtom<string | undefined>, $interactiveAllowed: ReadableAtom<InteractiveAllowed>, onlyBetPack: boolean, transport: Transport) => import("@nanostores/query").FetcherStore<import("@streamlayer/sl-eslib/interactive/feed/interactive.feed_pb").FeedItem[], any>;
405
404
  export declare const $activePromotionId: ($slStreamId: ReadableAtom<string | undefined>, transport: Transport) => import("@nanostores/query").FetcherStore<{
406
405
  id: string;
407
406
  question: {
@@ -3,11 +3,14 @@ import { eventBus } from '@streamlayer/sdk-web-interfaces';
3
3
  import { atom } from 'nanostores';
4
4
  import { Feed } from '@streamlayer/sl-eslib/interactive/feed/interactive.feed_connect';
5
5
  import { InteractiveAllowed } from '../background';
6
- export const $activeQuestion = (slStreamId, transport) => {
7
- const { client, queryKey } = transport.createPromiseClient(Feed, { method: 'syncQuestion', params: [slStreamId] });
6
+ export const $activeQuestion = (slStreamId, onlyBetPack, transport) => {
7
+ const { client, queryKey } = transport.createPromiseClient(Feed, {
8
+ method: 'syncQuestion',
9
+ params: [slStreamId, onlyBetPack ? 'true' : ''],
10
+ });
8
11
  return transport.nanoquery.createFetcherStore(queryKey, {
9
- fetcher: async (_, __, id) => {
10
- if (!id) {
12
+ fetcher: async (_, __, id, onlyBetPack) => {
13
+ if (!id || onlyBetPack) {
11
14
  return undefined;
12
15
  }
13
16
  const res = await client.syncQuestion({
@@ -50,13 +53,6 @@ export const questionSubscription = (questionId, transport) => {
50
53
  const subscription = transport.addSubscription(client.questionSubscription, { questionId }, { name: 'questionSubscription' });
51
54
  return subscription;
52
55
  };
53
- export const getQuestionByUser = async (questionId, transport) => {
54
- const { client } = transport.createPromiseClient(Feed, { method: 'questionByUser', params: [questionId] });
55
- const res = await client.questionByUser({
56
- questionId: questionId,
57
- });
58
- return res.data?.attributes?.question;
59
- };
60
56
  export const getQuestionDetail = async (questionId, transport) => {
61
57
  const { client } = transport.createPromiseClient(Feed, { method: 'getQuestion', params: [questionId] });
62
58
  const res = await client.getQuestion({
@@ -112,14 +108,14 @@ export const $pickHistory = (slStreamId, transport) => {
112
108
  },
113
109
  });
114
110
  };
115
- export const $feedList = ($slStreamId, $interactiveAllowed, transport) => {
111
+ export const $feedList = ($slStreamId, $interactiveAllowed, onlyBetPack, transport) => {
116
112
  const { client, queryKey } = transport.createPromiseClient(Feed, {
117
113
  method: 'list',
118
- params: [$slStreamId, $interactiveAllowed],
114
+ params: [$slStreamId, $interactiveAllowed, onlyBetPack ? 'true' : ''],
119
115
  });
120
116
  return transport.nanoquery.createFetcherStore(queryKey, {
121
- fetcher: async (_, __, slStreamId, interactiveAllowed) => {
122
- if (!slStreamId) {
117
+ fetcher: async (_, __, slStreamId, interactiveAllowed, onlyBetPack) => {
118
+ if (!slStreamId || onlyBetPack) {
123
119
  return [];
124
120
  }
125
121
  const res = await client.list({
@@ -3,6 +3,6 @@ import { ReadableAtom } from 'nanostores';
3
3
  import { LeaderboardSummaryItem } from '@streamlayer/sl-eslib/interactive/leaderboard/interactive.leaderboard_pb';
4
4
  import { Gamification } from '.';
5
5
  export declare const summary: ($eventId: ReadableAtom<string | undefined>, $userId: ReadableAtom<string | undefined>, $friends: Gamification["friends"] | undefined, transport: Transport) => {
6
- $store: import("nanostores").MapStore<LeaderboardSummaryItem | undefined>;
6
+ $store: import("nanostores").PreinitializedMapStore<LeaderboardSummaryItem | undefined> & object;
7
7
  invalidate: () => void;
8
8
  };
@@ -15,7 +15,7 @@ export const summary = ($eventId, $userId, $friends, transport) => {
15
15
  .get()
16
16
  .data?.map((friend) => friend.slId)
17
17
  : [];
18
- if (!usersIds) {
18
+ if (!usersIds || !eventId || !userId) {
19
19
  return;
20
20
  }
21
21
  const request = {
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "@streamlayer/feature-gamification",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "peerDependencies": {
5
5
  "@bufbuild/protobuf": "^1.10.0",
6
6
  "@fastify/deepmerge": "^2.0.0",
7
7
  "@streamlayer/sl-eslib": "^5.149.1",
8
- "nanostores": "^0.10.3",
9
- "@streamlayer/sdk-web-api": "^1.7.3",
10
- "@streamlayer/sdk-web-core": "^1.11.1",
11
- "@streamlayer/sdk-web-interfaces": "^1.4.12",
12
- "@streamlayer/sdk-web-logger": "^1.0.46",
13
- "@streamlayer/sdk-web-notifications": "^1.3.8",
14
- "@streamlayer/sdk-web-storage": "^1.0.46",
15
- "@streamlayer/sdk-web-types": "^1.10.3"
8
+ "uuid": "^11.1.0",
9
+ "nanostores": "^0.11.4",
10
+ "@streamlayer/sdk-web-api": "^1.8.0",
11
+ "@streamlayer/sdk-web-core": "^1.11.2",
12
+ "@streamlayer/sdk-web-interfaces": "^1.4.13",
13
+ "@streamlayer/sdk-web-logger": "^1.0.47",
14
+ "@streamlayer/sdk-web-notifications": "^1.3.9",
15
+ "@streamlayer/sdk-web-storage": "^1.0.47",
16
+ "@streamlayer/sdk-web-types": "^1.10.4"
16
17
  },
17
18
  "devDependencies": {
18
19
  "tslib": "^2.7.0"