@react-native-kakao/share 3.0.0 → 3.1.0-next.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 (32) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/RNCKakaoShare.podspec +0 -1
  3. package/android/build.gradle +1 -2
  4. package/android/src/main/java/net/mjstudio/rnkakao/share/RNCKakaoShareModule.kt +359 -11
  5. package/android/src/main/java/net/mjstudio/rnkakao/share/RNCKakaoShareTemplates.kt +5 -2
  6. package/ios/RNCKakaoShare.mm +69 -5
  7. package/ios/RNCKakaoShareManager.swift +349 -36
  8. package/lib/commonjs/index.js +145 -29
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/index.web.js +267 -48
  11. package/lib/commonjs/index.web.js.map +1 -1
  12. package/lib/commonjs/spec/NativeKakaoShare.ts +89 -3
  13. package/lib/commonjs/validateSharePickerSettings.js +33 -0
  14. package/lib/commonjs/validateSharePickerSettings.js.map +1 -0
  15. package/lib/module/index.js +135 -29
  16. package/lib/module/index.js.map +1 -1
  17. package/lib/module/index.web.js +258 -49
  18. package/lib/module/index.web.js.map +1 -1
  19. package/lib/module/spec/NativeKakaoShare.ts +89 -3
  20. package/lib/module/validateSharePickerSettings.js +29 -0
  21. package/lib/module/validateSharePickerSettings.js.map +1 -0
  22. package/lib/typescript/src/index.d.ts +88 -23
  23. package/lib/typescript/src/index.d.ts.map +1 -1
  24. package/lib/typescript/src/spec/NativeKakaoShare.d.ts +84 -1
  25. package/lib/typescript/src/spec/NativeKakaoShare.d.ts.map +1 -1
  26. package/lib/typescript/src/validateSharePickerSettings.d.ts +6 -0
  27. package/lib/typescript/src/validateSharePickerSettings.d.ts.map +1 -0
  28. package/package.json +5 -5
  29. package/src/index.ts +271 -15
  30. package/src/index.web.ts +305 -62
  31. package/src/spec/NativeKakaoShare.ts +89 -3
  32. package/src/validateSharePickerSettings.ts +38 -0
@@ -13,6 +13,68 @@
13
13
 
14
14
  RCT_EXPORT_MODULE()
15
15
 
