@cardsjd/portal 0.1.1 → 0.1.3

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.
@@ -5,18 +5,31 @@ export class FacebookPortal extends BasePortal {
5
5
  name = 'FacebookPortal';
6
6
  fBInstantGame = null;
7
7
 
8
- constructor(config, advertisementConfig) {
8
+ constructor(appConfig) {
9
9
  super();
10
- this.fBInstantGame = new FBInstantGame(config);
11
- this.advertisementConfig = advertisementConfig;
10
+ this.fBInstantGame = new FBInstantGame(appConfig);
11
+
12
+ this.appConfig = appConfig;
13
+
14
+ // Ad state
15
+ this.preloadedInterstitial = null;
16
+ this.preloadedRewardedVideo = null;
17
+ this._isAdLoading = false;
18
+ this._isAdLoaded = false;
19
+ this._isRewardedAdLoading = false;
20
+ this._isRewardedAdLoaded = false;
21
+ this._errorCount = 0;
22
+ this._errorCountMax = 6;
12
23
  }
24
+
13
25
  async init() {
14
26
  await this.fBInstantGame.initialize();
15
27
  }
16
- isAvailable() {
17
28
 
29
+ isAvailable() {
18
30
  return true;
19
31
  }
32
+
20
33
  async load() {
21
34
  const fbUserdata = await this.fBInstantGame.loadData();
22
35
  const fbProfile = await this.fBInstantGame.getProfile();
@@ -25,9 +38,11 @@ export class FacebookPortal extends BasePortal {
25
38
  data.user = fbProfile;
26
39
  return data;
27
40
  }
41
+
28
42
  async save(data, forceSave) {
29
43
  this.fBInstantGame.saveData(data, forceSave).catch(function () { });
30
44
  }
45
+
31
46
  gameStart() {
32
47
  }
33
48
 
@@ -51,31 +66,418 @@ export class FacebookPortal extends BasePortal {
51
66
  async subscribeBot() {
52
67
  await this.fBInstantGame.subscribeBot();
53
68
  }
69
+
54
70
  createShortCut() {
55
71
  this.fBInstantGame.createShortcut();
56
72
  }
73
+
57
74
  async getInvite() {
58
75
  //returns {message,room}
59
76
  return this.fBInstantGame.getInvite();
60
77
  }
78
+
61
79
  async invite(userId, room) {
62
80
  return this.fBInstantGame.invitePlayer(userId, room);
63
81
  }
82
+
64
83
  async findAndInvite(userFrom, room) {
65
84
  return this.fBInstantGame.inviteSend(userFrom, room);
66
85
  }
86
+
67
87
  async getFriends() {
68
88
  const fbUsers = await this.fBInstantGame.getConnectedPlayersAsync();
69
- if (!fbUsers) return [];
89
+ if (!fbUsers) {
90
+ return [];
91
+ }
92
+
70
93
  const friends = [];
71
94
  for (let i = 0; i < fbUsers.length; i++) {
72
95
  const fbUser = fbUsers[i];
73
96
 
74
97
  //Facebook only gaves the facebookid, no name or userid
75
98
  const facebookId = fbUser.getID();
76
- friends.push({ facebookId: facebookId });
99
+ friends.push({
100
+ facebookId: facebookId,
101
+ });
77
102
  }
103
+
78
104
  return friends;
79
105
  }
80
106
 
107
+ // ----- Ad methods -----
108
+
109
+ setupAds() {
110
+ console.log('FB_Ads.setup');
111
+
112
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
113
+ console.log('FBInstant plugin not ready'); return false;
114
+ }
115
+
116
+ this.isSetup = true;
117
+ return true;
118
+ }
119
+
120
+ isApiSupported(apiName) {
121
+ if (!globalThis.FBInstant) {
122
+ return false;
123
+ }
124
+
125
+ if (typeof globalThis.FBInstant[apiName] !== 'function') {
126
+ return false;
127
+ }
128
+
129
+ if (typeof globalThis.FBInstant.getSupportedAPIs !== 'function') {
130
+ return true;
131
+ }
132
+
133
+ try {
134
+ const supported = globalThis.FBInstant.getSupportedAPIs();
135
+ if (!Array.isArray(supported)) {
136
+ return true;
137
+ }
138
+
139
+ return supported.includes(apiName);
140
+ } catch (_ex) {
141
+ return true;
142
+ }
143
+ }
144
+
145
+ isErrorState() {
146
+ const isErrorState = this._errorCount > this._errorCountMax;
147
+ return isErrorState;
148
+ }
149
+
150
+ logError(errorCode) {
151
+ if (errorCode === 'ADS_NO_FILL') {
152
+ return;
153
+ }
154
+
155
+ if (errorCode === 'CLIENT_UNSUPPORTED_OPERATION') {
156
+ this._errorCount = this._errorCountMax;
157
+ }
158
+
159
+ this._errorCount = (this._errorCount || 0) + 1;
160
+ }
161
+
162
+ loadInterstitialAd(force) {
163
+ console.log('FB_Ads.loadInterstitialAd');
164
+
165
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
166
+ console.log('FBInstant plugin not ready'); return false;
167
+ }
168
+
169
+ if (!force && this._isAdLoading) {
170
+ console.log('FBInstant.loadInterstitialAd() - _isAdLoading = true');
171
+ return true;
172
+ }
173
+
174
+ if (!force && this._isAdLoaded) {
175
+ console.log('FBInstant.loadInterstitialAd() - _isAdLoaded = true');
176
+ return true;
177
+ }
178
+
179
+ if (!force && this.isErrorState()) {
180
+ console.log('FBInstant.loadInterstitialAd() - ErrorState = true');
181
+ return true;
182
+ }
183
+
184
+ this._isAdLoading = true;
185
+
186
+ const interstitialAdId = this.appConfig?.interstitalAdId;
187
+
188
+ console.log('FB_Ads.getInterstitialAdAsync start: ' + interstitialAdId);
189
+ if (!this.isApiSupported('getInterstitialAdAsync')) {
190
+ this._isAdLoading = false;
191
+ this._isAdLoaded = false;
192
+ this.logError('CLIENT_UNSUPPORTED_OPERATION');
193
+ console.warn('FBInstant.getInterstitialAdAsync is not supported on this client');
194
+ return false;
195
+ }
196
+
197
+ console.log('FB_Ads.getInterstitialAdAsync start: ' + this.appId);
198
+
199
+ try {
200
+ globalThis.FBInstant.getInterstitialAdAsync(
201
+ interstitialAdId, // Your Ad Placement Id
202
+ ).then((interstitial) => {
203
+ console.log('FB_Ads.getInterstitialAdAsync finished');
204
+ // Load the Ad asynchronously
205
+ this.preloadedInterstitial = interstitial;
206
+ return this.preloadedInterstitial.loadAsync();
207
+ }).then(() => {
208
+ this._isAdLoading = false;
209
+ this._isAdLoaded = true;
210
+
211
+ if (this.onAdLoaded) {
212
+ this.onAdLoaded({
213
+ adType: 'interstitial',
214
+ });
215
+ }
216
+
217
+ console.log('onAdLoaded: Interstitial preloaded');
218
+ }).catch((err) => {
219
+ this._isAdLoading = false;
220
+ this._isAdLoaded = false;
221
+
222
+ this.logError(err.code);
223
+
224
+ console.error('InterstitialAd Error: ' + err.message + ' ' + err.code);
225
+ });
226
+ } catch (ex) {
227
+ console.error('FB_Ads.getInterstitialAdAsync error: ' + ex);
228
+ }
229
+ }
230
+
231
+ showInterstitialAd() {
232
+ console.log('FB_Ads.showInterstitialAd');
233
+
234
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
235
+ console.log('FBInstant plugin not ready'); return false;
236
+ }
237
+
238
+ if (this.isErrorState()) {
239
+ console.log('FBInstant.showInterstitialAd() - ErrorState = true');
240
+ return true;
241
+ }
242
+
243
+ const isAdLoaded = this._isAdLoaded;
244
+
245
+ if (!isAdLoaded) {
246
+ this.loadInterstitialAd();
247
+ }
248
+
249
+ if (isAdLoaded) {
250
+ if (!this.preloadedInterstitial) {
251
+ console.log('FBInstant.showInterstitialAd() - error: preloadedInterstitial = null');
252
+ return false;
253
+ }
254
+
255
+ this.preloadedInterstitial.showAsync()
256
+ .then(() => {
257
+ // Perform post-ad success operation
258
+ console.log('Interstitial ad finished successfully');
259
+ this._isAdLoaded = false;
260
+
261
+ if (this.onAdClosed) {
262
+ this.onAdClosed({
263
+ adType: 'interstitial',
264
+ });
265
+ }
266
+ }).catch((err) => {
267
+
268
+ this.logError(err.code);
269
+ console.error('interstitialAd Error: ' + err.message + ' ' + err.code);
270
+
271
+ });
272
+ }
273
+
274
+ }
275
+
276
+ loadAndShowInterstitialAd() {
277
+ console.log('FB_Ads.showAd');
278
+
279
+ if (this.isErrorState()) {
280
+ console.log('FBInstant.loadAndShowInterstitialAd() - isErrorState = true');
281
+ return true;
282
+ }
283
+
284
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
285
+ console.log('FBInstant plugin not ready'); return false;
286
+ }
287
+
288
+ const interstitialAdId = this.appConfig?.interstitalAdId;
289
+ if (!this.isApiSupported('getInterstitialAdAsync')) {
290
+ this.logError('CLIENT_UNSUPPORTED_OPERATION');
291
+ console.warn('FBInstant.getInterstitialAdAsync is not supported on this client');
292
+ return false;
293
+ }
294
+ ////FBInstant.isGameStarted is a custom attached property, not from facebook. I am phaseing it out and hoping FBInstant will be ready when needed.
295
+ // if (!FBInstant.isGameStarted) {
296
+ // console.log('FBInstant plugin not ready: FBInstant.isGameStarted = false, aborting');
297
+ // return false;
298
+ // }
299
+
300
+ try {
301
+ globalThis.FBInstant.getInterstitialAdAsync(
302
+ interstitialAdId, // Your Ad Placement Id
303
+ ).then((interstitial) => {
304
+ console.log('FB_Ads.getInterstitialAdAsync finished');
305
+ // Load the Ad asynchronously
306
+ this.preloadedInterstitial = interstitial;
307
+ return this.preloadedInterstitial.loadAsync();
308
+ }).then(() => {
309
+ if (this.onAdLoaded) {
310
+ this.onAdLoaded({
311
+ adType: 'interstitial',
312
+ });
313
+ }
314
+
315
+ console.log('onAdLoaded: Interstitial preloaded');
316
+ return this.preloadedInterstitial.showAsync();
317
+ }).then(() => {
318
+ // Perform post-ad success operation
319
+ console.log('Interstitial ad finished successfully');
320
+
321
+ this._isAdLoaded = false;
322
+
323
+ if (this.onAdClosed) {
324
+ this.onAdClosed({
325
+ adType: 'interstitial',
326
+ });
327
+ }
328
+ }).catch((err) => {
329
+
330
+ this.logError(err.code);
331
+ console.error('InterstitialAd Error: ' + err.message + ' ' + err.code);
332
+
333
+ });
334
+
335
+ } catch (ex) {
336
+ console.error('FB_Ads.getInterstitialAdAsync error: ' + ex);
337
+ }
338
+ }
339
+
340
+ isAdLoaded() {
341
+ return this._isAdLoaded;
342
+ }
343
+
344
+ isRewardedAdLoaded() {
345
+ return this._isRewardedAdLoaded;
346
+ }
347
+
348
+ loadRewardedAd(onLoaded) {
349
+ console.log('FB_Ads.loadRewardedAd');
350
+
351
+ if (this.isErrorState()) {
352
+ console.log('FBInstant.loadRewardedAd() - isErrorState = true');
353
+ return true;
354
+ }
355
+
356
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
357
+ console.log('FBInstant plugin not ready'); return false;
358
+ }
359
+
360
+ const isAdLoaded = this._isRewardedAdLoaded;
361
+
362
+ if (!isAdLoaded) {
363
+ const rewardedAdId = this.appConfig?.rewardAdId;
364
+ if (!this.isApiSupported('getRewardedVideoAsync')) {
365
+ this._isRewardedAdLoaded = false;
366
+ this.logError('CLIENT_UNSUPPORTED_OPERATION');
367
+ console.warn('FBInstant.getRewardedVideoAsync is not supported on this client');
368
+ return false;
369
+ }
370
+
371
+ try {
372
+ globalThis.FBInstant.getRewardedVideoAsync(
373
+ rewardedAdId, // Your Ad Placement Id
374
+ ).then((rewarded) => {
375
+ console.log('FB_Ads.getRewardedVideoAsync finished');
376
+ // Load the Ad asynchronously
377
+ this.preloadedRewardedVideo = rewarded;
378
+ return this.preloadedRewardedVideo.loadAsync();
379
+ }).then(() => {
380
+ if (this.onAdLoaded) {
381
+ this.onAdLoaded({
382
+ adType: 'rewarded',
383
+ });
384
+ }
385
+
386
+ console.log('onAdLoaded: Rewarded preloaded');
387
+ this._isRewardedAdLoaded = true;
388
+
389
+ if (onLoaded) {
390
+ onLoaded();
391
+ }
392
+
393
+ }).catch((err) => {
394
+
395
+ this.logError(err.code);
396
+ console.error('loadRewardedAd Error: ' + err.message + ' ' + err.code);
397
+
398
+ });
399
+ } catch (ex) {
400
+ console.error('FB_Ads.getRewardedVideoAsync error: ' + ex);
401
+ }
402
+ }
403
+
404
+ if (isAdLoaded) {
405
+ console.log('requestRewardedAd is already loaded');
406
+ }
407
+
408
+ }
409
+
410
+ showRewardedAd() {
411
+ console.log('FB_Ads.ShowRewardedAd');
412
+
413
+ if (this.isErrorState()) {
414
+ console.log('FBInstant.ShowRewardedAd() - isErrorState = true');
415
+ return true;
416
+ }
417
+
418
+ if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
419
+ console.log('FBInstant plugin not ready'); return false;
420
+ }
421
+
422
+ const isAdLoaded = this._isRewardedAdLoaded;
423
+
424
+ if (!isAdLoaded) {
425
+ //change to auto play
426
+ this.loadRewardedAd(() => {
427
+ this.preloadedRewardedVideo.showAsync()
428
+ .then(() => {
429
+ // Perform post-ad success operation
430
+ console.log('Rewarded ad finished successfully');
431
+ this._isRewardedAdLoaded = false;
432
+
433
+ if (this.onAdClosed) {
434
+ this.onAdClosed({
435
+ adType: 'rewarded',
436
+ });
437
+ }
438
+
439
+ if (this.onAdRewarded) {
440
+ this.onAdRewarded({
441
+ adType: 'rewarded',
442
+ rewardAmount: 150,
443
+ });
444
+ }
445
+ }).catch((err) => {
446
+ this.logError(err.code);
447
+ console.error('RewardedAd Error: ' + err.message + ' ' + err.code);
448
+ });
449
+ });
450
+ }
451
+
452
+ if (isAdLoaded) {
453
+ this.preloadedRewardedVideo.showAsync()
454
+ .then(() => {
455
+ // Perform post-ad success operation
456
+ console.log('Rewarded ad finished successfully');
457
+ this._isRewardedAdLoaded = false;
458
+
459
+ if (this.onAdClosed) {
460
+ this.onAdClosed({
461
+ adType: 'rewarded',
462
+ });
463
+ }
464
+
465
+ if (this.onAdRewarded) {
466
+ this.onAdRewarded({
467
+ adType: 'rewarded',
468
+ rewardAmount: 150,
469
+ });
470
+ }
471
+ }).catch((err) => {
472
+
473
+ if (err && err.code === 'ADS_NO_FILL') { /* squelch */ } else {
474
+ this.logError();
475
+ }
476
+
477
+ console.error('RewardedAd Error: ' + err.message + ' ' + err.code);
478
+
479
+ });
480
+ }
481
+
482
+ }
81
483
  }
