@octane-xplat/camera 0.14.0 → 0.15.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.
Files changed (81) hide show
  1. package/README.md +26 -0
  2. package/package.json +22 -16
  3. package/platforms/android/java/com/octanexplat/camera/CameraPreviewView.java +9 -0
  4. package/platforms/android/java/com/octanexplat/camera/CameraSessionBridge.java +31 -0
  5. package/platforms/macos/src/CameraOwnership.swift +22 -0
  6. package/platforms/macos/src/PhotoCaptureLifecycle.swift +34 -0
  7. package/platforms/macos/src/XplatCameraHost.swift +139 -13
  8. package/platforms/macos/src/XplatPhotoCaptureSheet.swift +192 -0
  9. package/src/CameraView.android.tsrx +6 -2
  10. package/src/CameraView.ios.tsrx +4 -2
  11. package/src/CameraView.macos.tsrx +4 -2
  12. package/src/CameraView.web.tsrx +11 -0
  13. package/src/CameraView.windows.tsrx +4 -2
  14. package/src/camera-permission.mobile.ts +18 -4
  15. package/src/camera-session.windows.ts +4 -1
  16. package/src/host-movie.web.ts +141 -26
  17. package/src/index.ts +1 -0
  18. package/src/index.web.ts +1 -0
  19. package/src/preview-tap.ts +34 -0
  20. package/src/props.ts +8 -1
  21. package/src/session-backend.android.ts +42 -0
  22. package/src/session-backend.ios.ts +183 -17
  23. package/src/session-backend.linux.ts +22 -4
  24. package/src/session-backend.macos.ts +100 -17
  25. package/src/session-backend.ts +2 -0
  26. package/src/session-backend.web.ts +17 -0
  27. package/src/session-backend.windows.ts +88 -6
  28. package/src/session-core.ts +73 -9
  29. package/src/synthetic-session.ts +10 -0
  30. package/src/types.ts +28 -0
  31. package/types/props.d.ts +8 -1
  32. package/types/session-core.d.ts +11 -1
  33. package/types/synthetic-session.d.ts +4 -1
  34. package/types/types.d.ts +27 -0
  35. package/dist/linux/CameraView.web.tsrx.js +0 -337
  36. package/dist/linux/host-movie.web.js +0 -100
  37. package/dist/linux/index.js +0 -5
  38. package/dist/linux/layout-child.web.js +0 -29
  39. package/dist/linux/movie-metadata.web.js +0 -65
  40. package/dist/linux/octane-client-build.json +0 -8
  41. package/dist/linux/session-backend.linux.js +0 -479
  42. package/dist/linux/session-core.js +0 -368
  43. package/dist/linux/session.js +0 -29
  44. package/dist/linux/synthetic-session.js +0 -280
  45. package/dist/linux/types.js +0 -19
  46. package/dist/native/CameraView.android.js +0 -190
  47. package/dist/native/CameraView.ios.js +0 -154
  48. package/dist/native/CameraView.windows.js +0 -173
  49. package/dist/native/camera-permission.mobile.js +0 -45
  50. package/dist/native/camera-permission.windows.js +0 -43
  51. package/dist/native/camera-session.ios.js +0 -45
  52. package/dist/native/camera-session.windows.js +0 -78
  53. package/dist/native/cx.mobile.js +0 -9
  54. package/dist/native/cx.windows.js +0 -9
  55. package/dist/native/index.js +0 -5
  56. package/dist/native/layout-child.js +0 -53
  57. package/dist/native/layout-child.windows.js +0 -53
  58. package/dist/native/octane-client-build.json +0 -8
  59. package/dist/native/session-backend.android.js +0 -234
  60. package/dist/native/session-backend.ios.js +0 -682
  61. package/dist/native/session-backend.js +0 -55
  62. package/dist/native/session-backend.windows.js +0 -905
  63. package/dist/native/session-core.js +0 -368
  64. package/dist/native/session.js +0 -29
  65. package/dist/native/synthetic-session.js +0 -280
  66. package/dist/native/types.js +0 -19
  67. package/dist/web/CameraView.web.tsrx.js +0 -337
  68. package/dist/web/host-movie.web.js +0 -100
  69. package/dist/web/index.js +0 -5
  70. package/dist/web/layout-child.web.js +0 -29
  71. package/dist/web/movie-metadata.web.js +0 -65
  72. package/dist/web/movie-storage.web.js +0 -119
  73. package/dist/web/octane-client-build.json +0 -8
  74. package/dist/web/session-backend.web.js +0 -490
  75. package/dist/web/session-core.js +0 -368
  76. package/dist/web/session.js +0 -29
  77. package/dist/web/synthetic-session.js +0 -280
  78. package/dist/web/types.js +0 -19
  79. package/src/cx.macos.ts +0 -5
  80. package/src/cx.mobile.ts +0 -6
  81. package/src/cx.windows.ts +0 -6