16
+ RCT_EXPORT_METHOD(isKakaoTalkSharingAvailable : (RCTPromiseResolveBlock)
17
+ resolve reject : (RCTPromiseRejectBlock)reject) {
18
+ [[self manager] isKakaoTalkSharingAvailable:resolve];
19
+ }
20
+
21
+ RCT_EXPORT_METHOD(makeTemplateUrl : (NSString*)templateType templateId : (
22
+ double)templateId templateJson : (NSDictionary*)templateJson templateArgs : (NSDictionary*)
23
+ templateArgs serverCallbackArgs : (NSDictionary*)
24
+ serverCallbackArgs resolve : (RCTPromiseResolveBlock)
25
+ resolve reject : (RCTPromiseRejectBlock)reject) {
26
+ [[self manager] makeTemplateUrl:templateType
27
+ templateId:templateId
28
+ templateJson:templateJson
29
+ templateArgs:templateArgs
30
+ serverCallbackArgs:serverCallbackArgs
31
+ resolve:resolve
32
+ reject:reject];
33
+ }
34
+
35
+ RCT_EXPORT_METHOD(uploadImage : (NSString*)imageUri secureResource : (BOOL)
36
+ secureResource resolve : (RCTPromiseResolveBlock)
37
+ resolve reject : (RCTPromiseRejectBlock)reject) {
38
+ [[self manager] uploadImage:imageUri secureResource:secureResource resolve:resolve reject:reject];
39
+ }
40
+
41
+ RCT_EXPORT_METHOD(getTemplateDiagnostics : (NSString*)templateType templateId : (
42
+ double)templateId templateJson : (NSDictionary*)templateJson templateArgs : (NSDictionary*)
43
+ templateArgs serverCallbackArgs : (NSDictionary*)
44
+ serverCallbackArgs pickerSettings : (NSDictionary*)
45
+ pickerSettings resolve : (RCTPromiseResolveBlock)
46
+ resolve reject : (RCTPromiseRejectBlock)reject) {
47
+ [[self manager] getTemplateDiagnostics:templateType
48
+ templateId:templateId
49
+ templateJson:templateJson
50
+ templateArgs:templateArgs
51
+ serverCallbackArgs:serverCallbackArgs
52
+ pickerSettings:pickerSettings
53
+ resolve:resolve
54
+ reject:reject];
55
+ }
56
+
57
+ RCT_EXPORT_METHOD(
58
+ shareScrapTemplate : (NSString*)requestUrl useWebBrowserIfKakaoTalkNotAvailable : (BOOL)
59
+ useWebBrowserIfKakaoTalkNotAvailable templateId : (NSNumber*)templateId templateArgs : (
60
+ NSDictionary*)templateArgs serverCallbackArgs : (NSDictionary*)
61
+ serverCallbackArgs pickerSettings : (NSDictionary*)pickerSettings resolve : (
62
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
63
+ [[self manager] shareScrapTemplate:requestUrl
64
+ useWebBrowserIfKakaoTalkNotAvailable:useWebBrowserIfKakaoTalkNotAvailable
65
+ templateId:templateId
66
+ templateArgs:templateArgs
67
+ serverCallbackArgs:serverCallbackArgs
68
+ pickerSettings:pickerSettings
69
+ resolve:resolve
70
+ reject:reject];
71
+ }
72
+
73
+ RCT_EXPORT_METHOD(scrapImage : (NSString*)imageUrl secureResource : (BOOL)secureResource resolve : (
74
+ RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
75
+ [[self manager] scrapImage:imageUrl secureResource:secureResource resolve:resolve reject:reject];
76
+ }
77
+
16
78
  // RNC_KAKAO_SHARE_EXPORT_DEFAULT_TEMPLATE(shareFeedTemplate, feed)
17
79
  // RNC_KAKAO_SHARE_EXPORT_DEFAULT_TEMPLATE(shareListTemplate, list)
18
80
  // RNC_KAKAO_SHARE_EXPORT_DEFAULT_TEMPLATE(shareLocationTemplate, location)
@@ -21,11 +83,12 @@ RCT_EXPORT_MODULE()
21
83
  // RNC_KAKAO_SHARE_EXPORT_DEFAULT_TEMPLATE(shareCalendarTemplate, calendar)
22
84
 
23
85
  RCT_EXPORT_METHOD(
24
- shareOrSendMeOrSendFriendOrWhatever : (NSString*)sendType templateType : (NSString*)
25
- templateType templateId : (double)templateId templateJson : (NSDictionary*)templateJson
26
- receiverUuids : (NSArray*)receiverUuids useWebBrowserIfKakaoTalkNotAvailable : (BOOL)
27
- useWebBrowserIfKakaoTalkNotAvailable templateArgs : (NSDictionary*)
28
- templateArgs serverCallbackArgs : (NSDictionary*)serverCallbackArgs resolve : (
86
+ shareOrSendMeOrSendFriendOrWhatever : (NSString*)sendType templateType : (NSString*)templateType
87
+ templateId : (double)templateId templateJson : (NSDictionary*)templateJson receiverUuids : (
88
+ NSArray*)receiverUuids useWebBrowserIfKakaoTalkNotAvailable : (BOOL)
89
+ useWebBrowserIfKakaoTalkNotAvailable templateArgs : (NSDictionary*)
90
+ templateArgs serverCallbackArgs : (NSDictionary*)
91
+ serverCallbackArgs pickerSettings : (NSDictionary*)pickerSettings resolve : (
29
92
  RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) {
30
93
  [[self manager] shareOrSendMeOrSendFriendOrWhatever:sendType
31
94
  templateType:templateType
@@ -35,6 +98,7 @@ RCT_EXPORT_METHOD(
35
98
  useWebBrowserIfKakaoTalkNotAvailable:useWebBrowserIfKakaoTalkNotAvailable
36
99
  templateArgs:templateArgs
37
100
  serverCallbackArgs:serverCallbackArgs
101
+ pickerSettings:pickerSettings
38
102
  resolve:resolve
39
103
  reject:reject];
40
104
  }
@@ -6,10 +6,226 @@ import KakaoSDKTemplate
6
6
  import React
7
7
  import RNCKakaoCore
8
8
  import SafariServices
9
+ import UIKit
10
+
11
+ private let noCustomTemplateId: Int64 = -1
9
12
 
10
13
  @objc public class RNCKakaoShareManager: NSObject {
11
14
  @objc public static let shared = RNCKakaoShareManager()
12
15
 
16
+ @objc public func makeTemplateUrl(
17
+ _ templateType: String,
18
+ templateId: Int64,
19
+ templateJson: [String: Any],
20
+ templateArgs: [String: String]?,
21
+ serverCallbackArgs: [String: String]?,
22
+ resolve: @escaping RCTPromiseResolveBlock,
23
+ reject: @escaping RCTPromiseRejectBlock
24
+ ) {
25
+ onMain {
26
+ do {
27
+ let url: URL?
28
+ if templateType == "custom" {
29
+ url = ShareApi.shared.makeCustomUrl(
30
+ templateId: templateId, templateArgs: templateArgs,
31
+ serverCallbackArgs: serverCallbackArgs
32
+ )
33
+ } else if templateType == "scrap" {
34
+ guard let requestUrl = templateJson["requestUrl"] as? String else {
35
+ throw RNCKakaoError.unknown("requestUrl is required")
36
+ }
37
+ url = ShareApi.shared.makeScrapUrl(
38
+ requestUrl: requestUrl,
39
+ templateId: templateId == noCustomTemplateId ? nil : templateId,
40
+ templateArgs: templateArgs,
41
+ serverCallbackArgs: serverCallbackArgs
42
+ )
43
+ } else {
44
+ var template: [String: Any?] = templateJson
45
+ let templatable = try self.generateTemplatable(templateType, &template)
46
+ url = ShareApi.shared.makeDefaultUrl(
47
+ templatable: templatable, serverCallbackArgs: serverCallbackArgs
48
+ )
49
+ }
50
+ guard let url else {
51
+ throw RNCKakaoError.unknown("Failed to create sharing URL")
52
+ }
53
+ resolve(url.absoluteString)
54
+ } catch {
55
+ RNCKakaoUtil.reject(reject, error)
56
+ }
57
+ }
58
+ }
59
+
60
+ @objc public func isKakaoTalkSharingAvailable(_ resolve: @escaping RCTPromiseResolveBlock) {
61
+ onMain {
62
+ resolve(ShareApi.isKakaoTalkSharingAvailable())
63
+ }
64
+ }
65
+
66
+ @objc public func getTemplateDiagnostics(
67
+ _ templateType: String,
68
+ templateId: Int64,
69
+ templateJson: [String: Any],
70
+ templateArgs: [String: String]?,
71
+ serverCallbackArgs: [String: String]?,
72
+ pickerSettings: [String: Any]?,
73
+ resolve: @escaping RCTPromiseResolveBlock,
74
+ reject: @escaping RCTPromiseRejectBlock
75
+ ) {
76
+ onMain {
77
+ let requestUrl = templateType == "scrap" ? templateJson["requestUrl"] as? String : nil
78
+ guard templateType != "scrap" || requestUrl != nil else {
79
+ RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("requestUrl is required"))
80
+ return
81
+ }
82
+ let customTemplateId: Int64? =
83
+ templateType == "custom" || templateId != noCustomTemplateId ? templateId : nil
84
+ self.runShare(
85
+ templateType: templateType,
86
+ templateId: customTemplateId,
87
+ defaultTemplate: templateJson,
88
+ useWebBrowserIfKakaoTalkNotAvailable: false,
89
+ templateArgs: templateArgs,
90
+ serverCallbackArgs: serverCallbackArgs,
91
+ pickerSettings: pickerSettings,
92
+ requestUrl: requestUrl,
93
+ resolve: resolve,
94
+ reject: reject,
95
+ diagnosticsOnly: true
96
+ )
97
+ }
98
+ }
99
+
100
+ @objc public func uploadImage(
101
+ _ imageUri: String,
102
+ secureResource: Bool,
103
+ resolve: @escaping RCTPromiseResolveBlock,
104
+ reject: @escaping RCTPromiseRejectBlock
105
+ ) {
106
+ DispatchQueue.global(qos: .userInitiated).async {
107
+ do {
108
+ let maxImageBytes = 5 * 1024 * 1024
109
+ let imageSizeError = "Image must be no larger than 5 MB"
110
+ let data: Data
111
+ if imageUri.hasPrefix("data:image/") {
112
+ let parts = imageUri.split(separator: ",", maxSplits: 1, omittingEmptySubsequences: false)
113
+ guard parts.count == 2, parts[0].hasSuffix(";base64") else {
114
+ throw RNCKakaoError.unknown("Expected a base64 image data URI")
115
+ }
116
+ guard parts[1].utf8.count <= ((maxImageBytes + 2) / 3) * 4 else {
117
+ throw RNCKakaoError.unknown(imageSizeError)
118
+ }
119
+ guard let decoded = Data(base64Encoded: String(parts[1])) else {
120
+ throw RNCKakaoError.unknown("Expected a base64 image data URI")
121
+ }
122
+ data = decoded
123
+ } else {
124
+ let url = imageUri.hasPrefix("/") ? URL(fileURLWithPath: imageUri) : URL(string: imageUri)
125
+ guard let url, url.isFileURL else {
126
+ throw RNCKakaoError.unknown("Expected a local file or base64 image data URI")
127
+ }
128
+ let file = try FileHandle(forReadingFrom: url)
129
+ defer { try? file.close() }
130
+ data = try file.read(upToCount: maxImageBytes + 1) ?? Data()
131
+ }
132
+ guard data.count <= maxImageBytes else {
133
+ throw RNCKakaoError.unknown(imageSizeError)
134
+ }
135
+ guard let image = UIImage(data: data) else {
136
+ throw RNCKakaoError.unknown("Image file cannot be decoded")
137
+ }
138
+ onMain {
139
+ ShareApi.shared
140
+ .imageUpload(image: image, secureResource: secureResource) { result, error in
141
+ if let error {
142
+ RNCKakaoUtil.reject(reject, error)
143
+ } else if let result {
144
+ let original = result.infos.original
145
+ resolve([
146
+ "infos": [
147
+ "original": [
148
+ "url": original.url.absoluteString,
149
+ "contentType": original.contentType,
150
+ "length": original.length,
151
+ "width": original.width,
152
+ "height": original.height
153
+ ]
154
+ ]
155
+ ])
156
+ } else {
157
+ RNCKakaoUtil.reject(
158
+ reject,
159
+ RNCKakaoError.responseNotFound(name: "imageUploadResult")
160
+ )
161
+ }
162
+ }
163
+ }
164
+ } catch {
165
+ RNCKakaoUtil.reject(reject, error)
166
+ }
167
+ }
168
+ }
169
+
170
+ @objc public func shareScrapTemplate(
171
+ _ requestUrl: String,
172
+ useWebBrowserIfKakaoTalkNotAvailable: Bool,
173
+ templateId: NSNumber?,
174
+ templateArgs: [String: String]?,
175
+ serverCallbackArgs: [String: String]?,
176
+ pickerSettings: [String: Any]?,
177
+ resolve: @escaping RCTPromiseResolveBlock,
178
+ reject: @escaping RCTPromiseRejectBlock
179
+ ) {
180
+ onMain {
181
+ self.runShare(
182
+ templateType: "scrap",
183
+ templateId: templateId?.int64Value,
184
+ useWebBrowserIfKakaoTalkNotAvailable: useWebBrowserIfKakaoTalkNotAvailable,
185
+ templateArgs: templateArgs,
186
+ serverCallbackArgs: serverCallbackArgs,
187
+ pickerSettings: pickerSettings,
188
+ requestUrl: requestUrl,
189
+ resolve: resolve,
190
+ reject: reject
191
+ )
192
+ }
193
+ }
194
+
195
+ @objc public func scrapImage(
196
+ _ imageUrl: String,
197
+ secureResource: Bool,
198
+ resolve: @escaping RCTPromiseResolveBlock,
199
+ reject: @escaping RCTPromiseRejectBlock
200
+ ) {
201
+ guard let url = URL(string: imageUrl) else {
202
+ RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("Invalid image URL"))
203
+ return
204
+ }
205
+ onMain {
206
+ ShareApi.shared.imageScrap(imageUrl: url, secureResource: secureResource) { result, error in
207
+ if let error {
208
+ RNCKakaoUtil.reject(reject, error)
209
+ } else if let result {
210
+ let original = result.infos.original
211
+ resolve([
212
+ "infos": [
213
+ "original": [
214
+ "url": original.url.absoluteString,
215
+ "contentType": original.contentType,
216
+ "length": original.length,
217
+ "width": original.width,
218
+ "height": original.height
219
+ ]
220
+ ]
221
+ ])
222
+ } else {
223
+ RNCKakaoUtil.reject(reject, RNCKakaoError.responseNotFound(name: "imageUploadResult"))
224
+ }
225
+ }
226
+ }
227
+ }
228
+
13
229
  @objc public func shareOrSendMeOrSendFriendOrWhatever(
14
230
  _ sendType: String,
15
231
  templateType: String,
@@ -19,6 +235,7 @@ import SafariServices
19
235
  useWebBrowserIfKakaoTalkNotAvailable: Bool,
20
236
  templateArgs: [String: String]?,
21
237
  serverCallbackArgs: [String: String]?,
238
+ pickerSettings: [String: Any]?,
22
239
  resolve: @escaping RCTPromiseResolveBlock,
23
240
  reject: @escaping RCTPromiseRejectBlock
24
241
  ) {
@@ -32,9 +249,44 @@ import SafariServices
32
249
  useWebBrowserIfKakaoTalkNotAvailable: useWebBrowserIfKakaoTalkNotAvailable,
33
250
  templateArgs: templateArgs,
34
251
  serverCallbackArgs: serverCallbackArgs,
252
+ pickerSettings: pickerSettings,
35
253
  resolve: resolve,
36
254
  reject: reject
37
255
  )
256
+ } else if templateType == "scrap" {
257
+ guard let requestUrl = templateJson["requestUrl"] as? String else {
258
+ RNCKakaoUtil.reject(
259
+ reject,
260
+ RNCKakaoError.unknown("requestUrl is required for scrap messages")
261
+ )
262
+ return
263
+ }
264
+ let customTemplateId: Int64? = templateId == noCustomTemplateId ? nil : templateId
265
+ if sendType == "send-me" {
266
+ self.runSendMe(
267
+ templateType: templateType,
268
+ templateId: customTemplateId,
269
+ templateArgs: templateArgs,
270
+ resolve: resolve,
271
+ reject: reject,
272
+ requestUrl: requestUrl
273
+ )
274
+ } else if sendType == "send-friend" {
275
+ self.runSendFriend(
276
+ templateType: templateType,
277
+ templateId: customTemplateId,
278
+ receiverUuids: receiverUuids,
279
+ templateArgs: templateArgs,
280
+ resolve: resolve,
281
+ reject: reject,
282
+ requestUrl: requestUrl
283
+ )
284
+ } else {
285
+ RNCKakaoUtil.reject(
286
+ reject,
287
+ RNCKakaoError.unknown("Unknown sendType for scrap messages: \(sendType)")
288
+ )
289
+ }
38
290
  } else {
39
291
  self.shareOrSendDefaultTemplate(
40
292
  sendType: sendType,
@@ -43,6 +295,7 @@ import SafariServices
43
295
  receiverUuids: receiverUuids,
44
296
  useWebBrowserIfKakaoTalkNotAvailable: useWebBrowserIfKakaoTalkNotAvailable,
45
297
  serverCallbackArgs: serverCallbackArgs,
298
+ pickerSettings: pickerSettings,
46
299
  resolve: resolve,
47
300
  reject: reject
48
301
  )
@@ -58,6 +311,7 @@ import SafariServices
58
311
  useWebBrowserIfKakaoTalkNotAvailable: Bool,
59
312
  templateArgs: [String: String]?,
60
313
  serverCallbackArgs: [String: String]?,
314
+ pickerSettings: [String: Any]?,
61
315
  resolve: @escaping RCTPromiseResolveBlock,
62
316
  reject: @escaping RCTPromiseRejectBlock
63
317
  ) {
@@ -68,6 +322,7 @@ import SafariServices
68
322
  useWebBrowserIfKakaoTalkNotAvailable: useWebBrowserIfKakaoTalkNotAvailable,
69
323
  templateArgs: templateArgs,
70
324
  serverCallbackArgs: serverCallbackArgs,
325
+ pickerSettings: pickerSettings,
71
326
  resolve: resolve,
72
327
  reject: reject
73
328
  )
@@ -100,6 +355,7 @@ import SafariServices
100
355
  receiverUuids: [String],
101
356
  useWebBrowserIfKakaoTalkNotAvailable: Bool,
102
357
  serverCallbackArgs: [String: String]?,
358
+ pickerSettings: [String: Any]?,
103
359
  resolve: @escaping RCTPromiseResolveBlock,
104
360
  reject: @escaping RCTPromiseRejectBlock
105
361
  ) {
@@ -110,6 +366,7 @@ import SafariServices
110
366
  useWebBrowserIfKakaoTalkNotAvailable: useWebBrowserIfKakaoTalkNotAvailable,
111
367
  templateArgs: serverCallbackArgs,
112
368
  serverCallbackArgs: serverCallbackArgs,
369
+ pickerSettings: pickerSettings,
113
370
  resolve: resolve,
114
371
  reject: reject
115
372
  )
@@ -134,7 +391,8 @@ import SafariServices
134
391
  defaultTemplate: [String: Any?]? = nil,
135
392
  templateArgs: [String: String]? = nil,
136
393
  resolve: @escaping RCTPromiseResolveBlock,
137
- reject: @escaping RCTPromiseRejectBlock
394
+ reject: @escaping RCTPromiseRejectBlock,
395
+ requestUrl: String? = nil
138
396
  ) {
139
397
  let sendCompletion = { (error: Error?) in
140
398
  if let error {
@@ -144,7 +402,14 @@ import SafariServices
144
402
  }
145
403
  }
146
404
 
147
- if let templateId {
405
+ if let requestUrl {
406
+ TalkApi.shared.sendScrapMemo(
407
+ requestUrl: requestUrl,
408
+ templateId: templateId,
409
+ templateArgs: templateArgs,
410
+ completion: sendCompletion
411
+ )
412
+ } else if let templateId {
148
413
  TalkApi.shared.sendCustomMemo(
149
414
  templateId: templateId,
150
415
  templateArgs: templateArgs,
@@ -172,19 +437,37 @@ import SafariServices
172
437
  receiverUuids: [String],
173
438
  templateArgs: [String: String]? = nil,
174
439
  resolve: @escaping RCTPromiseResolveBlock,
175
- reject: @escaping RCTPromiseRejectBlock
440
+ reject: @escaping RCTPromiseRejectBlock,
441
+ requestUrl: String? = nil
176
442
  ) {
177
443
  let sendCompletion = { (messageSendResult: MessageSendResult?, error: Error?) in
178
444
  if let error {
179
445
  RNCKakaoUtil.reject(reject, error)
180
446
  } else if let messageSendResult {
181
- resolve(messageSendResult.successfulReceiverUuids ?? [])
447
+ resolve([
448
+ "successfulReceiverUuids": messageSendResult.successfulReceiverUuids ?? [],
449
+ "failureInfos": messageSendResult.failureInfos?.map { failure in
450
+ [
451
+ "code": failure.code,
452
+ "msg": failure.msg,
453
+ "receiverUuids": failure.receiverUuids
454
+ ]
455
+ } ?? []
456
+ ])
182
457
  } else {
183
458
  RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("messageSendResult"))
184
459
  }
185
460
  }
186
461
 
187
- if let templateId {
462
+ if let requestUrl {
463
+ TalkApi.shared.sendScrapMessage(
464
+ requestUrl: requestUrl,
465
+ templateId: templateId,
466
+ templateArgs: templateArgs,
467
+ receiverUuids: receiverUuids,
468
+ completion: sendCompletion
469
+ )
470
+ } else if let templateId {
188
471
  TalkApi.shared.sendCustomMessage(
189
472
  templateId: templateId,
190
473
  templateArgs: templateArgs,
@@ -217,16 +500,27 @@ import SafariServices
217
500
  useWebBrowserIfKakaoTalkNotAvailable: Bool,
218
501
  templateArgs: [String: String]? = nil,
219
502
  serverCallbackArgs: [String: String]?,
503
+ pickerSettings: [String: Any]?,
504
+ requestUrl: String? = nil,
220
505
  resolve: @escaping RCTPromiseResolveBlock,
221
- reject: @escaping RCTPromiseRejectBlock
506
+ reject: @escaping RCTPromiseRejectBlock,
507
+ diagnosticsOnly: Bool = false
222
508
  ) {
509
+ let result: Any? = requestUrl == nil ? 42 : nil
223
510
  let shareCompletion = { (sharingResult: SharingResult?, error: Error?) in
224
511
  if let error {
225
512
  RNCKakaoUtil.reject(reject, error)
226
513
  } else if let sharingResult {
514
+ if diagnosticsOnly {
515
+ resolve([
516
+ "warningMsg": sharingResult.warningMsg ?? [:],
517
+ "argumentMsg": sharingResult.argumentMsg ?? [:]
518
+ ])
519
+ return
520
+ }
227
521
  UIApplication.shared.open(sharingResult.url, options: [:]) { success in
228
522
  if success {
229
- resolve(42)
523
+ resolve(result)
230
524
  } else {
231
525
  RNCKakaoUtil.reject(
232
526
  reject,
@@ -239,10 +533,24 @@ import SafariServices
239
533
  }
240
534
  }
241
535
 
242
- if ShareApi.isKakaoTalkSharingAvailable() {
243
- if let templateId {
536
+ if diagnosticsOnly || ShareApi.isKakaoTalkSharingAvailable() {
537
+ let shareType = (pickerSettings?["type"] as? String).flatMap(ShareType.init(rawValue:))
538
+ let limit = (pickerSettings?["limit"] as? NSNumber)?.intValue
539
+ if let requestUrl {
540
+ ShareApi.shared.shareScrap(
541
+ requestUrl: requestUrl,
542
+ templateId: templateId,
543
+ templateArgs: templateArgs,
544
+ shareType: shareType,
545
+ limit: limit,
546
+ serverCallbackArgs: serverCallbackArgs,
547
+ completion: shareCompletion
548
+ )
549
+ } else if let templateId {
244
550
  ShareApi.shared.shareCustom(
245
551
  templateId: templateId,
552
+ shareType: shareType,
553
+ limit: limit,
246
554
  templateArgs: templateArgs,
247
555
  serverCallbackArgs: serverCallbackArgs,
248
556
  completion: shareCompletion
@@ -252,6 +560,8 @@ import SafariServices
252
560
  let templatable = try generateTemplatable(templateType, &defaultTemplate)
253
561
  ShareApi.shared.shareDefault(
254
562
  templatable: templatable,
563
+ shareType: shareType,
564
+ limit: limit,
255
565
  serverCallbackArgs: serverCallbackArgs,
256
566
  completion: shareCompletion
257
567
  )
@@ -265,25 +575,24 @@ import SafariServices
265
575
  )
266
576
  }
267
577
  } else if useWebBrowserIfKakaoTalkNotAvailable {
268
- if let templateId {
578
+ if let requestUrl {
579
+ if let url = ShareApi.shared.makeScrapUrl(
580
+ requestUrl: requestUrl,
581
+ templateId: templateId,
582
+ templateArgs: templateArgs,
583
+ serverCallbackArgs: serverCallbackArgs
584
+ ) {
585
+ presentShareUrl(url)
586
+ } else {
587
+ RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("makeScrapUrl failed"))
588
+ }
589
+ } else if let templateId {
269
590
  if let url = ShareApi.shared.makeCustomUrl(
270
591
  templateId: templateId,
271
592
  templateArgs: templateArgs,
272
593
  serverCallbackArgs: serverCallbackArgs
273
594
  ) {
274
- let safariViewController = SFSafariViewController(url: url)
275
- safariViewController.modalTransitionStyle = .crossDissolve
276
- safariViewController.modalPresentationStyle = .overCurrentContext
277
- RNCKakaoUtil.presentViewController(safariViewController) { success in
278
- if success {
279
- resolve(42)
280
- } else {
281
- RNCKakaoUtil.reject(
282
- reject,
283
- RNCKakaoError.unknown("SFSafariViewController open failed")
284
- )
285
- }
286
- }
595
+ presentShareUrl(url)
287
596
  } else {
288
597
  RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("makeCustomUrl failed"))
289
598
  }
@@ -295,19 +604,7 @@ import SafariServices
295
604
  templatable: templatable,
296
605
  serverCallbackArgs: serverCallbackArgs
297
606
  ) {
298
- let safariViewController = SFSafariViewController(url: url)
299
- safariViewController.modalTransitionStyle = .crossDissolve
300
- safariViewController.modalPresentationStyle = .overCurrentContext
301
- RNCKakaoUtil.presentViewController(safariViewController) { success in
302
- if success {
303
- resolve(42)
304
- } else {
305
- RNCKakaoUtil.reject(
306
- reject,
307
- RNCKakaoError.unknown("SFSafariViewController open failed")
308
- )
309
- }
310
- }
607
+ presentShareUrl(url)
311
608
  } else {
312
609
  RNCKakaoUtil.reject(reject, RNCKakaoError.unknown("makeDefaultUrl failed"))
313
610
  }
@@ -323,6 +620,22 @@ import SafariServices
323
620
  } else {
324
621
  RNCKakaoUtil.reject(reject, RNCKakaoError.kakaoAppNotAvailable(app: .talk))
325
622
  }
623
+
624
+ func presentShareUrl(_ url: URL) {
625
+ let safariViewController = SFSafariViewController(url: url)
626
+ safariViewController.modalTransitionStyle = .crossDissolve
627
+ safariViewController.modalPresentationStyle = .overCurrentContext
628
+ RNCKakaoUtil.presentViewController(safariViewController) { success in
629
+ if success {
630
+ resolve(result)
631
+ } else {
632
+ RNCKakaoUtil.reject(
633
+ reject,
634
+ RNCKakaoError.unknown("SFSafariViewController open failed")
635
+ )
636
+ }
637
+ }
638
+ }
326
639
  }
327
640
 
328
641
  private func generateTemplatable(