react-native-attachment-kit 1.0.0 → 1.0.2

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 (34) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +11 -1
  3. package/android/src/main/libs/rnattachmentkit-release.aar +0 -0
  4. package/android/src/newarch/java/com/rnattachmentkit/RNAttachmentKitModule.kt +3 -0
  5. package/android/src/oldarch/java/com/rnattachmentkit/RNAttachmentKitModule.kt +3 -0
  6. package/ios/RNAttachmentKit.swift +16 -0
  7. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Assets.car +0 -0
  8. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Headers/RNAttachmentKit-Swift.h +38 -1
  9. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Info.plist +0 -0
  10. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.abi.json +7143 -1781
  11. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.private.swiftinterface +115 -0
  12. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  13. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.swiftinterface +115 -0
  14. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/RNAttachmentKit +0 -0
  15. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeDirectory +0 -0
  16. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeResources +15 -15
  17. package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeSignature +0 -0
  18. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Assets.car +0 -0
  19. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Headers/RNAttachmentKit-Swift.h +76 -2
  20. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Info.plist +0 -0
  21. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.abi.json +7143 -1781
  22. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +115 -0
  23. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  24. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +115 -0
  25. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +7143 -1781
  26. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +115 -0
  27. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  28. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +115 -0
  29. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/RNAttachmentKit +0 -0
  30. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/_CodeSignature/CodeDirectory +0 -0
  31. package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/_CodeSignature/CodeResources +25 -25
  32. package/package.json +1 -1
  33. package/src/index.ts +45 -3
  34. package/src/types.ts +23 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.2 — 2026-10-09
