react-native-sdk-pianoio 0.3.0 → 0.3.1

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 (48) hide show
  1. package/README.md +3 -3
  2. package/SdkPianoio.podspec +4 -16
  3. package/android/build.gradle +12 -19
  4. package/android/gradle.properties +17 -2
  5. package/android/src/main/java/com/sdkpianoio/SdkPianoioModule.kt +543 -7
  6. package/android/src/main/java/com/sdkpianoio/SdkPianoioPackage.kt +3 -3
  7. package/ios/ComposerPianoImpl.swift +247 -0
  8. package/ios/MyComposerDelegate.swift +79 -206
  9. package/ios/SdkPianoio.swift +150 -0
  10. package/ios/SdkPianoioBridge.m +81 -0
  11. package/ios/services/TokenService.swift +10 -7
  12. package/lib/commonjs/NativeSdkPianoio.ts +12 -3
  13. package/lib/commonjs/PianoComposer.js +4 -4
  14. package/lib/commonjs/PianoComposer.js.map +1 -1
  15. package/lib/commonjs/debug.js +23 -0
  16. package/lib/commonjs/debug.js.map +1 -0
  17. package/lib/commonjs/index.js +7 -0
  18. package/lib/commonjs/index.js.map +1 -1
  19. package/lib/module/NativeSdkPianoio.ts +12 -3
  20. package/lib/module/PianoComposer.js +4 -4
  21. package/lib/module/PianoComposer.js.map +1 -1
  22. package/lib/module/debug.js +18 -0
  23. package/lib/module/debug.js.map +1 -0
  24. package/lib/module/index.js +1 -0
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts +1 -1
  27. package/lib/typescript/commonjs/src/NativeSdkPianoio.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/src/PianoComposer.d.ts +1 -1
  29. package/lib/typescript/commonjs/src/debug.d.ts +2 -0
  30. package/lib/typescript/commonjs/src/debug.d.ts.map +1 -0
  31. package/lib/typescript/commonjs/src/index.d.ts +1 -0
  32. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  33. package/lib/typescript/module/src/NativeSdkPianoio.d.ts +1 -1
  34. package/lib/typescript/module/src/NativeSdkPianoio.d.ts.map +1 -1
  35. package/lib/typescript/module/src/PianoComposer.d.ts +1 -1
  36. package/lib/typescript/module/src/debug.d.ts +2 -0
  37. package/lib/typescript/module/src/debug.d.ts.map +1 -0
  38. package/lib/typescript/module/src/index.d.ts +1 -0
  39. package/lib/typescript/module/src/index.d.ts.map +1 -1
  40. package/package.json +31 -16
  41. package/src/NativeSdkPianoio.ts +12 -3
  42. package/src/PianoComposer.tsx +4 -4
  43. package/src/debug.ts +19 -0
  44. package/src/index.tsx +1 -0
  45. package/ios/ComposerPiano.swift +0 -304
  46. package/ios/SdkPianoio.h +0 -4
  47. package/ios/SdkPianoio.mm +0 -283
  48. package/ios/services/ComposerService.swift +0 -49
