@imgly/editor-react-native 1.80.0-rc.1 → 1.81.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -1
- package/android/src/main/assets/ly.img.memories.style/content.json +50 -0
- package/android/src/main/assets/ly.img.memories.style/thumbnails/bubblegum.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/thumbnails/hologram.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/thumbnails/noir.png +0 -0
- package/android/src/main/assets/ly.img.memories.style/videos/bubblegum.mp4 +0 -0
- package/android/src/main/assets/ly.img.memories.style/videos/hologram.mp4 +0 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesApp.kt +77 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesConfiguration.kt +38 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesEditor.kt +79 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/MemoriesViewModel.kt +469 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/callback/OnCreate.kt +69 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/callback/OnExport.kt +46 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/BottomPanel.kt +151 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/Dock.kt +145 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/ExportOverlay.kt +229 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/NavigationBar.kt +80 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/component/Overlay.kt +138 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/extension/EditorScopeExt.kt +111 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/AddPhotoAlternate.kt +79 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/ArrowForward.kt +45 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Audiotrack.kt +43 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Check.kt +39 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/CheckCircle.kt +44 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Close.kt +43 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Delete.kt +54 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/DeleteOutline.kt +53 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Fullscreen.kt +74 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Image.kt +51 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Info.kt +48 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Pause.kt +46 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/PlayArrow.kt +38 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/RepeatOff.kt +80 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/RepeatOn.kt +59 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/SkipPrevious.kt +46 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Sort.kt +55 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Style.kt +59 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/Title.kt +43 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/TouchTriple.kt +134 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/VolumeDown.kt +48 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/iconPack/VolumeUp.kt +60 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/ExportStatus.kt +20 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/ImageItem.kt +8 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/model/TimelineImage.kt +18 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Events.kt +59 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Playback.kt +29 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/SceneSetup.kt +79 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Timeline.kt +27 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/Title.kt +162 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/scene/TrackEditor.kt +740 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/screen/ImageSelectionScreen.kt +387 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/screen/LoadingScreen.kt +258 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/FilterStylesSheet.kt +167 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/FilterStylesSheetType.kt +21 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/sheet/VolumeSheet.kt +104 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/StyleApplier.kt +220 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/StyleAssetSource.kt +43 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/style/VideoStyle.kt +118 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Animations.kt +58 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Constants.kt +20 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/ImageDate.kt +81 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/util/Utils.kt +27 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/CenteredAddImageButton.kt +82 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/DraggableImageItem.kt +145 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/FullscreenVideoControls.kt +136 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageGrid.kt +122 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageGridOverlay.kt +149 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageTimelineStrip.kt +323 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ImageToolbar.kt +401 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/ReorderableGridState.kt +183 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoControlPanel.kt +180 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoThumbnail.kt +110 -0
- package/android/src/main/kotlin/ly/img/editor/configuration/video/callback/OnCreate.kt +0 -7
- package/android/src/main/kotlin/ly/img/editor/configuration/video/component/InspectorBar.kt +2 -0
- package/ios/StarterKits/Video/callbacks/OnCreate+Video.swift +1 -1
- package/ios/StarterKits/Video/components/Dock+Video.swift +1 -0
- package/ios/StarterKits/Video/components/InspectorBar+Video.swift +4 -0
- package/package.json +1 -1
- package/src/NativeIMGLYEditor.ts +1 -1
package/android/src/main/kotlin/ly/img/editor/configuration/memories/widget/VideoControlPanel.kt
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
package ly.img.editor.configuration.memories.widget
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.clickable
|
|
4
|
+
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
5
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
6
|
+
import androidx.compose.foundation.layout.Box
|
|
7
|
+
import androidx.compose.foundation.layout.Column
|
|
8
|
+
import androidx.compose.foundation.layout.Row
|
|
9
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
10
|
+
import androidx.compose.foundation.layout.padding
|
|
11
|
+
import androidx.compose.foundation.layout.size
|
|
12
|
+
import androidx.compose.material.ripple.rememberRipple
|
|
13
|
+
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
14
|
+
import androidx.compose.material3.Icon
|
|
15
|
+
import androidx.compose.material3.MaterialTheme
|
|
16
|
+
import androidx.compose.runtime.Composable
|
|
17
|
+
import androidx.compose.runtime.getValue
|
|
18
|
+
import androidx.compose.runtime.mutableStateOf
|
|
19
|
+
import androidx.compose.runtime.remember
|
|
20
|
+
import androidx.compose.runtime.setValue
|
|
21
|
+
import androidx.compose.ui.Alignment
|
|
22
|
+
import androidx.compose.ui.Modifier
|
|
23
|
+
import androidx.compose.ui.tooling.preview.Preview
|
|
24
|
+
import androidx.compose.ui.unit.dp
|
|
25
|
+
import ly.img.editor.configuration.memories.iconPack.Fullscreen
|
|
26
|
+
import ly.img.editor.configuration.memories.iconPack.Pause
|
|
27
|
+
import ly.img.editor.configuration.memories.iconPack.PlayArrow
|
|
28
|
+
import ly.img.editor.configuration.memories.iconPack.RepeatOff
|
|
29
|
+
import ly.img.editor.configuration.memories.iconPack.RepeatOn
|
|
30
|
+
import ly.img.editor.configuration.memories.iconPack.SkipPrevious
|
|
31
|
+
import ly.img.editor.configuration.memories.iconPack.VolumeUp
|
|
32
|
+
import ly.img.editor.core.iconpack.IconPack
|
|
33
|
+
|
|
34
|
+
@OptIn(ExperimentalMaterial3Api::class)
|
|
35
|
+
@Composable
|
|
36
|
+
fun VideoControlPanel(
|
|
37
|
+
isPlaying: Boolean,
|
|
38
|
+
isLooping: Boolean,
|
|
39
|
+
onPlayPauseClick: () -> Unit,
|
|
40
|
+
onRestartClick: () -> Unit,
|
|
41
|
+
onLoopClick: () -> Unit,
|
|
42
|
+
onVolumeClick: () -> Unit,
|
|
43
|
+
onFullscreenClick: () -> Unit,
|
|
44
|
+
modifier: Modifier = Modifier,
|
|
45
|
+
) {
|
|
46
|
+
Column(
|
|
47
|
+
modifier = modifier.fillMaxWidth(),
|
|
48
|
+
) {
|
|
49
|
+
Box(
|
|
50
|
+
modifier = Modifier
|
|
51
|
+
.fillMaxWidth()
|
|
52
|
+
.padding(horizontal = 12.dp, vertical = 0.dp),
|
|
53
|
+
) {
|
|
54
|
+
// Left: Volume button (where the time used to be)
|
|
55
|
+
Icon(
|
|
56
|
+
imageVector = IconPack.VolumeUp,
|
|
57
|
+
contentDescription = "Volume",
|
|
58
|
+
tint = MaterialTheme.colorScheme.onBackground,
|
|
59
|
+
modifier = Modifier
|
|
60
|
+
.align(Alignment.CenterStart)
|
|
61
|
+
.size(32.dp)
|
|
62
|
+
.clickable(
|
|
63
|
+
interactionSource = remember { MutableInteractionSource() },
|
|
64
|
+
indication = rememberRipple(
|
|
65
|
+
bounded = false,
|
|
66
|
+
radius = 20.dp,
|
|
67
|
+
),
|
|
68
|
+
) { onVolumeClick() }
|
|
69
|
+
.padding(vertical = 4.dp),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Center: Play controls
|
|
73
|
+
Box(
|
|
74
|
+
modifier = Modifier.align(Alignment.Center),
|
|
75
|
+
contentAlignment = Alignment.Center,
|
|
76
|
+
) {
|
|
77
|
+
Row(
|
|
78
|
+
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
|
79
|
+
verticalAlignment = Alignment.CenterVertically,
|
|
80
|
+
) {
|
|
81
|
+
// Restart button
|
|
82
|
+
Icon(
|
|
83
|
+
imageVector = IconPack.SkipPrevious,
|
|
84
|
+
contentDescription = "Restart",
|
|
85
|
+
tint = MaterialTheme.colorScheme.onBackground,
|
|
86
|
+
modifier = Modifier
|
|
87
|
+
.size(48.dp)
|
|
88
|
+
.clickable(
|
|
89
|
+
interactionSource = remember { MutableInteractionSource() },
|
|
90
|
+
indication = rememberRipple(
|
|
91
|
+
bounded = false,
|
|
92
|
+
radius = 28.dp,
|
|
93
|
+
),
|
|
94
|
+
) { onRestartClick() }
|
|
95
|
+
.padding(vertical = 8.dp),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
// Play/Pause button
|
|
99
|
+
Icon(
|
|
100
|
+
imageVector = if (isPlaying) {
|
|
101
|
+
IconPack.Pause
|
|
102
|
+
} else {
|
|
103
|
+
IconPack.PlayArrow
|
|
104
|
+
},
|
|
105
|
+
contentDescription = if (isPlaying) "Pause" else "Play",
|
|
106
|
+
tint = MaterialTheme.colorScheme.onBackground,
|
|
107
|
+
modifier = Modifier
|
|
108
|
+
.size(48.dp)
|
|
109
|
+
.clickable(
|
|
110
|
+
interactionSource = remember { MutableInteractionSource() },
|
|
111
|
+
indication = rememberRipple(
|
|
112
|
+
bounded = false,
|
|
113
|
+
radius = 28.dp,
|
|
114
|
+
),
|
|
115
|
+
) { onPlayPauseClick() }
|
|
116
|
+
.padding(vertical = 8.dp),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
// Loop button
|
|
120
|
+
Icon(
|
|
121
|
+
imageVector = if (isLooping) IconPack.RepeatOn else IconPack.RepeatOff,
|
|
122
|
+
contentDescription = if (isLooping) "Disable Loop" else "Enable Loop",
|
|
123
|
+
tint = if (isLooping) {
|
|
124
|
+
MaterialTheme.colorScheme.primary
|
|
125
|
+
} else {
|
|
126
|
+
MaterialTheme.colorScheme.onBackground
|
|
127
|
+
},
|
|
128
|
+
modifier = Modifier
|
|
129
|
+
.size(48.dp)
|
|
130
|
+
.clickable(
|
|
131
|
+
interactionSource = remember { MutableInteractionSource() },
|
|
132
|
+
indication = rememberRipple(
|
|
133
|
+
bounded = false,
|
|
134
|
+
radius = 28.dp,
|
|
135
|
+
),
|
|
136
|
+
) { onLoopClick() }
|
|
137
|
+
.padding(vertical = 8.dp),
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Right: Fullscreen button (moved from the top navigation bar)
|
|
143
|
+
Icon(
|
|
144
|
+
imageVector = IconPack.Fullscreen,
|
|
145
|
+
contentDescription = "Fullscreen",
|
|
146
|
+
tint = MaterialTheme.colorScheme.onBackground,
|
|
147
|
+
modifier = Modifier
|
|
148
|
+
.align(Alignment.CenterEnd)
|
|
149
|
+
.size(32.dp)
|
|
150
|
+
.clickable(
|
|
151
|
+
interactionSource = remember { MutableInteractionSource() },
|
|
152
|
+
indication = rememberRipple(
|
|
153
|
+
bounded = false,
|
|
154
|
+
radius = 20.dp,
|
|
155
|
+
),
|
|
156
|
+
) { onFullscreenClick() }
|
|
157
|
+
.padding(vertical = 4.dp),
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@Preview(showBackground = true)
|
|
164
|
+
@Composable
|
|
165
|
+
fun VideoControlPanelPreview() {
|
|
166
|
+
var isPlaying by remember { mutableStateOf(false) }
|
|
167
|
+
var isLooping by remember { mutableStateOf(true) }
|
|
168
|
+
|
|
169
|
+
MaterialTheme {
|
|
170
|
+
VideoControlPanel(
|
|
171
|
+
isPlaying = isPlaying,
|
|
172
|
+
isLooping = isLooping,
|
|
173
|
+
onPlayPauseClick = { isPlaying = !isPlaying },
|
|
174
|
+
onRestartClick = { isPlaying = false },
|
|
175
|
+
onLoopClick = { isLooping = !isLooping },
|
|
176
|
+
onVolumeClick = { /* Volume control */ },
|
|
177
|
+
onFullscreenClick = { /* Enter fullscreen */ },
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
package ly.img.editor.configuration.memories.widget
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.media.MediaMetadataRetriever
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.util.LruCache
|
|
9
|
+
import androidx.compose.runtime.Composable
|
|
10
|
+
import androidx.compose.runtime.getValue
|
|
11
|
+
import androidx.compose.runtime.produceState
|
|
12
|
+
import androidx.compose.ui.platform.LocalContext
|
|
13
|
+
import kotlinx.coroutines.Dispatchers
|
|
14
|
+
import kotlinx.coroutines.withContext
|
|
15
|
+
import java.io.File
|
|
16
|
+
import java.io.FileOutputStream
|
|
17
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
18
|
+
|
|
19
|
+
private const val ANDROID_ASSET_PREFIX = "file:///android_asset/"
|
|
20
|
+
|
|
21
|
+
// Small process-wide cache so scrolling / recomposition doesn't re-decode, and the grid and the
|
|
22
|
+
// timeline strip share frames for the same video.
|
|
23
|
+
private val thumbnailCache = LruCache<String, Bitmap>(16)
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns a single still frame from the middle of the video at [url] for use as a thumbnail, or
|
|
27
|
+
* null while it is still being decoded. Uses the platform [MediaMetadataRetriever] (no extra
|
|
28
|
+
* dependency) off the main thread, and caches the result by URL.
|
|
29
|
+
*
|
|
30
|
+
* Handles `content://` (picked media), `file://`, and bundled `file:///android_asset/...` URIs.
|
|
31
|
+
*/
|
|
32
|
+
@Composable
|
|
33
|
+
fun rememberVideoThumbnail(
|
|
34
|
+
url: String,
|
|
35
|
+
targetPx: Int = 256,
|
|
36
|
+
): Bitmap? {
|
|
37
|
+
val context = LocalContext.current
|
|
38
|
+
return produceState<Bitmap?>(initialValue = thumbnailCache.get(url), key1 = url) {
|
|
39
|
+
if (value != null) return@produceState
|
|
40
|
+
value = withContext(Dispatchers.IO) {
|
|
41
|
+
extractMiddleFrame(context, url, targetPx)?.also { thumbnailCache.put(url, it) }
|
|
42
|
+
}
|
|
43
|
+
}.value
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Cache of already-written thumbnail files (video URL -> file:// URI) so a repeated request reuses
|
|
47
|
+
// the PNG on disk instead of decoding another frame. Concurrent because several thumbnail requests
|
|
48
|
+
// run on Dispatchers.IO threads at once.
|
|
49
|
+
private val thumbnailFileCache = ConcurrentHashMap<String, String>()
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Extract the middle frame of the video at [url], write it to a PNG in the app cache, and return its
|
|
53
|
+
* `file://` URI (suitable for an engine image fill), or null if a frame can't be decoded. Cached by
|
|
54
|
+
* URL. Runs its decode + write off the main thread.
|
|
55
|
+
*/
|
|
56
|
+
suspend fun videoThumbnailFileUri(
|
|
57
|
+
context: Context,
|
|
58
|
+
url: String,
|
|
59
|
+
targetPx: Int = 512,
|
|
60
|
+
): String? {
|
|
61
|
+
thumbnailFileCache[url]?.let { cached ->
|
|
62
|
+
if (Uri.parse(cached).path?.let { File(it).exists() } == true) return cached
|
|
63
|
+
}
|
|
64
|
+
return withContext(Dispatchers.IO) {
|
|
65
|
+
val bitmap = extractMiddleFrame(context, url, targetPx) ?: return@withContext null
|
|
66
|
+
try {
|
|
67
|
+
val dir = File(context.cacheDir, "burst_thumbs").apply { mkdirs() }
|
|
68
|
+
val file = File(dir, "thumb_${url.hashCode()}.png")
|
|
69
|
+
FileOutputStream(file).use { bitmap.compress(Bitmap.CompressFormat.PNG, 90, it) }
|
|
70
|
+
Uri.fromFile(file).toString().also { thumbnailFileCache[url] = it }
|
|
71
|
+
} catch (e: Exception) {
|
|
72
|
+
null
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private fun extractMiddleFrame(
|
|
78
|
+
context: Context,
|
|
79
|
+
url: String,
|
|
80
|
+
targetPx: Int,
|
|
81
|
+
): Bitmap? {
|
|
82
|
+
val retriever = MediaMetadataRetriever()
|
|
83
|
+
return try {
|
|
84
|
+
if (url.startsWith(ANDROID_ASSET_PREFIX)) {
|
|
85
|
+
// Bundled assets aren't real files: open via an asset file descriptor.
|
|
86
|
+
context.assets.openFd(url.removePrefix(ANDROID_ASSET_PREFIX)).use { afd ->
|
|
87
|
+
retriever.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length)
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
retriever.setDataSource(context, Uri.parse(url))
|
|
91
|
+
}
|
|
92
|
+
val durationMs = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: 0L
|
|
93
|
+
val middleUs = (durationMs / 2) * 1000
|
|
94
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
95
|
+
// Decode straight to a small bitmap to keep memory low.
|
|
96
|
+
retriever.getScaledFrameAtTime(
|
|
97
|
+
middleUs,
|
|
98
|
+
MediaMetadataRetriever.OPTION_CLOSEST_SYNC,
|
|
99
|
+
targetPx,
|
|
100
|
+
targetPx,
|
|
101
|
+
)
|
|
102
|
+
} else {
|
|
103
|
+
retriever.getFrameAtTime(middleUs, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
|
|
104
|
+
}
|
|
105
|
+
} catch (e: Exception) {
|
|
106
|
+
null
|
|
107
|
+
} finally {
|
|
108
|
+
runCatching { retriever.release() }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -110,13 +110,6 @@ suspend fun VideoConfigurationBuilder.onLoadAssetSources() {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
// Required for animations
|
|
114
|
-
editorContext.engine.block.setMetadata(
|
|
115
|
-
block = requireNotNull(editorContext.engine.scene.get()),
|
|
116
|
-
key = "ly.img.defaultAssetSourcesBaseUri",
|
|
117
|
-
value = editorContext.baseUri.toString(),
|
|
118
|
-
)
|
|
119
|
-
|
|
120
113
|
// Load local asset sources
|
|
121
114
|
editorContext.engine.asset.addLocalSource(
|
|
122
115
|
sourceId = "ly.img.image.upload",
|
|
@@ -27,6 +27,7 @@ import ly.img.editor.core.component.rememberSplit
|
|
|
27
27
|
import ly.img.editor.core.component.rememberTextBackground
|
|
28
28
|
import ly.img.editor.core.component.rememberTextOnPath
|
|
29
29
|
import ly.img.editor.core.component.rememberTextPresets
|
|
30
|
+
import ly.img.editor.core.component.rememberTransition
|
|
30
31
|
import ly.img.editor.core.component.rememberVoiceover
|
|
31
32
|
import ly.img.editor.core.component.rememberVolume
|
|
32
33
|
|
|
@@ -50,6 +51,7 @@ fun VideoConfigurationBuilder.rememberInspectorBar() = InspectorBar.remember {
|
|
|
50
51
|
add { InspectorBar.Button.rememberClipSpeed() } // Video
|
|
51
52
|
add { InspectorBar.Button.rememberCrop() } // Video, Image
|
|
52
53
|
add { InspectorBar.Button.rememberAnimations() } // Video, Image, Sticker, Shape, Text
|
|
54
|
+
add { InspectorBar.Button.rememberTransition() } // Video, Image
|
|
53
55
|
add { InspectorBar.Button.rememberAdjustments() } // Video, Image
|
|
54
56
|
add { InspectorBar.Button.rememberFilter() } // Video, Image
|
|
55
57
|
add { InspectorBar.Button.rememberEffect() } // Video, Image
|
|
@@ -93,7 +93,7 @@ public extension VideoEditorConfiguration {
|
|
|
93
93
|
"ly.img.sticker", "ly.img.vector.shape", "ly.img.filter", "ly.img.color.palette",
|
|
94
94
|
"ly.img.effect", "ly.img.blur", "ly.img.typeface", "ly.img.crop.presets",
|
|
95
95
|
"ly.img.page.presets", "ly.img.text", "ly.img.text.styles", "ly.img.text.curves", "ly.img.text.components",
|
|
96
|
-
"ly.img.image", "ly.img.video", "ly.img.audio",
|
|
96
|
+
"ly.img.image", "ly.img.video", "ly.img.audio", "ly.img.caption.presets",
|
|
97
97
|
]
|
|
98
98
|
try await withThrowingTaskGroup(of: String.self) { group in
|
|
99
99
|
for id in sourceIDs {
|
|
@@ -19,6 +19,7 @@ extension VideoEditorConfiguration {
|
|
|
19
19
|
Dock.Buttons.overlaysLibrary() // Video overlays
|
|
20
20
|
Dock.Buttons.textLibrary() // Text tools
|
|
21
21
|
Dock.Buttons.stickersAndShapesLibrary() // Stickers and shapes
|
|
22
|
+
Dock.Buttons.captions() // Caption creation, import and styling
|
|
22
23
|
Dock.Buttons.audioLibrary() // Audio tracks
|
|
23
24
|
Dock.Buttons.voiceover() // Voice recording
|
|
24
25
|
Dock.Buttons.resize() // Aspect ratio and canvas size
|
|
@@ -8,6 +8,10 @@ extension VideoEditorConfiguration {
|
|
|
8
8
|
InspectorBar.Configuration { builder in
|
|
9
9
|
// highlight-starter-kit-inspector-bar
|
|
10
10
|
builder.items { _ in
|
|
11
|
+
// Caption-only buttons, kept at the start so a caption selection leads with them.
|
|
12
|
+
InspectorBar.Buttons.editCaptions()
|
|
13
|
+
InspectorBar.Buttons.captionStyle()
|
|
14
|
+
|
|
11
15
|
InspectorBar.Buttons.replace()
|
|
12
16
|
|
|
13
17
|
InspectorBar.Buttons.editText()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imgly/editor-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.81.0-rc.0",
|
|
4
4
|
"description": "CreativeEditor SDK for React Native - enable photo, video and design editing for your users on iOS and Android.",
|
|
5
5
|
"react-native": "index.js",
|
|
6
6
|
"source": "index.js",
|
package/src/NativeIMGLYEditor.ts
CHANGED
|
@@ -96,7 +96,7 @@ export class EditorSettingsModel implements EditorSettings {
|
|
|
96
96
|
* sources (stickers, filters, and more).
|
|
97
97
|
*/
|
|
98
98
|
baseUri: string =
|
|
99
|
-
'https://cdn.img.ly/packages/imgly/cesdk-react-native/1.
|
|
99
|
+
'https://cdn.img.ly/packages/imgly/cesdk-react-native/1.81.0-rc.0/assets';
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Unique ID tied to your application's user.
|