@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.
Files changed (117) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/assets/scene/apparel.scene +1 -0
  3. package/android/src/main/assets/scene/design.scene +1 -0
  4. package/android/src/main/assets/scene/postcard.scene +1 -0
  5. package/android/src/main/assets/scene/video.scene +1 -0
  6. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/ApparelConfigurationBuilder.kt +113 -0
  7. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/EditorActivity.kt +37 -0
  8. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnCreate.kt +190 -0
  9. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnExport.kt +82 -0
  10. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/callback/OnLoaded.kt +88 -0
  11. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/CanvasMenu.kt +45 -0
  12. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/Dock.kt +37 -0
  13. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/InspectorBar.kt +52 -0
  14. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/NavigationBar.kt +45 -0
  15. package/android/src/main/kotlin/ly/img/editor/configuration/apparel/component/Overlay.kt +15 -0
  16. package/android/src/main/kotlin/ly/img/editor/configuration/design/DesignConfigurationBuilder.kt +106 -0
  17. package/android/src/main/kotlin/ly/img/editor/configuration/design/EditorActivity.kt +37 -0
  18. package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnCreate.kt +162 -0
  19. package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnExport.kt +82 -0
  20. package/android/src/main/kotlin/ly/img/editor/configuration/design/callback/OnLoaded.kt +10 -0
  21. package/android/src/main/kotlin/ly/img/editor/configuration/design/component/CanvasMenu.kt +45 -0
  22. package/android/src/main/kotlin/ly/img/editor/configuration/design/component/Dock.kt +35 -0
  23. package/android/src/main/kotlin/ly/img/editor/configuration/design/component/InspectorBar.kt +52 -0
  24. package/android/src/main/kotlin/ly/img/editor/configuration/design/component/NavigationBar.kt +45 -0
  25. package/android/src/main/kotlin/ly/img/editor/configuration/design/component/Overlay.kt +15 -0
  26. package/android/src/main/kotlin/ly/img/editor/configuration/photo/EditorActivity.kt +37 -0
  27. package/android/src/main/kotlin/ly/img/editor/configuration/photo/PhotoConfigurationBuilder.kt +106 -0
  28. package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnCreate.kt +143 -0
  29. package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnExport.kt +82 -0
  30. package/android/src/main/kotlin/ly/img/editor/configuration/photo/callback/OnLoaded.kt +49 -0
  31. package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/CanvasMenu.kt +45 -0
  32. package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/Dock.kt +43 -0
  33. package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/InspectorBar.kt +52 -0
  34. package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/NavigationBar.kt +45 -0
  35. package/android/src/main/kotlin/ly/img/editor/configuration/photo/component/Overlay.kt +15 -0
  36. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/EditorActivity.kt +37 -0
  37. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/PostcardConfigurationBuilder.kt +106 -0
  38. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnCreate.kt +149 -0
  39. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnExport.kt +82 -0
  40. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/callback/OnLoaded.kt +58 -0
  41. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/CanvasMenu.kt +45 -0
  42. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/Dock.kt +243 -0
  43. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/InspectorBar.kt +52 -0
  44. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/NavigationBar.kt +76 -0
  45. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/component/Overlay.kt +15 -0
  46. package/android/src/main/kotlin/ly/img/editor/configuration/postcard/ext/Engine.kt +107 -0
  47. package/android/src/main/kotlin/ly/img/editor/configuration/video/EditorActivity.kt +37 -0
  48. package/android/src/main/kotlin/ly/img/editor/configuration/video/VideoConfigurationBuilder.kt +135 -0
  49. package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnCreate.kt +191 -0
  50. package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnExport.kt +98 -0
  51. package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnLoaded.kt +20 -0
  52. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/BottomPanel.kt +13 -0
  53. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/CanvasMenu.kt +45 -0
  54. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/Dock.kt +71 -0
  55. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/InspectorBar.kt +68 -0
  56. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/NavigationBar.kt +57 -0
  57. package/android/src/main/kotlin/ly/img/editor/configuration/video/component/Overlay.kt +421 -0
  58. package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/CheckCircleOutline.kt +79 -0
  59. package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/ErrorOutline.kt +92 -0
  60. package/android/src/main/kotlin/ly/img/editor/configuration/video/iconPack/IconPack.kt +14 -0
  61. package/android/src/main/kotlin/ly/img/editor/configuration/video/model/ExportStatus.kt +39 -0
  62. package/ios/IMGLYEditorModule.swift +9 -1
  63. package/ios/StarterKits/Apparel/ApparelEditorConfiguration.swift +46 -0
  64. package/ios/StarterKits/Apparel/ApparelEditorStarterKit.swift +30 -0
  65. package/ios/StarterKits/Apparel/callbacks/OnChanged+Apparel.swift +116 -0
  66. package/ios/StarterKits/Apparel/callbacks/OnCreate+Apparel.swift +197 -0
  67. package/ios/StarterKits/Apparel/callbacks/OnExport+Apparel.swift +29 -0
  68. package/ios/StarterKits/Apparel/components/CanvasMenu+Apparel.swift +22 -0
  69. package/ios/StarterKits/Apparel/components/Dock+Apparel.swift +19 -0
  70. package/ios/StarterKits/Apparel/components/InspectorBar+Apparel.swift +35 -0
  71. package/ios/StarterKits/Apparel/components/NavigationBar+Apparel.swift +26 -0
  72. package/ios/StarterKits/Design/DesignEditorConfiguration.swift +43 -0
  73. package/ios/StarterKits/Design/DesignEditorStarterKit.swift +30 -0
  74. package/ios/StarterKits/Design/callbacks/OnCreate+Design.swift +131 -0
  75. package/ios/StarterKits/Design/callbacks/OnExport+Design.swift +30 -0
  76. package/ios/StarterKits/Design/components/CanvasMenu+Design.swift +22 -0
  77. package/ios/StarterKits/Design/components/Dock+Design.swift +23 -0
  78. package/ios/StarterKits/Design/components/InspectorBar+Design.swift +35 -0
  79. package/ios/StarterKits/Design/components/NavigationBar+Design.swift +24 -0
  80. package/ios/StarterKits/Photo/PhotoEditorConfiguration.swift +48 -0
  81. package/ios/StarterKits/Photo/PhotoEditorStarterKit.swift +30 -0
  82. package/ios/StarterKits/Photo/callbacks/OnChanged+Photo.swift +25 -0
  83. package/ios/StarterKits/Photo/callbacks/OnCreate+Photo.swift +138 -0
  84. package/ios/StarterKits/Photo/callbacks/OnExport+Photo.swift +29 -0
  85. package/ios/StarterKits/Photo/callbacks/OnLoaded+Photo.swift +18 -0
  86. package/ios/StarterKits/Photo/components/CanvasMenu+Photo.swift +22 -0
  87. package/ios/StarterKits/Photo/components/Dock+Photo.swift +23 -0
  88. package/ios/StarterKits/Photo/components/InspectorBar+Photo.swift +39 -0
  89. package/ios/StarterKits/Photo/components/NavigationBar+Photo.swift +24 -0
  90. package/ios/StarterKits/Photo/examples/ExampleForceCrop.swift +30 -0
  91. package/ios/StarterKits/Postcard/PostcardEditorConfiguration.swift +45 -0
  92. package/ios/StarterKits/Postcard/PostcardEditorStarterKit.swift +30 -0
  93. package/ios/StarterKits/Postcard/callbacks/OnChanged+Postcard.swift +92 -0
  94. package/ios/StarterKits/Postcard/callbacks/OnCreate+Postcard.swift +127 -0
  95. package/ios/StarterKits/Postcard/callbacks/OnExport+Postcard.swift +29 -0
  96. package/ios/StarterKits/Postcard/components/CanvasMenu+Postcard.swift +22 -0
  97. package/ios/StarterKits/Postcard/components/Dock+Postcard.swift +34 -0
  98. package/ios/StarterKits/Postcard/components/DockButtons+Postcard.swift +129 -0
  99. package/ios/StarterKits/Postcard/components/InspectorBar+Postcard.swift +35 -0
  100. package/ios/StarterKits/Postcard/components/NavigationBar+Postcard.swift +38 -0
  101. package/ios/StarterKits/Video/VideoEditorConfiguration.swift +54 -0
  102. package/ios/StarterKits/Video/VideoEditorStarterKit.swift +30 -0
  103. package/ios/StarterKits/Video/callbacks/OnCreate+Video.swift +137 -0
  104. package/ios/StarterKits/Video/callbacks/OnExport+Video.swift +46 -0
  105. package/ios/StarterKits/Video/components/BottomPanel+Video.swift +16 -0
  106. package/ios/StarterKits/Video/components/CanvasMenu+Video.swift +22 -0
  107. package/ios/StarterKits/Video/components/Dock+Video.swift +30 -0
  108. package/ios/StarterKits/Video/components/InspectorBar+Video.swift +43 -0
  109. package/ios/StarterKits/Video/components/NavigationBar+Video.swift +32 -0
  110. package/ios/StarterKits/Video/examples/ExampleVideoDurationConstraints.swift +23 -0
  111. package/ios/StarterKits/apparel-ui-b-empty.scene +1 -0
  112. package/ios/StarterKits/design-ui-empty.scene +1 -0
  113. package/ios/StarterKits/photo-ui-empty.png +0 -0
  114. package/ios/StarterKits/postcard-empty.scene +1 -0
  115. package/ios/StarterKits/video-empty.scene +1 -0
  116. package/package.json +1 -1
  117. package/src/NativeIMGLYEditor.ts +1 -1
