@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
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import UniformTypeIdentifiers
|
|
4
|
+
|
|
5
|
+
// MARK: - Default OnExport
|
|
6
|
+
|
|
7
|
+
extension DesignEditorConfiguration {
|
|
8
|
+
/// The default export handler.
|
|
9
|
+
///
|
|
10
|
+
/// Exports the scene as PDF and opens the system share sheet.
|
|
11
|
+
static var defaultOnExportHandler: OnExport.Handler {
|
|
12
|
+
{ engine, eventHandler, existing in
|
|
13
|
+
// highlight-starter-kit-on-export
|
|
14
|
+
try await existing()
|
|
15
|
+
guard let scene = try engine.scene.get() else {
|
|
16
|
+
throw EditorError("No scene was found.")
|
|
17
|
+
}
|
|
18
|
+
let data = try await engine.block.export(scene, mimeType: .pdf) { engine in
|
|
19
|
+
try engine.scene.getPages().forEach {
|
|
20
|
+
try engine.block.setScopeEnabled($0, key: "layer/visibility", enabled: true)
|
|
21
|
+
try engine.block.setVisible($0, visible: true)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
let url = FileManager.default.temporaryDirectory.appendingPathComponent("Export", conformingTo: .pdf)
|
|
25
|
+
try data.write(to: url, options: [.atomic])
|
|
26
|
+
eventHandler.send(.shareFile(url))
|
|
27
|
+
// highlight-starter-kit-on-export
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Canvas Menu
|
|
4
|
+
|
|
5
|
+
extension DesignEditorConfiguration {
|
|
6
|
+
/// The default canvas menu configuration.
|
|
7
|
+
static var defaultCanvasMenu: CanvasMenu.Configuration {
|
|
8
|
+
CanvasMenu.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-canvas-menu
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
CanvasMenu.Buttons.selectGroup()
|
|
12
|
+
CanvasMenu.Divider()
|
|
13
|
+
CanvasMenu.Buttons.bringForward()
|
|
14
|
+
CanvasMenu.Buttons.sendBackward()
|
|
15
|
+
CanvasMenu.Divider()
|
|
16
|
+
CanvasMenu.Buttons.duplicate()
|
|
17
|
+
CanvasMenu.Buttons.delete()
|
|
18
|
+
}
|
|
19
|
+
// highlight-starter-kit-canvas-menu
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Dock
|
|
4
|
+
|
|
5
|
+
extension DesignEditorConfiguration {
|
|
6
|
+
/// The default dock configuration.
|
|
7
|
+
static var defaultDock: Dock.Configuration {
|
|
8
|
+
Dock.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-dock
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
Dock.Buttons.elementsLibrary()
|
|
12
|
+
Dock.Buttons.photoRoll()
|
|
13
|
+
Dock.Buttons.systemCamera()
|
|
14
|
+
Dock.Buttons.imagesLibrary()
|
|
15
|
+
Dock.Buttons.textLibrary()
|
|
16
|
+
Dock.Buttons.shapesLibrary()
|
|
17
|
+
Dock.Buttons.stickersLibrary()
|
|
18
|
+
Dock.Buttons.resize()
|
|
19
|
+
}
|
|
20
|
+
// highlight-starter-kit-dock
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Inspector Bar
|
|
4
|
+
|
|
5
|
+
extension DesignEditorConfiguration {
|
|
6
|
+
/// The default inspector bar configuration.
|
|
7
|
+
static var defaultInspectorBar: InspectorBar.Configuration {
|
|
8
|
+
InspectorBar.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-inspector-bar
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
InspectorBar.Buttons.replace()
|
|
12
|
+
|
|
13
|
+
InspectorBar.Buttons.editText()
|
|
14
|
+
InspectorBar.Buttons.formatText()
|
|
15
|
+
InspectorBar.Buttons.fillStroke()
|
|
16
|
+
InspectorBar.Buttons.textBackground()
|
|
17
|
+
InspectorBar.Buttons.crop()
|
|
18
|
+
|
|
19
|
+
InspectorBar.Buttons.adjustments()
|
|
20
|
+
InspectorBar.Buttons.filter()
|
|
21
|
+
InspectorBar.Buttons.effect()
|
|
22
|
+
InspectorBar.Buttons.blur()
|
|
23
|
+
InspectorBar.Buttons.shape()
|
|
24
|
+
|
|
25
|
+
InspectorBar.Buttons.selectGroup()
|
|
26
|
+
InspectorBar.Buttons.enterGroup()
|
|
27
|
+
|
|
28
|
+
InspectorBar.Buttons.layer()
|
|
29
|
+
InspectorBar.Buttons.duplicate()
|
|
30
|
+
InspectorBar.Buttons.delete()
|
|
31
|
+
}
|
|
32
|
+
// highlight-starter-kit-inspector-bar
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Navigation Bar
|
|
4
|
+
|
|
5
|
+
extension DesignEditorConfiguration {
|
|
6
|
+
/// The default navigation bar configuration.
|
|
7
|
+
static var defaultNavigationBar: NavigationBar.Configuration {
|
|
8
|
+
NavigationBar.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-navigation-bar
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
NavigationBar.ItemGroup(placement: .topBarLeading) {
|
|
12
|
+
NavigationBar.Buttons.closeEditor()
|
|
13
|
+
}
|
|
14
|
+
NavigationBar.ItemGroup(placement: .topBarTrailing) {
|
|
15
|
+
NavigationBar.Buttons.undo()
|
|
16
|
+
NavigationBar.Buttons.redo()
|
|
17
|
+
NavigationBar.Buttons.togglePagesMode()
|
|
18
|
+
NavigationBar.Buttons.export()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// highlight-starter-kit-navigation-bar
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import SwiftUI
|
|
4
|
+
|
|
5
|
+
// CE.SDK Starter Kit: Photo Editor
|
|
6
|
+
//
|
|
7
|
+
// This starter kit provides a complete, production-ready Photo Editor configuration
|
|
8
|
+
// with all configuration code inline and fully documented. Copy this file into your
|
|
9
|
+
// project and customize it to match your needs.
|
|
10
|
+
|
|
11
|
+
// MARK: - Configuration
|
|
12
|
+
|
|
13
|
+
public final class PhotoEditorConfiguration: EditorConfiguration {
|
|
14
|
+
// MARK: - EditorConfiguration — Settings
|
|
15
|
+
|
|
16
|
+
/// The zoom padding for the canvas.
|
|
17
|
+
override public var zoomPadding: CGFloat? { 0 }
|
|
18
|
+
|
|
19
|
+
// MARK: - EditorConfiguration — Callbacks
|
|
20
|
+
|
|
21
|
+
/// The `onCreate` handler.
|
|
22
|
+
override public var onCreate: OnCreate.Handler? { Self.defaultOnCreateHandler }
|
|
23
|
+
|
|
24
|
+
/// The `onLoaded` handler.
|
|
25
|
+
override public var onLoaded: OnLoaded.Handler? { Self.defaultOnLoadedHandler }
|
|
26
|
+
|
|
27
|
+
/// The `onChanged` handler.
|
|
28
|
+
override public var onChanged: OnChanged.Handler? { Self.defaultOnChangedHandler }
|
|
29
|
+
|
|
30
|
+
/// The export handler.
|
|
31
|
+
///
|
|
32
|
+
/// Default: Exports the scene as PNG and opens the system share sheet.
|
|
33
|
+
override public var onExport: OnExport.Handler? { Self.defaultOnExportHandler }
|
|
34
|
+
|
|
35
|
+
// MARK: - EditorConfiguration — UI Components
|
|
36
|
+
|
|
37
|
+
/// The navigation bar configuration.
|
|
38
|
+
override public var navigationBar: NavigationBar.Configuration? { Self.defaultNavigationBar }
|
|
39
|
+
|
|
40
|
+
/// The dock configuration.
|
|
41
|
+
override public var dock: Dock.Configuration? { Self.defaultDock }
|
|
42
|
+
|
|
43
|
+
/// The inspector bar configuration.
|
|
44
|
+
override public var inspectorBar: InspectorBar.Configuration? { Self.defaultInspectorBar }
|
|
45
|
+
|
|
46
|
+
/// The canvas menu configuration.
|
|
47
|
+
override public var canvasMenu: CanvasMenu.Configuration? { Self.defaultCanvasMenu }
|
|
48
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import SwiftUI
|
|
4
|
+
|
|
5
|
+
// MARK: - Starter Kit View
|
|
6
|
+
|
|
7
|
+
struct PhotoEditorStarterKit: 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
|
+
PhotoEditorConfiguration()
|
|
20
|
+
}
|
|
21
|
+
// highlight-starter-kit-composable
|
|
22
|
+
}
|
|
23
|
+
// highlight-starter-kit-view
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MARK: - Preview
|
|
27
|
+
|
|
28
|
+
#Preview {
|
|
29
|
+
PhotoEditorStarterKit()
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
|
|
4
|
+
// MARK: - Default OnChanged
|
|
5
|
+
|
|
6
|
+
extension PhotoEditorConfiguration {
|
|
7
|
+
/// The default `onChanged` handler.
|
|
8
|
+
static var defaultOnChangedHandler: OnChanged.Handler {
|
|
9
|
+
{ update, context, _ in
|
|
10
|
+
switch update {
|
|
11
|
+
case let .editMode(oldValue, newValue):
|
|
12
|
+
guard oldValue != newValue else { return }
|
|
13
|
+
|
|
14
|
+
let isCrop = newValue == .crop
|
|
15
|
+
if let selection = context.engine.block.findAllSelected().first,
|
|
16
|
+
let type = try? context.engine.block.getType(selection), type == DesignBlockType.page.rawValue {
|
|
17
|
+
context.eventHandler.send(.setExtraCanvasInsets(isCrop ? 24 : 0))
|
|
18
|
+
}
|
|
19
|
+
try context.engine.editor.setSettingBool("page/allowResizeInteraction", value: isCrop)
|
|
20
|
+
default:
|
|
21
|
+
try OnChanged.default(update, context)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import IMGLYEditor
|
|
3
|
+
import IMGLYEngine
|
|
4
|
+
|
|
5
|
+
// MARK: - Default OnCreate
|
|
6
|
+
|
|
7
|
+
public extension PhotoEditorConfiguration {
|
|
8
|
+
/// The default `onCreate` handler.
|
|
9
|
+
internal static var defaultOnCreateHandler: OnCreate.Handler {
|
|
10
|
+
{ engine, _ in
|
|
11
|
+
try await defaultOnCreate()(engine)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// Default photo editor specific `OnCreate.Callback` implementation with solution specific settings, scene
|
|
16
|
+
/// and editor creation setup.
|
|
17
|
+
/// - Parameters:
|
|
18
|
+
/// - preCreateScene: Callback to do any pre scene loading tasks such as applying settings.
|
|
19
|
+
/// Defaults to `PhotoEditorConfiguration.defaultPreCreateScene`.
|
|
20
|
+
/// - createScene: Callback to load/create the scene and load asset sources. Defaults to
|
|
21
|
+
/// `PhotoEditorConfiguration.defaultCreateScene`.
|
|
22
|
+
/// - loadAssetSources: Callback to load any asset sources. Defaults to
|
|
23
|
+
/// `PhotoEditorConfiguration.defaultLoadAssetSources`.
|
|
24
|
+
/// - postCreateScene: Callback to do any post scene loading tasks. Defaults to
|
|
25
|
+
/// `PhotoEditorConfiguration.defaultPostCreateScene`.
|
|
26
|
+
/// - Returns: A composed `OnCreate.Callback`that sequentially executes all three initialization phases.
|
|
27
|
+
static func defaultOnCreate(
|
|
28
|
+
preCreateScene: @escaping OnCreate.Callback = defaultPreCreateScene,
|
|
29
|
+
createScene: @escaping OnCreate.Callback = defaultCreateScene,
|
|
30
|
+
loadAssetSources: @escaping OnCreate.Callback = defaultLoadAssetSources,
|
|
31
|
+
postCreateScene: @escaping OnCreate.Callback = defaultPostCreateScene,
|
|
32
|
+
) -> OnCreate.Callback {
|
|
33
|
+
{ engine in
|
|
34
|
+
try await preCreateScene(engine)
|
|
35
|
+
try await createScene(engine)
|
|
36
|
+
try await loadAssetSources(engine)
|
|
37
|
+
try await postCreateScene(engine)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Configures engine settings before scene loading.
|
|
42
|
+
///
|
|
43
|
+
/// Sets editor role, touch gestures, camera clamping, and global scopes.
|
|
44
|
+
static let defaultPreCreateScene: OnCreate.Callback = { engine in
|
|
45
|
+
try engine.editor.setRole("Adopter")
|
|
46
|
+
try engine.editor.setSettingEnum("camera/clamping/overshootMode", value: "Center")
|
|
47
|
+
|
|
48
|
+
let highlightColor: IMGLYEngine.Color = try engine.editor.getSettingColor("highlightColor")
|
|
49
|
+
try engine.editor.setSettingColor("placeholderHighlightColor", color: highlightColor)
|
|
50
|
+
|
|
51
|
+
try engine.editor.setSettingBool("touch/dragStartCanSelect", value: false)
|
|
52
|
+
try engine.editor.setSettingEnum("touch/pinchAction", value: "Zoom")
|
|
53
|
+
try engine.editor.setSettingEnum("touch/rotateAction", value: "None")
|
|
54
|
+
|
|
55
|
+
try ([
|
|
56
|
+
"appearance/adjustments", "appearance/filter", "appearance/effect",
|
|
57
|
+
"appearance/blur", "appearance/shadow",
|
|
58
|
+
"editor/select",
|
|
59
|
+
"fill/change", "fill/changeType",
|
|
60
|
+
"layer/crop", "layer/move", "layer/resize", "layer/rotate", "layer/flip",
|
|
61
|
+
"layer/opacity", "layer/blendMode", "layer/visibility", "layer/clipping",
|
|
62
|
+
"lifecycle/destroy", "lifecycle/duplicate",
|
|
63
|
+
"stroke/change", "shape/change",
|
|
64
|
+
"text/edit", "text/character",
|
|
65
|
+
]).forEach { scope in
|
|
66
|
+
try engine.editor.setGlobalScope(key: scope, value: .defer)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Creates a scene from the default photo image.
|
|
71
|
+
static let defaultCreateScene: OnCreate.Callback = { engine in
|
|
72
|
+
// highlight-starter-kit-on-create-scene
|
|
73
|
+
let imageURL = Bundle(for: PhotoEditorConfiguration.self).url(forResource: "photo-ui-empty", withExtension: "png")!
|
|
74
|
+
try await engine.scene.create(fromImage: imageURL)
|
|
75
|
+
// highlight-starter-kit-on-create-scene
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/// Registers all default and demo asset sources, plus text and photo roll sources.
|
|
79
|
+
static let defaultLoadAssetSources: OnCreate.Callback = { engine in
|
|
80
|
+
// highlight-starter-kit-on-load-asset-sources
|
|
81
|
+
let assetSources: [String: URL] = [
|
|
82
|
+
Engine.DefaultAssetSource.sticker.rawValue: Engine.assetBaseURL,
|
|
83
|
+
Engine.DefaultAssetSource.vectorPath.rawValue: Engine.assetBaseURL,
|
|
84
|
+
Engine.DefaultAssetSource.filterLut.rawValue: Engine.assetBaseURL,
|
|
85
|
+
Engine.DefaultAssetSource.filterDuotone.rawValue: Engine.assetBaseURL,
|
|
86
|
+
Engine.DefaultAssetSource.colorsDefaultPalette.rawValue: Engine.assetBaseURL,
|
|
87
|
+
Engine.DefaultAssetSource.effect.rawValue: Engine.assetBaseURL,
|
|
88
|
+
Engine.DefaultAssetSource.blur.rawValue: Engine.assetBaseURL,
|
|
89
|
+
Engine.DefaultAssetSource.typeface.rawValue: Engine.assetBaseURL,
|
|
90
|
+
Engine.DefaultAssetSource.cropPresets.rawValue: Engine.assetBaseURL,
|
|
91
|
+
Engine.DefaultAssetSource.pagePresets.rawValue: Engine.assetBaseURL,
|
|
92
|
+
|
|
93
|
+
Engine.DemoAssetSource.textComponents.rawValue: Engine.assetBaseURL,
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
try await withThrowingTaskGroup(of: Void.self) { group in
|
|
97
|
+
for assetSource in assetSources {
|
|
98
|
+
group.addTask {
|
|
99
|
+
try await engine.populateAssetSource(id: assetSource.key, baseURL: assetSource.value)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
try await group.waitForAll()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try await engine.asset.addSource(TextAssetSource(engine: engine))
|
|
106
|
+
try engine.asset.addSource(PhotoRollAssetSource(engine: engine))
|
|
107
|
+
// highlight-starter-kit-on-load-asset-sources
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Configures photo-specific page and crop behavior.
|
|
111
|
+
static let defaultPostCreateScene: OnCreate.Callback = { engine in
|
|
112
|
+
let page = try getSinglePage(engine)
|
|
113
|
+
|
|
114
|
+
try engine.editor.setHighlightingEnabled(page, enabled: false)
|
|
115
|
+
try engine.block.setScopeEnabled(page, key: "layer/move", enabled: false)
|
|
116
|
+
|
|
117
|
+
try engine.editor.setSettingBool("page/highlightWhenCropping", value: true)
|
|
118
|
+
try engine.editor.setSettingBool("page/allowMoveInteraction", value: true)
|
|
119
|
+
try engine.editor.setSettingBool("page/selectWhenNoBlocksSelected", value: true)
|
|
120
|
+
try engine.editor.setSettingBool("doubleClickToCropEnabled", value: false)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// MARK: - Helpers
|
|
124
|
+
|
|
125
|
+
/// Gets the single page with an image fill from the scene.
|
|
126
|
+
internal static func getSinglePage(_ engine: Engine, withImageFill: Bool = true) throws -> DesignBlockID {
|
|
127
|
+
let pages = try engine.scene.getPages()
|
|
128
|
+
guard let page = pages.first, pages.count == 1 else {
|
|
129
|
+
throw EditorError("A single page is required for this operation.")
|
|
130
|
+
}
|
|
131
|
+
if withImageFill {
|
|
132
|
+
guard try engine.block.getType(engine.block.getFill(page)) == FillType.image.rawValue else {
|
|
133
|
+
throw EditorError("A single page with an image fill is required for this operation.")
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return page
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import UniformTypeIdentifiers
|
|
4
|
+
|
|
5
|
+
// MARK: - Default OnExport
|
|
6
|
+
|
|
7
|
+
extension PhotoEditorConfiguration {
|
|
8
|
+
/// The default export handler.
|
|
9
|
+
///
|
|
10
|
+
/// Exports the scene as PNG and opens the system share sheet.
|
|
11
|
+
static var defaultOnExportHandler: OnExport.Handler {
|
|
12
|
+
{ engine, eventHandler, _ in
|
|
13
|
+
// highlight-starter-kit-on-export
|
|
14
|
+
guard let scene = try engine.scene.get() else {
|
|
15
|
+
throw EditorError("No scene was found.")
|
|
16
|
+
}
|
|
17
|
+
let data = try await engine.block.export(scene, mimeType: .png) { engine in
|
|
18
|
+
try engine.scene.getPages().forEach {
|
|
19
|
+
try engine.block.setScopeEnabled($0, key: "layer/visibility", enabled: true)
|
|
20
|
+
try engine.block.setVisible($0, visible: true)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
let url = FileManager.default.temporaryDirectory.appendingPathComponent("Export", conformingTo: .png)
|
|
24
|
+
try data.write(to: url, options: [.atomic])
|
|
25
|
+
eventHandler.send(.shareFile(url))
|
|
26
|
+
// highlight-starter-kit-on-export
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
|
|
4
|
+
// MARK: - Default OnLoaded
|
|
5
|
+
|
|
6
|
+
extension PhotoEditorConfiguration {
|
|
7
|
+
/// The default `onLoaded` handler.
|
|
8
|
+
static var defaultOnLoadedHandler: OnLoaded.Handler {
|
|
9
|
+
{ context, existing in
|
|
10
|
+
try await existing()
|
|
11
|
+
for try await _ in context.engine.editor.onHistoryUpdated {
|
|
12
|
+
let editMode = context.engine.editor.getEditMode()
|
|
13
|
+
let isCrop = editMode == .crop
|
|
14
|
+
try context.engine.editor.setSettingBool("page/allowResizeInteraction", value: isCrop)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Canvas Menu
|
|
4
|
+
|
|
5
|
+
extension PhotoEditorConfiguration {
|
|
6
|
+
/// The default canvas menu configuration.
|
|
7
|
+
static var defaultCanvasMenu: CanvasMenu.Configuration {
|
|
8
|
+
CanvasMenu.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-canvas-menu
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
CanvasMenu.Buttons.selectGroup()
|
|
12
|
+
CanvasMenu.Divider()
|
|
13
|
+
CanvasMenu.Buttons.bringForward()
|
|
14
|
+
CanvasMenu.Buttons.sendBackward()
|
|
15
|
+
CanvasMenu.Divider()
|
|
16
|
+
CanvasMenu.Buttons.duplicate()
|
|
17
|
+
CanvasMenu.Buttons.delete()
|
|
18
|
+
}
|
|
19
|
+
// highlight-starter-kit-canvas-menu
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Dock
|
|
4
|
+
|
|
5
|
+
extension PhotoEditorConfiguration {
|
|
6
|
+
/// The default dock configuration.
|
|
7
|
+
static var defaultDock: Dock.Configuration {
|
|
8
|
+
Dock.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-dock
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
Dock.Buttons.adjustments() // Image adjustments
|
|
12
|
+
Dock.Buttons.filter() // Filters
|
|
13
|
+
Dock.Buttons.effect() // Effects
|
|
14
|
+
Dock.Buttons.blur() // Blur
|
|
15
|
+
Dock.Buttons.crop() // Crop tool
|
|
16
|
+
Dock.Buttons.textLibrary() // Text tools
|
|
17
|
+
Dock.Buttons.shapesLibrary() // Shapes
|
|
18
|
+
Dock.Buttons.stickersLibrary() // Stickers
|
|
19
|
+
}
|
|
20
|
+
// highlight-starter-kit-dock
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
|
|
4
|
+
// MARK: - Inspector Bar
|
|
5
|
+
|
|
6
|
+
extension PhotoEditorConfiguration {
|
|
7
|
+
/// The default inspector bar configuration.
|
|
8
|
+
static var defaultInspectorBar: InspectorBar.Configuration {
|
|
9
|
+
InspectorBar.Configuration { builder in
|
|
10
|
+
// highlight-starter-kit-inspector-bar
|
|
11
|
+
builder.items { _ in
|
|
12
|
+
InspectorBar.Buttons.replace()
|
|
13
|
+
|
|
14
|
+
InspectorBar.Buttons.editText()
|
|
15
|
+
InspectorBar.Buttons.formatText()
|
|
16
|
+
InspectorBar.Buttons.fillStroke()
|
|
17
|
+
InspectorBar.Buttons.textBackground()
|
|
18
|
+
InspectorBar.Buttons.crop()
|
|
19
|
+
|
|
20
|
+
InspectorBar.Buttons.adjustments()
|
|
21
|
+
InspectorBar.Buttons.filter()
|
|
22
|
+
InspectorBar.Buttons.effect()
|
|
23
|
+
InspectorBar.Buttons.blur()
|
|
24
|
+
InspectorBar.Buttons.shape()
|
|
25
|
+
|
|
26
|
+
InspectorBar.Buttons.selectGroup()
|
|
27
|
+
InspectorBar.Buttons.enterGroup()
|
|
28
|
+
|
|
29
|
+
InspectorBar.Buttons.layer()
|
|
30
|
+
InspectorBar.Buttons.duplicate()
|
|
31
|
+
InspectorBar.Buttons.delete()
|
|
32
|
+
}
|
|
33
|
+
builder.enabled = {
|
|
34
|
+
try $0.engine.block.getType($0.selection.block) != DesignBlockType.page.rawValue
|
|
35
|
+
}
|
|
36
|
+
// highlight-starter-kit-inspector-bar
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
|
|
3
|
+
// MARK: - Navigation Bar
|
|
4
|
+
|
|
5
|
+
extension PhotoEditorConfiguration {
|
|
6
|
+
/// The default navigation bar configuration.
|
|
7
|
+
static var defaultNavigationBar: NavigationBar.Configuration {
|
|
8
|
+
NavigationBar.Configuration { builder in
|
|
9
|
+
// highlight-starter-kit-navigation-bar
|
|
10
|
+
builder.items { _ in
|
|
11
|
+
NavigationBar.ItemGroup(placement: .topBarLeading) {
|
|
12
|
+
NavigationBar.Buttons.closeEditor()
|
|
13
|
+
}
|
|
14
|
+
NavigationBar.ItemGroup(placement: .topBarTrailing) {
|
|
15
|
+
NavigationBar.Buttons.undo()
|
|
16
|
+
NavigationBar.Buttons.redo()
|
|
17
|
+
NavigationBar.Buttons.togglePreviewMode()
|
|
18
|
+
NavigationBar.Buttons.export()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// highlight-starter-kit-navigation-bar
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
@_spi(Internal) import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
|
|
4
|
+
// highlight-starter-kit-force-crop
|
|
5
|
+
/// Example: Apply force crop in the `onLoaded` callback.
|
|
6
|
+
/// Add this logic before or after the existing `onLoaded` handler in `PhotoEditorConfiguration`.
|
|
7
|
+
extension PhotoEditorConfiguration {
|
|
8
|
+
static var forceCropOnLoadedHandler: OnLoaded.Handler {
|
|
9
|
+
{ context, existing in
|
|
10
|
+
// Apply force crop: allow 1:1, 16:9, or 9:16
|
|
11
|
+
if let page = try context.engine.scene.getPages().first {
|
|
12
|
+
context.eventHandler.send(
|
|
13
|
+
.applyForceCrop(
|
|
14
|
+
to: page,
|
|
15
|
+
with: [
|
|
16
|
+
ForceCropPreset(sourceID: "ly.img.crop.presets", presetID: "aspect-ratio-1-1"),
|
|
17
|
+
ForceCropPreset(sourceID: "ly.img.crop.presets", presetID: "aspect-ratio-16-9"),
|
|
18
|
+
ForceCropPreset(sourceID: "ly.img.crop.presets", presetID: "aspect-ratio-9-16"),
|
|
19
|
+
],
|
|
20
|
+
mode: .ifNeeded,
|
|
21
|
+
),
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
// Continue with the existing onLoaded logic
|
|
25
|
+
try await existing()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// highlight-starter-kit-force-crop
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import SwiftUI
|
|
4
|
+
|
|
5
|
+
// CE.SDK Starter Kit: Postcard Editor
|
|
6
|
+
//
|
|
7
|
+
// This starter kit provides a complete, production-ready Postcard Editor configuration
|
|
8
|
+
// with all configuration code inline and fully documented. Copy this file into your
|
|
9
|
+
// project and customize it to match your needs.
|
|
10
|
+
|
|
11
|
+
// MARK: - Configuration
|
|
12
|
+
|
|
13
|
+
public final class PostcardEditorConfiguration: EditorConfiguration {
|
|
14
|
+
// MARK: - EditorConfiguration — Settings
|
|
15
|
+
|
|
16
|
+
/// The zoom padding for the canvas.
|
|
17
|
+
override public var zoomPadding: CGFloat? { 16 }
|
|
18
|
+
|
|
19
|
+
// MARK: - EditorConfiguration — Callbacks
|
|
20
|
+
|
|
21
|
+
/// The `onCreate` handler.
|
|
22
|
+
override public var onCreate: OnCreate.Handler? { Self.defaultOnCreateHandler }
|
|
23
|
+
|
|
24
|
+
/// The `onChanged` handler.
|
|
25
|
+
override public var onChanged: OnChanged.Handler? { Self.defaultOnChangedHandler }
|
|
26
|
+
|
|
27
|
+
/// The export handler.
|
|
28
|
+
///
|
|
29
|
+
/// Default: Exports the scene as PDF and opens the system share sheet.
|
|
30
|
+
override public var onExport: OnExport.Handler? { Self.defaultOnExportHandler }
|
|
31
|
+
|
|
32
|
+
// MARK: - EditorConfiguration — UI Components
|
|
33
|
+
|
|
34
|
+
/// The navigation bar configuration.
|
|
35
|
+
override public var navigationBar: NavigationBar.Configuration? { Self.defaultNavigationBar }
|
|
36
|
+
|
|
37
|
+
/// The dock configuration.
|
|
38
|
+
override public var dock: Dock.Configuration? { Self.defaultDock }
|
|
39
|
+
|
|
40
|
+
/// The inspector bar configuration.
|
|
41
|
+
override public var inspectorBar: InspectorBar.Configuration? { Self.defaultInspectorBar }
|
|
42
|
+
|
|
43
|
+
/// The canvas menu configuration.
|
|
44
|
+
override public var canvasMenu: CanvasMenu.Configuration? { Self.defaultCanvasMenu }
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import IMGLYEditor
|
|
2
|
+
import IMGLYEngine
|
|
3
|
+
import SwiftUI
|
|
4
|
+
|
|
5
|
+
// MARK: - Starter Kit View
|
|
6
|
+
|
|
7
|
+
struct PostcardEditorStarterKit: 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
|
+
PostcardEditorConfiguration()
|
|
20
|
+
}
|
|
21
|
+
// highlight-starter-kit-composable
|
|
22
|
+
}
|
|
23
|
+
// highlight-starter-kit-view
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MARK: - Preview
|
|
27
|
+
|
|
28
|
+
#Preview {
|
|
29
|
+
PostcardEditorStarterKit()
|
|
30
|
+
}
|