@@ -1,72 +1,107 @@
1
1
  import { BasePortal } from './BasePortal';
2
2
 
3
- const isGameDistribution = () => typeof globalThis.gdsdk !== 'undefined';
3
+ const AdType = {
4
+ Rewarded: 'rewarded',
5
+ Interstitial: 'interstitial',
6
+ };
4
7
 
5
- export class GameDistributionPortal extends BasePortal {
8
+ export class GameDistribution extends BasePortal {
6
9
  name = 'GameDistributionPortal';
7
- isInitialized = false;
8
- isError = false;
10
+ autoLogin = false;
9
11
 
10
- async init() {
12
+ constructor(appConfig) {
13
+ super();
14
+ this.appConfig = appConfig;
11
15
 
16
+ // Ad callback properties
17
+ this.onAdLoaded = null;
18
+ this.onAdOpened = null;
19
+ this.onAdClosed = null;
20
+ this.onAdError = null;
21
+ this.onAdRewarded = null;
22
+
23
+ this.adProviderName = 'GameDistribution';
24
+ this.isSetup = false;
25
+ this.isRewardedAdReady = false;
26
+ this.isInterstitialAdReady = false;
27
+ }
28
+
29
+ isReady() {
30
+ if (typeof globalThis.gdsdk === 'undefined') {
31
+ console.log('GameDistribution sdk not ready');
32
+ return false;
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // ----- Ad methods -----
39
+
40
+ async setupAds() {
41
+ if (!this.isReady()) {
42
+ return false;
43
+ }
44
+
45
+ if (this.isSetup) {
46
+ return true;
47
+ }
48
+
49
+ this.isSetup = true;
50
+
51
+ return true;
12
52
  }
13
53
 
14
- async load(userdata, advertisementConfig) {
15
- if (!this.isInitialized && advertisementConfig.gameDistributionId) {
16
- await this.#doInit(advertisementConfig.gameDistributionId);
54
+ async loadInterstitialAd() {
55
+ if (!this.isReady()) {
56
+ return false;
17
57
  }
18
58
 
19
- if (!isGameDistribution()) {
20
- return;
59
+ try {
60
+ await globalThis.gdsdk.preloadAd(AdType.Interstitial);
61
+ this.isInterstitialAdReady = true;
62
+ } catch {
63
+ this.isInterstitialAdReady = false;
21
64
  }
22
65
  }
23
66
 
24
- tryShowInterstitialAd() {
25
- if (!isGameDistribution()) {
26
- return;
67
+ async showInterstitialAd() {
68
+ if (!this.isReady()) {
69
+ return false;
27
70
  }
28
71
 
29
- globalThis?.gdsdk?.showAd?.();
72
+ return globalThis.gdsdk.showAd(AdType.Interstitial);
73
+ }
74
+
75
+ isAdLoaded() {
76
+ return this.isInterstitialAdReady;
30
77
  }
31
78
 
32
- async #doInit(gameId) {
33
- if (!this.isError) {
34
- globalThis.GD_OPTIONS = {
35
- gameId,
36
- onEvent: (event) => {
37
- this.#handleEvent(event);
38
- },
39
- };
79
+ isRewardedAdLoaded() {
80
+ return this.isRewardedAdReady;
81
+ }
40
82
 
83
+ async loadRewardedAd() {
84
+ if (!this.isReady()) {
85
+ return false;
86
+ }
87
+
88
+ (async () => {
41
89
  try {
42
- await import('https://html5.api.gamedistribution.com/main.min.js');
43
- this.isInitialized = true;
44
- } catch (err) {
45
- console.error('Failed to load GameDistribution');
46
- this.isError = true;
90
+ await globalThis.gdsdk.preloadAd(AdType.Rewarded);
91
+ this.isRewardedAdReady = true;
92
+
93
+ } catch (er) {
94
+ this.isRewardedAdReady = false;
47
95
  }
48
- }
96
+
97
+ })();
49
98
  }
50
99
 
51
- async #handleEvent(event) {
52
- console.log('got event from GD', event);
53
-
54
- switch (event.name) {
55
- case 'SDK_GAME_START':
56
- // advertisement done, resume game logic and unmute audio
57
- break;
58
- case 'SDK_GAME_PAUSE':
59
- // pause game logic / mute audio
60
- break;
61
- case 'SDK_GDPR_TRACKING':
62
- // this event is triggered when your user doesn't want to be tracked
63
- break;
64
- case 'SDK_GDPR_TARGETING':
65
- // this event is triggered when your user doesn't want personalised targeting of ads and such
66
- break;
67
- case 'SDK_REWARDED_WATCH_COMPLETE':
68
- // this event is triggered when your user completely watched rewarded ad
69
- break;
100
+ showRewardedAd() {
101
+ if (!this.isReady()) {
102
+ return false;
70
103
  }
104
+
105
+ return globalThis.gdsdk.showAd(AdType.Rewarded);
71
106
  }
72
- }
107
+ }