@@ -0,0 +1,79 @@
1
+ package ly.img.editor.configuration.video.iconPack
2
+
3
+ import androidx.compose.ui.graphics.Color
4
+ import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
5
+ import androidx.compose.ui.graphics.SolidColor
6
+ import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
7
+ import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
8
+ import androidx.compose.ui.graphics.vector.ImageVector
9
+ import androidx.compose.ui.graphics.vector.ImageVector.Builder
10
+ import androidx.compose.ui.graphics.vector.path
11
+ import androidx.compose.ui.unit.dp
12
+
13
+ /**
14
+ * Check-circle with outline icon
15
+ */
16
+ val IconPack.CheckCircleOutline: ImageVector
17
+ get() {
18
+ if (checkCircleOutline != null) {
19
+ return checkCircleOutline!!
20
+ }
21
+ checkCircleOutline = Builder(
22
+ name = "CheckCircleOutline",
23
+ defaultWidth = 24.0.dp,
24
+ defaultHeight = 24.0.dp,
25
+ viewportWidth = 24.0f,
26
+ viewportHeight = 24.0f,
27
+ ).apply {
28
+ path(
29
+ fill = SolidColor(Color(0xFF46464F)),
30
+ stroke = null,
31
+ strokeLineWidth = 0.0f,
32
+ strokeLineCap = Butt,
33
+ strokeLineJoin = Miter,
34
+ strokeLineMiter = 4.0f,
35
+ pathFillType = NonZero,
36
+ ) {
37
+ moveTo(10.6f, 16.6f)
38
+ lineTo(17.65f, 9.55f)
39
+ lineTo(16.25f, 8.15f)
40
+ lineTo(10.6f, 13.8f)
41
+ lineTo(7.75f, 10.95f)
42
+ lineTo(6.35f, 12.35f)
43
+ lineTo(10.6f, 16.6f)
44
+ close()
45
+ moveTo(12.0f, 22.0f)
46
+ curveTo(10.6167f, 22.0f, 9.3167f, 21.7373f, 8.1f, 21.212f)
47
+ curveTo(6.8833f, 20.6867f, 5.825f, 19.9743f, 4.925f, 19.075f)
48
+ curveTo(4.025f, 18.175f, 3.3127f, 17.1167f, 2.788f, 15.9f)
49
+ curveTo(2.2633f, 14.6833f, 2.0007f, 13.3833f, 2.0f, 12.0f)
50
+ curveTo(2.0f, 10.6167f, 2.2627f, 9.3167f, 2.788f, 8.1f)
51
+ curveTo(3.3133f, 6.8833f, 4.0257f, 5.825f, 4.925f, 4.925f)
52
+ curveTo(5.825f, 4.025f, 6.8833f, 3.3127f, 8.1f, 2.788f)
53
+ curveTo(9.3167f, 2.2633f, 10.6167f, 2.0007f, 12.0f, 2.0f)
54
+ curveTo(13.3833f, 2.0f, 14.6833f, 2.2627f, 15.9f, 2.788f)
55
+ curveTo(17.1167f, 3.3133f, 18.175f, 4.0257f, 19.075f, 4.925f)
56
+ curveTo(19.975f, 5.825f, 20.6877f, 6.8833f, 21.213f, 8.1f)
57
+ curveTo(21.7383f, 9.3167f, 22.0007f, 10.6167f, 22.0f, 12.0f)
58
+ curveTo(22.0f, 13.3833f, 21.7373f, 14.6833f, 21.212f, 15.9f)
59
+ curveTo(20.6867f, 17.1167f, 19.9743f, 18.175f, 19.075f, 19.075f)
60
+ curveTo(18.175f, 19.975f, 17.1167f, 20.6877f, 15.9f, 21.213f)
61
+ curveTo(14.6833f, 21.7383f, 13.3833f, 22.0007f, 12.0f, 22.0f)
62
+ close()
63
+ moveTo(12.0f, 20.0f)
64
+ curveTo(14.2333f, 20.0f, 16.125f, 19.225f, 17.675f, 17.675f)
65
+ curveTo(19.225f, 16.125f, 20.0f, 14.2333f, 20.0f, 12.0f)
66
+ curveTo(20.0f, 9.7667f, 19.225f, 7.875f, 17.675f, 6.325f)
67
+ curveTo(16.125f, 4.775f, 14.2333f, 4.0f, 12.0f, 4.0f)
68
+ curveTo(9.7667f, 4.0f, 7.875f, 4.775f, 6.325f, 6.325f)
69
+ curveTo(4.775f, 7.875f, 4.0f, 9.7667f, 4.0f, 12.0f)
70
+ curveTo(4.0f, 14.2333f, 4.775f, 16.125f, 6.325f, 17.675f)
71
+ curveTo(7.875f, 19.225f, 9.7667f, 20.0f, 12.0f, 20.0f)
72
+ close()
73
+ }
74
+ }
75
+ .build()
76
+ return checkCircleOutline!!
77
+ }
78
+
79
+ private var checkCircleOutline: ImageVector? = null
@@ -0,0 +1,92 @@
1
+ package ly.img.editor.configuration.video.iconPack
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import androidx.compose.ui.graphics.Color
5
+ import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
6
+ import androidx.compose.ui.graphics.SolidColor
7
+ import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
8
+ import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
9
+ import androidx.compose.ui.graphics.vector.ImageVector
10
+ import androidx.compose.ui.graphics.vector.ImageVector.Builder
11
+ import androidx.compose.ui.graphics.vector.path
12
+ import androidx.compose.ui.tooling.preview.Preview
13
+ import androidx.compose.ui.unit.dp
14
+
15
+ /**
16
+ * Error with outline icon
17
+ */
18
+ val IconPack.ErrorOutline: ImageVector
19
+ get() {
20
+ if (errorOutline != null) {
21
+ return errorOutline!!
22
+ }
23
+ errorOutline = Builder(
24
+ name = "ErrorOutline",
25
+ defaultWidth = 24.0.dp,
26
+ defaultHeight = 24.0.dp,
27
+ viewportWidth = 24.0f,
28
+ viewportHeight = 24.0f,
29
+ ).apply {
30
+ path(
31
+ fill = SolidColor(Color(0xFF49454F)),
32
+ stroke = null,
33
+ strokeLineWidth = 0.0f,
34
+ strokeLineCap = Butt,
35
+ strokeLineJoin = Miter,
36
+ strokeLineMiter = 4.0f,
37
+ pathFillType = NonZero,
38
+ ) {
39
+ moveTo(12.0f, 17.0f)
40
+ curveTo(12.2833f, 17.0f, 12.521f, 16.904f, 12.713f, 16.712f)
41
+ curveTo(12.9043f, 16.5207f, 13.0f, 16.2833f, 13.0f, 16.0f)
42
+ curveTo(13.0f, 15.7167f, 12.9043f, 15.479f, 12.713f, 15.287f)
43
+ curveTo(12.521f, 15.0957f, 12.2833f, 15.0f, 12.0f, 15.0f)
44
+ curveTo(11.7167f, 15.0f, 11.4793f, 15.0957f, 11.288f, 15.287f)
45
+ curveTo(11.096f, 15.479f, 11.0f, 15.7167f, 11.0f, 16.0f)
46
+ curveTo(11.0f, 16.2833f, 11.096f, 16.5207f, 11.288f, 16.712f)
47
+ curveTo(11.4793f, 16.904f, 11.7167f, 17.0f, 12.0f, 17.0f)
48
+ close()
49
+ moveTo(11.0f, 13.0f)
50
+ horizontalLineTo(13.0f)
51
+ verticalLineTo(7.0f)
52
+ horizontalLineTo(11.0f)
53
+ verticalLineTo(13.0f)
54
+ close()
55
+ moveTo(12.0f, 22.0f)
56
+ curveTo(10.6167f, 22.0f, 9.3167f, 21.7373f, 8.1f, 21.212f)
57
+ curveTo(6.8833f, 20.6873f, 5.825f, 19.975f, 4.925f, 19.075f)
58
+ curveTo(4.025f, 18.175f, 3.3127f, 17.1167f, 2.788f, 15.9f)
59
+ curveTo(2.2627f, 14.6833f, 2.0f, 13.3833f, 2.0f, 12.0f)
60
+ curveTo(2.0f, 10.6167f, 2.2627f, 9.3167f, 2.788f, 8.1f)
61
+ curveTo(3.3127f, 6.8833f, 4.025f, 5.825f, 4.925f, 4.925f)
62
+ curveTo(5.825f, 4.025f, 6.8833f, 3.3123f, 8.1f, 2.787f)
63
+ curveTo(9.3167f, 2.2623f, 10.6167f, 2.0f, 12.0f, 2.0f)
64
+ curveTo(13.3833f, 2.0f, 14.6833f, 2.2623f, 15.9f, 2.787f)
65
+ curveTo(17.1167f, 3.3123f, 18.175f, 4.025f, 19.075f, 4.925f)
66
+ curveTo(19.975f, 5.825f, 20.6873f, 6.8833f, 21.212f, 8.1f)
67
+ curveTo(21.7373f, 9.3167f, 22.0f, 10.6167f, 22.0f, 12.0f)
68
+ curveTo(22.0f, 13.3833f, 21.7373f, 14.6833f, 21.212f, 15.9f)
69
+ curveTo(20.6873f, 17.1167f, 19.975f, 18.175f, 19.075f, 19.075f)
70
+ curveTo(18.175f, 19.975f, 17.1167f, 20.6873f, 15.9f, 21.212f)
71
+ curveTo(14.6833f, 21.7373f, 13.3833f, 22.0f, 12.0f, 22.0f)
72
+ close()
73
+ moveTo(12.0f, 20.0f)
74
+ curveTo(14.2333f, 20.0f, 16.125f, 19.225f, 17.675f, 17.675f)
75
+ curveTo(19.225f, 16.125f, 20.0f, 14.2333f, 20.0f, 12.0f)
76
+ curveTo(20.0f, 9.7667f, 19.225f, 7.875f, 17.675f, 6.325f)
77
+ curveTo(16.125f, 4.775f, 14.2333f, 4.0f, 12.0f, 4.0f)
78
+ curveTo(9.7667f, 4.0f, 7.875f, 4.775f, 6.325f, 6.325f)
79
+ curveTo(4.775f, 7.875f, 4.0f, 9.7667f, 4.0f, 12.0f)
80
+ curveTo(4.0f, 14.2333f, 4.775f, 16.125f, 6.325f, 17.675f)
81
+ curveTo(7.875f, 19.225f, 9.7667f, 20.0f, 12.0f, 20.0f)
82
+ close()
83
+ }
84
+ }.build()
85
+ return errorOutline!!
86
+ }
87
+
88
+ private var errorOutline: ImageVector? = null
89
+
90
+ @Preview
91
+ @Composable
92
+ private fun Preview() = IconPack.ErrorOutline.IconPreview()
@@ -0,0 +1,14 @@
1
+ package ly.img.editor.configuration.video.iconPack
2
+
3
+ import androidx.compose.material3.Icon
4
+ import androidx.compose.material3.MaterialTheme
5
+ import androidx.compose.runtime.Composable
6
+ import androidx.compose.ui.graphics.vector.ImageVector
7
+
8
+ /**
9
+ * Icon pack of the starter kit to access all the icons.
10
+ */
11
+ object IconPack
12
+
13
+ @Composable
14
+ internal fun ImageVector.IconPreview() = Icon(this, contentDescription = null, tint = MaterialTheme.colorScheme.onPrimary)
@@ -0,0 +1,39 @@
1
+ package ly.img.editor.configuration.video.model
2
+
3
+ import androidx.annotation.FloatRange
4
+ import ly.img.engine.MimeType
5
+ import java.io.File
6
+
7
+ /**
8
+ * The export status of the starter kit.
9
+ */
10
+ sealed interface ExportStatus {
11
+ /**
12
+ * State when the export is active.
13
+ *
14
+ * @param progress the progress of the export.
15
+ */
16
+ data class Loading(
17
+ @FloatRange(from = 0.0, to = 1.0) val progress: Float,
18
+ ) : ExportStatus
19
+
20
+ /**
21
+ * State when the export is successfully completed.
22
+ *
23
+ * @param file the file where the exported content is written to.
24
+ * @param mimeType the mime type of the exported content.
25
+ */
26
+ data class Success(
27
+ val file: File,
28
+ val mimeType: MimeType = MimeType.MP4,
29
+ ) : ExportStatus
30
+
31
+ /**
32
+ * State when the export is completed with an exception.
33
+ *
34
+ * @param exception the exception that was thrown during the export.
35
+ */
36
+ data class Error(
37
+ val exception: Exception,
38
+ ) : ExportStatus
39
+ }
@@ -82,7 +82,15 @@ import UIKit
82
82
  .first as? UIWindowScene {
83
83
  if let rootViewController = windowScene.windows
84
84
  .filter(\.isKeyWindow).first?.rootViewController {
85
- rootViewController.present(presentationController, animated: true, completion: nil)
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)
86
94
  }
