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.
Files changed (44) hide show
  1. package/README.md +17 -1
  2. package/VideoPlayer/index.js +37 -23
  3. package/android/build.gradle +0 -1
  4. package/android/src/main/java/com/shakebug/CreateThumbnailModule.java +217 -0
  5. package/android/src/main/java/com/shakebug/NetInfoModule.java +1 -2
  6. package/android/src/main/java/com/shakebug/RNDeviceModule.java +1 -3
  7. package/android/src/main/java/com/shakebug/ShakebugPackage.java +10 -10
  8. package/android/src/main/java/com/shakebug/{Shakebug.java → ShakebugSensors.java} +16 -22
  9. package/ios/GetLocals/ShakebugSDKRNLocalize.h +1 -0
  10. package/ios/Thumbnaill/{VideoThumbnailManager.h → CreateThumbnail.h} +2 -1
  11. package/ios/Thumbnaill/CreateThumbnail.m +82 -0
  12. package/package.json +2 -5
  13. package/shakebug-react-native.podspec +0 -1
  14. package/src/APIs/AddIssue.js +13 -4
  15. package/src/APIs/AddReview.js +46 -0
  16. package/src/APIs/CustomUserId.js +47 -0
  17. package/src/APIs/Event.js +8 -3
  18. package/src/APIs/StartSession.js +6 -2
  19. package/src/Assets/images/solar_star-bold.png +0 -0
  20. package/src/Assets/images/solar_star-line-duotone.png +0 -0
  21. package/src/Componanats/ReviewModal.js +171 -0
  22. package/src/Componanats/ShakeFunction.js +6 -3
  23. package/src/Screens/AddDetailsScreen.js +14 -10
  24. package/src/Screens/FirstScreen.js +2 -2
  25. package/src/Screens/Shakebug.js +63 -6
  26. package/src/Screens/TrimVideoScreen.js +13 -7
  27. package/src/index.tsx +6 -2
  28. package/android/src/main/java/com/shakebug/ShakebugSDKScreenShotModule.java +0 -196
  29. package/android/src/main/java/com/shakebug/VideoPlayerModule.java +0 -199
  30. package/android/src/main/java/com/shakebug/VideoThumbnailModule.java +0 -215
  31. package/android/src/main/java/com/shakebug/VideoTrimModule.java +0 -372
  32. package/android/src/main/java/com/shakebug/adapters/VideoTrimmerAdapter.java +0 -54
  33. package/android/src/main/java/com/shakebug/utils/StorageUtil.java +0 -139
  34. package/android/src/main/java/com/shakebug/utils/VideoTrimmerUtil.java +0 -89
  35. package/android/src/main/java/com/shakebug/widgets/RangeSeekBarView.java +0 -534
  36. package/android/src/main/java/com/shakebug/widgets/VideoPlayerView.java +0 -429
  37. package/android/src/main/java/com/shakebug/widgets/VideoTrimmerView.java +0 -477
  38. package/ios/Thumbnaill/VideoThumbnailManager.m +0 -73
  39. package/ios/TrimVideo/ShakebugSDKVideoTrim.swift +0 -372
  40. package/ios/TrimVideo/VideoTrim-Bridging-Header.h +0 -10
  41. package/ios/TrimVideo/VideoTrim.m +0 -23
  42. package/ios/TrimVideo/VideoTrimmer.swift +0 -810
  43. package/ios/TrimVideo/VideoTrimmerThumb.swift +0 -119
  44. package/ios/TrimVideo/VideoTrimmerViewController.swift +0 -301
