react-native-newinstance-chat 0.1.0 → 0.2.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/NewinstanceChat.podspec +2 -1
- package/README.md +101 -3
- package/android/build.gradle +3 -5
- package/android/src/main/java/com/newinstancechat/NewinstanceChatModule.kt +78 -10
- package/ios/NewinstanceChat.mm +18 -1
- package/ios/NewinstanceChatImpl.swift +77 -15
- package/lib/module/NativeNewinstanceChat.js.map +1 -1
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeNewinstanceChat.d.ts +3 -1
- package/lib/typescript/src/NativeNewinstanceChat.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +5 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +56 -3
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +9 -3
- package/src/NativeNewinstanceChat.ts +3 -1
- package/src/index.tsx +14 -1
- package/src/types.ts +78 -3
package/NewinstanceChat.podspec
CHANGED
|
@@ -15,9 +15,10 @@ Pod::Spec.new do |s|
|
|
|
15
15
|
|
|
16
16
|
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
|
17
17
|
s.private_header_files = "ios/**/*.h"
|
|
18
|
+
s.pod_target_xcconfig = { "DEFINES_MODULE" => "YES" }
|
|
18
19
|
|
|
19
20
|
# Native chat SDK we wrap, published on CocoaPods Trunk.
|
|
20
|
-
s.dependency "LiveAndAiChat", "~> 0.
|
|
21
|
+
s.dependency "LiveAndAiChat", "~> 0.2.0"
|
|
21
22
|
|
|
22
23
|
install_modules_dependencies(s)
|
|
23
24
|
end
|
package/README.md
CHANGED
|
@@ -32,6 +32,16 @@ cd ios && pod install
|
|
|
32
32
|
Autolink pulls the `NewinstanceChat` podspec, which transitively depends
|
|
33
33
|
on `LiveAndAiChat` (the native SDK pod, published on CocoaPods Trunk).
|
|
34
34
|
|
|
35
|
+
Both default static-library Podfiles and `use_frameworks!` (any linkage)
|
|
36
|
+
are supported. If you see `'NewinstanceChat-Swift.h' file not found` you
|
|
37
|
+
are on 0.1.0, which only resolved the generated Swift header in
|
|
38
|
+
static-library builds. Upgrade to 0.1.1 or later, then reinstall pods:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npm install react-native-newinstance-chat@latest
|
|
42
|
+
cd ios && pod install
|
|
43
|
+
```
|
|
44
|
+
|
|
35
45
|
### Android
|
|
36
46
|
|
|
37
47
|
Autolink registers `NewinstanceChatPackage`. The underlying
|
|
@@ -54,6 +64,10 @@ sdk.setUser({
|
|
|
54
64
|
|
|
55
65
|
await sdk.initialize();
|
|
56
66
|
|
|
67
|
+
// `sdk.ready` is a Promise that resolves once the native module is configured -
|
|
68
|
+
// await it anywhere you need to know setup completed.
|
|
69
|
+
await sdk.ready;
|
|
70
|
+
|
|
57
71
|
// Later, in response to a host button tap:
|
|
58
72
|
sdk.openChat();
|
|
59
73
|
```
|
|
@@ -72,17 +86,101 @@ unsub();
|
|
|
72
86
|
```
|
|
73
87
|
|
|
74
88
|
Event names: `messageReceived`, `messageSent`, `agentTypingChanged`,
|
|
75
|
-
`connectionStateChanged`, `unreadCountChanged`, `error
|
|
76
|
-
for payload shapes.
|
|
89
|
+
`connectionStateChanged`, `unreadCountChanged`, `error`,
|
|
90
|
+
`attachmentUpdated`, `chatClosed`. See `src/types.ts` for payload shapes.
|
|
91
|
+
|
|
92
|
+
### The chat-close event
|
|
93
|
+
|
|
94
|
+
`chatClosed` fires **exactly once per chat presentation**, however the
|
|
95
|
+
screen went away: the in-chat close button, Android back navigation
|
|
96
|
+
(button or gesture), an iOS dismissal gesture, `closeChat()`,
|
|
97
|
+
`destroy()` (reason `session_ended`), or the host app navigating the
|
|
98
|
+
screen away. Rerenders and lifecycle churn never produce duplicates.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const unsub = sdk.addListener('chatClosed', (e) => {
|
|
103
|
+
// e.reason: 'close_button' | 'back_navigation' | 'gesture' |
|
|
104
|
+
// 'programmatic' | 'session_ended' | 'host_navigation'
|
|
105
|
+
// e.initiator: 'user' | 'host' | 'sdk'
|
|
106
|
+
// plus: timestamp, conversationId, assignmentId, channel,
|
|
107
|
+
// previousState, unreadCount, hasDraft,
|
|
108
|
+
// pendingAttachmentCount, metadata
|
|
109
|
+
analytics.track('chat_closed', { reason: e.reason });
|
|
110
|
+
});
|
|
111
|
+
return unsub; // always clean up on unmount
|
|
112
|
+
}, []);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Ordering: `chatClosed` is emitted after the SDK has left the open
|
|
116
|
+
state (`unreadCount` and `pendingAttachmentCount` reflect the moment of
|
|
117
|
+
dismissal). The event never contains message contents, credentials, or
|
|
118
|
+
attachment bytes.
|
|
77
119
|
|
|
78
120
|
### Sending messages programmatically
|
|
79
121
|
|
|
80
122
|
```ts
|
|
81
123
|
sdk.sendMessage('Hi, I have a question.');
|
|
82
|
-
sdk.attachFile({ uri: 'file:///…', name: 'screenshot.png', mimeType: 'image/png' });
|
|
83
124
|
sdk.retryMessage(failedMessageId);
|
|
84
125
|
```
|
|
85
126
|
|
|
127
|
+
### Programmatic attachments
|
|
128
|
+
|
|
129
|
+
`attachFile` accepts base64, data URIs, local file paths,
|
|
130
|
+
`content://` / `file://` URIs (picker outputs), and — when the native
|
|
131
|
+
SDK is configured with `allowRemoteAttachmentUrls` — remote URLs.
|
|
132
|
+
`sourceType: 'auto'` (the default) safely detects string inputs.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
// Base64 (e.g. from a camera or canvas):
|
|
136
|
+
const id = await sdk.attachFile({
|
|
137
|
+
source: pngBase64,
|
|
138
|
+
sourceType: 'base64',
|
|
139
|
+
name: 'photo.png',
|
|
140
|
+
mimeType: 'image/png',
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// React Native document picker result:
|
|
144
|
+
const [doc] = await pick(); // e.g. @react-native-documents/picker
|
|
145
|
+
await sdk.attachFile({
|
|
146
|
+
source: doc.uri, // content:// on Android, file:// on iOS
|
|
147
|
+
name: doc.name ?? 'document.pdf',
|
|
148
|
+
mimeType: doc.type ?? 'application/pdf',
|
|
149
|
+
size: doc.size ?? undefined,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Data URI:
|
|
153
|
+
await sdk.attachFile({ source: dataUri, name: 'chart.png' });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The returned promise resolves with the attachment **id** as soon as the
|
|
157
|
+
request is accepted and queued. Validation and upload run in the
|
|
158
|
+
background and never block the UI thread — failures surface as
|
|
159
|
+
`attachmentUpdated` with `status: 'failed'` plus an `error` event — and
|
|
160
|
+
the message is never sent until the upload succeeds (send drains only
|
|
161
|
+
uploaded attachments). Track progress and results via
|
|
162
|
+
`attachmentUpdated`:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
sdk.addListener('attachmentUpdated', (a) => {
|
|
166
|
+
// a.status: 'queued' | 'uploading' | 'uploaded' | 'failed' | 'cancelled'
|
|
167
|
+
// a.progress: 0..1 real byte progress
|
|
168
|
+
if (a.status === 'failed') console.warn(a.error);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
sdk.removeAttachment(id); // cancels an in-flight upload
|
|
172
|
+
sdk.clearAttachments();
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Validation happens before anything is queued: base64 must decode, URIs
|
|
176
|
+
must be readable, files must be non-empty and at most 25 MB, the MIME
|
|
177
|
+
type must be one of png/jpeg/webp/gif/pdf, a mismatched `size` is
|
|
178
|
+
rejected as corruption, and the extension must agree with the MIME
|
|
179
|
+
type. Attachment contents are never written to logs.
|
|
180
|
+
|
|
181
|
+
Allowed MIME types and the 25 MB cap mirror the web widget; keys and
|
|
182
|
+
limits are enforced again server-side.
|
|
183
|
+
|
|
86
184
|
Handoff to a live agent and typing indicators are driven automatically
|
|
87
185
|
by the native chat screen — there's nothing to wire up from the host.
|
|
88
186
|
|
package/android/build.gradle
CHANGED
|
@@ -65,15 +65,13 @@ android {
|
|
|
65
65
|
repositories {
|
|
66
66
|
google()
|
|
67
67
|
mavenCentral()
|
|
68
|
-
// Dev fallback
|
|
69
|
-
//
|
|
70
|
-
// in liveAndAiChat-android/ but the Maven Central publish hasn't
|
|
71
|
-
// landed yet. Remove this once the SDK is live on Maven Central.
|
|
68
|
+
// Dev fallback for local native SDK work after publishing
|
|
69
|
+
// liveAndAiChat-android with `./gradlew :sdk:publishToMavenLocal`.
|
|
72
70
|
mavenLocal()
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
dependencies {
|
|
76
74
|
implementation "com.facebook.react:react-android"
|
|
77
75
|
// Native chat SDK the bridge wraps. Published under cloud.newinstance.
|
|
78
|
-
implementation "cloud.newinstance:liveandaichat:0.
|
|
76
|
+
implementation "cloud.newinstance:liveandaichat:0.2.0"
|
|
79
77
|
}
|
|
@@ -5,8 +5,12 @@ import cloud.newinstance.liveandaichat.LiveAndAiChat
|
|
|
5
5
|
import cloud.newinstance.liveandaichat.LiveAndAiChatConfig
|
|
6
6
|
import cloud.newinstance.liveandaichat.LiveAndAiChatError
|
|
7
7
|
import cloud.newinstance.liveandaichat.ChatUser
|
|
8
|
+
import cloud.newinstance.liveandaichat.model.AttachmentRequest
|
|
9
|
+
import cloud.newinstance.liveandaichat.model.AttachmentSource
|
|
10
|
+
import cloud.newinstance.liveandaichat.model.ChatCloseEvent
|
|
8
11
|
import cloud.newinstance.liveandaichat.model.ChatMessage
|
|
9
12
|
import cloud.newinstance.liveandaichat.model.TransportMode
|
|
13
|
+
import cloud.newinstance.liveandaichat.upload.QueuedAttachment
|
|
10
14
|
import com.facebook.react.bridge.Arguments
|
|
11
15
|
import com.facebook.react.bridge.Promise
|
|
12
16
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
@@ -124,24 +128,57 @@ class NewinstanceChatModule(reactContext: ReactApplicationContext) :
|
|
|
124
128
|
promise.reject("E_NOT_CONFIGURED", "configure() must be called first")
|
|
125
129
|
return
|
|
126
130
|
}
|
|
127
|
-
val uri = opts.getString("uri")
|
|
128
131
|
val name = opts.getString("name")
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
if (name.isNullOrBlank()) {
|
|
133
|
+
promise.reject("E_ARGS", "name is required")
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
val sourceValue = opts.getString("source") ?: opts.getString("uri")
|
|
137
|
+
if (sourceValue.isNullOrBlank()) {
|
|
138
|
+
promise.reject("E_ARGS", "source (or legacy uri) is required")
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
val sourceType = opts.getString("sourceType") ?: "auto"
|
|
142
|
+
val source = AttachmentSource.fromTypeName(sourceType, sourceValue)
|
|
143
|
+
if (source == null) {
|
|
144
|
+
promise.reject(
|
|
145
|
+
"E_SOURCE",
|
|
146
|
+
if (sourceType == "auto") "Could not detect the attachment source type — pass sourceType explicitly"
|
|
147
|
+
else "Unknown sourceType: $sourceType",
|
|
148
|
+
)
|
|
132
149
|
return
|
|
133
150
|
}
|
|
151
|
+
val mimeType = opts.getString("mimeType")
|
|
152
|
+
val declaredSize = if (opts.hasKey("size") && !opts.isNull("size")) opts.getDouble("size").toLong() else null
|
|
153
|
+
val metadata = mutableMapOf<String, String>()
|
|
154
|
+
if (opts.hasKey("metadata") && !opts.isNull("metadata")) {
|
|
155
|
+
val map = opts.getMap("metadata")
|
|
156
|
+
map?.entryIterator?.forEach { (key, value) -> metadata[key] = value.toString() }
|
|
157
|
+
}
|
|
134
158
|
try {
|
|
135
|
-
val
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
159
|
+
val id = current.attach(
|
|
160
|
+
AttachmentRequest(
|
|
161
|
+
source = source,
|
|
162
|
+
name = name,
|
|
163
|
+
mimeType = mimeType,
|
|
164
|
+
declaredSize = declaredSize,
|
|
165
|
+
metadata = metadata,
|
|
166
|
+
),
|
|
167
|
+
)
|
|
168
|
+
promise.resolve(id)
|
|
140
169
|
} catch (e: Exception) {
|
|
141
|
-
promise.reject("
|
|
170
|
+
promise.reject("E_ATTACH", e.message, e)
|
|
142
171
|
}
|
|
143
172
|
}
|
|
144
173
|
|
|
174
|
+
override fun removeAttachment(id: String) {
|
|
175
|
+
sdk?.removeAttachment(id)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override fun clearAttachments() {
|
|
179
|
+
sdk?.clearAttachments()
|
|
180
|
+
}
|
|
181
|
+
|
|
145
182
|
override fun destroy() {
|
|
146
183
|
sdk?.destroy()
|
|
147
184
|
sdk = null
|
|
@@ -170,6 +207,37 @@ class NewinstanceChatModule(reactContext: ReactApplicationContext) :
|
|
|
170
207
|
override fun onUnreadCountChange(count: Int) {
|
|
171
208
|
emit("unreadCountChanged", count)
|
|
172
209
|
}
|
|
210
|
+
override fun onAttachmentUpdate(attachment: QueuedAttachment) {
|
|
211
|
+
val map = Arguments.createMap()
|
|
212
|
+
map.putString("id", attachment.id)
|
|
213
|
+
map.putString("name", attachment.name)
|
|
214
|
+
map.putString("mimeType", attachment.mimeType)
|
|
215
|
+
map.putDouble("size", attachment.size.toDouble())
|
|
216
|
+
map.putString("status", attachment.status.name.lowercase())
|
|
217
|
+
map.putDouble("progress", attachment.progress.toDouble())
|
|
218
|
+
attachment.publicUrl?.let { map.putString("url", it) }
|
|
219
|
+
attachment.errorReason?.let { map.putString("error", it) }
|
|
220
|
+
emit("attachmentUpdated", map)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
override fun onChatClosed(event: ChatCloseEvent) {
|
|
224
|
+
val map = Arguments.createMap()
|
|
225
|
+
map.putString("reason", event.reason.wire)
|
|
226
|
+
map.putString("initiator", event.initiator.wire)
|
|
227
|
+
map.putDouble("timestamp", event.timestamp.toDouble())
|
|
228
|
+
event.conversationId?.let { map.putString("conversationId", it) }
|
|
229
|
+
event.assignmentId?.let { map.putString("assignmentId", it) }
|
|
230
|
+
map.putString("channel", event.channel)
|
|
231
|
+
map.putString("previousState", event.previousState)
|
|
232
|
+
map.putInt("unreadCount", event.unreadCount)
|
|
233
|
+
map.putBoolean("hasDraft", event.hasDraft)
|
|
234
|
+
map.putInt("pendingAttachmentCount", event.pendingAttachmentCount)
|
|
235
|
+
val meta = Arguments.createMap()
|
|
236
|
+
event.metadata.forEach { (k, v) -> meta.putString(k, v) }
|
|
237
|
+
map.putMap("metadata", meta)
|
|
238
|
+
emit("chatClosed", map)
|
|
239
|
+
}
|
|
240
|
+
|
|
173
241
|
override fun onError(error: LiveAndAiChatError) {
|
|
174
242
|
val map = Arguments.createMap()
|
|
175
243
|
map.putString("type", error.type.name.lowercase())
|
package/ios/NewinstanceChat.mm
CHANGED
|
@@ -4,8 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
// Auto-generated Swift bridging header for this pod (created at build
|
|
6
6
|
// time by Xcode/CocoaPods when the pod mixes Obj-C and Swift). The pod
|
|
7
|
-
// name is `NewinstanceChat`, hence the header name.
|
|
7
|
+
// name is `NewinstanceChat`, hence the header name. Framework builds
|
|
8
|
+
// (`use_frameworks!`) place it inside the framework, reachable only via
|
|
9
|
+
// the angle-bracket path; static-library builds emit it to derived
|
|
10
|
+
// sources, reachable only via the quote form, so probe for both.
|
|
11
|
+
#if __has_include(<NewinstanceChat/NewinstanceChat-Swift.h>)
|
|
12
|
+
#import <NewinstanceChat/NewinstanceChat-Swift.h>
|
|
13
|
+
#else
|
|
8
14
|
#import "NewinstanceChat-Swift.h"
|
|
15
|
+
#endif
|
|
9
16
|
|
|
10
17
|
// Declare conformance to NewinstanceChatEmitter (defined in
|
|
11
18
|
// NewinstanceChatImpl.swift) so the Swift impl can hold a typed weak
|
|
@@ -69,6 +76,16 @@ RCT_EXPORT_MODULE()
|
|
|
69
76
|
[_impl attachFile:opts resolver:resolve rejecter:reject];
|
|
70
77
|
}
|
|
71
78
|
|
|
79
|
+
- (void)removeAttachment:(NSString *)attachmentId
|
|
80
|
+
{
|
|
81
|
+
[_impl removeAttachment:attachmentId];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
- (void)clearAttachments
|
|
85
|
+
{
|
|
86
|
+
[_impl clearAttachments];
|
|
87
|
+
}
|
|
88
|
+
|
|
72
89
|
// NativeEventEmitter wires these so it can track subscriber counts. The
|
|
73
90
|
// actual event payloads flow through RCTDeviceEventEmitter, so these are
|
|
74
91
|
// intentional no-ops.
|
|
@@ -140,24 +140,51 @@ public final class NewinstanceChatImpl: NSObject, LiveAndAiChatDelegate {
|
|
|
140
140
|
rejecter("E_NOT_CONFIGURED", "configure() must be called first", nil)
|
|
141
141
|
return
|
|
142
142
|
}
|
|
143
|
-
guard let
|
|
144
|
-
|
|
145
|
-
let mimeType = opts["mimeType"] as? String,
|
|
146
|
-
let url = URL(string: uri) else {
|
|
147
|
-
rejecter("E_ARGS", "uri, name, mimeType are required", nil)
|
|
143
|
+
guard let name = opts["name"] as? String, !name.isEmpty else {
|
|
144
|
+
rejecter("E_ARGS", "name is required", nil)
|
|
148
145
|
return
|
|
149
146
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
147
|
+
guard let sourceValue = (opts["source"] as? String) ?? (opts["uri"] as? String), !sourceValue.isEmpty else {
|
|
148
|
+
rejecter("E_ARGS", "source (or legacy uri) is required", nil)
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
let sourceType = (opts["sourceType"] as? String) ?? "auto"
|
|
152
|
+
guard let source = AttachmentSource.fromTypeName(sourceType, value: sourceValue) else {
|
|
153
|
+
rejecter(
|
|
154
|
+
"E_SOURCE",
|
|
155
|
+
sourceType == "auto"
|
|
156
|
+
? "Could not detect the attachment source type — pass sourceType explicitly"
|
|
157
|
+
: "Unknown sourceType: \(sourceType)",
|
|
158
|
+
nil
|
|
159
|
+
)
|
|
160
|
+
return
|
|
160
161
|
}
|
|
162
|
+
let mimeType = opts["mimeType"] as? String
|
|
163
|
+
let declaredSize = (opts["size"] as? NSNumber)?.int64Value
|
|
164
|
+
var metadata: [String: String] = [:]
|
|
165
|
+
if let raw = opts["metadata"] as? [String: Any] {
|
|
166
|
+
for (key, value) in raw { metadata[key] = String(describing: value) }
|
|
167
|
+
}
|
|
168
|
+
let request = AttachmentRequest(
|
|
169
|
+
source: source,
|
|
170
|
+
name: name,
|
|
171
|
+
mimeType: mimeType,
|
|
172
|
+
declaredSize: declaredSize,
|
|
173
|
+
metadata: metadata
|
|
174
|
+
)
|
|
175
|
+
DispatchQueue.main.async {
|
|
176
|
+
let id = sdk.attach(request)
|
|
177
|
+
resolver(id)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@objc(removeAttachment:)
|
|
182
|
+
public func removeAttachment(_ id: String) {
|
|
183
|
+
DispatchQueue.main.async { [weak self] in self?.sdk?.removeAttachment(id: id) }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@objc public func clearAttachments() {
|
|
187
|
+
DispatchQueue.main.async { [weak self] in self?.sdk?.clearAttachments() }
|
|
161
188
|
}
|
|
162
189
|
|
|
163
190
|
@objc public func destroy() {
|
|
@@ -171,6 +198,41 @@ public final class NewinstanceChatImpl: NSObject, LiveAndAiChatDelegate {
|
|
|
171
198
|
|
|
172
199
|
// MARK: - LiveAndAiChatDelegate
|
|
173
200
|
|
|
201
|
+
public func unreadCountDidChange(_ count: Int) {
|
|
202
|
+
emitter?.emitEvent("unreadCountChanged", body: count)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public func attachmentDidUpdate(_ attachment: QueuedAttachment) {
|
|
206
|
+
var body: [String: Any] = [
|
|
207
|
+
"id": attachment.id,
|
|
208
|
+
"name": attachment.name,
|
|
209
|
+
"mimeType": attachment.mimeType,
|
|
210
|
+
"size": attachment.size,
|
|
211
|
+
"status": attachment.status.rawValue,
|
|
212
|
+
"progress": attachment.progress,
|
|
213
|
+
]
|
|
214
|
+
if let url = attachment.publicUrl { body["url"] = url }
|
|
215
|
+
if let error = attachment.errorReason { body["error"] = error }
|
|
216
|
+
emitter?.emitEvent("attachmentUpdated", body: body)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public func chatDidClose(_ event: ChatCloseEvent) {
|
|
220
|
+
var body: [String: Any] = [
|
|
221
|
+
"reason": event.reason.rawValue,
|
|
222
|
+
"initiator": event.initiator.rawValue,
|
|
223
|
+
"timestamp": event.timestamp,
|
|
224
|
+
"channel": event.channel,
|
|
225
|
+
"previousState": event.previousState,
|
|
226
|
+
"unreadCount": event.unreadCount,
|
|
227
|
+
"hasDraft": event.hasDraft,
|
|
228
|
+
"pendingAttachmentCount": event.pendingAttachmentCount,
|
|
229
|
+
"metadata": event.metadata,
|
|
230
|
+
]
|
|
231
|
+
if let id = event.conversationId { body["conversationId"] = id }
|
|
232
|
+
if let id = event.assignmentId { body["assignmentId"] = id }
|
|
233
|
+
emitter?.emitEvent("chatClosed", body: body)
|
|
234
|
+
}
|
|
235
|
+
|
|
174
236
|
public func didReceiveMessage(_ message: ChatMessage) {
|
|
175
237
|
emitter?.emitEvent("messageReceived", body: Self.chatMessageToDict(message))
|
|
176
238
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeNewinstanceChat.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;;AAEpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeNewinstanceChat.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;;AAEpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAoBA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,iBAAiB,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -65,9 +65,22 @@ export class NewinstanceChat {
|
|
|
65
65
|
* uploaded reference into the next `sendMessage()`.
|
|
66
66
|
*/
|
|
67
67
|
attachFile(opts) {
|
|
68
|
+
if (!opts.source && !opts.uri) {
|
|
69
|
+
return Promise.reject(new Error('attachFile requires `source` (or the legacy `uri`)'));
|
|
70
|
+
}
|
|
68
71
|
return NativeNewinstanceChat.attachFile(opts);
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
/** Remove a queued attachment; cancels its upload if still in flight. */
|
|
75
|
+
removeAttachment(id) {
|
|
76
|
+
NativeNewinstanceChat.removeAttachment(id);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Remove every queued attachment and cancel in-flight uploads. */
|
|
80
|
+
clearAttachments() {
|
|
81
|
+
NativeNewinstanceChat.clearAttachments();
|
|
82
|
+
}
|
|
83
|
+
|
|
71
84
|
/**
|
|
72
85
|
* Subscribe to a native event. Returns an unsubscribe function — call it
|
|
73
86
|
* when your component unmounts to avoid leaks.
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeModules","NativeNewinstanceChat","emitterSource","NewinstanceChat","emitter","constructor","config","ready","configure","setUser","user","initialize","openChat","closeChat","sendMessage","text","retryMessage","messageId","attachFile","opts","addListener","event","handler","sub","remove","destroy"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,kBAAkB,EAClBC,aAAa,QAER,cAAc;AAErB,OAAOC,qBAAqB,MAAM,4BAAyB;AAqB3D;AACA;AACA;AACA,MAAMC,aAAkB,GACtBF,aAAa,CAACG,eAAe,IAAKF,qBAAiC;AACrE,MAAMG,OAAO,GAAG,IAAIL,kBAAkB,CAACG,aAAa,CAAC;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,eAAe,CAAC;EAC3B;;EAGAE,WAAWA,CAACC,MAA6B,EAAE;IACzC,IAAI,CAACC,KAAK,GAAGN,qBAAqB,CAACO,SAAS,CAACF,MAAM,CAAC;EACtD;;EAEA;AACF;AACA;AACA;AACA;EACEG,OAAOA,CAACC,IAAc,EAAQ;IAC5BT,qBAAqB,CAACQ,OAAO,CAACC,IAAI,CAAC;EACrC;;EAEA;AACF;AACA;AACA;AACA;EACEC,UAAUA,CAAA,EAAkB;IAC1B,OAAOV,qBAAqB,CAACU,UAAU,CAAC,CAAC;EAC3C;;EAEA;EACAC,QAAQA,CAAA,EAAS;IACfX,qBAAqB,CAACW,QAAQ,CAAC,CAAC;EAClC;;EAEA;EACAC,SAASA,CAAA,EAAS;IAChBZ,qBAAqB,CAACY,SAAS,CAAC,CAAC;EACnC;EAEAC,WAAWA,CAACC,IAAY,EAAQ;IAC9Bd,qBAAqB,CAACa,WAAW,CAACC,IAAI,CAAC;EACzC;EAEAC,YAAYA,CAACC,SAAiB,EAAQ;IACpChB,qBAAqB,CAACe,YAAY,CAACC,SAAS,CAAC;EAC/C;;EAEA;AACF;AACA;AACA;AACA;EACEC,UAAUA,CAACC,IAAqB,
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","NativeNewinstanceChat","emitterSource","NewinstanceChat","emitter","constructor","config","ready","configure","setUser","user","initialize","openChat","closeChat","sendMessage","text","retryMessage","messageId","attachFile","opts","source","uri","Promise","reject","Error","removeAttachment","id","clearAttachments","addListener","event","handler","sub","remove","destroy"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,kBAAkB,EAClBC,aAAa,QAER,cAAc;AAErB,OAAOC,qBAAqB,MAAM,4BAAyB;AAqB3D;AACA;AACA;AACA,MAAMC,aAAkB,GACtBF,aAAa,CAACG,eAAe,IAAKF,qBAAiC;AACrE,MAAMG,OAAO,GAAG,IAAIL,kBAAkB,CAACG,aAAa,CAAC;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,eAAe,CAAC;EAC3B;;EAGAE,WAAWA,CAACC,MAA6B,EAAE;IACzC,IAAI,CAACC,KAAK,GAAGN,qBAAqB,CAACO,SAAS,CAACF,MAAM,CAAC;EACtD;;EAEA;AACF;AACA;AACA;AACA;EACEG,OAAOA,CAACC,IAAc,EAAQ;IAC5BT,qBAAqB,CAACQ,OAAO,CAACC,IAAI,CAAC;EACrC;;EAEA;AACF;AACA;AACA;AACA;EACEC,UAAUA,CAAA,EAAkB;IAC1B,OAAOV,qBAAqB,CAACU,UAAU,CAAC,CAAC;EAC3C;;EAEA;EACAC,QAAQA,CAAA,EAAS;IACfX,qBAAqB,CAACW,QAAQ,CAAC,CAAC;EAClC;;EAEA;EACAC,SAASA,CAAA,EAAS;IAChBZ,qBAAqB,CAACY,SAAS,CAAC,CAAC;EACnC;EAEAC,WAAWA,CAACC,IAAY,EAAQ;IAC9Bd,qBAAqB,CAACa,WAAW,CAACC,IAAI,CAAC;EACzC;EAEAC,YAAYA,CAACC,SAAiB,EAAQ;IACpChB,qBAAqB,CAACe,YAAY,CAACC,SAAS,CAAC;EAC/C;;EAEA;AACF;AACA;AACA;AACA;EACEC,UAAUA,CAACC,IAAqB,EAAmB;IACjD,IAAI,CAACA,IAAI,CAACC,MAAM,IAAI,CAACD,IAAI,CAACE,GAAG,EAAE;MAC7B,OAAOC,OAAO,CAACC,MAAM,CAAC,IAAIC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxF;IACA,OAAOvB,qBAAqB,CAACiB,UAAU,CAACC,IAAI,CAAC;EAC/C;;EAEA;EACAM,gBAAgBA,CAACC,EAAU,EAAQ;IACjCzB,qBAAqB,CAACwB,gBAAgB,CAACC,EAAE,CAAC;EAC5C;;EAEA;EACAC,gBAAgBA,CAAA,EAAS;IACvB1B,qBAAqB,CAAC0B,gBAAgB,CAAC,CAAC;EAC1C;;EAEA;AACF;AACA;AACA;EACEC,WAAWA,CACTC,KAAQ,EACRC,OAAwB,EACZ;IACZ,MAAMC,GAAwB,GAAG3B,OAAO,CAACwB,WAAW,CAClDC,KAAK,EACLC,OACF,CAAC;IACD,OAAO,MAAMC,GAAG,CAACC,MAAM,CAAC,CAAC;EAC3B;;EAEA;AACF;AACA;AACA;EACEC,OAAOA,CAAA,EAAS;IACdhC,qBAAqB,CAACgC,OAAO,CAAC,CAAC;EACjC;AACF","ignoreList":[]}
|
|
@@ -17,7 +17,9 @@ export interface Spec extends TurboModule {
|
|
|
17
17
|
closeChat(): void;
|
|
18
18
|
sendMessage(text: string): void;
|
|
19
19
|
retryMessage(messageId: string): void;
|
|
20
|
-
attachFile(opts: Object): Promise<
|
|
20
|
+
attachFile(opts: Object): Promise<string>;
|
|
21
|
+
removeAttachment(id: string): void;
|
|
22
|
+
clearAttachments(): void;
|
|
21
23
|
destroy(): void;
|
|
22
24
|
addListener(eventName: string): void;
|
|
23
25
|
removeListeners(count: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeNewinstanceChat.d.ts","sourceRoot":"","sources":["../../../src/NativeNewinstanceChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE;;;;;;;;;GASG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,IAAI,IAAI,CAAC;IACjB,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeNewinstanceChat.d.ts","sourceRoot":"","sources":["../../../src/NativeNewinstanceChat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE;;;;;;;;;GASG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,IAAI,IAAI,CAAC;IACjB,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,IAAI,IAAI,CAAC;IACzB,OAAO,IAAI,IAAI,CAAC;IAIhB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAAyE"}
|
|
@@ -37,7 +37,11 @@ export declare class NewinstanceChat {
|
|
|
37
37
|
* `uri`, pushes them through the SDK's upload pipeline, and bundles the
|
|
38
38
|
* uploaded reference into the next `sendMessage()`.
|
|
39
39
|
*/
|
|
40
|
-
attachFile(opts: AttachmentInput): Promise<
|
|
40
|
+
attachFile(opts: AttachmentInput): Promise<string>;
|
|
41
|
+
/** Remove a queued attachment; cancels its upload if still in flight. */
|
|
42
|
+
removeAttachment(id: string): void;
|
|
43
|
+
/** Remove every queued attachment and cancel in-flight uploads. */
|
|
44
|
+
clearAttachments(): void;
|
|
41
45
|
/**
|
|
42
46
|
* Subscribe to a native event. Returns an unsubscribe function — call it
|
|
43
47
|
* when your component unmounts to avoid leaks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,eAAe,EACf,WAAW,EACX,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,SAAS,EACT,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,SAAS,CAAC;AASjB;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAElB,MAAM,EAAE,qBAAqB;IAIzC;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAI7B;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,uEAAuE;IACvE,QAAQ,IAAI,IAAI;IAIhB,sCAAsC;IACtC,SAAS,IAAI,IAAI;IAIjB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,eAAe,EACf,WAAW,EACX,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,SAAS,EACT,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,SAAS,CAAC;AASjB;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAElB,MAAM,EAAE,qBAAqB;IAIzC;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAI7B;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,uEAAuE;IACvE,QAAQ,IAAI,IAAI;IAIhB,sCAAsC;IACtC,SAAS,IAAI,IAAI;IAIjB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI/B,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAOlD,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIlC,mEAAmE;IACnE,gBAAgB,IAAI,IAAI;IAIxB;;;OAGG;IACH,WAAW,CAAC,CAAC,SAAS,SAAS,EAC7B,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,MAAM,IAAI;IAQb;;;OAGG;IACH,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -20,12 +20,63 @@ export interface ChatUser {
|
|
|
20
20
|
customerEmail?: string;
|
|
21
21
|
customerId?: string;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
export type AttachmentSourceType = 'auto' | 'base64' | 'dataUri' | 'file' | 'contentUri' | 'url';
|
|
24
|
+
/**
|
|
25
|
+
* A programmatic attachment. Provide `source` + optional `sourceType`
|
|
26
|
+
* (`'auto'` detects data URIs, `content://`/`file://` URIs, absolute
|
|
27
|
+
* paths, http(s) URLs — remote URLs upload only when the native SDK is
|
|
28
|
+
* configured with `allowRemoteAttachmentUrls` — and raw base64).
|
|
29
|
+
* The legacy `uri` field keeps working and behaves like
|
|
30
|
+
* `source` + `sourceType: 'auto'`.
|
|
31
|
+
*/
|
|
24
32
|
export interface AttachmentInput {
|
|
25
|
-
/**
|
|
26
|
-
|
|
33
|
+
/** Attachment data or locator, interpreted per `sourceType`. */
|
|
34
|
+
source?: string;
|
|
35
|
+
sourceType?: AttachmentSourceType;
|
|
36
|
+
/** @deprecated Use `source`. Local file URI, still fully supported. */
|
|
37
|
+
uri?: string;
|
|
38
|
+
name: string;
|
|
39
|
+
/** Required unless the source itself carries one (data URIs, content URIs) or the extension resolves it. */
|
|
40
|
+
mimeType?: string;
|
|
41
|
+
/** Expected byte size — validated against the resolved data as a corruption guard. */
|
|
42
|
+
size?: number;
|
|
43
|
+
/** Free-form string metadata carried on the queued attachment. */
|
|
44
|
+
metadata?: Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
export type AttachmentStatus = 'queued' | 'uploading' | 'uploaded' | 'failed' | 'cancelled';
|
|
47
|
+
/** Streamed on `attachmentUpdated` for every attachment state/progress change. */
|
|
48
|
+
export interface AttachmentUpdate {
|
|
49
|
+
id: string;
|
|
27
50
|
name: string;
|
|
28
51
|
mimeType: string;
|
|
52
|
+
size: number;
|
|
53
|
+
status: AttachmentStatus;
|
|
54
|
+
/** 0..1 — real byte progress while uploading. */
|
|
55
|
+
progress: number;
|
|
56
|
+
/** Public URL once `status === 'uploaded'`. */
|
|
57
|
+
url?: string;
|
|
58
|
+
/** Failure reason once `status === 'failed'`. */
|
|
59
|
+
error?: string;
|
|
60
|
+
}
|
|
61
|
+
export type ChatCloseReason = 'close_button' | 'back_navigation' | 'gesture' | 'programmatic' | 'session_ended' | 'host_navigation';
|
|
62
|
+
/**
|
|
63
|
+
* Fired exactly once per chat presentation when the chat screen goes
|
|
64
|
+
* away, however it was dismissed. Never contains message contents,
|
|
65
|
+
* credentials, or attachment data.
|
|
66
|
+
*/
|
|
67
|
+
export interface ChatClosedEvent {
|
|
68
|
+
reason: ChatCloseReason;
|
|
69
|
+
initiator: 'user' | 'host' | 'sdk';
|
|
70
|
+
/** Unix milliseconds. */
|
|
71
|
+
timestamp: number;
|
|
72
|
+
conversationId?: string;
|
|
73
|
+
assignmentId?: string;
|
|
74
|
+
channel: string;
|
|
75
|
+
previousState: string;
|
|
76
|
+
unreadCount: number;
|
|
77
|
+
hasDraft: boolean;
|
|
78
|
+
pendingAttachmentCount: number;
|
|
79
|
+
metadata: Record<string, string>;
|
|
29
80
|
}
|
|
30
81
|
export type ConnectionState = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'offline';
|
|
31
82
|
export interface ChatMessage {
|
|
@@ -63,6 +114,8 @@ export interface EventMap {
|
|
|
63
114
|
connectionStateChanged: (state: ConnectionState) => void;
|
|
64
115
|
unreadCountChanged: (count: number) => void;
|
|
65
116
|
error: (e: NewinstanceChatError) => void;
|
|
117
|
+
attachmentUpdated: (attachment: AttachmentUpdate) => void;
|
|
118
|
+
chatClosed: (event: ChatClosedEvent) => void;
|
|
66
119
|
}
|
|
67
120
|
export type EventName = keyof EventMap;
|
|
68
121
|
export type EventHandler<K extends EventName> = EventMap[K];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yGAAyG;IACzG,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACzB,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-newinstance-chat",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "New instance LiveAndAiChat React Native SDK
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "New instance LiveAndAiChat React Native SDK \u2014 AI + live-agent chat, drop-in native chat screen for iOS and Android.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -130,7 +130,9 @@
|
|
|
130
130
|
"preset": "@react-native/jest-preset",
|
|
131
131
|
"modulePathIgnorePatterns": [
|
|
132
132
|
"<rootDir>/example/node_modules",
|
|
133
|
-
"<rootDir>/lib/"
|
|
133
|
+
"<rootDir>/lib/",
|
|
134
|
+
"<rootDir>/example/ios",
|
|
135
|
+
"<rootDir>/example/android"
|
|
134
136
|
]
|
|
135
137
|
},
|
|
136
138
|
"release-it": {
|
|
@@ -162,5 +164,9 @@
|
|
|
162
164
|
"vite"
|
|
163
165
|
],
|
|
164
166
|
"version": "0.62.0"
|
|
167
|
+
},
|
|
168
|
+
"resolutions": {
|
|
169
|
+
"jest-environment-node": "^30.4.1",
|
|
170
|
+
"jest-mock": "^30.4.1"
|
|
165
171
|
}
|
|
166
172
|
}
|
|
@@ -18,7 +18,9 @@ export interface Spec extends TurboModule {
|
|
|
18
18
|
closeChat(): void;
|
|
19
19
|
sendMessage(text: string): void;
|
|
20
20
|
retryMessage(messageId: string): void;
|
|
21
|
-
attachFile(opts: Object): Promise<
|
|
21
|
+
attachFile(opts: Object): Promise<string>;
|
|
22
|
+
removeAttachment(id: string): void;
|
|
23
|
+
clearAttachments(): void;
|
|
22
24
|
destroy(): void;
|
|
23
25
|
|
|
24
26
|
// NativeEventEmitter on iOS calls these to track listener counts.
|
package/src/index.tsx
CHANGED
|
@@ -91,10 +91,23 @@ export class NewinstanceChat {
|
|
|
91
91
|
* `uri`, pushes them through the SDK's upload pipeline, and bundles the
|
|
92
92
|
* uploaded reference into the next `sendMessage()`.
|
|
93
93
|
*/
|
|
94
|
-
attachFile(opts: AttachmentInput): Promise<
|
|
94
|
+
attachFile(opts: AttachmentInput): Promise<string> {
|
|
95
|
+
if (!opts.source && !opts.uri) {
|
|
96
|
+
return Promise.reject(new Error('attachFile requires `source` (or the legacy `uri`)'));
|
|
97
|
+
}
|
|
95
98
|
return NativeNewinstanceChat.attachFile(opts);
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
/** Remove a queued attachment; cancels its upload if still in flight. */
|
|
102
|
+
removeAttachment(id: string): void {
|
|
103
|
+
NativeNewinstanceChat.removeAttachment(id);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Remove every queued attachment and cancel in-flight uploads. */
|
|
107
|
+
clearAttachments(): void {
|
|
108
|
+
NativeNewinstanceChat.clearAttachments();
|
|
109
|
+
}
|
|
110
|
+
|
|
98
111
|
/**
|
|
99
112
|
* Subscribe to a native event. Returns an unsubscribe function — call it
|
|
100
113
|
* when your component unmounts to avoid leaks.
|
package/src/types.ts
CHANGED
|
@@ -23,12 +23,85 @@ export interface ChatUser {
|
|
|
23
23
|
customerId?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
export type AttachmentSourceType =
|
|
27
|
+
| 'auto'
|
|
28
|
+
| 'base64'
|
|
29
|
+
| 'dataUri'
|
|
30
|
+
| 'file'
|
|
31
|
+
| 'contentUri'
|
|
32
|
+
| 'url';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A programmatic attachment. Provide `source` + optional `sourceType`
|
|
36
|
+
* (`'auto'` detects data URIs, `content://`/`file://` URIs, absolute
|
|
37
|
+
* paths, http(s) URLs — remote URLs upload only when the native SDK is
|
|
38
|
+
* configured with `allowRemoteAttachmentUrls` — and raw base64).
|
|
39
|
+
* The legacy `uri` field keeps working and behaves like
|
|
40
|
+
* `source` + `sourceType: 'auto'`.
|
|
41
|
+
*/
|
|
27
42
|
export interface AttachmentInput {
|
|
28
|
-
/**
|
|
29
|
-
|
|
43
|
+
/** Attachment data or locator, interpreted per `sourceType`. */
|
|
44
|
+
source?: string;
|
|
45
|
+
sourceType?: AttachmentSourceType;
|
|
46
|
+
/** @deprecated Use `source`. Local file URI, still fully supported. */
|
|
47
|
+
uri?: string;
|
|
48
|
+
name: string;
|
|
49
|
+
/** Required unless the source itself carries one (data URIs, content URIs) or the extension resolves it. */
|
|
50
|
+
mimeType?: string;
|
|
51
|
+
/** Expected byte size — validated against the resolved data as a corruption guard. */
|
|
52
|
+
size?: number;
|
|
53
|
+
/** Free-form string metadata carried on the queued attachment. */
|
|
54
|
+
metadata?: Record<string, string>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type AttachmentStatus =
|
|
58
|
+
| 'queued'
|
|
59
|
+
| 'uploading'
|
|
60
|
+
| 'uploaded'
|
|
61
|
+
| 'failed'
|
|
62
|
+
| 'cancelled';
|
|
63
|
+
|
|
64
|
+
/** Streamed on `attachmentUpdated` for every attachment state/progress change. */
|
|
65
|
+
export interface AttachmentUpdate {
|
|
66
|
+
id: string;
|
|
30
67
|
name: string;
|
|
31
68
|
mimeType: string;
|
|
69
|
+
size: number;
|
|
70
|
+
status: AttachmentStatus;
|
|
71
|
+
/** 0..1 — real byte progress while uploading. */
|
|
72
|
+
progress: number;
|
|
73
|
+
/** Public URL once `status === 'uploaded'`. */
|
|
74
|
+
url?: string;
|
|
75
|
+
/** Failure reason once `status === 'failed'`. */
|
|
76
|
+
error?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type ChatCloseReason =
|
|
80
|
+
| 'close_button'
|
|
81
|
+
| 'back_navigation'
|
|
82
|
+
| 'gesture'
|
|
83
|
+
| 'programmatic'
|
|
84
|
+
| 'session_ended'
|
|
85
|
+
| 'host_navigation';
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Fired exactly once per chat presentation when the chat screen goes
|
|
89
|
+
* away, however it was dismissed. Never contains message contents,
|
|
90
|
+
* credentials, or attachment data.
|
|
91
|
+
*/
|
|
92
|
+
export interface ChatClosedEvent {
|
|
93
|
+
reason: ChatCloseReason;
|
|
94
|
+
initiator: 'user' | 'host' | 'sdk';
|
|
95
|
+
/** Unix milliseconds. */
|
|
96
|
+
timestamp: number;
|
|
97
|
+
conversationId?: string;
|
|
98
|
+
assignmentId?: string;
|
|
99
|
+
channel: string;
|
|
100
|
+
previousState: string;
|
|
101
|
+
unreadCount: number;
|
|
102
|
+
hasDraft: boolean;
|
|
103
|
+
pendingAttachmentCount: number;
|
|
104
|
+
metadata: Record<string, string>;
|
|
32
105
|
}
|
|
33
106
|
|
|
34
107
|
export type ConnectionState =
|
|
@@ -80,6 +153,8 @@ export interface EventMap {
|
|
|
80
153
|
connectionStateChanged: (state: ConnectionState) => void;
|
|
81
154
|
unreadCountChanged: (count: number) => void;
|
|
82
155
|
error: (e: NewinstanceChatError) => void;
|
|
156
|
+
attachmentUpdated: (attachment: AttachmentUpdate) => void;
|
|
157
|
+
chatClosed: (event: ChatClosedEvent) => void;
|
|
83
158
|
}
|
|
84
159
|
|
|
85
160
|
export type EventName = keyof EventMap;
|