@mpgd/adapter-capacitor 0.12.4 → 0.13.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/README.md CHANGED
@@ -209,7 +209,7 @@ const gateway = createCapacitorPlatformGateway({ ..., providers: [notifications]
209
209
  ```
210
210
 
211
211
  <!--
212
- @link src/notifications-provider.ts#createCapacitorNotificationProvider Android omits advertising from remote purposes, waits for channels before register, refuses a token when channels cannot be created, ignores a dismiss, confirms an iOS schedule by content, and keeps a Doze-deferred alarm visible to cancellation.
212
+ @link src/notifications-provider.ts#createCapacitorNotificationProvider Android declares advertising like the FCM registry and registers rendersAdvertising with the shell's renderer, waits for channels before register, refuses a token when channels cannot be created, ignores a dismiss, confirms an iOS schedule by content, and keeps a Doze-deferred alarm visible to cancellation.
213
213
  @evidence ../../docs/specs/notifications/notifications-v2-rfc.md#profile-capacitor An Android FCM notification message cannot carry the opt-out action, and a killed-app tap is only in connectionOptions.notificationResponse.
214
214
  -->
215
215
  Create it once, early in startup: it registers its native listeners when it
@@ -321,14 +321,26 @@ is created, which is how a cold-start open reaches it.
321
321
  send names the category in `apns.payload.aps.category`.
322
322
  - The action opens the `optOutRoute` of the advertising topic the push names
323
323
  in its `topic` data key; without that key it opens nothing.
324
- - An Android FCM notification message cannot carry actions, so an Android
325
- advertising push needs the shell to render it natively with the action,
326
- which is not built yet (a follow-up after C1). Android `remote.purposes`
327
- still lists `advertising` so the provider pairs with the standard FCM
328
- registry, but `validateNotificationTopicCatalog` refuses a catalog that
329
- maps an advertising topic to `android`: the push would arrive without the
330
- opt-out action the Korean rules require (see the RFC's advertising
331
- rules). The kit's starter maps its sample advertising topic to iOS only.
324
+ - An Android FCM notification message cannot carry actions, so the shell
325
+ renders Android advertising pushes itself (AR1): the backend sends them
326
+ as data messages, and `dev.mpgd.capacitor.AdvertisingMessagingService`
327
+ from `@mpgd/capacitor-game-services`, declared as the shell's messaging
328
+ service in place of the messaging plugin's, posts them with the action.
329
+ Pass `advertisingRenderer: readCapacitorAdvertisingPushRenderer`: on
330
+ Android, with a catalog that maps an advertising topic, the provider
331
+ reads it once and registers `rendersAdvertising: true` when that service
332
+ is installed, and it announces its registration once the read answers,
333
+ so an app update that adds or removes the renderer reaches the backend
334
+ at its first start (once a player is signed in). Under the Korean rules the backend sends Android
335
+ advertising only to such an installation, and
336
+ `validateNotificationTopicCatalog` accepts an
337
+ advertising topic mapped to `android` only when the deployment sets
338
+ `shellRendersAdvertising: true`. Both taps open the game through the
339
+ messaging plugin as any push does; the plugin reports the action as a
340
+ `tap` with `mpgd.action: advertising-opt-out` in its data, which the
341
+ provider reads as the opt-out action. A read that fails or takes more
342
+ than five seconds counts as no renderer. The manifest lines are in the
343
+ [Firebase setup guide](../../docs/FIREBASE_NOTIFICATIONS.md#3-android).
332
344
  - **Settings.** Neither plugin opens the notification settings, so the
333
345
  provider takes an `openSettings` opener; without one `permission.settings`
334
346
  is `false` and `openSettings` answers `unavailable`.
@@ -405,6 +417,36 @@ iOS 13.6.0. Its Android default uses a dynamic patch selector; set
405
417
  `playServicesAdsVersion = '25.4.0'` in the game-owned `variables.gradle` to
406
418
  keep release builds reproducible until the plugin adopts a newer tested SDK.
407
419
 
420
+ Store declarations that come with AdMob:
421
+
422
+ - **Advertising ID (Android).** A shell generated without AdMob removes
423
+ `com.google.android.gms.permission.AD_ID` from the merged manifest
424
+ (`tools:node="remove"`). After installing AdMob, replace that line with
425
+ `<uses-permission android:name="com.google.android.gms.permission.AD_ID" />`
426
+ and answer "yes" to the Play Console advertising ID question; a production
427
+ build fails while the shell installs AdMob and still removes the permission,
428
+ unless `mpgd.game.json` records a deliberate no-advertising-ID policy with
429
+ `"ads": { "admob": { "advertisingId": "removed" } }` (for example a
430
+ child-directed game).
431
+ - **Application IDs.** A production build also fails when the Android
432
+ `com.google.android.gms.ads.APPLICATION_ID` meta-data or the iOS
433
+ `GADApplicationIdentifier` is missing (the SDK stops the app at launch), and
434
+ warns when `SKAdNetworkItems` lacks Google's `cstr6suwn9.skadnetwork`; copy
435
+ the current list from Google's
436
+ [SKAdNetwork page](https://developers.google.com/admob/ios/3p-skadnetworks).
437
+ - **app-ads.txt.** Set `ads.admob.publisherId` (`pub-` and 16 digits) in
438
+ `mpgd.game.json`, or keep a game-owned `legal/app-ads.txt` for mediation
439
+ lines, and `mpgd legal build` serves it at the legal site's root (and
440
+ removes an earlier `app-ads.txt` from the output once neither source
441
+ exists). The file
442
+ must sit at the root of the domain in the store listing (Play: developer
443
+ website; App Store: marketing URL), so serve the legal site from that
444
+ domain, not a subpath.
445
+ - **App Tracking Transparency.** The kit does no tracking and never shows the
446
+ ATT prompt. A game that adds tracking (IDFA, cross-app attribution) must add
447
+ `NSUserTrackingUsageDescription` and request ATT before it tracks, and answer
448
+ the App Store privacy questions accordingly.
449
+
408
450
  ```ts
409
451
  import { createCapacitorPlatformGateway } from '@mpgd/adapter-capacitor';
410
452
  import { createCapacitorAdMobRewardedProvider } from '@mpgd/adapter-capacitor/admob';
@@ -12,12 +12,22 @@ export declare const capacitorAdvertisingActionTypeId = "mpgd-advertising";
12
12
  /**
13
13
  * Keys of the push data the provider reads. A send carries the topic and the
14
14
  * topic's root-relative route in them; every other string entry reaches the
15
- * game as the open's untrusted `data`.
15
+ * game as the open's untrusted `data`, except the transport's keys and the
16
+ * Android advertising renderer's `mpgd.` keys. `action` is the renderer's
17
+ * mark on an open from its opt-out action, which the messaging plugin
18
+ * reports as a `tap` on Android.
16
19
  */
17
20
  export declare const capacitorNotificationDataKeys: Readonly<{
18
21
  readonly topic: 'topic';
19
22
  readonly route: 'route';
23
+ readonly action: 'mpgd.action';
20
24
  }>;
25
+ /**
26
+ * How long a registration waits for the Android advertising renderer read;
27
+ * a read that takes longer counts as no renderer, so registrations never
28
+ * stall on it.
29
+ */
30
+ export declare const capacitorAdvertisingRendererTimeoutMs = 5000;
21
31
  /** iOS keeps at most 64 pending local notifications per app. */
22
32
  export declare const capacitorIosMaxPendingLocalNotifications = 64;
23
33
  /** How long `openSettings` waits for the app to leave for the settings screen. */
@@ -60,6 +70,20 @@ export interface CreateCapacitorNotificationProviderInput {
60
70
  /** The title of the advertising opt-out action; '수신거부' when absent. */
61
71
  readonly advertisingOptOutTitle?: string;
62
72
  /**
73
+ * Android: whether the shell renders advertising pushes itself, with the
74
+ * opt-out action (`readCapacitorAdvertisingPushRenderer` over
75
+ * `@mpgd/capacitor-game-services`). An Android FCM notification message
76
+ * cannot carry actions, so the backend sends advertising to this
77
+ * installation only when its registration says `rendersAdvertising`, which
78
+ * the provider sets when this answers true. It is read once, when the
79
+ * provider is created, and only when the catalog maps an advertising
80
+ * topic to Android. A failure, or no answer within
81
+ * `capacitorAdvertisingRendererTimeoutMs`, reads as false and is reported;
82
+ * a shell whose plugin lacks the method (`UNIMPLEMENTED`) is not.
83
+ * Ignored on iOS, which shows the opt-out category's action itself.
84
+ */
85
+ readonly advertisingRenderer?: () => Promise<boolean>;
86
+ /**
63
87
  * Opens the OS notification settings for this app. Neither plugin can, so
64
88
  * the shell supplies it (for example a small native method). Without it
65
89
  * `permission.settings` is false and `openSettings` answers 'unavailable'.
@@ -16,12 +16,22 @@ export const capacitorAdvertisingActionTypeId = 'mpgd-advertising';
16
16
  /**
17
17
  * Keys of the push data the provider reads. A send carries the topic and the
18
18
  * topic's root-relative route in them; every other string entry reaches the
19
- * game as the open's untrusted `data`.
19
+ * game as the open's untrusted `data`, except the transport's keys and the
20
+ * Android advertising renderer's `mpgd.` keys. `action` is the renderer's
21
+ * mark on an open from its opt-out action, which the messaging plugin
22
+ * reports as a `tap` on Android.
20
23
  */
21
24
  export const capacitorNotificationDataKeys = Object.freeze({
22
25
  topic: 'topic',
23
26
  route: 'route',
27
+ action: 'mpgd.action',
24
28
  });
29
+ /**
30
+ * How long a registration waits for the Android advertising renderer read;
31
+ * a read that takes longer counts as no renderer, so registrations never
32
+ * stall on it.
33
+ */
34
+ export const capacitorAdvertisingRendererTimeoutMs = 5_000;
25
35
  /** iOS keeps at most 64 pending local notifications per app. */
26
36
  export const capacitorIosMaxPendingLocalNotifications = 64;
27
37
  /** How long `openSettings` waits for the app to leave for the settings screen. */
@@ -40,7 +50,7 @@ const extraKeys = Object.freeze({
40
50
  route: 'mpgdRoute',
41
51
  });
42
52
  /** Push data keys that are not the game's: the provider's own and the transport's. */
43
- const reservedDataKey = /^(?:topic|route|from|collapse_key|aps|fcm_options)$|^(?:google|gcm)\./u;
53
+ const reservedDataKey = /^(?:topic|route|from|collapse_key|aps|fcm_options)$|^(?:google|gcm|mpgd)\./u;
44
54
  const eventBufferLimit = 64;
45
55
  const maxNativeId = 0x7f_ff_ff_ff;
46
56
  /**
@@ -148,6 +158,39 @@ export function createCapacitorNotificationProvider(input) {
148
158
  // Reporting must not break the native listener that failed.
149
159
  }
150
160
  };
161
+ // Android advertising rendering: read once, before any registration
162
+ // names it. Only an Android catalog with an advertising topic asks.
163
+ let rendersAdvertising = false;
164
+ const rendererAsked = platform === 'android'
165
+ && push !== undefined
166
+ && input.advertisingRenderer !== undefined
167
+ && mappedTopics.some((topic) => topic.purpose === 'advertising');
168
+ const rendererRead = rendererAsked
169
+ ? (async () => {
170
+ let timer;
171
+ try {
172
+ const read = Promise.resolve().then(() => input.advertisingRenderer?.());
173
+ const late = new Promise((resolve) => {
174
+ timer = setTimeout(() => {
175
+ // A native call that never answers would otherwise go unnoticed.
176
+ reportError(new Error(`The advertising renderer read did not answer within ${capacitorAdvertisingRendererTimeoutMs} ms; `
177
+ + 'registering without rendersAdvertising.'));
178
+ resolve(false);
179
+ }, capacitorAdvertisingRendererTimeoutMs);
180
+ });
181
+ rendersAdvertising = (await Promise.race([read, late])) === true;
182
+ }
183
+ catch (error) {
184
+ // A shell built before the renderer answers UNIMPLEMENTED: it has none.
185
+ if (error?.code !== 'UNIMPLEMENTED') {
186
+ reportError(error);
187
+ }
188
+ }
189
+ finally {
190
+ clearTimeout(timer);
191
+ }
192
+ })()
193
+ : Promise.resolve();
151
194
  // Events.
152
195
  const listeners = new Set();
153
196
  const buffer = [];
@@ -295,12 +338,20 @@ export function createCapacitorNotificationProvider(input) {
295
338
  // FCM tokens only: `fcm-installation` addresses are reserved, because
296
339
  // FCM HTTP v1 cannot send to a Firebase installation id and the
297
340
  // game-services sender refuses them.
298
- address: { kind: 'fcm-token', value, permission },
341
+ address: {
342
+ kind: 'fcm-token',
343
+ value,
344
+ permission,
345
+ ...(rendersAdvertising ? { rendersAdvertising: true } : {}),
346
+ },
299
347
  ...(locale === undefined || locale === '' ? {} : { locale }),
300
348
  ...(timeZone === undefined || timeZone === '' ? {} : { timeZone }),
301
349
  };
302
350
  };
303
- const registrationOf = async (value) => registrationWith(value, await readAppState());
351
+ const registrationOf = async (value) => {
352
+ await rendererRead;
353
+ return registrationWith(value, await readAppState());
354
+ };
304
355
  /** The declared topic a push names; the payload is untrusted. */
305
356
  const declaredTopicOf = (data) => {
306
357
  return mappedTopic(stringOf(data[capacitorNotificationDataKeys.topic]));
@@ -315,10 +366,16 @@ export function createCapacitorNotificationProvider(input) {
315
366
  const data = isRecord(notification?.data) ? notification.data : {};
316
367
  const declared = declaredTopicOf(data);
317
368
  const topicId = declared?.id;
369
+ // On Android the messaging plugin reports every open as a `tap`; the
370
+ // advertising renderer marks one from its opt-out action in the data.
371
+ const action = actionId === 'tap'
372
+ && data[capacitorNotificationDataKeys.action] === notificationAdvertisingOptOutActionId
373
+ ? notificationAdvertisingOptOutActionId
374
+ : actionId;
318
375
  // The opt-out action opens the topic's declared opt-out screen, never a
319
376
  // route from the payload.
320
377
  let route;
321
- if (actionId !== notificationAdvertisingOptOutActionId) {
378
+ if (action !== notificationAdvertisingOptOutActionId) {
322
379
  route = safeRoute(data[capacitorNotificationDataKeys.route]);
323
380
  }
324
381
  else if (declared?.purpose === 'advertising') {
@@ -386,6 +443,7 @@ export function createCapacitorNotificationProvider(input) {
386
443
  ? lastObserved
387
444
  : undefined;
388
445
  const announcedNow = announced !== undefined && androidChannelsReady;
446
+ const announcedRendering = rendersAdvertising;
389
447
  if (announcedNow && announced !== undefined) {
390
448
  dispatch({
391
449
  type: 'endpoint-changed',
@@ -408,10 +466,10 @@ export function createCapacitorNotificationProvider(input) {
408
466
  if (registration === undefined || generation !== tokenGeneration) {
409
467
  return;
410
468
  }
411
- const permission = registration.address.kind === 'fcm-token'
412
- ? registration.address.permission
413
- : undefined;
414
- if (announcedNow && permission === announced) {
469
+ const address = registration.address.kind === 'fcm-token' ? registration.address : undefined;
470
+ if (announcedNow
471
+ && address?.permission === announced
472
+ && (address.rendersAdvertising === true) === announcedRendering) {
415
473
  return;
416
474
  }
417
475
  dispatch({ type: 'endpoint-changed', registration });
@@ -563,6 +621,48 @@ export function createCapacitorNotificationProvider(input) {
563
621
  ensureChannels().catch(reportSetupFailure);
564
622
  ensureActionTypes().catch(reportSetupFailure);
565
623
  }
624
+ // A shell update that adds or removes the renderer changes the
625
+ // registration without a new token, and Firebase announces a token only
626
+ // when it changes. Once the read answers, the current registration is
627
+ // announced; the runtime sends it only when it differs from the last one
628
+ // it sent, so an app update reaches the backend at its first start.
629
+ if (rendererAsked && configurationIssue === undefined && push !== undefined) {
630
+ const generation = tokenGeneration;
631
+ void (async () => {
632
+ await rendererRead;
633
+ let token;
634
+ try {
635
+ token = (await push.getToken()).token;
636
+ }
637
+ catch (error) {
638
+ // No token yet: `tokenReceived` announces the first one. A shell
639
+ // that cannot answer at all is reported, as `register()` does.
640
+ if (isConfigurationFailure(error)) {
641
+ reportError(error);
642
+ }
643
+ return;
644
+ }
645
+ if (typeof token !== 'string' || token === '' || generation !== tokenGeneration) {
646
+ return;
647
+ }
648
+ try {
649
+ await ensureChannels();
650
+ }
651
+ catch (error) {
652
+ reportSetupFailure(error);
653
+ // The foreground retry publishes this token once the channels exist.
654
+ if (generation === tokenGeneration && !androidChannelsReady) {
655
+ retainedToken = { token, generation };
656
+ }
657
+ return;
658
+ }
659
+ const registration = await registrationOf(token);
660
+ // A `tokenReceived` meanwhile announced its own, which is newer.
661
+ if (generation === tokenGeneration) {
662
+ dispatch({ type: 'endpoint-changed', registration });
663
+ }
664
+ })().catch(reportError);
665
+ }
566
666
  // Local reminder operations run one at a time: each reads the pending list
567
667
  // and decides from it, so two at once could both take the last free slot.
568
668
  let localQueue = Promise.resolve();
@@ -597,9 +697,9 @@ export function createCapacitorNotificationProvider(input) {
597
697
  // `createFcmProviderRegistration` publishes for android and ios.
598
698
  // `notificationRegistryMismatch` requires that list exactly; omitting
599
699
  // `advertising` on Android makes every standard pairing
600
- // `configuration-required`. An Android FCM notification message still
601
- // cannot carry the opt-out action: the catalog validator refuses an
602
- // advertising topic mapped to `android` until the shell renders it
700
+ // `configuration-required`. An Android FCM notification message
701
+ // cannot carry the opt-out action: the backend sends Android
702
+ // advertising only to a registration with `rendersAdvertising`
603
703
  // (RFC "Provider profiles", Capacitor).
604
704
  purposes: ['service', 'requested', 'advertising'],
605
705
  addressing: 'device',
@@ -0,0 +1,16 @@
1
+ import { type CapacitorGameServicesPlugin } from '@mpgd/capacitor-game-services';
2
+ /** The part of `@mpgd/capacitor-game-services` the renderer read calls. */
3
+ export type CapacitorAdvertisingPushRendererPlugin = Pick<CapacitorGameServicesPlugin, 'getAdvertisingPushRenderer'>;
4
+ /**
5
+ * Whether this Android shell renders advertising pushes itself, with the
6
+ * opt-out action: the messaging service Firebase Messaging resolves is the
7
+ * kit's renderer (`dev.mpgd.capacitor.AdvertisingMessagingService`, which
8
+ * `mpgd target init capacitor --providers notifications` declares in a new
9
+ * Android project). Pass it as the provider's `advertisingRenderer`, which
10
+ * then registers `rendersAdvertising` on Android. It throws when the plugin
11
+ * answers anything but `{ installed: boolean }`, which the provider reports;
12
+ * a shell built with an older plugin rejects it as `UNIMPLEMENTED`, which
13
+ * the provider reads as no renderer without reporting it. Either way the
14
+ * provider registers without the claim.
15
+ */
16
+ export declare function readCapacitorAdvertisingPushRenderer(plugin?: CapacitorAdvertisingPushRendererPlugin): Promise<boolean>;
@@ -0,0 +1,23 @@
1
+ import { CapacitorGameServices, } from '@mpgd/capacitor-game-services';
2
+ /**
3
+ * Whether this Android shell renders advertising pushes itself, with the
4
+ * opt-out action: the messaging service Firebase Messaging resolves is the
5
+ * kit's renderer (`dev.mpgd.capacitor.AdvertisingMessagingService`, which
6
+ * `mpgd target init capacitor --providers notifications` declares in a new
7
+ * Android project). Pass it as the provider's `advertisingRenderer`, which
8
+ * then registers `rendersAdvertising` on Android. It throws when the plugin
9
+ * answers anything but `{ installed: boolean }`, which the provider reports;
10
+ * a shell built with an older plugin rejects it as `UNIMPLEMENTED`, which
11
+ * the provider reads as no renderer without reporting it. Either way the
12
+ * provider registers without the claim.
13
+ */
14
+ export async function readCapacitorAdvertisingPushRenderer(plugin = CapacitorGameServices) {
15
+ const result = await plugin.getAdvertisingPushRenderer();
16
+ const installed = typeof result === 'object' && result !== null
17
+ ? result.installed
18
+ : undefined;
19
+ if (typeof installed !== 'boolean') {
20
+ throw new Error('The advertising push renderer read answered no installed flag.');
21
+ }
22
+ return installed;
23
+ }
@@ -1,9 +1,10 @@
1
1
  import { type CreateCapacitorNotificationProviderInput } from './notifications-provider.js';
2
2
  import type { CapacitorNotificationServiceProvider } from './providers.js';
3
3
  export { capacitorNotificationPluginNames, loadCapacitorNotificationSdks, type CapacitorNotificationSdkRuntime, type CapacitorNotificationSdks, type LoadCapacitorNotificationSdksInput, type LocalNotificationSdk, type LocalNotificationSdkActionType, type LocalNotificationSdkEntry, type LocalNotificationSdkSchema, type NotificationSdkChannel, type NotificationSdkPermissionState, type PushSdk, type PushSdkActionEvent, type PushSdkNotification, } from './notifications-sdk.js';
4
- export { capacitorAdvertisingActionTypeId, capacitorIosMaxPendingLocalNotifications, capacitorLocalNotificationId, capacitorNotificationChannelId, capacitorNotificationDataKeys, capacitorNotificationProviderId, capacitorSettingsLeaveTimeoutMs, capacitorSettingsReturnTimeoutMs, createCapacitorNotificationProvider, type CapacitorNotificationAppEvents, type CapacitorNotificationChannelSettings, type CapacitorNotificationProvider, type CreateCapacitorNotificationProviderInput, } from './notifications-provider.js';
4
+ export { capacitorAdvertisingActionTypeId, capacitorAdvertisingRendererTimeoutMs, capacitorIosMaxPendingLocalNotifications, capacitorLocalNotificationId, capacitorNotificationChannelId, capacitorNotificationDataKeys, capacitorNotificationProviderId, capacitorSettingsLeaveTimeoutMs, capacitorSettingsReturnTimeoutMs, createCapacitorNotificationProvider, type CapacitorNotificationAppEvents, type CapacitorNotificationChannelSettings, type CapacitorNotificationProvider, type CreateCapacitorNotificationProviderInput, } from './notifications-provider.js';
5
5
  export { createBridgeNotificationProvider, createNotificationProviderBridge, createNotificationServiceProvider, createNotificationSubscriptionAdapter, type CreateBridgeNotificationProviderInput, type CreateNotificationProviderBridgeInput, type CreateNotificationServiceProviderInput, type NotificationProviderBridge, } from './notifications-bridge.js';
6
6
  export { openCapacitorNotificationSettings, type CapacitorNotificationSettingsPlugin, } from './notifications-settings.js';
7
+ export { readCapacitorAdvertisingPushRenderer, type CapacitorAdvertisingPushRendererPlugin, } from './notifications-renderer.js';
7
8
  export type { CapacitorNotificationServiceProvider, CapacitorNotificationsV2Service, } from './providers.js';
8
9
  export interface CreateCapacitorNotificationServiceProviderInput extends CreateCapacitorNotificationProviderInput {
9
10
  /** The registry id; 'capacitor-notifications' when absent. */
@@ -6,9 +6,10 @@ import { createCapacitorNotificationProvider, } from './notifications-provider.j
6
6
  // optional `@capacitor-firebase/messaging` and `@capacitor/local-notifications`
7
7
  // peers; the base adapter entry loads neither.
8
8
  export { capacitorNotificationPluginNames, loadCapacitorNotificationSdks, } from './notifications-sdk.js';
9
- export { capacitorAdvertisingActionTypeId, capacitorIosMaxPendingLocalNotifications, capacitorLocalNotificationId, capacitorNotificationChannelId, capacitorNotificationDataKeys, capacitorNotificationProviderId, capacitorSettingsLeaveTimeoutMs, capacitorSettingsReturnTimeoutMs, createCapacitorNotificationProvider, } from './notifications-provider.js';
9
+ export { capacitorAdvertisingActionTypeId, capacitorAdvertisingRendererTimeoutMs, capacitorIosMaxPendingLocalNotifications, capacitorLocalNotificationId, capacitorNotificationChannelId, capacitorNotificationDataKeys, capacitorNotificationProviderId, capacitorSettingsLeaveTimeoutMs, capacitorSettingsReturnTimeoutMs, createCapacitorNotificationProvider, } from './notifications-provider.js';
10
10
  export { createBridgeNotificationProvider, createNotificationProviderBridge, createNotificationServiceProvider, createNotificationSubscriptionAdapter, } from './notifications-bridge.js';
11
11
  export { openCapacitorNotificationSettings, } from './notifications-settings.js';
12
+ export { readCapacitorAdvertisingPushRenderer, } from './notifications-renderer.js';
12
13
  /**
13
14
  * The provider and its registry entry in one call, with the same topics, for
14
15
  * `createCapacitorPlatformGateway({ providers: [...] })`:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/adapter-capacitor",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
4
4
  "description": "Capacitor platform adapter for mpgd Android and iOS shells.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -43,11 +43,11 @@
43
43
  ],
44
44
  "dependencies": {
45
45
  "@capacitor/app": "8.1.1",
46
- "@mpgd/game-services": "0.28.0",
47
- "@mpgd/bridge": "0.15.0",
48
- "@mpgd/platform": "0.27.2",
49
- "@mpgd/target-config": "0.23.7",
50
- "@mpgd/capacitor-game-services": "0.8.3"
46
+ "@mpgd/bridge": "0.16.1",
47
+ "@mpgd/capacitor-game-services": "0.9.0",
48
+ "@mpgd/game-services": "0.29.0",
49
+ "@mpgd/platform": "0.29.0",
50
+ "@mpgd/target-config": "0.23.9"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@capacitor-community/admob": "^8.1.0",
@@ -74,7 +74,7 @@
74
74
  "ttsc": "0.32.1",
75
75
  "typescript": "7.0.2",
76
76
  "vitest": "^4.0.0",
77
- "@mpgd/game-runtime": "0.8.1"
77
+ "@mpgd/game-runtime": "0.8.3"
78
78
  },
79
79
  "main": "./dist/index.js",
80
80
  "types": "./dist/index.d.ts",