@@ -1,190 +0,0 @@
1
- import { attachSessionPreview } from "./session.js";
2
- import { cameraHardwarePresent, ensureCameraPermission } from "./camera-permission.mobile.js";
3
- import { applyEscapeProps, layoutChildProps, nativeAccessibilityRole, nativeAccessibilityState } from "./layout-child.js";
4
- import { cx } from "./cx.mobile.js";
5
- import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalProps, universalValue, useCallback, useEffect, useImperativeHandle, useRef } from "@nativescript-community/octane";
6
- import { Application, View } from "@nativescript/core";
7
- //#region src/CameraView.android.tsrx
8
- var _hs$ = /* @__PURE__ */ hookSlots(5);
9
- var _h$0 = /* @__PURE__ */ Symbol(_hs$);
10
- var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
11
- var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
12
- var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
13
- var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
14
- var __octaneUniversalPlan0 = universalPlan("nativescript", {
15
- "kind": "host",
16
- "type": "gridlayout",
17
- "propsSlot": 0,
18
- "children": [{
19
- "kind": "host",
20
- "type": "camerapreview",
21
- "props": {
22
- "row": 0,
23
- "col": 0
24
- },
25
- "bindings": [["ref", 1]]
26
- }]
27
- });
28
- var CameraPreview = class extends View {
29
- createNativeView() {
30
- const nativeClass = globalThis.com.octanexplat.camera.CameraPreviewView;
31
- return new nativeClass(this._context);
32
- }
33
- };
34
- registerElement("camerapreview", CameraPreview);
35
- var CameraView = defineUniversalComponent("nativescript", function CameraView(props) {
36
- const host = useRef(null, _h$0);
37
- const active = props.active !== false;
38
- const facing = props.facing ?? "back";
39
- useImperativeHandle(props.ref, () => ({ native: host.current.android }), [], _h$1);
40
- const bindHost = useCallback((view) => {
41
- host.current = view;
42
- }, [], _h$2);
43
- useEffect(() => {
44
- const nativeView = host.current?.android;
45
- if (!nativeView) return;
46
- let disposed = false;
47
- let provider;
48
- let preview;
49
- nativeView.setCameraActive(active);
50
- if (!active) return () => nativeView.setCameraActive(false);
51
- const fail = (message) => props.onError?.({ message });
52
- if (props.session) {
53
- if (props.facing !== void 0) {
54
- fail("camera session conflicts with facing");
55
- return () => nativeView.setCameraActive(false);
56
- }
57
- try {
58
- const detach = attachSessionPreview(props.session, nativeView, {
59
- onReady: props.onReady,
60
- onError: (issue) => fail(issue.message)
61
- });
62
- return () => {
63
- detach();
64
- nativeView.setCameraActive(false);
65
- };
66
- } catch (error) {
67
- fail(error?.message ?? "camera session error");
68
- return () => nativeView.setCameraActive(false);
69
- }
70
- }
71
- if (!cameraHardwarePresent()) {
72
- fail("camera unsupported");
73
- return () => nativeView.setCameraActive(false);
74
- }
75
- ensureCameraPermission().then((granted) => {
76
- if (disposed) return;
77
- if (!granted) {
78
- fail("camera permission denied");
79
- return;
80
- }
81
- try {
82
- const context = Application.android.context;
83
- const cameraX = globalThis.androidx.camera;
84
- const future = cameraX.lifecycle.ProcessCameraProvider.getInstance(context);
85
- const executor = globalThis.androidx.core.content.ContextCompat.getMainExecutor(context);
86
- future.addListener(new java.lang.Runnable({ run() {
87
- if (disposed) return;
88
- try {
89
- provider = future.get();
90
- const selectorClass = cameraX.core.CameraSelector;
91
- const lens = facing === "front" ? selectorClass.LENS_FACING_FRONT : selectorClass.LENS_FACING_BACK;
92
- const selector = new selectorClass.Builder().requireLensFacing(lens).build();
93
- preview = new cameraX.core.Preview.Builder().build();
94
- preview.setSurfaceProvider(nativeView.getSurfaceProvider());
95
- provider.bindToLifecycle(nativeView, selector, preview);
96
- props.onReady?.();
97
- } catch (error) {
98
- fail(error?.message ?? "camera error");
99
- }
100
- } }), executor);
101
- } catch (error) {
102
- fail(error?.message ?? "camera error");
103
- }
104
- });
105
- return () => {
106
- disposed = true;
107
- nativeView.setCameraActive(false);
108
- if (provider && preview) try {
109
- provider.unbind(preview);
110
- } catch {}
111
- };
112
- }, [
113
- active,
114
- facing,
115
- props.session
116
- ], _h$3);
117
- useEffect(() => {
118
- const view = host.current;
119
- if (!view) return;
120
- applyEscapeProps(view.android, props);
121
- }, [props.ref, props.android], _h$4);
122
- return universalValue(__octaneUniversalPlan0, [universalProps([
123
- [
124
- "set",
125
- "id",
126
- props.id
127
- ],
128
- [
129
- "set",
130
- "rows",
131
- "*"
132
- ],
133
- [
134
- "set",
135
- "columns",
136
- "*"
137
- ],
138
- [
139
- "set",
140
- "className",
141
- cx("vx-layers", "vx-cameraview", props.className)
142
- ],
143
- [
144
- "set",
145
- "style",
146
- {
147
- backgroundColor: "#000",
148
- ...props.style
149
- }
150
- ],
151
- ["spread", layoutChildProps(props)],
152
- [
153
- "set",
154
- "accessible",
155
- props.accessible
156
- ],
157
- [
158
- "set",
159
- "accessibilityLabel",
160
- props.accessibilityLabel
161
- ],
162
- [
163
- "set",
164
- "accessibilityRole",
165
- nativeAccessibilityRole(props.accessibilityRole)
166
- ],
167
- [
168
- "set",
169
- "accessibilityHint",
170
- props.accessibilityHint
171
- ],
172
- [
173
- "set",
174
- "accessibilityValue",
175
- props.accessibilityValue
176
- ],
177
- [
178
- "set",
179
- "accessibilityState",
180
- nativeAccessibilityState(props.accessibilityState)
181
- ],
182
- [
183
- "set",
184
- "accessibilityLiveRegion",
185
- props.accessibilityLiveRegion
186
- ]
187
- ]), bindHost]);
188
- }, { "module": "@nativescript-community/octane" });
189
- //#endregion
190
- export { CameraView };
@@ -1,154 +0,0 @@
1
- import { attachSessionPreview } from "./session.js";
2
- import { cameraHardwarePresent, ensureCameraPermission } from "./camera-permission.mobile.js";
3
- import { startCameraPreview } from "./camera-session.ios.js";
4
- import { applyEscapeProps, layoutChildProps, nativeAccessibilityRole, nativeAccessibilityState } from "./layout-child.js";
5
- import { cx } from "./cx.mobile.js";
6
- import { defineUniversalComponent, hookSlots, universalPlan, universalProps, universalValue, useCallback, useEffect, useImperativeHandle, useRef } from "@nativescript-community/octane";
7
- //#region src/CameraView.ios.tsrx
8
- var _hs$ = /* @__PURE__ */ hookSlots(5);
9
- var _h$0 = /* @__PURE__ */ Symbol(_hs$);
10
- var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
11
- var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
12
- var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
13
- var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
14
- var __octaneUniversalPlan0 = universalPlan("nativescript", {
15
- "kind": "host",
16
- "type": "gridlayout",
17
- "propsSlot": 0
18
- });
19
- var CameraView = defineUniversalComponent("nativescript", function CameraView(props) {
20
- const host = useRef(null, _h$0);
21
- const active = props.active !== false;
22
- const facing = props.facing ?? "back";
23
- useImperativeHandle(props.ref, () => ({ native: host.current.ios ?? host.current.nativeViewProtected }), [], _h$1);
24
- const bindHost = useCallback((view) => {
25
- host.current = view;
26
- }, [], _h$2);
27
- useEffect(() => {
28
- const view = host.current;
29
- if (!view || !active) return;
30
- let disposed = false;
31
- let stopPreview;
32
- const fail = (message) => props.onError?.({ message });
33
- if (props.session) {
34
- if (props.facing !== void 0) {
35
- fail("camera session conflicts with facing");
36
- return;
37
- }
38
- try {
39
- const detach = attachSessionPreview(props.session, view, { onReady: () => {
40
- if (!disposed) props.onReady?.();
41
- } });
42
- return () => {
43
- disposed = true;
44
- detach();
45
- };
46
- } catch (error) {
47
- fail(error?.message ?? "camera session error");
48
- return;
49
- }
50
- }
51
- if (!cameraHardwarePresent()) {
52
- fail("camera unsupported");
53
- return;
54
- }
55
- ensureCameraPermission().then((granted) => {
56
- if (disposed) return;
57
- if (!granted) {
58
- fail("camera permission denied");
59
- return;
60
- }
61
- try {
62
- stopPreview = startCameraPreview(view, facing, props.onReady);
63
- } catch (error) {
64
- fail(error?.message ?? "camera error");
65
- }
66
- });
67
- return () => {
68
- disposed = true;
69
- stopPreview?.();
70
- };
71
- }, [
72
- active,
73
- facing,
74
- props.session
75
- ], _h$3);
76
- useEffect(() => {
77
- const view = host.current;
78
- if (!view) return;
79
- applyEscapeProps(view.ios ?? view.nativeViewProtected, props);
80
- }, [props.ref, props.ios], _h$4);
81
- return universalValue(__octaneUniversalPlan0, [universalProps([
82
- [
83
- "set",
84
- "ref",
85
- bindHost
86
- ],
87
- [
88
- "set",
89
- "id",
90
- props.id
91
- ],
92
- [
93
- "set",
94
- "rows",
95
- "*"
96
- ],
97
- [
98
- "set",
99
- "columns",
100
- "*"
101
- ],
102
- [
103
- "set",
104
- "className",
105
- cx("vx-layers", "vx-cameraview", props.className)
106
- ],
107
- [
108
- "set",
109
- "style",
110
- {
111
- backgroundColor: "#000",
112
- ...props.style
113
- }
114
- ],
115
- ["spread", layoutChildProps(props)],
116
- [
117
- "set",
118
- "accessible",
119
- props.accessible
120
- ],
121
- [
122
- "set",
123
- "accessibilityLabel",
124
- props.accessibilityLabel
125
- ],
126
- [
127
- "set",
128
- "accessibilityRole",
129
- nativeAccessibilityRole(props.accessibilityRole)
130
- ],
131
- [
132
- "set",
133
- "accessibilityHint",
134
- props.accessibilityHint
135
- ],
136
- [
137
- "set",
138
- "accessibilityValue",
139
- props.accessibilityValue
140
- ],
141
- [
142
- "set",
143
- "accessibilityState",
144
- nativeAccessibilityState(props.accessibilityState)
145
- ],
146
- [
147
- "set",
148
- "accessibilityLiveRegion",
149
- props.accessibilityLiveRegion
150
- ]
151
- ])]);
152
- }, { "module": "@nativescript-community/octane" });
153
- //#endregion
154
- export { CameraView };
@@ -1,173 +0,0 @@
1
- import { attachSessionPreview } from "./session.js";
2
- import { cameraHardwarePresent, ensureCameraPermission } from "./camera-permission.windows.js";
3
- import { startCameraPreview } from "./camera-session.windows.js";
4
- import { applyEscapeProps, layoutChildProps, nativeAccessibilityRole, nativeAccessibilityState } from "./layout-child.windows.js";
5
- import { cx } from "./cx.windows.js";
6
- import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalProps, universalValue, useCallback, useEffect, useImperativeHandle, useRef } from "@nativescript-community/octane";
7
- import { View } from "@nativescript/core";
8
- //#region src/CameraView.windows.tsrx
9
- var _hs$ = /* @__PURE__ */ hookSlots(5);
10
- var _h$0 = /* @__PURE__ */ Symbol(_hs$);
11
- var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
12
- var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
13
- var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
14
- var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
15
- var __octaneUniversalPlan0 = universalPlan("nativescript", {
16
- "kind": "host",
17
- "type": "gridlayout",
18
- "propsSlot": 0,
19
- "children": [{
20
- "kind": "host",
21
- "type": "camerapreview",
22
- "props": {
23
- "row": 0,
24
- "col": 0
25
- },
26
- "bindings": [["ref", 1]]
27
- }]
28
- });
29
- var CameraPreview = class extends View {
30
- createNativeView() {
31
- const { Microsoft } = globalThis;
32
- return new Microsoft.UI.Xaml.Controls.CaptureElement();
33
- }
34
- };
35
- registerElement("camerapreview", CameraPreview);
36
- var CameraView = defineUniversalComponent("nativescript", function CameraView(props) {
37
- const host = useRef(null, _h$0);
38
- const active = props.active !== false;
39
- const facing = props.facing ?? "back";
40
- useImperativeHandle(props.ref, () => ({ native: host.current?.nativeViewProtected }), [], _h$1);
41
- const bindHost = useCallback((view) => {
42
- host.current = view;
43
- }, [], _h$2);
44
- useEffect(() => {
45
- const view = host.current;
46
- if (!view || !active) return;
47
- let disposed = false;
48
- let stopPreview;
49
- const fail = (message) => props.onError?.({ message });
50
- if (props.session) {
51
- if (props.facing !== void 0) {
52
- fail("camera session conflicts with facing");
53
- return;
54
- }
55
- try {
56
- const detach = attachSessionPreview(props.session, view, {
57
- onReady: () => {
58
- if (!disposed) props.onReady?.();
59
- },
60
- onError: (issue) => {
61
- if (!disposed) fail(issue.message);
62
- }
63
- });
64
- return () => {
65
- disposed = true;
66
- detach();
67
- };
68
- } catch (error) {
69
- fail(error?.message ?? "camera session error");
70
- return;
71
- }
72
- }
73
- if (!cameraHardwarePresent()) {
74
- fail("camera unsupported");
75
- return;
76
- }
77
- ensureCameraPermission().then(async (granted) => {
78
- if (disposed) return;
79
- if (!granted) {
80
- fail("camera permission denied");
81
- return;
82
- }
83
- try {
84
- stopPreview = await startCameraPreview(view, facing, () => {
85
- if (!disposed) props.onReady?.();
86
- });
87
- } catch (error) {
88
- if (!disposed) fail(error?.message ?? "camera error");
89
- }
90
- });
91
- return () => {
92
- disposed = true;
93
- stopPreview?.();
94
- };
95
- }, [
96
- active,
97
- facing,
98
- props.session
99
- ], _h$3);
100
- useEffect(() => {
101
- const view = host.current;
102
- if (!view) return;
103
- applyEscapeProps(view.nativeViewProtected, props);
104
- }, [props.ref, props.windows], _h$4);
105
- return universalValue(__octaneUniversalPlan0, [universalProps([
106
- [
107
- "set",
108
- "id",
109
- props.id
110
- ],
111
- [
112
- "set",
113
- "rows",
114
- "*"
115
- ],
116
- [
117
- "set",
118
- "columns",
119
- "*"
120
- ],
121
- [
122
- "set",
123
- "className",
124
- cx("vx-layers", "vx-cameraview", props.className)
125
- ],
126
- [
127
- "set",
128
- "style",
129
- {
130
- backgroundColor: "#000",
131
- ...props.style
132
- }
133
- ],
134
- ["spread", layoutChildProps(props)],
135
- [
136
- "set",
137
- "accessible",
138
- props.accessible
139
- ],
140
- [
141
- "set",
142
- "accessibilityLabel",
143
- props.accessibilityLabel
144
- ],
145
- [
146
- "set",
147
- "accessibilityRole",
148
- nativeAccessibilityRole(props.accessibilityRole)
149
- ],
150
- [
151
- "set",
152
- "accessibilityHint",
153
- props.accessibilityHint
154
- ],
155
- [
156
- "set",
157
- "accessibilityValue",
158
- props.accessibilityValue
159
- ],
160
- [
161
- "set",
162
- "accessibilityState",
163
- nativeAccessibilityState(props.accessibilityState)
164
- ],
165
- [
166
- "set",
167
- "accessibilityLiveRegion",
168
- props.accessibilityLiveRegion
169
- ]
170
- ]), bindHost]);
171
- }, { "module": "@nativescript-community/octane" });
172
- //#endregion
173
- export { CameraView };
@@ -1,45 +0,0 @@
1
- import { Application, isAndroid, isIOS } from "@nativescript/core";
2
- //#region src/camera-permission.mobile.ts
3
- var requestCode = 7719;
4
- function cameraHardwarePresent() {
5
- if (isIOS) return typeof globalThis.AVCaptureDevice !== "undefined";
6
- if (!isAndroid) return false;
7
- try {
8
- return (Application.android?.context ?? Application.android?.startActivity)?.getPackageManager()?.hasSystemFeature("android.hardware.camera.any") !== false;
9
- } catch {
10
- return true;
11
- }
12
- }
13
- async function ensureCameraPermission() {
14
- try {
15
- if (isIOS) {
16
- const av = globalThis.AVCaptureDevice;
17
- const mediaType = globalThis.AVMediaTypeVideo ?? "vide";
18
- const status = av?.authorizationStatusForMediaType?.(mediaType);
19
- if (status === 3) return true;
20
- if (status === 1 || status === 2) return false;
21
- return await new Promise((resolve) => av.requestAccessForMediaTypeCompletionHandler(mediaType, resolve));
22
- }
23
- if (isAndroid) {
24
- const permission = "android.permission.CAMERA";
25
- const activity = Application.android.foregroundActivity ?? Application.android.startActivity;
26
- if (activity?.checkSelfPermission?.(permission) === android.content.pm.PackageManager.PERMISSION_GRANTED) return true;
27
- if (!activity) return false;
28
- return await new Promise((resolve) => {
29
- const currentRequest = requestCode++;
30
- const onResult = (args) => {
31
- if (args.requestCode !== currentRequest) return;
32
- Application.android.off(Application.android.activityRequestPermissionsEvent, onResult);
33
- resolve(args.grantResults?.[0] === android.content.pm.PackageManager.PERMISSION_GRANTED);
34
- };
35
- Application.android.on(Application.android.activityRequestPermissionsEvent, onResult);
36
- activity.requestPermissions([permission], currentRequest);
37
- });
38
- }
39
- } catch {
40
- return false;
41
- }
42
- return false;
43
- }
44
- //#endregion
45
- export { cameraHardwarePresent, ensureCameraPermission };
@@ -1,43 +0,0 @@
1
- //#region src/camera-permission.windows.ts
2
- /** Windows camera-permission probe for preview-only `CameraView` callers.
3
- * Uses `AppCapability` when projected and falls back to
4
- * `DeviceAccessInformation`; both are non-prompting checks — only
5
- * `RequestAccessAsync` may show the system prompt. */
6
- var windows = () => globalThis;
7
- var toPromise = (op) => {
8
- const { NSWinRT } = windows();
9
- if (NSWinRT?.toPromise && op != null) return NSWinRT.toPromise(op);
10
- if (op?.done) return new Promise((resolve, reject) => {
11
- try {
12
- op.done(resolve, reject);
13
- } catch (cause) {
14
- reject(cause);
15
- }
16
- });
17
- return Promise.resolve(op);
18
- };
19
- function cameraHardwarePresent() {
20
- const { Windows, Microsoft } = windows();
21
- return !!(Windows?.Media?.Capture?.MediaCapture && Windows?.Devices?.Enumeration?.DeviceInformation && Microsoft?.UI?.Xaml?.Controls?.CaptureElement);
22
- }
23
- async function ensureCameraPermission() {
24
- try {
25
- const { Windows } = windows();
26
- const capability = Windows?.Security?.Authorization?.AppCapabilityAccess?.AppCapability?.Create?.("webcam");
27
- if (capability) {
28
- const status = capability.CheckAccess();
29
- if (status === 4) return true;
30
- if (status === 3) return await toPromise(capability.RequestAccessAsync()) === 4;
31
- return false;
32
- }
33
- const enumeration = Windows?.Devices?.Enumeration;
34
- const deviceClass = enumeration?.DeviceClass?.VideoCapture;
35
- const info = deviceClass === void 0 ? void 0 : enumeration?.DeviceAccessInformation?.CreateFromDeviceClass(deviceClass);
36
- if (info) return info.CurrentStatus !== 2 && info.CurrentStatus !== 3;
37
- } catch {
38
- return false;
39
- }
40
- return false;
41
- }
42
- //#endregion
43
- export { cameraHardwarePresent, ensureCameraPermission };
@@ -1,45 +0,0 @@
1
- //#region src/camera-session.ios.ts
2
- /** Attach an AVFoundation preview layer to a NativeScript UIView host. */
3
- function startCameraPreview(view, facing, onReady) {
4
- const av = globalThis;
5
- const mediaType = av.AVMediaTypeVideo ?? "vide";
6
- const desiredPosition = facing === "front" ? av.AVCaptureDevicePositionFront ?? 2 : av.AVCaptureDevicePositionBack ?? 1;
7
- const devices = av.AVCaptureDevice.devicesWithMediaType(mediaType);
8
- let device = null;
9
- for (let index = 0; index < devices.count; index++) {
10
- const candidate = devices.objectAtIndex(index);
11
- if (candidate.position === desiredPosition) {
12
- device = candidate;
13
- break;
14
- }
15
- }
16
- if (!device) throw new Error("camera unavailable");
17
- const session = av.AVCaptureSession.new();
18
- const input = av.AVCaptureDeviceInput.deviceInputWithDeviceError(device);
19
- if (!input || !session.canAddInput(input)) throw new Error("camera input unavailable");
20
- session.addInput(input);
21
- const layer = av.AVCaptureVideoPreviewLayer.layerWithSession(session);
22
- layer.videoGravity = "resizeAspectFill";
23
- const connection = layer.connection;
24
- if (connection) {
25
- connection.automaticallyAdjustsVideoMirroring = false;
26
- if (connection.isVideoMirroringSupported) connection.isVideoMirrored = facing === "front";
27
- }
28
- const nativeView = view.ios ?? view.nativeViewProtected;
29
- if (!nativeView?.layer) throw new Error("camera preview host unavailable");
30
- nativeView.layer.addSublayer(layer);
31
- const updateFrame = () => {
32
- layer.frame = nativeView.bounds;
33
- };
34
- view.on?.("layoutChanged", updateFrame);
35
- updateFrame();
36
- session.startRunning();
37
- onReady?.();
38
- return () => {
39
- view.off?.("layoutChanged", updateFrame);
40
- session.stopRunning();
41
- layer.removeFromSuperlayer();
42
- };
43
- }
44
- //#endregion
45
- export { startCameraPreview };