@@ -0,0 +1,247 @@
1
+ //
2
+ // ComposerPianoImpl.swift
3
+ // SdkPianoio
4
+ //
5
+ //
6
+ import Foundation
7
+ import PianoComposer
8
+ import PianoOAuth
9
+ import React
10
+
11
+ @objcMembers public class ComposerPianoImpl: NSObject {
12
+ private var composer: PianoComposer?
13
+ private var delegateHelper: MyComposerDelegate?
14
+
15
+ // ✅ These will hold the promise functions from React Native
16
+ var promiseResolver: RCTPromiseResolveBlock?
17
+ var promiseRejecter: RCTPromiseRejectBlock?
18
+
19
+ // This is a static property to hold the AID
20
+ public static var aid = ""
21
+
22
+ @objc public func initializeComposer(_ aid: String) {
23
+ ComposerPianoImpl.aid = aid
24
+
25
+ // 1. Correctly initialize the TokenService first.
26
+ let tokenService = TokenService()
27
+
28
+ // 2. Initialize the delegate.
29
+ self.delegateHelper = MyComposerDelegate()
30
+
31
+ // 3. Link the delegate back to this class so it can resolve promises.
32
+ self.delegateHelper?.moduleImpl = self
33
+
34
+ // 4. Initialize the composer.
35
+ self.composer = PianoComposer(
36
+ aid: ComposerPianoImpl.aid, endpoint: PianoEndpoint.productionEurope)
37
+
38
+ // 5. Set the composer's delegate property directly. This is the standard Swift way.
39
+ self.composer?.delegate = self.delegateHelper
40
+ }
41
+
42
+ @objc public func executeComposer() {
43
+ print("Esecuzione composer")
44
+ DispatchQueue.main.async {
45
+ if let composer = self.composer {
46
+ print("Calling composer.execute()")
47
+ composer.execute()
48
+ } else {
49
+ print("⚠️ Composer è nil")
50
+ self.promiseRejecter?(
51
+ "composer_nil", "Piano Composer is not initialized.", nil)
52
+ }
53
+ }
54
+ }
55
+
56
+ @objc public func executeExperience(
57
+ resolver: @escaping RCTPromiseResolveBlock,
58
+ rejecter: @escaping RCTPromiseRejectBlock
59
+ ) {
60
+ self.promiseResolver = resolver
61
+ self.promiseRejecter = rejecter
62
+
63
+ self.executeComposer()
64
+ }
65
+
66
+ public func findViewBySelector(selector: String) -> UIView? {
67
+ return nil
68
+ }
69
+
70
+ // --- Configuration methods ---
71
+
72
+ @objc public func addTag(_ tag: String) {
73
+ _ = composer?.tag(tag)
74
+ }
75
+
76
+ @objc public func addTags(_ tags: [String]) {
77
+ _ = composer?.tags(tags)
78
+ }
79
+
80
+ @objc public func setZoneId(_ zoneId: String) {
81
+ _ = composer?.zoneId(zoneId)
82
+ }
83
+
84
+ @objc public func setReferrer(_ referrer: String) {
85
+ _ = composer?.referrer(referrer)
86
+ }
87
+
88
+ @objc public func setUrl(_ url: String) {
89
+ _ = composer?.url(url)
90
+ }
91
+
92
+ @objc public func setCustomVariable(_ name: String, value: String) {
93
+ _ = composer?.customVariable(name: name, value: value)
94
+ }
95
+
96
+ @objc public func setUserToken(_ token: String) {
97
+ _ = composer?.userToken(token)
98
+ }
99
+
100
+ // method to get values and helpers
101
+ @objc public func getAid() -> String {
102
+ if composer != nil {
103
+ return composer?.aid ?? ""
104
+ } else {
105
+ return ""
106
+ }
107
+ }
108
+
109
+ @objc public func getTags() -> [String] {
110
+ if let tags = composer?.tags, !tags.isEmpty {
111
+ return Array(tags)
112
+ } else {
113
+ return []
114
+ }
115
+ }
116
+
117
+ @objc public func getComposer() -> PianoComposer? {
118
+ return composer
119
+ }
120
+
121
+ @objc public func getZoneId() -> String {
122
+ return composer?.zoneId ?? ""
123
+ }
124
+
125
+ @objc public func getReferrer() -> String {
126
+ return composer?.referrer ?? ""
127
+ }
128
+
129
+ @objc public func getUrl() -> String {
130
+ return composer?.url ?? ""
131
+ }
132
+
133
+ @objc public func getUserToken() -> String {
134
+ return composer?.userToken ?? ""
135
+ }
136
+
137
+ // MARK: - Additional Methods for React Native Bridge
138
+
139
+ @objc public func executeComposerWithResolver(
140
+ resolver: @escaping RCTPromiseResolveBlock,
141
+ rejecter: @escaping RCTPromiseRejectBlock
142
+ ) {
143
+ self.promiseResolver = resolver
144
+ self.promiseRejecter = rejecter
145
+ self.executeComposer()
146
+ }
147
+
148
+ @objc public func showLoginWithResolver(
149
+ resolver: @escaping RCTPromiseResolveBlock,
150
+ rejecter: @escaping RCTPromiseRejectBlock
151
+ ) {
152
+ self.promiseResolver = resolver
153
+ self.promiseRejecter = rejecter
154
+
155
+ DispatchQueue.main.async {
156
+ if let composer = self.composer {
157
+ // This would need to be implemented based on Piano SDK's login functionality
158
+ print("Show login triggered")
159
+ resolver(true)
160
+ } else {
161
+ rejecter("composer_nil", "Piano Composer is not initialized.", nil)
162
+ }
163
+ }
164
+ }
165
+
166
+ @objc public func showTemplateWithResolver(
167
+ resolver: @escaping RCTPromiseResolveBlock,
168
+ rejecter: @escaping RCTPromiseRejectBlock
169
+ ) {
170
+ self.promiseResolver = resolver
171
+ self.promiseRejecter = rejecter
172
+ self.executeComposer()
173
+ }
174
+
175
+ @objc public func showFormWithResolver(
176
+ resolver: @escaping RCTPromiseResolveBlock,
177
+ rejecter: @escaping RCTPromiseRejectBlock
178
+ ) {
179
+ self.promiseResolver = resolver
180
+ self.promiseRejecter = rejecter
181
+ self.executeComposer()
182
+ }
183
+
184
+ @objc public func showRecommendationsWithResolver(
185
+ resolver: @escaping RCTPromiseResolveBlock,
186
+ rejecter: @escaping RCTPromiseRejectBlock
187
+ ) {
188
+ self.promiseResolver = resolver
189
+ self.promiseRejecter = rejecter
190
+ self.executeComposer()
191
+ }
192
+
193
+ @objc public func nonSiteWithResolver(
194
+ resolver: @escaping RCTPromiseResolveBlock,
195
+ rejecter: @escaping RCTPromiseRejectBlock
196
+ ) {
197
+ self.promiseResolver = resolver
198
+ self.promiseRejecter = rejecter
199
+ self.executeComposer()
200
+ }
201
+
202
+ @objc public func userSegmentTrueWithResolver(
203
+ resolver: @escaping RCTPromiseResolveBlock,
204
+ rejecter: @escaping RCTPromiseRejectBlock
205
+ ) {
206
+ self.promiseResolver = resolver
207
+ self.promiseRejecter = rejecter
208
+ self.executeComposer()
209
+ }
210
+
211
+ @objc public func userSegmentFalseWithResolver(
212
+ resolver: @escaping RCTPromiseResolveBlock,
213
+ rejecter: @escaping RCTPromiseRejectBlock
214
+ ) {
215
+ self.promiseResolver = resolver
216
+ self.promiseRejecter = rejecter
217
+ self.executeComposer()
218
+ }
219
+
220
+ @objc public func meterActiveWithResolver(
221
+ resolver: @escaping RCTPromiseResolveBlock,
222
+ rejecter: @escaping RCTPromiseRejectBlock
223
+ ) {
224
+ self.promiseResolver = resolver
225
+ self.promiseRejecter = rejecter
226
+ self.executeComposer()
227
+ }
228
+
229
+ @objc public func meterExpiredWithResolver(
230
+ resolver: @escaping RCTPromiseResolveBlock,
231
+ rejecter: @escaping RCTPromiseRejectBlock
232
+ ) {
233
+ self.promiseResolver = resolver
234
+ self.promiseRejecter = rejecter
235
+ self.executeComposer()
236
+ }
237
+
238
+ @objc public func composerExecutionCompletedWithResolver(
239
+ resolver: @escaping RCTPromiseResolveBlock,
240
+ rejecter: @escaping RCTPromiseRejectBlock
241
+ ) {
242
+ self.promiseResolver = resolver
243
+ self.promiseRejecter = rejecter
244
+ self.executeComposer()
245
+ }
246
+
247
+ }
@@ -7,236 +7,109 @@
7
7
  import Foundation
