@imgly/editor-react-native 1.73.0 → 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/android/build.gradle +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/ios/IMGLYEditorModule.swift +9 -1
- 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
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
@file:Suppress("UnusedReceiverParameter")
|
|
2
|
+
|
|
3
|
+
package ly.img.editor.configuration.photo.callback
|
|
4
|
+
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.util.SizeF
|
|
7
|
+
import androidx.core.net.toUri
|
|
8
|
+
import kotlinx.coroutines.coroutineScope
|
|
9
|
+
import kotlinx.coroutines.launch
|
|
10
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
11
|
+
import ly.img.editor.core.library.data.TextAssetSource
|
|
12
|
+
import ly.img.editor.core.library.data.TypefaceProvider
|
|
13
|
+
import ly.img.engine.DefaultAssetSource
|
|
14
|
+
import ly.img.engine.DemoAssetSource
|
|
15
|
+
import ly.img.engine.DesignBlock
|
|
16
|
+
import ly.img.engine.SceneLayout
|
|
17
|
+
import ly.img.engine.populateAssetSource
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The callback that is invoked when the editor is created.
|
|
21
|
+
*/
|
|
22
|
+
suspend fun PhotoConfigurationBuilder.onCreate(
|
|
23
|
+
preCreateScene: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
24
|
+
onPreCreateScene()
|
|
25
|
+
},
|
|
26
|
+
createScene: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
27
|
+
onCreateScene()
|
|
28
|
+
},
|
|
29
|
+
loadAssetSources: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
30
|
+
onLoadAssetSources()
|
|
31
|
+
},
|
|
32
|
+
postCreateScene: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
33
|
+
onPostCreateScene()
|
|
34
|
+
},
|
|
35
|
+
finally: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
36
|
+
onCreateFinally()
|
|
37
|
+
},
|
|
38
|
+
) {
|
|
39
|
+
try {
|
|
40
|
+
preCreateScene()
|
|
41
|
+
createScene()
|
|
42
|
+
loadAssetSources()
|
|
43
|
+
postCreateScene()
|
|
44
|
+
} finally {
|
|
45
|
+
finally()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The callback that is invoked before the scene is created.
|
|
51
|
+
*/
|
|
52
|
+
fun PhotoConfigurationBuilder.onPreCreateScene() {
|
|
53
|
+
showLoading = true
|
|
54
|
+
editorContext.engine.editor.setSettingBoolean(keypath = "page/moveChildrenWhenCroppingFill", value = true)
|
|
55
|
+
editorContext.engine.editor.setSettingBoolean(keypath = "page/selectWhenNoBlocksSelected", value = true)
|
|
56
|
+
editorContext.engine.editor.setSettingBoolean(keypath = "page/highlightWhenCropping", value = true)
|
|
57
|
+
editorContext.engine.editor.setSettingBoolean(keypath = "doubleClickToCropEnabled", value = false)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The callback that is responsible for creating the scene.
|
|
62
|
+
*/
|
|
63
|
+
// highlight-starter-kit-on-create-scene
|
|
64
|
+
suspend fun PhotoConfigurationBuilder.onCreateScene() {
|
|
65
|
+
getOrCreateSceneFromImage(imageUri = "https://cdn.img.ly/assets/demo/v3/ly.img.image/images/sample_1.jpg".toUri())
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
suspend fun PhotoConfigurationBuilder.getOrCreateSceneFromImage(
|
|
69
|
+
imageUri: Uri,
|
|
70
|
+
size: SizeF? = null,
|
|
71
|
+
dpi: Float = 300F,
|
|
72
|
+
pixelScaleFactor: Float = 1F,
|
|
73
|
+
sceneLayout: SceneLayout = SceneLayout.FREE,
|
|
74
|
+
): DesignBlock = editorContext.engine.scene.get() ?: editorContext.engine.scene.createFromImage(
|
|
75
|
+
imageUri = imageUri,
|
|
76
|
+
dpi = dpi,
|
|
77
|
+
pixelScaleFactor = pixelScaleFactor,
|
|
78
|
+
sceneLayout = sceneLayout,
|
|
79
|
+
).also {
|
|
80
|
+
size?.let {
|
|
81
|
+
val page = requireNotNull(editorContext.engine.scene.getCurrentPage())
|
|
82
|
+
editorContext.engine.block.setWidth(block = page, value = size.width)
|
|
83
|
+
editorContext.engine.block.setHeight(block = page, value = size.height)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// highlight-starter-kit-on-create-scene
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The callback that loads all the required assets sources.
|
|
90
|
+
*/
|
|
91
|
+
// highlight-starter-kit-on-load-asset-sources
|
|
92
|
+
suspend fun PhotoConfigurationBuilder.onLoadAssetSources() {
|
|
93
|
+
// Load asset sources in parallel from content.json files
|
|
94
|
+
coroutineScope {
|
|
95
|
+
listOf(
|
|
96
|
+
DefaultAssetSource.STICKER.key,
|
|
97
|
+
DefaultAssetSource.VECTOR_PATH.key,
|
|
98
|
+
DefaultAssetSource.FILTER_LUT.key,
|
|
99
|
+
DefaultAssetSource.FILTER_DUO_TONE.key,
|
|
100
|
+
DefaultAssetSource.CROP_PRESETS.key,
|
|
101
|
+
DefaultAssetSource.PAGE_PRESETS.key,
|
|
102
|
+
DefaultAssetSource.EFFECT.key,
|
|
103
|
+
DefaultAssetSource.BLUR.key,
|
|
104
|
+
DefaultAssetSource.TYPEFACE.key,
|
|
105
|
+
DemoAssetSource.TEXT_COMPONENTS.key,
|
|
106
|
+
).forEach { assetSource ->
|
|
107
|
+
launch {
|
|
108
|
+
val baseUri = editorContext.baseUri
|
|
109
|
+
editorContext.engine.populateAssetSource(
|
|
110
|
+
id = assetSource,
|
|
111
|
+
jsonUri = "$baseUri/$assetSource/content.json".toUri(),
|
|
112
|
+
replaceBaseUri = baseUri,
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Register text asset source
|
|
119
|
+
TypefaceProvider().provideTypeface(
|
|
120
|
+
engine = editorContext.engine,
|
|
121
|
+
name = "Roboto",
|
|
122
|
+
)?.let {
|
|
123
|
+
val textAssetSource = TextAssetSource(engine = editorContext.engine, typeface = it)
|
|
124
|
+
editorContext.engine.asset.addSource(textAssetSource)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// highlight-starter-kit-on-load-asset-sources
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The callback that is invoked right after [onCreateScene], after the scene is created.
|
|
131
|
+
*/
|
|
132
|
+
fun PhotoConfigurationBuilder.onPostCreateScene() {
|
|
133
|
+
val page = requireNotNull(editorContext.engine.scene.getCurrentPage())
|
|
134
|
+
editorContext.engine.block.setScopeEnabled(block = page, key = "layer/move", enabled = false)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The callback that is invoked as the last step of [onCreate].
|
|
139
|
+
* It always runs, no matter success or failure on previous steps.
|
|
140
|
+
*/
|
|
141
|
+
fun PhotoConfigurationBuilder.onCreateFinally() {
|
|
142
|
+
showLoading = false
|
|
143
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package ly.img.editor.configuration.photo.callback
|
|
2
|
+
|
|
3
|
+
import kotlinx.coroutines.CancellationException
|
|
4
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
5
|
+
import ly.img.engine.MimeType
|
|
6
|
+
import java.nio.ByteBuffer
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The callback that is invoked when the export button is clicked.
|
|
10
|
+
*/
|
|
11
|
+
suspend fun PhotoConfigurationBuilder.onExport(
|
|
12
|
+
preExport: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
13
|
+
onPreExport()
|
|
14
|
+
},
|
|
15
|
+
exportByteBuffer: suspend PhotoConfigurationBuilder.() -> ByteBuffer = {
|
|
16
|
+
onExportByteBuffer()
|
|
17
|
+
},
|
|
18
|
+
postExport: suspend PhotoConfigurationBuilder.(ByteBuffer) -> Unit = {
|
|
19
|
+
onPostExport(it)
|
|
20
|
+
},
|
|
21
|
+
error: suspend PhotoConfigurationBuilder.(Exception) -> Unit = {
|
|
22
|
+
onExportError(it)
|
|
23
|
+
},
|
|
24
|
+
finally: suspend PhotoConfigurationBuilder.() -> Unit = {
|
|
25
|
+
onExportFinally()
|
|
26
|
+
},
|
|
27
|
+
) {
|
|
28
|
+
try {
|
|
29
|
+
preExport()
|
|
30
|
+
val result = exportByteBuffer()
|
|
31
|
+
postExport(result)
|
|
32
|
+
} catch (exception: Exception) {
|
|
33
|
+
error(exception)
|
|
34
|
+
} finally {
|
|
35
|
+
finally()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The callback that is invoked before the export is started.
|
|
41
|
+
*/
|
|
42
|
+
fun PhotoConfigurationBuilder.onPreExport() {
|
|
43
|
+
showLoading = true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The callback that exports the content of the editor into [ByteBuffer].
|
|
48
|
+
*/
|
|
49
|
+
// highlight-starter-kit-on-export-byte-buffer
|
|
50
|
+
suspend fun PhotoConfigurationBuilder.onExportByteBuffer(): ByteBuffer = export(
|
|
51
|
+
block = requireNotNull(editorContext.engine.scene.get()),
|
|
52
|
+
mimeType = MimeType.PNG,
|
|
53
|
+
)
|
|
54
|
+
// highlight-starter-kit-on-export-byte-buffer
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The callback that is invoked after [onExportByteBuffer] and handles its output.
|
|
58
|
+
*/
|
|
59
|
+
// highlight-starter-kit-on-post-export
|
|
60
|
+
suspend fun PhotoConfigurationBuilder.onPostExport(byteBuffer: ByteBuffer) {
|
|
61
|
+
val file = writeToFile(byteBuffer = byteBuffer, mimeType = MimeType.PNG)
|
|
62
|
+
shareFile(file = file, mimeType = MimeType.PNG)
|
|
63
|
+
}
|
|
64
|
+
// highlight-starter-kit-on-post-export
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The callback that is invoked in case any of the export functions throw an exception.
|
|
68
|
+
*/
|
|
69
|
+
fun PhotoConfigurationBuilder.onExportError(error: Exception) {
|
|
70
|
+
if (error is CancellationException) {
|
|
71
|
+
throw error
|
|
72
|
+
}
|
|
73
|
+
this.error = error
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The callback that is invoked as the last step of [onExportByteBuffer].
|
|
78
|
+
* It always runs, no matter success or failure on previous steps.
|
|
79
|
+
*/
|
|
80
|
+
fun PhotoConfigurationBuilder.onExportFinally() {
|
|
81
|
+
showLoading = false
|
|
82
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package ly.img.editor.configuration.photo.callback
|
|
2
|
+
|
|
3
|
+
import androidx.compose.ui.unit.dp
|
|
4
|
+
import kotlinx.coroutines.coroutineScope
|
|
5
|
+
import kotlinx.coroutines.flow.distinctUntilChangedBy
|
|
6
|
+
import kotlinx.coroutines.flow.filter
|
|
7
|
+
import kotlinx.coroutines.launch
|
|
8
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
9
|
+
import ly.img.editor.core.component.data.Insets
|
|
10
|
+
import ly.img.editor.core.state.EditorViewMode
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The callback that is invoked when the editor is loaded and ready to be used.
|
|
14
|
+
*/
|
|
15
|
+
suspend fun PhotoConfigurationBuilder.onLoaded() {
|
|
16
|
+
coroutineScope {
|
|
17
|
+
launch { observeEditorViewMode() }
|
|
18
|
+
launch {
|
|
19
|
+
observeEditorEditMode(
|
|
20
|
+
extraInsets = { Insets(value = if (it == "Crop") 24.dp else 0.dp) },
|
|
21
|
+
) { editMode ->
|
|
22
|
+
// Allow resize only in crop mode.
|
|
23
|
+
editorContext.engine.editor.setSettingBoolean(
|
|
24
|
+
keypath = "page/allowResizeInteraction",
|
|
25
|
+
value = editMode == "Crop",
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Function that zooms to the current page when the [EditorViewMode] is preview.
|
|
34
|
+
*/
|
|
35
|
+
suspend fun PhotoConfigurationBuilder.observeEditorViewMode() {
|
|
36
|
+
editorContext.state
|
|
37
|
+
.distinctUntilChangedBy { it.viewMode to it.insets }
|
|
38
|
+
.filter { it.viewMode is EditorViewMode.Preview }
|
|
39
|
+
.collect { state ->
|
|
40
|
+
editorContext.engine.scene.immediateZoomToBlock(
|
|
41
|
+
block = requireNotNull(editorContext.engine.scene.getCurrentPage()),
|
|
42
|
+
paddingLeft = state.insets.left.value,
|
|
43
|
+
paddingTop = state.insets.top.value,
|
|
44
|
+
paddingRight = state.insets.right.value,
|
|
45
|
+
paddingBottom = 0F,
|
|
46
|
+
forceUpdate = true,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@file:Suppress("UnusedReceiverParameter")
|
|
2
|
+
|
|
3
|
+
package ly.img.editor.configuration.photo.component
|
|
4
|
+
|
|
5
|
+
import androidx.compose.runtime.Composable
|
|
6
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
7
|
+
import ly.img.editor.core.component.CanvasMenu
|
|
8
|
+
import ly.img.editor.core.component.EditorComponentId
|
|
9
|
+
import ly.img.editor.core.component.remember
|
|
10
|
+
import ly.img.editor.core.component.rememberBringForward
|
|
11
|
+
import ly.img.editor.core.component.rememberDelete
|
|
12
|
+
import ly.img.editor.core.component.rememberDuplicate
|
|
13
|
+
import ly.img.editor.core.component.rememberSelectGroup
|
|
14
|
+
import ly.img.editor.core.component.rememberSendBackward
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The configuration of the component that is displayed as horizontal list of items next to
|
|
18
|
+
* the selected design block.
|
|
19
|
+
*/
|
|
20
|
+
@Composable
|
|
21
|
+
fun PhotoConfigurationBuilder.rememberCanvasMenu() = CanvasMenu.remember {
|
|
22
|
+
listBuilder = {
|
|
23
|
+
CanvasMenu.ListBuilder.remember {
|
|
24
|
+
add { CanvasMenu.Button.rememberSelectGroup() }
|
|
25
|
+
if (editorContext.isSelectionInGroup) {
|
|
26
|
+
add {
|
|
27
|
+
CanvasMenu.Divider.remember {
|
|
28
|
+
id = { EditorComponentId("ly.img.component.canvasMenu.divider1") }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
add { CanvasMenu.Button.rememberBringForward() }
|
|
33
|
+
add { CanvasMenu.Button.rememberSendBackward() }
|
|
34
|
+
if (editorContext.canSelectionMove) {
|
|
35
|
+
add {
|
|
36
|
+
CanvasMenu.Divider.remember {
|
|
37
|
+
id = { EditorComponentId("ly.img.component.canvasMenu.divider2") }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
add { CanvasMenu.Button.rememberDuplicate() }
|
|
42
|
+
add { CanvasMenu.Button.rememberDelete() }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
@file:Suppress("UnusedReceiverParameter")
|
|
2
|
+
|
|
3
|
+
package ly.img.editor.configuration.photo.component
|
|
4
|
+
|
|
5
|
+
import androidx.compose.runtime.Composable
|
|
6
|
+
import androidx.compose.runtime.collectAsState
|
|
7
|
+
import androidx.compose.runtime.getValue
|
|
8
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
9
|
+
import ly.img.editor.core.component.Dock
|
|
10
|
+
import ly.img.editor.core.component.remember
|
|
11
|
+
import ly.img.editor.core.component.rememberAdjustments
|
|
12
|
+
import ly.img.editor.core.component.rememberBlur
|
|
13
|
+
import ly.img.editor.core.component.rememberCrop
|
|
14
|
+
import ly.img.editor.core.component.rememberEffect
|
|
15
|
+
import ly.img.editor.core.component.rememberFilter
|
|
16
|
+
import ly.img.editor.core.component.rememberShapesLibrary
|
|
17
|
+
import ly.img.editor.core.component.rememberStickersLibrary
|
|
18
|
+
import ly.img.editor.core.component.rememberTextLibrary
|
|
19
|
+
import ly.img.editor.core.state.EditorViewMode
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The configuration of the component that is displayed as horizontal list of items at the bottom of the editor.
|
|
23
|
+
*/
|
|
24
|
+
@Composable
|
|
25
|
+
fun PhotoConfigurationBuilder.rememberDock() = Dock.remember {
|
|
26
|
+
visible = {
|
|
27
|
+
val state by editorContext.state.collectAsState()
|
|
28
|
+
// Hide Dock in preview mode
|
|
29
|
+
state.viewMode !is EditorViewMode.Preview
|
|
30
|
+
}
|
|
31
|
+
listBuilder = {
|
|
32
|
+
Dock.ListBuilder.remember {
|
|
33
|
+
add { Dock.Button.rememberAdjustments() }
|
|
34
|
+
add { Dock.Button.rememberFilter() }
|
|
35
|
+
add { Dock.Button.rememberEffect() }
|
|
36
|
+
add { Dock.Button.rememberBlur() }
|
|
37
|
+
add { Dock.Button.rememberCrop() }
|
|
38
|
+
add { Dock.Button.rememberTextLibrary() }
|
|
39
|
+
add { Dock.Button.rememberShapesLibrary() }
|
|
40
|
+
add { Dock.Button.rememberStickersLibrary() }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
@file:Suppress("UnusedReceiverParameter")
|
|
2
|
+
|
|
3
|
+
package ly.img.editor.configuration.photo.component
|
|
4
|
+
|
|
5
|
+
import androidx.compose.runtime.Composable
|
|
6
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
7
|
+
import ly.img.editor.core.component.InspectorBar
|
|
8
|
+
import ly.img.editor.core.component.remember
|
|
9
|
+
import ly.img.editor.core.component.rememberAdjustments
|
|
10
|
+
import ly.img.editor.core.component.rememberBlur
|
|
11
|
+
import ly.img.editor.core.component.rememberCrop
|
|
12
|
+
import ly.img.editor.core.component.rememberDelete
|
|
13
|
+
import ly.img.editor.core.component.rememberDuplicate
|
|
14
|
+
import ly.img.editor.core.component.rememberEditText
|
|
15
|
+
import ly.img.editor.core.component.rememberEffect
|
|
16
|
+
import ly.img.editor.core.component.rememberEnterGroup
|
|
17
|
+
import ly.img.editor.core.component.rememberFillStroke
|
|
18
|
+
import ly.img.editor.core.component.rememberFilter
|
|
19
|
+
import ly.img.editor.core.component.rememberFormatText
|
|
20
|
+
import ly.img.editor.core.component.rememberLayer
|
|
21
|
+
import ly.img.editor.core.component.rememberReplace
|
|
22
|
+
import ly.img.editor.core.component.rememberSelectGroup
|
|
23
|
+
import ly.img.editor.core.component.rememberShape
|
|
24
|
+
import ly.img.editor.core.component.rememberTextBackground
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The configuration of the component that is displayed as horizontal list of items at the
|
|
28
|
+
* bottom of the editor when a design block is selected.
|
|
29
|
+
*/
|
|
30
|
+
@Composable
|
|
31
|
+
fun PhotoConfigurationBuilder.rememberInspectorBar() = InspectorBar.remember {
|
|
32
|
+
listBuilder = {
|
|
33
|
+
InspectorBar.ListBuilder.remember {
|
|
34
|
+
add { InspectorBar.Button.rememberReplace() } // Image, Sticker, Audio
|
|
35
|
+
add { InspectorBar.Button.rememberEditText() } // Text
|
|
36
|
+
add { InspectorBar.Button.rememberFormatText() } // Text
|
|
37
|
+
add { InspectorBar.Button.rememberFillStroke() } // Page, Image, Shape, Text
|
|
38
|
+
add { InspectorBar.Button.rememberTextBackground() } // Text
|
|
39
|
+
add { InspectorBar.Button.rememberCrop() } // Image
|
|
40
|
+
add { InspectorBar.Button.rememberAdjustments() } // Image
|
|
41
|
+
add { InspectorBar.Button.rememberFilter() } // Image
|
|
42
|
+
add { InspectorBar.Button.rememberEffect() } // Image
|
|
43
|
+
add { InspectorBar.Button.rememberBlur() } // Image
|
|
44
|
+
add { InspectorBar.Button.rememberShape() } // Image, Shape
|
|
45
|
+
add { InspectorBar.Button.rememberSelectGroup() } // Image, Sticker, Shape, Text
|
|
46
|
+
add { InspectorBar.Button.rememberEnterGroup() } // Group
|
|
47
|
+
add { InspectorBar.Button.rememberLayer() } // Image, Sticker, Shape, Text
|
|
48
|
+
add { InspectorBar.Button.rememberDuplicate() } // Image, Sticker, Shape, Text
|
|
49
|
+
add { InspectorBar.Button.rememberDelete() } // Image, Sticker, Shape, Text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@file:Suppress("UnusedReceiverParameter")
|
|
2
|
+
|
|
3
|
+
package ly.img.editor.configuration.photo.component
|
|
4
|
+
|
|
5
|
+
import androidx.compose.runtime.Composable
|
|
6
|
+
import androidx.compose.runtime.remember
|
|
7
|
+
import androidx.compose.ui.Alignment
|
|
8
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
9
|
+
import ly.img.editor.core.component.EditorTrigger
|
|
10
|
+
import ly.img.editor.core.component.NavigationBar
|
|
11
|
+
import ly.img.editor.core.component.remember
|
|
12
|
+
import ly.img.editor.core.component.rememberCloseEditor
|
|
13
|
+
import ly.img.editor.core.component.rememberExport
|
|
14
|
+
import ly.img.editor.core.component.rememberRedo
|
|
15
|
+
import ly.img.editor.core.component.rememberTogglePreviewMode
|
|
16
|
+
import ly.img.editor.core.component.rememberUndo
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The configuration of the component that is displayed as horizontal list of items at the top of the editor.
|
|
20
|
+
*/
|
|
21
|
+
@Composable
|
|
22
|
+
fun PhotoConfigurationBuilder.rememberNavigationBar() = NavigationBar.remember {
|
|
23
|
+
scope = {
|
|
24
|
+
val historyTrigger by EditorTrigger.remember {
|
|
25
|
+
editorContext.engine.editor.onHistoryUpdated()
|
|
26
|
+
}
|
|
27
|
+
// Update NavigationBar whenever the editor history changes
|
|
28
|
+
remember(this, historyTrigger) {
|
|
29
|
+
NavigationBar.Scope(parentScope = this)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
listBuilder = {
|
|
33
|
+
NavigationBar.ListBuilder.remember {
|
|
34
|
+
aligned(alignment = Alignment.Start) {
|
|
35
|
+
add { NavigationBar.Button.rememberCloseEditor() }
|
|
36
|
+
}
|
|
37
|
+
aligned(alignment = Alignment.End) {
|
|
38
|
+
add { NavigationBar.Button.rememberUndo() }
|
|
39
|
+
add { NavigationBar.Button.rememberRedo() }
|
|
40
|
+
add { NavigationBar.Button.rememberTogglePreviewMode() }
|
|
41
|
+
add { NavigationBar.Button.rememberExport() }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package ly.img.editor.configuration.photo.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import ly.img.editor.configuration.photo.PhotoConfigurationBuilder
|
|
5
|
+
import ly.img.editor.core.component.EditorComponent
|
|
6
|
+
import ly.img.editor.core.component.remember
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The configuration of the component that is displayed over the editor. It is useful if you want to display a popup dialog or anything in the
|
|
10
|
+
* overlay.
|
|
11
|
+
*/
|
|
12
|
+
@Composable
|
|
13
|
+
fun PhotoConfigurationBuilder.rememberOverlay() = EditorComponent.remember {
|
|
14
|
+
decoration = { Overlay() }
|
|
15
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// highlight-starter-kit-activity-full
|
|
2
|
+
package ly.img.editor.configuration.postcard
|
|
3
|
+
|
|
4
|
+
import android.os.Bundle
|
|
5
|
+
import androidx.activity.ComponentActivity
|
|
6
|
+
import androidx.activity.compose.setContent
|
|
7
|
+
import androidx.activity.enableEdgeToEdge
|
|
8
|
+
import ly.img.editor.Editor
|
|
9
|
+
import ly.img.editor.core.configuration.EditorConfiguration
|
|
10
|
+
import ly.img.editor.core.configuration.remember
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Encapsulated editor to be used in legacy activity navigation.
|
|
14
|
+
* Delete this file if you are using jetpack compose navigation.
|
|
15
|
+
*/
|
|
16
|
+
class EditorActivity : ComponentActivity() {
|
|
17
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
18
|
+
super.onCreate(savedInstanceState)
|
|
19
|
+
// This is required to remove the default action bar on top.
|
|
20
|
+
setTheme(android.R.style.Theme_Material_Light_NoActionBar)
|
|
21
|
+
// This is required, so that the editor is displayed full screen on relatively older devices.
|
|
22
|
+
enableEdgeToEdge()
|
|
23
|
+
setContent {
|
|
24
|
+
Editor(
|
|
25
|
+
license = null, // pass null or empty for evaluation mode with watermark
|
|
26
|
+
configuration = {
|
|
27
|
+
EditorConfiguration.remember(::PostcardConfigurationBuilder)
|
|
28
|
+
},
|
|
29
|
+
onClose = {
|
|
30
|
+
// Finish the activity, potentially handle errors.
|
|
31
|
+
finish()
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// highlight-starter-kit-activity-full
|
package/android/src/main/kotlin/ly/img/editor/configuration/postcard/PostcardConfigurationBuilder.kt
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package ly.img.editor.configuration.postcard
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Stable
|
|
4
|
+
import ly.img.editor.BasicConfigurationBuilder
|
|
5
|
+
import ly.img.editor.configuration.postcard.callback.onCreate
|
|
6
|
+
import ly.img.editor.configuration.postcard.callback.onExport
|
|
7
|
+
import ly.img.editor.configuration.postcard.callback.onLoaded
|
|
8
|
+
import ly.img.editor.configuration.postcard.component.rememberCanvasMenu
|
|
9
|
+
import ly.img.editor.configuration.postcard.component.rememberDock
|
|
10
|
+
import ly.img.editor.configuration.postcard.component.rememberInspectorBar
|
|
11
|
+
import ly.img.editor.configuration.postcard.component.rememberNavigationBar
|
|
12
|
+
import ly.img.editor.configuration.postcard.component.rememberOverlay
|
|
13
|
+
import ly.img.editor.core.EditorScope
|
|
14
|
+
import ly.img.editor.core.ScopedProperty
|
|
15
|
+
import ly.img.editor.core.component.EditorComponent
|
|
16
|
+
import ly.img.editor.core.event.EditorEvent
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Configuration builder class for postcard editor starter kit.
|
|
20
|
+
*/
|
|
21
|
+
@Stable
|
|
22
|
+
class PostcardConfigurationBuilder : BasicConfigurationBuilder() {
|
|
23
|
+
/**
|
|
24
|
+
* The callback that is invoked when the editor is created.
|
|
25
|
+
* Check parent class declaration for more details.
|
|
26
|
+
*/
|
|
27
|
+
override var onCreate: (suspend EditorScope.() -> Unit)? = {
|
|
28
|
+
onCreate()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The callback that is invoked when the editor is loaded and ready to be used.
|
|
33
|
+
* Check parent class declaration for more details.
|
|
34
|
+
*/
|
|
35
|
+
override var onLoaded: (suspend EditorScope.() -> Unit)? = {
|
|
36
|
+
onLoaded()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The callback that is invoked when the export button is clicked.
|
|
41
|
+
* Check parent class declaration for more details.
|
|
42
|
+
*/
|
|
43
|
+
override var onExport: (suspend EditorScope.() -> Unit)? = {
|
|
44
|
+
onExport()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The callback that is invoked after [EditorEvent.OnClose] event is triggered or when the system back button is clicked
|
|
49
|
+
* and editor cannot handle the event internally.
|
|
50
|
+
* Check parent class declaration for more details.
|
|
51
|
+
*/
|
|
52
|
+
override var onClose: (suspend EditorScope.() -> Unit)? = {
|
|
53
|
+
showConfirmationOrCloseEditor()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The callback that is invoked after the editor captures an error.
|
|
58
|
+
* Check parent class declaration for more details.
|
|
59
|
+
*/
|
|
60
|
+
override var onError: (suspend EditorScope.(Throwable) -> Unit)? = {
|
|
61
|
+
error = it
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The configuration of the component that is displayed as horizontal list of items at the bottom of the editor.
|
|
66
|
+
* Check parent class declaration for more details.
|
|
67
|
+
*/
|
|
68
|
+
override var dock: ScopedProperty<EditorScope, EditorComponent<*>>? = {
|
|
69
|
+
rememberDock()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The configuration of the component that is displayed as horizontal list of items at the top of the editor.
|
|
74
|
+
* Check parent class declaration for more details.
|
|
75
|
+
*/
|
|
76
|
+
override var navigationBar: ScopedProperty<EditorScope, EditorComponent<*>>? = {
|
|
77
|
+
rememberNavigationBar()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The configuration of the component that is displayed as horizontal list of items at the
|
|
82
|
+
* bottom of the editor when a design block is selected.
|
|
83
|
+
* Check parent class declaration for more details.
|
|
84
|
+
*/
|
|
85
|
+
override var inspectorBar: ScopedProperty<EditorScope, EditorComponent<*>>? = {
|
|
86
|
+
rememberInspectorBar()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The configuration of the component that is displayed as horizontal list of items next to
|
|
91
|
+
* the selected design block.
|
|
92
|
+
* Check parent class declaration for more details.
|
|
93
|
+
*/
|
|
94
|
+
override var canvasMenu: ScopedProperty<EditorScope, EditorComponent<*>>? = {
|
|
95
|
+
rememberCanvasMenu()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The configuration of the component that is displayed over the editor. It is useful if you want to display a popup dialog or anything in the
|
|
100
|
+
* overlay.
|
|
101
|
+
* Check parent class declaration for more details.
|
|
102
|
+
*/
|
|
103
|
+
override var overlay: ScopedProperty<EditorScope, EditorComponent<*>>? = {
|
|
104
|
+
rememberOverlay()
|
|
105
|
+
}
|
|
106
|
+
}
|