react-native-attachment-kit 1.0.1 → 1.0.5
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/CHANGELOG.md +116 -0
- package/README.md +356 -213
- package/android/build.gradle +3 -0
- package/android/src/main/libs/rnattachmentkit-release.aar +0 -0
- package/android/src/newarch/java/com/rnattachmentkit/RNAttachmentKitModule.kt +308 -10
- package/android/src/oldarch/java/com/rnattachmentkit/RNAttachmentKitModule.kt +311 -9
- package/ios/RNAttachmentKit.m +44 -0
- package/ios/RNAttachmentKit.swift +307 -23
- package/ios/RNAttachmentKit.xcframework/Info.plist +5 -5
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Assets.car +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Headers/RNAttachmentKit-Swift.h +30 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.abi.json +20349 -13021
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.private.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/RNAttachmentKit +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_crop_reflect~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_crop_reflect~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_crop_rotate~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_crop_rotate~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_delete~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_delete~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_forward~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_forward~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_reward~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_reward~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_back~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_back~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_blur~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_blur~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check_small~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check_small~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_close~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_close~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_crop~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_crop~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_drawing~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_drawing~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_effect~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_effect~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_emoji~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_emoji~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_eraser~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_eraser~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_mosaic~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_mosaic~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_text~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_editor_text~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_text_add~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/ToolbarIcons/ic_text_add~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeDirectory +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeResources +194 -62
- package/ios/RNAttachmentKit.xcframework/ios-arm64/RNAttachmentKit.framework/_CodeSignature/CodeSignature +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Assets.car +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Headers/RNAttachmentKit-Swift.h +60 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.abi.json +20349 -13021
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.abi.json +20349 -13021
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/Modules/RNAttachmentKit.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +118 -1
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/RNAttachmentKit +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_crop_reflect~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_crop_reflect~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_crop_rotate~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_crop_rotate~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_delete~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_delete~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_forward~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_forward~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_reward~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_drawing_reward~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_back~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_back~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_blur~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_blur~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check_small~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check_small~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_check~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_close~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_close~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_crop~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_crop~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_drawing~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_drawing~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_effect~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_effect~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_emoji~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_emoji~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_eraser~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_eraser~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_mosaic~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_mosaic~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_text~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_editor_text~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_text_add~dark.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/ToolbarIcons/ic_text_add~light.webp +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/_CodeSignature/CodeDirectory +0 -0
- package/ios/RNAttachmentKit.xcframework/ios-arm64_x86_64-simulator/RNAttachmentKit.framework/_CodeSignature/CodeResources +204 -72
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_crop_reflect~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_crop_reflect~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_crop_rotate~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_crop_rotate~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_delete~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_delete~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_forward~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_forward~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_reward~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_drawing_reward~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_back~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_back~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_blur~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_blur~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_check_small~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_check_small~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_check~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_check~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_close~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_close~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_crop~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_crop~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_drawing~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_drawing~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_effect~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_effect~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_emoji~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_emoji~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_eraser~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_eraser~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_mosaic~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_mosaic~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_text~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_editor_text~light.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_text_add~dark.webp +0 -0
- package/ios/RNAttachmentKitAssets/ToolbarIcons/ic_text_add~light.webp +0 -0
- package/package.json +1 -1
- package/src/NativeAttachmentKit.ts +10 -0
- package/src/index.d.ts +5 -56
- package/src/index.ts +188 -35
- package/src/types.ts +207 -11
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import UIKit
|
|
9
9
|
import Photos
|
|
10
10
|
import ImageIO
|
|
11
|
+
import CoreLocation
|
|
11
12
|
import RNAttachmentKit
|
|
12
13
|
|
|
13
14
|
#if RCT_NEW_ARCH_ENABLED
|
|
@@ -64,7 +65,8 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
64
65
|
@objc
|
|
65
66
|
override func supportedEvents() -> [String]! {
|
|
66
67
|
return ["onSelectionChange", "onImageProcessed", "onPageSelected", "onViewerWillClose", "onImageDeleted",
|
|
67
|
-
"onGalleryItemDeleted", "onGalleryNeedPage", "onGalleryClosed", "onGalleryGridSizeChanged"
|
|
68
|
+
"onGalleryItemDeleted", "onGalleryNeedPage", "onGalleryClosed", "onGalleryGridSizeChanged",
|
|
69
|
+
"onLocationSelected", "onFilesSelected"]
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
// MARK: - Public Methods
|
|
@@ -171,6 +173,213 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
171
173
|
}
|
|
172
174
|
}
|
|
173
175
|
|
|
176
|
+
// MARK: - Map Viewer (위치 메시지 → 지도)
|
|
177
|
+
|
|
178
|
+
private weak var activeMapViewerVC: MapViewerViewController?
|
|
179
|
+
/// updateMapViewerSourceRect 로 갱신되는 닫힘 위치 (window points)
|
|
180
|
+
private var mapViewerSourceRect: CGRect?
|
|
181
|
+
|
|
182
|
+
private static func cgFloat(_ v: Any?) -> CGFloat? {
|
|
183
|
+
if let n = v as? NSNumber { return CGFloat(truncating: n) }
|
|
184
|
+
if let d = v as? Double { return CGFloat(d) }
|
|
185
|
+
return nil
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private static func parseRect(_ v: Any?) -> CGRect? {
|
|
189
|
+
guard let d = v as? NSDictionary,
|
|
190
|
+
let x = cgFloat(d["x"]), let y = cgFloat(d["y"]),
|
|
191
|
+
let w = cgFloat(d["width"]), let h = cgFloat(d["height"]), w > 0, h > 0 else { return nil }
|
|
192
|
+
return CGRect(x: x, y: y, width: w, height: h)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/// 말풍선 이미지(정적 지도 스냅샷) 로드. 메모리/디스크 캐시 → file:// → 다운로드 순.
|
|
196
|
+
/// 실패하거나 너무 오래 걸리면 nil (이미지 없이 지도만 엶)
|
|
197
|
+
/// completion(이미지, 마커 뺀 이미지인지). renderLocationThumbnail 결과면 마커 뺀 짝을 씀 → 뷰어가 마커를 따로 그려
|
|
198
|
+
/// 말풍선 속 크기 ↔ 지도 마커 크기로 자연스럽게 바꿈
|
|
199
|
+
private func loadMapSourceImage(_ uri: String?, completion: @escaping (UIImage?, Bool) -> Void) {
|
|
200
|
+
guard let uri = uri, !uri.isEmpty else { completion(nil, false); return }
|
|
201
|
+
if uri.hasPrefix("file://") || uri.hasPrefix("/") {
|
|
202
|
+
let path = uri.hasPrefix("file://") ? (URL(string: uri)?.path ?? String(uri.dropFirst(7))) : uri
|
|
203
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
204
|
+
if let base = LocationThumbnailRenderer.markerlessFile(for: path), let img = UIImage(contentsOfFile: base) {
|
|
205
|
+
DispatchQueue.main.async { completion(img, true) }
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
let image = UIImage(contentsOfFile: path)
|
|
209
|
+
DispatchQueue.main.async { completion(image, false) }
|
|
210
|
+
}
|
|
211
|
+
return
|
|
212
|
+
}
|
|
213
|
+
if let cached = ViewerImageCache.shared.getMemoryImage(for: uri) { completion(cached, false); return }
|
|
214
|
+
var done = false
|
|
215
|
+
let finish: (UIImage?) -> Void = { image in
|
|
216
|
+
DispatchQueue.main.async {
|
|
217
|
+
guard !done else { return }
|
|
218
|
+
done = true
|
|
219
|
+
completion(image, false)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// 다운로드가 늦으면 이미지 없이 바로 엶 (탭 반응이 늦어지지 않게)
|
|
223
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { finish(nil) }
|
|
224
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
225
|
+
if let disk = ViewerImageCache.shared.getDiskImageSynchronously(for: uri) { finish(disk); return }
|
|
226
|
+
RemoteImageViewerViewController.prefetchImage(from: uri) { finish($0) }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@objc
|
|
231
|
+
func openMapViewer(_ options: NSDictionary,
|
|
232
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
233
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
234
|
+
guard let lat = RNAttachmentKit.cgFloat(options["latitude"]),
|
|
235
|
+
let lng = RNAttachmentKit.cgFloat(options["longitude"]) else {
|
|
236
|
+
reject("ERROR", "latitude and longitude are required", nil)
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
let sourceRect = RNAttachmentKit.parseRect(options["sourceRect"])
|
|
240
|
+
let imageUri = options["sourceImageUri"] as? String
|
|
241
|
+
DispatchQueue.main.async {
|
|
242
|
+
// 위치 정보만으로 여는 경우엔 이미지 로드를 기다리지 않음
|
|
243
|
+
let load: (@escaping (UIImage?, Bool) -> Void) -> Void = { done in
|
|
244
|
+
if sourceRect == nil { done(nil, false) } else { self.loadMapSourceImage(imageUri, completion: done) }
|
|
245
|
+
}
|
|
246
|
+
load { image, markerless in
|
|
247
|
+
guard let root = self.getRootViewController() else {
|
|
248
|
+
reject("ERROR", "Unable to get root view controller", nil)
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
var accent = UIColor(red: 1, green: 0.42, blue: 0.21, alpha: 1)
|
|
252
|
+
if let hex = options["themeColor"] as? String, let c = UIColor(hexString: hex) { accent = c }
|
|
253
|
+
let vc = MapViewerViewController(
|
|
254
|
+
latitude: Double(lat), longitude: Double(lng),
|
|
255
|
+
title: options["title"] as? String,
|
|
256
|
+
address: options["address"] as? String,
|
|
257
|
+
markerType: options["markerType"] as? String,
|
|
258
|
+
placeCategory: options["placeCategory"] as? String,
|
|
259
|
+
accentColor: accent,
|
|
260
|
+
languageCode: options["languageCode"] as? String ?? "en")
|
|
261
|
+
vc.overrideUserInterfaceStyle = RNAttachmentKit.interfaceStyle(options)
|
|
262
|
+
vc.showsDirections = (options["showDirections"] as? Bool) ?? true
|
|
263
|
+
vc.addressLanguageCode = (options["addressLanguageCode"] as? String).flatMap { $0.isEmpty ? nil : $0 }
|
|
264
|
+
if let span = RNAttachmentKit.cgFloat(options["spanMeters"]), span > 0 { vc.spanMeters = Double(span) }
|
|
265
|
+
if let r = RNAttachmentKit.cgFloat(options["sourceCornerRadius"]) { vc.sourceCornerRadius = r }
|
|
266
|
+
self.mapViewerSourceRect = sourceRect
|
|
267
|
+
if let rect = sourceRect {
|
|
268
|
+
vc.sourceRect = rect
|
|
269
|
+
vc.sourceImage = image
|
|
270
|
+
vc.sourceImageIsMarkerless = markerless && image != nil
|
|
271
|
+
vc.sourceRectProvider = { [weak self] in self?.mapViewerSourceRect }
|
|
272
|
+
}
|
|
273
|
+
vc.onClosed = { [weak self] in
|
|
274
|
+
self?.mapViewerSourceRect = nil
|
|
275
|
+
resolve(nil)
|
|
276
|
+
}
|
|
277
|
+
self.activeMapViewerVC = vc
|
|
278
|
+
root.present(vc, animated: sourceRect == nil)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@objc
|
|
284
|
+
func updateMapViewerSourceRect(_ rect: NSDictionary,
|
|
285
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
286
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
287
|
+
let parsed = RNAttachmentKit.parseRect(rect)
|
|
288
|
+
DispatchQueue.main.async {
|
|
289
|
+
if self.activeMapViewerVC != nil { self.mapViewerSourceRect = parsed }
|
|
290
|
+
resolve(nil)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/// 위치 메시지 말풍선 지도 썸네일을 이 기기에서 그려 캐시 (보낸 이미지 없이 위치 정보만으로)
|
|
295
|
+
@objc
|
|
296
|
+
func renderLocationThumbnail(_ options: NSDictionary,
|
|
297
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
298
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
299
|
+
guard let lat = RNAttachmentKit.cgFloat(options["latitude"]),
|
|
300
|
+
let lng = RNAttachmentKit.cgFloat(options["longitude"]),
|
|
301
|
+
let w = RNAttachmentKit.cgFloat(options["width"]), w > 0 else {
|
|
302
|
+
reject("E_INVALID_ARGS", "latitude, longitude and width are required", nil)
|
|
303
|
+
return
|
|
304
|
+
}
|
|
305
|
+
DispatchQueue.main.async {
|
|
306
|
+
// 비율(aspect)이 있으면 세로는 가로에서 계산, 없으면 height 그대로
|
|
307
|
+
guard let h = LocationThumbnailRenderer.height(forWidth: w, aspect: options["aspect"] as? String)
|
|
308
|
+
?? RNAttachmentKit.cgFloat(options["height"]), h > 0 else {
|
|
309
|
+
reject("E_INVALID_ARGS", "height (or aspect) is required", nil)
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
var accent = UIColor(red: 1, green: 0.42, blue: 0.21, alpha: 1)
|
|
313
|
+
if let hex = options["themeColor"] as? String, let c = UIColor(hexString: hex) { accent = c }
|
|
314
|
+
var style = RNAttachmentKit.interfaceStyle(options)
|
|
315
|
+
if style == .unspecified {
|
|
316
|
+
// "system": 지금 앱 화면 모드
|
|
317
|
+
style = UIApplication.shared.connectedScenes.compactMap { ($0 as? UIWindowScene)?.windows.first(where: \.isKeyWindow) }
|
|
318
|
+
.first?.traitCollection.userInterfaceStyle ?? UITraitCollection.current.userInterfaceStyle
|
|
319
|
+
}
|
|
320
|
+
var me: CLLocationCoordinate2D?
|
|
321
|
+
if let mlat = RNAttachmentKit.cgFloat(options["myLatitude"]), let mlng = RNAttachmentKit.cgFloat(options["myLongitude"]) {
|
|
322
|
+
me = CLLocationCoordinate2D(latitude: Double(mlat), longitude: Double(mlng))
|
|
323
|
+
}
|
|
324
|
+
let span = RNAttachmentKit.cgFloat(options["spanMeters"]).map { Double($0) }
|
|
325
|
+
var req = LocationThumbnailRequest(
|
|
326
|
+
latitude: Double(lat), longitude: Double(lng),
|
|
327
|
+
size: CGSize(width: w, height: h), scale: min(UIScreen.main.scale, 3),
|
|
328
|
+
isDark: style == .dark,
|
|
329
|
+
markerType: options["markerType"] as? String,
|
|
330
|
+
placeCategory: options["placeCategory"] as? String,
|
|
331
|
+
spanMeters: (span ?? 0) > 0 ? span : nil,
|
|
332
|
+
accentColor: accent,
|
|
333
|
+
myLocation: me)
|
|
334
|
+
// 결과 이미지 최대 크기 (px). 둘 다 없으면 512 × 512, 하나만 주면 다른 쪽은 제한 없음
|
|
335
|
+
// (예: maxWidth 512 만 주고 세로가 기본 512 에 잘려 작아지는 일이 없게)
|
|
336
|
+
let maxW = RNAttachmentKit.cgFloat(options["maxWidth"]).flatMap { $0 > 0 ? $0 : nil }
|
|
337
|
+
let maxH = RNAttachmentKit.cgFloat(options["maxHeight"]).flatMap { $0 > 0 ? $0 : nil }
|
|
338
|
+
if maxW != nil || maxH != nil {
|
|
339
|
+
req.maxPixelWidth = maxW ?? .greatestFiniteMagnitude
|
|
340
|
+
req.maxPixelHeight = maxH ?? .greatestFiniteMagnitude
|
|
341
|
+
}
|
|
342
|
+
LocationThumbnailRenderer.render(req) { result in
|
|
343
|
+
switch result {
|
|
344
|
+
case .success(let dict): resolve(dict)
|
|
345
|
+
case .failure(let error): reject("E_THUMBNAIL_FAILED", error.localizedDescription, error)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// MARK: - Reverse geocode (기기 지오코더, 디스크 캐시)
|
|
352
|
+
|
|
353
|
+
@objc
|
|
354
|
+
func reverseGeocode(_ options: NSDictionary,
|
|
355
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
356
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
357
|
+
let lat = (options["latitude"] as? NSNumber)?.doubleValue ?? .nan
|
|
358
|
+
let lng = (options["longitude"] as? NSNumber)?.doubleValue ?? .nan
|
|
359
|
+
let lang = (options["languageCode"] as? String).flatMap { $0.isEmpty ? nil : $0 } ?? "en"
|
|
360
|
+
ReverseGeocoder.shared.reverseGeocode(latitude: lat, longitude: lng, languageCode: lang) { result in
|
|
361
|
+
switch result {
|
|
362
|
+
case .success(let r): resolve(r.dictionary)
|
|
363
|
+
case .failure(let e): reject(e.code, e.message, nil)
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
@objc
|
|
369
|
+
func clearReverseGeocodeCache(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
370
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
371
|
+
ReverseGeocoder.shared.clearCache { resolve(nil) }
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@objc
|
|
375
|
+
func clearLocationThumbnailCache(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
376
|
+
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
377
|
+
DispatchQueue.global(qos: .utility).async {
|
|
378
|
+
LocationThumbnailRenderer.clearCache()
|
|
379
|
+
resolve(nil)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
174
383
|
@objc
|
|
175
384
|
func openViewer(_ options: NSDictionary,
|
|
176
385
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
@@ -560,30 +769,42 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
560
769
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
561
770
|
reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
562
771
|
let startTime = CFAbsoluteTimeGetCurrent()
|
|
772
|
+
#if DEBUG
|
|
563
773
|
print("✅ [DEBUG] received options: \(options)")
|
|
564
774
|
print("🔵 [DEBUG] openGallery 시작 - 시간: \(startTime)")
|
|
565
|
-
|
|
775
|
+
#endif
|
|
776
|
+
|
|
777
|
+
// 예전에 파일/위치 탭에서 임시 폴더에 복사해 두고 24시간이 지난 것 정리 (백그라운드, UI 와 무관)
|
|
778
|
+
DispatchQueue.global(qos: .utility).async {
|
|
779
|
+
TempFileCleaner.cleanupStaleTempFiles()
|
|
780
|
+
}
|
|
781
|
+
|
|
566
782
|
// Main thread에서 실행
|
|
567
783
|
DispatchQueue.main.async { [weak self] () -> Void in
|
|
568
784
|
guard let self = self else {
|
|
569
785
|
reject("ERROR", "Module deallocated", nil)
|
|
570
786
|
return
|
|
571
787
|
}
|
|
572
|
-
|
|
788
|
+
|
|
789
|
+
#if DEBUG
|
|
573
790
|
print("🔵 [DEBUG] workItem 실행 시작 - 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - startTime))초")
|
|
574
|
-
|
|
791
|
+
#endif
|
|
792
|
+
|
|
575
793
|
let step1 = CFAbsoluteTimeGetCurrent()
|
|
576
794
|
guard let rootViewController = self.getRootViewController() else {
|
|
577
795
|
print("❌ [DEBUG] getRootViewController 실패")
|
|
578
796
|
reject("ERROR", "Unable to get root view controller", nil)
|
|
579
797
|
return
|
|
580
798
|
}
|
|
799
|
+
#if DEBUG
|
|
581
800
|
print("🔵 [DEBUG] getRootViewController 완료 - 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - step1))초")
|
|
582
|
-
|
|
801
|
+
#endif
|
|
802
|
+
|
|
583
803
|
let step2 = CFAbsoluteTimeGetCurrent()
|
|
584
|
-
print("🔵 [DEBUG] GalleryViewController 생성 시작...")
|
|
585
804
|
let galleryVC = GalleryViewController()
|
|
805
|
+
#if DEBUG
|
|
586
806
|
print("🔵 [DEBUG] GalleryViewController 생성 완료 - 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - step2))초")
|
|
807
|
+
#endif
|
|
587
808
|
|
|
588
809
|
// 현재 갤러리 참조 저장
|
|
589
810
|
self.currentGalleryVC = galleryVC
|
|
@@ -679,6 +900,8 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
679
900
|
editorVC.onCancel = { [weak currentGallery] in
|
|
680
901
|
currentGallery?.selectedAssets.removeAll()
|
|
681
902
|
currentGallery?.refreshSelectionAfterEdit()
|
|
903
|
+
// 결과 전달 책임이 갤러리로 돌아옴 → 닫기가 다시 취소(reject)를 보낼 수 있게
|
|
904
|
+
currentGallery?.hasReturnedImages = false
|
|
682
905
|
}
|
|
683
906
|
|
|
684
907
|
var savedDetent: UISheetPresentationController.Detent.Identifier? = nil
|
|
@@ -714,7 +937,35 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
714
937
|
}
|
|
715
938
|
}
|
|
716
939
|
|
|
717
|
-
|
|
940
|
+
// 첨부 메뉴(갤러리 / 위치 / 파일). 기본 false — 켜지 않으면 기존과 같음
|
|
941
|
+
galleryVC.showsAttachMenu = options["showAttachMenu"] as? Bool ?? false
|
|
942
|
+
// 위치 보내기 때 지도 캡처 이미지 (기본 true). false 면 위치 정보만 — 받는 쪽이 renderLocationThumbnail 로 그림
|
|
943
|
+
galleryVC.capturesLocationImage = options["captureLocationImage"] as? Bool ?? true
|
|
944
|
+
// 위치 탭에서 보내기 → onLocationSelected 이벤트로 결과를 넘기고, openGallery 는 빈 배열로 끝냄
|
|
945
|
+
galleryVC.onLocationSelected = { [weak self, weak galleryVC] location in
|
|
946
|
+
self?.currentGalleryVC = nil
|
|
947
|
+
self?.sendEvent(withName: "onLocationSelected", body: location.dictionary)
|
|
948
|
+
resolve([])
|
|
949
|
+
galleryVC?.releaseAfterReturn()
|
|
950
|
+
}
|
|
951
|
+
// 파일 탭에서 보내기 → onFilesSelected 이벤트 { files: [{uri, path, name, size, mimeType}] }, openGallery 는 빈 배열
|
|
952
|
+
// 일부 파일만 복사에 실패하면 (추가 필드) failed: [{name, error}] 를 함께 보냄 (files 는 그대로)
|
|
953
|
+
galleryVC.onFilesSelectedWithFailures = { [weak self, weak galleryVC] files, failures in
|
|
954
|
+
self?.currentGalleryVC = nil
|
|
955
|
+
var body: [String: Any] = ["files": files.map { $0.dictionary }]
|
|
956
|
+
if !failures.isEmpty { body["failed"] = failures.map { $0.dictionary } }
|
|
957
|
+
self?.sendEvent(withName: "onFilesSelected", body: body)
|
|
958
|
+
resolve([])
|
|
959
|
+
galleryVC?.releaseAfterReturn()
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// ⚠️ 클로저 안에서 galleryVC 를 강하게 잡으면 galleryVC → onImagesSelected → galleryVC 순환 참조가 되어
|
|
963
|
+
// (성공 경로는 viewDidDisappear 가 정리를 deinit 으로 미루므로) 갤러리가 영영 해제되지 않았습니다.
|
|
964
|
+
// 필요한 값은 미리 상수로 꺼내고, galleryVC 는 weak 로만 씁니다.
|
|
965
|
+
let galleryMaxWidth = galleryVC.maxWidth
|
|
966
|
+
let galleryMaxHeight = galleryVC.maxHeight
|
|
967
|
+
let galleryFormat = galleryVC.outputFormat // "webp" | "jpg" | "png"
|
|
968
|
+
galleryVC.onImagesSelected = { [weak self, weak galleryVC] selectedImages in
|
|
718
969
|
guard let self = self else { resolve([]); return }
|
|
719
970
|
|
|
720
971
|
guard !selectedImages.isEmpty else {
|
|
@@ -725,16 +976,22 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
725
976
|
|
|
726
977
|
var results: [[String: Any]] = []
|
|
727
978
|
let tempDir = self.prepareCacheDirectory()
|
|
728
|
-
let maxWidth =
|
|
729
|
-
let maxHeight =
|
|
730
|
-
let format =
|
|
979
|
+
let maxWidth = galleryMaxWidth
|
|
980
|
+
let maxHeight = galleryMaxHeight
|
|
981
|
+
let format = galleryFormat
|
|
731
982
|
let mimeType = self.mimeType(for: format)
|
|
732
983
|
let needResize = (maxWidth > 0 || maxHeight > 0)
|
|
984
|
+
let total = selectedImages.count
|
|
733
985
|
|
|
734
986
|
let resultsLock = NSLock()
|
|
735
|
-
|
|
987
|
+
// 처리한 이미지는 바로 놓아 주도록 (전체 UIImage 배열을 끝까지 들고 있지 않게) 옵셔널 배열로 옮김
|
|
988
|
+
var pending: [(PHAsset?, UIImage)?] = selectedImages.map { $0 }
|
|
989
|
+
|
|
736
990
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
737
|
-
for
|
|
991
|
+
for index in 0..<total {
|
|
992
|
+
guard let pair = pending[index] else { continue }
|
|
993
|
+
pending[index] = nil
|
|
994
|
+
autoreleasepool {
|
|
738
995
|
let (asset, image) = pair
|
|
739
996
|
let timestamp = Int(Date().timeIntervalSince1970 * 1000)
|
|
740
997
|
let originalSize = image.size
|
|
@@ -778,7 +1035,7 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
778
1035
|
|
|
779
1036
|
self.sendEvent(withName: "onImageProcessed", body: [
|
|
780
1037
|
"index": index,
|
|
781
|
-
"total":
|
|
1038
|
+
"total": total,
|
|
782
1039
|
"image": currentResult
|
|
783
1040
|
])
|
|
784
1041
|
} else {
|
|
@@ -828,15 +1085,18 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
828
1085
|
|
|
829
1086
|
self.sendEvent(withName: "onImageProcessed", body: [
|
|
830
1087
|
"index": index,
|
|
831
|
-
"total":
|
|
1088
|
+
"total": total,
|
|
832
1089
|
"image": currentResult
|
|
833
1090
|
])
|
|
834
1091
|
}
|
|
1092
|
+
} // end autoreleasepool
|
|
835
1093
|
} // end for
|
|
836
1094
|
|
|
837
1095
|
DispatchQueue.main.async {
|
|
838
1096
|
self.currentGalleryVC = nil
|
|
839
1097
|
resolve(results)
|
|
1098
|
+
// 결과를 넘긴 뒤: 갤러리의 PHCachingImageManager 캐시·콜백 해제 (닫힘 애니메이션에는 영향 없음)
|
|
1099
|
+
galleryVC?.releaseAfterReturn()
|
|
840
1100
|
}
|
|
841
1101
|
}
|
|
842
1102
|
}
|
|
@@ -877,13 +1137,16 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
877
1137
|
}
|
|
878
1138
|
}
|
|
879
1139
|
}
|
|
1140
|
+
#if DEBUG
|
|
880
1141
|
print("🔵 [DEBUG] Sheet 설정 완료 - 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - step3))초")
|
|
1142
|
+
#endif
|
|
881
1143
|
|
|
882
1144
|
let step4 = CFAbsoluteTimeGetCurrent()
|
|
883
|
-
print("🔵 [DEBUG] present 시작...")
|
|
884
1145
|
rootViewController.present(navigationController, animated: true)
|
|
1146
|
+
#if DEBUG
|
|
885
1147
|
print("🔵 [DEBUG] present 완료 - 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - step4))초")
|
|
886
1148
|
print("✅ [DEBUG] openGallery 전체 완료 - 총 경과: \(String(format: "%.3f", CFAbsoluteTimeGetCurrent() - startTime))초")
|
|
1149
|
+
#endif
|
|
887
1150
|
}
|
|
888
1151
|
}
|
|
889
1152
|
|
|
@@ -902,6 +1165,13 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
902
1165
|
return
|
|
903
1166
|
}
|
|
904
1167
|
|
|
1168
|
+
// openGallery 약속이 아직 안 풀렸으면 (닫기 버튼과 같은 경로로) 취소를 먼저 전달 → reject("CANCELLED")
|
|
1169
|
+
// 안 그러면 아래 cleanupMemory 가 콜백을 지워 버려 JS 약속이 영영 안 풀렸습니다.
|
|
1170
|
+
if !galleryVC.hasReturnedImages {
|
|
1171
|
+
galleryVC.hasReturnedImages = true
|
|
1172
|
+
galleryVC.onImagesSelected?([])
|
|
1173
|
+
}
|
|
1174
|
+
|
|
905
1175
|
// 갤러리 닫기 전 강제 정리
|
|
906
1176
|
galleryVC.forceCleanupBeforeDismiss()
|
|
907
1177
|
|
|
@@ -1032,14 +1302,18 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1032
1302
|
let options: [CFString: Any] = [kCGImageDestinationLossyCompressionQuality: quality]
|
|
1033
1303
|
CGImageDestinationAddImage(destination, cgImage, options as CFDictionary)
|
|
1034
1304
|
if CGImageDestinationFinalize(destination) {
|
|
1305
|
+
#if DEBUG
|
|
1035
1306
|
NSLog("✅ [encodeWebP] iOS 16 네이티브 WebP 인코딩 성공 - %d bytes", data.length)
|
|
1307
|
+
#endif
|
|
1036
1308
|
return data as Data
|
|
1037
1309
|
}
|
|
1038
1310
|
}
|
|
1039
1311
|
}
|
|
1040
1312
|
}
|
|
1041
1313
|
|
|
1314
|
+
#if DEBUG
|
|
1042
1315
|
NSLog("🟣 [encodeWebP] SDImageWebPCoder 런타임 폴백 시도")
|
|
1316
|
+
#endif
|
|
1043
1317
|
// iOS 14, 15이거나 네이티브 실패 시 SDImageWebPCoder 런타임 호출
|
|
1044
1318
|
if let coderClass = NSClassFromString("SDImageWebPCoder") as? NSObject.Type {
|
|
1045
1319
|
if coderClass.responds(to: NSSelectorFromString("sharedCoder")) {
|
|
@@ -1057,7 +1331,9 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1057
1331
|
// format: 3 (SDImageFormatWebP)
|
|
1058
1332
|
let options: [String: Any] = ["encodeCompressionQuality": quality]
|
|
1059
1333
|
if let data = encode(sharedCoder, encodeSel, image, 3, options) {
|
|
1334
|
+
#if DEBUG
|
|
1060
1335
|
NSLog("✅ [encodeWebP] SDImageWebPCoder 런타임 인코딩 성공 - %d bytes", data.count)
|
|
1336
|
+
#endif
|
|
1061
1337
|
return data
|
|
1062
1338
|
} else {
|
|
1063
1339
|
NSLog("❌ [encodeWebP] SDImageWebPCoder 런타임 인코딩 실패 (nil 반환)")
|
|
@@ -1237,6 +1513,7 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1237
1513
|
DispatchQueue.main.async {
|
|
1238
1514
|
self.currentGalleryVC = nil
|
|
1239
1515
|
reject("ERROR", "Failed to load image from editor", nil)
|
|
1516
|
+
galleryVC?.releaseAfterReturn()
|
|
1240
1517
|
}
|
|
1241
1518
|
return
|
|
1242
1519
|
}
|
|
@@ -1275,6 +1552,7 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1275
1552
|
DispatchQueue.main.async {
|
|
1276
1553
|
self.currentGalleryVC = nil
|
|
1277
1554
|
resolve([result])
|
|
1555
|
+
galleryVC?.releaseAfterReturn()
|
|
1278
1556
|
}
|
|
1279
1557
|
}
|
|
1280
1558
|
}
|
|
@@ -1289,10 +1567,12 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1289
1567
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
1290
1568
|
let photoManager = PhotoManager.shared
|
|
1291
1569
|
var results: [[String: Any]] = []
|
|
1292
|
-
let dispatchGroup = DispatchGroup()
|
|
1293
1570
|
let resultsLock = NSLock()
|
|
1294
1571
|
|
|
1572
|
+
// 한 장씩 순서대로 처리 (동시에 전부 디코딩하면 메모리가 치솟음). 해상도는 줄이지 않음
|
|
1295
1573
|
for (index, asset) in assets.enumerated() {
|
|
1574
|
+
autoreleasepool {
|
|
1575
|
+
let dispatchGroup = DispatchGroup()
|
|
1296
1576
|
dispatchGroup.enter()
|
|
1297
1577
|
let timestamp = Int(Date().timeIntervalSince1970 * 1000)
|
|
1298
1578
|
let originalUri = "ph://\(asset.localIdentifier)"
|
|
@@ -1367,10 +1647,10 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1367
1647
|
}
|
|
1368
1648
|
}
|
|
1369
1649
|
}
|
|
1650
|
+
dispatchGroup.wait()
|
|
1651
|
+
} // end autoreleasepool
|
|
1370
1652
|
}
|
|
1371
1653
|
|
|
1372
|
-
dispatchGroup.wait()
|
|
1373
|
-
|
|
1374
1654
|
DispatchQueue.main.async {
|
|
1375
1655
|
self.currentGalleryVC = nil
|
|
1376
1656
|
if results.isEmpty {
|
|
@@ -1379,6 +1659,7 @@ class RNAttachmentKit: RCTEventEmitter {
|
|
|
1379
1659
|
// 순서를 유지하기 위해
|
|
1380
1660
|
resolve(results)
|
|
1381
1661
|
}
|
|
1662
|
+
galleryVC.releaseAfterReturn()
|
|
1382
1663
|
}
|
|
1383
1664
|
}
|
|
1384
1665
|
}
|
|
@@ -1674,8 +1955,11 @@ fileprivate extension RNAttachmentKit {
|
|
|
1674
1955
|
self.editorTransitionDelegate?.onCurrentAssetChanged = { [weak currentGallery] currentAsset in
|
|
1675
1956
|
currentGallery?.setHiddenAsset(currentAsset, scrollIntoView: true)
|
|
1676
1957
|
}
|
|
1677
|
-
self.editorTransitionDelegate?.onEditorClosed = { [weak currentGallery] in
|
|
1958
|
+
self.editorTransitionDelegate?.onEditorClosed = { [weak self, weak currentGallery] in
|
|
1678
1959
|
currentGallery?.setHiddenAsset(nil)
|
|
1960
|
+
// 편집 화면이 닫혔으니 sourceImage/uncroppedImage 를 들고 있는 전환 델리게이트를 놓아 줌
|
|
1961
|
+
// (호출 중인 객체이므로 다음 런루프에서)
|
|
1962
|
+
DispatchQueue.main.async { self?.editorTransitionDelegate = nil }
|
|
1679
1963
|
}
|
|
1680
1964
|
currentGallery.setHiddenAsset(asset)
|
|
1681
1965
|
|
|
@@ -1686,10 +1970,10 @@ fileprivate extension RNAttachmentKit {
|
|
|
1686
1970
|
editorVC.themeColor = color
|
|
1687
1971
|
}
|
|
1688
1972
|
|
|
1689
|
-
editorVC.onConfirmMulti = { [weak currentGallery] (assets, croppedImages, filterStates) in
|
|
1973
|
+
editorVC.onConfirmMulti = { [weak currentGallery, weak editorVC] (assets, croppedImages, filterStates) in
|
|
1690
1974
|
guard let currentGallery = currentGallery else { return }
|
|
1691
1975
|
|
|
1692
|
-
editorVC
|
|
1976
|
+
editorVC?.dismiss(animated: true) {
|
|
1693
1977
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
1694
1978
|
var newlyEditedAssets: [PHAsset] = []
|
|
1695
1979
|
|
|
@@ -1731,7 +2015,7 @@ fileprivate extension RNAttachmentKit {
|
|
|
1731
2015
|
}
|
|
1732
2016
|
|
|
1733
2017
|
// patch398: 편집 화면의 전송 버튼 — 편집본을 갤러리에 반영하고 선택한 사진을 바로 전송(편집 화면/갤러리 모두 닫힘)
|
|
1734
|
-
editorVC.onSendMulti = { [weak currentGallery] (assets, croppedImages, filterStates) in
|
|
2018
|
+
editorVC.onSendMulti = { [weak currentGallery, weak editorVC] (assets, croppedImages, filterStates) in
|
|
1735
2019
|
guard let currentGallery = currentGallery else { return }
|
|
1736
2020
|
for asset in assets {
|
|
1737
2021
|
guard var img = croppedImages[asset] else { continue }
|
|
@@ -1748,7 +2032,7 @@ fileprivate extension RNAttachmentKit {
|
|
|
1748
2032
|
// patch399: 편집 화면의 이미지가 갤러리 자리로 돌아가는 애니메이션이 끝난 뒤에 전송합니다.
|
|
1749
2033
|
currentGallery.refreshThumbnails(for: assets)
|
|
1750
2034
|
currentGallery.updateSelectedCellNumbers()
|
|
1751
|
-
editorVC
|
|
2035
|
+
editorVC?.dismiss(animated: true) { [weak currentGallery] in
|
|
1752
2036
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
|
|
1753
2037
|
currentGallery?.sendSelectionFromEditor()
|
|
1754
2038
|
}
|
|
@@ -8,32 +8,32 @@
|
|
|
8
8
|
<key>BinaryPath</key>
|
|
9
9
|
<string>RNAttachmentKit.framework/RNAttachmentKit</string>
|
|
10
10
|
<key>LibraryIdentifier</key>
|
|
11
|
-
<string>ios-
|
|
11
|
+
<string>ios-arm64_x86_64-simulator</string>
|
|
12
12
|
<key>LibraryPath</key>
|
|
13
13
|
<string>RNAttachmentKit.framework</string>
|
|
14
14
|
<key>SupportedArchitectures</key>
|
|
15
15
|
<array>
|
|
16
16
|
<string>arm64</string>
|
|
17
|
+
<string>x86_64</string>
|
|
17
18
|
</array>
|
|
18
19
|
<key>SupportedPlatform</key>
|
|
19
20
|
<string>ios</string>
|
|
21
|
+
<key>SupportedPlatformVariant</key>
|
|
22
|
+
<string>simulator</string>
|
|
20
23
|
</dict>
|
|
21
24
|
<dict>
|
|
22
25
|
<key>BinaryPath</key>
|
|
23
26
|
<string>RNAttachmentKit.framework/RNAttachmentKit</string>
|
|
24
27
|
<key>LibraryIdentifier</key>
|
|
25
|
-
<string>ios-
|
|
28
|
+
<string>ios-arm64</string>
|
|
26
29
|
<key>LibraryPath</key>
|
|
27
30
|
<string>RNAttachmentKit.framework</string>
|
|
28
31
|
<key>SupportedArchitectures</key>
|
|
29
32
|
<array>
|
|
30
33
|
<string>arm64</string>
|
|
31
|
-
<string>x86_64</string>
|
|
32
34
|
</array>
|
|
33
35
|
<key>SupportedPlatform</key>
|
|
34
36
|
<string>ios</string>
|
|
35
|
-
<key>SupportedPlatformVariant</key>
|
|
36
|
-
<string>simulator</string>
|
|
37
37
|
</dict>
|
|
38
38
|
</array>
|
|
39
39
|
<key>CFBundlePackageType</key>
|
|
Binary file
|
|
@@ -347,7 +347,9 @@ extern "C" {
|
|
|
347
347
|
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
|
348
348
|
#endif
|
|
349
349
|
@import CoreFoundation;
|
|
350
|
+
@import CoreLocation;
|
|
350
351
|
@import Foundation;
|
|
352
|
+
@import MapKit;
|
|
351
353
|
@import ObjectiveC;
|
|
352
354
|
@import UIKit;
|
|
353
355
|
#endif
|
|
@@ -529,6 +531,34 @@ SWIFT_CLASS("_TtC15RNAttachmentKit25ImageEditorViewController")
|
|
|
529
531
|
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView * _Nonnull)scrollView;
|
|
530
532
|
@end
|
|
531
533
|
|
|
534
|
+
SWIFT_CLASS("_TtC15RNAttachmentKit23MapViewerViewController")
|
|
535
|
+
@interface MapViewerViewController : UIViewController
|
|
536
|
+
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)coder SWIFT_UNAVAILABLE;
|
|
537
|
+
- (void)viewDidLoad;
|
|
538
|
+
- (void)viewDidLayoutSubviews;
|
|
539
|
+
@property (nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle;
|
|
540
|
+
- (void)viewWillAppear:(BOOL)animated;
|
|
541
|
+
- (void)viewDidAppear:(BOOL)animated;
|
|
542
|
+
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil SWIFT_UNAVAILABLE;
|
|
543
|
+
@end
|
|
544
|
+
|
|
545
|
+
@class CLLocationManager;
|
|
546
|
+
@class CLLocation;
|
|
547
|
+
@interface MapViewerViewController (SWIFT_EXTENSION(RNAttachmentKit)) <CLLocationManagerDelegate>
|
|
548
|
+
- (void)locationManagerDidChangeAuthorization:(CLLocationManager * _Nonnull)manager;
|
|
549
|
+
- (void)locationManager:(CLLocationManager * _Nonnull)manager didUpdateLocations:(NSArray<CLLocation *> * _Nonnull)locations;
|
|
550
|
+
- (void)locationManager:(CLLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nonnull)error;
|
|
551
|
+
@end
|
|
552
|
+
|
|
553
|
+
@class MKMapView;
|
|
554
|
+
@protocol MKAnnotation;
|
|
555
|
+
@class MKAnnotationView;
|
|
556
|
+
@interface MapViewerViewController (SWIFT_EXTENSION(RNAttachmentKit)) <MKMapViewDelegate>
|
|
557
|
+
- (void)mapViewDidFinishRenderingMap:(MKMapView * _Nonnull)mapView fullyRendered:(BOOL)fullyRendered;
|
|
558
|
+
- (MKAnnotationView * _Nullable)mapView:(MKMapView * _Nonnull)mapView viewForAnnotation:(id <MKAnnotation> _Nonnull)annotation SWIFT_WARN_UNUSED_RESULT;
|
|
559
|
+
- (void)mapView:(MKMapView * _Nonnull)mapView didSelectAnnotationView:(MKAnnotationView * _Nonnull)view;
|
|
560
|
+
@end
|
|
561
|
+
|
|
532
562
|
/// 사진 모아보기 화면. 피커 갤러리(GalleryViewController)와 같은 바텀시트(60% → 확장, 아래로 끌어 닫기),
|
|
533
563
|
/// 같은 상단 바·칸 모양·스크롤바/날짜 표시를 씁니다. 칸을 누르면 뷰어가 그 칸에서 줌으로 열리고,
|
|
534
564
|
/// 뷰어에서 몇 장을 넘기든 닫으면 지금 보던 사진의 칸으로 돌아갑니다.
|