@@ -1,119 +0,0 @@
1
- //
2
- // VideoTrimmerThumb.swift
3
- // Shakebug
4
- //
5
- // Created by ideveloper2 on 26/04/24.
6
- // Copyright © 2024 Facebook. All rights reserved.
7
- //
8
-
9
- import UIKit
10
-
11
- @available(iOS 13.0, *)
12
- class VideoTrimmerThumb: UIView {
13
- var isActive = false
14
-
15
- var leadingChevronImageView = UIImageView(image: UIImage(systemName: "chevron.compact.left"))
16
- var trailingChevronView = UIImageView(image: UIImage(systemName: "chevron.compact.right"))
17
-
18
- var wrapperView = UIView()
19
- var leadingView = UIView()
20
- var trailingView = UIView()
21
- var topView = UIView()
22
- var bottomView = UIView()
23
-
24
- let leadingGrabber = UIControl()
25
- let trailingGrabber = UIControl()
26
-
27
- let chevronWidth = CGFloat(16)
28
- let edgeHeight = CGFloat(4)
29
-
30
- // MARK: - Input
31
- @objc private func x(_ sender: Any) {
32
-
33
- }
34
-
35
- // MARK: - Private
36
- private func updateColor() {
37
- let color = UIColor.systemYellow
38
- leadingView.backgroundColor = color
39
- trailingView.backgroundColor = color
40
- topView.backgroundColor = color
41
- bottomView.backgroundColor = color
42
- }
43
-
44
- private func setup() {
45
-
46
- leadingChevronImageView.contentMode = .scaleAspectFill
47
- trailingChevronView.contentMode = .scaleAspectFill
48
-
49
- leadingChevronImageView.tintColor = .white
50
- trailingChevronView.tintColor = .white
51
-
52
- leadingChevronImageView.tintAdjustmentMode = .normal
53
- trailingChevronView.tintAdjustmentMode = .normal
54
-
55
- leadingView.layer.cornerRadius = 6
56
- leadingView.layer.cornerCurve = .continuous
57
- leadingView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMinXMinYCorner]
58
-
59
- trailingView.layer.cornerRadius = 6
60
- trailingView.layer.cornerCurve = .continuous
61
- trailingView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner]
62
-
63
- leadingView.addSubview(leadingChevronImageView)
64
- trailingView.addSubview(trailingChevronView)
65
-
66
- // wrapperView.layer.shadowColor = UIColor.black.cgColor
67
- // wrapperView.layer.shadowOffset = .zero
68
- // wrapperView.layer.shadowRadius = 2
69
- // wrapperView.layer.shadowOpacity = 0.25
70
-
71
- wrapperView.addSubview(leadingView)
72
- wrapperView.addSubview(trailingView)
73
- wrapperView.addSubview(topView)
74
- wrapperView.addSubview(bottomView)
75
- addSubview(wrapperView)
76
-
77
- wrapperView.addSubview(leadingGrabber)
78
- wrapperView.addSubview(trailingGrabber)
79
-
80
- updateColor()
81
- }
82
-
83
-
84
-
85
- // MARK: - UIView
86
-
87
- override func layoutSubviews() {
88
- super.layoutSubviews()
89
-
90
- let size = bounds.size
91
-
92
- wrapperView.frame = CGRect(origin: .zero, size: size)
93
-
94
- leadingView.frame = CGRect(x: 0, y: 0, width: chevronWidth, height: bounds.height)
95
- trailingView.frame = CGRect(x: bounds.width - chevronWidth, y: 0, width: chevronWidth, height: bounds.height)
96
- topView.frame = CGRect(x: chevronWidth, y: 0, width: bounds.width - chevronWidth * 2, height: edgeHeight)
97
- bottomView.frame = CGRect(x: chevronWidth, y: bounds.height - edgeHeight, width: bounds.width - chevronWidth * 2, height: edgeHeight)
98
-
99
- let chevronHorizontalInset = CGFloat(2)
100
- let chevronVerticalInset = CGFloat(8)
101
- let chevronFrame = CGRect(x: chevronHorizontalInset, y: chevronVerticalInset, width: chevronWidth - chevronHorizontalInset * 2, height: size.height - chevronVerticalInset * 2)
102
-
103
- leadingChevronImageView.frame = chevronFrame
104
- trailingChevronView.frame = chevronFrame
105
-
106
- leadingGrabber.frame = leadingView.frame
107
- trailingGrabber.frame = trailingView.frame
108
- }
109
-
110
- override init(frame: CGRect) {
111
- super.init(frame: frame)
112
- setup()
113
- }
114
-
115
- required init?(coder: NSCoder) {
116
- super.init(coder: coder)
117
- setup()
118
- }
119
- }
@@ -1,301 +0,0 @@
1
- //
2
- // VideoTrimmerViewController.swift
3
- // Shakebug
4
- //
5
- // Created by ideveloper2 on 26/04/24.
6
- // Copyright © 2024 Facebook. All rights reserved.
7
- //
8
-
9
- import UIKit
10
- import AVKit
11
-
12
- extension CMTime {
13
- var displayString: String {
14
- let offset = TimeInterval(seconds)
15
- let numberOfNanosecondsFloat = (offset - TimeInterval(Int(offset))) * 1000.0
16
- let nanoseconds = Int(numberOfNanosecondsFloat)
17
- let formatter = DateComponentsFormatter()
18
- formatter.unitsStyle = .positional
19
- formatter.zeroFormattingBehavior = .pad
20
- formatter.allowedUnits = [.minute, .second]
21
- return String(format: "%@.%03d", formatter.string(from: offset) ?? "00:00", nanoseconds)
22
- }
23
- }
24
-
25
- extension AVAsset {
26
- var fullRange: CMTimeRange {
27
- return CMTimeRange(start: .zero, duration: duration)
28
- }
29
- func trimmedComposition(_ range: CMTimeRange) -> AVAsset {
30
- guard CMTimeRangeEqual(fullRange, range) == false else {return self}
31
-
32
- let composition = AVMutableComposition()
33
- try? composition.insertTimeRange(range, of: self, at: .zero)
34
-
35
- if let videoTrack = tracks(withMediaType: .video).first {
36
- composition.tracks.forEach {$0.preferredTransform = videoTrack.preferredTransform}
37
- }
38
- return composition
39
- }
40
- }
41
-
42
- @available(iOS 13.0, *)
43
- class VideoTrimmerViewController: UIViewController {
44
- var asset: AVAsset!
45
- var maximumDuration: Int?
46
- var minimumDuration: Int?
47
- var cancelBtnText = "Cancel"
48
- var saveButtonText = "Save"
49
- var cancelBtnClicked: (() -> Void)?
50
- var saveBtnClicked: ((CMTimeRange) -> Void)?
51
-
52
- let playerController = AVPlayerViewController()
53
- var trimmer: VideoTrimmer!
54
- var timingStackView: UIStackView!
55
- var leadingTrimLabel: UILabel!
56
- var currentTimeLabel: UILabel!
57
- var trailingTrimLabel: UILabel!
58
-
59
- private var btnStackView: UIStackView!
60
- private var cancelBtn: UIButton!
61
- private var playBtn: UIButton!
62
- private var saveBtn: UIButton!
63
- private let playIcon = UIImage(systemName: "play.fill")
64
- private let pauseIcon = UIImage(systemName: "pause.fill")
65
-
66
- private var wasPlaying = false
67
- private var player: AVPlayer! {playerController.player}
68
- private var timeObserverToken: Any?
69
-
70
-
71
- // MARK: - Input
72
- @objc private func didBeginTrimming(_ sender: VideoTrimmer) {
73
- updateLabels()
74
-
75
- wasPlaying = (player.timeControlStatus != .paused)
76
- player.pause()
77
-
78
- updatePlayerAsset()
79
- }
80
-
81
- @objc private func didEndTrimming(_ sender: VideoTrimmer) {
82
- updateLabels()
83
-
84
- if wasPlaying == true {
85
- player.play()
86
- }
87
-
88
- updatePlayerAsset()
89
- }
90
-
91
- @objc private func selectedRangeDidChanged(_ sender: VideoTrimmer) {
92
- updateLabels()
93
- }
94
-
95
- @objc private func didBeginScrubbing(_ sender: VideoTrimmer) {
96
- updateLabels()
97
-
98
- wasPlaying = (player.timeControlStatus != .paused)
99
- player.pause()
100
- }
101
-
102
- @objc private func didEndScrubbing(_ sender: VideoTrimmer) {
103
- updateLabels()
104
-
105
- if wasPlaying == true {
106
- player.play()
107
- }
108
- }
109
-
110
- @objc private func progressDidChanged(_ sender: VideoTrimmer) {
111
- updateLabels()
112
-
113
- let time = CMTimeSubtract(trimmer.progress, trimmer.selectedRange.start)
114
- player.seek(to: time, toleranceBefore: .zero, toleranceAfter: .zero)
115
- }
116
-
117
- // MARK: - Private
118
- private func updateLabels() {
119
- leadingTrimLabel.text = trimmer.selectedRange.start.displayString
120
- currentTimeLabel.text = trimmer.progress.displayString
121
- trailingTrimLabel.text = trimmer.selectedRange.end.displayString
122
- }
123
-
124
- private func updatePlayerAsset() {
125
- let outputRange = trimmer.trimmingState == .none ? trimmer.selectedRange : asset.fullRange
126
- let trimmedAsset = asset.trimmedComposition(outputRange)
127
- if trimmedAsset != player.currentItem?.asset {
128
- player.replaceCurrentItem(with: AVPlayerItem(asset: trimmedAsset))
129
- }
130
- }
131
-
132
- // MARK: - UIViewController
133
- override func viewDidLoad() {
134
- super.viewDidLoad()
135
-
136
- view.backgroundColor = .black
137
-
138
- // bottom action buttons
139
- cancelBtn = UIButton(type: .system)
140
- cancelBtn.setTitle(cancelBtnText, for: .normal)
141
- cancelBtn.titleLabel?.font = .systemFont(ofSize: 18)
142
- cancelBtn.setTitleColor(.white, for: .normal)
143
- cancelBtn.addTarget(self, action: #selector(onCancelBtnClicked), for: .touchUpInside)
144
-
145
-
146
- playBtn = UIButton(type: .system)
147
- playBtn.setImage(playIcon, for: .normal)
148
- playBtn.tintColor = .systemBlue
149
- playBtn.addTarget(self, action: #selector(togglePlay(sender:)), for: .touchUpInside)
150
-
151
- saveBtn = UIButton(type: .system)
152
- saveBtn.setTitle(saveButtonText, for: .normal)
153
- saveBtn.titleLabel?.font = .systemFont(ofSize: 18)
154
- saveBtn.setTitleColor(.systemBlue, for: .normal)
155
- saveBtn.addTarget(self, action: #selector(onSaveBtnClicked), for: .touchUpInside)
156
-
157
- btnStackView = UIStackView(arrangedSubviews: [cancelBtn, playBtn, saveBtn])
158
- btnStackView.axis = .horizontal
159
- btnStackView.alignment = .fill
160
- btnStackView.distribution = .fillEqually
161
- btnStackView.spacing = UIStackView.spacingUseSystem
162
- view.addSubview(btnStackView)
163
- btnStackView.translatesAutoresizingMaskIntoConstraints = false
164
- NSLayoutConstraint.activate([
165
- btnStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
166
- btnStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
167
- btnStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16),
168
- ])
169
-
170
- // time labels
171
- leadingTrimLabel = UILabel()
172
- leadingTrimLabel.font = UIFont.preferredFont(forTextStyle: .caption1)
173
- leadingTrimLabel.textAlignment = .left
174
- leadingTrimLabel.textColor = .white
175
-
176
- currentTimeLabel = UILabel()
177
- currentTimeLabel.font = UIFont.preferredFont(forTextStyle: .caption1)
178
- currentTimeLabel.textAlignment = .center
179
- currentTimeLabel.textColor = .white
180
-
181
- trailingTrimLabel = UILabel()
182
- trailingTrimLabel.font = UIFont.preferredFont(forTextStyle: .caption1)
183
- trailingTrimLabel.textAlignment = .right
184
- trailingTrimLabel.textColor = .white
185
-
186
- timingStackView = UIStackView(arrangedSubviews: [leadingTrimLabel, currentTimeLabel, trailingTrimLabel])
187
- timingStackView.axis = .horizontal
188
- timingStackView.alignment = .fill
189
- timingStackView.distribution = .fillEqually
190
- timingStackView.spacing = UIStackView.spacingUseSystem
191
- view.addSubview(timingStackView)
192
- timingStackView.translatesAutoresizingMaskIntoConstraints = false
193
- NSLayoutConstraint.activate([
194
- timingStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
195
- timingStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
196
- timingStackView.bottomAnchor.constraint(equalTo: btnStackView.topAnchor, constant: -8),
197
- ])
198
-
199
- // THIS IS WHERE WE SETUP THE VIDEOTRIMMER:
200
- trimmer = VideoTrimmer()
201
- trimmer.asset = asset // this should happen before trimmer.selectedRange below otherwise its didSet will override
202
- trimmer.minimumDuration = CMTime(seconds: 1, preferredTimescale: 600)
203
-
204
- if maximumDuration != nil {
205
- trimmer.maximumDuration = CMTime(seconds: max(1, Double(maximumDuration!)), preferredTimescale: 600) // minimum 1 second
206
-
207
- // guard check to make sure max duration can only <= asset.duration
208
- if CMTimeCompare(trimmer.maximumDuration, asset.duration) == 1 {
209
- trimmer.maximumDuration = asset.duration
210
- }
211
-
212
- trimmer.selectedRange = CMTimeRange(start: .zero, end: trimmer.maximumDuration)
213
- }
214
-
215
- if minimumDuration != nil {
216
- trimmer.minimumDuration = CMTime(seconds: max(1, Double(minimumDuration!)), preferredTimescale: 600) // minimum 1 second
217
- }
218
-
219
- trimmer.addTarget(self, action: #selector(didBeginTrimming(_:)), for: VideoTrimmer.didBeginTrimming)
220
- trimmer.addTarget(self, action: #selector(didEndTrimming(_:)), for: VideoTrimmer.didEndTrimming)
221
- trimmer.addTarget(self, action: #selector(selectedRangeDidChanged(_:)), for: VideoTrimmer.selectedRangeChanged)
222
- trimmer.addTarget(self, action: #selector(didBeginScrubbing(_:)), for: VideoTrimmer.didBeginScrubbing)
223
- trimmer.addTarget(self, action: #selector(didEndScrubbing(_:)), for: VideoTrimmer.didEndScrubbing)
224
- trimmer.addTarget(self, action: #selector(progressDidChanged(_:)), for: VideoTrimmer.progressChanged)
225
- view.addSubview(trimmer)
226
- trimmer.translatesAutoresizingMaskIntoConstraints = false
227
- NSLayoutConstraint.activate([
228
- trimmer.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
229
- trimmer.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
230
- trimmer.bottomAnchor.constraint(equalTo: timingStackView.topAnchor, constant: -16),
231
- trimmer.heightAnchor.constraint(equalToConstant: 50),
232
- ])
233
-
234
- playerController.showsPlaybackControls = false // hide control buttons
235
- if #available(iOS 16.0, *) {
236
- playerController.allowsVideoFrameAnalysis = false // hide live text
237
- }
238
- playerController.player = AVPlayer()
239
- try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: []) // this is to play audio even when device is in silent mode
240
- addChild(playerController)
241
- view.addSubview(playerController.view)
242
- playerController.view.translatesAutoresizingMaskIntoConstraints = false
243
- NSLayoutConstraint.activate([
244
- playerController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
245
- playerController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
246
- playerController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
247
- playerController.view.bottomAnchor.constraint(equalTo: trimmer.topAnchor, constant: -16)
248
- ])
249
-
250
- updatePlayerAsset()
251
-
252
- timeObserverToken = player.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 30), queue: .main) { [weak self] time in
253
- guard let self = self else {return}
254
-
255
- currentTimeLabel.text = player.currentTime().displayString
256
-
257
- // when we're not trimming, the players starting point is actual later than the trimmer,
258
- // (because the vidoe has been trimmed), so we need to account for that.
259
- // When we're trimming, we always show the full video
260
- let finalTime = self.trimmer.trimmingState == .none ? CMTimeAdd(time, self.trimmer.selectedRange.start) : time
261
- self.trimmer.progress = finalTime
262
-
263
- if self.player.timeControlStatus == .playing {
264
- self.playBtn.setImage(self.pauseIcon, for: .normal)
265
- } else {
266
- self.playBtn.setImage(self.playIcon, for: .normal)
267
- }
268
- }
269
-
270
- updateLabels()
271
- }
272
-
273
- override func viewWillDisappear(_ animated: Bool) {
274
- super.viewWillDisappear(animated)
275
-
276
- player.pause()
277
- if timeObserverToken != nil {
278
- player.removeTimeObserver(timeObserverToken as Any)
279
- timeObserverToken = nil
280
- }
281
- playerController.player = nil
282
- playerController.dismiss(animated: false, completion: nil)
283
- }
284
-
285
- @objc private func togglePlay(sender: UIButton) {
286
- if player.timeControlStatus == .playing {
287
- player.pause()
288
- } else {
289
- player.play()
290
- }
291
-
292
- }
293
-
294
- @objc func onSaveBtnClicked() {
295
- saveBtnClicked?(trimmer.selectedRange)
296
- }
297
-
298
- @objc func onCancelBtnClicked() {
299
- cancelBtnClicked?()
300
- }
301
- }