shakebug-react-native 2.4.9 → 2.4.11
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 +0 -12
- package/VideoPlayer/PlayVideo.tsx +4 -46
- package/VideoPlayer/index.js +6 -43
- package/android/src/main/java/com/shakebug/BaseUtils.java +7 -19
- package/android/src/main/java/com/shakebug/DeviceUtil.java +34 -21
- package/android/src/main/java/com/shakebug/ShakebugPackage.java +3 -3
- package/android/src/main/java/com/shakebug/UnitConverter.java +8 -8
- package/android/src/main/java/com/shakebug/VideoPlayerModule.java +81 -0
- package/android/src/main/java/com/shakebug/VideoTrimModule.java +387 -0
- package/android/src/main/java/com/shakebug/VideoTrimUtil.java +133 -0
- package/android/src/main/java/com/shakebug/adapters/VideoTrimmerAdapter.java +53 -0
- package/android/src/main/java/com/shakebug/callback/SingleCallback.java +0 -6
- package/android/src/main/java/com/shakebug/thread/BackgroundExecutor.java +1 -93
- package/android/src/main/java/com/shakebug/thread/UiThreadExecutor.java +0 -37
- package/android/src/main/java/com/shakebug/utils/StorageUtil.java +135 -0
- package/android/src/main/java/com/shakebug/utils/VideoTrimmerUtil.java +70 -0
- package/android/src/main/java/com/shakebug/widgets/RangeSeekBarView.java +534 -0
- package/android/src/main/java/com/shakebug/widgets/SpacesItemDecoration2.java +1 -2
- package/android/src/main/java/com/shakebug/widgets/VideoPlayerView.java +317 -0
- package/android/src/main/java/com/shakebug/widgets/VideoTrimmerView.java +520 -0
- package/android/src/main/res/drawable/ic_volume_off.xml +10 -0
- package/android/src/main/res/drawable/ic_volume_on.xml +10 -0
- package/android/src/main/res/layout/{video_player_view.xml → shakebug_video_player_view.xml} +29 -9
- package/ios/TrimVideo/ShakebugSDKVideoTrim.swift +389 -0
- package/ios/TrimVideo/VideoTrim-Bridging-Header.h +10 -0
- package/ios/TrimVideo/VideoTrim.m +23 -0
- package/ios/TrimVideo/VideoTrimmer.swift +810 -0
- package/ios/TrimVideo/VideoTrimmerThumb.swift +119 -0
- package/ios/TrimVideo/VideoTrimmerViewController.swift +322 -0
- package/ios/VideoPlayer/VideoPlayerModule.m +23 -7
- package/package.json +1 -1
- package/src/APIs/AddIssue.js +7 -5
- package/src/APIs/AddReview.js +5 -2
- package/src/APIs/CustomUserId.js +5 -2
- package/src/APIs/EndSession.js +3 -2
- package/src/APIs/Event.js +5 -2
- package/src/APIs/FetchRemoteCodeAPI.js +5 -2
- package/src/APIs/MatchKey.js +3 -2
- package/src/APIs/StartSession.js +44 -23
- package/src/Componanats/LoadingModal.js +59 -0
- package/src/Componanats/ShakeFunction.js +32 -14
- package/src/Screens/AddDetailsScreen.js +28 -31
- package/src/Screens/FirstScreen.js +15 -18
- package/src/Screens/Shakebug.js +11 -6
- package/src/Screens/TrimVideoScreen.js +37 -22
- package/src/index.tsx +7 -6
- package/trimVideo/src/index.tsx +12 -48
- package/Volumes:.fileloc +0 -8
- package/shakebug-react-native-2.4.8.tgz +0 -0
- /package/android/src/main/res/layout/{video_thumb_item_layout.xml → shakebug_video_thumb_item_layout.xml} +0 -0
- /package/android/src/main/res/layout/{video_trimmer_view.xml → shakebug_video_trimmer_view.xml} +0 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
package com.shakebug.widgets;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.content.pm.ActivityInfo;
|
|
5
|
+
import android.media.MediaPlayer;
|
|
6
|
+
import android.net.Uri;
|
|
7
|
+
import android.os.Handler;
|
|
8
|
+
import android.os.Looper;
|
|
9
|
+
import android.util.AttributeSet;
|
|
10
|
+
import android.view.LayoutInflater;
|
|
11
|
+
import android.view.View;
|
|
12
|
+
import android.view.ViewGroup;
|
|
13
|
+
import android.widget.FrameLayout;
|
|
14
|
+
import android.widget.ImageView;
|
|
15
|
+
import android.widget.RelativeLayout;
|
|
16
|
+
import android.widget.SeekBar;
|
|
17
|
+
import android.widget.SeekBar.OnSeekBarChangeListener;
|
|
18
|
+
import android.widget.TextView;
|
|
19
|
+
|
|
20
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
21
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
22
|
+
import com.shakebug.R;
|
|
23
|
+
import com.shakebug.interfaces.VideoPlayerListner;
|
|
24
|
+
|
|
25
|
+
import java.util.Locale;
|
|
26
|
+
import java.util.concurrent.TimeUnit;
|
|
27
|
+
|
|
28
|
+
public class VideoPlayerView extends FrameLayout {
|
|
29
|
+
|
|
30
|
+
private static final String TAG = VideoPlayerView.class.getSimpleName();
|
|
31
|
+
|
|
32
|
+
private Context mContext;
|
|
33
|
+
private RelativeLayout mLinearVideo;
|
|
34
|
+
private ZVideoView mVideoView;
|
|
35
|
+
private ImageView mPlayView;
|
|
36
|
+
private SeekBar mSeekBar;
|
|
37
|
+
private TextView mTvCurrentTime;
|
|
38
|
+
private TextView mTvDuration;
|
|
39
|
+
private ImageView mCancelBtn;
|
|
40
|
+
private ImageView mMuteBtn;
|
|
41
|
+
private MediaPlayer mMediaPlayer;
|
|
42
|
+
private boolean mIsMuted = false;
|
|
43
|
+
|
|
44
|
+
private Uri mSourceUri;
|
|
45
|
+
private VideoPlayerListner mOnVideoPlayerListener;
|
|
46
|
+
private int mDuration = 0;
|
|
47
|
+
private boolean mIsPrepared = false;
|
|
48
|
+
private final Handler mAnimationHandler = new Handler(Looper.getMainLooper());
|
|
49
|
+
|
|
50
|
+
public VideoPlayerView(Context context) {
|
|
51
|
+
super(context);
|
|
52
|
+
init(context, null);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public VideoPlayerView(Context context, AttributeSet attrs) {
|
|
56
|
+
super(context, attrs);
|
|
57
|
+
init(context, null);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public VideoPlayerView(Context context, ReadableMap config, AttributeSet attrs) {
|
|
61
|
+
super(context, attrs);
|
|
62
|
+
init(context, config);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private void init(Context context, ReadableMap config) {
|
|
66
|
+
this.mContext = context;
|
|
67
|
+
|
|
68
|
+
LayoutInflater.from(context).inflate(R.layout.shakebug_video_player_view, this, true);
|
|
69
|
+
|
|
70
|
+
mLinearVideo = findViewById(R.id.layout_surface_view);
|
|
71
|
+
mVideoView = findViewById(R.id.video_loader);
|
|
72
|
+
mPlayView = findViewById(R.id.icon_video_play);
|
|
73
|
+
mSeekBar = findViewById(R.id.videoSeekBar);
|
|
74
|
+
mTvCurrentTime = findViewById(R.id.textViewCurrentTime);
|
|
75
|
+
mTvDuration = findViewById(R.id.textViewDuration);
|
|
76
|
+
mCancelBtn = findViewById(R.id.cancelBtn);
|
|
77
|
+
mMuteBtn = findViewById(R.id.muteBtn);
|
|
78
|
+
|
|
79
|
+
setUpListeners();
|
|
80
|
+
setUpSeekBar();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public void initVideoByURI(final Uri videoURI) {
|
|
84
|
+
this.mSourceUri = videoURI;
|
|
85
|
+
mIsPrepared = false;
|
|
86
|
+
try {
|
|
87
|
+
mVideoView.setVideoURI(videoURI);
|
|
88
|
+
mVideoView.requestFocus();
|
|
89
|
+
} catch (Exception e) {
|
|
90
|
+
e.printStackTrace();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private void setUpListeners() {
|
|
95
|
+
mVideoView.setOnPreparedListener(mp -> {
|
|
96
|
+
try {
|
|
97
|
+
mMediaPlayer = mp;
|
|
98
|
+
mIsPrepared = true;
|
|
99
|
+
mDuration = mVideoView.getDuration();
|
|
100
|
+
if (mDuration > 0) {
|
|
101
|
+
mSeekBar.setMax(mDuration);
|
|
102
|
+
updateDurationText(mDuration);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (mIsMuted) {
|
|
106
|
+
mMediaPlayer.setVolume(0f, 0f);
|
|
107
|
+
} else {
|
|
108
|
+
mMediaPlayer.setVolume(1f, 1f);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Adjust aspect ratio
|
|
112
|
+
adjustVideoAspectRatio(mp);
|
|
113
|
+
|
|
114
|
+
setPlayPauseViewIcon(true);
|
|
115
|
+
mVideoView.start();
|
|
116
|
+
mAnimationHandler.post(mUpdateSeekBarTask);
|
|
117
|
+
} catch (Exception e) {
|
|
118
|
+
e.printStackTrace();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
mVideoView.setOnCompletionListener(mp -> {
|
|
123
|
+
try {
|
|
124
|
+
mVideoView.seekTo(0);
|
|
125
|
+
mSeekBar.setProgress(0);
|
|
126
|
+
updateCurrentDurationText(0);
|
|
127
|
+
setPlayPauseViewIcon(false);
|
|
128
|
+
mAnimationHandler.removeCallbacks(mUpdateSeekBarTask);
|
|
129
|
+
} catch (Exception e) {
|
|
130
|
+
e.printStackTrace();
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
mVideoView.setOnErrorListener((mp, what, extra) -> {
|
|
135
|
+
setPlayPauseViewIcon(false);
|
|
136
|
+
return true;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (mCancelBtn != null) {
|
|
140
|
+
mCancelBtn.setOnClickListener(view -> {
|
|
141
|
+
onVideoPause();
|
|
142
|
+
if (mOnVideoPlayerListener != null) {
|
|
143
|
+
mOnVideoPlayerListener.onCancel();
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (mMuteBtn != null) {
|
|
149
|
+
mMuteBtn.setOnClickListener(view -> {
|
|
150
|
+
mIsMuted = !mIsMuted;
|
|
151
|
+
if (mMediaPlayer != null) {
|
|
152
|
+
if (mIsMuted) {
|
|
153
|
+
mMediaPlayer.setVolume(0f, 0f);
|
|
154
|
+
mMuteBtn.setImageResource(R.drawable.ic_volume_off);
|
|
155
|
+
} else {
|
|
156
|
+
mMediaPlayer.setVolume(1f, 1f);
|
|
157
|
+
mMuteBtn.setImageResource(R.drawable.ic_volume_on);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (mPlayView != null) {
|
|
164
|
+
mPlayView.setOnClickListener(view -> playVideoOrPause());
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private void adjustVideoAspectRatio(MediaPlayer mp) {
|
|
169
|
+
try {
|
|
170
|
+
int videoWidth = mp.getVideoWidth();
|
|
171
|
+
int videoHeight = mp.getVideoHeight();
|
|
172
|
+
if (videoWidth == 0 || videoHeight == 0) return;
|
|
173
|
+
|
|
174
|
+
int containerWidth = mLinearVideo.getWidth();
|
|
175
|
+
int containerHeight = mLinearVideo.getHeight();
|
|
176
|
+
if (containerWidth == 0 || containerHeight == 0) return;
|
|
177
|
+
|
|
178
|
+
ViewGroup.LayoutParams lp = mVideoView.getLayoutParams();
|
|
179
|
+
float videoAspect = (float) videoWidth / (float) videoHeight;
|
|
180
|
+
float containerAspect = (float) containerWidth / (float) containerHeight;
|
|
181
|
+
|
|
182
|
+
if (videoAspect > containerAspect) {
|
|
183
|
+
lp.width = containerWidth;
|
|
184
|
+
lp.height = (int) (containerWidth / videoAspect);
|
|
185
|
+
} else {
|
|
186
|
+
lp.height = containerHeight;
|
|
187
|
+
lp.width = (int) (containerHeight * videoAspect);
|
|
188
|
+
}
|
|
189
|
+
mVideoView.setLayoutParams(lp);
|
|
190
|
+
} catch (Exception e) {
|
|
191
|
+
e.printStackTrace();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private void setUpSeekBar() {
|
|
196
|
+
if (mSeekBar == null) return;
|
|
197
|
+
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
|
|
198
|
+
@Override
|
|
199
|
+
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
|
200
|
+
if (fromUser && mIsPrepared) {
|
|
201
|
+
try {
|
|
202
|
+
// Only update UI text while dragging, don't overwhelm MediaPlayer with seekTo
|
|
203
|
+
updateCurrentDurationText(progress);
|
|
204
|
+
} catch (Exception e) {
|
|
205
|
+
e.printStackTrace();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@Override
|
|
211
|
+
public void onStartTrackingTouch(SeekBar seekBar) {
|
|
212
|
+
if (mIsPrepared) {
|
|
213
|
+
mVideoView.pause();
|
|
214
|
+
mAnimationHandler.removeCallbacks(mUpdateSeekBarTask);
|
|
215
|
+
setPlayPauseViewIcon(false);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@Override
|
|
220
|
+
public void onStopTrackingTouch(SeekBar seekBar) {
|
|
221
|
+
if (mIsPrepared) {
|
|
222
|
+
// Perform the actual seek only when the user releases the thumb
|
|
223
|
+
mVideoView.seekTo(seekBar.getProgress());
|
|
224
|
+
// Force start playing from the new position
|
|
225
|
+
mVideoView.start();
|
|
226
|
+
mAnimationHandler.post(mUpdateSeekBarTask);
|
|
227
|
+
setPlayPauseViewIcon(true);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private final Runnable mUpdateSeekBarTask = new Runnable() {
|
|
234
|
+
@Override
|
|
235
|
+
public void run() {
|
|
236
|
+
try {
|
|
237
|
+
if (mVideoView != null && mVideoView.isPlaying()) {
|
|
238
|
+
int currentPos = mVideoView.getCurrentPosition();
|
|
239
|
+
if (mSeekBar != null) {
|
|
240
|
+
mSeekBar.setProgress(currentPos);
|
|
241
|
+
}
|
|
242
|
+
updateCurrentDurationText(currentPos);
|
|
243
|
+
mAnimationHandler.postDelayed(this, 100);
|
|
244
|
+
}
|
|
245
|
+
} catch (Exception e) {
|
|
246
|
+
e.printStackTrace();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
private void playVideoOrPause() {
|
|
252
|
+
try {
|
|
253
|
+
if (mVideoView.isPlaying()) {
|
|
254
|
+
mVideoView.pause();
|
|
255
|
+
mAnimationHandler.removeCallbacks(mUpdateSeekBarTask);
|
|
256
|
+
setPlayPauseViewIcon(false);
|
|
257
|
+
} else {
|
|
258
|
+
mVideoView.start();
|
|
259
|
+
mAnimationHandler.post(mUpdateSeekBarTask);
|
|
260
|
+
setPlayPauseViewIcon(true);
|
|
261
|
+
}
|
|
262
|
+
} catch (Exception e) {
|
|
263
|
+
e.printStackTrace();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
public void onVideoPause() {
|
|
268
|
+
try {
|
|
269
|
+
if (mVideoView != null && mVideoView.isPlaying()) {
|
|
270
|
+
mVideoView.pause();
|
|
271
|
+
setPlayPauseViewIcon(false);
|
|
272
|
+
mAnimationHandler.removeCallbacks(mUpdateSeekBarTask);
|
|
273
|
+
}
|
|
274
|
+
} catch (Exception e) {
|
|
275
|
+
e.printStackTrace();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private void setPlayPauseViewIcon(boolean isPlaying) {
|
|
280
|
+
if (mPlayView != null) {
|
|
281
|
+
mPlayView.setImageResource(isPlaying ? R.drawable.ic_video_pause_black : R.drawable.ic_video_play_black);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public static String formatTime(long durationMs) {
|
|
286
|
+
long minutes = TimeUnit.MILLISECONDS.toMinutes(durationMs) % 60;
|
|
287
|
+
long seconds = TimeUnit.MILLISECONDS.toSeconds(durationMs) % 60;
|
|
288
|
+
return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private void updateDurationText(long duration) {
|
|
292
|
+
if (mTvDuration != null) {
|
|
293
|
+
mTvDuration.setText(formatTime(duration));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private void updateCurrentDurationText(int progress) {
|
|
298
|
+
if (mTvCurrentTime != null) {
|
|
299
|
+
mTvCurrentTime.setText(formatTime(progress));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
public void setOnTrimVideoListener(VideoPlayerListner onVideoPlayerListener) {
|
|
304
|
+
this.mOnVideoPlayerListener = onVideoPlayerListener;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public void onDestroy() {
|
|
308
|
+
try {
|
|
309
|
+
mAnimationHandler.removeCallbacks(mUpdateSeekBarTask);
|
|
310
|
+
if (mVideoView != null) {
|
|
311
|
+
mVideoView.stopPlayback();
|
|
312
|
+
}
|
|
313
|
+
} catch (Exception e) {
|
|
314
|
+
e.printStackTrace();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|