87
95
  }
88
96
  }
@@ -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
+ }
@@ -0,0 +1,116 @@
1
+ import IMGLYEditor
2
+ import IMGLYEngine
3
+
4
+ // MARK: - Default OnChanged
5
+
6
+ extension ApparelEditorConfiguration {
7
+ /// The default `onChanged` handler.
8
+ static var defaultOnChangedHandler: OnChanged.Handler {
9
+ { update, context, _ in
10
+ switch update {
11
+ case let .gestureActive(_, newValue):
12
+ try Self.showOutline(newValue, engine: context.engine)
13
+
14
+ case let .page(_, newValue):
15
+ // Deselect all blocks.
16
+ try context.engine.block.findAllSelected().forEach {
17
+ try context.engine.block.setSelected($0, selected: false)
18
+ }
19
+
20
+ // Reset history.
21
+ let oldHistory = context.engine.editor.getActiveHistory()
22
+ let newHistory = context.engine.editor.createHistory()
23
+ context.engine.editor.setActiveHistory(newHistory)
24
+ context.engine.editor.destroyHistory(oldHistory)
25
+ try context.engine.editor.addUndoStep()
26
+
27
+ if let stack = try? context.engine.block.find(byType: .stack).first {
28
+ try context.engine.block.setEnum(stack, property: "stack/axis", value: "Depth")
29
+ }
30
+
31
+ let pages = try context.engine.scene.getPages()
32
+ for (i, block) in pages.enumerated() {
33
+ let isVisibilityEnabled = try context.engine.block.isScopeEnabled(block, key: "layer/visibility")
34
+ try context.engine.block.setScopeEnabled(block, key: "layer/visibility", enabled: true)
35
+ try context.engine.block.setVisible(block, visible: i == newValue)
36
+ try context.engine.block.setScopeEnabled(block, key: "layer/visibility", enabled: isVisibilityEnabled)
37
+ }
38
+
39
+ case let .viewMode(_, state):
40
+ if state.editorViewMode == .edit {
41
+ try Self.setupPage(context)
42
+ } else if state.editorViewMode == .preview {
43
+ guard let scene = try context.engine.block.find(byType: .scene).first
44
+ else { throw EditorError("No scene found.") }
45
+
46
+ Task {
47
+ // Disable camera clamping.
48
+ if try context.engine.scene.unstable_isCameraZoomClampingEnabled(scene) {
49
+ try context.engine.scene.unstable_disableCameraZoomClamping()
50
+ }
51
+ if try context.engine.scene.unstable_isCameraPositionClampingEnabled(scene) {
52
+ try context.engine.scene.unstable_disableCameraPositionClamping()
53
+ }
54
+
55
+ // Zoom to the backdrop image.
56
+ try await context.engine.scene.zoom(
57
+ to: Self.getBackdropImage(engine: context.engine),
58
+ paddingLeft: Float(state.insets?.leading ?? 0),
59
+ paddingTop: Float(state.insets?.top ?? 0),
60
+ paddingRight: Float(state.insets?.trailing ?? 0),
61
+ paddingBottom: Float(state.insets?.bottom ?? 0),
62
+ )
63
+
64
+ // Deselect all blocks.
65
+ let selectedBlocks = context.engine.block.findAllSelected()
66
+ try selectedBlocks.forEach { try context.engine.block.setSelected($0, selected: false) }
67
+
68
+ try Self.setupPage(context)
69
+ }
70
+ } else {
71
+ try OnChanged.default(update, context)
72
+ }
73
+
74
+ default:
75
+ try OnChanged.default(update, context)
76
+ }
77
+ }
78
+ }
79
+
80
+ // MARK: - Helpers
81
+
82
+ /// Gets the backdrop image from the scene.
83
+ /// The backdrop image is the only image that is a direct child of the scene block.
84
+ static func getBackdropImage(engine: Engine) throws -> DesignBlockID {
85
+ guard let scene = try engine.scene.get() else { throw EditorError("No scene found.") }
86
+ let childIDs = try engine.block.getChildren(scene)
87
+ let imageID = try childIDs.first {
88
+ guard try engine.block.getType($0) == DesignBlockType.graphic.rawValue,
89
+ try engine.block.supportsFill($0)
90
+ else {
91
+ return false
92
+ }
93
+ return try engine.block.getType(try engine.block.getFill($0)) == FillType.image.rawValue
94
+ }
95
+ guard let imageID else {
96
+ throw EditorError("No backdrop image found.")
97
+ }
98
+ return imageID
99
+ }
100
+
101
+ /// Configures the current page for proper apparel editing.
102
+ static func setupPage(_ context: OnChanged.Context) throws {
103
+ guard let page = try context.engine.scene.getCurrentPage() else {
104
+ throw EditorError("No scene found.")
105
+ }
106
+
107
+ let fillChangeEnabled = try context.engine.block.isScopeEnabled(page, key: "fill/change")
108
+ let layerClippingEnabled = try context.engine.block.isScopeEnabled(page, key: "layer/clipping")
109
+ try context.engine.editor.setSettingBool("page/dimOutOfPageAreas", value: false)
110
+ try context.engine.block.setClipped(page, clipped: true)
111
+ try context.engine.block.setBool(page, property: "fill/enabled", value: false)
112
+ try showOutline(false, engine: context.engine)
113
+ try context.engine.block.setScopeEnabled(page, key: "fill/change", enabled: fillChangeEnabled)
114
+ try context.engine.block.setScopeEnabled(page, key: "layer/clipping", enabled: layerClippingEnabled)
115
+ }
116
+ }
@@ -0,0 +1,197 @@
1
+ import CoreGraphics
2
+ import Foundation
3
+ import IMGLYEditor
4
+ import IMGLYEngine
5
+
6
+ // MARK: - Default OnCreate
7
+
8
+ public extension ApparelEditorConfiguration {
9
+ /// The default `onCreate` handler.
10
+ internal static var defaultOnCreateHandler: OnCreate.Handler {
11
+ { engine, _ in
12
+ try await defaultOnCreate()(engine)
13
+ }
14
+ }
15
+
16
+ /// Default apparel editor specific `OnCreate.Callback` implementation with solution specific settings, scene
17
+ /// and editor creation setup.
18
+ /// - Parameters:
19
+ /// - preCreateScene: Callback to do any pre scene loading tasks such as applying settings.
20
+ /// Defaults to `ApparelEditorConfiguration.defaultPreCreateScene`.
21
+ /// - createScene: Callback to load/create the scene and load asset sources. Defaults to
22
+ /// `ApparelEditorConfiguration.defaultCreateScene`.
23
+ /// - loadAssetSources: Callback to load any asset sources. Defaults to
24
+ /// `ApparelEditorConfiguration.defaultLoadAssetSources`.
25
+ /// - postCreateScene: Callback to do any post scene loading tasks. Defaults to
26
+ /// `ApparelEditorConfiguration.defaultPostCreateScene`.
27
+ /// - Returns: A composed `OnCreate.Callback`that sequentially executes all three initialization phases.
28
+ static func defaultOnCreate(
29
+ preCreateScene: @escaping OnCreate.Callback = defaultPreCreateScene,
30
+ createScene: @escaping OnCreate.Callback = defaultCreateScene,
31
+ loadAssetSources: @escaping OnCreate.Callback = defaultLoadAssetSources,
32
+ postCreateScene: @escaping OnCreate.Callback = defaultPostCreateScene,
33
+ ) -> OnCreate.Callback {
34
+ { engine in
35
+ try await preCreateScene(engine)
36
+ try await createScene(engine)
37
+ try await loadAssetSources(engine)
38
+ try await postCreateScene(engine)
39
+ }
40
+ }
41
+
42
+ /// Configures engine settings before scene loading.
43
+ ///
44
+ /// Sets editor role, touch gestures, camera clamping, and global scopes.
45
+ static let defaultPreCreateScene: OnCreate.Callback = { engine in
46
+ try engine.editor.setRole("Adopter")
47
+ try engine.editor.setSettingEnum("camera/clamping/overshootMode", value: "Center")
48
+
49
+ let highlightColor: IMGLYEngine.Color = try engine.editor.getSettingColor("highlightColor")
50
+ try engine.editor.setSettingColor("placeholderHighlightColor", color: highlightColor)
51
+
52
+ try engine.editor.setSettingBool("touch/dragStartCanSelect", value: false)
53
+ try engine.editor.setSettingEnum("touch/pinchAction", value: "Zoom")
54
+ try engine.editor.setSettingEnum("touch/rotateAction", value: "None")
55
+
56
+ try ([
57
+ "appearance/adjustments", "appearance/filter", "appearance/effect",
58
+ "appearance/blur", "appearance/shadow",
59
+ "editor/select",
60
+ "fill/change", "fill/changeType",
61
+ "layer/crop", "layer/move", "layer/resize", "layer/rotate", "layer/flip",
62
+ "layer/opacity", "layer/blendMode", "layer/visibility", "layer/clipping",
63
+ "lifecycle/destroy", "lifecycle/duplicate",
64
+ "stroke/change", "shape/change",
65
+ "text/edit", "text/character",
66
+ ]).forEach { scope in
67
+ try engine.editor.setGlobalScope(key: scope, value: .defer)
68
+ }
69
+ }
70
+
71
+ /// Loads the built-in empty apparel scene.
72
+ static let defaultCreateScene: OnCreate.Callback = { engine in
73
+ // highlight-starter-kit-on-create-scene
74
+ let sceneURL = Bundle(for: ApparelEditorConfiguration.self).url(
75
+ forResource: "apparel-ui-b-empty",
76
+ withExtension: "scene",
77
+ )!
78
+ try await engine.scene.load(from: sceneURL)
79
+ // highlight-starter-kit-on-create-scene
80
+ }
81
+
82
+ /// Registers all default and demo asset sources, plus text and photo roll sources.
83
+ static let defaultLoadAssetSources: OnCreate.Callback = { engine in
84
+ // highlight-starter-kit-on-load-asset-sources
85
+ let assetSources: [String: URL] = [
86
+ Engine.DefaultAssetSource.sticker.rawValue: Engine.assetBaseURL,
87
+ Engine.DefaultAssetSource.vectorPath.rawValue: Engine.assetBaseURL,
88
+ Engine.DefaultAssetSource.filterLut.rawValue: Engine.assetBaseURL,
89
+ Engine.DefaultAssetSource.filterDuotone.rawValue: Engine.assetBaseURL,
90
+ Engine.DefaultAssetSource.colorsDefaultPalette.rawValue: Engine.assetBaseURL,
91
+ Engine.DefaultAssetSource.effect.rawValue: Engine.assetBaseURL,
92
+ Engine.DefaultAssetSource.blur.rawValue: Engine.assetBaseURL,
93
+ Engine.DefaultAssetSource.typeface.rawValue: Engine.assetBaseURL,
94
+ Engine.DefaultAssetSource.cropPresets.rawValue: Engine.assetBaseURL,
95
+ Engine.DefaultAssetSource.pagePresets.rawValue: Engine.assetBaseURL,
96
+
97
+ Engine.DemoAssetSource.image.rawValue: Engine.assetBaseURL,
98
+ Engine.DemoAssetSource.textComponents.rawValue: Engine.assetBaseURL,
99
+ ]
100
+
101
+ try await withThrowingTaskGroup(of: Void.self) { group in
102
+ for assetSource in assetSources {
103
+ group.addTask {
104
+ try await engine.populateAssetSource(id: assetSource.key, baseURL: assetSource.value)
105
+ }
106
+ }
107
+ try await group.waitForAll()
108
+ }
109
+
110
+ try engine.asset.addLocalSource(
111
+ sourceID: Engine.DemoAssetSource.imageUpload.rawValue,
112
+ supportedMimeTypes: Engine.DemoAssetSource.imageUpload.mimeTypes,
113
+ )
114
+
115
+ try await engine.asset.addSource(TextAssetSource(engine: engine))
116
+ try engine.asset.addSource(PhotoRollAssetSource(engine: engine))
117
+ // highlight-starter-kit-on-load-asset-sources
118
+ }
119
+
120
+ /// Configures apparel-specific outline and page clipping behavior.
121
+ static let defaultPostCreateScene: OnCreate.Callback = { engine in
122
+ guard let scene = try engine.block.find(byType: .scene).first,
123
+ let page = try engine.scene.getPages().first
124
+ else {
125
+ return
126
+ }
127
+
128
+ // Add outline block for apparel shape visualization.
129
+ _ = try ApparelEditorConfiguration.addOutline(
130
+ "always-on-top-page-outline", for: page, to: scene, engine: engine,
131
+ )
132
+ try ApparelEditorConfiguration.showOutline(false, engine: engine)
133
+
134
+ // Temporarily enable scopes to configure page clipping.
135
+ let isFillChangeEnabled = try engine.block.isScopeEnabled(page, key: "fill/change")
136
+ let isLayerClippingEnabled = try engine.block.isScopeEnabled(page, key: "layer/clipping")
137
+ try engine.block.setScopeEnabled(page, key: "fill/change", enabled: true)
138
+ try engine.block.setScopeEnabled(page, key: "layer/clipping", enabled: true)
139
+
140
+ // Configure page appearance and clipping for apparel editing.
141
+ try engine.editor.setSettingBool("page/dimOutOfPageAreas", value: false)
142
+ try engine.block.setClipped(page, clipped: true)
143
+ try engine.block.setBool(page, property: "fill/enabled", value: false)
144
+ try ApparelEditorConfiguration.showOutline(false, engine: engine)
145
+
146
+ // Restore original scope states.
147
+ try engine.block.setScopeEnabled(page, key: "fill/change", enabled: isFillChangeEnabled)
148
+ try engine.block.setScopeEnabled(page, key: "layer/clipping", enabled: isLayerClippingEnabled)
149
+ }
150
+
151
+ // MARK: - Helpers
152
+
153
+ /// Adds an outline block for apparel shape visualization.
154
+ internal static func addOutline(
155
+ _ name: String? = nil,
156
+ for id: DesignBlockID,
157
+ to parent: DesignBlockID,
158
+ engine: Engine,
159
+ ) throws -> DesignBlockID {
160
+ let outline = try engine.block.create(.graphic)
161
+ let rect = try engine.block.createShape(.rect)
162
+ try engine.block.setShape(outline, shape: rect)
163
+
164
+ let height = try engine.block.getHeight(id)
165
+ let width = try engine.block.getWidth(id)
166
+
167
+ if let name {
168
+ try engine.block.setName(outline, name: name)
169
+ }
170
+ try engine.block.setHeightMode(outline, mode: .absolute)
171
+ try engine.block.setHeight(outline, value: height)
172
+ try engine.block.setWidthMode(outline, mode: .absolute)
173
+ try engine.block.setWidth(outline, value: width)
174
+ try engine.block.appendChild(to: parent, child: outline)
175
+
176
+ try engine.block.setBool(outline, property: "fill/enabled", value: false)
177
+ try engine.block.setBool(outline, property: "stroke/enabled", value: true)
178
+ try engine.block.setStrokeStyle(outline, style: .dotted)
179
+ try engine.block.setStrokeWidth(outline, width: 1.0)
180
+ try engine.block.setBlendMode(outline, mode: .difference)
181
+ try engine.block.setScopeEnabled(outline, key: "editor/select", enabled: false)
182
+ if let color = Color(cgColor: CGColor.imgly.white) {
183
+ try engine.block.setColor(outline, property: "stroke/color", color: color)
184
+ }
185
+ return outline
186
+ }
187
+
188
+ /// Shows or hides the outline block.
189
+ internal static func showOutline(_ isVisible: Bool, engine: Engine) throws {
190
+ guard let outline = engine.block.find(byName: "always-on-top-page-outline").first else {
191
+ throw EditorError("No outline block was found.")
192
+ }
193
+ try engine.block.setVisible(outline, visible: isVisible)
194
+ // Workaround: Trigger opacity to force refresh on "fast" devices.
195
+ try engine.block.setOpacity(outline, value: isVisible ? 1 : 0)
196
+ }
197
+ }
@@ -0,0 +1,29 @@
1
+ import IMGLYEditor
2
+ import IMGLYEngine
3
+ import UniformTypeIdentifiers
4
+
5
+ // MARK: - Default OnExport
6
+
7
+ extension ApparelEditorConfiguration {
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, _ 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: .pdf) { 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: .pdf)
24
+ try data.write(to: url, options: [.atomic])
25
+ eventHandler.send(.shareFile(url))
26
+ // highlight-starter-kit-on-export
27
+ }
28
+ }
29
+ }