@capgo/capacitor-screen-orientation 8.3.1 → 8.4.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.
package/dist/plugin.js CHANGED
@@ -5,46 +5,191 @@ var capacitorScreenOrientation = (function (exports, core) {
5
5
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorScreenOrientationWeb()),
6
6
  });
7
7
 
8
- const FLAT_FOLD = { state: 'flat', isSeparating: false, posture: 'flat' };
8
+ const MEDIUM_WIDTH = 600;
9
+ const EXPANDED_WIDTH = 840;
10
+ const LARGE_WIDTH = 1200;
11
+ const EXTRA_LARGE_WIDTH = 1600;
12
+ const MEDIUM_HEIGHT = 480;
13
+ const EXPANDED_HEIGHT = 900;
14
+ function widthClassOf(width) {
15
+ if (width >= EXTRA_LARGE_WIDTH)
16
+ return 'extraLarge';
17
+ if (width >= LARGE_WIDTH)
18
+ return 'large';
19
+ if (width >= EXPANDED_WIDTH)
20
+ return 'expanded';
21
+ if (width >= MEDIUM_WIDTH)
22
+ return 'medium';
23
+ return 'compact';
24
+ }
25
+ function heightClassOf(height) {
26
+ if (height >= EXPANDED_HEIGHT)
27
+ return 'expanded';
28
+ if (height >= MEDIUM_HEIGHT)
29
+ return 'medium';
30
+ return 'compact';
31
+ }
9
32
  function sizeClassOf(width, height) {
10
- const widthClass = width >= 1600
11
- ? 'extraLarge'
12
- : width >= 1200
13
- ? 'large'
14
- : width >= 840
15
- ? 'expanded'
16
- : width >= 600
17
- ? 'medium'
18
- : 'compact';
19
- const heightClass = height >= 900 ? 'expanded' : height >= 480 ? 'medium' : 'compact';
20
33
  return {
21
- horizontal: width >= 600 ? 'regular' : 'compact',
22
- vertical: height >= 480 ? 'regular' : 'compact',
23
- widthClass,
24
- heightClass,
34
+ horizontal: width >= MEDIUM_WIDTH ? 'regular' : 'compact',
35
+ vertical: height >= MEDIUM_HEIGHT ? 'regular' : 'compact',
36
+ widthClass: widthClassOf(width),
37
+ heightClass: heightClassOf(height),
38
+ };
39
+ }
40
+
41
+ const EDGE_TOLERANCE = 1;
42
+ function splitViewport(fold, width, height) {
43
+ const whole = [{ x: 0, y: 0, width, height }];
44
+ const hinge = fold === null || fold === void 0 ? void 0 : fold.hingeBounds;
45
+ if (!(fold === null || fold === void 0 ? void 0 : fold.isSeparating) || !hinge)
46
+ return whole;
47
+ if (fold.hingeOrientation === 'vertical') {
48
+ const right = hinge.x + hinge.width;
49
+ const spansHeight = hinge.y <= EDGE_TOLERANCE && hinge.y + hinge.height >= height - EDGE_TOLERANCE;
50
+ if (!spansHeight || hinge.x <= 0 || right >= width)
51
+ return whole;
52
+ return [
53
+ { x: 0, y: 0, width: hinge.x, height },
54
+ { x: right, y: 0, width: width - right, height },
55
+ ];
56
+ }
57
+ const bottom = hinge.y + hinge.height;
58
+ const spansWidth = hinge.x <= EDGE_TOLERANCE && hinge.x + hinge.width >= width - EDGE_TOLERANCE;
59
+ if (!spansWidth || hinge.y <= 0 || bottom >= height)
60
+ return whole;
61
+ return [
62
+ { x: 0, y: 0, width, height: hinge.y },
63
+ { x: 0, y: bottom, width, height: height - bottom },
64
+ ];
65
+ }
66
+
67
+ const FLAT_FOLD = { state: 'flat', isSeparating: false, posture: 'flat' };
68
+ function webFoldApisAvailable() {
69
+ return (typeof window !== 'undefined' &&
70
+ typeof navigator !== 'undefined' &&
71
+ ('devicePosture' in navigator || 'viewport' in window));
72
+ }
73
+ function webDeviceFoldable() {
74
+ if (!webFoldApisAvailable()) {
75
+ return { foldable: false, supportsTabletop: false };
76
+ }
77
+ const fold = readWebFoldState(window.innerWidth, window.innerHeight);
78
+ const foldable = fold.state === 'half-opened' || (fold.isSeparating && fold.hingeBounds != null);
79
+ const supportsTabletop = foldable && (fold.posture === 'tabletop' || fold.hingeOrientation === 'horizontal');
80
+ return { foldable, supportsTabletop };
81
+ }
82
+ function readWebFoldState(width, height) {
83
+ var _a, _b;
84
+ if (typeof window === 'undefined' || typeof navigator === 'undefined') {
85
+ return FLAT_FOLD;
86
+ }
87
+ const fromSegments = foldFromViewportSegments(width, height);
88
+ if (fromSegments) {
89
+ return fromSegments;
90
+ }
91
+ const postureType = (_b = (_a = navigator.devicePosture) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'continuous';
92
+ if (postureType === 'folded') {
93
+ return { state: 'half-opened', isSeparating: false, posture: 'book' };
94
+ }
95
+ return FLAT_FOLD;
96
+ }
97
+ function foldFromViewportSegments(width, height) {
98
+ var _a;
99
+ const viewport = window.viewport;
100
+ if (!viewport) {
101
+ return null;
102
+ }
103
+ const rawSegments = viewport.segments;
104
+ if (!rawSegments || rawSegments.length !== 2) {
105
+ return null;
106
+ }
107
+ const rects = rawSegments.map((rect) => ({
108
+ x: rect.x,
109
+ y: rect.y,
110
+ width: rect.width,
111
+ height: rect.height,
112
+ }));
113
+ const folded = ((_a = navigator.devicePosture) === null || _a === void 0 ? void 0 : _a.type) === 'folded';
114
+ const state = folded ? 'half-opened' : 'flat';
115
+ const vertical = rects.every((r) => r.y <= 1 && r.height >= height - 1);
116
+ if (vertical) {
117
+ const sorted = [...rects].sort((a, b) => a.x - b.x);
118
+ const left = sorted[0];
119
+ const right = sorted[1];
120
+ const hingeX = left.x + left.width;
121
+ const hingeW = right.x - hingeX;
122
+ if (hingeW < 0) {
123
+ return null;
124
+ }
125
+ const hingeBounds = { x: hingeX, y: 0, width: hingeW, height };
126
+ return finalizeSegmentFold(state, folded, 'vertical', hingeBounds, width, height);
127
+ }
128
+ const horizontal = rects.every((r) => r.x <= 1 && r.width >= width - 1);
129
+ if (horizontal) {
130
+ const sorted = [...rects].sort((a, b) => a.y - b.y);
131
+ const top = sorted[0];
132
+ const bottom = sorted[1];
133
+ const hingeY = top.y + top.height;
134
+ const hingeH = bottom.y - hingeY;
135
+ if (hingeH < 0) {
136
+ return null;
137
+ }
138
+ const hingeBounds = { x: 0, y: hingeY, width, height: hingeH };
139
+ return finalizeSegmentFold(state, folded, 'horizontal', hingeBounds, width, height);
140
+ }
141
+ return null;
142
+ }
143
+ function finalizeSegmentFold(state, folded, hingeOrientation, hingeBounds, width, height) {
144
+ const fold = foldWithHinge(state, folded, hingeOrientation, hingeBounds, true);
145
+ if (splitViewport(fold, width, height).length !== 2) {
146
+ return null;
147
+ }
148
+ return fold;
149
+ }
150
+ function foldWithHinge(state, folded, hingeOrientation, hingeBounds, isSeparating) {
151
+ const posture = !folded ? 'flat' : hingeOrientation === 'horizontal' ? 'tabletop' : 'book';
152
+ const fold = {
153
+ state,
154
+ isSeparating,
155
+ posture,
156
+ hingeOrientation,
157
+ hingeBounds,
25
158
  };
159
+ const gap = hingeOrientation === 'vertical' ? hingeBounds.width : hingeBounds.height;
160
+ if (gap > 0) {
161
+ fold.occludedBounds = Object.assign({}, hingeBounds);
162
+ }
163
+ return fold;
26
164
  }
165
+ function foldStateKey(state) {
166
+ return JSON.stringify(state);
167
+ }
168
+
27
169
  class CapacitorScreenOrientationWeb extends core.WebPlugin {
28
170
  constructor() {
29
- var _a;
171
+ var _a, _b;
30
172
  super();
31
173
  this.pluginVersion = '1.0.0';
174
+ this.lastFoldKey = null;
32
175
  this.lastSizeClass = null;
33
176
  if ((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation) {
34
177
  window.screen.orientation.addEventListener('change', () => {
35
178
  this.notifyListeners('screenOrientationChange', {
36
179
  type: this.mapOrientationType(window.screen.orientation.type),
37
180
  });
181
+ this.notifyFoldIfChanged();
38
182
  });
39
183
  }
40
184
  window.addEventListener('resize', () => {
41
- const next = this.readSizeClass();
42
- const previous = JSON.stringify(this.lastSizeClass);
43
- if (previous === JSON.stringify(next))
44
- return;
45
- this.lastSizeClass = next;
46
- this.notifyListeners('sizeClassChange', next);
185
+ this.notifySizeClassIfChanged();
186
+ this.notifyFoldIfChanged();
47
187
  });
188
+ (_b = navigator.devicePosture) === null || _b === void 0 ? void 0 : _b.addEventListener('change', () => {
189
+ this.notifyFoldIfChanged();
190
+ });
191
+ this.lastSizeClass = this.readSizeClass();
192
+ this.lastFoldKey = foldStateKey(readWebFoldState(window.innerWidth, window.innerHeight));
48
193
  }
49
194
  async orientation() {
50
195
  var _a;
@@ -61,8 +206,6 @@ var capacitorScreenOrientation = (function (exports, core) {
61
206
  if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.lock)) {
62
207
  throw this.unavailable('Screen Orientation lock not available');
63
208
  }
64
- // bypassOrientationLock is only supported on iOS native platform
65
- // Silently ignore it on web
66
209
  try {
67
210
  await screenOrientation.lock(options.orientation);
68
211
  }
@@ -79,13 +222,10 @@ var capacitorScreenOrientation = (function (exports, core) {
79
222
  screenOrientation.unlock();
80
223
  }
81
224
  async startOrientationTracking(_options) {
82
- // Motion-based orientation tracking is only supported on iOS
83
- // Silently ignore on web
84
225
  console.warn('Motion-based orientation tracking is not available on web platform', _options);
85
226
  }
86
227
  async stopOrientationTracking() {
87
- // Motion-based orientation tracking is only supported on iOS
88
- // Silently ignore on web
228
+ // No-op on web
89
229
  }
90
230
  async isOrientationLocked() {
91
231
  const orientationResult = await this.orientation();
@@ -95,10 +235,10 @@ var capacitorScreenOrientation = (function (exports, core) {
95
235
  };
96
236
  }
97
237
  async isDeviceFoldable() {
98
- return { foldable: false, supportsTabletop: false };
238
+ return webDeviceFoldable();
99
239
  }
100
240
  async getFoldState() {
101
- return FLAT_FOLD;
241
+ return readWebFoldState(window.innerWidth, window.innerHeight);
102
242
  }
103
243
  async getHingeAngle() {
104
244
  return { angle: null, status: null };
@@ -121,6 +261,23 @@ var capacitorScreenOrientation = (function (exports, core) {
121
261
  readSizeClass() {
122
262
  return sizeClassOf(window.innerWidth, window.innerHeight);
123
263
  }
264
+ notifySizeClassIfChanged() {
265
+ const next = this.readSizeClass();
266
+ const previous = JSON.stringify(this.lastSizeClass);
267
+ if (previous === JSON.stringify(next))
268
+ return;
269
+ this.lastSizeClass = next;
270
+ this.notifyListeners('sizeClassChange', next);
271
+ }
272
+ notifyFoldIfChanged() {
273
+ const next = readWebFoldState(window.innerWidth, window.innerHeight);
274
+ const key = foldStateKey(next);
275
+ if (key === this.lastFoldKey) {
276
+ return;
277
+ }
278
+ this.lastFoldKey = key;
279
+ this.notifyListeners('foldStateChange', next);
280
+ }
124
281
  mapOrientationType(type) {
125
282
  if (type.includes('portrait-primary') || type === 'portrait-primary') {
126
283
  return 'portrait-primary';
@@ -134,7 +291,7 @@ var capacitorScreenOrientation = (function (exports, core) {
134
291
  if (type.includes('landscape-secondary') || type === 'landscape-secondary') {
135
292
  return 'landscape-secondary';
136
293
  }
137
- return 'portrait-primary'; // default fallback
294
+ return 'portrait-primary';
138
295
  }
139
296
  }
140
297
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenOrientation = registerPlugin('CapacitorScreenOrientation', {\n web: () => import('./web').then((m) => new m.CapacitorScreenOrientationWeb()),\n});\nexport * from './definitions';\nexport { ScreenOrientation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nconst FLAT_FOLD = { state: 'flat', isSeparating: false, posture: 'flat' };\nexport function sizeClassOf(width, height) {\n const widthClass = width >= 1600\n ? 'extraLarge'\n : width >= 1200\n ? 'large'\n : width >= 840\n ? 'expanded'\n : width >= 600\n ? 'medium'\n : 'compact';\n const heightClass = height >= 900 ? 'expanded' : height >= 480 ? 'medium' : 'compact';\n return {\n horizontal: width >= 600 ? 'regular' : 'compact',\n vertical: height >= 480 ? 'regular' : 'compact',\n widthClass,\n heightClass,\n };\n}\nexport class CapacitorScreenOrientationWeb extends WebPlugin {\n constructor() {\n var _a;\n super();\n this.pluginVersion = '1.0.0';\n this.lastSizeClass = null;\n if ((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation) {\n window.screen.orientation.addEventListener('change', () => {\n this.notifyListeners('screenOrientationChange', {\n type: this.mapOrientationType(window.screen.orientation.type),\n });\n });\n }\n window.addEventListener('resize', () => {\n const next = this.readSizeClass();\n const previous = JSON.stringify(this.lastSizeClass);\n if (previous === JSON.stringify(next))\n return;\n this.lastSizeClass = next;\n this.notifyListeners('sizeClassChange', next);\n });\n }\n async orientation() {\n var _a;\n if (!((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation)) {\n throw this.unavailable('Screen Orientation API not available');\n }\n return {\n type: this.mapOrientationType(window.screen.orientation.type),\n };\n }\n async lock(options) {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.lock)) {\n throw this.unavailable('Screen Orientation lock not available');\n }\n // bypassOrientationLock is only supported on iOS native platform\n // Silently ignore it on web\n try {\n await screenOrientation.lock(options.orientation);\n }\n catch (error) {\n throw new Error(`Failed to lock orientation: ${error}`);\n }\n }\n async unlock() {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.unlock)) {\n throw this.unavailable('Screen Orientation unlock not available');\n }\n screenOrientation.unlock();\n }\n async startOrientationTracking(_options) {\n // Motion-based orientation tracking is only supported on iOS\n // Silently ignore on web\n console.warn('Motion-based orientation tracking is not available on web platform', _options);\n }\n async stopOrientationTracking() {\n // Motion-based orientation tracking is only supported on iOS\n // Silently ignore on web\n }\n async isOrientationLocked() {\n const orientationResult = await this.orientation();\n return {\n locked: false,\n uiOrientation: orientationResult.type,\n };\n }\n async isDeviceFoldable() {\n return { foldable: false, supportsTabletop: false };\n }\n async getFoldState() {\n return FLAT_FOLD;\n }\n async getHingeAngle() {\n return { angle: null, status: null };\n }\n async getReservedRegions() {\n return { regions: [] };\n }\n async getBarPlacement() {\n return { verticalBarEdge: null, inset: 0 };\n }\n async setVerticalBarBehavior() {\n return { applied: false };\n }\n async getSizeClass() {\n return this.readSizeClass();\n }\n async getPluginVersion() {\n return { version: this.pluginVersion };\n }\n readSizeClass() {\n return sizeClassOf(window.innerWidth, window.innerHeight);\n }\n mapOrientationType(type) {\n if (type.includes('portrait-primary') || type === 'portrait-primary') {\n return 'portrait-primary';\n }\n if (type.includes('portrait-secondary') || type === 'portrait-secondary') {\n return 'portrait-secondary';\n }\n if (type.includes('landscape-primary') || type === 'landscape-primary') {\n return 'landscape-primary';\n }\n if (type.includes('landscape-secondary') || type === 'landscape-secondary') {\n return 'landscape-secondary';\n }\n return 'portrait-primary'; // default fallback\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/size-class.js","esm/segments.js","esm/web-fold.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst ScreenOrientation = registerPlugin('CapacitorScreenOrientation', {\n web: () => import('./web').then((m) => new m.CapacitorScreenOrientationWeb()),\n});\nexport * from './definitions';\nexport { ScreenOrientation };\n//# sourceMappingURL=index.js.map","const MEDIUM_WIDTH = 600;\nconst EXPANDED_WIDTH = 840;\nconst LARGE_WIDTH = 1200;\nconst EXTRA_LARGE_WIDTH = 1600;\nconst MEDIUM_HEIGHT = 480;\nconst EXPANDED_HEIGHT = 900;\nfunction widthClassOf(width) {\n if (width >= EXTRA_LARGE_WIDTH)\n return 'extraLarge';\n if (width >= LARGE_WIDTH)\n return 'large';\n if (width >= EXPANDED_WIDTH)\n return 'expanded';\n if (width >= MEDIUM_WIDTH)\n return 'medium';\n return 'compact';\n}\nfunction heightClassOf(height) {\n if (height >= EXPANDED_HEIGHT)\n return 'expanded';\n if (height >= MEDIUM_HEIGHT)\n return 'medium';\n return 'compact';\n}\nexport function sizeClassOf(width, height) {\n return {\n horizontal: width >= MEDIUM_WIDTH ? 'regular' : 'compact',\n vertical: height >= MEDIUM_HEIGHT ? 'regular' : 'compact',\n widthClass: widthClassOf(width),\n heightClass: heightClassOf(height),\n };\n}\n//# sourceMappingURL=size-class.js.map","const EDGE_TOLERANCE = 1;\nexport function splitViewport(fold, width, height) {\n const whole = [{ x: 0, y: 0, width, height }];\n const hinge = fold === null || fold === void 0 ? void 0 : fold.hingeBounds;\n if (!(fold === null || fold === void 0 ? void 0 : fold.isSeparating) || !hinge)\n return whole;\n if (fold.hingeOrientation === 'vertical') {\n const right = hinge.x + hinge.width;\n const spansHeight = hinge.y <= EDGE_TOLERANCE && hinge.y + hinge.height >= height - EDGE_TOLERANCE;\n if (!spansHeight || hinge.x <= 0 || right >= width)\n return whole;\n return [\n { x: 0, y: 0, width: hinge.x, height },\n { x: right, y: 0, width: width - right, height },\n ];\n }\n const bottom = hinge.y + hinge.height;\n const spansWidth = hinge.x <= EDGE_TOLERANCE && hinge.x + hinge.width >= width - EDGE_TOLERANCE;\n if (!spansWidth || hinge.y <= 0 || bottom >= height)\n return whole;\n return [\n { x: 0, y: 0, width, height: hinge.y },\n { x: 0, y: bottom, width, height: height - bottom },\n ];\n}\n//# sourceMappingURL=segments.js.map","import { splitViewport } from './segments';\nconst FLAT_FOLD = { state: 'flat', isSeparating: false, posture: 'flat' };\nexport function webFoldApisAvailable() {\n return (typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n ('devicePosture' in navigator || 'viewport' in window));\n}\nexport function webDeviceFoldable() {\n if (!webFoldApisAvailable()) {\n return { foldable: false, supportsTabletop: false };\n }\n const fold = readWebFoldState(window.innerWidth, window.innerHeight);\n const foldable = fold.state === 'half-opened' || (fold.isSeparating && fold.hingeBounds != null);\n const supportsTabletop = foldable && (fold.posture === 'tabletop' || fold.hingeOrientation === 'horizontal');\n return { foldable, supportsTabletop };\n}\nexport function readWebFoldState(width, height) {\n var _a, _b;\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return FLAT_FOLD;\n }\n const fromSegments = foldFromViewportSegments(width, height);\n if (fromSegments) {\n return fromSegments;\n }\n const postureType = (_b = (_a = navigator.devicePosture) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'continuous';\n if (postureType === 'folded') {\n return { state: 'half-opened', isSeparating: false, posture: 'book' };\n }\n return FLAT_FOLD;\n}\nfunction foldFromViewportSegments(width, height) {\n var _a;\n const viewport = window.viewport;\n if (!viewport) {\n return null;\n }\n const rawSegments = viewport.segments;\n if (!rawSegments || rawSegments.length !== 2) {\n return null;\n }\n const rects = rawSegments.map((rect) => ({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n }));\n const folded = ((_a = navigator.devicePosture) === null || _a === void 0 ? void 0 : _a.type) === 'folded';\n const state = folded ? 'half-opened' : 'flat';\n const vertical = rects.every((r) => r.y <= 1 && r.height >= height - 1);\n if (vertical) {\n const sorted = [...rects].sort((a, b) => a.x - b.x);\n const left = sorted[0];\n const right = sorted[1];\n const hingeX = left.x + left.width;\n const hingeW = right.x - hingeX;\n if (hingeW < 0) {\n return null;\n }\n const hingeBounds = { x: hingeX, y: 0, width: hingeW, height };\n return finalizeSegmentFold(state, folded, 'vertical', hingeBounds, width, height);\n }\n const horizontal = rects.every((r) => r.x <= 1 && r.width >= width - 1);\n if (horizontal) {\n const sorted = [...rects].sort((a, b) => a.y - b.y);\n const top = sorted[0];\n const bottom = sorted[1];\n const hingeY = top.y + top.height;\n const hingeH = bottom.y - hingeY;\n if (hingeH < 0) {\n return null;\n }\n const hingeBounds = { x: 0, y: hingeY, width, height: hingeH };\n return finalizeSegmentFold(state, folded, 'horizontal', hingeBounds, width, height);\n }\n return null;\n}\nfunction finalizeSegmentFold(state, folded, hingeOrientation, hingeBounds, width, height) {\n const fold = foldWithHinge(state, folded, hingeOrientation, hingeBounds, true);\n if (splitViewport(fold, width, height).length !== 2) {\n return null;\n }\n return fold;\n}\nfunction foldWithHinge(state, folded, hingeOrientation, hingeBounds, isSeparating) {\n const posture = !folded ? 'flat' : hingeOrientation === 'horizontal' ? 'tabletop' : 'book';\n const fold = {\n state,\n isSeparating,\n posture,\n hingeOrientation,\n hingeBounds,\n };\n const gap = hingeOrientation === 'vertical' ? hingeBounds.width : hingeBounds.height;\n if (gap > 0) {\n fold.occludedBounds = Object.assign({}, hingeBounds);\n }\n return fold;\n}\nexport function foldStateKey(state) {\n return JSON.stringify(state);\n}\n//# sourceMappingURL=web-fold.js.map","import { WebPlugin } from '@capacitor/core';\nimport { sizeClassOf } from './size-class';\nimport { foldStateKey, readWebFoldState, webDeviceFoldable } from './web-fold';\nexport { sizeClassOf } from './size-class';\nexport class CapacitorScreenOrientationWeb extends WebPlugin {\n constructor() {\n var _a, _b;\n super();\n this.pluginVersion = '1.0.0';\n this.lastFoldKey = null;\n this.lastSizeClass = null;\n if ((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation) {\n window.screen.orientation.addEventListener('change', () => {\n this.notifyListeners('screenOrientationChange', {\n type: this.mapOrientationType(window.screen.orientation.type),\n });\n this.notifyFoldIfChanged();\n });\n }\n window.addEventListener('resize', () => {\n this.notifySizeClassIfChanged();\n this.notifyFoldIfChanged();\n });\n (_b = navigator.devicePosture) === null || _b === void 0 ? void 0 : _b.addEventListener('change', () => {\n this.notifyFoldIfChanged();\n });\n this.lastSizeClass = this.readSizeClass();\n this.lastFoldKey = foldStateKey(readWebFoldState(window.innerWidth, window.innerHeight));\n }\n async orientation() {\n var _a;\n if (!((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation)) {\n throw this.unavailable('Screen Orientation API not available');\n }\n return {\n type: this.mapOrientationType(window.screen.orientation.type),\n };\n }\n async lock(options) {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.lock)) {\n throw this.unavailable('Screen Orientation lock not available');\n }\n try {\n await screenOrientation.lock(options.orientation);\n }\n catch (error) {\n throw new Error(`Failed to lock orientation: ${error}`);\n }\n }\n async unlock() {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.unlock)) {\n throw this.unavailable('Screen Orientation unlock not available');\n }\n screenOrientation.unlock();\n }\n async startOrientationTracking(_options) {\n console.warn('Motion-based orientation tracking is not available on web platform', _options);\n }\n async stopOrientationTracking() {\n // No-op on web\n }\n async isOrientationLocked() {\n const orientationResult = await this.orientation();\n return {\n locked: false,\n uiOrientation: orientationResult.type,\n };\n }\n async isDeviceFoldable() {\n return webDeviceFoldable();\n }\n async getFoldState() {\n return readWebFoldState(window.innerWidth, window.innerHeight);\n }\n async getHingeAngle() {\n return { angle: null, status: null };\n }\n async getReservedRegions() {\n return { regions: [] };\n }\n async getBarPlacement() {\n return { verticalBarEdge: null, inset: 0 };\n }\n async setVerticalBarBehavior() {\n return { applied: false };\n }\n async getSizeClass() {\n return this.readSizeClass();\n }\n async getPluginVersion() {\n return { version: this.pluginVersion };\n }\n readSizeClass() {\n return sizeClassOf(window.innerWidth, window.innerHeight);\n }\n notifySizeClassIfChanged() {\n const next = this.readSizeClass();\n const previous = JSON.stringify(this.lastSizeClass);\n if (previous === JSON.stringify(next))\n return;\n this.lastSizeClass = next;\n this.notifyListeners('sizeClassChange', next);\n }\n notifyFoldIfChanged() {\n const next = readWebFoldState(window.innerWidth, window.innerHeight);\n const key = foldStateKey(next);\n if (key === this.lastFoldKey) {\n return;\n }\n this.lastFoldKey = key;\n this.notifyListeners('foldStateChange', next);\n }\n mapOrientationType(type) {\n if (type.includes('portrait-primary') || type === 'portrait-primary') {\n return 'portrait-primary';\n }\n if (type.includes('portrait-secondary') || type === 'portrait-secondary') {\n return 'portrait-secondary';\n }\n if (type.includes('landscape-primary') || type === 'landscape-primary') {\n return 'landscape-primary';\n }\n if (type.includes('landscape-secondary') || type === 'landscape-secondary') {\n return 'landscape-secondary';\n }\n return 'portrait-primary';\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
@@ -11,7 +11,7 @@ import UIKit
11
11
  */
12
12
  @objc(CapacitorScreenOrientationPlugin)
13
13
  public class CapacitorScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
14
- private let pluginVersion: String = "8.3.1"
14
+ private let pluginVersion: String = "8.4.1"
15
15
  public let identifier = "CapacitorScreenOrientationPlugin"
16
16
  public let jsName = "CapacitorScreenOrientation"
17
17
  public let pluginMethods: [CAPPluginMethod] = [
@@ -181,8 +181,9 @@ public class CapacitorScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
181
181
  print("Screen orientation geometry update warning: \(error.localizedDescription)")
182
182
  }
183
183
  } else {
184
- let orientationValue = self.preferredInterfaceOrientationValue(from: orientationString)
185
- UIDevice.current.setValue(orientationValue, forKey: "orientation")
184
+ // iOS 15 has no public API to force a rotation (requestGeometryUpdate is iOS 16+).
185
+ // supportedOrientations was set above, so the UI rotates into the locked mask as soon as
186
+ // the device orientation allows it; the lock is not guaranteed to rotate the UI immediately.
186
187
  UINavigationController.attemptRotationToDeviceOrientation()
187
188
  }
188
189
 
@@ -464,21 +465,6 @@ public class CapacitorScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
464
465
  }
465
466
  }
466
467
 
467
- private func preferredInterfaceOrientationValue(from orientationString: String) -> Int {
468
- switch orientationString {
469
- case "any":
470
- return UIInterfaceOrientation.unknown.rawValue
471
- case "landscape", "landscape-primary":
472
- return UIInterfaceOrientation.landscapeLeft.rawValue
473
- case "landscape-secondary":
474
- return UIInterfaceOrientation.landscapeRight.rawValue
475
- case "portrait-secondary":
476
- return UIInterfaceOrientation.portraitUpsideDown.rawValue
477
- default:
478
- return UIInterfaceOrientation.portrait.rawValue
479
- }
480
- }
481
-
482
468
  private func orientationValues(from mask: UIInterfaceOrientationMask) -> [Int] {
483
469
  var values: [Int] = []
484
470
 
@@ -1,32 +1,34 @@
1
1
  import Foundation
2
- import ObjectiveC
3
2
  import UIKit
4
3
 
5
- /// iPhone Duo fold, hinge, and bar placement.
6
- /// The types landed in UIKit 9127.0.85 (iOS 27.1). This calls them through the
7
- /// runtime so a build with the 27.0 SDK still works on the iPhone Duo simulator.
4
+ /// iPhone Duo fold, hinge, and bar placement (UIKit APIs in iOS 27.1).
5
+ #if canImport(UIKit, _version: 9127.0.85)
6
+ private let duoFoldSDKCompiled = true
7
+ #else
8
+ private let duoFoldSDKCompiled = false
9
+ #endif
10
+
8
11
  final class IPhoneDuoFold: NSObject {
9
12
  static let shared = IPhoneDuoFold()
10
13
 
11
14
  private let available: Bool
12
- private let divisionKind: AnyObject?
13
- private let occlusionKind: AnyObject?
14
15
  private var hingeStatus: Int?
15
16
  private var hingeRadians: Double?
16
- private var interaction: AnyObject?
17
17
  private var onChange: (() -> Void)?
18
18
 
19
+ #if canImport(UIKit, _version: 9127.0.85)
20
+ private var interaction: UIHingeInteraction?
21
+ #endif
22
+
19
23
  private override init() {
20
- let viewResponds = UIView.instancesRespond(to: NSSelectorFromString("reservedRegionsOfKind:options:"))
21
- let kindClass: AnyClass? = NSClassFromString("UIViewReservedRegionKind")
22
- let interactionClass: AnyClass? = NSClassFromString("UIHingeInteraction")
23
- available = viewResponds && kindClass != nil && interactionClass != nil
24
- if let kindClass = kindClass {
25
- divisionKind = IPhoneDuoFold.classObject(kindClass, "divisionRegionKind")
26
- occlusionKind = IPhoneDuoFold.classObject(kindClass, "occlusionRegionKind")
24
+ if duoFoldSDKCompiled {
25
+ if #available(iOS 27.1, *) {
26
+ available = true
27
+ } else {
28
+ available = false
29
+ }
27
30
  } else {
28
- divisionKind = nil
29
- occlusionKind = nil
31
+ available = false
30
32
  }
31
33
  super.init()
32
34
  }
@@ -35,7 +37,12 @@ final class IPhoneDuoFold: NSObject {
35
37
  guard available else { return false }
36
38
  if let status = hingeStatus, status != 0 { return true }
37
39
  guard let view = view else { return false }
38
- return !regions(kind: divisionKind, in: view, options: 1).isEmpty
40
+ #if canImport(UIKit, _version: 9127.0.85)
41
+ if #available(iOS 27.1, *) {
42
+ return !regions(kind: .division, in: view).isEmpty
43
+ }
44
+ #endif
45
+ return false
39
46
  }
40
47
 
41
48
  func foldState(in view: UIView?) -> [String: Any] {
@@ -138,21 +145,26 @@ final class IPhoneDuoFold: NSObject {
138
145
  }
139
146
 
140
147
  func observe(in view: UIView, onChange: @escaping () -> Void) {
141
- guard available, interaction == nil, let interactionClass: AnyClass = NSClassFromString("UIHingeInteraction") else { return }
148
+ guard available else { return }
149
+ #if canImport(UIKit, _version: 9127.0.85)
150
+ guard interaction == nil else { return }
151
+ guard #available(iOS 27.1, *) else { return }
142
152
  self.onChange = onChange
143
- let block: @convention(block) (AnyObject, AnyObject) -> Void = { [weak self] _, update in
144
- self?.store(update)
145
- self?.onChange?()
153
+ let interaction = UIHingeInteraction { [weak self] _, update in
154
+ guard let self else { return }
155
+ if let hinge = update.hinge {
156
+ self.hingeStatus = self.statusCode(hinge.status)
157
+ self.hingeRadians = hinge.angle
158
+ } else {
159
+ // UIKit sends a nil hinge when the interaction leaves a hierarchy that provides hinge updates.
160
+ self.hingeStatus = nil
161
+ self.hingeRadians = nil
162
+ }
163
+ self.onChange?()
146
164
  }
147
- let sel = NSSelectorFromString("initWithUpdateHandler:")
148
- typealias InitFn = @convention(c) (AnyObject, Selector, AnyObject) -> AnyObject?
149
- let allocated = interactionClass.alloc()
150
- guard let initFn = class_getMethodImplementation(interactionClass, sel) else { return }
151
- let interaction = unsafeBitCast(initFn, to: InitFn.self)(allocated, sel, block as AnyObject)
152
165
  self.interaction = interaction
153
- if let interaction = interaction {
154
- view.perform(NSSelectorFromString("addInteraction:"), with: interaction)
155
- }
166
+ view.addInteraction(interaction)
167
+ #endif
156
168
  }
157
169
 
158
170
  private var hingeDegrees: Double? {
@@ -160,33 +172,57 @@ final class IPhoneDuoFold: NSObject {
160
172
  return radians * 180 / .pi
161
173
  }
162
174
 
163
- private func store(_ update: AnyObject) {
164
- guard let hinge = object(update, "hinge") else { return }
165
- hingeStatus = integer(hinge, "status")
166
- hingeRadians = double(hinge, "angle")
175
+ private func allRegions(in view: UIView) -> [Region] {
176
+ #if canImport(UIKit, _version: 9127.0.85)
177
+ if #available(iOS 27.1, *) {
178
+ return regions(kind: .division, in: view) + regions(kind: .occlusion, in: view)
179
+ }
180
+ #endif
181
+ return []
182
+ }
183
+
184
+ #if canImport(UIKit, _version: 9127.0.85)
185
+ @available(iOS 27.1, *)
186
+ private func regions(kind: UIView.ReservedRegion.Kind, in view: UIView) -> [Region] {
187
+ let queryOptions: UIView.ReservedRegion.QueryOptions = .includeInactive
188
+ return view.reservedRegions(kind: kind, options: queryOptions).map { region in
189
+ Region(
190
+ kind: regionKindName(region.kind),
191
+ frame: region.frame,
192
+ margins: region.margins,
193
+ active: region.isActive
194
+ )
195
+ }
167
196
  }
168
197
 
169
- private func allRegions(in view: UIView) -> [Region] {
170
- regions(kind: divisionKind, in: view, options: 1) + regions(kind: occlusionKind, in: view, options: 1)
198
+ @available(iOS 27.1, *)
199
+ private func regionKindName(_ kind: UIView.ReservedRegion.Kind) -> String {
200
+ switch kind {
201
+ case .occlusion:
202
+ return "occlusion"
203
+ case .division:
204
+ return "division"
205
+ default:
206
+ return "division"
207
+ }
171
208
  }
172
209
 
173
- private func regions(kind: AnyObject?, in view: UIView, options: UInt) -> [Region] {
174
- guard let kind = kind else { return [] }
175
- let sel = NSSelectorFromString("reservedRegionsOfKind:options:")
176
- typealias Fn = @convention(c) (AnyObject, Selector, AnyObject, UInt) -> NSArray?
177
- let list = unsafeBitCast(view.method(for: sel), to: Fn.self)(view, sel, kind, options) ?? []
178
- return list.compactMap { item in
179
- guard let region = item as? AnyObject else { return nil }
180
- let kindObject = object(region, "kind")
181
- let name = kindObject?.description.contains("occlusion") == true ? "occlusion" : "division"
182
- return Region(
183
- kind: name,
184
- frame: rect(region, "frame"),
185
- margins: insets(region, "margins"),
186
- active: bool(region, "isActive")
187
- )
210
+ @available(iOS 27.1, *)
211
+ private func statusCode(_ status: UIHinge.Status) -> Int {
212
+ switch status {
213
+ case .closed:
214
+ return 1
215
+ case .partiallyOpen:
216
+ return 2
217
+ case .fullyOpen:
218
+ return 3
219
+ case .unknown:
220
+ return 0
221
+ @unknown default:
222
+ return 0
188
223
  }
189
224
  }
225
+ #endif
190
226
 
191
227
  private func statusName(_ status: Int?) -> String? {
192
228
  switch status {
@@ -212,47 +248,4 @@ final class IPhoneDuoFold: NSObject {
212
248
  "height": Int(rect.size.height.rounded())
213
249
  ]
214
250
  }
215
-
216
- private static func classObject(_ cls: AnyClass, _ name: String) -> AnyObject? {
217
- let sel = NSSelectorFromString(name)
218
- typealias Fn = @convention(c) (AnyClass, Selector) -> AnyObject?
219
- guard let imp = class_getMethodImplementation(object_getClass(cls), sel) else { return nil }
220
- return unsafeBitCast(imp, to: Fn.self)(cls, sel)
221
- }
222
-
223
- private func object(_ target: AnyObject, _ name: String) -> AnyObject? {
224
- let sel = NSSelectorFromString(name)
225
- typealias Fn = @convention(c) (AnyObject, Selector) -> AnyObject?
226
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
227
- }
228
-
229
- private func integer(_ target: AnyObject, _ name: String) -> Int {
230
- let sel = NSSelectorFromString(name)
231
- typealias Fn = @convention(c) (AnyObject, Selector) -> Int
232
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
233
- }
234
-
235
- private func double(_ target: AnyObject, _ name: String) -> Double {
236
- let sel = NSSelectorFromString(name)
237
- typealias Fn = @convention(c) (AnyObject, Selector) -> Double
238
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
239
- }
240
-
241
- private func bool(_ target: AnyObject, _ name: String) -> Bool {
242
- let sel = NSSelectorFromString(name)
243
- typealias Fn = @convention(c) (AnyObject, Selector) -> Bool
244
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
245
- }
246
-
247
- private func rect(_ target: AnyObject, _ name: String) -> CGRect {
248
- let sel = NSSelectorFromString(name)
249
- typealias Fn = @convention(c) (AnyObject, Selector) -> CGRect
250
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
251
- }
252
-
253
- private func insets(_ target: AnyObject, _ name: String) -> UIEdgeInsets {
254
- let sel = NSSelectorFromString(name)
255
- typealias Fn = @convention(c) (AnyObject, Selector) -> UIEdgeInsets
256
- return unsafeBitCast(target.method(for: sel), to: Fn.self)(target, sel)
257
- }
258
251
  }