@virex-tech/paywallo-sdk 2.4.0 → 2.5.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.
@@ -20,4 +20,7 @@ RCT_EXTERN_METHOD(setUserID:(NSString *)userId)
20
20
 
21
21
  RCT_EXTERN_METHOD(flush)
22
22
 
23
+ RCT_EXTERN_METHOD(fetchDeferredAppLink:(RCTPromiseResolveBlock)resolve
24
+ reject:(RCTPromiseRejectBlock)reject)
25
+
23
26
  @end
@@ -72,6 +72,18 @@ class PaywalloFBBridge: NSObject {
72
72
  AppEvents.shared.flush()
73
73
  }
74
74
 
75
+ // MARK: - Deferred App Link (iOS deferred deep link → fbclid)
76
+
77
+ @objc
78
+ func fetchDeferredAppLink(
79
+ _ resolve: @escaping RCTPromiseResolveBlock,
80
+ reject: @escaping RCTPromiseRejectBlock
81
+ ) {
82
+ AppLinkUtility.fetchDeferredAppLink { url, _ in
83
+ resolve(url?.absoluteString)
84
+ }
85
+ }
86
+
75
87
  @objc
76
88
  static func requiresMainQueueSetup() -> Bool {
77
89
  return false
@@ -119,6 +131,14 @@ class PaywalloFBBridge: NSObject {
119
131
  @objc
120
132
  func flush() {}
121
133
 
134
+ @objc
135
+ func fetchDeferredAppLink(
136
+ _ resolve: @escaping RCTPromiseResolveBlock,
137
+ reject: @escaping RCTPromiseRejectBlock
138
+ ) {
139
+ resolve(nil)
140
+ }
141
+
122
142
  @objc
123
143
  static func requiresMainQueueSetup() -> Bool {
124
144
  return false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@virex-tech/paywallo-sdk",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "SDK React Native para integração com Paywallo - Paywalls, Subscriptions e Analytics",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -66,6 +66,9 @@
66
66
  },
67
67
  "peerDependencies": {
68
68
  "@react-native-firebase/app": "^22.0.0",
69
+ "expo-application": "*",
70
+ "expo-device": "*",
71
+ "expo-localization": "*",
69
72
  "expo-tracking-transparency": "*",
70
73
  "react": "*",
71
74
  "react-native": "*",
@@ -1,148 +0,0 @@
1
- package com.paywallo.sdk
2
-
3
- import com.facebook.react.bridge.*
4
- import android.os.Build
5
- import android.os.Environment
6
- import android.os.StatFs
7
- import android.app.ActivityManager
8
- import android.content.Context
9
- import android.provider.Settings
10
- import android.telephony.TelephonyManager
11
- import androidx.core.content.pm.PackageInfoCompat
12
- import com.android.installreferrer.api.InstallReferrerClient
13
- import com.android.installreferrer.api.InstallReferrerStateListener
14
-
15
- class PaywalloDeviceModule(private val reactContext: ReactApplicationContext) :
16
- ReactContextBaseJavaModule(reactContext) {
17
-
18
- override fun getName() = "PaywalloDevice"
19
-
20
- @ReactMethod
21
- fun getDeviceInfo(promise: Promise) {
22
- try {
23
- val map = Arguments.createMap()
24
-
25
- // deviceId
26
- try {
27
- val deviceId = Settings.Secure.getString(
28
- reactContext.contentResolver,
29
- Settings.Secure.ANDROID_ID
30
- )
31
- map.putString("deviceId", if (deviceId.isNullOrEmpty()) "unknown" else deviceId)
32
- } catch (e: Exception) {
33
- map.putString("deviceId", "unknown")
34
- }
35
-
36
- map.putString("model", Build.MODEL ?: "unknown")
37
- map.putString("modelId", Build.DEVICE ?: "unknown")
38
- map.putString("systemVersion", Build.VERSION.RELEASE ?: "unknown")
39
- map.putString("systemName", "Android")
40
- map.putString("brand", Build.BRAND ?: "unknown")
41
-
42
- // appVersion, buildNumber, bundleId
43
- try {
44
- val packageName = reactContext.packageName
45
- val pm = reactContext.packageManager
46
- val pkgInfo = pm.getPackageInfo(packageName, 0)
47
- map.putString("appVersion", pkgInfo.versionName ?: "unknown")
48
- val buildNumber = PackageInfoCompat.getLongVersionCode(pkgInfo).toString()
49
- map.putString("buildNumber", buildNumber)
50
- map.putString("bundleId", packageName)
51
- } catch (e: Exception) {
52
- map.putString("appVersion", "unknown")
53
- map.putString("buildNumber", "unknown")
54
- map.putString("bundleId", reactContext.packageName ?: "unknown")
55
- }
56
-
57
- // totalDisk, freeDisk
58
- try {
59
- val stat = StatFs(Environment.getDataDirectory().path)
60
- map.putDouble("totalDisk", stat.totalBytes.toDouble())
61
- map.putDouble("freeDisk", stat.availableBytes.toDouble())
62
- } catch (e: Exception) {
63
- map.putDouble("totalDisk", 0.0)
64
- map.putDouble("freeDisk", 0.0)
65
- }
66
-
67
- // totalRam
68
- try {
69
- val activityManager = reactContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
70
- val memInfo = ActivityManager.MemoryInfo()
71
- activityManager.getMemoryInfo(memInfo)
72
- map.putDouble("totalRam", memInfo.totalMem.toDouble())
73
- } catch (e: Exception) {
74
- map.putDouble("totalRam", 0.0)
75
- }
76
-
77
- // carrier
78
- try {
79
- val tm = reactContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
80
- val carrier = tm.networkOperatorName
81
- map.putString("carrier", if (carrier.isNullOrEmpty()) "unknown" else carrier)
82
- } catch (e: Exception) {
83
- map.putString("carrier", "unknown")
84
- }
85
-
86
- // installerPackage
87
- try {
88
- val packageName = reactContext.packageName
89
- val pm = reactContext.packageManager
90
- val installer = pm.getInstallerPackageName(packageName)
91
- if (installer != null) {
92
- map.putString("installerPackage", installer)
93
- } else {
94
- map.putNull("installerPackage")
95
- }
96
- } catch (e: Exception) {
97
- map.putNull("installerPackage")
98
- }
99
-
100
- // idfv — iOS-only concept
101
- map.putNull("idfv")
102
-
103
- promise.resolve(map)
104
- } catch (e: Exception) {
105
- promise.resolve(Arguments.createMap())
106
- }
107
- }
108
-
109
- @ReactMethod
110
- fun getInstallReferrer(promise: Promise) {
111
- try {
112
- val client = InstallReferrerClient.newBuilder(reactContext).build()
113
- // resolved tracks whether the promise was already settled to prevent
114
- // double-resolve when endConnection() triggers onInstallReferrerServiceDisconnected
115
- var resolved = false
116
-
117
- client.startConnection(object : InstallReferrerStateListener {
118
- override fun onInstallReferrerSetupFinished(responseCode: Int) {
119
- if (resolved) return
120
- if (responseCode == InstallReferrerClient.InstallReferrerResponse.OK) {
121
- try {
122
- val referrer = client.installReferrer.installReferrer
123
- resolved = true
124
- promise.resolve(referrer)
125
- } catch (e: Exception) {
126
- resolved = true
127
- promise.resolve(null)
128
- } finally {
129
- client.endConnection()
130
- }
131
- } else {
132
- resolved = true
133
- client.endConnection()
134
- promise.resolve(null)
135
- }
136
- }
137
-
138
- override fun onInstallReferrerServiceDisconnected() {
139
- if (resolved) return
140
- resolved = true
141
- promise.resolve(null)
142
- }
143
- })
144
- } catch (e: Exception) {
145
- promise.resolve(null)
146
- }
147
- }
148
- }
@@ -1,8 +0,0 @@
1
- #import <React/RCTBridgeModule.h>
2
-
3
- @interface RCT_EXTERN_MODULE(PaywalloDevice, NSObject)
4
-
5
- RCT_EXTERN_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve
6
- reject:(RCTPromiseRejectBlock)reject)
7
-
8
- @end
@@ -1,119 +0,0 @@
1
- import Foundation
2
- import UIKit
3
- import CoreTelephony
4
- import WebKit
5
-
6
- @objc(PaywalloDevice)
7
- class PaywalloDevice: NSObject {
8
-
9
- // requiresMainQueueSetup = true so UIDevice properties are read on the main thread
10
- @objc static func requiresMainQueueSetup() -> Bool { return true }
11
-
12
- // MARK: - Get Device Info
13
-
14
- @objc
15
- func getDeviceInfo(
16
- _ resolve: @escaping RCTPromiseResolveBlock,
17
- reject: @escaping RCTPromiseRejectBlock
18
- ) {
19
- // UIDevice properties are MainActor — must be read on the main thread
20
- DispatchQueue.main.async {
21
- let device = UIDevice.current
22
- let processInfo = ProcessInfo.processInfo
23
- let bundle = Bundle.main
24
- let info = bundle.infoDictionary
25
-
26
- let deviceId = device.identifierForVendor?.uuidString ?? ""
27
- let model = device.model
28
- let systemVersion = device.systemVersion
29
- let systemName = device.systemName
30
- let appVersion = info?["CFBundleShortVersionString"] as? String ?? "unknown"
31
- let buildNumber = info?["CFBundleVersion"] as? String ?? "unknown"
32
- let bundleId = bundle.bundleIdentifier ?? "unknown"
33
- let totalRam = NSNumber(value: processInfo.physicalMemory)
34
-
35
- // Disk stats — off main thread safe but called here for simplicity
36
- var totalDisk: NSNumber = 0
37
- var freeDisk: NSNumber = 0
38
- do {
39
- let attrs = try FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory())
40
- if let size = attrs[.systemSize] as? NSNumber { totalDisk = size }
41
- if let free = attrs[.systemFreeSize] as? NSNumber { freeDisk = free }
42
- } catch {
43
- // fallback stays 0
44
- }
45
-
46
- // Model identifier (sysctl — safe on any thread)
47
- let modelId = self.getModelIdentifier()
48
-
49
- // Darwin version (sysctl — synchronous, safe on any thread)
50
- let darwinVersion = self.getDarwinVersion()
51
-
52
- // WebKit version extracted from WKWebView user agent
53
- let webkitVersion = self.getWebKitVersion()
54
-
55
- // Carrier: CTTelephonyNetworkInfo is deprecated in iOS 16+ but still functional.
56
- // Using conditional to suppress warning; no replacement API exists for carrier name.
57
- var carrier = "unknown"
58
- let networkInfo = CTTelephonyNetworkInfo()
59
- if let providers = networkInfo.serviceSubscriberCellularProviders,
60
- let first = providers.values.first,
61
- let name = first.carrierName
62
- {
63
- carrier = name
64
- }
65
-
66
- var result: [String: Any] = [
67
- "deviceId": deviceId,
68
- "model": model,
69
- "modelId": modelId,
70
- "systemVersion": systemVersion,
71
- "appVersion": appVersion,
72
- "buildNumber": buildNumber,
73
- "bundleId": bundleId,
74
- "brand": "Apple",
75
- "systemName": systemName,
76
- "totalDisk": totalDisk,
77
- "freeDisk": freeDisk,
78
- "totalRam": totalRam,
79
- "carrier": carrier,
80
- "idfv": deviceId,
81
- "installerPackage": NSNull(),
82
- "darwinVersion": darwinVersion as Any,
83
- ]
84
- if let wkv = webkitVersion {
85
- result["webkitVersion"] = wkv
86
- }
87
-
88
- resolve(result)
89
- }
90
- }
91
-
92
- // MARK: - Helpers
93
-
94
- private func getModelIdentifier() -> String {
95
- var size = 0
96
- sysctlbyname("hw.machine", nil, &size, nil, 0)
97
- guard size > 0 else { return "unknown" }
98
- var machine = [CChar](repeating: 0, count: size)
99
- sysctlbyname("hw.machine", &machine, &size, nil, 0)
100
- return String(cString: machine)
101
- }
102
-
103
- private func getDarwinVersion() -> String? {
104
- var size = 0
105
- sysctlbyname("kern.osrelease", nil, &size, nil, 0)
106
- guard size > 0 else { return nil }
107
- var release = [CChar](repeating: 0, count: size)
108
- sysctlbyname("kern.osrelease", &release, &size, nil, 0)
109
- return String(cString: release)
110
- }
111
-
112
- private func getWebKitVersion() -> String? {
113
- guard let ua = WKWebView().value(forKey: "userAgent") as? String else { return nil }
114
- // Extract AppleWebKit/605.1.15 → "605.1.15"
115
- guard let range = ua.range(of: #"AppleWebKit/([\d.]+)"#, options: .regularExpression) else { return nil }
116
- let match = String(ua[range])
117
- return match.components(separatedBy: "/").last
118
- }
119
- }