8
8
  import PianoComposer
9
9
  import PianoOAuth
10
- import PianoCommon
11
- import PianoTemplate
12
-
13
- import SwiftUI
14
- import WebKit
15
-
16
- public class MyComposerDelegate: ComposerService, PianoShowTemplateDelegate {
17
-
18
- var view: WKWebView?
19
-
20
- func experienceExecute(composer: PianoComposer, event: XpEvent, params: ExperienceExecuteEventParams?) {
21
- print("Evento ricevuto: \(event)")
22
- print(event.eventType)
23
- }
24
-
25
- func showTemplate(params: ShowTemplateEventParams) {
26
- if params.displayMode == .inline {
27
- let request = URLRequest(url: URL(string: params.templateUrl)!)
28
- view?.load(request)
29
- }
30
- }
31
-
32
- public func setComposerAndDelegate(_ myComposer: PianoComposer) -> PianoComposer? {
33
- myComposer.delegate = self;
34
- return myComposer;
35
- }
36
-
37
- public func myShowLogin(composer: PianoComposer, event: XpEvent, params: [AnyHashable: Any]?) {
38
- DispatchQueue.main.async {
39
- PianoID.shared.aid = composer.aid;
40
- PianoID.shared.endpoint = composer.endpoint;
41
- PianoID.shared.signUpEnabled = true;
42
-
43
- PianoID.shared.signIn();
44
- };
45
- }
46
-
47
- public func myShowForm(composer: PianoComposer, event: XpEvent, params: [AnyHashable: Any]?) {
48
- DispatchQueue.main.async {
49
- PianoID.shared.formInfo(accessToken: PianoIDToken.description()) { formInfo, error in
50
- if let error = error {
51
- print("Errore nel recuperare il form: \(error.localizedDescription)")
52
- return
53
- }
54
-
55
- guard let formInfo = formInfo else {
56
- print("FormInfo non disponibile.")
57
- return
58
- }
59
-
60
- composer.delegate?.showForm?(composer: composer, event: event, params: nil)
61
- }
62
- }
63
- }
64
10
 
11
+ // import PianoTemplate
65
12
 
66
-
67
- public func myShowTemplate(composer: PianoComposer, event: XpEvent, params: ShowTemplateEventParams?) {
68
- if let p = params {
69
- let webView = WKWebView()
70
- let request = URLRequest(url: URL(string: p.templateUrl)!)
71
- webView.load(request)
72
-
73
- // Aggiungi webView alla vista principale
74
- let controller = PianoShowTemplateController(p)
75
- controller.delegate = self
76
- controller.show()
77
-
78
- self.execute();
79
- }
80
- }
81
-
82
- public func executeExperience(composer: PianoComposer, event: XpEvent, params: ExperienceExecuteEventParams?) {
83
- composer.delegate?.experienceExecute?(composer: composer, event: event, params: params)
84
-
85
- }
86
-
87
- public func composerExecutionCompleted(composer: PianoComposer, event: XpEvent, params: ExperienceExecuteEventParams?) {
88
- composer.delegate?.composerExecutionCompleted?(composer: composer)
89
-
90
- }
13
+ @objcMembers public class MyComposerDelegate: NSObject, PianoComposerDelegate {
91
14
 
15
+ // ✅ STEP 1: Add a weak reference back to the main implementation class.
16
+ // This lets us access the stored promiseResolver and promiseRejecter.
17
+ weak var moduleImpl: ComposerPianoImpl?
92
18
 
93
-
94
- public func findViewBySelector(selector: String) -> UIView? {
95
- return nil;
96
- }
97
-
98
- public func showRecommendations(composer: PianoComposer, event: XpEvent, params: ShowRecommendationsEventParams?) {
99
- DispatchQueue.main.async {
100
- composer.delegate?.showRecommendations?(composer: composer, event: event, params: params)
101
- }
102
- }
103
-
104
- public func nonSite(composer: PianoComposer, event: XpEvent) {
105
- DispatchQueue.main.async {
106
- composer.delegate?.nonSite?(composer: composer, event: event)
107
- }
108
- }
109
-
110
- public func userSegmentTrue(composer: PianoComposer, event: XpEvent) {
111
- DispatchQueue.main.async {
112
- composer.delegate?.userSegmentTrue?(composer: composer, event: event)
113
- }
114
- }
115
-
116
- public func userSegmentFalse(composer: PianoComposer, event: XpEvent) {
117
- DispatchQueue.main.async {
118
- composer.delegate?.userSegmentFalse?(composer: composer, event: event)
119
- }
120
- }
121
-
122
- public func meterActive(composer: PianoComposer, event: XpEvent, params: PageViewMeterEventParams?) {
123
- DispatchQueue.main.async {
124
- composer.delegate?.meterActive?(composer: composer, event: event, params: params)
125
- }
126
- }
127
-
128
- public func meterExpired(composer: PianoComposer, event: XpEvent, params: PageViewMeterEventParams?) {
129
- DispatchQueue.main.async {
130
- composer.delegate?.meterExpired?(composer: composer, event: event, params: params)
131
- }
132
- }
133
-
134
- public func composerDidCompleteExecution(_ composer: PianoComposer, result: PianoComposerEdgeResult?) {
135
- print("✅ Composer execution finished.")
136
-
137
- // Qui puoi notificare JS, inviare un evento, ecc.
138
- // Ad esempio: invia una notifica o chiama una callback
139
- }
19
+ // ✅ STEP 2: This is a generic helper function to resolve the promise.
20
+ // We'll call this from all the different delegate methods.
21
+ private func resolvePromise(with eventData: [String: Any]) {
22
+ guard self.moduleImpl?.promiseResolver != nil else { return }
140
23
 
141
- public func composerExecutionFailed(_ composer: PianoComposer, error: Error) {
142
- print("❌ Composer execution failed with error: \(error.localizedDescription)")
24
+ self.moduleImpl?.promiseResolver?(eventData)
25
+ self.clearPromiseHandlers()
143
26
  }
144
- }
145
-
146
-
147
-
148
27
 
28
+ private func rejectPromise(with error: Error) {
29
+ guard self.moduleImpl?.promiseRejecter != nil else { return }
149
30
 
31
+ let errorCode = "execution_failed"
32
+ let errorMessage = error.localizedDescription
33
+ self.moduleImpl?.promiseRejecter?(errorCode, errorMessage, error)
34
+ self.clearPromiseHandlers()
35
+ }
150
36
 
151
- struct WebView : UIViewRepresentable {
37
+ private func clearPromiseHandlers() {
38
+ self.moduleImpl?.promiseResolver = nil
39
+ self.moduleImpl?.promiseRejecter = nil
40
+ }
152
41
 
153
- let webView: WKWebView
42
+ // ✅ STEP 3: Implement the real delegate methods.
43
+ // The Piano SDK will call these automatically.
154
44
 
155
- @Binding var height: CGFloat
45
+ public func executeExperience(
46
+ composer: PianoComposer, event: XpEvent
47
+ ) {
48
+ print("✅ Delegate received: executeExperience")
156
49
 
157
- class Coordinator: NSObject, WKNavigationDelegate {
50
+ // Correct: Access the experienceId from the public 'eventExecutionContext' object
51
+ let experienceId = event.eventExecutionContext?.experienceId ?? ""
158
52
 
159
- var parent: WebView
53
+ let eventData: [String: Any] = [
54
+ "eventType": event.eventType,
55
+ "experienceId": experienceId,
56
+ ]
160
57
 
161
- init(_ parent: WebView) {
162
- self.parent = parent
163
- }
58
+ resolvePromise(with: eventData)
59
+ }
164
60
 
165
- func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
166
- webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (height, error) in
167
- DispatchQueue.main.async {
168
- self.parent.height = height as! CGFloat
169
- }
170
- })
171
- }
172
- }
61
+ public func showTemplate(
62
+ composer: PianoComposer, event: XpEvent, params: ShowTemplateEventParams?
63
+ ) {
64
+ print("✅ Delegate received: showTemplate")
173
65
 
174
- func makeCoordinator() -> Coordinator {
175
- Coordinator(self)
176
- }
66
+ // Correct: Access the experienceId from the public 'eventExecutionContext' object
67
+ let experienceId = event.eventExecutionContext?.experienceId ?? ""
177
68
 
178
- func makeUIView(context: Context) -> WKWebView {
179
- webView.scrollView.bounces = false
180
- webView.navigationDelegate = context.coordinator
69
+ let eventData: [String: Any] = [
70
+ "eventType": event.eventType,
71
+ "experienceId": experienceId,
72
+ "templateUrl": params?.templateUrl ?? "",
73
+ "displayMode": params?.displayMode.rawValue ?? "",
74
+ ]
181
75
 
182
- return webView
183
- }
76
+ resolvePromise(with: eventData)
77
+ }
184
78
 
