react-native-video-trim 7.0.0 → 7.1.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/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
  * [Behavior Options](#behavior-options)
13
13
  - [Platform Setup](#platform-setup)
14
14
  - [Advanced Features](#advanced-features)
15
+ * [Theming](#theming)
15
16
  * [Audio Trimming](#audio-trimming)
16
17
  * [Remote Files (HTTPS)](#remote-files-https)
17
18
  * [Video Transforms (Flip, Rotate, Crop)](#video-transforms-flip-rotate-crop)
@@ -24,8 +25,7 @@
24
25
  <div align="center">
25
26
  <h2>📱 Professional video trimmer for React Native apps</h2>
26
27
 
27
- <img src="images/android.gif" width="300" />
28
- <img src="images/ios.gif" width="300" />
28
+ <img src="images/ios.png" width="300" />
29
29
 
30
30
  <p>
31
31
  <strong>✅ iOS & Android</strong> •
@@ -48,6 +48,7 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
48
48
  - **✅ File Validation** - Built-in validation for media files
49
49
  - **🗂️ File Management** - List, clean up, and delete specific files
50
50
  - **🔄 Universal Architecture** - Works with both New and Old React Native architectures
51
+ - **🎨 Dark & Light Theme** - Built-in dark and light theme support
51
52
 
52
53
  ### 🎛️ Core Capabilities
53
54
 
@@ -60,6 +61,7 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
60
61
  | **Save Options** | Photos, Documents, Share sheet integration |
61
62
  | **File Management** | Complete file lifecycle management |
62
63
  | **Customization** | Extensive UI and behavior customization |
64
+ | **Theming** | Dark and light theme with automatic color adaptation |
63
65
 
64
66
  <div align="center">
65
67
  <img src="images/document_picker.png" width="250" />
@@ -282,14 +284,15 @@ All configuration options are optional. Here are the most commonly used ones:
282
284
 
283
285
  | Option | Type | Default | Description |
284
286
  |--------|------|---------|-------------|
287
+ | `theme` | `'dark' \| 'light'` | `'dark'` | Editor color theme (see [Theming](#theming)) |
285
288
  | `cancelButtonText` | `string` | `"Cancel"` | Cancel button text |
286
289
  | `saveButtonText` | `string` | `"Save"` | Save button text |
287
290
  | `trimmingText` | `string` | `"Trimming video..."` | Progress dialog text |
288
291
  | `headerText` | `string` | - | Header text |
289
292
  | `headerTextSize` | `number` | `16` | Header text size |
290
- | `headerTextColor` | `string` | - | Header text color |
293
+ | `headerTextColor` | `string` | - | Header text color (defaults to black in light theme, white in dark theme) |
291
294
  | `trimmerColor` | `string` | - | Trimmer bar color |
292
- | `handleIconColor` | `string` | - | Trimmer left/right handles color |
295
+ | `handleIconColor` | `string` | - | Trimmer left/right handles color (defaults to black in light theme, white in dark theme) |
293
296
  | `fullScreenModalIOS` | `boolean` | `false` | Use fullscreen modal on iOS |
294
297
 
295
298
  ### Dialog Options
@@ -367,6 +370,7 @@ showEditor(videoPath, {
367
370
  removeAfterSavedToPhoto: true,
368
371
 
369
372
  // UI customization
373
+ theme: 'light',
370
374
  headerText: "Trim Your Video",
371
375
  cancelButtonText: "Back",
372
376
  saveButtonText: "Done",
@@ -398,6 +402,34 @@ buildscript {
398
402
 
399
403
  ## Advanced Features
400
404
 
405
+ ### Theming
406
+
407
+ The editor supports dark and light themes. Set the `theme` option to switch between them:
408
+
409
+ ```javascript
410
+ // Light theme
411
+ showEditor(videoUrl, {
412
+ theme: 'light',
413
+ });
414
+
415
+ // Dark theme (default)
416
+ showEditor(videoUrl, {
417
+ theme: 'dark',
418
+ });
419
+ ```
420
+
421
+ | | Dark (default) | Light |
422
+ |---|---|---|
423
+ | **Background** | Black | White |
424
+ | **Icons & text** | White | Black |
425
+ | **Cancel/Save text** | White | Black |
426
+ | **Crop brackets & grid** | White | Black |
427
+ | **Progress indicator** | White | White |
428
+ | **Trimmer handle chevrons** | White | White |
429
+ | **Dialogs** | Dark style | Light style |
430
+
431
+ The `headerTextColor` and `handleIconColor` options automatically adapt to the active theme but can still be overridden explicitly.
432
+
401
433
  ### Audio Trimming
402
434
 
403
435
  <div align="center">
@@ -6,8 +6,6 @@ import android.graphics.Color
6
6
  import android.graphics.Paint
7
7
  import android.graphics.Path
8
8
  import android.graphics.RectF
9
- import android.graphics.Region
10
- import android.os.Build
11
9
  import android.util.AttributeSet
12
10
  import android.util.TypedValue
13
11
  import android.view.MotionEvent
@@ -46,16 +44,27 @@ class CropOverlayView @JvmOverloads constructor(
46
44
  var onCropBegan: (() -> Unit)? = null
47
45
  var onCropEnded: (() -> Unit)? = null
48
46
 
47
+ var isLightTheme = false
48
+ set(value) {
49
+ field = value
50
+ val c = if (value) Color.BLACK else Color.WHITE
51
+ borderPaint.color = c
52
+ gridPaint.color = c
53
+ cornerPaint.color = c
54
+ invalidate()
55
+ }
56
+
49
57
  private val minCropSize = dpToPx(60f)
50
58
  private val borderWidth = dpToPx(1f)
51
59
  private val cornerLength = dpToPx(20f)
52
60
  private val cornerWidth = dpToPx(4f)
61
+ private val edgeHandleLength = dpToPx(20f)
53
62
  private val gridLineWidth = 1f / resources.displayMetrics.density
54
63
  private val edgeHitZone = dpToPx(30f)
55
64
 
56
65
  private val borderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
57
66
  style = Paint.Style.STROKE
58
- color = Color.argb(153, 255, 255, 255)
67
+ color = Color.WHITE
59
68
  strokeWidth = borderWidth
60
69
  }
61
70
  private val gridPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
@@ -68,10 +77,7 @@ class CropOverlayView @JvmOverloads constructor(
68
77
  color = Color.WHITE
69
78
  strokeWidth = cornerWidth
70
79
  strokeCap = Paint.Cap.ROUND
71
- }
72
- private val dimmingPaint = Paint().apply {
73
- color = Color.argb(140, 0, 0, 0)
74
- style = Paint.Style.FILL
80
+ strokeJoin = Paint.Join.ROUND
75
81
  }
76
82
 
77
83
  private enum class DragEdge {
@@ -126,8 +132,6 @@ class CropOverlayView @JvmOverloads constructor(
126
132
  if (cropRect.isEmpty) return
127
133
  val cr = cropRect
128
134
 
129
- drawDimming(canvas, cr)
130
-
131
135
  canvas.drawRect(cr, borderPaint)
132
136
 
133
137
  for (i in 1..2) {
@@ -140,33 +144,27 @@ class CropOverlayView @JvmOverloads constructor(
140
144
  }
141
145
 
142
146
  val cl = cornerLength
147
+ val hw = cornerWidth / 2f
143
148
  val path = Path()
144
149
  fun addCorner(sx: Float, sy: Float, cx: Float, cy: Float, ex: Float, ey: Float) {
145
150
  path.moveTo(sx, sy); path.lineTo(cx, cy); path.lineTo(ex, ey)
146
151
  }
147
- addCorner(cr.left, cr.top + cl, cr.left, cr.top, cr.left + cl, cr.top)
148
- addCorner(cr.right - cl, cr.top, cr.right, cr.top, cr.right, cr.top + cl)
149
- addCorner(cr.left, cr.bottom - cl, cr.left, cr.bottom, cr.left + cl, cr.bottom)
150
- addCorner(cr.right - cl, cr.bottom, cr.right, cr.bottom, cr.right, cr.bottom - cl)
152
+ addCorner(cr.left - hw, cr.top + cl, cr.left - hw, cr.top - hw, cr.left + cl, cr.top - hw)
153
+ addCorner(cr.right - cl, cr.top - hw, cr.right + hw, cr.top - hw, cr.right + hw, cr.top + cl)
154
+ addCorner(cr.left - hw, cr.bottom - cl, cr.left - hw, cr.bottom + hw, cr.left + cl, cr.bottom + hw)
155
+ addCorner(cr.right - cl, cr.bottom + hw, cr.right + hw, cr.bottom + hw, cr.right + hw, cr.bottom - cl)
156
+
157
+ val ehl = edgeHandleLength / 2f
158
+ val cx = cr.centerX()
159
+ val cy = cr.centerY()
160
+ path.moveTo(cx - ehl, cr.top - hw); path.lineTo(cx + ehl, cr.top - hw)
161
+ path.moveTo(cx - ehl, cr.bottom + hw); path.lineTo(cx + ehl, cr.bottom + hw)
162
+ path.moveTo(cr.left - hw, cy - ehl); path.lineTo(cr.left - hw, cy + ehl)
163
+ path.moveTo(cr.right + hw, cy - ehl); path.lineTo(cr.right + hw, cy + ehl)
164
+
151
165
  canvas.drawPath(path, cornerPaint)
152
166
  }
153
167
 
154
- private fun drawDimming(canvas: Canvas, cr: RectF) {
155
- canvas.save()
156
- val fullPath = Path()
157
- fullPath.addRect(0f, 0f, width.toFloat(), height.toFloat(), Path.Direction.CW)
158
- val cropPath = Path()
159
- cropPath.addRect(cr, Path.Direction.CW)
160
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
161
- fullPath.op(cropPath, Path.Op.DIFFERENCE)
162
- canvas.drawPath(fullPath, dimmingPaint)
163
- } else {
164
- @Suppress("DEPRECATION")
165
- canvas.clipPath(cropPath, Region.Op.DIFFERENCE)
166
- canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), dimmingPaint)
167
- }
168
- canvas.restore()
169
- }
170
168
 
171
169
  override fun onTouchEvent(event: MotionEvent): Boolean {
172
170
  if (event.pointerCount > 1) {
@@ -181,6 +181,9 @@ class VideoTrimmerView(
181
181
 
182
182
  private var trimmerColor = context.getString(R.string.trim_color).toColorInt()
183
183
  private var handleIconColor = Color.BLACK
184
+ private var isLightTheme = false
185
+ private val iconColor: Int get() = if (isLightTheme) Color.BLACK else Color.WHITE
186
+ private val dimmedIconColor: Int get() = if (isLightTheme) Color.argb(128, 0, 0, 0) else Color.argb(128, 255, 255, 255)
184
187
  private lateinit var leadingChevron: ImageView
185
188
  private lateinit var trailingChevron: ImageView
186
189
 
@@ -266,10 +269,19 @@ class VideoTrimmerView(
266
269
  }
267
270
  mVideoView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
268
271
  override fun onSurfaceTextureAvailable(st: SurfaceTexture, w: Int, h: Int) {
269
- setupVideoPlayer(st, videoURI)
272
+ val mp = mediaPlayer
273
+ if (mp != null) {
274
+ videoSurface?.release()
275
+ videoSurface = Surface(st)
276
+ mp.setSurface(videoSurface)
277
+ } else {
278
+ setupVideoPlayer(st, videoURI)
279
+ }
270
280
  }
271
281
  override fun onSurfaceTextureSizeChanged(st: SurfaceTexture, w: Int, h: Int) {}
272
- override fun onSurfaceTextureDestroyed(st: SurfaceTexture): Boolean = true
282
+ override fun onSurfaceTextureDestroyed(st: SurfaceTexture): Boolean {
283
+ return false
284
+ }
273
285
  override fun onSurfaceTextureUpdated(st: SurfaceTexture) {}
274
286
  }
275
287
  } else {
@@ -320,20 +332,25 @@ class VideoTrimmerView(
320
332
  if (vw <= 0 || vh <= 0) return
321
333
 
322
334
  videoContainer.post {
323
- val containerW = videoContainer.width
324
- val containerH = videoContainer.height
325
- if (containerW <= 0 || containerH <= 0) return@post
335
+ val cw = containerContentWidth().toInt()
336
+ val ch = containerContentHeight().toInt()
337
+ if (cw <= 0 || ch <= 0) return@post
338
+
339
+ val margin = bracketOverflow()
340
+ val availW = cw - 2 * margin
341
+ val availH = ch - 2 * margin
342
+ if (availW <= 0 || availH <= 0) return@post
326
343
 
327
344
  val videoAR = vw.toFloat() / vh
328
- val containerAR = containerW.toFloat() / containerH
345
+ val containerAR = availW.toFloat() / availH
329
346
  val newW: Int
330
347
  val newH: Int
331
348
  if (videoAR > containerAR) {
332
- newW = containerW
333
- newH = (containerW / videoAR).toInt()
349
+ newW = availW
350
+ newH = (availW / videoAR).toInt()
334
351
  } else {
335
- newH = containerH
336
- newW = (containerH * videoAR).toInt()
352
+ newH = availH
353
+ newW = (availH * videoAR).toInt()
337
354
  }
338
355
  mVideoView.layoutParams = FrameLayout.LayoutParams(newW, newH, Gravity.CENTER)
339
356
  }
@@ -519,6 +536,10 @@ class VideoTrimmerView(
519
536
  cropBtn.setOnClickListener { onCropTapped() }
520
537
  undoBtn.setOnClickListener { onUndoTapped() }
521
538
  redoBtn.setOnClickListener { onRedoTapped() }
539
+
540
+ cropBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
541
+ undoBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
542
+ redoBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
522
543
  }
523
544
 
524
545
  fun onSaveClicked() {
@@ -633,6 +654,8 @@ class VideoTrimmerView(
633
654
  mMinDuration = maxOf(1000L, config.getDouble("minDuration").toLong())
634
655
  }
635
656
 
657
+ isLightTheme = config.hasKey("theme") && config.getString("theme") == "light"
658
+
636
659
  cancelBtn.text = config.getString("cancelButtonText")
637
660
  saveBtn.text = config.getString("saveButtonText")
638
661
  isVideoType = config.hasKey("type") && config.getString("type") == "video"
@@ -673,9 +696,10 @@ class VideoTrimmerView(
673
696
  trimmerColor = if (config.hasKey("trimmerColor")) config.getInt("trimmerColor") else context.getString(
674
697
  R.string.trim_color
675
698
  ).toColorInt()
676
- handleIconColor = if (config.hasKey("handleIconColor")) config.getInt("handleIconColor") else Color.BLACK
699
+ handleIconColor = if (config.hasKey("handleIconColor")) config.getInt("handleIconColor") else (if (isLightTheme) Color.WHITE else Color.BLACK)
677
700
 
678
701
  applyTrimmerColor()
702
+ applyThemeColors()
679
703
  }
680
704
 
681
705
  private fun applyTrimmerColor() {
@@ -704,6 +728,39 @@ class VideoTrimmerView(
704
728
  trailingChevron.setColorFilter(handleIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
705
729
  }
706
730
 
731
+ private fun applyThemeColors() {
732
+ val bgColor = if (isLightTheme) Color.WHITE else Color.BLACK
733
+ val textColor = if (isLightTheme) Color.BLACK else Color.WHITE
734
+ val overlayColor = if (isLightTheme) Color.argb(153, 255, 255, 255) else Color.argb(191, 0, 0, 0)
735
+
736
+ // Backgrounds
737
+ (findViewById<View>(R.id.layout) as? RelativeLayout)?.setBackgroundColor(bgColor)
738
+ headerView.setBackgroundColor(bgColor)
739
+ transformRow.setBackgroundColor(bgColor)
740
+ videoContainer.setBackgroundColor(bgColor)
741
+
742
+ // Text colors
743
+ cancelBtn.setTextColor(iconColor)
744
+ startTimeText.setTextColor(textColor)
745
+ currentTimeText.setTextColor(textColor)
746
+ endTimeText.setTextColor(textColor)
747
+
748
+ // Play icon
749
+ mPlayView.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.SRC_IN)
750
+
751
+ // Transform toolbar icons
752
+ flipBtn.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.SRC_IN)
753
+ rotateBtn.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.SRC_IN)
754
+ cropBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
755
+ undoBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
756
+ redoBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
757
+
758
+ // Overlays
759
+ leadingOverlay.setBackgroundColor(overlayColor)
760
+ trailingOverlay.setBackgroundColor(overlayColor)
761
+
762
+ }
763
+
707
764
  private fun dpToPx(dp: Int): Int {
708
765
  return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), resources.displayMetrics).toInt()
709
766
  }
@@ -916,9 +973,14 @@ class VideoTrimmerView(
916
973
  var newX = event.rawX - view.width.toFloat() / 2
917
974
 
918
975
  if (isLeading) {
976
+ val unclamped = newX
919
977
  newX = maxOf(0f, minOf(newX, trailingHandle.x - view.width))
978
+ if (unclamped < 0f) didClamp = true
920
979
  } else {
921
- newX = minOf(trimmerContainerBg.width.toFloat() + view.width, maxOf(newX, leadingHandle.x + view.width))
980
+ val unclamped = newX
981
+ val maxX = trimmerContainerBg.width.toFloat() + view.width
982
+ newX = minOf(maxX, maxOf(newX, leadingHandle.x + view.width))
983
+ if (unclamped > maxX) didClamp = true
922
984
  }
923
985
 
924
986
  view.x = newX
@@ -1062,7 +1124,8 @@ class VideoTrimmerView(
1062
1124
 
1063
1125
  private fun playHapticFeedback(isLight: Boolean) {
1064
1126
  if (vibrator != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && enableHapticFeedback) {
1065
- vibrator!!.vibrate(VibrationEffect.createOneShot(if (isLight) 10L else 25L, VibrationEffect.DEFAULT_AMPLITUDE))
1127
+ val amplitude = if (isLight) 30 else 80
1128
+ vibrator!!.vibrate(VibrationEffect.createOneShot(if (isLight) 8L else 15L, amplitude))
1066
1129
  }
1067
1130
  }
1068
1131
 
@@ -1304,14 +1367,28 @@ class VideoTrimmerView(
1304
1367
 
1305
1368
  // region Transform
1306
1369
 
1370
+ private fun containerContentWidth(): Float =
1371
+ (videoContainer.width - videoContainer.paddingLeft - videoContainer.paddingRight).toFloat()
1372
+
1373
+ private fun containerContentHeight(): Float =
1374
+ (videoContainer.height - videoContainer.paddingTop - videoContainer.paddingBottom).toFloat()
1375
+
1376
+ private fun bracketOverflow(): Int =
1377
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics).toInt()
1378
+
1307
1379
  private fun onFlipTapped() {
1308
1380
  pushUndo()
1309
1381
  isFlipped = !isFlipped
1310
1382
  val newCumDeg = -cumulativeRotationDeg
1311
1383
  val fitScale = if (rotationCount % 2 != 0) {
1312
- val cw = videoContainer.width.toFloat()
1313
- val ch = videoContainer.height.toFloat()
1314
- if (cw > 0 && ch > 0) minOf(cw / ch, ch / cw) else 1f
1384
+ val cw = containerContentWidth()
1385
+ val ch = containerContentHeight()
1386
+ val vw = mVideoView.width.toFloat()
1387
+ val vh = mVideoView.height.toFloat()
1388
+ val margin = bracketOverflow().toFloat()
1389
+ val availW = cw - 2 * margin
1390
+ val availH = ch - 2 * margin
1391
+ if (availW > 0 && availH > 0 && vw > 0 && vh > 0) minOf(availW / vh, availH / vw) else 1f
1315
1392
  } else {
1316
1393
  1f
1317
1394
  }
@@ -1379,17 +1456,29 @@ class VideoTrimmerView(
1379
1456
  }
1380
1457
 
1381
1458
  private fun updateVideoTransform(resetCrop: Boolean = false) {
1382
- val containerW = videoContainer.width.toFloat()
1383
- val containerH = videoContainer.height.toFloat()
1384
- if (containerW <= 0 || containerH <= 0) return
1459
+ val cw = containerContentWidth()
1460
+ val ch = containerContentHeight()
1461
+ if (cw <= 0 || ch <= 0) return
1385
1462
 
1386
1463
  val fitScale = if (rotationCount % 2 != 0) {
1387
- minOf(containerW / containerH, containerH / containerW)
1464
+ val vw = mVideoView.width.toFloat()
1465
+ val vh = mVideoView.height.toFloat()
1466
+ val margin = bracketOverflow().toFloat()
1467
+ val availW = cw - 2 * margin
1468
+ val availH = ch - 2 * margin
1469
+ if (vw > 0 && vh > 0 && availW > 0 && availH > 0) minOf(availW / vh, availH / vw) else 1f
1388
1470
  } else {
1389
1471
  1f
1390
1472
  }
1391
1473
  val flipMul = if (isFlipped) -1f else 1f
1392
1474
 
1475
+ if (isCropActive) {
1476
+ cropOverlay?.animate()
1477
+ ?.alpha(0f)
1478
+ ?.setDuration(125)
1479
+ ?.start()
1480
+ }
1481
+
1393
1482
  mVideoView.animate()
1394
1483
  .scaleX(flipMul * fitScale)
1395
1484
  .scaleY(fitScale)
@@ -1400,6 +1489,10 @@ class VideoTrimmerView(
1400
1489
  if (resetCrop && isCropActive) {
1401
1490
  updateCropAllowedRect()
1402
1491
  cropOverlay?.resetCrop()
1492
+ cropOverlay?.animate()
1493
+ ?.alpha(1f)
1494
+ ?.setDuration(125)
1495
+ ?.start()
1403
1496
  }
1404
1497
  }
1405
1498
  .start()
@@ -1412,7 +1505,7 @@ class VideoTrimmerView(
1412
1505
  private fun onCropTapped() {
1413
1506
  isCropActive = !isCropActive
1414
1507
  cropBtn.setColorFilter(
1415
- if (isCropActive) Color.WHITE else Color.argb(128, 255, 255, 255),
1508
+ if (isCropActive) iconColor else dimmedIconColor,
1416
1509
  android.graphics.PorterDuff.Mode.SRC_IN
1417
1510
  )
1418
1511
  playHapticFeedback(true)
@@ -1422,6 +1515,7 @@ class VideoTrimmerView(
1422
1515
  private fun showCropOverlay() {
1423
1516
  hideCropOverlayImmediate()
1424
1517
  val overlay = CropOverlayView(mContext)
1518
+ overlay.isLightTheme = isLightTheme
1425
1519
  overlay.layoutParams = FrameLayout.LayoutParams(
1426
1520
  FrameLayout.LayoutParams.MATCH_PARENT,
1427
1521
  FrameLayout.LayoutParams.MATCH_PARENT
@@ -1457,6 +1551,7 @@ class VideoTrimmerView(
1457
1551
  private fun showCropOverlayImmediate() {
1458
1552
  hideCropOverlayImmediate()
1459
1553
  val overlay = CropOverlayView(mContext)
1554
+ overlay.isLightTheme = isLightTheme
1460
1555
  overlay.layoutParams = FrameLayout.LayoutParams(
1461
1556
  FrameLayout.LayoutParams.MATCH_PARENT,
1462
1557
  FrameLayout.LayoutParams.MATCH_PARENT
@@ -1487,22 +1582,25 @@ class VideoTrimmerView(
1487
1582
  }
1488
1583
 
1489
1584
  private fun getVideoDisplayRectInContainer(): RectF {
1490
- val containerW = videoContainer.width.toFloat()
1491
- val containerH = videoContainer.height.toFloat()
1492
- if (containerW <= 0 || containerH <= 0) return RectF()
1585
+ val cw = containerContentWidth()
1586
+ val ch = containerContentHeight()
1587
+ if (cw <= 0 || ch <= 0) return RectF()
1493
1588
 
1494
1589
  val tvW = mVideoView.width.toFloat()
1495
1590
  val tvH = mVideoView.height.toFloat()
1496
1591
  if (tvW <= 0 || tvH <= 0) return RectF()
1497
1592
 
1498
- val tvX = (containerW - tvW) / 2f
1499
- val tvY = (containerH - tvH) / 2f
1593
+ val tvX = (cw - tvW) / 2f
1594
+ val tvY = (ch - tvH) / 2f
1500
1595
  val videoRect = RectF(tvX, tvY, tvX + tvW, tvY + tvH)
1501
1596
 
1502
- val pivotX = containerW / 2f
1503
- val pivotY = containerH / 2f
1597
+ val pivotX = cw / 2f
1598
+ val pivotY = ch / 2f
1599
+ val margin = bracketOverflow().toFloat()
1600
+ val availW = cw - 2 * margin
1601
+ val availH = ch - 2 * margin
1504
1602
  val fitScale = if (rotationCount % 2 != 0) {
1505
- minOf(containerW / containerH, containerH / containerW)
1603
+ if (tvW > 0 && tvH > 0 && availW > 0 && availH > 0) minOf(availW / tvH, availH / tvW) else 1f
1506
1604
  } else {
1507
1605
  1f
1508
1606
  }
@@ -1603,10 +1701,15 @@ class VideoTrimmerView(
1603
1701
  isFlipped = snap.isFlipped
1604
1702
  cumulativeRotationDeg = snap.cumulativeRotationDeg
1605
1703
 
1606
- val containerW = videoContainer.width.toFloat()
1607
- val containerH = videoContainer.height.toFloat()
1608
- val fitScale = if (rotationCount % 2 != 0 && containerW > 0 && containerH > 0) {
1609
- minOf(containerW / containerH, containerH / containerW)
1704
+ val cw = containerContentWidth()
1705
+ val ch = containerContentHeight()
1706
+ val vw = mVideoView.width.toFloat()
1707
+ val vh = mVideoView.height.toFloat()
1708
+ val margin = bracketOverflow().toFloat()
1709
+ val availW = cw - 2 * margin
1710
+ val availH = ch - 2 * margin
1711
+ val fitScale = if (rotationCount % 2 != 0 && availW > 0 && availH > 0 && vw > 0 && vh > 0) {
1712
+ minOf(availW / vh, availH / vw)
1610
1713
  } else {
1611
1714
  1f
1612
1715
  }
@@ -1616,17 +1719,14 @@ class VideoTrimmerView(
1616
1719
  val onComplete = Runnable {
1617
1720
  if (snap.isCropActive) {
1618
1721
  isCropActive = true
1619
- cropBtn.setColorFilter(Color.WHITE, android.graphics.PorterDuff.Mode.SRC_IN)
1722
+ cropBtn.setColorFilter(iconColor, android.graphics.PorterDuff.Mode.SRC_IN)
1620
1723
  showCropOverlayImmediate()
1621
1724
  updateCropAllowedRect()
1622
1725
  val norm = snap.cropNormalized
1623
1726
  if (norm != null) setCropFromNormalized(norm) else cropOverlay?.resetCrop()
1624
1727
  } else {
1625
1728
  isCropActive = false
1626
- cropBtn.setColorFilter(
1627
- Color.argb(128, 255, 255, 255),
1628
- android.graphics.PorterDuff.Mode.SRC_IN
1629
- )
1729
+ cropBtn.setColorFilter(dimmedIconColor, android.graphics.PorterDuff.Mode.SRC_IN)
1630
1730
  hideCropOverlayImmediate()
1631
1731
  }
1632
1732
  }
@@ -1680,16 +1780,14 @@ class VideoTrimmerView(
1680
1780
  }
1681
1781
 
1682
1782
  private fun updateUndoRedoButtons() {
1683
- val dimmed = Color.argb(128, 255, 255, 255)
1684
- val active = Color.WHITE
1685
1783
  undoBtn.isEnabled = undoStack.isNotEmpty()
1686
1784
  undoBtn.setColorFilter(
1687
- if (undoStack.isNotEmpty()) active else dimmed,
1785
+ if (undoStack.isNotEmpty()) iconColor else dimmedIconColor,
1688
1786
  android.graphics.PorterDuff.Mode.SRC_IN
1689
1787
  )
1690
1788
  redoBtn.isEnabled = redoStack.isNotEmpty()
1691
1789
  redoBtn.setColorFilter(
1692
- if (redoStack.isNotEmpty()) active else dimmed,
1790
+ if (redoStack.isNotEmpty()) iconColor else dimmedIconColor,
1693
1791
  android.graphics.PorterDuff.Mode.SRC_IN
1694
1792
  )
1695
1793
  }
@@ -94,8 +94,8 @@
94
94
 
95
95
  <ImageView
96
96
  android:id="@+id/undoBtn"
97
- android:layout_width="22dp"
98
- android:layout_height="22dp"
97
+ android:layout_width="18dp"
98
+ android:layout_height="18dp"
99
99
  android:src="@drawable/arrow_uturn_backward"
100
100
  android:tint="#80FFFFFF"
101
101
  android:scaleType="fitCenter"
@@ -104,8 +104,8 @@
104
104
 
105
105
  <ImageView
106
106
  android:id="@+id/redoBtn"
107
- android:layout_width="22dp"
108
- android:layout_height="22dp"
107
+ android:layout_width="18dp"
108
+ android:layout_height="18dp"
109
109
  android:src="@drawable/arrow_uturn_forward"
110
110
  android:tint="#80FFFFFF"
111
111
  android:scaleType="fitCenter"
@@ -120,7 +120,9 @@
120
120
  android:layout_above="@+id/layout"
121
121
  android:layout_below="@+id/transformRow"
122
122
  android:background="@android:color/black"
123
- android:clipChildren="true">
123
+ android:clipChildren="true"
124
+ android:clipToPadding="false"
125
+ android:paddingVertical="4dp">
124
126
 
125
127
  <TextureView
126
128
  android:id="@+id/video_loader"
@@ -6,7 +6,6 @@ class CropOverlayView: UIView {
6
6
  var cropRect: CGRect = .zero {
7
7
  didSet {
8
8
  setNeedsDisplay()
9
- updateDimmingMask()
10
9
  }
11
10
  }
12
11
 
@@ -27,10 +26,15 @@ class CropOverlayView: UIView {
27
26
  var onCropBegan: (() -> Void)?
28
27
  var onCropEnded: (() -> Void)?
29
28
 
29
+ var isLightTheme = false {
30
+ didSet { setNeedsDisplay() }
31
+ }
32
+
30
33
  private let minCropSize: CGFloat = 60
31
34
  private let borderWidth: CGFloat = 1.0
32
35
  private let cornerLength: CGFloat = 20
33
36
  private let cornerWidth: CGFloat = 4.0
37
+ private let edgeHandleLength: CGFloat = 20
34
38
  private let gridLineWidth: CGFloat = CGFloat(1.0 / UIScreen.main.scale)
35
39
  private let edgeHitZone: CGFloat = 30
36
40
 
@@ -38,8 +42,6 @@ class CropOverlayView: UIView {
38
42
  private var dragStart: CGPoint = .zero
39
43
  private var dragStartRect: CGRect = .zero
40
44
 
41
- private let dimmingLayer = CAShapeLayer()
42
-
43
45
  private enum DragEdge {
44
46
  case top, bottom, left, right
45
47
  case topLeft, topRight, bottomLeft, bottomRight
@@ -59,13 +61,9 @@ class CropOverlayView: UIView {
59
61
  private func commonInit() {
60
62
  backgroundColor = .clear
61
63
  isUserInteractionEnabled = true
62
- clipsToBounds = true
64
+ clipsToBounds = false
63
65
  isOpaque = false
64
66
 
65
- dimmingLayer.fillRule = .evenOdd
66
- dimmingLayer.fillColor = UIColor.black.withAlphaComponent(0.55).cgColor
67
- layer.addSublayer(dimmingLayer)
68
-
69
67
  let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
70
68
  addGestureRecognizer(pan)
71
69
 
@@ -73,32 +71,18 @@ class CropOverlayView: UIView {
73
71
  addGestureRecognizer(pinch)
74
72
  }
75
73
 
76
- override func layoutSubviews() {
77
- super.layoutSubviews()
78
- updateDimmingMask()
79
- }
80
-
81
- private func updateDimmingMask() {
82
- let full = UIBezierPath(rect: bounds)
83
- if !cropRect.isEmpty {
84
- full.append(UIBezierPath(rect: cropRect))
85
- }
86
- dimmingLayer.path = full.cgPath
87
- dimmingLayer.frame = bounds
88
- }
89
-
90
74
  // MARK: - Drawing
91
75
 
92
76
  override func draw(_ rect: CGRect) {
93
77
  guard !cropRect.isEmpty, let ctx = UIGraphicsGetCurrentContext() else { return }
94
78
  let cr = cropRect
95
79
 
96
- ctx.setStrokeColor(UIColor.white.withAlphaComponent(0.6).cgColor)
80
+ let strokeColor = (isLightTheme ? UIColor.black : UIColor.white).cgColor
81
+ ctx.setStrokeColor(strokeColor)
97
82
  ctx.setLineWidth(borderWidth)
98
83
  ctx.stroke(cr)
99
84
 
100
85
  ctx.setLineWidth(gridLineWidth)
101
- ctx.setStrokeColor(UIColor.white.cgColor)
102
86
  for i in 1...2 {
103
87
  let x = cr.minX + cr.width * CGFloat(i) / 3
104
88
  ctx.move(to: CGPoint(x: x, y: cr.minY))
@@ -111,30 +95,44 @@ class CropOverlayView: UIView {
111
95
  }
112
96
  ctx.strokePath()
113
97
 
114
- ctx.setStrokeColor(UIColor.white.cgColor)
98
+ ctx.setStrokeColor(strokeColor)
115
99
  ctx.setLineWidth(cornerWidth)
116
100
  ctx.setLineCap(.round)
101
+ ctx.setLineJoin(.round)
117
102
 
118
103
  let cl = cornerLength
104
+ let hw = cornerWidth / 2
119
105
  let corners: [(CGPoint, CGPoint, CGPoint)] = [
120
- (CGPoint(x: cr.minX, y: cr.minY + cl),
121
- CGPoint(x: cr.minX, y: cr.minY),
122
- CGPoint(x: cr.minX + cl, y: cr.minY)),
123
- (CGPoint(x: cr.maxX - cl, y: cr.minY),
124
- CGPoint(x: cr.maxX, y: cr.minY),
125
- CGPoint(x: cr.maxX, y: cr.minY + cl)),
126
- (CGPoint(x: cr.minX, y: cr.maxY - cl),
127
- CGPoint(x: cr.minX, y: cr.maxY),
128
- CGPoint(x: cr.minX + cl, y: cr.maxY)),
129
- (CGPoint(x: cr.maxX - cl, y: cr.maxY),
130
- CGPoint(x: cr.maxX, y: cr.maxY),
131
- CGPoint(x: cr.maxX, y: cr.maxY - cl)),
106
+ (CGPoint(x: cr.minX - hw, y: cr.minY + cl),
107
+ CGPoint(x: cr.minX - hw, y: cr.minY - hw),
108
+ CGPoint(x: cr.minX + cl, y: cr.minY - hw)),
109
+ (CGPoint(x: cr.maxX - cl, y: cr.minY - hw),
110
+ CGPoint(x: cr.maxX + hw, y: cr.minY - hw),
111
+ CGPoint(x: cr.maxX + hw, y: cr.minY + cl)),
112
+ (CGPoint(x: cr.minX - hw, y: cr.maxY - cl),
113
+ CGPoint(x: cr.minX - hw, y: cr.maxY + hw),
114
+ CGPoint(x: cr.minX + cl, y: cr.maxY + hw)),
115
+ (CGPoint(x: cr.maxX - cl, y: cr.maxY + hw),
116
+ CGPoint(x: cr.maxX + hw, y: cr.maxY + hw),
117
+ CGPoint(x: cr.maxX + hw, y: cr.maxY - cl)),
132
118
  ]
133
119
  for (start, corner, end) in corners {
134
120
  ctx.move(to: start)
135
121
  ctx.addLine(to: corner)
136
122
  ctx.addLine(to: end)
137
123
  }
124
+
125
+ let ehl = edgeHandleLength / 2
126
+ let cx = cr.midX, cy = cr.midY
127
+ ctx.move(to: CGPoint(x: cx - ehl, y: cr.minY - hw))
128
+ ctx.addLine(to: CGPoint(x: cx + ehl, y: cr.minY - hw))
129
+ ctx.move(to: CGPoint(x: cx - ehl, y: cr.maxY + hw))
130
+ ctx.addLine(to: CGPoint(x: cx + ehl, y: cr.maxY + hw))
131
+ ctx.move(to: CGPoint(x: cr.minX - hw, y: cy - ehl))
132
+ ctx.addLine(to: CGPoint(x: cr.minX - hw, y: cy + ehl))
133
+ ctx.move(to: CGPoint(x: cr.maxX + hw, y: cy - ehl))
134
+ ctx.addLine(to: CGPoint(x: cr.maxX + hw, y: cy + ehl))
135
+
138
136
  ctx.strokePath()
139
137
  }
140
138
 
package/ios/VideoTrim.mm CHANGED
@@ -160,6 +160,11 @@ RCT_EXPORT_MODULE()
160
160
  dict[@"zoomOnWaitingDuration"] = @(zoomOnWaitingDurationOpt.value());
161
161
  }
162
162
 
163
+ NSString *theme = config.theme();
164
+ if (theme != nil) {
165
+ dict[@"theme"] = theme;
166
+ }
167
+
163
168
  [self->videoTrim showEditor:filePath withConfig:dict];
164
169
  }
165
170
 
@@ -13,6 +13,9 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
13
13
  private var vc: VideoTrimmerViewController?
14
14
  private var outputFile: URL?
15
15
  private var editorConfig: NSDictionary?
16
+ private var isLightTheme: Bool {
17
+ return (editorConfig?["theme"] as? String) == "light"
18
+ }
16
19
 
17
20
  // MARK: base options
18
21
  private var saveToPhoto: Bool {
@@ -289,7 +292,7 @@ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDe
289
292
  progressAlert.onDismiss = {
290
293
  if self.enableCancelTrimmingDialog {
291
294
  let dialogMessage = UIAlertController(title: self.cancelTrimmingDialogTitle, message: self.cancelTrimmingDialogMessage, preferredStyle: .alert)
292
- dialogMessage.overrideUserInterfaceStyle = .dark
295
+ dialogMessage.overrideUserInterfaceStyle = self.isLightTheme ? .light : .dark
293
296
 
294
297
  // Create OK button with action handler
295
298
  let ok = UIAlertAction(title: self.cancelTrimmingDialogConfirmText, style: .destructive, handler: { (action) -> Void in
@@ -879,7 +882,7 @@ extension VideoTrim {
879
882
 
880
883
  // Create Alert
881
884
  let dialogMessage = UIAlertController(title: self.cancelDialogTitle, message: self.cancelDialogMessage, preferredStyle: .alert)
882
- dialogMessage.overrideUserInterfaceStyle = .dark
885
+ dialogMessage.overrideUserInterfaceStyle = self.isLightTheme ? .light : .dark
883
886
 
884
887
  // Create OK button with action handler
885
888
  let ok = UIAlertAction(title: self.cancelDialogConfirmText, style: .destructive, handler: { (action) -> Void in
@@ -911,7 +914,7 @@ extension VideoTrim {
911
914
 
912
915
  // Create Alert
913
916
  let dialogMessage = UIAlertController(title: self.saveDialogTitle, message: self.saveDialogMessage, preferredStyle: .alert)
914
- dialogMessage.overrideUserInterfaceStyle = .dark
917
+ dialogMessage.overrideUserInterfaceStyle = self.isLightTheme ? .light : .dark
915
918
 
916
919
  // Create OK button with action handler
917
920
  let ok = UIAlertAction(title: self.saveDialogConfirmText, style: .default, handler: { (action) -> Void in
@@ -1134,7 +1137,7 @@ extension VideoTrim {
1134
1137
 
1135
1138
  if alertOnFailToLoad {
1136
1139
  let dialogMessage = UIAlertController(title: alertOnFailTitle, message: alertOnFailMessage, preferredStyle: .alert)
1137
- dialogMessage.overrideUserInterfaceStyle = .dark
1140
+ dialogMessage.overrideUserInterfaceStyle = isLightTheme ? .light : .dark
1138
1141
 
1139
1142
  // Create Cancel button with action handlder
1140
1143
  let ok = UIAlertAction(title: alertOnFailCloseText, style: .default)
@@ -133,10 +133,10 @@ import AVFoundation
133
133
  }
134
134
  }
135
135
 
136
- // the asset to use
137
136
  var asset: AVAsset? {
138
137
  didSet {
139
138
  if let asset = asset {
139
+ applyThemeColors()
140
140
  let duration = asset.duration
141
141
  range = CMTimeRange(start: .zero, duration: duration)
142
142
  selectedRange = range
@@ -159,6 +159,7 @@ import AVFoundation
159
159
  var maximumDuration: CMTime = .positiveInfinity
160
160
  var enableHapticFeedback = true
161
161
  var zoomOnWaitingDuration: Double = 5.0 // Default: 5 seconds
162
+ var isLightTheme = false
162
163
 
163
164
  // the available range of the asset.
164
165
  // Will be set to the full duration of the asset when assigning a new asset
@@ -219,14 +220,12 @@ import AVFoundation
219
220
  // yes if the user is scrubbing the progress indicator
220
221
  private(set) var isScrubbing = false
221
222
 
222
- // background color for the track
223
223
  var trackBackgroundColor = UIColor.black {
224
224
  didSet {
225
225
  thumbnailWrapperView.backgroundColor = trackBackgroundColor
226
226
  }
227
227
  }
228
228
 
229
- // background color for the place where the thumbs rest on when the selectedRange == range
230
229
  var thumbRestColor = UIColor.black {
231
230
  didSet {
232
231
  leadingThumbRest.backgroundColor = thumbRestColor
@@ -276,6 +275,16 @@ import AVFoundation
276
275
 
277
276
 
278
277
  // MARK: - Private
278
+ private func applyThemeColors() {
279
+ let bg: UIColor = isLightTheme ? .white : .black
280
+ let coverAlpha: CGFloat = isLightTheme ? 0.6 : 0.75
281
+ trackBackgroundColor = bg
282
+ thumbRestColor = bg
283
+ thumbnailLeadingCoverView.backgroundColor = UIColor(white: isLightTheme ? 1 : 0, alpha: coverAlpha)
284
+ thumbnailTrailingCoverView.backgroundColor = UIColor(white: isLightTheme ? 1 : 0, alpha: coverAlpha)
285
+ shadowView.layer.shadowColor = (isLightTheme ? UIColor.gray : UIColor.black).cgColor
286
+ }
287
+
279
288
  private func setup() {
280
289
  addSubview(thumbnailClipView)
281
290
  thumbnailClipView.addSubview(thumbnailWrapperView)
@@ -285,8 +294,6 @@ import AVFoundation
285
294
  thumbnailWrapperView.addSubview(thumbnailLeadingCoverView)
286
295
  thumbnailWrapperView.addSubview(thumbnailTrailingCoverView)
287
296
 
288
- progressIndicator.backgroundColor = .white
289
- progressIndicator.layer.shadowColor = UIColor.black.cgColor
290
297
  progressIndicator.layer.shadowOffset = .zero
291
298
  progressIndicator.layer.shadowRadius = 2
292
299
  progressIndicator.layer.shadowOpacity = 0.25
@@ -302,13 +309,7 @@ import AVFoundation
302
309
 
303
310
  thumbnailClipView.clipsToBounds = true
304
311
  thumbnailTrackView.clipsToBounds = true
305
- thumbnailLeadingCoverView.backgroundColor = UIColor(white: 0, alpha: 0.75)
306
- thumbnailTrailingCoverView.backgroundColor = UIColor(white: 0, alpha: 0.75)
307
312
 
308
- leadingThumbRest.backgroundColor = thumbRestColor
309
- trailingThumbRest.backgroundColor = thumbRestColor
310
-
311
- thumbnailWrapperView.backgroundColor = trackBackgroundColor
312
313
  thumbnailWrapperView.layer.cornerRadius = 6
313
314
  thumbnailWrapperView.layer.cornerCurve = .continuous
314
315
 
@@ -320,11 +321,20 @@ import AVFoundation
320
321
  trailingThumbRest.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner]
321
322
  trailingThumbRest.layer.cornerCurve = .continuous
322
323
 
323
- shadowView.layer.shadowColor = UIColor.black.cgColor
324
324
  shadowView.layer.shadowOffset = .zero
325
325
  shadowView.layer.shadowRadius = 2
326
326
  shadowView.layer.shadowOpacity = 0.25
327
327
 
328
+ // Apply default (dark theme) colors — overridden by applyThemeColors() when asset is set
329
+ progressIndicator.backgroundColor = .white
330
+ progressIndicator.layer.shadowColor = UIColor.black.cgColor
331
+ thumbnailLeadingCoverView.backgroundColor = UIColor(white: 0, alpha: 0.75)
332
+ thumbnailTrailingCoverView.backgroundColor = UIColor(white: 0, alpha: 0.75)
333
+ leadingThumbRest.backgroundColor = thumbRestColor
334
+ trailingThumbRest.backgroundColor = thumbRestColor
335
+ thumbnailWrapperView.backgroundColor = trackBackgroundColor
336
+ shadowView.layer.shadowColor = UIColor.black.cgColor
337
+
328
338
  setupConstraints()
329
339
  setupGestures()
330
340
  }
@@ -49,9 +49,11 @@ class VideoTrimmerViewController: UIViewController {
49
49
  private var enableHapticFeedback = true
50
50
  private var zoomOnWaitingDuration: Double = 5.0 // Default: 5 seconds
51
51
 
52
- // New color properties
53
52
  private var trimmerColor: UIColor = UIColor.systemYellow
54
53
  private var handleIconColor: UIColor = UIColor.black
54
+ private var isLightTheme = false
55
+ private var iconColor: UIColor { isLightTheme ? .black : .white }
56
+ private var dimmedIconColor: UIColor { iconColor.withAlphaComponent(0.5) }
55
57
 
56
58
  private let playerController = AVPlayerViewController()
57
59
  private var trimmer: VideoTrimmer!
@@ -212,6 +214,14 @@ class VideoTrimmerViewController: UIViewController {
212
214
  setupView()
213
215
  setupButtons()
214
216
  setupTimeLabels()
217
+
218
+ NotificationCenter.default.addObserver(self, selector: #selector(appWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
219
+ }
220
+
221
+ @objc private func appWillResignActive() {
222
+ guard asset != nil else { return }
223
+ player.pause()
224
+ setPlayBtnIcon()
215
225
  }
216
226
 
217
227
  override func viewWillDisappear(_ animated: Bool) {
@@ -228,8 +238,8 @@ class VideoTrimmerViewController: UIViewController {
228
238
  player.removeTimeObserver(token)
229
239
  timeObserverToken = nil
230
240
  }
231
- // Remove observer
232
241
  NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
242
+ NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
233
243
 
234
244
  playerController.player = nil
235
245
  playerController.dismiss(animated: false, completion: nil)
@@ -276,8 +286,8 @@ class VideoTrimmerViewController: UIViewController {
276
286
 
277
287
  // MARK: - Setup Methods
278
288
  private func setupView() {
279
- self.overrideUserInterfaceStyle = .dark
280
- view.backgroundColor = .black // need to have this otherwise during animation the background of this VC is still white in white theme
289
+ self.overrideUserInterfaceStyle = isLightTheme ? .light : .dark
290
+ view.backgroundColor = isLightTheme ? .white : .black
281
291
 
282
292
  if let headerText = headerText {
283
293
  headerView = UIView()
@@ -326,8 +336,8 @@ class VideoTrimmerViewController: UIViewController {
326
336
  }
327
337
 
328
338
  private func setupButtons() {
329
- cancelBtn = UIButton.createButton(title: cancelButtonText, font: .systemFont(ofSize: 18), titleColor: .white, target: self, action: #selector(onCancelBtnClicked))
330
- playBtn = UIButton.createButton(image: playIcon, tintColor: .white, target: self, action: #selector(togglePlay(sender:)))
339
+ cancelBtn = UIButton.createButton(title: cancelButtonText, font: .systemFont(ofSize: 18), titleColor: iconColor, target: self, action: #selector(onCancelBtnClicked))
340
+ playBtn = UIButton.createButton(image: playIcon, tintColor: iconColor, target: self, action: #selector(togglePlay(sender:)))
331
341
  playBtn.alpha = 0
332
342
  playBtn.isEnabled = false
333
343
 
@@ -354,11 +364,12 @@ class VideoTrimmerViewController: UIViewController {
354
364
  }
355
365
 
356
366
  private func setupTimeLabels() {
357
- leadingTrimLabel = UILabel.createLabel(textAlignment: .left, textColor: .white)
367
+ let labelColor = isLightTheme ? UIColor.black : UIColor.white
368
+ leadingTrimLabel = UILabel.createLabel(textAlignment: .left, textColor: labelColor)
358
369
  leadingTrimLabel.text = "00:00.000"
359
- currentTimeLabel = UILabel.createLabel(textAlignment: .center, textColor: .white)
370
+ currentTimeLabel = UILabel.createLabel(textAlignment: .center, textColor: labelColor)
360
371
  currentTimeLabel.text = "00:00.000"
361
- trailingTrimLabel = UILabel.createLabel(textAlignment: .right, textColor: .white)
372
+ trailingTrimLabel = UILabel.createLabel(textAlignment: .right, textColor: labelColor)
362
373
  trailingTrimLabel.text = "00:00.000"
363
374
 
364
375
  timingStackView = UIStackView(arrangedSubviews: [leadingTrimLabel, currentTimeLabel, trailingTrimLabel])
@@ -377,6 +388,7 @@ class VideoTrimmerViewController: UIViewController {
377
388
 
378
389
  private func setupVideoTrimmer() {
379
390
  trimmer = VideoTrimmer()
391
+ trimmer.isLightTheme = isLightTheme
380
392
  trimmer.asset = asset
381
393
  trimmer.minimumDuration = CMTime(seconds: 1, preferredTimescale: 600)
382
394
  trimmer.enableHapticFeedback = enableHapticFeedback
@@ -469,11 +481,14 @@ class VideoTrimmerViewController: UIViewController {
469
481
  addChild(playerController)
470
482
  playerContainerView.addSubview(playerController.view)
471
483
  playerController.view.translatesAutoresizingMaskIntoConstraints = false
484
+ playerController.view.backgroundColor = .clear
485
+
486
+ let bracketInset: CGFloat = 5
472
487
  NSLayoutConstraint.activate([
473
- playerController.view.leadingAnchor.constraint(equalTo: playerContainerView.leadingAnchor),
474
- playerController.view.trailingAnchor.constraint(equalTo: playerContainerView.trailingAnchor),
475
- playerController.view.topAnchor.constraint(equalTo: playerContainerView.topAnchor),
476
- playerController.view.bottomAnchor.constraint(equalTo: playerContainerView.bottomAnchor)
488
+ playerController.view.topAnchor.constraint(equalTo: playerContainerView.topAnchor, constant: bracketInset),
489
+ playerController.view.bottomAnchor.constraint(equalTo: playerContainerView.bottomAnchor, constant: -bracketInset),
490
+ playerController.view.leadingAnchor.constraint(equalTo: playerContainerView.leadingAnchor, constant: bracketInset),
491
+ playerController.view.trailingAnchor.constraint(equalTo: playerContainerView.trailingAnchor, constant: -bracketInset),
477
492
  ])
478
493
 
479
494
  // Add observer for the end of playback
@@ -491,34 +506,33 @@ class VideoTrimmerViewController: UIViewController {
491
506
  guard isVideoType else { return }
492
507
 
493
508
  let symbolConfig = UIImage.SymbolConfiguration(pointSize: 14, weight: .medium)
494
- let dimmed = UIColor.white.withAlphaComponent(0.5)
495
509
 
496
510
  let flipBtn = UIButton(type: .system)
497
511
  flipBtn.setImage(UIImage(systemName: "arrow.trianglehead.left.and.right.righttriangle.left.righttriangle.right", withConfiguration: symbolConfig), for: .normal)
498
- flipBtn.tintColor = .white
512
+ flipBtn.tintColor = iconColor
499
513
  flipBtn.addTarget(self, action: #selector(onFlipTapped), for: .touchUpInside)
500
514
 
501
515
  let rotateBtn = UIButton(type: .system)
502
516
  rotateBtn.setImage(UIImage(systemName: "rotate.left", withConfiguration: symbolConfig), for: .normal)
503
- rotateBtn.tintColor = .white
517
+ rotateBtn.tintColor = iconColor
504
518
  rotateBtn.addTarget(self, action: #selector(onRotateTapped), for: .touchUpInside)
505
519
 
506
520
  let cropButton = UIButton(type: .system)
507
521
  cropButton.setImage(UIImage(systemName: "crop", withConfiguration: symbolConfig), for: .normal)
508
- cropButton.tintColor = UIColor.white.withAlphaComponent(0.5)
522
+ cropButton.tintColor = dimmedIconColor
509
523
  cropButton.addTarget(self, action: #selector(onCropTapped), for: .touchUpInside)
510
524
  self.cropBtn = cropButton
511
525
 
512
526
  let undoButton = UIButton(type: .system)
513
527
  undoButton.setImage(UIImage(systemName: "arrow.uturn.backward", withConfiguration: symbolConfig), for: .normal)
514
- undoButton.tintColor = dimmed
528
+ undoButton.tintColor = dimmedIconColor
515
529
  undoButton.isEnabled = false
516
530
  undoButton.addTarget(self, action: #selector(onUndoTapped), for: .touchUpInside)
517
531
  self.undoBtn = undoButton
518
532
 
519
533
  let redoButton = UIButton(type: .system)
520
534
  redoButton.setImage(UIImage(systemName: "arrow.uturn.forward", withConfiguration: symbolConfig), for: .normal)
521
- redoButton.tintColor = dimmed
535
+ redoButton.tintColor = dimmedIconColor
522
536
  redoButton.isEnabled = false
523
537
  redoButton.addTarget(self, action: #selector(onRedoTapped), for: .touchUpInside)
524
538
  self.redoBtn = redoButton
@@ -582,29 +596,63 @@ class VideoTrimmerViewController: UIViewController {
582
596
  updateVideoTransform(resetCrop: true)
583
597
  }
584
598
 
585
- private func updateVideoTransform(resetCrop: Bool = false) {
599
+ private func buildVideoTransform() -> CGAffineTransform {
586
600
  let angle = -CGFloat(rotationCount) * (.pi / 2)
587
601
  var transform = CGAffineTransform.identity
588
-
589
602
  if isFlipped {
590
603
  transform = transform.scaledBy(x: -1, y: 1)
591
604
  }
592
605
  transform = transform.rotated(by: angle)
593
-
594
606
  if rotationCount % 2 != 0 {
595
- let bounds = playerContainerView.bounds
596
- if bounds.width > 0 && bounds.height > 0 {
597
- let fitScale = min(bounds.width / bounds.height, bounds.height / bounds.width)
607
+ let pvBounds = playerController.view.bounds
608
+ let cBounds = playerContainerView.bounds
609
+ if pvBounds.width > 0 && pvBounds.height > 0 && cBounds.width > 0 && cBounds.height > 0 {
610
+ var videoW = pvBounds.width
611
+ var videoH = pvBounds.height
612
+ if let track = asset?.tracks(withMediaType: .video).first {
613
+ let raw = track.naturalSize
614
+ let pt = track.preferredTransform
615
+ let a = atan2(pt.b, pt.a)
616
+ let srcRotated = abs(a - .pi / 2) < 0.1 || abs(a + .pi / 2) < 0.1
617
+ let ds = srcRotated ? CGSize(width: raw.height, height: raw.width) : raw
618
+ if ds.width > 0 && ds.height > 0 {
619
+ let videoAR = ds.width / ds.height
620
+ let viewAR = pvBounds.width / pvBounds.height
621
+ if videoAR > viewAR {
622
+ videoW = pvBounds.width
623
+ videoH = pvBounds.width / videoAR
624
+ } else {
625
+ videoH = pvBounds.height
626
+ videoW = pvBounds.height * videoAR
627
+ }
628
+ }
629
+ }
630
+ let bracketMargin: CGFloat = 5
631
+ let availW = cBounds.width - 2 * bracketMargin
632
+ let availH = cBounds.height - 2 * bracketMargin
633
+ let fitScale = min(availW / videoH, availH / videoW)
598
634
  transform = transform.scaledBy(x: fitScale, y: fitScale)
599
635
  }
600
636
  }
601
-
637
+ return transform
638
+ }
639
+
640
+ private func updateVideoTransform(resetCrop: Bool = false) {
641
+ let transform = buildVideoTransform()
642
+ if isCropActive {
643
+ UIView.animate(withDuration: 0.15) {
644
+ self.cropOverlayView?.alpha = 0
645
+ }
646
+ }
602
647
  UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) {
603
648
  self.playerController.view.transform = transform
604
649
  } completion: { _ in
605
650
  if resetCrop && self.isCropActive {
606
651
  self.updateCropAllowedRect()
607
652
  self.cropOverlayView?.resetCrop()
653
+ UIView.animate(withDuration: 0.15) {
654
+ self.cropOverlayView?.alpha = 1
655
+ }
608
656
  }
609
657
  }
610
658
  }
@@ -644,21 +692,11 @@ class VideoTrimmerViewController: UIViewController {
644
692
  rotationCount = snap.rotationCount
645
693
  isFlipped = snap.isFlipped
646
694
 
647
- let angle = -CGFloat(rotationCount) * (.pi / 2)
648
- var transform = CGAffineTransform.identity
649
- if isFlipped { transform = transform.scaledBy(x: -1, y: 1) }
650
- transform = transform.rotated(by: angle)
651
- if rotationCount % 2 != 0 {
652
- let bounds = playerContainerView.bounds
653
- if bounds.width > 0 && bounds.height > 0 {
654
- let fitScale = min(bounds.width / bounds.height, bounds.height / bounds.width)
655
- transform = transform.scaledBy(x: fitScale, y: fitScale)
656
- }
657
- }
695
+ let transform = buildVideoTransform()
658
696
 
659
697
  let wasActive = isCropActive
660
698
  isCropActive = snap.isCropActive
661
- cropBtn?.tintColor = isCropActive ? .white : UIColor.white.withAlphaComponent(0.5)
699
+ cropBtn?.tintColor = isCropActive ? iconColor : dimmedIconColor
662
700
 
663
701
  UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) {
664
702
  self.playerController.view.transform = transform
@@ -690,10 +728,9 @@ class VideoTrimmerViewController: UIViewController {
690
728
  }
691
729
 
692
730
  private func updateUndoRedoButtons() {
693
- let dimmed = UIColor.white.withAlphaComponent(0.5)
694
- undoBtn?.tintColor = undoStack.isEmpty ? dimmed : .white
731
+ undoBtn?.tintColor = undoStack.isEmpty ? dimmedIconColor : iconColor
695
732
  undoBtn?.isEnabled = !undoStack.isEmpty
696
- redoBtn?.tintColor = redoStack.isEmpty ? dimmed : .white
733
+ redoBtn?.tintColor = redoStack.isEmpty ? dimmedIconColor : iconColor
697
734
  redoBtn?.isEnabled = !redoStack.isEmpty
698
735
  }
699
736
 
@@ -701,7 +738,7 @@ class VideoTrimmerViewController: UIViewController {
701
738
 
702
739
  @objc private func onCropTapped() {
703
740
  isCropActive.toggle()
704
- cropBtn?.tintColor = isCropActive ? .white : UIColor.white.withAlphaComponent(0.5)
741
+ cropBtn?.tintColor = isCropActive ? iconColor : dimmedIconColor
705
742
 
706
743
  if enableHapticFeedback {
707
744
  UIImpactFeedbackGenerator(style: .light).impactOccurred()
@@ -742,6 +779,7 @@ class VideoTrimmerViewController: UIViewController {
742
779
 
743
780
  private func createCropOverlay() {
744
781
  let overlay = CropOverlayView()
782
+ overlay.isLightTheme = isLightTheme
745
783
  overlay.translatesAutoresizingMaskIntoConstraints = false
746
784
  overlay.alpha = 0
747
785
  playerContainerView.addSubview(overlay)
@@ -915,6 +953,8 @@ class VideoTrimmerViewController: UIViewController {
915
953
  minimumDuration = minDuration
916
954
  }
917
955
 
956
+ isLightTheme = (config["theme"] as? String) == "light"
957
+
918
958
  cancelButtonText = config["cancelButtonText"] as? String ?? "Cancel"
919
959
  saveButtonText = config["saveButtonText"] as? String ?? "Save"
920
960
  jumpToPositionOnLoad = config["jumpToPositionOnLoad"] as? Double ?? 0
@@ -926,12 +966,11 @@ class VideoTrimmerViewController: UIViewController {
926
966
  headerTextSize = config["headerTextSize"] as? Int ?? 16
927
967
  headerTextColor = config["headerTextColor"] as? Double
928
968
 
929
- // Handle new color properties
930
969
  if let trimmerColorValue = config["trimmerColor"] as? Double {
931
970
  trimmerColor = RCTConvert.uiColor(trimmerColorValue) ?? UIColor.systemYellow
932
971
  }
933
972
  if let handleIconColorValue = config["handleIconColor"] as? Double {
934
- handleIconColor = RCTConvert.uiColor(handleIconColorValue) ?? UIColor.black
973
+ handleIconColor = RCTConvert.uiColor(handleIconColorValue) ?? (isLightTheme ? .white : .black)
935
974
  }
936
975
  }
937
976
 
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAGlD;AACA;AACA;;AAwBA;AACA;AACA;;AAgGA;AACA;AACA;;AAQA;AACA;AACA;;AAUA;AACA;AACA;;AAcA;AACA;AACA;;AAmEA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,WAAW,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeVideoTrim.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAGlD;AACA;AACA;;AAwBA;AACA;AACA;;AAqGA;AACA;AACA;;AAQA;AACA;AACA;;AAUA;AACA;AACA;;AAcA;AACA;AACA;;AAmEA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,WAAW,CAAC","ignoreList":[]}
@@ -90,9 +90,10 @@ export function showEditor(filePath, config) {
90
90
  trimmerColor,
91
91
  handleIconColor
92
92
  } = config;
93
- const _headerTextColor = processColor(headerTextColor || 'white');
93
+ const isLight = config.theme === 'light';
94
+ const _headerTextColor = processColor(headerTextColor || (isLight ? 'black' : 'white'));
94
95
  const _trimmerColor = processColor(trimmerColor || '#f1d247');
95
- const _handleIconColor = processColor(handleIconColor || 'black');
96
+ const _handleIconColor = processColor(handleIconColor || (isLight ? 'white' : 'black'));
96
97
  VideoTrim.showEditor(filePath, createEditorConfig({
97
98
  ...config,
98
99
  headerTextColor: _headerTextColor,
@@ -1 +1 @@
1
- {"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","enablePreciseTrimming","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","cancelButtonText","saveButtonText","enableCancelDialog","cancelDialogTitle","cancelDialogMessage","cancelDialogCancelText","cancelDialogConfirmText","enableSaveDialog","saveDialogTitle","saveDialogMessage","saveDialogCancelText","saveDialogConfirmText","trimmingText","fullScreenModalIOS","autoplay","jumpToPositionOnLoad","closeWhenFinish","enableCancelTrimming","cancelTrimmingButtonText","enableCancelTrimmingDialog","cancelTrimmingDialogTitle","cancelTrimmingDialogMessage","cancelTrimmingDialogCancelText","cancelTrimmingDialogConfirmText","headerText","headerTextSize","headerTextColor","trimmerColor","handleIconColor","zoomOnWaitingDuration","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","_headerTextColor","_trimmerColor","_handleIconColor","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["VideoTrimNewArch","VideoTrimOldArch","processColor","isFabric","global","nativeFabricUIManager","VideoTrim","createBaseOptions","overrides","saveToPhoto","type","outputExt","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","enablePreciseTrimming","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","cancelButtonText","saveButtonText","enableCancelDialog","cancelDialogTitle","cancelDialogMessage","cancelDialogCancelText","cancelDialogConfirmText","enableSaveDialog","saveDialogTitle","saveDialogMessage","saveDialogCancelText","saveDialogConfirmText","trimmingText","fullScreenModalIOS","autoplay","jumpToPositionOnLoad","closeWhenFinish","enableCancelTrimming","cancelTrimmingButtonText","enableCancelTrimmingDialog","cancelTrimmingDialogTitle","cancelTrimmingDialogMessage","cancelTrimmingDialogCancelText","cancelTrimmingDialogConfirmText","headerText","headerTextSize","headerTextColor","trimmerColor","handleIconColor","zoomOnWaitingDuration","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","isLight","theme","_headerTextColor","_trimmerColor","_handleIconColor","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -121,6 +121,11 @@ export interface EditorConfig extends BaseOptions {
121
121
  * this duration around the current trim position for more precise editing.
122
122
  */
123
123
  zoomOnWaitingDuration?: number;
124
+ /**
125
+ * Editor theme. `"dark"` (default) uses a black background with white UI elements.
126
+ * `"light"` uses a white background with black icons/text and white trimmer-handle chevrons.
127
+ */
128
+ theme?: string;
124
129
  }
125
130
  /**
126
131
  * Options for headless (non-UI) trim operations.
@@ -1 +1 @@
1
- {"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NativeVideoTrim.d.ts","sourceRoot":"","sources":["../../../src/NativeVideoTrim.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,UAAU,EACX,MAAM,mBAAmB,CAAC;AAK3B,QAAA,MAAM,SAAS,KAAiD,CAAC;AA4EjE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CACb,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAC3E,GAAG;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CAeN;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,cAAc,mBAAmB,CAAC;AAClC,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,UAAU,EACX,MAAM,mBAAmB,CAAC;AAK3B,QAAA,MAAM,SAAS,KAAiD,CAAC;AA4EjE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CACb,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAC3E,GAAG;IACF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CAoBN;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CAErB;AAED,cAAc,mBAAmB,CAAC;AAClC,eAAe,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-video-trim",
3
- "version": "7.0.0",
3
+ "version": "7.1.0",
4
4
  "description": "Video trimmer for your React Native app",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -124,6 +124,11 @@ export interface EditorConfig extends BaseOptions {
124
124
  * this duration around the current trim position for more precise editing.
125
125
  */
126
126
  zoomOnWaitingDuration?: number;
127
+ /**
128
+ * Editor theme. `"dark"` (default) uses a black background with white UI elements.
129
+ * `"light"` uses a white background with black icons/text and white trimmer-handle chevrons.
130
+ */
131
+ theme?: string;
127
132
  }
128
133
 
129
134
  /**
package/src/index.tsx CHANGED
@@ -106,9 +106,14 @@ export function showEditor(
106
106
  }
107
107
  ): void {
108
108
  const { headerTextColor, trimmerColor, handleIconColor } = config;
109
- const _headerTextColor = processColor(headerTextColor || 'white');
109
+ const isLight = config.theme === 'light';
110
+ const _headerTextColor = processColor(
111
+ headerTextColor || (isLight ? 'black' : 'white')
112
+ );
110
113
  const _trimmerColor = processColor(trimmerColor || '#f1d247');
111
- const _handleIconColor = processColor(handleIconColor || 'black');
114
+ const _handleIconColor = processColor(
115
+ handleIconColor || (isLight ? 'white' : 'black')
116
+ );
112
117
 
113
118
  VideoTrim.showEditor(
114
119
  filePath,