@imgly/editor-react-native 1.81.1 → 1.82.0-rc.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.
Files changed (26) hide show
  1. package/IMGLYEditorModule.podspec +3 -1
  2. package/README.md +17 -0
  3. package/android/build.gradle +1 -1
  4. package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnCreate.kt +1 -0
  5. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/Dock.kt +2 -0
  6. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/InspectorBar.kt +4 -0
  7. package/ios/IMGLYEditorModuleImplementation.swift +62 -0
  8. package/ios/Model/EditorPreset.swift +2 -0
  9. package/ios/Model/EditorResult.swift +2 -0
  10. package/ios/Model/EditorSettings.swift +2 -0
  11. package/ios/Model/Source.swift +2 -0
  12. package/ios/Package.swift +114 -0
  13. package/ios/StarterKits/Apparel/callbacks/OnCreate+Apparel.swift +6 -4
  14. package/ios/StarterKits/Design/callbacks/OnCreate+Design.swift +6 -4
  15. package/ios/StarterKits/Photo/callbacks/OnCreate+Photo.swift +6 -1
  16. package/ios/StarterKits/Postcard/callbacks/OnCreate+Postcard.swift +6 -4
  17. package/ios/StarterKits/Video/callbacks/OnCreate+Video.swift +6 -1
  18. package/ios/{Constants → bridge}/IMGLYConstants.m +3 -0
  19. package/ios/{IMGLYEditorModule.mm → bridge/IMGLYEditorModule.mm} +5 -24
  20. package/ios/bridge/IMGLYEditorModuleSupport.m +23 -0
  21. package/ios/{Constants → bridge/include}/IMGLYConstants.h +2 -0
  22. package/ios/bridge/include/IMGLYEditorModuleSupport.h +46 -0
  23. package/package.json +1 -1
  24. package/src/NativeIMGLYEditor.ts +1 -1
  25. package/ios/IMGLYEditorModule-Bridging-Header.h +0 -3
  26. /package/ios/{IMGLYEditorModule.h → bridge/include/IMGLYEditorModule.h} +0 -0
@@ -14,7 +14,9 @@ Pod::Spec.new do |s|
14
14
  s.source = { path: './ios' }
15
15
 
16
16
  s.source_files = 'ios/**/*.{h,m,mm,swift}'
17
- s.exclude_files = 'ios/StarterKits/**/*StarterKit.swift'
17
+ # ios/Package.swift is the manifest for React Native's experimental Swift
18
+ # Package Manager mode, not a source file.
19
+ s.exclude_files = ['ios/StarterKits/**/*StarterKit.swift', 'ios/Package.swift']
18
20
  s.resources = 'ios/StarterKits/*.{scene,png}'
19
21
 
20
22
  s.dependency 'IMGLYUI', s.version.to_s
package/README.md CHANGED
@@ -29,3 +29,20 @@ const result = await IMGLYEditor.openEditor(settings);
29
29
  ## Changelog
30
30
 