185
- func updateUIView(_ uiView: WKWebView, context: Context) {}
186
- }
79
+ public func meterExpired(
80
+ composer: PianoComposer, event: XpEvent, params: PageViewMeterEventParams?
81
+ ) {
82
+ print("✅ Delegate received: meterExpired")
187
83
 
188
- fileprivate class ShowTemplateService: ComposerService, PianoShowTemplateDelegate {
84
+ // Correct: Access the experienceId from the public 'eventExecutionContext' object
85
+ let experienceId = event.eventExecutionContext?.experienceId ?? ""
189
86
 
190
- @Published var webView: WKWebView? = nil
87
+ let eventData: [String: Any] = [
88
+ "eventType": event.eventType,
89
+ "experienceId": experienceId,
90
+ "meterName": params?.meterName ?? "",
91
+ ]
191
92
 
192
- override func prepare(composer: PianoComposer) {
193
- webView = nil
194
- _ = composer.tag("templates")
195
- }
93
+ resolvePromise(with: eventData)
94
+ }
196
95
 
197
- func showTemplate(composer: PianoComposer, event: XpEvent, params: ShowTemplateEventParams?) {
198
- if let p = params {
199
- if p.displayMode == .inline {
200
- webView = WKWebView()
201
- }
96
+ public func composerExecutionFailed(_ composer: PianoComposer, error: Error) {
97
+ print("❌ Delegate received: composerExecutionFailed")
98
+ rejectPromise(with: error)
99
+ }
202
100
 
203
- let controller = PianoShowTemplateController(p)
204
- controller.delegate = self
205
- controller.show()
206
- }
207
- }
101
+ public func composerExecutionCompleted(composer: PianoComposer) {
102
+ print("✅ Delegate received: composerExecutionCompleted")
103
+ resolvePromise(with: ["eventType": "composerExecutionCompleted"])
104
+ }
208
105
 
209
- func findViewBySelector(selector: String) -> UIView? {
210
- selector == "template" ? webView : nil
211
- }
212
- }
106
+ public func experienceExecutionFailed(composer: PianoComposer, event: XpEvent, params: FailureEventParams?) {
107
+ print(" Delegate received: experienceExecutionFailed")
108
+ let error = NSError(domain: "PianoSDK", code: -1, userInfo: [NSLocalizedDescriptionKey: "Experience execution failed"])
109
+ rejectPromise(with: error)
110
+ }
213
111
 
214
- struct ShowTemplateView: View {
215
-
216
- @ObservedObject private var service: ShowTemplateService
217
-
218
- @State private var height: CGFloat = .zero
219
-
220
- init(tokenService: TokenService) {
221
- service = ShowTemplateService(tokenService: tokenService)
222
- }
223
-
224
- var body: some View {
225
- if #available(iOS 14.0, *) {
226
- VStack(spacing: 20) {
227
- if !service.loading {
228
- Button("Execute") {
229
- service.execute()
230
- }
231
-
232
- if let wv = service.webView {
233
- WebView(webView: wv, height: $height)
234
- .frame(height: height > 320 ? 320 : height)
235
- }
236
- } else {
237
-
238
- }
239
- }.navigationTitle("Show template")
240
- }
241
- }
112
+ public func findViewBySelector(selector: String) -> UIView? {
113
+ return nil
114
+ }
242
115
  }