@capgo/camera-preview 7.24.15 → 7.26.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 +8 -3
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +22 -4
- package/dist/docs.json +28 -2
- package/dist/esm/definitions.d.ts +12 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +3 -1
- package/dist/esm/web.js +7 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +7 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +7 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +146 -25
- package/package.json +1 -1
|
@@ -34,7 +34,7 @@ extension UIWindow {
|
|
|
34
34
|
*/
|
|
35
35
|
@objc(CameraPreview)
|
|
36
36
|
public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelegate {
|
|
37
|
-
private let pluginVersion: String = "7.
|
|
37
|
+
private let pluginVersion: String = "7.26.0"
|
|
38
38
|
public let identifier = "CameraPreviewPlugin"
|
|
39
39
|
public let jsName = "CameraPreview"
|
|
40
40
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -106,6 +106,10 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
106
106
|
private var waitingForLocation: Bool = false
|
|
107
107
|
private var isPresentingPermissionAlert: Bool = false
|
|
108
108
|
|
|
109
|
+
// Store original webview colors to restore them when stopping
|
|
110
|
+
private var originalWebViewBackgroundColor: UIColor?
|
|
111
|
+
private var originalWebViewSubviewColors: [UIView: UIColor] = [:]
|
|
112
|
+
|
|
109
113
|
// MARK: - Helper Methods for Aspect Ratio
|
|
110
114
|
|
|
111
115
|
/// Parses aspect ratio string and returns the appropriate ratio for the current orientation
|
|
@@ -141,6 +145,30 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
141
145
|
private func makeWebViewTransparent() {
|
|
142
146
|
guard let webView = self.webView else { return }
|
|
143
147
|
|
|
148
|
+
// IMPORTANT: Save colors synchronously FIRST to prevent race condition
|
|
149
|
+
// If we don't have saved colors yet, save them now (before going async)
|
|
150
|
+
if self.originalWebViewBackgroundColor == nil {
|
|
151
|
+
self.originalWebViewBackgroundColor = webView.backgroundColor
|
|
152
|
+
self.originalWebViewSubviewColors.removeAll()
|
|
153
|
+
|
|
154
|
+
// Define a recursive function to traverse and save colors
|
|
155
|
+
func saveSubviewColors(_ view: UIView) {
|
|
156
|
+
// Save the original background color before changing it
|
|
157
|
+
if let bgColor = view.backgroundColor, bgColor != .clear {
|
|
158
|
+
self.originalWebViewSubviewColors[view] = bgColor
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Recurse for all subviews
|
|
162
|
+
for subview in view.subviews {
|
|
163
|
+
saveSubviewColors(subview)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Save all subview colors synchronously
|
|
168
|
+
saveSubviewColors(webView)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Now make the changes asynchronously on main thread
|
|
144
172
|
DispatchQueue.main.async {
|
|
145
173
|
_ = CFAbsoluteTimeGetCurrent()
|
|
146
174
|
|
|
@@ -170,6 +198,51 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
170
198
|
}
|
|
171
199
|
}
|
|
172
200
|
|
|
201
|
+
private func restoreWebViewBackground(_ webView: UIView) {
|
|
202
|
+
// Restore the saved background colors
|
|
203
|
+
func restoreSubviewsBackground(_ view: UIView) {
|
|
204
|
+
// Restore the saved background color for this view
|
|
205
|
+
if let savedColor = self.originalWebViewSubviewColors[view] {
|
|
206
|
+
view.backgroundColor = savedColor
|
|
207
|
+
} else {
|
|
208
|
+
// Fallback: If no saved color, intelligently restore based on view type
|
|
209
|
+
let className = String(describing: type(of: view))
|
|
210
|
+
if className.contains("WKScrollView") || className.contains("WKContentView") {
|
|
211
|
+
// Only restore if it's currently clear (meaning we likely made it transparent)
|
|
212
|
+
if view.backgroundColor == .clear || view.backgroundColor == nil {
|
|
213
|
+
view.backgroundColor = .white
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Recurse for all subviews
|
|
219
|
+
for subview in view.subviews {
|
|
220
|
+
restoreSubviewsBackground(subview)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Restore the main webview background color
|
|
225
|
+
if let originalColor = self.originalWebViewBackgroundColor {
|
|
226
|
+
webView.backgroundColor = originalColor
|
|
227
|
+
} else {
|
|
228
|
+
// Fallback: If no saved color and webview is clear, restore to white
|
|
229
|
+
if webView.backgroundColor == .clear || webView.backgroundColor == nil {
|
|
230
|
+
webView.backgroundColor = .white
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Restore all subviews
|
|
235
|
+
restoreSubviewsBackground(webView)
|
|
236
|
+
|
|
237
|
+
// Clear the saved colors dictionary
|
|
238
|
+
self.originalWebViewSubviewColors.removeAll()
|
|
239
|
+
self.originalWebViewBackgroundColor = nil
|
|
240
|
+
|
|
241
|
+
// Force a layout pass to apply changes
|
|
242
|
+
webView.setNeedsLayout()
|
|
243
|
+
webView.layoutIfNeeded()
|
|
244
|
+
}
|
|
245
|
+
|
|
173
246
|
private func presentCameraPermissionAlert(title: String,
|
|
174
247
|
message: String,
|
|
175
248
|
openSettingsText: String,
|
|
@@ -580,20 +653,54 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
580
653
|
print(" - positioning: \(call.getString("positioning") ?? "top")")
|
|
581
654
|
print(" - initialZoomLevel: \(call.getFloat("initialZoomLevel") ?? 1.0)")
|
|
582
655
|
print(" - disableFocusIndicator: \(call.getBool("disableFocusIndicator") ?? false)")
|
|
656
|
+
print(" - force: \(call.getBool("force") ?? false)")
|
|
583
657
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
658
|
+
let force = call.getBool("force") ?? false
|
|
659
|
+
|
|
660
|
+
// If force is true, kill everything and restart no matter what
|
|
661
|
+
if force {
|
|
662
|
+
if self.isInitializing || self.isInitialized || self.cameraController.isCapturingPhoto || self.cameraController.stopRequestedAfterCapture {
|
|
663
|
+
// Force stop everything synchronously
|
|
664
|
+
DispatchQueue.main.sync {
|
|
665
|
+
self.cameraController.removeGridOverlay()
|
|
666
|
+
if let previewView = self.previewView {
|
|
667
|
+
previewView.removeFromSuperview()
|
|
668
|
+
self.previewView = nil
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Restore webView to opaque state with original background
|
|
672
|
+
if let webView = self.webView {
|
|
673
|
+
webView.isOpaque = true
|
|
674
|
+
// Restore the original background colors that were saved
|
|
675
|
+
self.restoreWebViewBackground(webView)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Force stop the camera controller regardless of state
|
|
679
|
+
self.cameraController.stopRequestedAfterCapture = false
|
|
680
|
+
self.cameraController.cleanup()
|
|
681
|
+
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
|
|
682
|
+
UIDevice.current.endGeneratingDeviceOrientationNotifications()
|
|
683
|
+
self.isInitialized = false
|
|
684
|
+
self.isInitializing = false
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
// Normal checks only when force is false
|
|
689
|
+
if self.isInitializing {
|
|
690
|
+
call.reject("camera initialization in progress")
|
|
691
|
+
return
|
|
692
|
+
}
|
|
693
|
+
if self.isInitialized {
|
|
694
|
+
call.reject("camera already started")
|
|
695
|
+
return
|
|
696
|
+
}
|
|
697
|
+
// Guard against starting while a deferred stop is pending due to in-flight capture
|
|
698
|
+
if self.cameraController.isCapturingPhoto || self.cameraController.stopRequestedAfterCapture {
|
|
699
|
+
call.reject("camera is stopping or busy, please retry shortly")
|
|
700
|
+
return
|
|
701
|
+
}
|
|
596
702
|
}
|
|
703
|
+
|
|
597
704
|
self.isInitializing = true
|
|
598
705
|
|
|
599
706
|
self.cameraPosition = call.getString("position") ?? "rear"
|
|
@@ -653,7 +760,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
653
760
|
return
|
|
654
761
|
}
|
|
655
762
|
let beginStart: () -> Void = {
|
|
656
|
-
if self.cameraController.captureSession?.isRunning ?? false {
|
|
763
|
+
if (self.cameraController.captureSession?.isRunning ?? false) && !force {
|
|
657
764
|
DispatchQueue.main.async {
|
|
658
765
|
self.isInitializing = false
|
|
659
766
|
call.reject("camera already started")
|
|
@@ -826,13 +933,18 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
826
933
|
}
|
|
827
934
|
|
|
828
935
|
@objc func stop(_ call: CAPPluginCall) {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
936
|
+
let force = call.getBool("force") ?? false
|
|
937
|
+
|
|
938
|
+
// If force is true, skip all checks and force stop
|
|
939
|
+
if !force {
|
|
940
|
+
if self.isInitializing {
|
|
941
|
+
call.reject("cannot stop camera while initialization is in progress")
|
|
942
|
+
return
|
|
943
|
+
}
|
|
944
|
+
if !self.isInitialized {
|
|
945
|
+
call.reject("camera not initialized")
|
|
946
|
+
return
|
|
947
|
+
}
|
|
836
948
|
}
|
|
837
949
|
|
|
838
950
|
// UI operations must be on main thread
|
|
@@ -845,7 +957,13 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
845
957
|
self.previewView = nil
|
|
846
958
|
}
|
|
847
959
|
|
|
848
|
-
|
|
960
|
+
// Restore webView to opaque state with original background
|
|
961
|
+
if let webView = self.webView {
|
|
962
|
+
webView.isOpaque = true
|
|
963
|
+
// Restore the original background colors that were saved
|
|
964
|
+
self.restoreWebViewBackground(webView)
|
|
965
|
+
}
|
|
966
|
+
|
|
849
967
|
self.isInitialized = false
|
|
850
968
|
self.isInitializing = false
|
|
851
969
|
|
|
@@ -854,11 +972,14 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
854
972
|
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
|
|
855
973
|
UIDevice.current.endGeneratingDeviceOrientationNotifications()
|
|
856
974
|
|
|
857
|
-
if self.cameraController.isCapturingPhoto {
|
|
858
|
-
// Defer heavy cleanup until capture callback completes
|
|
975
|
+
if self.cameraController.isCapturingPhoto && !force {
|
|
976
|
+
// Defer heavy cleanup until capture callback completes (only if not forcing)
|
|
859
977
|
self.cameraController.stopRequestedAfterCapture = true
|
|
860
978
|
} else {
|
|
861
|
-
//
|
|
979
|
+
// Force stop or no capture pending; cleanup now
|
|
980
|
+
if force {
|
|
981
|
+
self.cameraController.stopRequestedAfterCapture = false
|
|
982
|
+
}
|
|
862
983
|
self.cameraController.cleanup()
|
|
863
984
|
}
|
|
864
985
|
|