react-native-qpush 0.0.0-stage → 1.0.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.
Files changed (98) hide show
  1. package/README.md +439 -2
  2. package/android/build.gradle +77 -0
  3. package/android/gradle.properties +5 -0
  4. package/android/proguard-rules.pro +5 -0
  5. package/android/src/main/AndroidManifest.xml +29 -0
  6. package/android/src/main/java/com/qpush/reactnative/QPushDeviceInfo.kt +96 -0
  7. package/android/src/main/java/com/qpush/reactnative/QPushEventBus.kt +153 -0
  8. package/android/src/main/java/com/qpush/reactnative/QPushFcm.kt +108 -0
  9. package/android/src/main/java/com/qpush/reactnative/QPushHttp.kt +92 -0
  10. package/android/src/main/java/com/qpush/reactnative/QPushImages.kt +103 -0
  11. package/android/src/main/java/com/qpush/reactnative/QPushLog.kt +39 -0
  12. package/android/src/main/java/com/qpush/reactnative/QPushMessagingService.kt +77 -0
  13. package/android/src/main/java/com/qpush/reactnative/QPushNotificationOpenActivity.kt +121 -0
  14. package/android/src/main/java/com/qpush/reactnative/QPushNotificationRenderer.kt +256 -0
  15. package/android/src/main/java/com/qpush/reactnative/QPushPayload.kt +114 -0
  16. package/android/src/main/java/com/qpush/reactnative/QPushPushModule.kt +368 -0
  17. package/android/src/main/java/com/qpush/reactnative/QPushPushPackage.kt +15 -0
  18. package/android/src/main/java/com/qpush/reactnative/QPushStore.kt +108 -0
  19. package/android/src/main/res/values/qpush_strings.xml +6 -0
  20. package/app.plugin.js +1 -0
  21. package/ios/Extension/QPushNotificationServiceExtension.swift +261 -0
  22. package/ios/Extension/QPushPushExtension.podspec +34 -0
  23. package/ios/QPushPush.m +62 -0
  24. package/ios/QPushPush.swift +186 -0
  25. package/ios/QPushPushBridge.h +5 -0
  26. package/ios/QPushPushCore.swift +457 -0
  27. package/ios/QPushPushHooks.m +237 -0
  28. package/ios/QPushPushSupport.swift +249 -0
  29. package/ios_nse_template/Info.plist +38 -0
  30. package/ios_nse_template/NotificationService.entitlements +10 -0
  31. package/ios_nse_template/NotificationService.swift +44 -0
  32. package/lib/NativeQPushPush.d.ts +44 -0
  33. package/lib/NativeQPushPush.js +4 -0
  34. package/lib/QPush.d.ts +117 -0
  35. package/lib/QPush.js +206 -0
  36. package/lib/core/QPushCore.d.ts +148 -0
  37. package/lib/core/QPushCore.js +1387 -0
  38. package/lib/core/constants.d.ts +37 -0
  39. package/lib/core/constants.js +40 -0
  40. package/lib/core/events.d.ts +11 -0
  41. package/lib/core/events.js +40 -0
  42. package/lib/core/http.d.ts +41 -0
  43. package/lib/core/http.js +123 -0
  44. package/lib/core/logger.d.ts +18 -0
  45. package/lib/core/logger.js +43 -0
  46. package/lib/core/operationQueue.d.ts +117 -0
  47. package/lib/core/operationQueue.js +264 -0
  48. package/lib/core/operations.d.ts +80 -0
  49. package/lib/core/operations.js +88 -0
  50. package/lib/core/payload.d.ts +20 -0
  51. package/lib/core/payload.js +187 -0
  52. package/lib/core/platform.d.ts +72 -0
  53. package/lib/core/platform.js +7 -0
  54. package/lib/core/state.d.ts +51 -0
  55. package/lib/core/state.js +74 -0
  56. package/lib/core/storage.d.ts +34 -0
  57. package/lib/core/storage.js +68 -0
  58. package/lib/core/subscription.d.ts +67 -0
  59. package/lib/core/subscription.js +98 -0
  60. package/lib/core/tags.d.ts +39 -0
  61. package/lib/core/tags.js +123 -0
  62. package/lib/core/url.d.ts +17 -0
  63. package/lib/core/url.js +64 -0
  64. package/lib/core/uuid.d.ts +2 -0
  65. package/lib/core/uuid.js +18 -0
  66. package/lib/index.d.ts +7 -0
  67. package/lib/index.js +15 -0
  68. package/lib/notification.d.ts +67 -0
  69. package/lib/notification.js +73 -0
  70. package/lib/reactNativePlatform.d.ts +3 -0
  71. package/lib/reactNativePlatform.js +164 -0
  72. package/lib/types.d.ts +157 -0
  73. package/lib/types.js +31 -0
  74. package/package.json +70 -4
  75. package/plugin/withQPush.js +330 -0
  76. package/react-native-qpush.podspec +30 -0
  77. package/react-native.config.js +18 -0
  78. package/src/NativeQPushPush.ts +57 -0
  79. package/src/QPush.ts +292 -0
  80. package/src/core/QPushCore.ts +1515 -0
  81. package/src/core/constants.ts +42 -0
  82. package/src/core/events.ts +34 -0
  83. package/src/core/http.ts +146 -0
  84. package/src/core/logger.ts +42 -0
  85. package/src/core/operationQueue.ts +324 -0
  86. package/src/core/operations.ts +166 -0
  87. package/src/core/payload.ts +175 -0
  88. package/src/core/platform.ts +84 -0
  89. package/src/core/state.ts +127 -0
  90. package/src/core/storage.ts +76 -0
  91. package/src/core/subscription.ts +133 -0
  92. package/src/core/tags.ts +116 -0
  93. package/src/core/url.ts +58 -0
  94. package/src/core/uuid.ts +13 -0
  95. package/src/index.ts +23 -0
  96. package/src/notification.ts +113 -0
  97. package/src/reactNativePlatform.ts +172 -0
  98. package/src/types.ts +174 -0
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * URL helpers. React Native's `URL` polyfill is incomplete (several getters
4
+ * throw "not implemented"), so everything here is plain string handling.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.normalizeServerUrl = normalizeServerUrl;
8
+ exports.joinUrl = joinUrl;
9
+ exports.encodeSegment = encodeSegment;
10
+ const API_SUFFIX = '/api/v1';
11
+ /**
12
+ * Normalizes the server URL given to `QPush.initialize`:
13
+ * - trims whitespace, drops query string / fragment and trailing slashes
14
+ * - prepends `https://` when no scheme is given
15
+ * - appends `/api/v1` when the path does not already end with it
16
+ *
17
+ * Returns `null` when the value cannot be used.
18
+ */
19
+ function normalizeServerUrl(input) {
20
+ var _a;
21
+ if (typeof input !== 'string')
22
+ return null;
23
+ let url = input.trim();
24
+ if (url.length === 0)
25
+ return null;
26
+ // Strip fragment and query string.
27
+ const hashIndex = url.indexOf('#');
28
+ if (hashIndex >= 0)
29
+ url = url.slice(0, hashIndex);
30
+ const queryIndex = url.indexOf('?');
31
+ if (queryIndex >= 0)
32
+ url = url.slice(0, queryIndex);
33
+ if (!/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(url)) {
34
+ if (url.startsWith('//'))
35
+ url = url.slice(2);
36
+ url = `https://${url}`;
37
+ }
38
+ const match = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([^/]*)(\/.*)?$/.exec(url);
39
+ if (!match)
40
+ return null;
41
+ const scheme = match[1].toLowerCase();
42
+ const host = match[2];
43
+ if (scheme !== 'http' && scheme !== 'https')
44
+ return null;
45
+ if (host.length === 0 || /\s/.test(host))
46
+ return null;
47
+ let path = ((_a = match[3]) !== null && _a !== void 0 ? _a : '').replace(/\/+$/, '');
48
+ // Collapse duplicated slashes inside the path.
49
+ path = path.replace(/\/{2,}/g, '/');
50
+ if (!path.toLowerCase().endsWith(API_SUFFIX)) {
51
+ path = `${path}${API_SUFFIX}`;
52
+ }
53
+ return `${scheme}://${host}${path}`;
54
+ }
55
+ /** Joins the API base URL with an absolute API path (`/apps/...`). */
56
+ function joinUrl(base, path) {
57
+ const trimmedBase = base.replace(/\/+$/, '');
58
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`;
59
+ return `${trimmedBase}${normalizedPath}`;
60
+ }
61
+ /** Encodes a single path segment (alias ids, labels, ids). */
62
+ function encodeSegment(segment) {
63
+ return encodeURIComponent(segment);
64
+ }
@@ -0,0 +1,2 @@
1
+ /** RFC 4122 v4 UUID (used for local ids only, not security sensitive). */
2
+ export declare function generateUuid(random?: () => number): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateUuid = generateUuid;
4
+ /** RFC 4122 v4 UUID (used for local ids only, not security sensitive). */
5
+ function generateUuid(random = Math.random) {
6
+ const hex = [];
7
+ for (let i = 0; i < 16; i++) {
8
+ let byte = Math.floor(random() * 256) & 0xff;
9
+ if (i === 6)
10
+ byte = (byte & 0x0f) | 0x40;
11
+ if (i === 8)
12
+ byte = (byte & 0x3f) | 0x80;
13
+ hex.push(byte.toString(16).padStart(2, '0'));
14
+ }
15
+ return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex
16
+ .slice(8, 10)
17
+ .join('')}-${hex.slice(10, 16).join('')}`;
18
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { QPush, QPush as default } from './QPush';
2
+ export type { QPushType, NotificationEventName, NotificationEventTypeMap, PushSubscriptionEventTypeMap, UserEventTypeMap, } from './QPush';
3
+ export { QPushNotification, NotificationWillDisplayEvent } from './notification';
4
+ export type { NotificationClickEvent } from './notification';
5
+ export { LogLevel, NotificationPermission, QPUSH_CLOUD_API_URL } from './types';
6
+ export type { ActionButton, QPushInitOptions, QPushNotificationData, NotificationClickResult, PermissionStatus, PushSubscriptionChangedState, PushSubscriptionState, UserChangedState, UserState, } from './types';
7
+ export { SDK_VERSION } from './core/constants';
package/lib/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SDK_VERSION = exports.QPUSH_CLOUD_API_URL = exports.NotificationPermission = exports.LogLevel = exports.NotificationWillDisplayEvent = exports.QPushNotification = exports.default = exports.QPush = void 0;
4
+ var QPush_1 = require("./QPush");
5
+ Object.defineProperty(exports, "QPush", { enumerable: true, get: function () { return QPush_1.QPush; } });
6
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return QPush_1.QPush; } });
7
+ var notification_1 = require("./notification");
8
+ Object.defineProperty(exports, "QPushNotification", { enumerable: true, get: function () { return notification_1.QPushNotification; } });
9
+ Object.defineProperty(exports, "NotificationWillDisplayEvent", { enumerable: true, get: function () { return notification_1.NotificationWillDisplayEvent; } });
10
+ var types_1 = require("./types");
11
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return types_1.LogLevel; } });
12
+ Object.defineProperty(exports, "NotificationPermission", { enumerable: true, get: function () { return types_1.NotificationPermission; } });
13
+ Object.defineProperty(exports, "QPUSH_CLOUD_API_URL", { enumerable: true, get: function () { return types_1.QPUSH_CLOUD_API_URL; } });
14
+ var constants_1 = require("./core/constants");
15
+ Object.defineProperty(exports, "SDK_VERSION", { enumerable: true, get: function () { return constants_1.SDK_VERSION; } });
@@ -0,0 +1,67 @@
1
+ import type { ActionButton, QPushNotificationData, NotificationClickResult } from './types';
2
+ /**
3
+ * A received notification. Same idea as OneSignal's `OSNotification`:
4
+ * read-only content plus `display()` for foreground notifications whose
5
+ * default display was prevented.
6
+ */
7
+ export declare class QPushNotification implements QPushNotificationData {
8
+ readonly notificationId: string;
9
+ readonly title?: string;
10
+ readonly subtitle?: string;
11
+ readonly body?: string;
12
+ readonly launchURL?: string;
13
+ readonly additionalData?: Record<string, unknown>;
14
+ readonly bigPicture?: string;
15
+ readonly largeIcon?: string;
16
+ readonly smallIcon?: string;
17
+ readonly accentColor?: string;
18
+ readonly sound?: string;
19
+ readonly channelId?: string;
20
+ readonly priority?: number;
21
+ readonly groupKey?: string;
22
+ readonly collapseId?: string;
23
+ readonly visibility?: number;
24
+ readonly badge?: number;
25
+ readonly category?: string;
26
+ readonly interruptionLevel?: string;
27
+ readonly relevanceScore?: number;
28
+ readonly contentAvailable?: boolean;
29
+ readonly actionButtons?: ActionButton[];
30
+ readonly rawPayload: Record<string, unknown>;
31
+ private readonly displayHandler?;
32
+ constructor(data: QPushNotificationData, displayHandler?: () => void);
33
+ /**
34
+ * Displays the notification. Only meaningful inside a
35
+ * `foregroundWillDisplay` listener after `event.preventDefault()`; a no-op
36
+ * otherwise.
37
+ */
38
+ display(): void;
39
+ /** Plain object copy (safe to serialize / store in React state). */
40
+ toJSON(): QPushNotificationData;
41
+ }
42
+ /** Payload of the `click` event (mirrors OneSignal's `NotificationClickEvent`). */
43
+ export interface NotificationClickEvent {
44
+ result: NotificationClickResult;
45
+ notification: QPushNotification;
46
+ }
47
+ /**
48
+ * Payload of the `foregroundWillDisplay` event. Call `preventDefault()`
49
+ * synchronously inside the listener to stop the notification from being
50
+ * shown; call `getNotification().display()` later to show it anyway.
51
+ */
52
+ export declare class NotificationWillDisplayEvent {
53
+ private readonly onDisplay;
54
+ private state;
55
+ private readonly notification;
56
+ constructor(data: QPushNotificationData, onDisplay: () => void);
57
+ /** Prevents the default display. Must be called synchronously in the listener. */
58
+ preventDefault(): void;
59
+ getNotification(): QPushNotification;
60
+ /** @internal */
61
+ get isPrevented(): boolean;
62
+ /** @internal */
63
+ get isDisplayed(): boolean;
64
+ private display;
65
+ /** @internal Called after all listeners ran: displays unless prevented. */
66
+ settle(): 'displayed' | 'prevented';
67
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationWillDisplayEvent = exports.QPushNotification = void 0;
4
+ /**
5
+ * A received notification. Same idea as OneSignal's `OSNotification`:
6
+ * read-only content plus `display()` for foreground notifications whose
7
+ * default display was prevented.
8
+ */
9
+ class QPushNotification {
10
+ constructor(data, displayHandler) {
11
+ Object.assign(this, data);
12
+ Object.defineProperty(this, 'displayHandler', { value: displayHandler, enumerable: false });
13
+ }
14
+ /**
15
+ * Displays the notification. Only meaningful inside a
16
+ * `foregroundWillDisplay` listener after `event.preventDefault()`; a no-op
17
+ * otherwise.
18
+ */
19
+ display() {
20
+ var _a;
21
+ (_a = this.displayHandler) === null || _a === void 0 ? void 0 : _a.call(this);
22
+ }
23
+ /** Plain object copy (safe to serialize / store in React state). */
24
+ toJSON() {
25
+ const copy = {};
26
+ for (const key of Object.keys(this)) {
27
+ copy[key] = this[key];
28
+ }
29
+ return copy;
30
+ }
31
+ }
32
+ exports.QPushNotification = QPushNotification;
33
+ /**
34
+ * Payload of the `foregroundWillDisplay` event. Call `preventDefault()`
35
+ * synchronously inside the listener to stop the notification from being
36
+ * shown; call `getNotification().display()` later to show it anyway.
37
+ */
38
+ class NotificationWillDisplayEvent {
39
+ constructor(data, onDisplay) {
40
+ this.onDisplay = onDisplay;
41
+ this.state = 'pending';
42
+ this.notification = new QPushNotification(data, () => this.display());
43
+ }
44
+ /** Prevents the default display. Must be called synchronously in the listener. */
45
+ preventDefault() {
46
+ if (this.state === 'pending')
47
+ this.state = 'prevented';
48
+ }
49
+ getNotification() {
50
+ return this.notification;
51
+ }
52
+ /** @internal */
53
+ get isPrevented() {
54
+ return this.state === 'prevented';
55
+ }
56
+ /** @internal */
57
+ get isDisplayed() {
58
+ return this.state === 'displayed';
59
+ }
60
+ display() {
61
+ if (this.state === 'displayed')
62
+ return;
63
+ this.state = 'displayed';
64
+ this.onDisplay();
65
+ }
66
+ /** @internal Called after all listeners ran: displays unless prevented. */
67
+ settle() {
68
+ if (this.state === 'pending')
69
+ this.display();
70
+ return this.state === 'displayed' ? 'displayed' : 'prevented';
71
+ }
72
+ }
73
+ exports.NotificationWillDisplayEvent = NotificationWillDisplayEvent;
@@ -0,0 +1,3 @@
1
+ import type { PlatformAdapter } from './core/platform';
2
+ /** Builds the platform adapter for a real React Native app. */
3
+ export declare function createReactNativePlatform(): PlatformAdapter;
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createReactNativePlatform = createReactNativePlatform;
7
+ const react_native_1 = require("react-native");
8
+ const NativeQPushPush_1 = __importDefault(require("./NativeQPushPush"));
9
+ const platform_1 = require("./core/platform");
10
+ const storage_1 = require("./core/storage");
11
+ const LINKING_ERROR = "react-native-qpush: the native module 'QPushPush' is not available. " +
12
+ 'Make sure you rebuilt the app after installing the package (pod install on iOS) ' +
13
+ 'and that you are not running in Expo Go (use a development build).';
14
+ const PERMISSIONS = ['notDetermined', 'denied', 'granted', 'provisional', 'ephemeral'];
15
+ function resolveNativeModule() {
16
+ var _a;
17
+ let module = null;
18
+ try {
19
+ module = NativeQPushPush_1.default !== null && NativeQPushPush_1.default !== void 0 ? NativeQPushPush_1.default : null;
20
+ }
21
+ catch {
22
+ module = null;
23
+ }
24
+ if (!module)
25
+ module = (_a = react_native_1.NativeModules.QPushPush) !== null && _a !== void 0 ? _a : null;
26
+ return module;
27
+ }
28
+ /** In-memory stand-in so JS keeps working (and logs) when the module is missing. */
29
+ function createFallbackBridge(os) {
30
+ const store = new storage_1.MemoryStore();
31
+ let warned = false;
32
+ const warn = () => {
33
+ if (!warned) {
34
+ warned = true;
35
+ console.error(`[QPush] ${LINKING_ERROR}`);
36
+ }
37
+ };
38
+ return {
39
+ getItem: (key) => store.getItem(key),
40
+ setItem: (key, value) => store.setItem(key, value),
41
+ removeItem: (key) => store.removeItem(key),
42
+ getDeviceInfo: async () => ({ platform: os }),
43
+ registerForPush: async () => {
44
+ warn();
45
+ return { token: null, error: 'native_module_missing' };
46
+ },
47
+ getPermissionStatus: async () => 'notDetermined',
48
+ requestPermission: async () => {
49
+ warn();
50
+ return false;
51
+ },
52
+ registerForProvisionalAuthorization: async () => false,
53
+ canRequestPermission: async () => false,
54
+ clearAll: warn,
55
+ removeNotification: warn,
56
+ removeGroupedNotifications: warn,
57
+ clearBadge: async () => 0,
58
+ setJsReady: () => { },
59
+ displayForegroundNotification: () => { },
60
+ preventForegroundDisplay: () => { },
61
+ setAutoOpenUrls: () => { },
62
+ setLogLevel: () => { },
63
+ beginBackgroundTask: async () => -1,
64
+ endBackgroundTask: () => { },
65
+ };
66
+ }
67
+ function toDeviceInfo(raw, os) {
68
+ const value = (raw !== null && raw !== void 0 ? raw : {});
69
+ const str = (key) => (typeof value[key] === 'string' && value[key] !== '' ? value[key] : undefined);
70
+ const info = { platform: os };
71
+ info.deviceModel = str('deviceModel');
72
+ info.deviceOs = str('deviceOs');
73
+ info.appVersion = str('appVersion');
74
+ info.timezone = str('timezone');
75
+ info.locale = str('locale');
76
+ info.language = str('language');
77
+ info.country = str('country');
78
+ info.carrier = str('carrier');
79
+ if (typeof value.rooted === 'boolean')
80
+ info.rooted = value.rooted;
81
+ if (typeof value.netType === 'number' && value.netType >= 0)
82
+ info.netType = value.netType;
83
+ if (os === 'ios')
84
+ info.testType = typeof value.testType === 'number' ? value.testType : null;
85
+ return info;
86
+ }
87
+ function toRegistration(raw) {
88
+ const value = (raw !== null && raw !== void 0 ? raw : {});
89
+ const result = {
90
+ token: typeof value.token === 'string' && value.token !== '' ? value.token : null,
91
+ };
92
+ if (typeof value.notificationTypes === 'number')
93
+ result.notificationTypes = value.notificationTypes;
94
+ if (typeof value.error === 'string')
95
+ result.error = value.error;
96
+ return result;
97
+ }
98
+ function wrapNative(module, os) {
99
+ return {
100
+ getItem: (key) => module.getItem(key),
101
+ setItem: (key, value) => module.setItem(key, value),
102
+ removeItem: (key) => module.removeItem(key),
103
+ getDeviceInfo: async () => toDeviceInfo(await module.getDeviceInfo(), os),
104
+ registerForPush: async (fcm) => toRegistration(await module.registerForPush(fcm ? { ...fcm } : null)),
105
+ getPermissionStatus: async () => {
106
+ const status = await module.getPermissionStatus();
107
+ return PERMISSIONS.includes(status) ? status : 'notDetermined';
108
+ },
109
+ requestPermission: (fallback) => module.requestPermission(fallback),
110
+ registerForProvisionalAuthorization: () => module.registerForProvisionalAuthorization(),
111
+ canRequestPermission: () => module.canRequestPermission(),
112
+ clearAll: () => module.clearAll(),
113
+ removeNotification: (id) => module.removeNotification(id),
114
+ removeGroupedNotifications: (group) => module.removeGroupedNotifications(group),
115
+ clearBadge: async () => {
116
+ const previous = await module.clearBadge();
117
+ return typeof previous === 'number' ? previous : 0;
118
+ },
119
+ setJsReady: () => module.setJsReady(),
120
+ displayForegroundNotification: (id) => module.displayForegroundNotification(id),
121
+ preventForegroundDisplay: (id) => module.preventForegroundDisplay(id),
122
+ setAutoOpenUrls: (enabled) => module.setAutoOpenUrls(enabled),
123
+ setLogLevel: (level) => module.setLogLevel(level),
124
+ beginBackgroundTask: async () => {
125
+ const id = await module.beginBackgroundTask();
126
+ return typeof id === 'number' ? id : -1;
127
+ },
128
+ endBackgroundTask: (id) => module.endBackgroundTask(id),
129
+ };
130
+ }
131
+ /** Builds the platform adapter for a real React Native app. */
132
+ function createReactNativePlatform() {
133
+ const os = react_native_1.Platform.OS === 'ios' ? 'ios' : 'android';
134
+ const module = resolveNativeModule();
135
+ const native = module ? wrapNative(module, os) : createFallbackBridge(os);
136
+ let nativeEvents;
137
+ if (module) {
138
+ // iOS requires the module instance; on Android it lets the emitter call
139
+ // addListener/removeListeners on the module.
140
+ const emitter = new react_native_1.NativeEventEmitter(module);
141
+ nativeEvents = {
142
+ addListener: (eventName, listener) => emitter.addListener(eventName, listener),
143
+ };
144
+ }
145
+ else {
146
+ nativeEvents = { addListener: () => ({ remove: () => { } }) };
147
+ }
148
+ const fetchImpl = (url, init) => fetch(url, init);
149
+ return {
150
+ os,
151
+ native,
152
+ nativeEvents,
153
+ appState: {
154
+ get currentState() {
155
+ return react_native_1.AppState.currentState;
156
+ },
157
+ addEventListener: (type, listener) => react_native_1.AppState.addEventListener(type, listener),
158
+ },
159
+ fetch: fetchImpl,
160
+ scheduler: platform_1.defaultScheduler,
161
+ now: () => Date.now(),
162
+ random: () => Math.random(),
163
+ };
164
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Public types of react-native-qpush.
3
+ *
4
+ * Names and shapes intentionally mirror OneSignal's React Native SDK v5 so
5
+ * migrating code is mostly a search & replace of `OneSignal` -> `QPush`.
6
+ */
7
+ /** Log verbosity, same numeric values as OneSignal's `LogLevel`. */
8
+ export declare enum LogLevel {
9
+ None = 0,
10
+ Fatal = 1,
11
+ Error = 2,
12
+ Warn = 3,
13
+ Info = 4,
14
+ Debug = 5,
15
+ Verbose = 6
16
+ }
17
+ /** Native permission state (mirrors OneSignal's `OSNotificationPermission`). */
18
+ export declare enum NotificationPermission {
19
+ NotDetermined = 0,
20
+ Denied = 1,
21
+ Authorized = 2,
22
+ Provisional = 3,
23
+ Ephemeral = 4
24
+ }
25
+ /** Permission state as reported by the native layer. */
26
+ export type PermissionStatus = 'notDetermined' | 'denied' | 'granted' | 'provisional' | 'ephemeral';
27
+ /** Base URL of the qpush cloud API, used when no serverUrl is given. */
28
+ export declare const QPUSH_CLOUD_API_URL = "https://qpush.dev/api/v1";
29
+ export interface QPushInitOptions {
30
+ /**
31
+ * API base URL. Defaults to the qpush cloud (`https://qpush.dev/api/v1`);
32
+ * set it only if you self-host. `/api/v1` is appended when missing.
33
+ */
34
+ serverUrl?: string;
35
+ /** Optional log level applied before anything else runs. */
36
+ logLevel?: LogLevel;
37
+ }
38
+ /** An action button attached to a notification. */
39
+ export interface ActionButton {
40
+ id: string;
41
+ text: string;
42
+ /** Android drawable resource name. */
43
+ icon?: string;
44
+ url?: string;
45
+ }
46
+ /** Normalized notification content (platform independent). */
47
+ export interface QPushNotificationData {
48
+ /** QPush notification id (uuid). */
49
+ notificationId: string;
50
+ title?: string;
51
+ subtitle?: string;
52
+ body?: string;
53
+ /** URL / deep link opened when the notification is tapped. */
54
+ launchURL?: string;
55
+ /** Custom JSON sent with the notification (`data`). */
56
+ additionalData?: Record<string, unknown>;
57
+ /** Big picture (Android) / attachment (iOS) image URL. */
58
+ bigPicture?: string;
59
+ largeIcon?: string;
60
+ smallIcon?: string;
61
+ /** ARGB hex, e.g. `FF0070F3` (Android). */
62
+ accentColor?: string;
63
+ sound?: string;
64
+ /** Android notification channel id. */
65
+ channelId?: string;
66
+ /** 10 = high, 5 = normal (Android). */
67
+ priority?: number;
68
+ /** Android group key / iOS thread-id. */
69
+ groupKey?: string;
70
+ collapseId?: string;
71
+ /** 1 public, 0 private, -1 secret (Android). */
72
+ visibility?: number;
73
+ /** iOS badge value from `aps.badge`. */
74
+ badge?: number;
75
+ /** iOS category identifier. */
76
+ category?: string;
77
+ /** iOS interruption level (`passive`, `active`, `time-sensitive`, `critical`). */
78
+ interruptionLevel?: string;
79
+ /** iOS relevance score (0..1). */
80
+ relevanceScore?: number;
81
+ /** `true` for background / silent pushes (iOS `content-available`). */
82
+ contentAvailable?: boolean;
83
+ actionButtons?: ActionButton[];
84
+ /** The untouched payload as received from the OS. */
85
+ rawPayload: Record<string, unknown>;
86
+ }
87
+ /** Result of a notification click. */
88
+ export interface NotificationClickResult {
89
+ /** Id of the tapped action button, when a button was tapped. */
90
+ actionId?: string;
91
+ /** URL that was (or would have been) opened. Button URL wins over the notification URL. */
92
+ url?: string;
93
+ }
94
+ export interface PushSubscriptionState {
95
+ id: string | null;
96
+ token: string | null;
97
+ optedIn: boolean;
98
+ }
99
+ export interface PushSubscriptionChangedState {
100
+ previous: PushSubscriptionState;
101
+ current: PushSubscriptionState;
102
+ }
103
+ export interface UserState {
104
+ qpushId: string | null;
105
+ externalId: string | null;
106
+ }
107
+ export interface UserChangedState {
108
+ current: UserState;
109
+ }
110
+ /** FCM parameters returned by `GET /apps/{app_id}/android_params.js`. */
111
+ export interface FcmParams {
112
+ project_id: string;
113
+ app_id: string;
114
+ api_key: string;
115
+ sender_id: string;
116
+ }
117
+ export interface AndroidParams {
118
+ app_id: string;
119
+ fcm: FcmParams | null;
120
+ use_identity_verification?: boolean;
121
+ }
122
+ export interface IosParams {
123
+ app_id: string;
124
+ apns_configured?: boolean;
125
+ environment?: string;
126
+ use_identity_verification?: boolean;
127
+ }
128
+ /** Subscription object as defined by the QPush protocol. */
129
+ export interface SubscriptionPayload {
130
+ id?: string;
131
+ type: 'AndroidPush' | 'iOSPush';
132
+ token?: string | null;
133
+ enabled: boolean;
134
+ notification_types: number;
135
+ session_count?: number;
136
+ device_model?: string;
137
+ device_os?: string;
138
+ sdk: string;
139
+ app_version?: string;
140
+ test_type?: number | null;
141
+ carrier?: string;
142
+ rooted?: boolean;
143
+ net_type?: number;
144
+ }
145
+ /** User object as defined by the QPush protocol. */
146
+ export interface UserPayload {
147
+ identity: Record<string, string>;
148
+ properties?: {
149
+ language?: string;
150
+ timezone_id?: string;
151
+ country?: string;
152
+ tags?: Record<string, string>;
153
+ first_active?: number;
154
+ last_active?: number;
155
+ };
156
+ subscriptions?: SubscriptionPayload[];
157
+ }
package/lib/types.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * Public types of react-native-qpush.
4
+ *
5
+ * Names and shapes intentionally mirror OneSignal's React Native SDK v5 so
6
+ * migrating code is mostly a search & replace of `OneSignal` -> `QPush`.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.QPUSH_CLOUD_API_URL = exports.NotificationPermission = exports.LogLevel = void 0;
10
+ /** Log verbosity, same numeric values as OneSignal's `LogLevel`. */
11
+ var LogLevel;
12
+ (function (LogLevel) {
13
+ LogLevel[LogLevel["None"] = 0] = "None";
14
+ LogLevel[LogLevel["Fatal"] = 1] = "Fatal";
15
+ LogLevel[LogLevel["Error"] = 2] = "Error";
16
+ LogLevel[LogLevel["Warn"] = 3] = "Warn";
17
+ LogLevel[LogLevel["Info"] = 4] = "Info";
18
+ LogLevel[LogLevel["Debug"] = 5] = "Debug";
19
+ LogLevel[LogLevel["Verbose"] = 6] = "Verbose";
20
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
21
+ /** Native permission state (mirrors OneSignal's `OSNotificationPermission`). */
22
+ var NotificationPermission;
23
+ (function (NotificationPermission) {
24
+ NotificationPermission[NotificationPermission["NotDetermined"] = 0] = "NotDetermined";
25
+ NotificationPermission[NotificationPermission["Denied"] = 1] = "Denied";
26
+ NotificationPermission[NotificationPermission["Authorized"] = 2] = "Authorized";
27
+ NotificationPermission[NotificationPermission["Provisional"] = 3] = "Provisional";
28
+ NotificationPermission[NotificationPermission["Ephemeral"] = 4] = "Ephemeral";
29
+ })(NotificationPermission || (exports.NotificationPermission = NotificationPermission = {}));
30
+ /** Base URL of the qpush cloud API, used when no serverUrl is given. */
31
+ exports.QPUSH_CLOUD_API_URL = 'https://qpush.dev/api/v1';