shakebug-react-native 2.4.9 → 2.4.10

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.
Files changed (42) hide show
  1. package/README.md +0 -12
  2. package/VideoPlayer/PlayVideo.tsx +4 -46
  3. package/VideoPlayer/index.js +6 -43
  4. package/android/src/main/java/com/shakebug/BaseUtils.java +7 -19
  5. package/android/src/main/java/com/shakebug/DeviceUtil.java +34 -21
  6. package/android/src/main/java/com/shakebug/ShakebugPackage.java +3 -3
  7. package/android/src/main/java/com/shakebug/UnitConverter.java +8 -8
  8. package/android/src/main/java/com/shakebug/VideoPlayerModule.java +81 -0
  9. package/android/src/main/java/com/shakebug/VideoTrimModule.java +387 -0
  10. package/android/src/main/java/com/shakebug/VideoTrimUtil.java +133 -0
  11. package/android/src/main/java/com/shakebug/adapters/VideoTrimmerAdapter.java +53 -0
  12. package/android/src/main/java/com/shakebug/callback/SingleCallback.java +0 -6
  13. package/android/src/main/java/com/shakebug/thread/BackgroundExecutor.java +1 -93
  14. package/android/src/main/java/com/shakebug/thread/UiThreadExecutor.java +0 -37
  15. package/android/src/main/java/com/shakebug/utils/StorageUtil.java +135 -0
  16. package/android/src/main/java/com/shakebug/utils/VideoTrimmerUtil.java +70 -0
  17. package/android/src/main/java/com/shakebug/widgets/RangeSeekBarView.java +534 -0
  18. package/android/src/main/java/com/shakebug/widgets/SpacesItemDecoration2.java +1 -2
  19. package/android/src/main/java/com/shakebug/widgets/VideoPlayerView.java +317 -0
  20. package/android/src/main/java/com/shakebug/widgets/VideoTrimmerView.java +520 -0
  21. package/android/src/main/res/drawable/ic_volume_off.xml +10 -0
  22. package/android/src/main/res/drawable/ic_volume_on.xml +10 -0
  23. package/android/src/main/res/layout/{video_player_view.xml → shakebug_video_player_view.xml} +29 -9
  24. package/ios/TrimVideo/ShakebugSDKVideoTrim.swift +389 -0
  25. package/ios/TrimVideo/VideoTrim-Bridging-Header.h +10 -0
  26. package/ios/TrimVideo/VideoTrim.m +23 -0
  27. package/ios/TrimVideo/VideoTrimmer.swift +810 -0
  28. package/ios/TrimVideo/VideoTrimmerThumb.swift +119 -0
  29. package/ios/TrimVideo/VideoTrimmerViewController.swift +322 -0
  30. package/ios/VideoPlayer/VideoPlayerModule.m +23 -7
  31. package/package.json +1 -1
  32. package/src/Componanats/LoadingModal.js +59 -0
  33. package/src/Componanats/ShakeFunction.js +2 -10
  34. package/src/Screens/AddDetailsScreen.js +28 -31
  35. package/src/Screens/FirstScreen.js +15 -18
  36. package/src/Screens/Shakebug.js +1 -1
  37. package/src/Screens/TrimVideoScreen.js +37 -22
  38. package/src/index.tsx +4 -4
  39. package/trimVideo/src/index.tsx +12 -48
  40. package/shakebug-react-native-2.4.8.tgz +0 -0
  41. /package/android/src/main/res/layout/{video_thumb_item_layout.xml → shakebug_video_thumb_item_layout.xml} +0 -0
  42. /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
+ }