31
31
  To keep up-to-date with the latest changes, visit [CHANGELOG](https://img.ly/docs/cesdk/changelog/).
32
+
33
+ ## Swift Package Manager (experimental)
34
+
35
+ React Native 0.87 introduced an experimental Swift Package Manager mode (`npx react-native spm`) — see the [React Native 0.87 announcement](https://reactnative.dev/blog/2026/08/11/react-native-0.87) and the [0.87.0 release notes](https://github.com/react/react-native/releases/tag/v0.87.0). This module dual-ships a SwiftPM manifest (`ios/Package.swift`) next to its podspec, so React Native's SPM autolinking resolves it out of the box. CocoaPods currently remains the default integration path; the React Native team does not recommend the SPM mode for production yet.
36
+
37
+ The notes below describe React Native **0.87.0**. That is the version this
38
+ support was built and verified against. We have not verified newer React Native
39
+ versions, so we do not know whether these workarounds still apply there. React
40
+ Native calls this mode experimental and can change its commands, flags, and
41
+ generated layout in any release. Check the release notes of the React Native
42
+ version you use.
43
+
44
+ Note: React Native 0.87 pins its generated autolinking package to iOS 15 while this module requires iOS 16. Until the floor is derived from the linked libraries upstream, raise the `platforms:` entries in `react-native/scripts/spm/generate-spm-autolinking.js` to `.iOS(.v16)` (for example with `patch-package`).
45
+
46
+ Note: The app target itself must also build with an iOS 16 deployment target. The React Native template scaffolds a lower one, which works until your app code imports this module directly — for example for native customization — and then fails with a minimum-deployment-target error. Raise the **iOS Deployment Target** of the app target in Xcode to 16.0.
47
+
48
+ Note: React Native 0.87.0 ships `hermes-compiler` for bytecode version 98 while its prebuilt SwiftPM Hermes runtime expects 99, so any build with an embedded JS bundle crashes at startup. Install `hermes-compiler@^260318099` until a React Native release aligns the two.
@@ -146,7 +146,7 @@ repositories {
146
146
  }
147
147
 
148
148
  dependencies {
149
- api "ly.img:editor:1.81.1"
149
+ api "ly.img:editor:1.82.0-rc.0"
150
150
 
151
151
  implementation "androidx.activity:activity-ktx:1.9.0"
152
152
  implementation "androidx.appcompat:appcompat:1.7.1"
@@ -97,6 +97,7 @@ suspend fun VideoConfigurationBuilder.onLoadAssetSources() {
97
97
  "ly.img.text.styles",
98
98
  "ly.img.text.curves",
99
99
  "ly.img.text.components",
100
+ "ly.img.caption.presets",
100
101
  "ly.img.image",
101
102
  "ly.img.audio",
102
103
  "ly.img.video",
@@ -12,6 +12,7 @@ import ly.img.editor.core.component.Dock
12
12
  import ly.img.editor.core.component.EditorTrigger
13
13
  import ly.img.editor.core.component.remember
14
14
  import ly.img.editor.core.component.rememberAudiosLibrary
15
+ import ly.img.editor.core.component.rememberCaptions
15
16
  import ly.img.editor.core.component.rememberOverlaysLibrary
16
17
  import ly.img.editor.core.component.rememberResizeAll
17
18
  import ly.img.editor.core.component.rememberStickersAndShapesLibrary
@@ -60,6 +61,7 @@ fun VideoConfigurationBuilder.rememberDock() = Dock.remember {
60
61
  add { Dock.Button.rememberOverlaysLibrary() }
61
62
  add { Dock.Button.rememberTextLibrary() }
62
63
  add { Dock.Button.rememberStickersAndShapesLibrary() }
64
+ add { Dock.Button.rememberCaptions() }
63
65
  add { Dock.Button.rememberAudiosLibrary() }
64
66
  add { Dock.Button.rememberVoiceoverRecord() }
65
67
  add { Dock.Button.rememberResizeAll() }
@@ -9,10 +9,12 @@ import ly.img.editor.core.component.remember
9
9
  import ly.img.editor.core.component.rememberAdjustments
10
10
  import ly.img.editor.core.component.rememberAnimations
11
11
  import ly.img.editor.core.component.rememberBlur
12
+ import ly.img.editor.core.component.rememberCaptionStyle
12
13
  import ly.img.editor.core.component.rememberClipSpeed
13
14
  import ly.img.editor.core.component.rememberCrop
14
15
  import ly.img.editor.core.component.rememberDelete
15
16
  import ly.img.editor.core.component.rememberDuplicate
17
+ import ly.img.editor.core.component.rememberEditCaptions
16
18
  import ly.img.editor.core.component.rememberEditText
17
19
  import ly.img.editor.core.component.rememberEffect
18
20
  import ly.img.editor.core.component.rememberEnterGroup
@@ -41,6 +43,8 @@ fun VideoConfigurationBuilder.rememberInspectorBar() = InspectorBar.remember {
41
43
  InspectorBar.ListBuilder.remember {
42
44
  add { InspectorBar.Button.rememberVoiceover() } // Voiceover Audio
43
45
  add { InspectorBar.Button.rememberReplace() } // Video, Image, Sticker, Audio
46
+ add { InspectorBar.Button.rememberEditCaptions() } // Caption
47
+ add { InspectorBar.Button.rememberCaptionStyle() } // Caption
44
48
  add { InspectorBar.Button.rememberEditText() } // Text
45
49
  add { InspectorBar.Button.rememberTextPresets() } // Text
46
50
  add { InspectorBar.Button.rememberFormatText() } // Text
@@ -0,0 +1,62 @@
1
+ import Foundation
2
+ #if canImport(IMGLYEditorModuleObjC)
3
+ // Swift Package Manager builds the Objective-C++ bridge as a separate target.
4
+ // Under CocoaPods both languages share one module, so no import is needed.
5
+ import IMGLYEditorModuleObjC
6
+ #endif
7
+
8
+ /// The Swift implementation behind the Objective-C++ React Native bridge.
9
+ ///
10
+ /// The bridge resolves this class at runtime by its stable Objective-C name
11
+ /// (see `IMGLYEditorModuleImplementationProvider`), so no static
12
+ /// Objective-C → Swift reference exists. This is what allows building the
13
+ /// module with Swift Package Manager, which cannot compile mixed
14
+ /// Swift/Objective-C++ targets (SE-0403).
15
+ @objc(IMGLYEditorModuleDefaultImplementation)
16
+ final class IMGLYEditorModuleDefaultImplementation: NSObject, IMGLYEditorModuleImplementation {
17
+ func openEditor(
18
+ withSettings settings: [AnyHashable: Any],
19
+ preset: String?,
20
+ metadata: [AnyHashable: Any]?,
21
+ resolve: @escaping IMGLYEditorResolveBlock,
22
+ reject: @escaping IMGLYEditorRejectBlock,
23
+ ) {
24
+ guard let settings = settings as? [String: Any],
25
+ let convertedSettings = EditorSettings.fromDictionary(settings) else {
26
+ reject(IMGLYErrorParsing, IMGLYErrorParsingMessage, nil)
27
+ return
28
+ }
29
+ // Unknown and missing presets both fall back to the design editor,
30
+ // matching `EditorPreset.fromString`.
31
+ let convertedPreset = EditorPresetParser.fromString((preset ?? "design") as NSString)
32
+ let metadata = metadata as? [String: Any]
33
+
34
+ DispatchQueue.main.async {
35
+ MainActor.assumeIsolated {
36
+ IMGLYEditorModuleSwiftAdapter.shared.openEditor(
37
+ convertedPreset,
38
+ settings: convertedSettings,
39
+ metadata: metadata,
40
+ ) { result, error in
41
+ if let result {
42
+ // Missing fields resolve as null, matching the Android module.
43
+ // The annotated binding keeps the heterogeneous literal out of the
44
+ // surrounding closure expression, which overwhelms the type checker
45
+ // ("failed to produce diagnostic" on the Xcode 26.6 toolchain).
46
+ let payload: [String: Any] = [
47
+ "artifact": result.artifact ?? NSNull(),
48
+ "scene": result.scene ?? NSNull(),
49
+ "thumbnail": result.thumbnail ?? NSNull(),
50
+ "metadata": result.metadata,
51
+ ]
52
+ resolve(payload)
53
+ } else if let error {
54
+ reject(IMGLYErrorExportFailed, IMGLYErrorExportFailedMessage, error)
55
+ } else {
56
+ resolve(NSNull())
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
@@ -1,3 +1,5 @@
1
+ import Foundation
2
+
1
3
  /// An enum containing all prebuild editor configurations.
2
4
  @objc public enum EditorPreset: Int {
3
5
  /// The apparel editor.
@@ -1,3 +1,5 @@
1
+ import Foundation
2
+
1
3
  /// A struct representing the result of an editor export.
2
4
  @objc @objcMembers public class EditorResult: NSObject {
3
5
  /// The source of the exported scene.
@@ -1,3 +1,5 @@
1
+ import Foundation
2
+
1
3
  /// A struct containing all necessary settings to setup the editor.
2
4
  @objc @objcMembers public class EditorSettings: NSObject, Codable {
3
5
  /// The license key. Pass `nil` to run the SDK in evaluation mode with a watermark.
@@ -1,3 +1,5 @@
1
+ import Foundation
2
+
1
3
  /// A struct to declare a suitable source for the editor.
2
4
  public struct Source: Codable {
3
5
  /// The source to load into the editor.
@@ -0,0 +1,114 @@
1
+ // swift-tools-version: 6.1
2
+ // 6.1 is the parse floor for the trailing-comma syntax SwiftFormat enforces (SE-0439). The
3
+ // toolchain floor comes from the IMGLYUI-swift dependency (tools 6.3.1) — do not lower this.
4
+
5
+ // Hand-authored manifest for React Native's experimental Swift Package Manager
6
+ // mode (React Native >= 0.87, `npx react-native spm`). CocoaPods
7
+ // (IMGLYEditorModule.podspec) remains the supported default integration.
8
+ //
9
+ // React Native's SPM autolinking consumes this manifest through a symlink at
10
+ // <app>/ios/build/generated/autolinking/libs/EditorReactNative -> this
11
+ // directory, so the relative package references below resolve against that
12
+ // location. This is React Native's documented contract for libraries that ship
13
+ // their own manifest (react-native/scripts/spm/__doc__/spm-header-paths-contract.md);
14
+ // the package and product must be named after the npm package
15
+ // (@imgly/editor-react-native -> EditorReactNative).
16
+ //
17
+ // The Objective-C++ bridge and the Swift implementation are separate targets
18
+ // because SwiftPM cannot compile mixed-language targets (SE-0403). The bridge
19
+ // resolves the Swift implementation at runtime (IMGLYEditorModuleSupport.h),
20
+ // so no Objective-C -> Swift compile-time dependency exists.
21
+ //
22
+ // The StarterKits directory holds tooling-provided sources and resources; do not
23
+ // hand-edit it. Its entry files are excluded from the target below because they
24
+ // reference app-side symbols that do not exist in the module.
25
+
26
+ import Foundation
27
+ import PackageDescription
28
+
29
+ // Single-source the version from package.json, like the podspec does, so
30
+ // release automation bumps the IMG.LY dependency pin together with the
31
+ // package version. React Native's autolinking references this manifest
32
+ // through a symlink, so resolve it before walking up to the package root.
33
+ let version: Version = {
34
+ let packageJSON = URL(fileURLWithPath: #filePath)
35
+ .resolvingSymlinksInPath()
36
+ .deletingLastPathComponent()
37
+ .deletingLastPathComponent()
38
+ .appendingPathComponent("package.json")
39
+ guard let data = try? Data(contentsOf: packageJSON),
40
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
41
+ let versionString = json["version"] as? String,
42
+ let version = Version(versionString) else {
43
+ fatalError("Unable to read the package version from \(packageJSON.path).")
44
+ }
45
+ return version
46
+ }()
47
+
48
+ let package = Package(
49
+ name: "EditorReactNative",
50
+ platforms: [
51
+ .iOS(.v16),
52
+ ],
53
+ products: [
54
+ .library(name: "EditorReactNative", targets: ["IMGLYEditorModule", "IMGLYEditorModuleObjC"]),
55
+ ],
56
+ dependencies: [
57
+ .package(name: "ReactNative", path: "../../../../xcframeworks"),
58
+ .package(name: "React-GeneratedCode", path: "../../../ios"),
59
+ // Pinned exactly: the module and IMGLYUI are versioned in lockstep, matching the podspec.
60
+ .package(url: "https://github.com/imgly/IMGLYUI-swift.git", exact: version),
61
+ ],
62
+ targets: [
63
+ .target(
64
+ name: "IMGLYEditorModuleObjC",
65
+ dependencies: [
66
+ .product(name: "ReactHeaders", package: "ReactNative"),
67
+ .product(name: "ReactNativeHeaders", package: "ReactNative"),
68
+ .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
69
+ .product(name: "ReactAppHeaders", package: "React-GeneratedCode"),
70
+ ],
71
+ path: "bridge",
72
+ publicHeadersPath: "include",
73
+ cxxSettings: [
74
+ // React Native's SwiftPM autolinking defines this for no target, while
75
+ // CocoaPods defines it for every one. Without it this module would
76
+ // compile its legacy bridge branch and run behind the TurboModule
77
+ // interop layer, so the integration path would decide the dispatch
78
+ // mechanism. The codegen'd spec headers the branch needs come from the
79
+ // ReactAppHeaders product above.
80
+ .define("RCT_NEW_ARCH_ENABLED", to: "1"),
81
+ .define("DEBUG", .when(configuration: .debug)),
82
+ .define("NDEBUG", .when(configuration: .release)),
83
+ ],
84
+ linkerSettings: [.linkedFramework("Foundation")],
85
+ ),
86
+ .target(
87
+ name: "IMGLYEditorModule",
88
+ dependencies: [
89
+ "IMGLYEditorModuleObjC",
90
+ // The umbrella product is the only product that vends the IMGLYEditor module.
91
+ .product(name: "IMGLYUI", package: "IMGLYUI-swift"),
92
+ ],
93
+ path: ".",
94
+ exclude: [
95
+ "bridge",
96
+ "StarterKits/Apparel/ApparelEditorStarterKit.swift",
97
+ "StarterKits/Design/DesignEditorStarterKit.swift",
98
+ "StarterKits/Photo/PhotoEditorStarterKit.swift",
99
+ "StarterKits/Postcard/PostcardEditorStarterKit.swift",
100
+ "StarterKits/Video/VideoEditorStarterKit.swift",
101
+ ],
102
+ resources: [
103
+ .copy("StarterKits/apparel-ui-b-empty.scene"),
104
+ .copy("StarterKits/design-ui-empty.scene"),
105
+ .copy("StarterKits/photo-ui-empty.png"),
106
+ .copy("StarterKits/postcard-empty.scene"),
107
+ .copy("StarterKits/video-empty.scene"),
108
+ ],
109
+ ),
110
+ ],
111
+ // The module sources are written for the Swift 5 language mode.
112
+ swiftLanguageModes: [.v5],
113
+ cxxLanguageStandard: .cxx20,
114
+ )
@@ -71,10 +71,12 @@ public extension ApparelEditorConfiguration {
71
71
  /// Loads the built-in empty apparel scene.
72
72
  static let defaultCreateScene: OnCreate.Callback = { engine in
73
73
  // highlight-starter-kit-on-create-scene
74
- let sceneURL = Bundle(for: ApparelEditorConfiguration.self).url(
75
- forResource: "apparel-ui-b-empty",
76
- withExtension: "scene",
77
- )!
74
+ #if SWIFT_PACKAGE
75
+ let bundle = Bundle.module
76
+ #else
77
+ let bundle = Bundle(for: ApparelEditorConfiguration.self)
78
+ #endif
79
+ let sceneURL = bundle.url(forResource: "apparel-ui-b-empty", withExtension: "scene")!
78
80
  try await engine.scene.load(from: sceneURL)
79
81
  // highlight-starter-kit-on-create-scene
80
82
  }
@@ -70,10 +70,12 @@ public extension DesignEditorConfiguration {
70
70
  /// Loads the built-in empty design scene.
71
71
  static let defaultCreateScene: OnCreate.Callback = { engine in
72
72
  // highlight-starter-kit-on-create-scene
73
- let sceneURL = Bundle(for: DesignEditorConfiguration.self).url(
74
- forResource: "design-ui-empty",
75
- withExtension: "scene",
76
- )!
73
+ #if SWIFT_PACKAGE
74
+ let bundle = Bundle.module
75
+ #else
76
+ let bundle = Bundle(for: DesignEditorConfiguration.self)
77
+ #endif
78
+ let sceneURL = bundle.url(forResource: "design-ui-empty", withExtension: "scene")!
77
79
  try await engine.scene.load(from: sceneURL)
78
80
  // highlight-starter-kit-on-create-scene
79
81
  }
@@ -70,7 +70,12 @@ public extension PhotoEditorConfiguration {
70
70
  /// Creates a scene from the default photo image.
71
71
  static let defaultCreateScene: OnCreate.Callback = { engine in
72
72
  // highlight-starter-kit-on-create-scene
73
- let imageURL = Bundle(for: PhotoEditorConfiguration.self).url(forResource: "photo-ui-empty", withExtension: "png")!
73
+ #if SWIFT_PACKAGE
74
+ let bundle = Bundle.module
75
+ #else
76
+ let bundle = Bundle(for: PhotoEditorConfiguration.self)
77
+ #endif
78
+ let imageURL = bundle.url(forResource: "photo-ui-empty", withExtension: "png")!
74
79
  try await engine.scene.create(fromImage: imageURL)
75
80
  // highlight-starter-kit-on-create-scene
76
81
  }
@@ -70,10 +70,12 @@ public extension PostcardEditorConfiguration {
70
70
  /// Loads the built-in empty postcard scene.
71
71
  static let defaultCreateScene: OnCreate.Callback = { engine in
72
72
  // highlight-starter-kit-on-create-scene
73
- let sceneURL = Bundle(for: PostcardEditorConfiguration.self).url(
74
- forResource: "postcard-empty",
75
- withExtension: "scene",
76
- )!
73
+ #if SWIFT_PACKAGE
74
+ let bundle = Bundle.module
75
+ #else
76
+ let bundle = Bundle(for: PostcardEditorConfiguration.self)
77
+ #endif
78
+ let sceneURL = bundle.url(forResource: "postcard-empty", withExtension: "scene")!
77
79
  try await engine.scene.load(from: sceneURL)
78
80
  // highlight-starter-kit-on-create-scene
79
81
  }
@@ -79,7 +79,12 @@ public extension VideoEditorConfiguration {
79
79
  /// Loads the built-in empty video scene.
80
80
  static let defaultCreateScene: OnCreate.Callback = { engine in
81
81
  // highlight-starter-kit-on-create-scene
82
- let sceneURL = Bundle(for: VideoEditorConfiguration.self).url(forResource: "video-empty", withExtension: "scene")!
82
+ #if SWIFT_PACKAGE
83
+ let bundle = Bundle.module
84
+ #else
85
+ let bundle = Bundle(for: VideoEditorConfiguration.self)
86
+ #endif
87
+ let sceneURL = bundle.url(forResource: "video-empty", withExtension: "scene")!
83
88
  try await engine.scene.load(from: sceneURL)
84
89
  // highlight-starter-kit-on-create-scene
85
90
  }
@@ -5,9 +5,12 @@
5
5
  // Error codes
6
6
  NSString* const IMGLYErrorExportFailed = @"E_EXPORT_FAILED";
7
7
  NSString* const IMGLYErrorParsing = @"E_PARSING";
8
+ NSString* const IMGLYErrorImplementationMissing = @"E_IMPLEMENTATION_MISSING";
8
9
 
9
10
  // Error messages
10
11
  NSString* const IMGLYErrorExportFailedMessage = @"The export of the asset failed due to: ";
11
12
  NSString* const IMGLYErrorParsingMessage = @"Unable to parse the argument(s): ";
13
+ NSString* const IMGLYErrorImplementationMissingMessage =
14
+ @"The Swift implementation of the IMGLYEditor module was not linked into the app.";
12
15
 
13
16
  @end
@@ -1,6 +1,6 @@
1
1
  #import "IMGLYEditorModule.h"
2
- #import "IMGLYEditorModule/IMGLYEditorModule-Swift.h"
3
2
  #import "IMGLYConstants.h"
3
+ #import "IMGLYEditorModuleSupport.h"
4
4
 
5
5
  @implementation IMGLYEditorModule
6
6
 
@@ -52,31 +52,12 @@ RCT_EXPORT_METHOD(openEditor : (nonnull NSDictionary*)settings source : (nullabl
52
52
  metadata:(NSDictionary*)metadata
53
53
  resolve:(RCTPromiseResolveBlock)resolve
54
54
  reject:(RCTPromiseRejectBlock)reject {
55
- EditorSettings* convertedSettings = [EditorSettings fromDictionary:settings];
56
- if (convertedSettings == nil) {
57
- reject(IMGLYErrorParsing, IMGLYErrorParsingMessage, nil);
55
+ id<IMGLYEditorModuleImplementation> implementation = IMGLYEditorModuleImplementationProvider.implementation;
56
+ if (implementation == nil) {
57
+ reject(IMGLYErrorImplementationMissing, IMGLYErrorImplementationMissingMessage, nil);
58
58
  return;
59
59
  }
60
- EditorPreset convertedPreset = [EditorPresetParser fromString:preset];
61
- dispatch_async(dispatch_get_main_queue(), ^{
62
- [[IMGLYEditorModuleSwiftAdapter shared] openEditor:convertedPreset
63
- settings:convertedSettings
64
- metadata:metadata
65
- completion:^(EditorResult* _Nullable result, NSError* _Nullable error) {
66
- if (result != nil) {
67
- resolve(@ {
68
- @"artifact" : result.artifact,
69
- @"scene" : result.scene,
70
- @"thumbnail" : result.thumbnail,
71
- @"metadata" : result.metadata
72
- });
73
- } else if (error != nil) {
74
- reject(IMGLYErrorExportFailed, IMGLYErrorExportFailedMessage, error);
75
- } else {
76
- resolve([NSNull null]);
77
- }
78
- }];
79
- });
60
+ [implementation openEditorWithSettings:settings preset:preset metadata:metadata resolve:resolve reject:reject];
80
61
  }
81
62
 
82
63
  @end
@@ -0,0 +1,23 @@
1
+ #import "IMGLYEditorModuleSupport.h"
2
+
3
+ @implementation IMGLYEditorModuleImplementationProvider
4
+
5
+ + (nullable id<IMGLYEditorModuleImplementation>)implementation {
6
+ static id<IMGLYEditorModuleImplementation> implementation;
7
+ static dispatch_once_t onceToken;
8
+ dispatch_once(&onceToken, ^{
9
+ // The Swift class is looked up by its stable Objective-C runtime name
10
+ // (`IMGLYEditorModuleImplementation.swift`) because this target must not
11
+ // reference Swift at compile time. React Native apps link with `-ObjC` on
12
+ // both the CocoaPods and the Swift Package Manager path, which keeps the
13
+ // class alive in Release and Archive builds despite the missing static
14
+ // reference.
15
+ Class implementationClass = NSClassFromString(@"IMGLYEditorModuleDefaultImplementation");
16
+ if ([implementationClass conformsToProtocol:@protocol(IMGLYEditorModuleImplementation)]) {
17
+ implementation = [[implementationClass alloc] init];
18
+ }
19
+ });
20
+ return implementation;
21
+ }
22
+
23
+ @end
@@ -5,9 +5,11 @@
5
5
  // Error codes
6
6
  extern NSString* const IMGLYErrorExportFailed;
7
7
  extern NSString* const IMGLYErrorParsing;
8
+ extern NSString* const IMGLYErrorImplementationMissing;
8
9
 
9
10
  // Error messages
10
11
  extern NSString* const IMGLYErrorExportFailedMessage;
11
12
  extern NSString* const IMGLYErrorParsingMessage;
13
+ extern NSString* const IMGLYErrorImplementationMissingMessage;
12
14
 
13
15
  @end
@@ -0,0 +1,46 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ /// Resolves a fulfilled result. Mirrors React Native's `RCTPromiseResolveBlock`
6
+ /// without importing React, so the Swift implementation stays React-free.
7
+ typedef void (^IMGLYEditorResolveBlock)(id _Nullable result);
8
+
9
+ /// Rejects with an error. Mirrors React Native's `RCTPromiseRejectBlock`.
10
+ typedef void (^IMGLYEditorRejectBlock)(NSString* code, NSString* message, NSError* _Nullable error);
11
+
12
+ /// The seam between the Objective-C++ React Native bridge and the Swift
13
+ /// implementation of the editor module.
14
+ ///
15
+ /// The bridge resolves the implementation at runtime through
16
+ /// `IMGLYEditorModuleImplementationProvider` instead of importing the generated
17
+ /// `-Swift.h` header. Swift Package Manager cannot compile mixed
18
+ /// Swift/Objective-C++ targets (SE-0403) and never emits that header, so the
19
+ /// Objective-C target must not depend on Swift at compile time.
20
+ @protocol IMGLYEditorModuleImplementation <NSObject>
21
+
22
+ /// Opens the creative editor.
23
+ /// - Parameters:
24
+ /// - settings: The raw editor settings as received from JavaScript.
25
+ /// - preset: The raw editor preset identifier as received from JavaScript.
26
+ /// - metadata: Any custom metadata as received from JavaScript.
27
+ /// - resolve: The block to invoke with the export result, or `NSNull` on cancellation.
28
+ /// - reject: The block to invoke when parsing or the export fails.
29
+ - (void)openEditorWithSettings:(NSDictionary*)settings
30
+ preset:(nullable NSString*)preset
31
+ metadata:(nullable NSDictionary*)metadata
32
+ resolve:(IMGLYEditorResolveBlock)resolve
33
+ reject:(IMGLYEditorRejectBlock)reject;
34
+
35
+ @end
36
+
37
+ /// Resolves the Swift implementation of the editor module at runtime.
38
+ @interface IMGLYEditorModuleImplementationProvider : NSObject
39
+
40
+ /// The resolved implementation, or `nil` when the Swift part of this module
41
+ /// was not linked into the app.
42
+ + (nullable id<IMGLYEditorModuleImplementation>)implementation;
43
+
44
+ @end
45
+
46
+ NS_ASSUME_NONNULL_END
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imgly/editor-react-native",
3
- "version": "1.81.1",
3
+ "version": "1.82.0-rc.0",
4
4
  "description": "CreativeEditor SDK for React Native - enable photo, video and design editing for your users on iOS and Android.",
5
5
  "react-native": "index.js",
6
6
  "source": "index.js",
@@ -96,7 +96,7 @@ export class EditorSettingsModel implements EditorSettings {
96
96
  * sources (stickers, filters, and more).
97
97
  */
98
98
  baseUri: string =
99
- 'https://cdn.img.ly/packages/imgly/cesdk-react-native/1.81.1/assets';
99
+ 'https://cdn.img.ly/packages/imgly/cesdk-react-native/1.82.0-rc.0/assets';
100
100
 
101
101
  /**
102
102
  * Unique ID tied to your application's user.
@@ -1,3 +0,0 @@
1
- //
2
- // Use this file to import your target's public headers that you would like to expose to Swift.
3
- //