react-native-video-trim 5.1.0 → 6.0.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
@@ -1,6 +1,7 @@
1
1
  # Table of contents
2
2
  - [Installation](#installation)
3
3
  * [For iOS (React Native CLI project)](#for-ios-react-native-cli-project)
4
+ * [For Android New Arch (React Native CLI project)](#for-android-new-arch-react-native-cli-project)
4
5
  * [For Expo project](#for-expo-project)
5
6
  * [Usage](#usage)
6
7
  - [Methods](#methods)
@@ -11,10 +12,7 @@
11
12
  * [listFiles()](#listfiles)
12
13
  * [cleanFiles()](#cleanfiles)
13
14
  * [deleteFile()](#deletefile)
14
- - [Callbacks (New arch)](#callbacks-new-arch)
15
- * [showEditor](#showeditor)
16
- * [closeEditor](#closeeditor-1)
17
- - [Audio support](#audio-support)
15
+ - [Audio only support](#audio-only-support)
18
16
  - [Cancel trimming](#cancel-trimming)
19
17
  - [Fail to load media](#fail-to-load-media)
20
18
  - [Rotation](#rotation)
@@ -45,35 +43,38 @@
45
43
 
46
44
  # Installation
47
45
 
46
+ Both new + old arch are supported in a single distribution
47
+
48
48
  ```sh
49
- # new arch
50
49
  npm install react-native-video-trim
51
50
 
52
- # old arch
53
- npm install react-native-video-trim@^3.0.0
54
-
55
51
  # or with yarn
56
-
57
- # new arch
58
52
  yarn add react-native-video-trim
59
53
 
60
- # old arch
61
- yarn add react-native-video-trim@^3.0.0
62
54
  ```
63
55
 
64
- ## For iOS (React Native CLI project)
56
+ ## iOS (RN CLI project)
65
57
  Run the following command to setup for iOS:
66
58
  ```
67
59
  npx pod-install ios
68
60
  ```
61
+ ## Android New Arch (RN CLI project)
62
+ If you are using New Arch, in `android` folder run:
63
+ ```
64
+ ./gradlew generateCodegenArtifactsFromSchema
65
+ ```
69
66
  ## For Expo project
70
67
  You need to run `prebuild` in order for native code takes effect:
71
68
  ```
72
69
  npx expo prebuild
73
70
  ```
74
- Then you need to restart to make the changes take effect
71
+ Then you should to restart to make the changes take effect
72
+
73
+ Note that on iOS, Expo Go may not work because of library linking, you may see this error:
75
74
 
76
- > Note that on iOS you'll need to run on real device, Expo Go may not work because of library linking
75
+ <img src="images/expo_error.PNG" width="150" />
76
+
77
+ To avoid the error, you should open `ios/yourproject.xcworkspace` then manually build and run your app
77
78
 
78
79
  ## Usage
79
80
 
@@ -90,7 +91,10 @@ showEditor(videoUrl, {
90
91
  maxDuration: 20,
91
92
  });
92
93
  ```
93
- Usually this library will be used along with other library to select video file, Eg. [react-native-image-picker](https://github.com/react-native-image-picker/react-native-image-picker). Below is real world example:
94
+ Usually this library will be used along with other library to select video file, Eg. [react-native-image-picker](https://github.com/react-native-image-picker/react-native-image-picker). Below are real world examples:
95
+
96
+ <details>
97
+ <summary>New Arch usage</summary>
94
98
 
95
99
  ```jsx
96
100
  import * as React from 'react';
@@ -100,51 +104,49 @@ import {
100
104
  View,
101
105
  Text,
102
106
  TouchableOpacity,
103
- NativeEventEmitter,
104
- NativeModules,
105
107
  type EventSubscription,
106
108
  } from 'react-native';
107
- import { isValidFile, showEditor } from 'react-native-video-trim';
109
+ import { isValidFile, showEditor, type Spec } from 'react-native-video-trim';
108
110
  import { launchImageLibrary } from 'react-native-image-picker';
109
111
 
110
112
  export default function App() {
111
113
  const listenerSubscription = useRef<Record<string, EventSubscription>>({});
112
114
 
113
115
  useEffect(() => {
114
- listenerSubscription.current.onLoad = NativeVideoTrim.onLoad(
116
+ listenerSubscription.current.onLoad = (NativeVideoTrim as Spec).onLoad(
115
117
  ({ duration }) => console.log('onLoad', duration)
116
118
  );
117
119
 
118
120
  listenerSubscription.current.onStartTrimming =
119
- NativeVideoTrim.onStartTrimming(() => console.log('onStartTrimming'));
121
+ (NativeVideoTrim as Spec).onStartTrimming(() => console.log('onStartTrimming'));
120
122
 
121
123
  listenerSubscription.current.onCancelTrimming =
122
- NativeVideoTrim.onCancelTrimming(() => console.log('onCancelTrimming'));
123
- listenerSubscription.current.onCancel = NativeVideoTrim.onCancel(() =>
124
+ (NativeVideoTrim as Spec).onCancelTrimming(() => console.log('onCancelTrimming'));
125
+ listenerSubscription.current.onCancel = (NativeVideoTrim as Spec).onCancel(() =>
124
126
  console.log('onCancel')
125
127
  );
126
- listenerSubscription.current.onHide = NativeVideoTrim.onHide(() =>
128
+ listenerSubscription.current.onHide = (NativeVideoTrim as Spec).onHide(() =>
127
129
  console.log('onHide')
128
130
  );
129
- listenerSubscription.current.onShow = NativeVideoTrim.onShow(() =>
131
+ listenerSubscription.current.onShow = (NativeVideoTrim as Spec).onShow(() =>
130
132
  console.log('onShow')
131
133
  );
132
134
  listenerSubscription.current.onFinishTrimming =
133
- NativeVideoTrim.onFinishTrimming(
135
+ (NativeVideoTrim as Spec).onFinishTrimming(
134
136
  ({ outputPath, startTime, endTime, duration }) =>
135
137
  console.log(
136
138
  'onFinishTrimming',
137
139
  `outputPath: ${outputPath}, startTime: ${startTime}, endTime: ${endTime}, duration: ${duration}`
138
140
  )
139
141
  );
140
- listenerSubscription.current.onLog = NativeVideoTrim.onLog(
142
+ listenerSubscription.current.onLog = (NativeVideoTrim as Spec).onLog(
141
143
  ({ level, message, sessionId }) =>
142
144
  console.log(
143
145
  'onLog',
144
146
  `level: ${level}, message: ${message}, sessionId: ${sessionId}`
145
147
  )
146
148
  );
147
- listenerSubscription.current.onStatistics = NativeVideoTrim.onStatistics(
149
+ listenerSubscription.current.onStatistics = (NativeVideoTrim as Spec).onStatistics(
148
150
  ({
149
151
  sessionId,
150
152
  videoFrameNumber,
@@ -160,7 +162,7 @@ export default function App() {
160
162
  `sessionId: ${sessionId}, videoFrameNumber: ${videoFrameNumber}, videoFps: ${videoFps}, videoQuality: ${videoQuality}, size: ${size}, time: ${time}, bitrate: ${bitrate}, speed: ${speed}`
161
163
  )
162
164
  );
163
- listenerSubscription.current.onError = NativeVideoTrim.onError(
165
+ listenerSubscription.current.onError = (NativeVideoTrim as Spec).onError(
164
166
  ({ message, errorCode }) =>
165
167
  console.log('onError', `message: ${message}, errorCode: ${errorCode}`)
166
168
  );
@@ -225,6 +227,130 @@ const styles = StyleSheet.create({
225
227
  },
226
228
  });
227
229
  ```
230
+ </details>
231
+
232
+ <br />
233
+
234
+ <details>
235
+ <summary>Old Arch usage</summary>
236
+
237
+ ```jsx
238
+ import * as React from 'react';
239
+
240
+ import {
241
+ StyleSheet,
242
+ View,
243
+ Text,
244
+ TouchableOpacity,
245
+ NativeEventEmitter,
246
+ NativeModules,
247
+ } from 'react-native';
248
+ import { isValidFile, showEditor } from 'react-native-video-trim';
249
+ import { launchImageLibrary } from 'react-native-image-picker';
250
+
251
+ export default function App() {
252
+ useEffect(() => {
253
+ const eventEmitter = new NativeEventEmitter(NativeModules.VideoTrim);
254
+ const subscription = eventEmitter.addListener('VideoTrim', (event) => {
255
+ switch (event.name) {
256
+ case 'onLoad': {
257
+ console.log('onLoadListener', event);
258
+ break;
259
+ }
260
+ case 'onShow': {
261
+ console.log('onShowListener', event);
262
+ break;
263
+ }
264
+ case 'onHide': {
265
+ console.log('onHide', event);
266
+ break;
267
+ }
268
+ case 'onStartTrimming': {
269
+ console.log('onStartTrimming', event);
270
+ break;
271
+ }
272
+ case 'onFinishTrimming': {
273
+ console.log('onFinishTrimming', event);
274
+ break;
275
+ }
276
+ case 'onCancelTrimming': {
277
+ console.log('onCancelTrimming', event);
278
+ break;
279
+ }
280
+ case 'onCancel': {
281
+ console.log('onCancel', event);
282
+ break;
283
+ }
284
+ case 'onError': {
285
+ console.log('onError', event);
286
+ break;
287
+ }
288
+ case 'onLog': {
289
+ console.log('onLog', event);
290
+ break;
291
+ }
292
+ case 'onStatistics': {
293
+ console.log('onStatistics', event);
294
+ break;
295
+ }
296
+ }
297
+ });
298
+
299
+ return () => {
300
+ subscription.remove();
301
+ };
302
+ }, []);
303
+
304
+ return (
305
+ <View style={styles.container}>
306
+ <TouchableOpacity
307
+ onPress={async () => {
308
+ const result = await launchImageLibrary({
309
+ mediaType: 'video',
310
+ assetRepresentationMode: 'current',
311
+ });
312
+
313
+ isValidFile(result.assets![0]?.uri || '').then((res) =>
314
+ console.log(res)
315
+ );
316
+
317
+ showEditor(result.assets![0]?.uri || '', {
318
+ maxDuration: 20,
319
+ });
320
+ }}
321
+ style={{ padding: 10, backgroundColor: 'red' }}
322
+ >
323
+ <Text>Launch Library</Text>
324
+ </TouchableOpacity>
325
+ <TouchableOpacity
326
+ onPress={() => {
327
+ isValidFile('invalid file path').then((res) => console.log(res));
328
+ }}
329
+ style={{
330
+ padding: 10,
331
+ backgroundColor: 'blue',
332
+ marginTop: 20,
333
+ }}
334
+ >
335
+ <Text>Check Video Valid</Text>
336
+ </TouchableOpacity>
337
+ </View>
338
+ );
339
+ }
340
+
341
+ const styles = StyleSheet.create({
342
+ container: {
343
+ flex: 1,
344
+ alignItems: 'center',
345
+ justifyContent: 'center',
346
+ },
347
+ });
348
+ ```
349
+ </details>
350
+
351
+ <br />
352
+
353
+ Checkout [Example folder](./example/src/) for more details
228
354
 
229
355
  # Methods
230
356
 
@@ -282,7 +408,7 @@ Main method to show Video Editor UI.
282
408
  - `alertOnFailCloseText` (`default = "Close"`)
283
409
  - `enableRotation` (`default = false`)
284
410
  - `rotationAngle` (`default = 0`)
285
- - `changeStatusBarColorOnOpen` (`default = false`): Update status bar color to black background color when editor is opened (useful in somecases where your theme has titlebar in different color than black)
411
+ - `changeStatusBarColorOnOpen` (`default = false`): (Android only) Update status bar color to black background color when editor is opened (useful in somecases where your theme has titlebar in different color than black)
286
412
 
287
413
  If `saveToPhoto = true`, you must ensure that you have request permission to write to photo/gallery
288
414
  - For Android: you need to have `<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />` in AndroidManifest.xml
@@ -334,21 +460,7 @@ Clean all generated output files in app storage. Return number of successfully d
334
460
  ## deleteFile()
335
461
  Delete a file in app storage. Return `true` if success
336
462
 
337
- # Callbacks (New arch)
338
-
339
- ## showEditor
340
-
341
- ```ts
342
- showEditor('file', config)
343
- ```
344
-
345
- ## closeEditor
346
-
347
- ```ts
348
- closeEditor()
349
- ```
350
-
351
- # Audio support
463
+ # Audio only support
352
464
  <div align="left">
353
465
  <img src="images/audio_android.jpg" width="200" />
354
466
  <img src="images/audio_ios.jpg" width="200" />
@@ -19,7 +19,9 @@ buildscript {
19
19
  apply plugin: "com.android.library"
20
20
  apply plugin: "kotlin-android"
21
21
 
22
- apply plugin: "com.facebook.react"
22
+ if (isNewArchitectureEnabled()) {
23
+ apply plugin: "com.facebook.react"
24
+ }
23
25
 
24
26
  def getExtOrIntegerDefault(name) {
25
27
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["VideoTrim_" + name]).toInteger()
@@ -33,6 +35,10 @@ def getPackageVersionOrDefault() {
33
35
  return rootProject.ext.has("VideoTrim_ffmpeg_version") ? rootProject.ext.get("VideoTrim_ffmpeg_version") : project.properties["VideoTrim_ffmpeg_version"]
34
36
  }
35
37
 
38
+ def isNewArchitectureEnabled() {
39
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
40
+ }
41
+
36
42
  android {
37
43
  namespace "com.videotrim"
38
44
 
@@ -41,6 +47,7 @@ android {
41
47
  defaultConfig {
42
48
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
43
49
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
50
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
44
51
  }
45
52
 
46
53
  buildFeatures {
@@ -64,10 +71,16 @@ android {
64
71
 
65
72
  sourceSets {
66
73
  main {
67
- java.srcDirs += [
68
- "generated/java",
69
- "generated/jni"
70
- ]
74
+ if (isNewArchitectureEnabled()) {
75
+ java.srcDirs += [
76
+ "src/newarch",
77
+ // Codegen specs
78
+ "generated/java",
79
+ "generated/jni"
80
+ ]
81
+ } else {
82
+ java.srcDirs += "src/oldarch"
83
+ }
71
84
  }
72
85
  }
73
86
  }
@@ -85,8 +98,10 @@ dependencies {
85
98
  implementation 'io.github.maitrungduc1410:ffmpeg-kit-' + getPackageNameOrDefault() +':' + getPackageVersionOrDefault()
86
99
  }
87
100
 
88
- react {
89
- jsRootDir = file("../src/")
90
- libraryName = "VideoTrim"
91
- codegenJavaPackageName = "com.videotrim"
101
+ if (isNewArchitectureEnabled()) {
102
+ react {
103
+ jsRootDir = file("../src/")
104
+ libraryName = "VideoTrim"
105
+ codegenJavaPackageName = "com.videotrim"
106
+ }
92
107
  }
@@ -17,7 +17,6 @@ import android.util.TypedValue
17
17
  import android.view.Gravity
18
18
  import android.view.View
19
19
  import android.view.ViewGroup
20
- import android.view.Window
21
20
  import android.view.WindowManager
22
21
  import android.widget.Button
23
22
  import android.widget.LinearLayout
@@ -32,8 +31,14 @@ import androidx.core.view.ViewCompat
32
31
  import androidx.core.view.WindowInsetsCompat
33
32
  import com.arthenica.ffmpegkit.FFmpegKit
34
33
  import com.arthenica.ffmpegkit.ReturnCode
35
- import com.facebook.react.bridge.*
36
- import com.facebook.react.module.annotations.ReactModule
34
+ import com.facebook.react.bridge.Arguments
35
+ import com.facebook.react.bridge.BaseActivityEventListener
36
+ import com.facebook.react.bridge.LifecycleEventListener
37
+ import com.facebook.react.bridge.Promise
38
+ import com.facebook.react.bridge.ReactApplicationContext
39
+ import com.facebook.react.bridge.ReadableMap
40
+ import com.facebook.react.bridge.UiThreadUtil
41
+ import com.facebook.react.bridge.WritableMap
37
42
  import com.videotrim.enums.ErrorCode
38
43
  import com.videotrim.interfaces.VideoTrimListener
39
44
  import com.videotrim.utils.MediaMetadataUtil
@@ -47,9 +52,14 @@ import java.text.SimpleDateFormat
47
52
  import java.util.Date
48
53
  import java.util.TimeZone
49
54
 
50
- @ReactModule(name = VideoTrimModule.NAME)
51
- class VideoTrimModule(reactContext: ReactApplicationContext) :
52
- NativeVideoTrimSpec(reactContext), VideoTrimListener, LifecycleEventListener {
55
+ /**
56
+ * Contains all shared business logic between old + new arch.
57
+ * Does NOT know how to emit events.
58
+ */
59
+ open class BaseVideoTrimModule internal constructor(
60
+ private val reactApplicationContext: ReactApplicationContext,
61
+ private val sendEvent: (eventName: String, params: WritableMap?) -> Unit
62
+ ) : VideoTrimListener, LifecycleEventListener {
53
63
 
54
64
  private var isInit: Boolean = false
55
65
  private var trimmerView: VideoTrimmerView? = null
@@ -62,6 +72,8 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
62
72
  private var editorConfig: ReadableMap? = null
63
73
  private var trimOptions: ReadableMap? = null
64
74
  private var originalStatusBarColor: Int = Color.TRANSPARENT
75
+ private val shouldChangeStatusBarColorOnOpen: Boolean
76
+ get() = editorConfig?.hasKey("changeStatusBarColorOnOpen") == true && editorConfig?.getBoolean("changeStatusBarColorOnOpen") == true
65
77
 
66
78
  init {
67
79
  val mActivityEventListener = object : BaseActivityEventListener() {
@@ -114,7 +126,8 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
114
126
  reactApplicationContext.addActivityEventListener(mActivityEventListener)
115
127
  }
116
128
 
117
- override fun showEditor(
129
+
130
+ fun showEditor(
118
131
  filePath: String,
119
132
  config: ReadableMap,
120
133
  ) {
@@ -149,7 +162,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
149
162
  alertDialog?.setOnShowListener {
150
163
  applySafeAreaToDialog(alertDialog!!, trimmerView!!)
151
164
 
152
- emitOnShow()
165
+ sendEvent("onShow", null)
153
166
  }
154
167
 
155
168
  // this is to ensure to release resource if dialog is dismissed in unexpected way (Eg. open control/notification center by dragging from top of screen)
@@ -160,7 +173,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
160
173
  trimmerView = null
161
174
  }
162
175
  hideDialog(true)
163
- emitOnHide()
176
+ sendEvent("onHide", null)
164
177
  }
165
178
 
166
179
  alertDialog?.show()
@@ -196,8 +209,8 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
196
209
 
197
210
  // 2. restore flags to their previous state
198
211
  // For most cases, just setting the color is enough.
199
- it.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
200
- it.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
212
+ it.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
213
+ it.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
201
214
  }
202
215
  }
203
216
 
@@ -249,15 +262,15 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
249
262
  hideDialog(true)
250
263
  }
251
264
 
252
- override fun invalidate() {
253
- super.invalidate()
254
- hideDialog(true)
255
- }
265
+ // override fun invalidate() {
266
+ // super.invalidate()
267
+ // hideDialog(true)
268
+ // }
256
269
 
257
270
  override fun onLoad(duration: Int) {
258
271
  val map = Arguments.createMap()
259
272
  map.putInt("duration", duration)
260
- emitOnLoad(map)
273
+ sendEvent("onLoad", map)
261
274
  }
262
275
 
263
276
  override fun onTrimmingProgress(percentage: Int) {
@@ -279,7 +292,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
279
292
  map.putInt("duration", duration)
280
293
  map.putDouble("startTime", startTime.toDouble())
281
294
  map.putDouble("endTime", endTime.toDouble())
282
- emitOnFinishTrimming(map)
295
+ sendEvent("onFinishTrimming", map)
283
296
 
284
297
  if (editorConfig?.getBoolean("saveToPhoto") == true && isVideoType) {
285
298
  try {
@@ -311,19 +324,19 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
311
324
  }
312
325
 
313
326
  override fun onCancelTrim() {
314
- emitOnCancelTrimming()
327
+ sendEvent("onCancelTrimming", null)
315
328
  }
316
329
 
317
330
  override fun onError(errorMessage: String?, errorCode: ErrorCode) {
318
331
  val map = Arguments.createMap()
319
332
  map.putString("message", errorMessage)
320
333
  map.putString("errorCode", errorCode.name)
321
- emitOnError(map)
334
+ sendEvent("onError", map)
322
335
  }
323
336
 
324
337
  override fun onCancel() {
325
338
  if (!editorConfig?.getBoolean("enableCancelDialog")!!) {
326
- emitOnCancel()
339
+ sendEvent("onCancel", null)
327
340
  hideDialog(true)
328
341
  return
329
342
  }
@@ -334,7 +347,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
334
347
  builder.setCancelable(false)
335
348
  builder.setPositiveButton(editorConfig?.getString("cancelDialogConfirmText")) { dialog: DialogInterface, _: Int ->
336
349
  dialog.cancel()
337
- emitOnCancel()
350
+ sendEvent("onCancel", null)
338
351
  hideDialog(true)
339
352
  }
340
353
  builder.setNegativeButton(
@@ -369,12 +382,12 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
369
382
  alertDialog.show()
370
383
  }
371
384
 
372
- override fun onLog(log: ReadableMap) {
373
- emitOnLog( log)
385
+ override fun onLog(log: WritableMap) {
386
+ sendEvent("onLog", log)
374
387
  }
375
388
 
376
- override fun onStatistics(statistics: ReadableMap) {
377
- emitOnStatistics(statistics)
389
+ override fun onStatistics(statistics: WritableMap) {
390
+ sendEvent("onStatistics", statistics)
378
391
  }
379
392
 
380
393
  private fun startTrim() {
@@ -478,7 +491,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
478
491
  mProgressDialog = builder.create()
479
492
 
480
493
  mProgressDialog!!.setOnShowListener {
481
- emitOnStartTrimming()
494
+ sendEvent("onStartTrimming", null)
482
495
  if (trimmerView != null) {
483
496
  trimmerView!!.onSaveClicked()
484
497
  }
@@ -516,45 +529,33 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
516
529
  }
517
530
  }
518
531
 
519
- // private fun sendEvent(
520
- // eventName: String,
521
- // params: Map<String, String>
522
- // ) {
523
- // onEvent?.let { it(eventName, params) }
524
- //
525
- // if (eventName == "onHide" && onComplete != null) {
526
- // onComplete?.let { it() }
527
- // onComplete = null // Clear the callback after invoking it
528
- // }
529
- // }
530
-
531
- override fun listFiles(promise: Promise) {
532
- promise.resolve(StorageUtil.listFiles(reactApplicationContext))
532
+ fun listFiles(promise: Promise) {
533
+ promise.resolve(Arguments.fromArray(StorageUtil.listFiles(reactApplicationContext)))
533
534
  }
534
535
 
535
- override fun cleanFiles(promise: Promise) {
536
- val files = StorageUtil.listFiles(reactApplicationContext)
537
- var successCount = 0
538
- for (file in files) {
539
- val state = StorageUtil.deleteFile(file)
540
- if (state) {
541
- successCount++
542
- }
536
+ fun cleanFiles(promise: Promise) {
537
+ val files = StorageUtil.listFiles(reactApplicationContext)
538
+ var successCount = 0
539
+ for (file in files) {
540
+ val state = StorageUtil.deleteFile(file)
541
+ if (state) {
542
+ successCount++
543
543
  }
544
+ }
544
545
 
545
- promise.resolve(successCount.toDouble())
546
+ promise.resolve(successCount.toDouble())
546
547
  }
547
548
 
548
- override fun deleteFile(filePath: String?, promise: Promise) {
549
- promise.resolve(StorageUtil.deleteFile(filePath))
549
+ fun deleteFile(filePath: String, promise: Promise) {
550
+ promise.resolve(StorageUtil.deleteFile(filePath))
550
551
  }
551
552
 
552
- override fun closeEditor() {
553
+ fun closeEditor() {
553
554
  hideDialog(true)
554
- emitOnHide()
555
+ sendEvent("onHide", null)
555
556
  }
556
557
 
557
- override fun isValidFile(url: String, promise: Promise) {
558
+ fun isValidFile(url: String, promise: Promise) {
558
559
  MediaMetadataUtil.checkFileValidity(url) { isValid: Boolean, fileType: String, duration: Long ->
559
560
  if (isValid) {
560
561
  Log.d(TAG, "Valid $fileType file with duration: $duration milliseconds")
@@ -572,7 +573,7 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
572
573
  }
573
574
  }
574
575
 
575
- override fun trim(url: String, options: ReadableMap?, promise: Promise) {
576
+ fun trim(url: String, options: ReadableMap?, promise: Promise) {
576
577
  trimOptions = options
577
578
 
578
579
  val currentDate = Date()
@@ -694,9 +695,6 @@ class VideoTrimModule(reactContext: ReactApplicationContext) :
694
695
  reactApplicationContext.currentActivity?.startActivity(Intent.createChooser(shareIntent, "Share file"))
695
696
  }
696
697
 
697
- val shouldChangeStatusBarColorOnOpen: Boolean
698
- get() = editorConfig?.hasKey("changeStatusBarColorOnOpen") == true && editorConfig?.getBoolean("changeStatusBarColorOnOpen") == true
699
-
700
698
  companion object {
701
699
  const val NAME = "VideoTrim"
702
700
  const val TAG = "VideoTrimModule"
@@ -1,6 +1,7 @@
1
1
  package com.videotrim.interfaces;
2
2
 
3
3
  import com.facebook.react.bridge.ReadableMap;
4
+ import com.facebook.react.bridge.WritableMap;
4
5
  import com.videotrim.enums.ErrorCode;
5
6
 
6
7
  import java.util.Map;
@@ -13,6 +14,6 @@ public interface VideoTrimListener {
13
14
  void onError(String errorMessage, ErrorCode errorCode);
14
15
  void onCancel();
15
16
  void onSave();
16
- void onLog(ReadableMap log);
17
- void onStatistics(ReadableMap statistics);
17
+ void onLog(WritableMap log);
18
+ void onStatistics(WritableMap statistics);
18
19
  }
@@ -17,9 +17,7 @@ import com.videotrim.interfaces.VideoTrimListener;
17
17
  import java.text.SimpleDateFormat;
18
18
  import java.util.ArrayList;
19
19
  import java.util.Date;
20
- import java.util.HashMap;
21
20
  import java.util.List;
22
- import java.util.Map;
23
21
  import java.util.TimeZone;
24
22
 
25
23
  import iknow.android.utils.DeviceUtil;
@@ -81,8 +79,14 @@ public class VideoTrimmerUtil {
81
79
  cmds.add(outputFile);
82
80
 
83
81
  String[] command = cmds.toArray(new String[0]);
82
+ String cmdStr = "Command: " + String.join(" ", command);
84
83
 
85
- Log.d(TAG,"Command: " + String.join(",", command));
84
+ Log.d(TAG, cmdStr);
85
+
86
+ WritableMap m = Arguments.createMap();
87
+ m.putString("message", cmdStr);
88
+
89
+ callback.onLog(m);
86
90
 
87
91
  return FFmpegKit.executeWithArgumentsAsync(command, session -> {
88
92
  SessionState state = session.getState();
@@ -0,0 +1,76 @@
1
+ package com.videotrim
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.Promise
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReadableMap
7
+ import com.facebook.react.bridge.WritableMap
8
+
9
+ class VideoTrimModule(
10
+ context: ReactApplicationContext
11
+ ) : VideoTrimSpec(context) {
12
+ // making BaseVideoTrimModule as abstract class then inherit from here doesn't work
13
+ // hence using composition instead of inheritance
14
+ private val base = BaseVideoTrimModule(
15
+ context
16
+ ) { eventName, params -> sendEvent(eventName, params) }
17
+
18
+ private fun sendEvent(eventName: String, params: WritableMap?) {
19
+ when (eventName) {
20
+ "onHide" -> emitOnHide()
21
+ "onShow" -> emitOnShow()
22
+ "onCancel" -> emitOnCancel()
23
+ "onStartTrimming" -> emitOnStartTrimming()
24
+ "onFinishTrimming" -> emitOnFinishTrimming(params)
25
+ "onCancelTrimming" -> emitOnCancelTrimming()
26
+ "onLog" -> emitOnLog(params)
27
+ "onStatistics" -> emitOnStatistics(params)
28
+ "onError" -> emitOnError(params)
29
+ "onLoad" -> emitOnLoad(params)
30
+ // default case to handle unexpected event names
31
+ else -> {
32
+ Log.d(NAME, "Unknown event: $eventName")
33
+ }
34
+ }
35
+ }
36
+
37
+ override fun showEditor(
38
+ filePath: String,
39
+ config: ReadableMap
40
+ ) {
41
+ base.showEditor(filePath, config)
42
+ }
43
+
44
+ override fun listFiles(promise: Promise) {
45
+ base.listFiles(promise)
46
+ }
47
+
48
+ override fun cleanFiles(promise: Promise) {
49
+ base.cleanFiles(promise)
50
+ }
51
+
52
+ override fun deleteFile(filePath: String, promise: Promise) {
53
+ base.deleteFile(filePath, promise)
54
+ }
55
+
56
+ override fun closeEditor() {
57
+ base.closeEditor()
58
+ }
59
+
60
+ override fun isValidFile(url: String, promise: Promise) {
61
+ base.isValidFile(url, promise)
62
+ }
63
+
64
+ override fun trim(
65
+ url: String,
66
+ options: ReadableMap,
67
+ promise: Promise
68
+ ) {
69
+ base.trim(url, options, promise)
70
+ }
71
+
72
+ companion object {
73
+ const val NAME = "VideoTrim"
74
+ }
75
+
76
+ }
@@ -0,0 +1,7 @@
1
+ package com.videotrim
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+
5
+ abstract class VideoTrimSpec internal constructor(context: ReactApplicationContext) :
6
+ NativeVideoTrimSpec(context) {
7
+ }
@@ -0,0 +1,75 @@
1
+ package com.videotrim
2
+
3
+ import com.facebook.react.bridge.ReactApplicationContext
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.bridge.WritableMap
6
+
7
+ import com.facebook.react.bridge.*
8
+ import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.modules.core.DeviceEventManagerModule
10
+
11
+
12
+ @ReactModule(name = VideoTrimModule.NAME)
13
+ class VideoTrimModule internal constructor(context: ReactApplicationContext) : VideoTrimSpec(context) {
14
+ // making BaseVideoTrimModule as abstract class then inherit from here doesn't work
15
+ // hence using composition instead of inheritance
16
+ private val base = BaseVideoTrimModule(
17
+ context
18
+ ) { eventName, params -> sendEvent(eventName, params) }
19
+
20
+
21
+ private fun sendEvent(eventName: String, params: WritableMap?) {
22
+ val map = params ?: Arguments.createMap()
23
+ map.putString("name", eventName)
24
+ reactApplicationContext
25
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
26
+ .emit(NAME, map)
27
+ }
28
+
29
+ override fun getName(): String {
30
+ return NAME
31
+ }
32
+
33
+ @ReactMethod
34
+ override fun showEditor(filePath: String, config: ReadableMap) {
35
+ base.showEditor(filePath, config)
36
+ }
37
+
38
+ @ReactMethod
39
+ override fun listFiles(promise: Promise) {
40
+ base.listFiles(promise)
41
+ }
42
+
43
+ @ReactMethod
44
+ override fun cleanFiles(promise: Promise) {
45
+ base.cleanFiles(promise)
46
+ }
47
+
48
+ @ReactMethod
49
+ override fun deleteFile(filePath: String, promise: Promise) {
50
+ base.deleteFile(filePath, promise)
51
+ }
52
+
53
+ @ReactMethod
54
+ override fun closeEditor() {
55
+ base.closeEditor()
56
+ }
57
+
58
+ @ReactMethod
59
+ override fun isValidFile(url: String, promise: Promise) {
60
+ base.isValidFile(url, promise)
61
+ }
62
+
63
+ @ReactMethod
64
+ override fun trim(
65
+ url: String,
66
+ options: ReadableMap?,
67
+ promise: Promise
68
+ ) {
69
+ base.trim(url, options, promise)
70
+ }
71
+
72
+ companion object {
73
+ const val NAME = "VideoTrim"
74
+ }
75
+ }
@@ -0,0 +1,24 @@
1
+ package com.videotrim
2
+
3
+ import com.facebook.react.bridge.Promise
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
6
+ import com.facebook.react.bridge.ReadableMap
7
+
8
+ abstract class VideoTrimSpec internal constructor(context: ReactApplicationContext) :
9
+ ReactContextBaseJavaModule(context) {
10
+
11
+ abstract fun showEditor(filePath: String, config: ReadableMap)
12
+
13
+ abstract fun listFiles(promise: Promise)
14
+
15
+ abstract fun cleanFiles(promise: Promise)
16
+
17
+ abstract fun deleteFile(filePath: String, promise: Promise)
18
+
19
+ abstract fun closeEditor()
20
+
21
+ abstract fun isValidFile(url: String, promise: Promise)
22
+
23
+ abstract fun trim(url: String, options: ReadableMap?, promise: Promise)
24
+ }
@@ -1 +1 @@
1
-
1
+ #import <React/RCTBridgeModule.h>
package/ios/VideoTrim.mm CHANGED
@@ -1,5 +1,12 @@
1
- #import "VideoTrim.h"
1
+ // because Swift class inherits from RCTEventEmitter, hence we need to import it here for both new and old arch
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ #ifdef RCT_NEW_ARCH_ENABLED
5
+
6
+ #import <VideoTrimSpec/VideoTrimSpec.h>
2
7
  #import <VideoTrim-Swift.h>
8
+ @interface VideoTrim : NativeVideoTrimSpecBase <NativeVideoTrimSpec, VideoTrimProtocol>
9
+ @end
3
10
 
4
11
  @implementation VideoTrim {
5
12
  VideoTrimSwift * _Nullable videoTrim;
@@ -45,9 +52,9 @@ RCT_EXPORT_MODULE()
45
52
  options:(JS::NativeVideoTrim::TrimOptions &)options
46
53
  resolve:(nonnull RCTPromiseResolveBlock)resolve
47
54
  reject:(nonnull RCTPromiseRejectBlock)reject {
48
- // TODO: implement
49
55
  if (!self->videoTrim) {
50
56
  self->videoTrim = [[VideoTrimSwift alloc] init];
57
+ self->videoTrim.isNewArch = true;
51
58
  }
52
59
 
53
60
  NSMutableDictionary *dict = [NSMutableDictionary dictionary];
@@ -83,6 +90,7 @@ RCT_EXPORT_MODULE()
83
90
  if (!self->videoTrim) {
84
91
  self->videoTrim = [[VideoTrimSwift alloc] init];
85
92
  self->videoTrim.delegate = self;
93
+ self->videoTrim.isNewArch = true;
86
94
  }
87
95
 
88
96
  NSMutableDictionary *dict = [NSMutableDictionary dictionary];
@@ -140,7 +148,7 @@ RCT_EXPORT_MODULE()
140
148
 
141
149
  - (void)closeEditor {
142
150
  if (self->videoTrim) {
143
- [self->videoTrim closeEditor];
151
+ [self->videoTrim closeEditor:0];
144
152
  }
145
153
  }
146
154
 
@@ -178,3 +186,27 @@ RCT_EXPORT_MODULE()
178
186
  }
179
187
 
180
188
  @end
189
+
190
+ #else
191
+
192
+ #import <React/RCTBridgeModule.h>
193
+
194
+ @interface RCT_EXTERN_REMAP_MODULE(VideoTrim, VideoTrimSwift, RCTEventEmitter)
195
+
196
+ RCT_EXTERN_METHOD(showEditor:(NSString*)uri withConfig:(NSDictionary *)config)
197
+ RCT_EXTERN_METHOD(listFiles:(RCTPromiseResolveBlock)resolve
198
+ withRejecter:(RCTPromiseRejectBlock)reject)
199
+ RCT_EXTERN_METHOD(cleanFiles:(RCTPromiseResolveBlock)resolve
200
+ withRejecter:(RCTPromiseRejectBlock)reject)
201
+ RCT_EXTERN_METHOD(deleteFile:(NSString*)uri withResolver:(RCTPromiseResolveBlock)resolve
202
+ withRejecter:(RCTPromiseRejectBlock)reject)
203
+ RCT_EXTERN_METHOD(closeEditor)
204
+ RCT_EXTERN_METHOD(isValidFile:(NSString*)uri withResolver:(RCTPromiseResolveBlock)resolve
205
+ withRejecter:(RCTPromiseRejectBlock)reject)
206
+ RCT_EXTERN_METHOD(trim:(NSString*)uri withConfig:(NSDictionary *)config
207
+ withResolver:(RCTPromiseResolveBlock)resolve
208
+ withRejecter:(RCTPromiseRejectBlock)reject)
209
+ @end
210
+
211
+ #endif
212
+
@@ -6,7 +6,7 @@ let FILE_PREFIX = "trimmedVideo"
6
6
  let BEFORE_TRIM_PREFIX = "beforeTrim"
7
7
 
8
8
  @objc(VideoTrimSwift)
9
- public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate {
9
+ public class VideoTrim: RCTEventEmitter, AssetLoaderDelegate, UIDocumentPickerDelegate {
10
10
  // MARK: instance private props
11
11
  private var isShowing = false
12
12
  private var vc: VideoTrimmerViewController?
@@ -210,10 +210,41 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
210
210
  }
211
211
 
212
212
  @objc public weak var delegate: VideoTrimProtocol?
213
+ @objc public var isNewArch = false
214
+
215
+
216
+
217
+ // MARK: for old arch
218
+ private var hasListeners = false
219
+
220
+ @objc
221
+ static public override func requiresMainQueueSetup() -> Bool {
222
+ return false
223
+ }
224
+
225
+ public override func supportedEvents() -> [String]! {
226
+ return ["VideoTrim"]
227
+ }
228
+
229
+ public override func startObserving() {
230
+ hasListeners = true
231
+ }
232
+
233
+ public override func stopObserving() {
234
+ hasListeners = false
235
+ }
213
236
 
214
237
 
215
238
  private func emitEventToJS(_ eventName: String, eventData: [String: Any]?) {
216
- delegate?.emitEventToJS(eventName: eventName, body: eventData)
239
+ if isNewArch {
240
+ delegate?.emitEventToJS(eventName: eventName, body: eventData)
241
+ } else {
242
+ if hasListeners {
243
+ var modifiedEventData = eventData ?? [:] // If eventData is nil, create an empty dictionary
244
+ modifiedEventData["name"] = eventName
245
+ sendEvent(withName: "VideoTrim", body: modifiedEventData)
246
+ }
247
+ }
217
248
  }
218
249
 
219
250
  private static func deleteFile(url: URL) -> Int {
@@ -381,7 +412,7 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
381
412
  }
382
413
 
383
414
  if self.closeWhenFinish {
384
- self.closeEditor()
415
+ self.closeEditor(delay: 500)
385
416
  }
386
417
 
387
418
  } else if ReturnCode.isCancel(returnCode) {
@@ -391,7 +422,7 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
391
422
  // FAILURE
392
423
  self.onError(message: "Command failed with state \(String(describing: FFmpegKitConfig.sessionState(toString: state ?? .failed))) and rc \(String(describing: returnCode)).\(String(describing: session?.getFailStackTrace()))", code: .trimmingFailed)
393
424
  if self.closeWhenFinish {
394
- self.closeEditor()
425
+ self.closeEditor(delay: 500)
395
426
  }
396
427
  }
397
428
 
@@ -433,6 +464,7 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
433
464
  })
434
465
  }
435
466
 
467
+ // New Arch
436
468
  @objc(trim:url:config:)
437
469
  public func _trim(inputFile: String, config: NSDictionary, completion: @escaping ([String: Any]?) -> Void) {
438
470
  var destPath: URL?
@@ -502,7 +534,13 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
502
534
  }, withLogCallback: nil, withStatisticsCallback: nil)
503
535
  }
504
536
 
505
-
537
+ // Old Arch
538
+ @objc(trim:withConfig:withResolver:withRejecter:)
539
+ func _trim(inputFile: String, config: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
540
+ _trim(inputFile: inputFile, config: config, completion: { payload in
541
+ resolve(payload)
542
+ })
543
+ }
506
544
 
507
545
  private func saveFileToFilesApp(fileURL: URL) {
508
546
  DispatchQueue.main.async {
@@ -602,6 +640,7 @@ public class VideoTrim: NSObject, AssetLoaderDelegate, UIDocumentPickerDelegate
602
640
 
603
641
  // MARK: @objc instance methods
604
642
  extension VideoTrim {
643
+ // Old + New arch
605
644
  @objc(showEditor:withConfig:)
606
645
  public func showEditor(uri: String, config: NSDictionary) {
607
646
  if isShowing {
@@ -679,10 +718,7 @@ extension VideoTrim {
679
718
  if !self.enableCancelDialog {
680
719
  self.emitEventToJS("onCancel", eventData: nil)
681
720
 
682
- vc.dismiss(animated: true, completion: {
683
- self.emitEventToJS("onHide", eventData: nil)
684
- self.isShowing = false
685
- })
721
+ self.closeEditor()
686
722
  return
687
723
  }
688
724
 
@@ -693,11 +729,7 @@ extension VideoTrim {
693
729
  // Create OK button with action handler
694
730
  let ok = UIAlertAction(title: self.cancelDialogConfirmText, style: .destructive, handler: { (action) -> Void in
695
731
  self.emitEventToJS("onCancel", eventData: nil)
696
-
697
- vc.dismiss(animated: true, completion: {
698
- self.emitEventToJS("onHide", eventData: nil)
699
- self.isShowing = false
700
- })
732
+ self.closeEditor()
701
733
  })
702
734
 
703
735
  // Create Cancel button with action handlder
@@ -760,31 +792,45 @@ extension VideoTrim {
760
792
  })
761
793
  }
762
794
  }
763
-
764
795
  }
765
796
 
766
- @objc(closeEditor)
767
- public func closeEditor() {
797
+ // New Arch
798
+ @objc(closeEditor:)
799
+ public func closeEditor(delay: Int = 0) {
768
800
  guard let vc = vc else { return }
769
801
  // some how in case we trim a very short video the view controller is still visible after first .dismiss call
770
802
  // even the file is successfully saved
771
803
  // that's why we need a small delay here to ensure vc will be dismissed
772
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
804
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(delay)) {
773
805
  vc.dismiss(animated: true, completion: {
774
806
  self.emitEventToJS("onHide", eventData: nil)
775
807
  self.isShowing = false
776
808
  })
777
809
  }
778
810
  }
811
+
812
+ // Old Arch
813
+ @objc(closeEditor)
814
+ func closeEditor() -> Void {
815
+ closeEditor()
816
+ }
779
817
  }
780
818
 
781
819
  // MARK: @objc static methods
782
820
  extension VideoTrim {
821
+ // New Arch
783
822
  @objc(listFiles)
784
823
  public static func _listFiles() -> [String] {
785
824
  return listFiles().map{ $0.absoluteString }
786
825
  }
787
826
 
827
+ // Old Arch
828
+ @objc(listFiles:withRejecter:)
829
+ func listFiles(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
830
+ resolve(VideoTrim._listFiles())
831
+ }
832
+
833
+ // New Arch
788
834
  @objc(cleanFiles)
789
835
  public static func cleanFiles() -> Int {
790
836
  let files = listFiles()
@@ -800,12 +846,25 @@ extension VideoTrim {
800
846
  return successCount
801
847
  }
802
848
 
849
+ // Old Arch
850
+ @objc(cleanFiles:withRejecter:)
851
+ func cleanFiles(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
852
+ resolve(VideoTrim.cleanFiles())
853
+ }
854
+
855
+ // New Arch
803
856
  @objc(deleteFile:)
804
857
  public static func deleteFile(uri: String) -> Bool {
805
858
  let state = deleteFile(url: URL(string: uri)!)
806
859
  return state == 0
807
860
  }
808
861
 
862
+ // Old Arch
863
+ @objc(deleteFile:withResolver:withRejecter:)
864
+ func deleteFile(uri: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
865
+ resolve(VideoTrim.deleteFile(uri: uri))
866
+ }
867
+
809
868
  private static func listFiles() -> [URL] {
810
869
  var files: [URL] = []
811
870
 
@@ -826,6 +885,7 @@ extension VideoTrim {
826
885
  return files
827
886
  }
828
887
 
888
+ // New Arch
829
889
  @objc(isValidFile:url:)
830
890
  public static func isValidFile(url: String, completion: @escaping ([String: Any]) -> Void) -> Void {
831
891
  let fileURL = URL(string: url)!
@@ -846,6 +906,15 @@ extension VideoTrim {
846
906
  }
847
907
  }
848
908
 
909
+ // Old Arch
910
+ @objc(isValidFile:withResolver:withRejecter:)
911
+ func isValidFile(uri: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
912
+ VideoTrim.isValidFile(url: uri, completion: { payload in
913
+ resolve(payload)
914
+ }
915
+ )
916
+ }
917
+
849
918
  private static func checkFileValidity(url: URL, completion: @escaping (Bool, String, Double) -> Void) {
850
919
  let asset = AVAsset(url: url)
851
920
 
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ import { NativeModules, Platform } from 'react-native';
4
+ export * from "./NativeVideoTrim.js";
5
+ const LINKING_ERROR = `The package 'react-native-video-trim' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
6
+ ios: "- You have run 'pod install'\n",
7
+ default: ''
8
+ }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
9
+ const VideoTrim = NativeModules.VideoTrim ? NativeModules.VideoTrim : new Proxy({}, {
10
+ get() {
11
+ throw new Error(LINKING_ERROR);
12
+ }
13
+ });
14
+ export default VideoTrim;
15
+ //# sourceMappingURL=OldArch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","VideoTrim","Proxy","get","Error"],"sourceRoot":"../../src","sources":["OldArch.ts"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,cAAc,sBAAmB;AAEjC,MAAMC,aAAa,GACjB,kFAAkF,GAClFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,SAAS,GAAGN,aAAa,CAACM,SAAS,GACrCN,aAAa,CAACM,SAAS,GACvB,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,eAAeI,SAAS","ignoreList":[]}
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
 
3
- import VideoTrim from "./NativeVideoTrim.js";
3
+ import VideoTrimNewArch from "./NativeVideoTrim.js";
4
+ import VideoTrimOldArch from "./OldArch.js";
4
5
  import { processColor } from 'react-native';
5
- export * from "./NativeVideoTrim.js";
6
+
7
+ // React Native runtime flags like nativeFabricUIManager are not in TypeScript types. Using `any` here is intentional and safe.
8
+ const isFabric = !!global.nativeFabricUIManager;
9
+ const VideoTrim = isFabric ? VideoTrimNewArch : VideoTrimOldArch;
6
10
  function createBaseOptions(overrides = {}) {
7
11
  return {
8
12
  saveToPhoto: false,
@@ -1 +1 @@
1
- {"version":3,"names":["VideoTrim","processColor","createBaseOptions","overrides","saveToPhoto","type","outputExt","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","enableRotation","rotationAngle","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","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","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","color","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","openDocumentsOnFinish","openShareSheetOnFinish","removeAfterSavedToPhoto","removeAfterFailedToSavePhoto","removeAfterSavedToDocuments","removeAfterFailedToSaveDocuments","removeAfterShared","removeAfterFailedToShare","enableRotation","rotationAngle","createEditorConfig","enableHapticFeedback","maxDuration","minDuration","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","alertOnFailToLoad","alertOnFailTitle","alertOnFailMessage","alertOnFailCloseText","createTrimOptions","startTime","endTime","showEditor","filePath","config","color","listFiles","cleanFiles","deleteFile","trim","length","Error","closeEditor","isValidFile","url","options"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ export * from './NativeVideoTrim';
2
+ declare const VideoTrim: any;
3
+ export default VideoTrim;
4
+ //# sourceMappingURL=OldArch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OldArch.d.ts","sourceRoot":"","sources":["../../../src/OldArch.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAC;AAQlC,QAAA,MAAM,SAAS,KASV,CAAC;AAEN,eAAe,SAAS,CAAC"}
@@ -1,6 +1,5 @@
1
- import VideoTrim from './NativeVideoTrim';
2
1
  import type { EditorConfig, FileValidationResult, TrimOptions } from './NativeVideoTrim';
3
- export * from './NativeVideoTrim';
2
+ declare const VideoTrim: any;
4
3
  /**
5
4
  * Show video editor
6
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAEV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,cAAc,mBAAmB,CAAC;AA0ElC;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC,GAAG;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CAWN;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,MAAM,CAAC,CAEjB;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,EACZ,MAAM,mBAAmB,CAAC;AAK3B,QAAA,MAAM,SAAS,KAAiD,CAAC;AA0EjE;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC,GAAG;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CAWN;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,MAAM,CAAC,CAEjB;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": "5.1.0",
3
+ "version": "6.0.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",
package/src/OldArch.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+ export * from './NativeVideoTrim';
3
+
4
+ const LINKING_ERROR =
5
+ `The package 'react-native-video-trim' doesn't seem to be linked. Make sure: \n\n` +
6
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
7
+ '- You rebuilt the app after installing the package\n' +
8
+ '- You are not using Expo Go\n';
9
+
10
+ const VideoTrim = NativeModules.VideoTrim
11
+ ? NativeModules.VideoTrim
12
+ : new Proxy(
13
+ {},
14
+ {
15
+ get() {
16
+ throw new Error(LINKING_ERROR);
17
+ },
18
+ }
19
+ );
20
+
21
+ export default VideoTrim;
package/src/index.tsx CHANGED
@@ -1,4 +1,5 @@
1
- import VideoTrim from './NativeVideoTrim';
1
+ import VideoTrimNewArch from './NativeVideoTrim';
2
+ import VideoTrimOldArch from './OldArch';
2
3
  import type {
3
4
  BaseOptions,
4
5
  EditorConfig,
@@ -6,7 +7,10 @@ import type {
6
7
  TrimOptions,
7
8
  } from './NativeVideoTrim';
8
9
  import { processColor } from 'react-native';
9
- export * from './NativeVideoTrim';
10
+
11
+ // React Native runtime flags like nativeFabricUIManager are not in TypeScript types. Using `any` here is intentional and safe.
12
+ const isFabric = !!(global as any).nativeFabricUIManager;
13
+ const VideoTrim = isFabric ? VideoTrimNewArch : VideoTrimOldArch;
10
14
 
11
15
  function createBaseOptions(overrides: Partial<BaseOptions> = {}): BaseOptions {
12
16
  return {
package/ios/VideoTrim.h DELETED
@@ -1,5 +0,0 @@
1
- #import <VideoTrimSpec/VideoTrimSpec.h>
2
- #import <VideoTrim-Swift.h>
3
-
4
- @interface VideoTrim : NativeVideoTrimSpecBase <NativeVideoTrimSpec, VideoTrimProtocol>
5
- @end