@imgly/editor-react-native 1.72.0 → 1.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IMGLYEditorModule.podspec +23 -0
- package/android/build.gradle +9 -6
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/kotlin/ly/img/editor/reactnative/module/activity/EditorActivity.kt +2 -0
- package/android/src/main/kotlin/ly/img/editor/reactnative/module/builder/EditorBuilder.kt +240 -282
- package/ios/Extensions/OnCreate+.swift +38 -62
- package/ios/IMGLYEditorModule.swift +1 -0
- package/ios/Model/EditorBuilder.swift +132 -225
- package/ios/Model/ModalEditorConfiguration.swift +40 -0
- package/ios/Model/Source.swift +8 -0
- package/package.json +1 -1
- package/src/NativeIMGLYEditor.ts +1 -1
- package/ios/View/ModalEditor.swift +0 -43
|
@@ -2,70 +2,46 @@ import Foundation
|
|
|
2
2
|
import IMGLYEditor
|
|
3
3
|
import IMGLYEngine
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
extension OnCreate {
|
|
7
|
-
/// Populates the editor based on a given `config`, `sourceType` and `defaultScene`.
|
|
8
|
-
/// - Parameters:
|
|
9
|
-
/// - settings: The `EditorSettings` containing the relevant editor information.
|
|
10
|
-
/// - sourceType: The `EditorSourceType` defining of which type the source is.
|
|
11
|
-
/// - defaultSource: The `URL` of the defaultScene if no `EditorSettings.source` is specified.
|
|
12
|
-
/// - Returns: An `OnCreate.Callback`.
|
|
13
|
-
@MainActor
|
|
14
|
-
public static func load(
|
|
15
|
-
_ settings: EditorSettings?,
|
|
16
|
-
_ sourceType: EditorSourceType = .scene,
|
|
17
|
-
defaultSource: URL? = nil,
|
|
18
|
-
) -> OnCreate.Callback {
|
|
19
|
-
{ engine in
|
|
20
|
-
var url: URL?
|
|
21
|
-
|
|
22
|
-
if let source = settings?.source?.source {
|
|
23
|
-
if let sourceUrl = URL(string: source), sourceUrl.scheme != nil {
|
|
24
|
-
url = sourceUrl
|
|
25
|
-
} else {
|
|
26
|
-
throw "Specified URL is not valid."
|
|
27
|
-
}
|
|
28
|
-
} else if let defaultSource {
|
|
29
|
-
url = defaultSource
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if let url {
|
|
33
|
-
switch settings?.source?.type ?? sourceType {
|
|
34
|
-
case .image:
|
|
35
|
-
try await engine.scene.create(fromImage: url)
|
|
36
|
-
case .video:
|
|
37
|
-
try await engine.scene.create(fromVideo: url)
|
|
38
|
-
default:
|
|
39
|
-
try await engine.scene.load(from: url)
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
try await OnCreate.default(engine)
|
|
43
|
-
}
|
|
5
|
+
// MARK: - React Native Source Loading
|
|
44
6
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
7
|
+
public extension OnCreate {
|
|
8
|
+
/// Loads a source from React Native editor settings.
|
|
9
|
+
///
|
|
10
|
+
/// This helper is designed to be used as the `createScene` parameter of starter kit
|
|
11
|
+
/// `defaultOnCreate` callbacks. It resolves the source URL from settings and loads it
|
|
12
|
+
/// based on the specified source type.
|
|
13
|
+
///
|
|
14
|
+
/// ## Example
|
|
15
|
+
/// ```swift
|
|
16
|
+
/// builder.onCreate { engine, _ in
|
|
17
|
+
/// if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
18
|
+
/// try await DesignEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
19
|
+
/// } else {
|
|
20
|
+
/// try await DesignEditorConfiguration.defaultOnCreate()(engine)
|
|
21
|
+
/// }
|
|
22
|
+
/// }
|
|
23
|
+
/// ```
|
|
24
|
+
///
|
|
25
|
+
/// - Parameter settings: The `EditorSettings` containing the source configuration from React Native.
|
|
26
|
+
/// - Returns: An `OnCreate.Callback` that loads the source, or `nil` if no source is specified
|
|
27
|
+
/// (allowing the starter kit's default scene to be used instead).
|
|
28
|
+
/// - Throws: If a source is specified but its URL is invalid.
|
|
29
|
+
static func loadFromSettings(
|
|
30
|
+
_ settings: EditorSettings?,
|
|
31
|
+
) throws -> Callback? {
|
|
32
|
+
guard let source = settings?.source else { return nil }
|
|
33
|
+
guard let url = source.url else {
|
|
34
|
+
throw "Specified URL is not valid: \(source.source)"
|
|
52
35
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
try await engine.addDemoAssetSources(
|
|
63
|
-
baseURL: baseURI,
|
|
64
|
-
sceneMode: engine.scene.getMode(),
|
|
65
|
-
withUploadAssetSources: true,
|
|
66
|
-
)
|
|
67
|
-
try await engine.asset.addSource(TextAssetSource(engine: engine))
|
|
68
|
-
try engine.asset.addSource(PhotoRollAssetSource(engine: engine))
|
|
36
|
+
return { engine in
|
|
37
|
+
switch source.type {
|
|
38
|
+
case .image:
|
|
39
|
+
try await engine.scene.create(fromImage: url)
|
|
40
|
+
case .video:
|
|
41
|
+
try await engine.scene.create(fromVideo: url)
|
|
42
|
+
case .scene:
|
|
43
|
+
try await engine.scene.load(from: url)
|
|
44
|
+
}
|
|
69
45
|
}
|
|
70
46
|
}
|
|
71
47
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import IMGLYPhotoEditor
|
|
4
|
-
import IMGLYPostcardEditor
|
|
5
|
-
import IMGLYVideoEditor
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
6
3
|
import SwiftUI
|
|
7
4
|
import UIKit
|
|
8
5
|
|
|
@@ -18,60 +15,156 @@ public enum EditorBuilder {
|
|
|
18
15
|
/// - metadata: The metadata.
|
|
19
16
|
/// - result: The `EditorBuilderResult` used to return a result.
|
|
20
17
|
/// - Returns: A `UIViewController`.
|
|
21
|
-
public typealias Builder = (
|
|
18
|
+
public typealias Builder = @MainActor (
|
|
22
19
|
_ settings: EditorSettings,
|
|
23
20
|
_ preset: EditorPreset?,
|
|
24
21
|
_ metadata: [String: Any]?,
|
|
25
22
|
_ result: @escaping EditorBuilderResult
|
|
26
23
|
) -> UIViewController
|
|
27
24
|
|
|
28
|
-
/// The default apparel editor.
|
|
29
|
-
public static func apparel() -> Builder {
|
|
30
|
-
{ config, _, _, result in
|
|
31
|
-
@ViewBuilder func apparelEditor(settings _: EditorSettings, result: @escaping EditorBuilderResult) -> some View {
|
|
32
|
-
ModalApparelEditor(settings: config, result: result)
|
|
33
|
-
}
|
|
34
|
-
return UIHostingController(rootView: apparelEditor(settings: config, result: result))
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/// The default postcard editor.
|
|
39
|
-
public static func postcard() -> Builder {
|
|
40
|
-
{ config, _, _, result in
|
|
41
|
-
@ViewBuilder func postcardEditor(settings _: EditorSettings, result: @escaping EditorBuilderResult) -> some View {
|
|
42
|
-
ModalPostcardEditor(settings: config, result: result)
|
|
43
|
-
}
|
|
44
|
-
return UIHostingController(rootView: postcardEditor(settings: config, result: result))
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
25
|
/// The default design editor.
|
|
49
26
|
public static func design() -> Builder {
|
|
50
27
|
{ settings, _, _, result in
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
28
|
+
UIHostingController(rootView: NavigationView {
|
|
29
|
+
Editor(engineSettings(for: settings))
|
|
30
|
+
.imgly.configuration {
|
|
31
|
+
DesignEditorConfiguration { builder in
|
|
32
|
+
builder.onCreate { engine, _ in
|
|
33
|
+
if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
34
|
+
try await DesignEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
35
|
+
} else {
|
|
36
|
+
try await DesignEditorConfiguration.defaultOnCreate()(engine)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
builder.onExport { engine, _, _ in
|
|
40
|
+
do {
|
|
41
|
+
let editorResult = try await OnExport.export(engine, .pdf)
|
|
42
|
+
result(.success(editorResult))
|
|
43
|
+
} catch {
|
|
44
|
+
result(.failure(error))
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
ModalEditorConfiguration(result: result)
|
|
49
|
+
}
|
|
50
|
+
}.navigationViewStyle(.stack))
|
|
55
51
|
}
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
/// The default photo editor.
|
|
59
55
|
public static func photo() -> Builder {
|
|
60
56
|
{ settings, _, _, result in
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
UIHostingController(rootView: NavigationView {
|
|
58
|
+
Editor(engineSettings(for: settings))
|
|
59
|
+
.imgly.configuration {
|
|
60
|
+
PhotoEditorConfiguration { builder in
|
|
61
|
+
builder.onCreate { engine, _ in
|
|
62
|
+
if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
63
|
+
try await PhotoEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
64
|
+
} else {
|
|
65
|
+
try await PhotoEditorConfiguration.defaultOnCreate()(engine)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
builder.onExport { engine, _, _ in
|
|
69
|
+
do {
|
|
70
|
+
let editorResult = try await OnExport.export(engine, .png)
|
|
71
|
+
result(.success(editorResult))
|
|
72
|
+
} catch {
|
|
73
|
+
result(.failure(error))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
ModalEditorConfiguration(result: result)
|
|
78
|
+
}
|
|
79
|
+
}.navigationViewStyle(.stack))
|
|
65
80
|
}
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
/// The default video editor.
|
|
69
84
|
public static func video() -> Builder {
|
|
70
85
|
{ settings, _, _, result in
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
UIHostingController(rootView: NavigationView {
|
|
87
|
+
Editor(engineSettings(for: settings))
|
|
88
|
+
.imgly.configuration {
|
|
89
|
+
VideoEditorConfiguration { builder in
|
|
90
|
+
builder.onCreate { engine, _ in
|
|
91
|
+
if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
92
|
+
try await VideoEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
93
|
+
} else {
|
|
94
|
+
try await VideoEditorConfiguration.defaultOnCreate()(engine)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
builder.onExport { engine, eventHandler, _ in
|
|
98
|
+
do {
|
|
99
|
+
let editorResult = try await OnExport.exportVideo(engine, eventHandler, .mp4)
|
|
100
|
+
result(.success(editorResult))
|
|
101
|
+
} catch {
|
|
102
|
+
if error is CancellationError { return }
|
|
103
|
+
result(.failure(error))
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
ModalEditorConfiguration(result: result)
|
|
108
|
+
}
|
|
109
|
+
}.navigationViewStyle(.stack))
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// The default apparel editor.
|
|
114
|
+
public static func apparel() -> Builder {
|
|
115
|
+
{ settings, _, _, result in
|
|
116
|
+
UIHostingController(rootView: NavigationView {
|
|
117
|
+
Editor(engineSettings(for: settings))
|
|
118
|
+
.imgly.configuration {
|
|
119
|
+
ApparelEditorConfiguration { builder in
|
|
120
|
+
builder.onCreate { engine, _ in
|
|
121
|
+
if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
122
|
+
try await ApparelEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
123
|
+
} else {
|
|
124
|
+
try await ApparelEditorConfiguration.defaultOnCreate()(engine)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
builder.onExport { engine, _, _ in
|
|
128
|
+
do {
|
|
129
|
+
let editorResult = try await OnExport.export(engine, .pdf)
|
|
130
|
+
result(.success(editorResult))
|
|
131
|
+
} catch {
|
|
132
|
+
result(.failure(error))
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
ModalEditorConfiguration(result: result)
|
|
137
|
+
}
|
|
138
|
+
}.navigationViewStyle(.stack))
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// The default postcard editor.
|
|
143
|
+
public static func postcard() -> Builder {
|
|
144
|
+
{ settings, _, _, result in
|
|
145
|
+
UIHostingController(rootView: NavigationView {
|
|
146
|
+
Editor(engineSettings(for: settings))
|
|
147
|
+
.imgly.configuration {
|
|
148
|
+
PostcardEditorConfiguration { builder in
|
|
149
|
+
builder.onCreate { engine, _ in
|
|
150
|
+
if let createScene = try OnCreate.loadFromSettings(settings) {
|
|
151
|
+
try await PostcardEditorConfiguration.defaultOnCreate(createScene: createScene)(engine)
|
|
152
|
+
} else {
|
|
153
|
+
try await PostcardEditorConfiguration.defaultOnCreate()(engine)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
builder.onExport { engine, _, _ in
|
|
157
|
+
do {
|
|
158
|
+
let editorResult = try await OnExport.export(engine, .pdf)
|
|
159
|
+
result(.success(editorResult))
|
|
160
|
+
} catch {
|
|
161
|
+
result(.failure(error))
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
ModalEditorConfiguration(result: result)
|
|
166
|
+
}
|
|
167
|
+
}.navigationViewStyle(.stack))
|
|
75
168
|
}
|
|
76
169
|
}
|
|
77
170
|
|
|
@@ -91,14 +184,9 @@ public enum EditorBuilder {
|
|
|
91
184
|
}
|
|
92
185
|
}
|
|
93
186
|
|
|
94
|
-
// MARK: -
|
|
187
|
+
// MARK: - Helpers
|
|
95
188
|
|
|
96
|
-
/// An extension for the editor views.
|
|
97
189
|
extension EditorBuilder {
|
|
98
|
-
/// The message to send if the native error has been dismissed after throwing an error.
|
|
99
|
-
private static let exportFailedMessage =
|
|
100
|
-
"Failed to initialize the editor. Please verify that the loaded license is correct."
|
|
101
|
-
|
|
102
190
|
/// Generates `EngineSettings` based on an `EditorSettings`.
|
|
103
191
|
/// - Parameter settings: The `EditorSettings`.
|
|
104
192
|
/// - Returns: The derived `EngineSettings`.
|
|
@@ -109,185 +197,4 @@ extension EditorBuilder {
|
|
|
109
197
|
EngineSettings(license: settings.license, userID: settings.userId)
|
|
110
198
|
}
|
|
111
199
|
}
|
|
112
|
-
|
|
113
|
-
/// A modal apparel editor handling native errors.
|
|
114
|
-
private struct ModalApparelEditor: View {
|
|
115
|
-
@Environment(\.dismiss) private var dismiss
|
|
116
|
-
private let settings: EditorSettings
|
|
117
|
-
private let result: EditorBuilderResult
|
|
118
|
-
|
|
119
|
-
init(settings: EditorSettings, result: @escaping EditorBuilderResult) {
|
|
120
|
-
self.settings = settings
|
|
121
|
-
self.result = result
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
var body: some View {
|
|
125
|
-
ModalEditor {
|
|
126
|
-
ApparelEditor(engineSettings(for: settings))
|
|
127
|
-
.imgly.onCreate { engine in
|
|
128
|
-
try await OnCreate.load(settings, defaultSource: ApparelEditor.defaultScene)(engine)
|
|
129
|
-
}
|
|
130
|
-
.imgly.onExport { engine, _ in
|
|
131
|
-
do {
|
|
132
|
-
let editorResult = try await OnExport.export(engine, .pdf)
|
|
133
|
-
result(.success(editorResult))
|
|
134
|
-
} catch {
|
|
135
|
-
result(.failure(error))
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
} onDismiss: { cancelled in
|
|
139
|
-
if cancelled {
|
|
140
|
-
result(.success(nil))
|
|
141
|
-
dismiss()
|
|
142
|
-
} else {
|
|
143
|
-
result(.failure(exportFailedMessage))
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/// A modal postcard editor handling native errors.
|
|
150
|
-
private struct ModalPostcardEditor: View {
|
|
151
|
-
@Environment(\.dismiss) private var dismiss
|
|
152
|
-
private let settings: EditorSettings
|
|
153
|
-
private let result: EditorBuilderResult
|
|
154
|
-
|
|
155
|
-
init(settings: EditorSettings, result: @escaping EditorBuilderResult) {
|
|
156
|
-
self.settings = settings
|
|
157
|
-
self.result = result
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
var body: some View {
|
|
161
|
-
ModalEditor {
|
|
162
|
-
PostcardEditor(engineSettings(for: settings))
|
|
163
|
-
.imgly.onCreate { engine in
|
|
164
|
-
try await OnCreate.load(settings, defaultSource: PostcardEditor.defaultScene)(engine)
|
|
165
|
-
}
|
|
166
|
-
.imgly.onExport { engine, _ in
|
|
167
|
-
do {
|
|
168
|
-
let editorResult = try await OnExport.export(engine, .pdf)
|
|
169
|
-
result(.success(editorResult))
|
|
170
|
-
} catch {
|
|
171
|
-
result(.failure(error))
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
} onDismiss: { cancelled in
|
|
175
|
-
if cancelled {
|
|
176
|
-
result(.success(nil))
|
|
177
|
-
dismiss()
|
|
178
|
-
} else {
|
|
179
|
-
result(.failure(exportFailedMessage))
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/// A modal design editor handling native errors.
|
|
186
|
-
private struct ModalDesignEditor: View {
|
|
187
|
-
@Environment(\.dismiss) private var dismiss
|
|
188
|
-
private let settings: EditorSettings
|
|
189
|
-
private let result: EditorBuilderResult
|
|
190
|
-
|
|
191
|
-
init(settings: EditorSettings, result: @escaping EditorBuilderResult) {
|
|
192
|
-
self.settings = settings
|
|
193
|
-
self.result = result
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
var body: some View {
|
|
197
|
-
ModalEditor {
|
|
198
|
-
DesignEditor(engineSettings(for: settings))
|
|
199
|
-
.imgly.onCreate { engine in
|
|
200
|
-
try await OnCreate.load(settings, defaultSource: DesignEditor.defaultScene)(engine)
|
|
201
|
-
}
|
|
202
|
-
.imgly.onExport { engine, _ in
|
|
203
|
-
do {
|
|
204
|
-
let editorResult = try await OnExport.export(engine, .pdf)
|
|
205
|
-
result(.success(editorResult))
|
|
206
|
-
} catch {
|
|
207
|
-
result(.failure(error))
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
} onDismiss: { cancelled in
|
|
211
|
-
if cancelled {
|
|
212
|
-
result(.success(nil))
|
|
213
|
-
dismiss()
|
|
214
|
-
} else {
|
|
215
|
-
result(.failure(exportFailedMessage))
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/// A modal photo editor handling native errors.
|
|
222
|
-
private struct ModalPhotoEditor: View {
|
|
223
|
-
@Environment(\.dismiss) private var dismiss
|
|
224
|
-
private let settings: EditorSettings
|
|
225
|
-
private let result: EditorBuilderResult
|
|
226
|
-
|
|
227
|
-
init(settings: EditorSettings, result: @escaping EditorBuilderResult) {
|
|
228
|
-
self.settings = settings
|
|
229
|
-
self.result = result
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
var body: some View {
|
|
233
|
-
ModalEditor {
|
|
234
|
-
PhotoEditor(engineSettings(for: settings))
|
|
235
|
-
.imgly.onCreate { engine in
|
|
236
|
-
try await OnCreate
|
|
237
|
-
.load(settings, settings.source?.type ?? .image, defaultSource: PhotoEditor.defaultImage)(engine)
|
|
238
|
-
}
|
|
239
|
-
.imgly.onExport { engine, _ in
|
|
240
|
-
do {
|
|
241
|
-
let editorResult = try await OnExport.export(engine, .png)
|
|
242
|
-
result(.success(editorResult))
|
|
243
|
-
} catch {
|
|
244
|
-
result(.failure(error))
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
} onDismiss: { cancelled in
|
|
248
|
-
if cancelled {
|
|
249
|
-
result(.success(nil))
|
|
250
|
-
dismiss()
|
|
251
|
-
} else {
|
|
252
|
-
result(.failure(exportFailedMessage))
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/// A modal video editor handling native errors.
|
|
259
|
-
private struct ModalVideoEditor: View {
|
|
260
|
-
@Environment(\.dismiss) private var dismiss
|
|
261
|
-
private let settings: EditorSettings
|
|
262
|
-
private let result: EditorBuilderResult
|
|
263
|
-
|
|
264
|
-
init(settings: EditorSettings, result: @escaping EditorBuilderResult) {
|
|
265
|
-
self.settings = settings
|
|
266
|
-
self.result = result
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
var body: some View {
|
|
270
|
-
ModalEditor {
|
|
271
|
-
VideoEditor(engineSettings(for: settings))
|
|
272
|
-
.imgly.onCreate { engine in
|
|
273
|
-
try await OnCreate.load(settings, defaultSource: VideoEditor.defaultScene)(engine)
|
|
274
|
-
}
|
|
275
|
-
.imgly.onExport { engine, eventHandler in
|
|
276
|
-
do {
|
|
277
|
-
let editorResult = try await OnExport.exportVideo(engine, eventHandler, .mp4)
|
|
278
|
-
result(.success(editorResult))
|
|
279
|
-
} catch {
|
|
280
|
-
result(.failure(error))
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
} onDismiss: { cancelled in
|
|
284
|
-
if cancelled {
|
|
285
|
-
result(.success(nil))
|
|
286
|
-
dismiss()
|
|
287
|
-
} else {
|
|
288
|
-
result(.failure(exportFailedMessage))
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
200
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
/// An editor configuration that handles modal dismiss behavior for React Native.
|
|
5
|
+
public final class ModalEditorConfiguration: EditorConfiguration {
|
|
6
|
+
private let result: EditorBuilder.EditorBuilderResult
|
|
7
|
+
|
|
8
|
+
/// Creates a modal editor configuration.
|
|
9
|
+
/// - Parameters:
|
|
10
|
+
/// - result: The closure used to return a result to React Native.
|
|
11
|
+
/// - customize: An optional closure to further customize the configuration.
|
|
12
|
+
public init(
|
|
13
|
+
result: @escaping EditorBuilder.EditorBuilderResult,
|
|
14
|
+
customize: (_ builder: Builder) -> Void = { _ in },
|
|
15
|
+
) {
|
|
16
|
+
self.result = result
|
|
17
|
+
super.init(customize)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override public var navigationBar: NavigationBar.Configuration? {
|
|
21
|
+
NavigationBar.Configuration { navBuilder in
|
|
22
|
+
navBuilder.modify { [result] _, items in
|
|
23
|
+
items.replace(id: NavigationBar.Buttons.ID.closeEditor) {
|
|
24
|
+
NavigationBar.Buttons.closeEditor(
|
|
25
|
+
action: { _ in result(.success(nil)) },
|
|
26
|
+
label: { _ in SwiftUI.Label("Home", systemImage: "house") },
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override public var onError: OnError.Handler? {
|
|
34
|
+
{ [result] error, eventHandler, _ in
|
|
35
|
+
eventHandler.send(.showErrorAlert(error) {
|
|
36
|
+
result(.failure("Failed to initialize the editor. Please verify that the loaded license is correct."))
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
package/ios/Model/Source.swift
CHANGED
|
@@ -5,4 +5,12 @@ public struct Source: Codable {
|
|
|
5
5
|
|
|
6
6
|
/// The source type.
|
|
7
7
|
public var type: EditorSourceType
|
|
8
|
+
|
|
9
|
+
/// The resolved source URL, or `nil` if the source string is not a valid URL with a scheme.
|
|
10
|
+
public var url: URL? {
|
|
11
|
+
guard let url = URL(string: source), url.scheme != nil else {
|
|
12
|
+
return nil
|
|
13
|
+
}
|
|
14
|
+
return url
|
|
15
|
+
}
|
|
8
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imgly/editor-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.73.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",
|
package/src/NativeIMGLYEditor.ts
CHANGED
|
@@ -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.
|
|
99
|
+
'https://cdn.img.ly/packages/imgly/cesdk-react-native/1.73.0/assets';
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Unique ID tied to your application's user.
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import IMGLYEditor
|
|
2
|
-
import SwiftUI
|
|
3
|
-
|
|
4
|
-
/// The `ModalEditor` contains an editor and adds the top navigation bar.
|
|
5
|
-
public struct ModalEditor<Editor: View, Label: View>: View {
|
|
6
|
-
@ViewBuilder private let editor: () -> Editor
|
|
7
|
-
@ViewBuilder private let dismissLabel: () -> Label
|
|
8
|
-
private let onDismiss: (_ cancelled: Bool) -> Void
|
|
9
|
-
|
|
10
|
-
/// Initializes a new `ModalEditor`.
|
|
11
|
-
/// - Parameters:
|
|
12
|
-
/// - editor: The editor that is contained.
|
|
13
|
-
/// - dismissLabel: The label used for the dismiss action.
|
|
14
|
-
/// - onDismiss: The closure called when the editor is dismissed.
|
|
15
|
-
/// - cancelled: Indicates whether the editor has been dismissed by the user.
|
|
16
|
-
/// If `false`, the editor has been closed due to an error.
|
|
17
|
-
public init(@ViewBuilder editor: @escaping () -> Editor,
|
|
18
|
-
@ViewBuilder dismissLabel: @escaping () -> Label = { SwiftUI.Label("Home", systemImage: "house") },
|
|
19
|
-
onDismiss: @escaping (_ cancelled: Bool) -> Void) {
|
|
20
|
-
self.editor = editor
|
|
21
|
-
self.dismissLabel = dismissLabel
|
|
22
|
-
self.onDismiss = onDismiss
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// The body.
|
|
26
|
-
public var body: some View {
|
|
27
|
-
NavigationView {
|
|
28
|
-
editor()
|
|
29
|
-
.imgly.modifyNavigationBarItems { _, items in
|
|
30
|
-
items.replace(id: NavigationBar.Buttons.ID.closeEditor) {
|
|
31
|
-
NavigationBar.Buttons.closeEditor(
|
|
32
|
-
action: { _ in onDismiss(true) },
|
|
33
|
-
label: { _ in dismissLabel() },
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
.imgly.onError { error, eventHandler in
|
|
38
|
-
eventHandler.send(.showErrorAlert(error) { onDismiss(false) })
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
.navigationViewStyle(.stack)
|
|
42
|
-
}
|
|
43
|
-
}
|