@imgly/editor-react-native 1.72.3 → 1.73.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IMGLYEditorModule.podspec +23 -0
- package/android/build.gradle +9 -6
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/assets/scene/apparel.scene +1 -0
- package/android/src/main/assets/scene/design.scene +1 -0
- package/android/src/main/assets/scene/postcard.scene +1 -0
- package/android/src/main/assets/scene/video.scene +1 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/ApparelConfigurationBuilder.kt +113 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/EditorActivity.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnCreate.kt +190 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnExport.kt +82 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnLoaded.kt +88 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/CanvasMenu.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/Dock.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/InspectorBar.kt +52 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/NavigationBar.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/Overlay.kt +15 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/DesignConfigurationBuilder.kt +106 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/EditorActivity.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnCreate.kt +162 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnExport.kt +82 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnLoaded.kt +10 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/component/CanvasMenu.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/component/Dock.kt +35 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/component/InspectorBar.kt +52 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/component/NavigationBar.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/design/component/Overlay.kt +15 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/EditorActivity.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/PhotoConfigurationBuilder.kt +106 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnCreate.kt +143 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnExport.kt +82 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnLoaded.kt +49 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/CanvasMenu.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/Dock.kt +43 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/InspectorBar.kt +52 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/NavigationBar.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/Overlay.kt +15 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/EditorActivity.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/PostcardConfigurationBuilder.kt +106 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnCreate.kt +149 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnExport.kt +82 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnLoaded.kt +58 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/CanvasMenu.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/Dock.kt +243 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/InspectorBar.kt +52 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/NavigationBar.kt +76 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/Overlay.kt +15 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/postcard/ext/Engine.kt +107 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/EditorActivity.kt +37 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/VideoConfigurationBuilder.kt +135 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnCreate.kt +191 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnExport.kt +98 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnLoaded.kt +20 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/BottomPanel.kt +13 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/CanvasMenu.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/Dock.kt +71 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/InspectorBar.kt +68 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/NavigationBar.kt +57 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/Overlay.kt +421 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/CheckCircleOutline.kt +79 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/ErrorOutline.kt +92 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/IconPack.kt +14 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/model/ExportStatus.kt +39 -0
- 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 +10 -1
- package/ios/Model/EditorBuilder.swift +132 -225
- package/ios/Model/ModalEditorConfiguration.swift +40 -0
- package/ios/Model/Source.swift +8 -0
- package/ios/StarterKits/Apparel/ApparelEditorConfiguration.swift +46 -0
- package/ios/StarterKits/Apparel/ApparelEditorStarterKit.swift +30 -0
- package/ios/StarterKits/Apparel/callbacks/OnChanged+Apparel.swift +116 -0
- package/ios/StarterKits/Apparel/callbacks/OnCreate+Apparel.swift +197 -0
- package/ios/StarterKits/Apparel/callbacks/OnExport+Apparel.swift +29 -0
- package/ios/StarterKits/Apparel/components/CanvasMenu+Apparel.swift +22 -0
- package/ios/StarterKits/Apparel/components/Dock+Apparel.swift +19 -0
- package/ios/StarterKits/Apparel/components/InspectorBar+Apparel.swift +35 -0
- package/ios/StarterKits/Apparel/components/NavigationBar+Apparel.swift +26 -0
- package/ios/StarterKits/Design/DesignEditorConfiguration.swift +43 -0
- package/ios/StarterKits/Design/DesignEditorStarterKit.swift +30 -0
- package/ios/StarterKits/Design/callbacks/OnCreate+Design.swift +131 -0
- package/ios/StarterKits/Design/callbacks/OnExport+Design.swift +30 -0
- package/ios/StarterKits/Design/components/CanvasMenu+Design.swift +22 -0
- package/ios/StarterKits/Design/components/Dock+Design.swift +23 -0
- package/ios/StarterKits/Design/components/InspectorBar+Design.swift +35 -0
- package/ios/StarterKits/Design/components/NavigationBar+Design.swift +24 -0
- package/ios/StarterKits/Photo/PhotoEditorConfiguration.swift +48 -0
- package/ios/StarterKits/Photo/PhotoEditorStarterKit.swift +30 -0
- package/ios/StarterKits/Photo/callbacks/OnChanged+Photo.swift +25 -0
- package/ios/StarterKits/Photo/callbacks/OnCreate+Photo.swift +138 -0
- package/ios/StarterKits/Photo/callbacks/OnExport+Photo.swift +29 -0
- package/ios/StarterKits/Photo/callbacks/OnLoaded+Photo.swift +18 -0
- package/ios/StarterKits/Photo/components/CanvasMenu+Photo.swift +22 -0
- package/ios/StarterKits/Photo/components/Dock+Photo.swift +23 -0
- package/ios/StarterKits/Photo/components/InspectorBar+Photo.swift +39 -0
- package/ios/StarterKits/Photo/components/NavigationBar+Photo.swift +24 -0
- package/ios/StarterKits/Photo/examples/ExampleForceCrop.swift +30 -0
- package/ios/StarterKits/Postcard/PostcardEditorConfiguration.swift +45 -0
- package/ios/StarterKits/Postcard/PostcardEditorStarterKit.swift +30 -0
- package/ios/StarterKits/Postcard/callbacks/OnChanged+Postcard.swift +92 -0
- package/ios/StarterKits/Postcard/callbacks/OnCreate+Postcard.swift +127 -0
- package/ios/StarterKits/Postcard/callbacks/OnExport+Postcard.swift +29 -0
- package/ios/StarterKits/Postcard/components/CanvasMenu+Postcard.swift +22 -0
- package/ios/StarterKits/Postcard/components/Dock+Postcard.swift +34 -0
- package/ios/StarterKits/Postcard/components/DockButtons+Postcard.swift +129 -0
- package/ios/StarterKits/Postcard/components/InspectorBar+Postcard.swift +35 -0
- package/ios/StarterKits/Postcard/components/NavigationBar+Postcard.swift +38 -0
- package/ios/StarterKits/Video/VideoEditorConfiguration.swift +54 -0
- package/ios/StarterKits/Video/VideoEditorStarterKit.swift +30 -0
- package/ios/StarterKits/Video/callbacks/OnCreate+Video.swift +137 -0
- package/ios/StarterKits/Video/callbacks/OnExport+Video.swift +46 -0
- package/ios/StarterKits/Video/components/BottomPanel+Video.swift +16 -0
- package/ios/StarterKits/Video/components/CanvasMenu+Video.swift +22 -0
- package/ios/StarterKits/Video/components/Dock+Video.swift +30 -0
- package/ios/StarterKits/Video/components/InspectorBar+Video.swift +43 -0
- package/ios/StarterKits/Video/components/NavigationBar+Video.swift +32 -0
- package/ios/StarterKits/Video/examples/ExampleVideoDurationConstraints.swift +23 -0
- package/ios/StarterKits/apparel-ui-b-empty.scene +1 -0
- package/ios/StarterKits/design-ui-empty.scene +1 -0
- package/ios/StarterKits/photo-ui-empty.png +0 -0
- package/ios/StarterKits/postcard-empty.scene +1 -0
- package/ios/StarterKits/video-empty.scene +1 -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,6 +1,7 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
|
|
3
3
|
/// The iOS implementation for the `@imgly/editor-react-native` React Native module.
|
|
4
|
+
@MainActor
|
|
4
5
|
@objc(IMGLYEditorModuleSwiftAdapter) @objcMembers public class IMGLYEditorModuleSwiftAdapter: NSObject {
|
|
5
6
|
// MARK: - Typealias
|
|
6
7
|
|
|
@@ -81,7 +82,15 @@ import UIKit
|
|
|
81
82
|
.first as? UIWindowScene {
|
|
82
83
|
if let rootViewController = windowScene.windows
|
|
83
84
|
.filter(\.isKeyWindow).first?.rootViewController {
|
|
84
|
-
|
|
85
|
+
// Walk up the presentation chain to the topmost view controller.
|
|
86
|
+
// Presenting on a VC that is already presenting another VC silently
|
|
87
|
+
// no-ops in UIKit, which leaves the SDK Promise hanging forever when
|
|
88
|
+
// the host app uses react-native-screens / Expo Router / RN <Modal>.
|
|
89
|
+
var topViewController: UIViewController = rootViewController
|
|
90
|
+
while let presented = topViewController.presentedViewController {
|
|
91
|
+
topViewController = presented
|
|
92
|
+
}
|
|
93
|
+
topViewController.present(presentationController, animated: true, completion: nil)
|
|
85
94
|
}
|
|
86
95
|
}
|
|
87
96
|
}
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import CoreGraphics
|
|
2
|
+
import IMGLYEditor
|
|
3
|
+
import IMGLYEngine
|
|
4
|
+
import SwiftUI
|
|
5
|
+
|
|
6
|
+
// CE.SDK Starter Kit: Apparel Editor
|
|
7
|
+
//
|
|
8
|
+
// This starter kit provides a complete, production-ready Apparel Editor configuration
|
|
9
|
+
// with all configuration code inline and fully documented. Copy this file into your
|
|
10
|
+
// project and customize it to match your needs.
|
|
11
|
+
|
|
12
|
+
// MARK: - Configuration
|
|
13
|
+
|
|
14
|
+
public final class ApparelEditorConfiguration: EditorConfiguration {
|
|
15
|
+
// MARK: - EditorConfiguration — Settings
|
|
16
|
+
|
|
17
|
+
/// The zoom padding for the canvas.
|
|
18
|
+
override public var zoomPadding: CGFloat? { 16 }
|
|
19
|
+
|
|
20
|
+
// MARK: - EditorConfiguration — Callbacks
|
|
21
|
+
|
|
22
|
+
/// The `onCreate` handler.
|
|
23
|
+
override public var onCreate: OnCreate.Handler? { Self.defaultOnCreateHandler }
|
|
24
|
+
|
|
25
|
+
/// The `onChanged` handler.
|
|
26
|
+
override public var onChanged: OnChanged.Handler? { Self.defaultOnChangedHandler }
|
|
27
|
+
|
|
28
|
+
/// The export handler.
|
|
29
|
+
///
|
|
30
|
+
/// Default: Exports the scene as PDF and opens the system share sheet.
|
|
31
|
+
override public var onExport: OnExport.Handler? { Self.defaultOnExportHandler }
|
|
32
|
+
|
|
33
|
+
// MARK: - EditorConfiguration — UI Components
|
|
34
|
+
|
|
35
|
+
/// The navigation bar configuration.
|
|
36
|
+
override public var navigationBar: NavigationBar.Configuration? { Self.defaultNavigationBar }
|
|
37
|
+
|
|
38
|
+
/// The dock configuration.
|
|
39
|
+
override public var dock: Dock.Configuration? { Self.defaultDock }
|
|
40
|
+
|
|
41
|
+
/// The inspector bar configuration.
|
|
42
|
+
override public var inspectorBar: InspectorBar.Configuration? { Self.defaultInspectorBar }
|
|
43
|
+
|
|
44
|
+
/// The canvas menu configuration.
|
|
45
|
+
override public var canvasMenu: CanvasMenu.Configuration? { Self.defaultCanvasMenu }
|
|
46
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import SwiftUI
|
|
4
|
+
|
|
5
|
+
// MARK: - Starter Kit View
|
|
6
|
+
|
|
7
|
+
struct ApparelEditorStarterKit: View {
|
|
8
|
+
// Provide `EngineSettings` with your license and an optional userId.
|
|
9
|
+
let settings = EngineSettings(
|
|
10
|
+
license: secrets.licenseKey, // Use nil for evaluation mode with watermark
|
|
11
|
+
userID: "<your unique user id>",
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
// highlight-starter-kit-view
|
|
15
|
+
var body: some View {
|
|
16
|
+
// highlight-starter-kit-composable
|
|
17
|
+
Editor(settings)
|
|
18
|
+
.imgly.configuration {
|
|
19
|
+
ApparelEditorConfiguration()
|
|
20
|
+
}
|
|
21
|
+
// highlight-starter-kit-composable
|
|
22
|
+
}
|
|
23
|
+
// highlight-starter-kit-view
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MARK: - Preview
|
|
27
|
+
|
|
28
|
+
#Preview {
|
|
29
|
+
ApparelEditorStarterKit()
|
|
30
|
+
}
|