4
+
5
+ Android:
6
+ - Overlay image viewer (`useOverlayViewer`) open/close animations are 50ms shorter: open 250→200ms (photo zoom now follows `openDuration` instead of a fixed 250ms), close 200→150ms.
7
+
8
+ ## 1.0.1 — 2026-10-09
9
+
10
+ New:
11
+ - `appearance: 'system' | 'light' | 'dark'` option — global default via `init(key, { appearance })`, per-call override on every `open*`. `'system'` (default) follows the device setting.
12
+ - `AttachmentKit.setDefaults({ languageCode, themeColor, appearance })` / `AttachmentKit.getDefaults()` — change global defaults any time after `init`.
13
+
14
+ Android fixes:
15
+ - Picker → editor no longer flashes the wrong theme when the app forces `appearance: 'light' | 'dark'` that differs from the device setting. The night mode is now set in `attachBaseContext` instead of `onCreate`, so AppCompat no longer draws the screen once and then recreates it. Same fix in `CropActivity`, `ProfileCropActivity`, `DrawingActivity`, `ImageViewerActivity`.
16
+ - Fixed crash `UninitializedPropertyAccessException: lateinit property viewPager` in `ImageEditorActivity.finish()` when the editor was recreated (theme recreate above, system dark-mode switch, or process restore). `finish()` now closes immediately if the screen was never set up, and the editor's photo list (`EditorDataHolder`) is cleared only when the editor really closes and only if it still holds that editor's list.
17
+ - Editor open/close/pull-to-dismiss background now uses the theme color `@color/editor_background` instead of hard-coded black. In light mode the editor used to fade in black and then flash to white when the photo pager appeared.
18
+ - Tapping a photo in the picker no longer blinks the grid cell before the zoom animation. The cell is now hidden right after the editor draws its first frame (the editor's overlay photo covers the cell at that moment), instead of when the picker launches the editor.
19
+ - Pull-to-dismiss in the editor now slides the selection badge away with the top bar (it used to stay floating on screen while the photo was dragged).
20
+ - Picker grid spacing reduced from 4dp to 1dp between cells (same as iOS).
21
+ - Guard against sending the same photo twice after editing (multi-select): the selection returned from the editor is mapped back to original URIs and de-duplicated, the editor keeps only original URIs in its selection, and `sendSelectedImagesNow()` de-duplicates after mapping to edited files.
22
+
3
23
  ## 1.0.0 — 2026-10-02
4
24
 
5
25
  Renamed from `react-native-turbo-image-picker` 2.0.8 (source 1.2.43 + the 2026-10-02 grid-menu and Android expand-position fixes) to `react-native-attachment-kit`. **JS API, options, event names and type names are unchanged** — apps only change the import path.
package/README.md CHANGED
@@ -69,7 +69,8 @@ import AttachmentKit from 'react-native-attachment-kit';
69
69
  // Pass your license key (if you have one to remove the watermark) and default configurations
70
70
  AttachmentKit.init("", {
71
71
  languageCode: 'en',
72
- themeColor: '#ff0000'
72
+ themeColor: '#ff0000',
73
+ appearance: 'system', // 'system' (default, follows the device) | 'light' | 'dark'
73
74
  }).catch(console.error);
74
75
 
75
76
  // Step 2: Open Image Picker
@@ -137,6 +138,15 @@ Initializes the module with a license key and global defaults.
137
138
  | `licenseKey` | `string` | Your license key. Pass `""` for evaluation (watermark shown). |
138
139
  | `options.themeColor` | `string` | Global default theme color (hex). |
139
140
  | `options.languageCode` | `string` | Global default language code. |
141
+ | `options.appearance` | `'system' \| 'light' \| 'dark'` | Global default screen mode. `'system'` (default) follows the device setting; `'light'` / `'dark'` force it. Every `open*` call also accepts `appearance` to override per call. |
142
+
143
+ ### `AttachmentKit.setDefaults(options)` / `AttachmentKit.getDefaults()`
144
+
145
+ Changes the global defaults (`languageCode`, `themeColor`, `appearance`) at any time after `init` — e.g. right after the user changes the app's theme or language. Only the values you pass are changed.
146
+
147
+ ```ts
148
+ AttachmentKit.setDefaults({ appearance: 'dark' })
149
+ ```
140
150
 
141
151
  ---
142
152
 
@@ -199,6 +199,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
199
199
 
200
200
  override fun openEditor(options: ReadableMap, promise: Promise) {
201
201
  val activity = getCurrentActivity()
202
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
202
203
  if (activity == null) {
203
204
  promise.reject(E_NO_ACTIVITY, "Activity doesn't exist")
204
205
  return
@@ -274,6 +275,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
274
275
  // 편집기/크롭 등 다른 화면들은 TurboImagePickerConfig.languageCode(전역)로 로케일을 잡는데,
275
276
  // 그동안 JS가 넘긴 languageCode를 여기에 반영하는 코드가 없어서 항상 기본값 "en"이었습니다.
276
277
  TurboImagePickerConfig.languageCode = languageCode
278
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
277
279
 
278
280
  val themeColor = if (options.hasKey("themeColor")) {
279
281
  options.getString("themeColor")
@@ -461,6 +463,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
461
463
  // 설정된 언어를 따릅니다.
462
464
  val viewerLanguageCode = if (options.hasKey("languageCode")) (options.getString("languageCode") ?: "en") else "en"
463
465
  TurboImagePickerConfig.languageCode = viewerLanguageCode
466
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
464
467
 
465
468
  var startX = -1f
466
469
  var startY = -1f
@@ -137,6 +137,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
137
137
  @ReactMethod
138
138
  override fun openEditor(options: ReadableMap, promise: Promise) {
139
139
  val activity = getCurrentActivity()
140
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
140
141
  if (activity == null) {
141
142
  promise.reject(E_NO_ACTIVITY, "Activity doesn't exist")
142
143
  return
@@ -212,6 +213,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
212
213
  // 편집기/크롭 등 다른 화면들은 TurboImagePickerConfig.languageCode(전역)로 로케일을 잡는데,
213
214
  // 그동안 JS가 넘긴 languageCode를 여기에 반영하는 코드가 없어서 항상 기본값 "en"이었습니다.
214
215
  TurboImagePickerConfig.languageCode = languageCode
216
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
215
217
 
216
218
  val themeColor = if (options.hasKey("themeColor")) {
217
219
  options.getString("themeColor")
@@ -458,6 +460,7 @@ class RNAttachmentKitModule(reactContext: ReactApplicationContext) :
458
460
  // 설정된 언어를 따릅니다.
459
461
  val viewerLanguageCode = if (options.hasKey("languageCode")) (options.getString("languageCode") ?: "en") else "en"
460
462
  TurboImagePickerConfig.languageCode = viewerLanguageCode
463
+ TurboImagePickerConfig.updateAppearance(if (options.hasKey("appearance")) options.getString("appearance") else null)
461
464
 
462
465
  val openDuration = if (options.hasKey("openDuration")) options.getInt("openDuration") else defaultAnimationConfig["viewerOpen"] ?: 250
463
466
  val closeDuration = if (options.hasKey("closeDuration")) options.getInt("closeDuration") else defaultAnimationConfig["viewerClose"] ?: 200
@@ -22,6 +22,16 @@ import SDWebImageWebPCoder
22
22
 
23
23
  @objc(RNAttachmentKit)
24
24
  class RNAttachmentKit: RCTEventEmitter {
25
+
26
+ /// RN 옵션 appearance: "light" | "dark" | "system"(기본, 생략) → 화면 강제 모드.
27
+ /// "system" 이면 기기 설정을 따릅니다 (.unspecified).
28
+ static func interfaceStyle(_ options: NSDictionary?) -> UIUserInterfaceStyle {
29
+ switch (options?["appearance"] as? String)?.lowercased() {
30
+ case "dark": return .dark
31
+ case "light": return .light
32
+ default: return .unspecified
33
+ }
34
+ }
25
35
 
26
36
  public static var shared: RNAttachmentKit?
27
37
 
@@ -286,6 +296,7 @@ class RNAttachmentKit: RCTEventEmitter {
286
296
  self.zoomAnimator.sourceImage = nil
287
297
 
288
298
  viewerVC.modalPresentationStyle = .custom
299
+ viewerVC.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
289
300
  viewerVC.transitioningDelegate = self
290
301
 
291
302
  self.activeViewerVC = viewerVC
@@ -452,6 +463,7 @@ class RNAttachmentKit: RCTEventEmitter {
452
463
  editorVC.allAssets = [asset]
453
464
  editorVC.currentIndex = 0
454
465
  editorVC.modalPresentationStyle = .fullScreen
466
+ editorVC.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
455
467
  editorVC.singlePhotoMode = true
456
468
  if let color = themeColor {
457
469
  editorVC.themeColor = color
@@ -502,6 +514,7 @@ class RNAttachmentKit: RCTEventEmitter {
502
514
  editorVC.standaloneImage = image
503
515
  editorVC.currentIndex = 0
504
516
  editorVC.modalPresentationStyle = .fullScreen
517
+ editorVC.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
505
518
  editorVC.singlePhotoMode = true
506
519
  if let color = themeColor {
507
520
  editorVC.themeColor = color
@@ -648,6 +661,7 @@ class RNAttachmentKit: RCTEventEmitter {
648
661
  editorVC.disableCrop = true
649
662
  editorVC.croppedImages = [0: croppedImage]
650
663
  editorVC.modalPresentationStyle = .overFullScreen
664
+ editorVC.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
651
665
 
652
666
  if let hex = currentGallery.themeColorHex, let color = UIColor(hexString: hex) {
653
667
  editorVC.themeColor = color
@@ -829,6 +843,7 @@ class RNAttachmentKit: RCTEventEmitter {
829
843
 
830
844
  let navigationController = UINavigationController(rootViewController: galleryVC)
831
845
  navigationController.modalPresentationStyle = .custom
846
+ navigationController.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
832
847
  navigationController.transitioningDelegate = galleryVC.customTransitioningDelegate
833
848
 
834
849
  // navigationController.view.backgroundColor 설정 제거 (투명한 탑바 지원을 위함)
@@ -1613,6 +1628,7 @@ fileprivate extension RNAttachmentKit {
1613
1628
  }
1614
1629
 
1615
1630
  editorVC.modalPresentationStyle = .overFullScreen
1631
+ editorVC.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
1616
1632
  editorVC.singlePhotoMode = !isMultiSelect
1617
1633
  // selectionMode 'multi' + 최대 1장: 편집 화면에서 다른 사진을 선택하면 기존 선택과 교체
1618
1634
  editorVC.replaceSelectionWhenFull = currentGallery.forceMultiMode && currentGallery.maxSelection == 1
@@ -374,6 +374,31 @@ extern "C" {
374
374
 
375
375
  @class NSCoder;
376
376
  @class UITraitCollection;
377
+ /// 바 뒤 화면 하단을 아래로 갈수록 진하게 흐리게(+아주 옅게 어둡게) 덮는 배경. 터치는 통과.
378
+ SWIFT_CLASS("_TtC15RNAttachmentKit18AttachMenuBackdrop")
379
+ @interface AttachMenuBackdrop : UIView
380
+ - (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER;
381
+ - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder SWIFT_UNAVAILABLE;
382
+ - (void)layoutSubviews;
383
+ - (void)didMoveToWindow;
384
+ - (void)traitCollectionDidChange:(UITraitCollection * _Nullable)previousTraitCollection;
385
+ @end
386
+
387
+ SWIFT_CLASS("_TtC15RNAttachmentKit13AttachMenuBar")
388
+ @interface AttachMenuBar : UIView
389
+ - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder SWIFT_UNAVAILABLE;
390
+ - (void)didMoveToWindow;
391
+ - (void)layoutSubviews;
392
+ - (void)traitCollectionDidChange:(UITraitCollection * _Nullable)previousTraitCollection;
393
+ - (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE;
394
+ @end
395
+
396
+ @class UITabBar;
397
+ @class UITabBarItem;
398
+ @interface AttachMenuBar (SWIFT_EXTENSION(RNAttachmentKit)) <UITabBarDelegate>
399
+ - (void)tabBar:(UITabBar * _Nonnull)tabBar didSelectItem:(UITabBarItem * _Nonnull)item;
400
+ @end
401
+
377
402
  @class NSString;
378
403
  @class NSBundle;
379
404
  SWIFT_CLASS("_TtC15RNAttachmentKit25GalleryBaseViewController")
@@ -414,6 +439,13 @@ SWIFT_AVAILABILITY(ios,introduced=15.0)
414
439
  - (void)collectionView:(UICollectionView * _Nonnull)collectionView cancelPrefetchingForItemsAtIndexPaths:(NSArray<NSIndexPath *> * _Nonnull)indexPaths;
415
440
  @end
416
441
 
442
+ @class UIDocumentPickerViewController;
443
+ @class NSURL;
444
+ @interface GalleryBaseViewController (SWIFT_EXTENSION(RNAttachmentKit)) <UIDocumentPickerDelegate>
445
+ - (void)documentPicker:(UIDocumentPickerViewController * _Nonnull)controller didPickDocumentsAtURLs:(NSArray<NSURL *> * _Nonnull)urls;
446
+ - (void)documentPickerWasCancelled:(UIDocumentPickerViewController * _Nonnull)controller;
447
+ @end
448
+
417
449
  @class UIImagePickerController;
418
450
  @interface GalleryBaseViewController (SWIFT_EXTENSION(RNAttachmentKit)) <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
419
451
  - (void)imagePickerController:(UIImagePickerController * _Nonnull)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey, id> * _Nonnull)info;
@@ -445,6 +477,12 @@ SWIFT_CLASS("_TtC15RNAttachmentKit21GalleryViewController")
445
477
  - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder OBJC_DESIGNATED_INITIALIZER;
446
478
  @end
447
479
 
480
+ @class UIGestureRecognizer;
481
+ @class UITouch;
482
+ @interface GalleryViewController (SWIFT_EXTENSION(RNAttachmentKit)) <UIGestureRecognizerDelegate>
483
+ - (BOOL)gestureRecognizer:(UIGestureRecognizer * _Nonnull)gestureRecognizer shouldReceiveTouch:(UITouch * _Nonnull)touch SWIFT_WARN_UNUSED_RESULT;
484
+ @end
485
+
448
486
  @protocol UIViewControllerAnimatedTransitioning;
449
487
  SWIFT_CLASS("_TtC15RNAttachmentKit29ImageEditorTransitionDelegate")
450
488
  @interface ImageEditorTransitionDelegate : NSObject <UIViewControllerTransitioningDelegate>
@@ -475,7 +513,6 @@ SWIFT_CLASS("_TtC15RNAttachmentKit25ImageEditorViewController")
475
513
  - (void)collectionView:(UICollectionView * _Nonnull)cv cancelPrefetchingForItemsAtIndexPaths:(NSArray<NSIndexPath *> * _Nonnull)indexPaths;
476
514
  @end
477
515
 
478
- @class UIGestureRecognizer;
479
516
  @interface ImageEditorViewController (SWIFT_EXTENSION(RNAttachmentKit)) <UIGestureRecognizerDelegate>
480
517
  - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer * _Nonnull)gestureRecognizer SWIFT_WARN_UNUSED_RESULT;
481
518
  - (BOOL)gestureRecognizer:(UIGestureRecognizer * _Nonnull)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer * _Nonnull)otherGestureRecognizer SWIFT_WARN_UNUSED_RESULT;