@streamlayer/feature-gamification 0.21.2 → 0.23.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.
- package/lib/gamification.d.ts +7 -25
- package/lib/gamification.js +57 -137
- package/lib/highlights.js +5 -6
- package/lib/onboarding.d.ts +23 -0
- package/lib/onboarding.js +116 -0
- package/lib/storage.d.ts +1 -1
- package/package.json +7 -7
package/lib/gamification.d.ts
CHANGED
|
@@ -6,23 +6,9 @@ import type { PlainMessage } from '@bufbuild/protobuf';
|
|
|
6
6
|
import { WritableAtom } from 'nanostores';
|
|
7
7
|
import * as queries from './queries';
|
|
8
8
|
import { leaderboard } from './leaderboard';
|
|
9
|
+
import { OnboardingStatus } from './onboarding';
|
|
9
10
|
import { LeaderboardItem } from './queries/leaderboard';
|
|
10
11
|
import { GamificationBackground } from './';
|
|
11
|
-
/**
|
|
12
|
-
* Required: in-app should be displayed and questions not available
|
|
13
|
-
* Optional: in-app should be displayed but questions are available
|
|
14
|
-
* Completed: user completed onboarding, cached in browser. Linked by eventId, organizationId and userId
|
|
15
|
-
* Disabled: no in-app but questions are available
|
|
16
|
-
* Unavailable: no in-app and questions not available [behavior is discussed]
|
|
17
|
-
*/
|
|
18
|
-
export declare enum OnboardingStatus {
|
|
19
|
-
Unset = "unset",
|
|
20
|
-
Required = "required",
|
|
21
|
-
Optional = "optional",
|
|
22
|
-
Completed = "completed",
|
|
23
|
-
Disabled = "disabled",
|
|
24
|
-
Unavailable = "unavailable"
|
|
25
|
-
}
|
|
26
12
|
/**
|
|
27
13
|
* Gamification (Games) Overlay
|
|
28
14
|
* Includes:
|
|
@@ -42,29 +28,25 @@ export declare class Gamification extends AbstractFeature<'games', PlainMessage<
|
|
|
42
28
|
/** leaderboard list */
|
|
43
29
|
leaderboardList: ReturnType<typeof leaderboard>;
|
|
44
30
|
/** onboarding status */
|
|
45
|
-
onboardingStatus:
|
|
31
|
+
onboardingStatus: {
|
|
32
|
+
$store: WritableAtom<OnboardingStatus | undefined>;
|
|
33
|
+
submitInplay: () => Promise<void>;
|
|
34
|
+
};
|
|
46
35
|
/** opened question */
|
|
47
36
|
openedQuestion: GamificationBackground['openedQuestion'];
|
|
48
37
|
/** pinned leaderboard id */
|
|
49
38
|
openedUser: WritableAtom<LeaderboardItem | undefined>;
|
|
39
|
+
closeFeature: () => void;
|
|
40
|
+
openFeature: () => void;
|
|
50
41
|
private notifications;
|
|
51
42
|
private transport;
|
|
52
|
-
private closeFeature;
|
|
53
|
-
private openFeature;
|
|
54
43
|
/** gamification background class, handle subscriptions and notifications for closed overlay */
|
|
55
44
|
private background;
|
|
56
45
|
/** Browser cache */
|
|
57
46
|
private storage;
|
|
58
47
|
constructor(config: FeatureProps, source: FeatureSource, instance: StreamLayerContext);
|
|
59
|
-
/**
|
|
60
|
-
* check onboarding status, sync with browser cache
|
|
61
|
-
* retrieve onboarding settings from api
|
|
62
|
-
*/
|
|
63
|
-
onboardingProcess: () => Promise<void>;
|
|
64
|
-
showOnboardingInApp: () => void;
|
|
65
48
|
connect: (transport: StreamLayerContext['transport']) => void;
|
|
66
49
|
disconnect: () => void;
|
|
67
|
-
submitInplay: () => Promise<void>;
|
|
68
50
|
submitAnswer: (questionId: string, answerId: string) => Promise<void>;
|
|
69
51
|
skipQuestion: (questionId: string) => Promise<void>;
|
|
70
52
|
openQuestion: (questionId: string) => void;
|
package/lib/gamification.js
CHANGED
|
@@ -6,24 +6,9 @@ import * as queries from './queries';
|
|
|
6
6
|
import * as actions from './queries/actions';
|
|
7
7
|
import { GamificationStorage } from './storage';
|
|
8
8
|
import { leaderboard } from './leaderboard';
|
|
9
|
+
import { onboarding } from './onboarding';
|
|
9
10
|
import { gamificationBackground } from './';
|
|
10
11
|
const GamificationQuestionTypes = new Set([QuestionType.POLL, QuestionType.PREDICTION, QuestionType.TRIVIA]);
|
|
11
|
-
/**
|
|
12
|
-
* Required: in-app should be displayed and questions not available
|
|
13
|
-
* Optional: in-app should be displayed but questions are available
|
|
14
|
-
* Completed: user completed onboarding, cached in browser. Linked by eventId, organizationId and userId
|
|
15
|
-
* Disabled: no in-app but questions are available
|
|
16
|
-
* Unavailable: no in-app and questions not available [behavior is discussed]
|
|
17
|
-
*/
|
|
18
|
-
export var OnboardingStatus;
|
|
19
|
-
(function (OnboardingStatus) {
|
|
20
|
-
OnboardingStatus["Unset"] = "unset";
|
|
21
|
-
OnboardingStatus["Required"] = "required";
|
|
22
|
-
OnboardingStatus["Optional"] = "optional";
|
|
23
|
-
OnboardingStatus["Completed"] = "completed";
|
|
24
|
-
OnboardingStatus["Disabled"] = "disabled";
|
|
25
|
-
OnboardingStatus["Unavailable"] = "unavailable";
|
|
26
|
-
})(OnboardingStatus || (OnboardingStatus = {}));
|
|
27
12
|
/**
|
|
28
13
|
* Gamification (Games) Overlay
|
|
29
14
|
* Includes:
|
|
@@ -48,10 +33,10 @@ export class Gamification extends AbstractFeature {
|
|
|
48
33
|
openedQuestion;
|
|
49
34
|
/** pinned leaderboard id */
|
|
50
35
|
openedUser;
|
|
51
|
-
notifications;
|
|
52
|
-
transport;
|
|
53
36
|
closeFeature;
|
|
54
37
|
openFeature;
|
|
38
|
+
notifications;
|
|
39
|
+
transport;
|
|
55
40
|
/** gamification background class, handle subscriptions and notifications for closed overlay */
|
|
56
41
|
background;
|
|
57
42
|
/** Browser cache */
|
|
@@ -64,131 +49,76 @@ export class Gamification extends AbstractFeature {
|
|
|
64
49
|
this.feedList = this.background.feedList;
|
|
65
50
|
this.openedUser = createSingleStore(undefined);
|
|
66
51
|
this.leaderboardId = new SingleStore(createSingleStore(this.settings.getValue('pinnedLeaderboardId')), 'pinnedLeaderboardId').getStore();
|
|
67
|
-
this.onboardingStatus =
|
|
52
|
+
this.onboardingStatus = onboarding(this, this.background, instance.transport, instance.notifications);
|
|
68
53
|
this.notifications = instance.notifications;
|
|
69
54
|
this.transport = instance.transport;
|
|
70
55
|
this.closeFeature = instance.sdk.closeFeature;
|
|
71
56
|
this.openFeature = () => instance.sdk.openFeature(FeatureType.GAMES);
|
|
72
57
|
this.openedQuestion = this.background.openedQuestion;
|
|
73
58
|
this.leaderboardList = leaderboard(this.transport, this.background.slStreamId);
|
|
74
|
-
this.onboardingStatus.subscribe((onboardingStatus) => {
|
|
75
|
-
if (onboardingStatus === OnboardingStatus.Optional || OnboardingStatus.Required) {
|
|
76
|
-
this.showOnboardingInApp();
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
59
|
this.status.subscribe((status) => {
|
|
80
60
|
if (status === FeatureStatus.Ready) {
|
|
81
|
-
this.notifications.close(this.background.getCurrentSessionId({ prefix: 'onboarding' }));
|
|
82
61
|
this.connect(instance.transport);
|
|
83
62
|
}
|
|
84
63
|
else {
|
|
85
64
|
this.disconnect();
|
|
86
65
|
}
|
|
87
66
|
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
});
|
|
67
|
+
/**
|
|
68
|
+
* listen for active question and show in-app notification
|
|
69
|
+
*/
|
|
93
70
|
this.background.activeQuestionId.listen((question) => {
|
|
94
|
-
if (question && question.data && this.onboardingStatus.get()) {
|
|
71
|
+
if (question && question.data && this.onboardingStatus.$store.get()) {
|
|
95
72
|
if (question.data.question?.id !== undefined &&
|
|
96
73
|
question.data.question.notification !== undefined &&
|
|
97
74
|
question.data.moderation?.bypassNotifications?.inAppSilence !== SilenceSetting.ON &&
|
|
98
|
-
GamificationQuestionTypes.has(question.data.question.type) &&
|
|
99
75
|
question.data.question.status === QuestionStatus.ACTIVE) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
76
|
+
if (GamificationQuestionTypes.has(question.data.question.type)) {
|
|
77
|
+
this.notifications.add({
|
|
78
|
+
type: NotificationType.QUESTION,
|
|
79
|
+
action: () => question.data?.question && this.openQuestion(question.data.question.id),
|
|
80
|
+
close: () => question.data?.question && this.closeQuestion(question.data.question.id),
|
|
81
|
+
autoHideDuration: 1000 * +(question.data.question?.appearance?.autoHideInterval || '5'),
|
|
82
|
+
id: this.background.getCurrentSessionId({ prefix: 'notification', entity: question.data.question.id }),
|
|
83
|
+
data: {
|
|
84
|
+
questionType: question.data.question.type,
|
|
85
|
+
question: {
|
|
86
|
+
title: question.data.question.notification.title,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else if (question.data.question.type === QuestionType.FACTOID) {
|
|
92
|
+
const instantView = {
|
|
93
|
+
heading: '',
|
|
94
|
+
body: '',
|
|
95
|
+
image: '',
|
|
96
|
+
video: {
|
|
97
|
+
id: '',
|
|
98
|
+
url: '',
|
|
99
|
+
thumbnailUrl: '',
|
|
100
|
+
},
|
|
101
|
+
webLink: {
|
|
102
|
+
label: '',
|
|
103
|
+
url: '',
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
this.notifications.add({
|
|
107
|
+
type: NotificationType.QUESTION,
|
|
108
|
+
action: () => question.data?.question && this.openQuestion(question.data.question.id),
|
|
109
|
+
close: () => question.data?.question && this.closeQuestion(question.data.question.id),
|
|
110
|
+
autoHideDuration: 1000 * +(question.data.question?.appearance?.autoHideInterval || '5'),
|
|
111
|
+
id: this.background.getCurrentSessionId({ prefix: 'notification', entity: question.data.question.id }),
|
|
112
|
+
data: {
|
|
113
|
+
questionType: question.data.question.type,
|
|
114
|
+
insight: instantView,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
});
|
|
117
|
-
void this.onboardingProcess();
|
|
118
|
-
this.background.userId.subscribe((userId) => {
|
|
119
|
-
if (userId) {
|
|
120
|
-
void this.onboardingProcess();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
this.background.moderation.subscribe((value) => {
|
|
124
|
-
if (value.data) {
|
|
125
|
-
void this.onboardingProcess();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
121
|
}
|
|
129
|
-
/**
|
|
130
|
-
* check onboarding status, sync with browser cache
|
|
131
|
-
* retrieve onboarding settings from api
|
|
132
|
-
*/
|
|
133
|
-
onboardingProcess = async () => {
|
|
134
|
-
const userId = this.background.userId.get();
|
|
135
|
-
if (!userId) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const onboardingStatus = this.storage.getOnboardingStatus({
|
|
139
|
-
userId,
|
|
140
|
-
organizationId: this.background.organizationId.get() || '',
|
|
141
|
-
eventId: this.background.slStreamId.get() || '',
|
|
142
|
-
});
|
|
143
|
-
if (onboardingStatus === OnboardingStatus.Completed) {
|
|
144
|
-
this.onboardingStatus.set(OnboardingStatus.Completed);
|
|
145
|
-
}
|
|
146
|
-
const moderation = await this.background.moderation.getValue();
|
|
147
|
-
if (this.onboardingStatus.get() === OnboardingStatus.Completed) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const onboardingEnabled = !!(moderation?.options?.onboardingEnabled && this.featureSettings.get().inplayGame?.onboarding?.completed);
|
|
151
|
-
const optIn = !!this.featureSettings.get().inplayGame?.titleCard?.optIn;
|
|
152
|
-
if (onboardingEnabled) {
|
|
153
|
-
if (optIn) {
|
|
154
|
-
this.onboardingStatus.set(OnboardingStatus.Required);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
this.onboardingStatus.set(OnboardingStatus.Optional);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
if (optIn) {
|
|
162
|
-
this.onboardingStatus.set(OnboardingStatus.Unavailable);
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
this.onboardingStatus.set(OnboardingStatus.Disabled);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
showOnboardingInApp = () => {
|
|
170
|
-
const { inplayGame } = this.featureSettings.get();
|
|
171
|
-
if (!inplayGame) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const { titleCard, overview } = inplayGame;
|
|
175
|
-
this.notifications.add({
|
|
176
|
-
type: NotificationType.ONBOARDING,
|
|
177
|
-
id: this.background.getCurrentSessionId({ prefix: 'onboarding' }),
|
|
178
|
-
action: this.openFeature,
|
|
179
|
-
close: this.closeFeature,
|
|
180
|
-
autoHideDuration: 100000,
|
|
181
|
-
data: {
|
|
182
|
-
header: titleCard?.header,
|
|
183
|
-
title: titleCard?.title,
|
|
184
|
-
subtitle: titleCard?.subtitle,
|
|
185
|
-
graphicBg: titleCard?.appearance?.graphic,
|
|
186
|
-
icon: titleCard?.media?.icon,
|
|
187
|
-
sponsorLogo: titleCard?.media?.sponsorLogo,
|
|
188
|
-
primaryColor: overview?.appearance?.primaryColor,
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
};
|
|
192
122
|
connect = (transport) => {
|
|
193
123
|
this.userSummary.invalidate();
|
|
194
124
|
this.leaderboardList.invalidate();
|
|
@@ -207,15 +137,18 @@ export class Gamification extends AbstractFeature {
|
|
|
207
137
|
const question = await queries.getQuestionByUser(id, transport);
|
|
208
138
|
const correctAnswer = question?.answers.find(({ correct }) => correct);
|
|
209
139
|
this.notifications.add({
|
|
210
|
-
type: NotificationType.
|
|
140
|
+
type: NotificationType.QUESTION_RESOLVED,
|
|
211
141
|
action: () => this.openQuestion(id),
|
|
212
142
|
close: () => this.closeQuestion(id),
|
|
213
143
|
autoHideDuration: 5000,
|
|
214
144
|
id: notificationId,
|
|
215
145
|
data: {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
:
|
|
146
|
+
questionType: QuestionType.PREDICTION,
|
|
147
|
+
question: {
|
|
148
|
+
title: correctAnswer?.youVoted
|
|
149
|
+
? `Congratulations! You answered correctly! You won ${correctAnswer.points} pts!`
|
|
150
|
+
: `Better luck next time! Correct: ${correctAnswer?.text}!`,
|
|
151
|
+
},
|
|
219
152
|
},
|
|
220
153
|
});
|
|
221
154
|
}
|
|
@@ -230,19 +163,6 @@ export class Gamification extends AbstractFeature {
|
|
|
230
163
|
disconnect = () => {
|
|
231
164
|
this.background.feedSubscription.removeListener('feed-subscription-questions-list');
|
|
232
165
|
};
|
|
233
|
-
// onboarding
|
|
234
|
-
submitInplay = async () => {
|
|
235
|
-
const eventId = this.background.slStreamId.get();
|
|
236
|
-
if (eventId) {
|
|
237
|
-
await actions.submitInplay(this.transport, eventId);
|
|
238
|
-
this.onboardingStatus.set(OnboardingStatus.Completed);
|
|
239
|
-
this.storage.saveOnboardingStatus({
|
|
240
|
-
organizationId: this.background.organizationId.get() || '',
|
|
241
|
-
userId: this.background.userId.get() || '',
|
|
242
|
-
eventId,
|
|
243
|
-
}, OnboardingStatus.Completed);
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
166
|
submitAnswer = async (questionId, answerId) => {
|
|
247
167
|
await actions.submitAnswer(this.transport, { questionId, answerId });
|
|
248
168
|
// Todo: add invalidate openedQuestion
|
package/lib/highlights.js
CHANGED
|
@@ -37,14 +37,13 @@ export class Highlights extends AbstractFeature {
|
|
|
37
37
|
type: NotificationType.QUESTION,
|
|
38
38
|
action: () => question.data?.question && this.openHighlight(question.data.question.id),
|
|
39
39
|
close: () => question.data?.question && this.closeHighlight(question.data.question.id),
|
|
40
|
-
autoHideDuration: +(question.data.
|
|
40
|
+
autoHideDuration: 1000 * +(question.data.question?.appearance?.autoHideInterval || '5'),
|
|
41
41
|
id: this.background.getCurrentSessionId({ prefix: 'notification', entity: question.data.question.id }),
|
|
42
42
|
data: {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
imagePosition: question.data.question.notification.imagePosition,
|
|
43
|
+
questionType: question.data.question.type,
|
|
44
|
+
question: {
|
|
45
|
+
title: question.data.question.notification.title,
|
|
46
|
+
},
|
|
48
47
|
},
|
|
49
48
|
});
|
|
50
49
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Transport } from '@streamlayer/sdk-web-api';
|
|
2
|
+
import { type Notifications } from '@streamlayer/sdk-web-notifications';
|
|
3
|
+
import { GamificationBackground } from './background';
|
|
4
|
+
import { Gamification } from './';
|
|
5
|
+
/**
|
|
6
|
+
* Required: in-app should be displayed and questions not available
|
|
7
|
+
* Optional: in-app should be displayed but questions are available
|
|
8
|
+
* Completed: user completed onboarding, cached in browser. Linked by eventId, organizationId and userId
|
|
9
|
+
* Disabled: no in-app but questions are available
|
|
10
|
+
* Unavailable: no in-app and questions not available [behavior is discussed]
|
|
11
|
+
*/
|
|
12
|
+
export declare enum OnboardingStatus {
|
|
13
|
+
Unset = "unset",
|
|
14
|
+
Required = "required",
|
|
15
|
+
Optional = "optional",
|
|
16
|
+
Completed = "completed",
|
|
17
|
+
Disabled = "disabled",
|
|
18
|
+
Unavailable = "unavailable"
|
|
19
|
+
}
|
|
20
|
+
export declare const onboarding: (service: Gamification, background: GamificationBackground, transport: Transport, notifications: Notifications) => {
|
|
21
|
+
$store: import("nanostores").WritableAtom<OnboardingStatus>;
|
|
22
|
+
submitInplay: () => Promise<void>;
|
|
23
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createSingleStore } from '@streamlayer/sdk-web-interfaces';
|
|
2
|
+
import { NotificationType } from '@streamlayer/sdk-web-notifications';
|
|
3
|
+
import { QuestionType } from '@streamlayer/sdk-web-types';
|
|
4
|
+
import { GamificationStorage } from './storage';
|
|
5
|
+
import { submitInplay as submitInplayApi } from './queries/actions';
|
|
6
|
+
/**
|
|
7
|
+
* Required: in-app should be displayed and questions not available
|
|
8
|
+
* Optional: in-app should be displayed but questions are available
|
|
9
|
+
* Completed: user completed onboarding, cached in browser. Linked by eventId, organizationId and userId
|
|
10
|
+
* Disabled: no in-app but questions are available
|
|
11
|
+
* Unavailable: no in-app and questions not available [behavior is discussed]
|
|
12
|
+
*/
|
|
13
|
+
export var OnboardingStatus;
|
|
14
|
+
(function (OnboardingStatus) {
|
|
15
|
+
OnboardingStatus["Unset"] = "unset";
|
|
16
|
+
OnboardingStatus["Required"] = "required";
|
|
17
|
+
OnboardingStatus["Optional"] = "optional";
|
|
18
|
+
OnboardingStatus["Completed"] = "completed";
|
|
19
|
+
OnboardingStatus["Disabled"] = "disabled";
|
|
20
|
+
OnboardingStatus["Unavailable"] = "unavailable";
|
|
21
|
+
})(OnboardingStatus || (OnboardingStatus = {}));
|
|
22
|
+
export const onboarding = (service, background, transport, notifications) => {
|
|
23
|
+
const storage = new GamificationStorage();
|
|
24
|
+
const $store = createSingleStore(OnboardingStatus.Unset);
|
|
25
|
+
const showOnboardingInApp = () => {
|
|
26
|
+
const { inplayGame = {} } = service.featureSettings.get();
|
|
27
|
+
const notificationId = background.getCurrentSessionId({ prefix: 'onboarding' });
|
|
28
|
+
notifications.add({
|
|
29
|
+
type: NotificationType.ONBOARDING,
|
|
30
|
+
id: notificationId,
|
|
31
|
+
action: service.openFeature,
|
|
32
|
+
close: () => {
|
|
33
|
+
notifications.markAsViewed(notificationId);
|
|
34
|
+
},
|
|
35
|
+
autoHideDuration: 1000000,
|
|
36
|
+
data: {
|
|
37
|
+
questionType: QuestionType.UNSET,
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
onboarding: { ...inplayGame },
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
$store.subscribe((onboardingStatus) => {
|
|
45
|
+
if (onboardingStatus === OnboardingStatus.Optional || OnboardingStatus.Required) {
|
|
46
|
+
showOnboardingInApp();
|
|
47
|
+
}
|
|
48
|
+
if (onboardingStatus === OnboardingStatus.Completed) {
|
|
49
|
+
background.activeQuestionId.invalidate();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* check onboarding status, sync with browser cache
|
|
54
|
+
* retrieve onboarding settings from api
|
|
55
|
+
*/
|
|
56
|
+
const onboardingProcess = async () => {
|
|
57
|
+
const userId = background.userId.get();
|
|
58
|
+
if (!userId) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const onboardingStatus = storage.getOnboardingStatus({
|
|
62
|
+
userId,
|
|
63
|
+
organizationId: background.organizationId.get() || '',
|
|
64
|
+
eventId: background.slStreamId.get() || '',
|
|
65
|
+
});
|
|
66
|
+
if (onboardingStatus === OnboardingStatus.Completed) {
|
|
67
|
+
$store.set(OnboardingStatus.Completed);
|
|
68
|
+
}
|
|
69
|
+
const moderation = await background.moderation.getValue();
|
|
70
|
+
if ($store.get() === OnboardingStatus.Completed) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const onboardingEnabled = !!(moderation?.options?.onboardingEnabled && service.featureSettings.get().inplayGame?.onboarding?.completed);
|
|
74
|
+
const optIn = !!service.featureSettings.get().inplayGame?.titleCard?.optIn;
|
|
75
|
+
if (onboardingEnabled) {
|
|
76
|
+
if (optIn) {
|
|
77
|
+
$store.set(OnboardingStatus.Required);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
$store.set(OnboardingStatus.Optional);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
if (optIn) {
|
|
85
|
+
$store.set(OnboardingStatus.Unavailable);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
$store.set(OnboardingStatus.Disabled);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
void onboardingProcess();
|
|
93
|
+
background.userId.subscribe((userId) => {
|
|
94
|
+
if (userId) {
|
|
95
|
+
void onboardingProcess();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
background.moderation.subscribe((value) => {
|
|
99
|
+
if (value.data) {
|
|
100
|
+
void onboardingProcess();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
const submitInplay = async () => {
|
|
104
|
+
const eventId = background.slStreamId.get();
|
|
105
|
+
if (eventId) {
|
|
106
|
+
await submitInplayApi(transport, eventId);
|
|
107
|
+
$store.set(OnboardingStatus.Completed);
|
|
108
|
+
storage.saveOnboardingStatus({
|
|
109
|
+
organizationId: background.organizationId.get() || '',
|
|
110
|
+
userId: background.userId.get() || '',
|
|
111
|
+
eventId,
|
|
112
|
+
}, OnboardingStatus.Completed);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
return { $store, submitInplay };
|
|
116
|
+
};
|
package/lib/storage.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamlayer/feature-gamification",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@bufbuild/protobuf": "^1.4.2",
|
|
6
6
|
"@streamlayer/sl-eslib": "^5.53.6",
|
|
7
7
|
"@fastify/deepmerge": "*",
|
|
8
8
|
"nanostores": "^0.9.5",
|
|
9
9
|
"@streamlayer/sdk-web-api": "^0.0.1",
|
|
10
|
-
"@streamlayer/sdk-web-
|
|
11
|
-
"@streamlayer/sdk-web-
|
|
12
|
-
"@streamlayer/sdk-web-
|
|
13
|
-
"@streamlayer/sdk-web-notifications": "^0.
|
|
14
|
-
"@streamlayer/sdk-web-storage": "^0.0.
|
|
15
|
-
"@streamlayer/sdk-web-types": "^0.
|
|
10
|
+
"@streamlayer/sdk-web-interfaces": "^0.18.14",
|
|
11
|
+
"@streamlayer/sdk-web-logger": "^0.0.3",
|
|
12
|
+
"@streamlayer/sdk-web-core": "^0.17.7",
|
|
13
|
+
"@streamlayer/sdk-web-notifications": "^0.12.0",
|
|
14
|
+
"@streamlayer/sdk-web-storage": "^0.0.3",
|
|
15
|
+
"@streamlayer/sdk-web-types": "^0.20.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"tslib": "^2.6.2"
|