shakebug-react-native 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/VideoPlayer/index.js +37 -23
- package/android/build.gradle +0 -1
- package/android/src/main/java/com/shakebug/CreateThumbnailModule.java +217 -0
- package/android/src/main/java/com/shakebug/NetInfoModule.java +1 -2
- package/android/src/main/java/com/shakebug/RNDeviceModule.java +1 -3
- package/android/src/main/java/com/shakebug/ShakebugPackage.java +10 -10
- package/android/src/main/java/com/shakebug/{Shakebug.java → ShakebugSensors.java} +16 -22
- package/ios/GetLocals/ShakebugSDKRNLocalize.h +1 -0
- package/ios/Thumbnaill/{VideoThumbnailManager.h → CreateThumbnail.h} +2 -1
- package/ios/Thumbnaill/CreateThumbnail.m +82 -0
- package/package.json +2 -5
- package/shakebug-react-native.podspec +0 -1
- package/src/APIs/AddIssue.js +13 -4
- package/src/APIs/AddReview.js +46 -0
- package/src/APIs/CustomUserId.js +47 -0
- package/src/APIs/Event.js +8 -3
- package/src/APIs/StartSession.js +6 -2
- package/src/Assets/images/solar_star-bold.png +0 -0
- package/src/Assets/images/solar_star-line-duotone.png +0 -0
- package/src/Componanats/ReviewModal.js +171 -0
- package/src/Componanats/ShakeFunction.js +6 -3
- package/src/Screens/AddDetailsScreen.js +14 -10
- package/src/Screens/FirstScreen.js +2 -2
- package/src/Screens/Shakebug.js +63 -6
- package/src/Screens/TrimVideoScreen.js +13 -7
- package/src/index.tsx +6 -2
- package/android/src/main/java/com/shakebug/ShakebugSDKScreenShotModule.java +0 -196
- package/android/src/main/java/com/shakebug/VideoPlayerModule.java +0 -199
- package/android/src/main/java/com/shakebug/VideoThumbnailModule.java +0 -215
- package/android/src/main/java/com/shakebug/VideoTrimModule.java +0 -372
- package/android/src/main/java/com/shakebug/adapters/VideoTrimmerAdapter.java +0 -54
- package/android/src/main/java/com/shakebug/utils/StorageUtil.java +0 -139
- package/android/src/main/java/com/shakebug/utils/VideoTrimmerUtil.java +0 -89
- package/android/src/main/java/com/shakebug/widgets/RangeSeekBarView.java +0 -534
- package/android/src/main/java/com/shakebug/widgets/VideoPlayerView.java +0 -429
- package/android/src/main/java/com/shakebug/widgets/VideoTrimmerView.java +0 -477
- package/ios/Thumbnaill/VideoThumbnailManager.m +0 -73
- package/ios/TrimVideo/ShakebugSDKVideoTrim.swift +0 -372
- package/ios/TrimVideo/VideoTrim-Bridging-Header.h +0 -10
- package/ios/TrimVideo/VideoTrim.m +0 -23
- package/ios/TrimVideo/VideoTrimmer.swift +0 -810
- package/ios/TrimVideo/VideoTrimmerThumb.swift +0 -119
- package/ios/TrimVideo/VideoTrimmerViewController.swift +0 -301
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { NativeEventEmitter, NativeModules, SafeAreaView, StatusBar } from 'react-native'
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform, SafeAreaView, StatusBar } from 'react-native'
|
|
2
2
|
import React, { useEffect, useState } from 'react'
|
|
3
|
-
import { showEditor } from '
|
|
3
|
+
import { showEditor } from 'react-native-video-trim';
|
|
4
4
|
import { useNavigation } from '../Componanats/NavigationContext';
|
|
5
5
|
import { Localization } from '../Componanats/localization';
|
|
6
6
|
|
|
@@ -12,10 +12,15 @@ const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatus
|
|
|
12
12
|
|
|
13
13
|
const { goToScreenAtIndex, navigate, goBack } = useNavigation();
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
// For display video trimmer
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
StatusBar.setHidden(true)
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
const uri = video; // your path
|
|
21
|
+
const trimmedUri = uri.replace('file://', '');
|
|
22
|
+
|
|
23
|
+
showEditor(Platform.OS == 'android' ? trimmedUri : video, {
|
|
19
24
|
saveButtonText: Localization[global.ShakebugLanguage].Choose,
|
|
20
25
|
cancelButtonText: Localization[global.ShakebugLanguage].Cancel,
|
|
21
26
|
trimmingText: Localization[global.ShakebugLanguage].TrimmingText,
|
|
@@ -32,8 +37,9 @@ const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatus
|
|
|
32
37
|
saveDialogCancelText: Localization[global.ShakebugLanguage].No,
|
|
33
38
|
saveDialogConfirmText: Localization[global.ShakebugLanguage].Yes
|
|
34
39
|
});
|
|
35
|
-
|
|
36
|
-
const
|
|
40
|
+
|
|
41
|
+
const eventEmitter = new NativeEventEmitter(NativeModules.VideoTrim);
|
|
42
|
+
const subscription = eventEmitter.addListener('VideoTrim', (event) => {
|
|
37
43
|
switch (event.name) {
|
|
38
44
|
case 'onShow': {
|
|
39
45
|
break;
|
|
@@ -50,7 +56,7 @@ const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatus
|
|
|
50
56
|
navigate("AddDetailsScreen", { media: `${event.outputPath}`, mediaType: 'video', themeColor: themeColor, SDKScreenTitle: SDKScreenTitle, updateParent: updateParent });
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
|
-
case '
|
|
59
|
+
case 'onCancel': {
|
|
54
60
|
UpdateStatusBar()
|
|
55
61
|
if (Type == "video") {
|
|
56
62
|
goToScreenAtIndex(1)
|
|
@@ -62,7 +68,7 @@ const TrimVideoScreen = ({ video, themeColor, SDKScreenTitle, Type, UpdateStatus
|
|
|
62
68
|
goToScreenAtIndex(3)
|
|
63
69
|
}
|
|
64
70
|
return;
|
|
65
|
-
|
|
71
|
+
break;
|
|
66
72
|
}
|
|
67
73
|
case 'onError': {
|
|
68
74
|
break;
|
package/src/index.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { NavigationContainer, findFocusedRoute } from '@react-navigation/native'
|
|
|
4
4
|
import { getLocales } from '../GetLocals/src';
|
|
5
5
|
import { NativeModules, Text, View, findNodeHandle } from 'react-native';
|
|
6
6
|
import { useGlobalState } from './Componanats/GlobalStateContext'
|
|
7
|
+
import { CustomUserIdApi } from './APIs/CustomUserId'
|
|
7
8
|
|
|
8
9
|
let Languages = ['ENGLISH', 'HINDI', 'GUJARATI', 'ARABIC', 'CHINESE', 'DUTCH', 'FRENCH', 'GERMAN', 'GREEK', 'INDONESIAN', 'ITALIAN', 'JAPANESE', 'KOREAN', 'RUSSIAN', 'SPANISH', 'TURKISH', 'UKRAINIAN', 'MARATHI', 'TAMIL', 'TELUGU']
|
|
9
10
|
let LanguageCodes = ['en', 'hi', 'gu', 'ar', 'zh', 'nl', 'fr', 'de', 'el', 'id', 'it', 'ja', 'ko', 'ru', 'es', 'tr', 'uk', 'mr', 'ta', 'te']
|
|
@@ -41,7 +42,7 @@ const ShakebugView: React.FC<ShakebugViewProps> = ({
|
|
|
41
42
|
allowCrashReport = true,
|
|
42
43
|
makeLogEnabled = false,
|
|
43
44
|
ShakebugLanguage = LocalLanguage != -1 ? Languages[LocalLanguage] : "ENGLISH",
|
|
44
|
-
setShakebugSDKEndPointURL = ["https://www.shakebug.com/api/v1.
|
|
45
|
+
setShakebugSDKEndPointURL = ["https://www.shakebug.com/api/v1.4/webservice.php/", "MarchShake2022", ""]
|
|
45
46
|
}) => {
|
|
46
47
|
|
|
47
48
|
return (
|
|
@@ -76,7 +77,6 @@ export const triggerBugReporting = (): void => {
|
|
|
76
77
|
global.isTrigger = true;
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
|
|
80
80
|
export const ShakebugSdkProtectedView = ({ children }) => {
|
|
81
81
|
|
|
82
82
|
const { isRecordingStart, isScreenShot } = useGlobalState();
|
|
@@ -115,3 +115,7 @@ export const ShakebugSdkProtectedView = ({ children }) => {
|
|
|
115
115
|
export const IsShakebugSDKOpen = () => {
|
|
116
116
|
return global.isShakebugSDKOpen;
|
|
117
117
|
}
|
|
118
|
+
|
|
119
|
+
export const addCustomUser = (id, name, email, country, other, applicationsid) => {
|
|
120
|
+
CustomUserIdApi(id, name, email, country, other, applicationsid)
|
|
121
|
+
}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
package com.shakebug;
|
|
3
|
-
|
|
4
|
-
import android.app.Activity;
|
|
5
|
-
import android.content.Context;
|
|
6
|
-
import android.net.Uri;
|
|
7
|
-
import android.os.AsyncTask;
|
|
8
|
-
import androidx.annotation.NonNull;
|
|
9
|
-
import android.util.DisplayMetrics;
|
|
10
|
-
import android.util.Log;
|
|
11
|
-
|
|
12
|
-
import com.facebook.react.bridge.GuardedAsyncTask;
|
|
13
|
-
import com.facebook.react.bridge.Promise;
|
|
14
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
15
|
-
import com.facebook.react.bridge.ReactContext;
|
|
16
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
17
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
18
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
19
|
-
import com.facebook.react.uimanager.UIManagerModule;
|
|
20
|
-
|
|
21
|
-
import java.io.File;
|
|
22
|
-
import java.io.FilenameFilter;
|
|
23
|
-
import java.io.IOException;
|
|
24
|
-
import java.util.Collections;
|
|
25
|
-
import java.util.Map;
|
|
26
|
-
import java.util.concurrent.Executor;
|
|
27
|
-
import java.util.concurrent.Executors;
|
|
28
|
-
|
|
29
|
-
import com.shakebug.ViewShot.Formats;
|
|
30
|
-
import com.shakebug.ViewShot.Results;
|
|
31
|
-
|
|
32
|
-
public class ShakebugSDKScreenShotModule extends ReactContextBaseJavaModule {
|
|
33
|
-
|
|
34
|
-
public static final String RNVIEW_SHOT = "ShakebugSDKRNViewShot";
|
|
35
|
-
|
|
36
|
-
private final ReactApplicationContext reactContext;
|
|
37
|
-
|
|
38
|
-
private final Executor executor = Executors.newCachedThreadPool();
|
|
39
|
-
|
|
40
|
-
public ShakebugSDKScreenShotModule(ReactApplicationContext reactContext) {
|
|
41
|
-
super(reactContext);
|
|
42
|
-
this.reactContext = reactContext;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@Override
|
|
46
|
-
public String getName() {
|
|
47
|
-
return RNVIEW_SHOT;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@Override
|
|
51
|
-
public Map<String, Object> getConstants() {
|
|
52
|
-
return Collections.emptyMap();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
@Override
|
|
56
|
-
public void onCatalystInstanceDestroy() {
|
|
57
|
-
super.onCatalystInstanceDestroy();
|
|
58
|
-
new CleanTask(getReactApplicationContext()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
@ReactMethod
|
|
62
|
-
public void releaseCapture(String uri) {
|
|
63
|
-
final String path = Uri.parse(uri).getPath();
|
|
64
|
-
if (path == null) return;
|
|
65
|
-
File file = new File(path);
|
|
66
|
-
if (!file.exists()) return;
|
|
67
|
-
File parent = file.getParentFile();
|
|
68
|
-
if (parent.equals(reactContext.getExternalCacheDir()) || parent.equals(reactContext.getCacheDir())) {
|
|
69
|
-
file.delete();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@ReactMethod
|
|
74
|
-
public void captureRef(int tag, ReadableMap options, Promise promise) {
|
|
75
|
-
final ReactApplicationContext context = getReactApplicationContext();
|
|
76
|
-
final DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
|
77
|
-
|
|
78
|
-
final String extension = options.getString("format");
|
|
79
|
-
final int imageFormat = "jpg".equals(extension)
|
|
80
|
-
? Formats.JPEG
|
|
81
|
-
: "webm".equals(extension)
|
|
82
|
-
? Formats.WEBP
|
|
83
|
-
: "raw".equals(extension)
|
|
84
|
-
? Formats.RAW
|
|
85
|
-
: Formats.PNG;
|
|
86
|
-
|
|
87
|
-
final double quality = options.getDouble("quality");
|
|
88
|
-
final Integer scaleWidth = options.hasKey("width") ? options.getInt("width") : null;
|
|
89
|
-
final Integer scaleHeight = options.hasKey("height") ? options.getInt("height") : null;
|
|
90
|
-
final String resultStreamFormat = options.getString("result");
|
|
91
|
-
final String fileName = options.hasKey("fileName") ? options.getString("fileName") : null;
|
|
92
|
-
final Boolean snapshotContentContainer = options.getBoolean("snapshotContentContainer");
|
|
93
|
-
final boolean handleGLSurfaceView = options.hasKey("handleGLSurfaceViewOnAndroid") && options.getBoolean("handleGLSurfaceViewOnAndroid");
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
File outputFile = null;
|
|
97
|
-
if (Results.TEMP_FILE.equals(resultStreamFormat)) {
|
|
98
|
-
outputFile = createTempFile(getReactApplicationContext(), extension, fileName);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
final Activity activity = getCurrentActivity();
|
|
102
|
-
final UIManagerModule uiManager = this.reactContext.getNativeModule(UIManagerModule.class);
|
|
103
|
-
|
|
104
|
-
uiManager.addUIBlock(new ViewShot(
|
|
105
|
-
tag, extension, imageFormat, quality,
|
|
106
|
-
scaleWidth, scaleHeight, outputFile, resultStreamFormat,
|
|
107
|
-
snapshotContentContainer, reactContext, activity, handleGLSurfaceView, promise, executor)
|
|
108
|
-
);
|
|
109
|
-
} catch (final Throwable ex) {
|
|
110
|
-
Log.e(RNVIEW_SHOT, "Failed to snapshot view tag " + tag, ex);
|
|
111
|
-
promise.reject(ViewShot.ERROR_UNABLE_TO_SNAPSHOT, "Failed to snapshot view tag " + tag);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
@ReactMethod
|
|
116
|
-
public void captureScreen(ReadableMap options, Promise promise) {
|
|
117
|
-
captureRef(-1, options, promise);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private static final String TEMP_FILE_PREFIX = "ReactNative-snapshot-image";
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Asynchronous task that cleans up cache dirs (internal and, if available, external) of cropped
|
|
124
|
-
* image files. This is run when the catalyst instance is being destroyed (i.e. app is shutting
|
|
125
|
-
* down) and when the module is instantiated, to handle the case where the app crashed.
|
|
126
|
-
*/
|
|
127
|
-
private static class CleanTask extends GuardedAsyncTask<Void, Void> implements FilenameFilter {
|
|
128
|
-
private final File cacheDir;
|
|
129
|
-
private final File externalCacheDir;
|
|
130
|
-
|
|
131
|
-
private CleanTask(ReactContext context) {
|
|
132
|
-
super(context);
|
|
133
|
-
|
|
134
|
-
cacheDir = context.getCacheDir();
|
|
135
|
-
externalCacheDir = context.getExternalCacheDir();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
@Override
|
|
139
|
-
protected void doInBackgroundGuarded(Void... params) {
|
|
140
|
-
if (null != cacheDir) {
|
|
141
|
-
cleanDirectory(cacheDir);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (externalCacheDir != null) {
|
|
145
|
-
cleanDirectory(externalCacheDir);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@Override
|
|
150
|
-
public final boolean accept(File dir, String filename) {
|
|
151
|
-
return filename.startsWith(TEMP_FILE_PREFIX);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private void cleanDirectory(@NonNull final File directory) {
|
|
155
|
-
final File[] toDelete = directory.listFiles(this);
|
|
156
|
-
|
|
157
|
-
if (toDelete != null) {
|
|
158
|
-
for (File file : toDelete) {
|
|
159
|
-
if (file.delete()) {
|
|
160
|
-
Log.d(RNVIEW_SHOT, "deleted file: " + file.getAbsolutePath());
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Create a temporary file in the cache directory on either internal or external storage,
|
|
169
|
-
* whichever is available and has more free space.
|
|
170
|
-
*/
|
|
171
|
-
@NonNull
|
|
172
|
-
private File createTempFile(@NonNull final Context context, @NonNull final String ext, String fileName) throws IOException {
|
|
173
|
-
final File externalCacheDir = context.getExternalCacheDir();
|
|
174
|
-
final File internalCacheDir = context.getCacheDir();
|
|
175
|
-
final File cacheDir;
|
|
176
|
-
|
|
177
|
-
if (externalCacheDir == null && internalCacheDir == null) {
|
|
178
|
-
throw new IOException("No cache directory available");
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (externalCacheDir == null) {
|
|
182
|
-
cacheDir = internalCacheDir;
|
|
183
|
-
} else if (internalCacheDir == null) {
|
|
184
|
-
cacheDir = externalCacheDir;
|
|
185
|
-
} else {
|
|
186
|
-
cacheDir = externalCacheDir.getFreeSpace() > internalCacheDir.getFreeSpace() ?
|
|
187
|
-
externalCacheDir : internalCacheDir;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
final String suffix = "." + ext;
|
|
191
|
-
if (fileName != null) {
|
|
192
|
-
return File.createTempFile(fileName, suffix, cacheDir);
|
|
193
|
-
}
|
|
194
|
-
return File.createTempFile(TEMP_FILE_PREFIX, suffix, cacheDir);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
package com.shakebug;
|
|
2
|
-
|
|
3
|
-
import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
|
|
4
|
-
|
|
5
|
-
import android.app.Activity;
|
|
6
|
-
import android.media.MediaMetadataRetriever;
|
|
7
|
-
import android.net.Uri;
|
|
8
|
-
import android.widget.ProgressBar;
|
|
9
|
-
|
|
10
|
-
import androidx.annotation.NonNull;
|
|
11
|
-
import androidx.annotation.Nullable;
|
|
12
|
-
import androidx.appcompat.app.AlertDialog;
|
|
13
|
-
|
|
14
|
-
import com.facebook.react.bridge.Arguments;
|
|
15
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
16
|
-
import com.facebook.react.bridge.Promise;
|
|
17
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
|
-
import com.facebook.react.bridge.ReactContext;
|
|
19
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
20
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
21
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
22
|
-
import com.facebook.react.bridge.WritableMap;
|
|
23
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
24
|
-
import com.shakebug.interfaces.VideoPlayerListner;
|
|
25
|
-
import com.shakebug.widgets.VideoPlayerView;
|
|
26
|
-
|
|
27
|
-
public class VideoPlayerModule extends ReactContextBaseJavaModule implements VideoPlayerListner, LifecycleEventListener {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
private static final String MODULE_NAME = "ShakebugSDKVideoPlayerModule";
|
|
31
|
-
private static Boolean isInit = false;
|
|
32
|
-
private VideoPlayerView trimmerView;
|
|
33
|
-
private AlertDialog alertDialog;
|
|
34
|
-
private AlertDialog mProgressDialog;
|
|
35
|
-
private ProgressBar mProgressBar;
|
|
36
|
-
private int listenerCount = 0;
|
|
37
|
-
|
|
38
|
-
private Promise showEditorPromise;
|
|
39
|
-
|
|
40
|
-
private boolean enableCancelDialog = true;
|
|
41
|
-
private String cancelDialogTitle = "Warning!";
|
|
42
|
-
private String cancelDialogMessage = "Are you sure want to cancel?";
|
|
43
|
-
private String cancelDialogCancelText = "Close";
|
|
44
|
-
private String cancelDialogConfirmText = "Proceed";
|
|
45
|
-
// Activity activity = getReactApplicationContext().getCurrentActivity();
|
|
46
|
-
|
|
47
|
-
public VideoPlayerModule(ReactApplicationContext reactContext) {
|
|
48
|
-
super(reactContext);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@Override
|
|
52
|
-
@NonNull
|
|
53
|
-
public String getName() {
|
|
54
|
-
return MODULE_NAME;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// From Trimmer
|
|
62
|
-
|
|
63
|
-
@ReactMethod
|
|
64
|
-
public void showEditor(String videoPath, ReadableMap config) {
|
|
65
|
-
// if (trimmerView != null || alertDialog != null) {
|
|
66
|
-
// return;
|
|
67
|
-
// }
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (!isValidVideo(videoPath)) {
|
|
71
|
-
WritableMap map = Arguments.createMap();
|
|
72
|
-
map.putString("message", "File is not a valid video");
|
|
73
|
-
sendEvent(getReactApplicationContext(), "onError", map);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
enableCancelDialog = config.hasKey("enableCancelDialog") ? config.getBoolean("enableCancelDialog") : true;
|
|
78
|
-
cancelDialogTitle = config.hasKey("cancelDialogTitle") ? config.getString("cancelDialogTitle") : "Warning!";
|
|
79
|
-
cancelDialogMessage = config.hasKey("cancelDialogMessage") ? config.getString("cancelDialogMessage") : "Are you sure want to cancel?";
|
|
80
|
-
cancelDialogCancelText = config.hasKey("cancelDialogCancelText") ? config.getString("cancelDialogCancelText") : "Close";
|
|
81
|
-
cancelDialogConfirmText = config.hasKey("cancelDialogConfirmText") ? config.getString("cancelDialogConfirmText") : "Proceed";
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Activity activity = getReactApplicationContext().getCurrentActivity();
|
|
85
|
-
|
|
86
|
-
if (!isInit) {
|
|
87
|
-
init(activity);
|
|
88
|
-
isInit = true;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// here is NOT main thread, we need to create VideoTrimmerView on UI thread, so that later we can update it using same thread
|
|
92
|
-
|
|
93
|
-
runOnUiThread(() -> {
|
|
94
|
-
trimmerView = new VideoPlayerView(getReactApplicationContext(), config, null);
|
|
95
|
-
trimmerView.setOnTrimVideoListener(this);
|
|
96
|
-
trimmerView.initVideoByURI(Uri.parse(videoPath));
|
|
97
|
-
|
|
98
|
-
AlertDialog.Builder builder = new AlertDialog.Builder(activity, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
|
|
99
|
-
builder.setCancelable(false);
|
|
100
|
-
alertDialog = builder.create();
|
|
101
|
-
alertDialog.setView(trimmerView);
|
|
102
|
-
alertDialog.show();
|
|
103
|
-
|
|
104
|
-
// 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)
|
|
105
|
-
alertDialog.setOnDismissListener(dialog -> {
|
|
106
|
-
// This is called in same thread as the trimmer view -> UI thread
|
|
107
|
-
if (trimmerView != null) {
|
|
108
|
-
trimmerView.onDestroy();
|
|
109
|
-
trimmerView = null;
|
|
110
|
-
}
|
|
111
|
-
sendEvent(getReactApplicationContext(), "onHide", null);
|
|
112
|
-
});
|
|
113
|
-
sendEvent(getReactApplicationContext(), "onShow", null);
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private void init(Activity activity) {
|
|
118
|
-
isInit = true;
|
|
119
|
-
// we have to init this before create videoTrimmerView
|
|
120
|
-
BaseUtils.init(getReactApplicationContext());
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
@Override
|
|
124
|
-
public void onHostResume() {
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
@Override
|
|
129
|
-
public void onHostPause() {
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
@Override
|
|
134
|
-
public void onHostDestroy() {
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
@Override public void onCancel() {
|
|
140
|
-
if (!enableCancelDialog) {
|
|
141
|
-
alertDialog.dismiss(); // Dismiss the alertDialog when the close button is clicked
|
|
142
|
-
trimmerView.onDestroy(); // Clean up the trimmerView
|
|
143
|
-
trimmerView = null;
|
|
144
|
-
sendEvent(getReactApplicationContext(), "onCancelPlayer", null);
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
AlertDialog.Builder builder = new AlertDialog.Builder(getReactApplicationContext().getCurrentActivity());
|
|
149
|
-
builder.setMessage(cancelDialogMessage);
|
|
150
|
-
builder.setTitle(cancelDialogTitle);
|
|
151
|
-
builder.setCancelable(false);
|
|
152
|
-
builder.setPositiveButton(cancelDialogConfirmText, (dialog, which) -> {
|
|
153
|
-
dialog.cancel();
|
|
154
|
-
sendEvent(getReactApplicationContext(), "onCancelPlayer", null);
|
|
155
|
-
});
|
|
156
|
-
builder.setNegativeButton(cancelDialogCancelText, (dialog, which) -> {
|
|
157
|
-
dialog.cancel();
|
|
158
|
-
});
|
|
159
|
-
AlertDialog alertDialog = builder.create();
|
|
160
|
-
alertDialog.show();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
@ReactMethod
|
|
164
|
-
public void addListener(String eventName) {
|
|
165
|
-
// This method is required by React
|
|
166
|
-
listenerCount += 1;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
@ReactMethod
|
|
170
|
-
public void removeListeners(Integer count) {
|
|
171
|
-
// This method is required by React
|
|
172
|
-
listenerCount -= count;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
|
|
176
|
-
if (listenerCount > 0) {
|
|
177
|
-
WritableMap map = params != null ? params : Arguments.createMap();
|
|
178
|
-
map.putString("name", eventName);
|
|
179
|
-
reactContext
|
|
180
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
181
|
-
.emit("ShakebugSDKVideoPlayer", map);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
public boolean isValidVideo(String filePath) {
|
|
187
|
-
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
retriever.setDataSource(getReactApplicationContext(), Uri.parse(filePath));
|
|
191
|
-
} catch (Exception e){
|
|
192
|
-
e.printStackTrace();
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
String hasVideo = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO);
|
|
197
|
-
return "yes".equals(hasVideo);
|
|
198
|
-
}
|
|
199
|
-
}
|