11import Foundation
2+ import IONCameraLib
23import Capacitor
34import Photos
45import PhotosUI
@@ -8,6 +9,12 @@ public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
89 public let identifier = " CAPCameraPlugin "
910 public let jsName = " Camera "
1011 public let pluginMethods : [ CAPPluginMethod ] = [
12+ CAPPluginMethod ( name: " takePhoto " , returnType: CAPPluginReturnPromise) ,
13+ CAPPluginMethod ( name: " chooseFromGallery " , returnType: CAPPluginReturnPromise) ,
14+ CAPPluginMethod ( name: " editURIPhoto " , returnType: CAPPluginReturnPromise) ,
15+ CAPPluginMethod ( name: " editPhoto " , returnType: CAPPluginReturnPromise) ,
16+ CAPPluginMethod ( name: " recordVideo " , returnType: CAPPluginReturnPromise) ,
17+ CAPPluginMethod ( name: " playVideo " , returnType: CAPPluginReturnPromise) ,
1118 CAPPluginMethod ( name: " getPhoto " , returnType: CAPPluginReturnPromise) ,
1219 CAPPluginMethod ( name: " pickImages " , returnType: CAPPluginReturnPromise) ,
1320 CAPPluginMethod ( name: " checkPermissions " , returnType: CAPPluginReturnPromise) ,
@@ -20,8 +27,83 @@ public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
2027 private let defaultSource = CameraSource . prompt
2128 private let defaultDirection = CameraDirection . rear
2229 private var multiple = false
30+
31+ private lazy var cameraManager = IONCAMRFactory . createCameraManagerWrapper ( withDelegate: self , and: self . bridge? . viewController ?? UIViewController ( ) )
32+ private lazy var galleryManager = IONCAMRFactory . createGalleryManagerWrapper ( withDelegate: self , and: self . bridge? . viewController ?? UIViewController ( ) )
33+ private lazy var editManager = IONCAMRFactory . createEditManagerWrapper ( withDelegate: self , and: self . bridge? . viewController ?? UIViewController ( ) )
34+ private lazy var videoManager = IONCAMRFactory . createVideoManagerWrapper ( withDelegate: self , and: self . bridge? . viewController ?? UIViewController ( ) )
2335
2436 private var imageCounter = 0
37+
38+ private func decodeParameters< T: Decodable > ( from call: CAPPluginCall ) -> T ? {
39+ guard let dict = call. options as? [ String : Any ] ,
40+ let data = try ? JSONSerialization . data ( withJSONObject: dict)
41+ else { return nil }
42+ return try ? JSONDecoder ( ) . decode ( T . self, from: data)
43+ }
44+
45+ private func sendError( _ error: IONCAMRError ) {
46+ DispatchQueue . main. async {
47+ self . call? . reject ( error. localizedDescription, " OS-PLUG-CAMR- " + String( format: " %04d " , error. errorCode) )
48+ }
49+ }
50+
51+ private func handleCall< T: Decodable > ( _ call: CAPPluginCall , error: IONCAMRError , action: @escaping ( T ) -> Void ) {
52+ self . call = call
53+ guard let options: T = decodeParameters ( from: call) else {
54+ sendError ( error)
55+ return
56+ }
57+ DispatchQueue . main. async {
58+ action ( options)
59+ }
60+ }
61+
62+ @objc func takePhoto( _ call: CAPPluginCall ) {
63+ handleCall ( call, error: . takePictureArguments) { ( options: IONCAMRTakePhotoOptions ) in
64+ self . cameraManager. takePhoto ( with: options)
65+ }
66+ }
67+
68+ @objc func chooseFromGallery( _ call: CAPPluginCall ) {
69+ handleCall ( call, error: . chooseMultimediaIssue) { ( options: IONCAMRGalleryOptions ) in
70+ self . galleryManager. chooseFromGallery ( with: options)
71+ }
72+ }
73+
74+ @objc func editURIPhoto( _ call: CAPPluginCall ) {
75+ handleCall ( call, error: . editPictureIssue) { ( options: IONCAMRPhotoEditOptions ) in
76+ self . editManager. editPhoto ( with: options)
77+ }
78+ }
79+
80+ @objc func editPhoto( _ call: CAPPluginCall ) {
81+ handleCall ( call, error: . editPictureIssue) { ( options: IONCAMRPhotoEditOptions ) in
82+ self . editManager. editPhoto ( with: options)
83+ }
84+ }
85+
86+ @objc func recordVideo( _ call: CAPPluginCall ) {
87+ handleCall ( call, error: . captureVideoIssue) { ( options: IONCAMRRecordVideoOptions ) in
88+ self . cameraManager. recordVideo ( with: options)
89+ }
90+ }
91+
92+ @objc func playVideo( _ call: CAPPluginCall ) {
93+ handleCall ( call, error: . playVideoIssue) { ( options: IONCAMRPlayVideoOptions ) in
94+ Task {
95+ do {
96+ try await self . videoManager. playVideo ( options. url)
97+ call. resolve ( )
98+ } catch let error as IONCAMRError {
99+ self . callback ( error: error)
100+ } catch {
101+ self . callback ( error: . playVideoIssue)
102+ }
103+ }
104+ }
105+ }
106+
25107
26108 @objc override public func checkPermissions( _ call: CAPPluginCall ) {
27109 var result : [ String : Any ] = [ : ]
@@ -126,6 +208,7 @@ public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
126208 }
127209 }
128210
211+ @available ( * , deprecated, message: " Use takePhoto or chooseFromGallery instead " )
129212 @objc func getPhoto( _ call: CAPPluginCall ) {
130213 self . multiple = false
131214 self . call = call
@@ -150,15 +233,6 @@ public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
150233 }
151234 }
152235
153- @objc func pickImages( _ call: CAPPluginCall ) {
154- self . multiple = true
155- self . call = call
156- self . settings = cameraSettings ( from: call)
157- DispatchQueue . main. async {
158- self . showPhotos ( )
159- }
160- }
161-
162236 private func checkUsageDescriptions( ) -> String ? {
163237 if let dict = Bundle . main. infoDictionary {
164238 for key in CameraPropertyListKeys . allCases where dict [ key. rawValue] == nil {
@@ -168,6 +242,16 @@ public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
168242 return nil
169243 }
170244
245+ @available ( * , deprecated, message: " Use chooseFromGallery instead " )
246+ @objc func pickImages( _ call: CAPPluginCall ) {
247+ self . multiple = true
248+ self . call = call
249+ self . settings = cameraSettings ( from: call)
250+ DispatchQueue . main. async {
251+ self . showPhotos ( )
252+ }
253+ }
254+
171255 private func cameraSettings( from call: CAPPluginCall ) -> CameraSettings {
172256 var settings = CameraSettings ( )
173257 settings. jpegQuality = min ( abs ( CGFloat ( call. getFloat ( " quality " ) ?? 100.0 ) ) / 100.0 , 1.0 )
@@ -551,3 +635,64 @@ private extension CameraPlugin {
551635 return result
552636 }
553637}
638+
639+ extension CameraPlugin : IONCAMRCallbackDelegate {
640+
641+ public func callback( error: IONCAMRError ) {
642+ sendError ( error)
643+ }
644+
645+ public func callback( result: IONCAMRMediaResult ) {
646+ resolve ( result)
647+ }
648+
649+ public func callback( result: [ IONCAMRMediaResult ] ) {
650+ resolve ( [ " results " : result] )
651+ }
652+
653+ private func resolve< T: Encodable > ( _ value: T ) {
654+ do {
655+ let data = try JSONEncoder ( ) . encode ( value)
656+ var json = try JSONSerialization . jsonObject ( with: data)
657+
658+ // Add webPath to results
659+ if var dict = json as? [ String : Any ] {
660+ // Handle single result
661+ if let uri = dict [ " uri " ] as? String ,
662+ let webPath = resolveWebPath ( from: uri) {
663+ dict [ " webPath " ] = webPath
664+ }
665+
666+ // Handle array of results
667+ if var results = dict [ " results " ] as? [ [ String : Any ] ] {
668+ results = results. map { item in
669+ var newItem = item
670+ if let uri = item [ " uri " ] as? String ,
671+ let webPath = resolveWebPath ( from: uri) {
672+ newItem [ " webPath " ] = webPath
673+ }
674+ return newItem
675+ }
676+ dict [ " results " ] = results
677+ }
678+
679+ json = dict
680+ }
681+
682+ DispatchQueue . main. async {
683+ self . call? . resolve ( json as? [ String : Any ] ?? [ : ] )
684+ }
685+ } catch {
686+ sendError ( . invalidEncodeResultMedia)
687+ }
688+ }
689+
690+ private func resolveWebPath( from uri: String ) -> String ? {
691+ guard !uri. isEmpty,
692+ let fileURL = URL ( string: uri) ,
693+ let webURL = bridge? . portablePath ( fromLocalURL: fileURL) else {
694+ return nil
695+ }
696+ return webURL. absoluteString
697+ }
698+ }
0 commit comments