@symbiote-native/screen-orientation 0.0.1 → 0.2.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 +4 -2
- package/build/angular/index.d.ts +1 -1
- package/build/angular/index.js +2 -2
- package/build/angular/services/screen-orientation.service/index.js +1 -1
- package/build/core/index.js +2 -2
- package/build/core/screen-orientation.js +9 -2
- package/build/react/hooks/use-screen-orientation/index.js +1 -1
- package/build/react/index.d.ts +1 -1
- package/build/react/index.js +2 -2
- package/build/svelte/index.d.ts +2 -0
- package/build/svelte/index.js +5 -0
- package/build/svelte/runes/use-screen-orientation.svelte.d.ts +4 -0
- package/build/svelte/runes/use-screen-orientation.svelte.js +35 -0
- package/build/vue/composables/use-screen-orientation/index.js +1 -1
- package/build/vue/index.d.ts +1 -1
- package/build/vue/index.js +2 -2
- package/build-ngc/angular/index.d.ts +1 -1
- package/build-ngc/angular/index.js +1 -1
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/services/screen-orientation.service/index.js +3 -3
- package/build-ngc/core/screen-orientation.js +7 -0
- package/build-ngc/core/screen-orientation.js.map +1 -1
- package/package.json +30 -13
- package/src/angular/index.ts +1 -23
- package/src/core/screen-orientation.ts +7 -0
- package/src/react/index.ts +1 -23
- package/src/svelte/index.ts +6 -0
- package/src/svelte/runes/use-screen-orientation.svelte.ts +48 -0
- package/src/svelte/svelte-ambient.d.ts +6 -0
- package/src/vue/index.ts +1 -23
- package/src/angular/services/screen-orientation.service/screen-orientation.service.test.ts +0 -101
- package/src/core/screen-orientation.test.ts +0 -307
- package/src/react/hooks/use-screen-orientation/use-screen-orientation.test.tsx +0 -93
- package/src/vue/composables/use-screen-orientation/use-screen-orientation.test.ts +0 -98
package/README.md
CHANGED
|
@@ -40,8 +40,8 @@ with zero further changes:
|
|
|
40
40
|
|
|
41
41
|
Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
|
|
42
42
|
peer-dependency exclusion list — live in the `symbiote-expo-native-module` skill. Reference
|
|
43
|
-
implementation:
|
|
44
|
-
|
|
43
|
+
implementation: `examples/expo-react/ios/Podfile` and
|
|
44
|
+
`examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt`.
|
|
45
45
|
|
|
46
46
|
No platform permission string is needed for screen-orientation's surface — locking and reading the
|
|
47
47
|
current orientation read/write system state with no runtime permission prompt on either platform.
|
|
@@ -132,6 +132,8 @@ getOrientationLockAsync(): Promise<OrientationLock> // the current loc
|
|
|
132
132
|
getPlatformOrientationLockAsync(): Promise<PlatformOrientationInfo>
|
|
133
133
|
supportsOrientationLockAsync(orientationLock): Promise<boolean>
|
|
134
134
|
addOrientationChangeListener(listener): EventSubscription // fires whenever orientation/lock changes
|
|
135
|
+
removeOrientationChangeListener(subscription): void // removes one subscription
|
|
136
|
+
removeOrientationChangeListeners(): void // removes every subscription at once
|
|
135
137
|
```
|
|
136
138
|
|
|
137
139
|
Plus `Orientation` (enum: `UNKNOWN`/`PORTRAIT_UP`/`PORTRAIT_DOWN`/`LANDSCAPE_LEFT`/
|
package/build/angular/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { ScreenOrientationService } from './services/screen-orientation.service';
|
|
2
|
-
export
|
|
2
|
+
export * from '../core';
|
package/build/angular/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// ScreenOrientationService is the Angular-only lifecycle half; the free functions and event
|
|
2
2
|
// subscription plumbing all live in core, shared with React/Vue.
|
|
3
|
-
export { ScreenOrientationService } from './services/screen-orientation.service';
|
|
4
|
-
export
|
|
3
|
+
export { ScreenOrientationService } from './services/screen-orientation.service/index.js';
|
|
4
|
+
export * from '../core/index.js';
|
|
@@ -33,7 +33,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
35
|
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
|
|
36
|
-
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core';
|
|
36
|
+
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core/index.js';
|
|
37
37
|
// Angular twin of React's `useScreenOrientation` hook and Vue's `useScreenOrientation`
|
|
38
38
|
// composable.
|
|
39
39
|
//
|
package/build/core/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { lockAsync, lockPlatformAsync, unlockAsync, getOrientationAsync, getOrientationLockAsync, getPlatformOrientationLockAsync, supportsOrientationLockAsync, addOrientationChangeListener, removeOrientationChangeListeners, removeOrientationChangeListener, } from './screen-orientation';
|
|
2
|
-
export { Orientation, OrientationLock, SizeClassIOS, WebOrientationLock, WebOrientation, } from './types';
|
|
1
|
+
export { lockAsync, lockPlatformAsync, unlockAsync, getOrientationAsync, getOrientationLockAsync, getPlatformOrientationLockAsync, supportsOrientationLockAsync, addOrientationChangeListener, removeOrientationChangeListeners, removeOrientationChangeListener, } from './screen-orientation.js';
|
|
2
|
+
export { Orientation, OrientationLock, SizeClassIOS, WebOrientationLock, WebOrientation, } from './types.js';
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// native method is absent — same convention as packages/network/src/core/network.ts.
|
|
4
4
|
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
5
5
|
import { Dimensions } from 'react-native';
|
|
6
|
-
import { expoScreenOrientation } from './native-module';
|
|
7
|
-
import { Orientation, OrientationLock, WebOrientationLock, } from './types';
|
|
6
|
+
import { expoScreenOrientation } from './native-module.js';
|
|
7
|
+
import { Orientation, OrientationLock, WebOrientationLock, } from './types.js';
|
|
8
8
|
const NATIVE_MODULE_NAME = 'ScreenOrientation';
|
|
9
9
|
let _orientationChangeSubscribers = [];
|
|
10
10
|
let _lastOrientationLock = OrientationLock.UNKNOWN;
|
|
@@ -23,6 +23,13 @@ export async function lockAsync(orientationLock) {
|
|
|
23
23
|
await expoScreenOrientation.lockAsync(orientationLock);
|
|
24
24
|
_lastOrientationLock = orientationLock;
|
|
25
25
|
}
|
|
26
|
+
// UPSTREAM-BUG(expo): .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts:81
|
|
27
|
+
// and :112 - TWO falsy traps, and Android's SCREEN_ORIENTATION_LANDSCAPE is 0: the truthiness
|
|
28
|
+
// check skips the assignment, and even with that one fixed, !platformOrientationParam still
|
|
29
|
+
// rejects the assigned 0. Fixing only the first trap changes nothing.
|
|
30
|
+
// The caller gets a TypeError and the call never reaches native, so landscape cannot be locked
|
|
31
|
+
// on Android through this API.
|
|
32
|
+
// Ported verbatim for parity; do NOT fix without recording a deliberate divergence.
|
|
26
33
|
/** Locks the screen to a platform-specific orientation param — Android constant, iOS
|
|
27
34
|
* orientation array, or web `WebOrientationLock`. */
|
|
28
35
|
export async function lockPlatformAsync(options) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the initial value with one-shot getOrientationAsync()/getOrientationLockAsync() calls before
|
|
3
3
|
// the first native event fires, mirroring packages/network's useNetworkState.
|
|
4
4
|
import { useEffect, useState } from 'react';
|
|
5
|
-
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core';
|
|
5
|
+
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core/index.js';
|
|
6
6
|
export function useScreenOrientation() {
|
|
7
7
|
const [screenOrientation, setScreenOrientation] = useState({
|
|
8
8
|
orientation: Orientation.UNKNOWN,
|
package/build/react/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { useScreenOrientation } from './hooks/use-screen-orientation';
|
|
2
|
-
export
|
|
2
|
+
export * from '../core';
|
package/build/react/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @symbiote-native/screen-orientation/react: the React entry over the framework-agnostic core.
|
|
2
|
-
export { useScreenOrientation } from './hooks/use-screen-orientation';
|
|
3
|
-
export
|
|
2
|
+
export { useScreenOrientation } from './hooks/use-screen-orientation/index.js';
|
|
3
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/screen-orientation/svelte: the Svelte entry over the framework-agnostic core —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/svelte/src/runes (never
|
|
3
|
+
// `hooks`/`composables`, those are React's and Vue's terms).
|
|
4
|
+
export { useScreenOrientation } from './runes/use-screen-orientation.svelte';
|
|
5
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core (core/screen-orientation.ts). Seeds the
|
|
2
|
+
// initial value with one-shot getOrientationAsync()/getOrientationLockAsync() calls before the
|
|
3
|
+
// first native event fires, mirroring packages/network's useNetworkState.
|
|
4
|
+
//
|
|
5
|
+
// `.svelte.ts` extension: runes ($state/$effect) only work there outside a `.svelte` component;
|
|
6
|
+
// `runes/` is Svelte's name for the lifecycle bucket (React's `hooks/`, Vue's `composables/`).
|
|
7
|
+
// Returns a boxed getter, not a bare `$state`: Svelte 5 reactivity is lexically scoped to the
|
|
8
|
+
// declaring module and doesn't survive being returned raw from a plain function, so the caller
|
|
9
|
+
// reads `.current` like unwrapping Vue's `Ref` via `.value`.
|
|
10
|
+
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../core/index.js';
|
|
11
|
+
export function useScreenOrientation() {
|
|
12
|
+
let screenOrientation = $state({
|
|
13
|
+
orientation: Orientation.UNKNOWN,
|
|
14
|
+
orientationLock: OrientationLock.UNKNOWN,
|
|
15
|
+
});
|
|
16
|
+
$effect(() => {
|
|
17
|
+
// Write-only touches of `screenOrientation`, so the effect has no dependency on it and runs
|
|
18
|
+
// once per mount - the twin of Vue's onMounted/onUnmounted pair.
|
|
19
|
+
Promise.all([getOrientationAsync(), getOrientationLockAsync()]).then(([orientation, orientationLock]) => {
|
|
20
|
+
screenOrientation = { orientation, orientationLock };
|
|
21
|
+
});
|
|
22
|
+
const subscription = addOrientationChangeListener(event => {
|
|
23
|
+
screenOrientation = {
|
|
24
|
+
orientation: event.orientationInfo.orientation,
|
|
25
|
+
orientationLock: event.orientationLock,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
return () => subscription.remove();
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
get current() {
|
|
32
|
+
return screenOrientation;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// initial value with one-shot getOrientationAsync()/getOrientationLockAsync() calls before the
|
|
3
3
|
// first native event fires, mirroring packages/network's useNetworkState.
|
|
4
4
|
import { onMounted, onUnmounted, ref } from '@vue/runtime-core';
|
|
5
|
-
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core';
|
|
5
|
+
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core/index.js';
|
|
6
6
|
export function useScreenOrientation() {
|
|
7
7
|
const screenOrientation = ref({
|
|
8
8
|
orientation: Orientation.UNKNOWN,
|
package/build/vue/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { useScreenOrientation } from './composables/use-screen-orientation';
|
|
2
|
-
export
|
|
2
|
+
export * from '../core';
|
package/build/vue/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// @symbiote-native/screen-orientation/vue: the Vue entry over the framework-agnostic core.
|
|
2
|
-
export { useScreenOrientation } from './composables/use-screen-orientation';
|
|
3
|
-
export
|
|
2
|
+
export { useScreenOrientation } from './composables/use-screen-orientation/index.js';
|
|
3
|
+
export * from '../core/index.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { ScreenOrientationService } from './services/screen-orientation.service';
|
|
2
|
-
export
|
|
2
|
+
export * from '../core';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ScreenOrientationService is the Angular-only lifecycle half; the free functions and event
|
|
2
2
|
// subscription plumbing all live in core, shared with React/Vue.
|
|
3
3
|
export { ScreenOrientationService } from './services/screen-orientation.service';
|
|
4
|
-
export
|
|
4
|
+
export * from '../core';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,iEAAiE;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,iEAAiE;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,cAAc,SAAS,CAAC"}
|
|
@@ -24,10 +24,10 @@ export class ScreenOrientationService {
|
|
|
24
24
|
}, { injector: this.injector });
|
|
25
25
|
return screenOrientation.asReadonly();
|
|
26
26
|
}
|
|
27
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
28
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.
|
|
27
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScreenOrientationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
28
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScreenOrientationService, providedIn: 'root' });
|
|
29
29
|
}
|
|
30
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
30
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ScreenOrientationService, decorators: [{
|
|
31
31
|
type: Injectable,
|
|
32
32
|
args: [{ providedIn: 'root' }]
|
|
33
33
|
}] });
|
|
@@ -23,6 +23,13 @@ export async function lockAsync(orientationLock) {
|
|
|
23
23
|
await expoScreenOrientation.lockAsync(orientationLock);
|
|
24
24
|
_lastOrientationLock = orientationLock;
|
|
25
25
|
}
|
|
26
|
+
// UPSTREAM-BUG(expo): .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts:81
|
|
27
|
+
// and :112 - TWO falsy traps, and Android's SCREEN_ORIENTATION_LANDSCAPE is 0: the truthiness
|
|
28
|
+
// check skips the assignment, and even with that one fixed, !platformOrientationParam still
|
|
29
|
+
// rejects the assigned 0. Fixing only the first trap changes nothing.
|
|
30
|
+
// The caller gets a TypeError and the call never reaches native, so landscape cannot be locked
|
|
31
|
+
// on Android through this API.
|
|
32
|
+
// Ported verbatim for parity; do NOT fix without recording a deliberate divergence.
|
|
26
33
|
/** Locks the screen to a platform-specific orientation param — Android constant, iOS
|
|
27
34
|
* orientation array, or web `WebOrientationLock`. */
|
|
28
35
|
export async function lockPlatformAsync(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen-orientation.js","sourceRoot":"","sources":["../../src/core/screen-orientation.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,2FAA2F;AAC3F,qFAAqF;AACrF,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAA0B,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAkC,MAAM,iBAAiB,CAAC;AACxF,OAAO,EACL,WAAW,EACX,eAAe,EACf,kBAAkB,GAInB,MAAM,SAAS,CAAC;AAEjB,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAE/C,IAAI,6BAA6B,GAAwB,EAAE,CAAC;AAC5D,IAAI,oBAAoB,GAAoB,eAAe,CAAC,OAAO,CAAC;AAEpE,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,eAAgC;IAC9D,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACxD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,6BAA6B,eAAe,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,eAAe,KAAK,eAAe,CAAC,KAAK,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IACD,MAAM,qBAAqB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACvD,oBAAoB,GAAG,eAAe,CAAC;AACzC,CAAC;AAED;qDACqD;AACrD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAgC;IACtE,IAAI,CAAC,qBAAqB,CAAC,iBAAiB,EAAE,CAAC;QAC7C,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,GAC7F,OAAO,CAAC;IACV,IAAI,wBAA+D,CAAC;IACpE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,gCAAgC,EAAE,CAAC;QAClE,IAAI,KAAK,CAAC,gCAAgC,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,SAAS,CACjB,8FAA8F,gCAAgC,EAAE,CACjI,CAAC;QACJ,CAAC;QACD,wBAAwB,GAAG,gCAAgC,CAAC;IAC9D,CAAC;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,yBAAyB,EAAE,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,SAAS,CACjB,mFAAmF,yBAAyB,EAAE,CAC/G,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAChD,KAAK,MAAM,WAAW,IAAI,yBAAyB,EAAE,CAAC;YACpD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,SAAS,CACjB,mCAAmC,WAAW,6BAA6B,CAC5E,CAAC;YACJ,CAAC;QACH,CAAC;QACD,wBAAwB,GAAG,yBAAyB,CAAC;IACvD,CAAC;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,wBAAwB,EAAE,CAAC;QAC7D,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC9D,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;YAC5D,MAAM,IAAI,SAAS,CAAC,iCAAiC,wBAAwB,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,wBAAwB,GAAG,wBAAwB,CAAC;IACtD,CAAC;IACD,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,qEAAqE,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,qBAAqB,CAAC,iBAAiB,CAAC,wBAAwB,CAAC,CAAC;IACxE,oBAAoB,GAAG,eAAe,CAAC,KAAK,CAAC;AAC/C,CAAC;AAED,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,qBAAqB,CAAC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,EAAE,CAAC;QAC/C,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,qBAAqB,CAAC,mBAAmB,EAAE,CAAC;AACrD,CAAC;AAED;0EAC0E;AAC1E,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,IAAI,CAAC,qBAAqB,CAAC,uBAAuB,EAAE,CAAC;QACnD,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,OAAO,qBAAqB,CAAC,uBAAuB,EAAE,CAAC;AACzD,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,+BAA+B;IACnD,MAAM,uBAAuB,GAAG,MAAM,qBAAqB,CAAC,+BAA+B,EAAE,EAAE,CAAC;IAChG,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,uBAAuB,KAAK,QAAQ,EAAE,CAAC;QAC7E,OAAO,EAAE,gCAAgC,EAAE,uBAAuB,EAAE,CAAC;IACvE,CAAC;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACpE,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,OAAO,uBAAuB,KAAK,QAAQ,EAAE,CAAC;QACzE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,CAAC;IAC/D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,eAAgC;IAEhC,IAAI,CAAC,qBAAqB,CAAC,4BAA4B,EAAE,CAAC;QACxD,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,8BAA8B,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACxD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,6BAA6B,eAAe,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,qBAAqB,CAAC,4BAA4B,CAAC,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,4BAA4B,CAC1C,QAAmC;IAEnC,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,sDAAsD,QAAQ,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,YAAY,GAAG,qCAAqC,CAAC,QAAQ,CAAC,CAAC;IACrE,6BAA6B,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,gCAAgC;IAC9C,IAAI,CAAC,GAAG,6BAA6B,CAAC,MAAM,CAAC;IAC7C,OAAO,CAAC,EAAE,EAAE,CAAC;QACX,6BAA6B,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3C,6BAA6B,CAAC,GAAG,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,+BAA+B,CAAC,YAA+B;IAC7E,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAC3D,CAAC;IACD,YAAY,CAAC,MAAM,EAAE,CAAC;IACtB,6BAA6B,GAAG,6BAA6B,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC;AACpG,CAAC;AAED,+FAA+F;AAC/F,+FAA+F;AAC/F,SAAS,qCAAqC,CAC5C,QAAmC;IAEnC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QACnD,OAAO,qBAAqB,CAAC,WAAW,CACtC,yBAAyB,EACzB,KAAK,EAAE,MAA8B,EAAE,EAAE;YACvC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CACF,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACvD,uBAAuB,EAAE;YACzB,mBAAmB,EAAE;SACtB,CAAC,CAAC;QACH,QAAQ,CAAC,EAAE,eAAe,EAAE,EAAE,WAAW,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"screen-orientation.js","sourceRoot":"","sources":["../../src/core/screen-orientation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/screen-orientation",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "expo-screen-orientation wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, and Angular adapters. Orientation locking (lockAsync/lockPlatformAsync/unlockAsync), the current orientation and lock, and an auto-updating orientation-change hook/composable/service.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"types": "./build/react/index.d.ts",
|
|
31
31
|
"default": "./build/react/index.js"
|
|
32
32
|
},
|
|
33
|
+
"./svelte": {
|
|
34
|
+
"types": "./build/svelte/index.d.ts",
|
|
35
|
+
"default": "./build/svelte/index.js"
|
|
36
|
+
},
|
|
33
37
|
"./angular": {
|
|
34
38
|
"types": "./build-ngc/angular/index.d.ts",
|
|
35
39
|
"react-native": "./build-ngc/angular/index.js",
|
|
@@ -40,7 +44,10 @@
|
|
|
40
44
|
"src",
|
|
41
45
|
"build",
|
|
42
46
|
"build-ngc",
|
|
43
|
-
"native-link.json"
|
|
47
|
+
"native-link.json",
|
|
48
|
+
"!src/**/*.test.*",
|
|
49
|
+
"!src/**/*.spec.*",
|
|
50
|
+
"!src/**/*.detox.*"
|
|
44
51
|
],
|
|
45
52
|
"publishConfig": {
|
|
46
53
|
"access": "public"
|
|
@@ -50,15 +57,17 @@
|
|
|
50
57
|
"expo-modules-core": "57.0.5"
|
|
51
58
|
},
|
|
52
59
|
"peerDependencies": {
|
|
60
|
+
"@symbiote-native/angular": ">=0.6.2",
|
|
53
61
|
"@symbiote-native/engine": ">=0.1.7",
|
|
62
|
+
"@symbiote-native/react": ">=0.2.8",
|
|
63
|
+
"@symbiote-native/svelte": ">=0.1.0",
|
|
64
|
+
"@symbiote-native/vue": ">=0.3.8",
|
|
54
65
|
"@angular/core": ">=20",
|
|
55
66
|
"@vue/runtime-core": "^3.5.13",
|
|
56
67
|
"react": ">=19.0.0",
|
|
57
68
|
"react-native": ">=0.86",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"@symbiote-native/react": "0.2.8",
|
|
61
|
-
"@symbiote-native/vue": "0.3.8"
|
|
69
|
+
"svelte": ">=5.56.0",
|
|
70
|
+
"vue": ">=3.5.0"
|
|
62
71
|
},
|
|
63
72
|
"peerDependenciesMeta": {
|
|
64
73
|
"@symbiote-native/angular": {
|
|
@@ -67,6 +76,9 @@
|
|
|
67
76
|
"@symbiote-native/react": {
|
|
68
77
|
"optional": true
|
|
69
78
|
},
|
|
79
|
+
"@symbiote-native/svelte": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
70
82
|
"@symbiote-native/vue": {
|
|
71
83
|
"optional": true
|
|
72
84
|
},
|
|
@@ -79,24 +91,29 @@
|
|
|
79
91
|
"react": {
|
|
80
92
|
"optional": true
|
|
81
93
|
},
|
|
94
|
+
"svelte": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
82
97
|
"vue": {
|
|
83
98
|
"optional": true
|
|
84
99
|
}
|
|
85
100
|
},
|
|
86
101
|
"devDependencies": {
|
|
87
|
-
"@angular/compiler": "
|
|
88
|
-
"@angular/compiler-cli": "
|
|
89
|
-
"@angular/core": "
|
|
102
|
+
"@angular/compiler": "~22.0.8",
|
|
103
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
104
|
+
"@angular/core": "~22.0.8",
|
|
90
105
|
"@types/node": "^26.0.0",
|
|
91
106
|
"@types/react": "^19.2.0",
|
|
92
107
|
"@vue/runtime-core": "^3.5.13",
|
|
93
108
|
"react": "19.2.3",
|
|
109
|
+
"svelte": "^5.56.0",
|
|
94
110
|
"typescript": "~6.0.0",
|
|
111
|
+
"@symbiote-native/angular": "0.7.0",
|
|
112
|
+
"@symbiote-native/engine": "0.2.0",
|
|
113
|
+
"@symbiote-native/react": "0.3.0",
|
|
114
|
+
"@symbiote-native/svelte": "0.2.0",
|
|
95
115
|
"@symbiote-native/test-utils": "0.1.6",
|
|
96
|
-
"@symbiote-native/
|
|
97
|
-
"@symbiote-native/angular": "0.6.1",
|
|
98
|
-
"@symbiote-native/vue": "0.3.8",
|
|
99
|
-
"@symbiote-native/react": "0.2.8"
|
|
116
|
+
"@symbiote-native/vue": "0.4.0"
|
|
100
117
|
},
|
|
101
118
|
"scripts": {
|
|
102
119
|
"typecheck": "tsc --build",
|
package/src/angular/index.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
// ScreenOrientationService is the Angular-only lifecycle half; the free functions and event
|
|
2
2
|
// subscription plumbing all live in core, shared with React/Vue.
|
|
3
3
|
export { ScreenOrientationService } from './services/screen-orientation.service';
|
|
4
|
-
export
|
|
5
|
-
lockAsync,
|
|
6
|
-
lockPlatformAsync,
|
|
7
|
-
unlockAsync,
|
|
8
|
-
getOrientationAsync,
|
|
9
|
-
getOrientationLockAsync,
|
|
10
|
-
getPlatformOrientationLockAsync,
|
|
11
|
-
supportsOrientationLockAsync,
|
|
12
|
-
addOrientationChangeListener,
|
|
13
|
-
removeOrientationChangeListeners,
|
|
14
|
-
removeOrientationChangeListener,
|
|
15
|
-
Orientation,
|
|
16
|
-
OrientationLock,
|
|
17
|
-
SizeClassIOS,
|
|
18
|
-
WebOrientationLock,
|
|
19
|
-
WebOrientation,
|
|
20
|
-
type PlatformOrientationInfo,
|
|
21
|
-
type ScreenOrientationInfo,
|
|
22
|
-
type OrientationChangeEvent,
|
|
23
|
-
type OrientationChangeListener,
|
|
24
|
-
type ScreenOrientationState,
|
|
25
|
-
type EventSubscription,
|
|
26
|
-
} from '../core';
|
|
4
|
+
export * from '../core';
|
|
@@ -34,6 +34,13 @@ export async function lockAsync(orientationLock: OrientationLock): Promise<void>
|
|
|
34
34
|
_lastOrientationLock = orientationLock;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// UPSTREAM-BUG(expo): .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts:81
|
|
38
|
+
// and :112 - TWO falsy traps, and Android's SCREEN_ORIENTATION_LANDSCAPE is 0: the truthiness
|
|
39
|
+
// check skips the assignment, and even with that one fixed, !platformOrientationParam still
|
|
40
|
+
// rejects the assigned 0. Fixing only the first trap changes nothing.
|
|
41
|
+
// The caller gets a TypeError and the call never reaches native, so landscape cannot be locked
|
|
42
|
+
// on Android through this API.
|
|
43
|
+
// Ported verbatim for parity; do NOT fix without recording a deliberate divergence.
|
|
37
44
|
/** Locks the screen to a platform-specific orientation param — Android constant, iOS
|
|
38
45
|
* orientation array, or web `WebOrientationLock`. */
|
|
39
46
|
export async function lockPlatformAsync(options: PlatformOrientationInfo): Promise<void> {
|
package/src/react/index.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/screen-orientation/react: the React entry over the framework-agnostic core.
|
|
2
2
|
|
|
3
3
|
export { useScreenOrientation } from './hooks/use-screen-orientation';
|
|
4
|
-
export
|
|
5
|
-
lockAsync,
|
|
6
|
-
lockPlatformAsync,
|
|
7
|
-
unlockAsync,
|
|
8
|
-
getOrientationAsync,
|
|
9
|
-
getOrientationLockAsync,
|
|
10
|
-
getPlatformOrientationLockAsync,
|
|
11
|
-
supportsOrientationLockAsync,
|
|
12
|
-
addOrientationChangeListener,
|
|
13
|
-
removeOrientationChangeListeners,
|
|
14
|
-
removeOrientationChangeListener,
|
|
15
|
-
Orientation,
|
|
16
|
-
OrientationLock,
|
|
17
|
-
SizeClassIOS,
|
|
18
|
-
WebOrientationLock,
|
|
19
|
-
WebOrientation,
|
|
20
|
-
type PlatformOrientationInfo,
|
|
21
|
-
type ScreenOrientationInfo,
|
|
22
|
-
type OrientationChangeEvent,
|
|
23
|
-
type OrientationChangeListener,
|
|
24
|
-
type ScreenOrientationState,
|
|
25
|
-
type EventSubscription,
|
|
26
|
-
} from '../core';
|
|
4
|
+
export * from '../core';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @symbiote-native/screen-orientation/svelte: the Svelte entry over the framework-agnostic core —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/svelte/src/runes (never
|
|
3
|
+
// `hooks`/`composables`, those are React's and Vue's terms).
|
|
4
|
+
|
|
5
|
+
export { useScreenOrientation } from './runes/use-screen-orientation.svelte';
|
|
6
|
+
export * from '../core';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Svelte lifecycle wiring over the framework-agnostic core (core/screen-orientation.ts). Seeds the
|
|
2
|
+
// initial value with one-shot getOrientationAsync()/getOrientationLockAsync() calls before the
|
|
3
|
+
// first native event fires, mirroring packages/network's useNetworkState.
|
|
4
|
+
//
|
|
5
|
+
// `.svelte.ts` extension: runes ($state/$effect) only work there outside a `.svelte` component;
|
|
6
|
+
// `runes/` is Svelte's name for the lifecycle bucket (React's `hooks/`, Vue's `composables/`).
|
|
7
|
+
// Returns a boxed getter, not a bare `$state`: Svelte 5 reactivity is lexically scoped to the
|
|
8
|
+
// declaring module and doesn't survive being returned raw from a plain function, so the caller
|
|
9
|
+
// reads `.current` like unwrapping Vue's `Ref` via `.value`.
|
|
10
|
+
import {
|
|
11
|
+
addOrientationChangeListener,
|
|
12
|
+
getOrientationAsync,
|
|
13
|
+
getOrientationLockAsync,
|
|
14
|
+
Orientation,
|
|
15
|
+
OrientationLock,
|
|
16
|
+
type EventSubscription,
|
|
17
|
+
type ScreenOrientationState,
|
|
18
|
+
} from '../../core';
|
|
19
|
+
|
|
20
|
+
export function useScreenOrientation(): { readonly current: ScreenOrientationState } {
|
|
21
|
+
let screenOrientation = $state<ScreenOrientationState>({
|
|
22
|
+
orientation: Orientation.UNKNOWN,
|
|
23
|
+
orientationLock: OrientationLock.UNKNOWN,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
$effect(() => {
|
|
27
|
+
// Write-only touches of `screenOrientation`, so the effect has no dependency on it and runs
|
|
28
|
+
// once per mount - the twin of Vue's onMounted/onUnmounted pair.
|
|
29
|
+
Promise.all([getOrientationAsync(), getOrientationLockAsync()]).then(
|
|
30
|
+
([orientation, orientationLock]) => {
|
|
31
|
+
screenOrientation = { orientation, orientationLock };
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
const subscription: EventSubscription = addOrientationChangeListener(event => {
|
|
35
|
+
screenOrientation = {
|
|
36
|
+
orientation: event.orientationInfo.orientation,
|
|
37
|
+
orientationLock: event.orientationLock,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
return () => subscription.remove();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
get current(): ScreenOrientationState {
|
|
45
|
+
return screenOrientation;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Pulls in svelte's ambient global declarations ($state/$effect/...) for this package's tsc
|
|
2
|
+
// program. adapters/svelte gets these for free because render.ts does a real value import from
|
|
3
|
+
// 'svelte' (any file in a program importing a module loads its ambient globals for the whole
|
|
4
|
+
// program); this package has no such import, so a triple-slash reference does the same job
|
|
5
|
+
// explicitly rather than relying on an incidental side-effect.
|
|
6
|
+
/// <reference types="svelte" />
|
package/src/vue/index.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/screen-orientation/vue: the Vue entry over the framework-agnostic core.
|
|
2
2
|
|
|
3
3
|
export { useScreenOrientation } from './composables/use-screen-orientation';
|
|
4
|
-
export
|
|
5
|
-
lockAsync,
|
|
6
|
-
lockPlatformAsync,
|
|
7
|
-
unlockAsync,
|
|
8
|
-
getOrientationAsync,
|
|
9
|
-
getOrientationLockAsync,
|
|
10
|
-
getPlatformOrientationLockAsync,
|
|
11
|
-
supportsOrientationLockAsync,
|
|
12
|
-
addOrientationChangeListener,
|
|
13
|
-
removeOrientationChangeListeners,
|
|
14
|
-
removeOrientationChangeListener,
|
|
15
|
-
Orientation,
|
|
16
|
-
OrientationLock,
|
|
17
|
-
SizeClassIOS,
|
|
18
|
-
WebOrientationLock,
|
|
19
|
-
WebOrientation,
|
|
20
|
-
type PlatformOrientationInfo,
|
|
21
|
-
type ScreenOrientationInfo,
|
|
22
|
-
type OrientationChangeEvent,
|
|
23
|
-
type OrientationChangeListener,
|
|
24
|
-
type ScreenOrientationState,
|
|
25
|
-
type EventSubscription,
|
|
26
|
-
} from '../core';
|
|
4
|
+
export * from '../core';
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
// Co-located Angular-driven test (ADR 0025) for ScreenOrientationService. See network's
|
|
2
|
-
// network-state.service.test.ts for the shared rationale.
|
|
3
|
-
|
|
4
|
-
import '@angular/compiler';
|
|
5
|
-
import { Component, inject, type Signal } from '@angular/core';
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { mount, unmount } from '@symbiote-native/angular';
|
|
8
|
-
import { installFabric } from '@symbiote-native/test-utils';
|
|
9
|
-
import { ScreenOrientationService } from './index';
|
|
10
|
-
|
|
11
|
-
type IScreenOrientationState = { orientation: number; orientationLock: number };
|
|
12
|
-
type IOrientationChangeEvent = {
|
|
13
|
-
orientationLock: number;
|
|
14
|
-
orientationInfo: { orientation: number };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const addListenerMock = vi.fn();
|
|
18
|
-
const removeMock = vi.fn();
|
|
19
|
-
const getOrientationAsyncMock = vi.fn(async () => 1);
|
|
20
|
-
const getOrientationLockAsyncMock = vi.fn(async () => 0);
|
|
21
|
-
|
|
22
|
-
vi.mock('../../../core', () => ({
|
|
23
|
-
addOrientationChangeListener: (listener: (event: IOrientationChangeEvent) => void) =>
|
|
24
|
-
addListenerMock(listener),
|
|
25
|
-
getOrientationAsync: () => getOrientationAsyncMock(),
|
|
26
|
-
getOrientationLockAsync: () => getOrientationLockAsyncMock(),
|
|
27
|
-
Orientation: { UNKNOWN: 0, PORTRAIT_UP: 1 },
|
|
28
|
-
OrientationLock: { UNKNOWN: 9, DEFAULT: 0 },
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
const ROOT_TAG = 974;
|
|
32
|
-
const fabric = installFabric();
|
|
33
|
-
const tick = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
|
|
34
|
-
|
|
35
|
-
let capturedResult: Signal<IScreenOrientationState> | undefined;
|
|
36
|
-
let capturedListener: ((event: IOrientationChangeEvent) => void) | undefined;
|
|
37
|
-
|
|
38
|
-
@Component({
|
|
39
|
-
selector: 'symbiote-screen-orientation-host',
|
|
40
|
-
standalone: true,
|
|
41
|
-
template: '',
|
|
42
|
-
})
|
|
43
|
-
class ScreenOrientationHost {
|
|
44
|
-
readonly screenOrientation = inject(ScreenOrientationService).connect();
|
|
45
|
-
|
|
46
|
-
constructor() {
|
|
47
|
-
capturedResult = this.screenOrientation;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
capturedResult = undefined;
|
|
53
|
-
capturedListener = undefined;
|
|
54
|
-
getOrientationAsyncMock.mockResolvedValue(1);
|
|
55
|
-
getOrientationLockAsyncMock.mockResolvedValue(0);
|
|
56
|
-
addListenerMock.mockImplementation(listener => {
|
|
57
|
-
capturedListener = listener;
|
|
58
|
-
return { remove: removeMock };
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
afterEach(() => {
|
|
63
|
-
unmount(ROOT_TAG);
|
|
64
|
-
fabric.reset();
|
|
65
|
-
vi.clearAllMocks();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
describe('ScreenOrientationService.connect', () => {
|
|
69
|
-
it('reports Orientation/OrientationLock UNKNOWN before the initial fetch resolves', async () => {
|
|
70
|
-
mount(ROOT_TAG, ScreenOrientationHost);
|
|
71
|
-
|
|
72
|
-
expect(capturedResult?.()).toEqual({ orientation: 0, orientationLock: 9 });
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('reports the fetched state once getOrientationAsync()/getOrientationLockAsync() resolve', async () => {
|
|
76
|
-
mount(ROOT_TAG, ScreenOrientationHost);
|
|
77
|
-
await tick();
|
|
78
|
-
|
|
79
|
-
expect(capturedResult?.()).toEqual({ orientation: 1, orientationLock: 0 });
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('updates the signal when the registered listener fires', async () => {
|
|
83
|
-
mount(ROOT_TAG, ScreenOrientationHost);
|
|
84
|
-
await tick();
|
|
85
|
-
|
|
86
|
-
if (capturedListener === undefined) throw new Error('addListener callback was not captured');
|
|
87
|
-
capturedListener({ orientationLock: 5, orientationInfo: { orientation: 3 } });
|
|
88
|
-
|
|
89
|
-
expect(capturedResult?.()).toEqual({ orientation: 3, orientationLock: 5 });
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('removes the subscription when the host component is unmounted', async () => {
|
|
93
|
-
mount(ROOT_TAG, ScreenOrientationHost);
|
|
94
|
-
await tick();
|
|
95
|
-
|
|
96
|
-
unmount(ROOT_TAG);
|
|
97
|
-
await tick();
|
|
98
|
-
|
|
99
|
-
expect(removeMock).toHaveBeenCalledOnce();
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
const FAKE_NATIVE_SCREEN_ORIENTATION = {
|
|
4
|
-
lockAsync: vi.fn(async () => undefined),
|
|
5
|
-
lockPlatformAsync: vi.fn(async () => undefined),
|
|
6
|
-
getOrientationAsync: vi.fn(async () => 1),
|
|
7
|
-
getOrientationLockAsync: vi.fn(async () => 0),
|
|
8
|
-
getPlatformOrientationLockAsync: vi.fn(async () => 0),
|
|
9
|
-
supportsOrientationLockAsync: vi.fn(async () => true),
|
|
10
|
-
addListener: vi.fn(() => ({ remove: vi.fn() })),
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// The real ExpoScreenOrientation native module only exists on device — resolving it via
|
|
14
|
-
// requireNativeModule() at import time would throw in this headless test run, so the
|
|
15
|
-
// module-lookup file is faked in place of expo-modules-core's runtime resolution, same pattern
|
|
16
|
-
// packages/network/src/core/network.test.ts uses.
|
|
17
|
-
vi.mock('./native-module', () => ({
|
|
18
|
-
expoScreenOrientation: FAKE_NATIVE_SCREEN_ORIENTATION,
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
// expo-modules-core's real entry transitively imports 'react-native' for Platform/
|
|
22
|
-
// TurboModuleRegistry, whose Flow-typed source Vitest's Oxc transform can't parse — same fake
|
|
23
|
-
// packages/cellular/src/core/cellular.test.ts uses. Platform.OS is mutable per-test.
|
|
24
|
-
const fakePlatform = { OS: 'ios' as 'ios' | 'android' | 'web' };
|
|
25
|
-
|
|
26
|
-
vi.mock('expo-modules-core', () => ({
|
|
27
|
-
Platform: fakePlatform,
|
|
28
|
-
UnavailabilityError: class UnavailabilityError extends Error {
|
|
29
|
-
constructor(moduleName: string, propertyName: string) {
|
|
30
|
-
super(`${propertyName} is not available on ${moduleName}`);
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
// Android doesn't emit `expoDidUpdateDimensions` — the module piggybacks on RN's own Dimensions
|
|
36
|
-
// change event there instead (see the function-level comment in screen-orientation.ts).
|
|
37
|
-
vi.mock('react-native', () => ({
|
|
38
|
-
Dimensions: { addEventListener: vi.fn(() => ({ remove: vi.fn() })) },
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
const {
|
|
42
|
-
lockAsync,
|
|
43
|
-
lockPlatformAsync,
|
|
44
|
-
unlockAsync,
|
|
45
|
-
getOrientationAsync,
|
|
46
|
-
getOrientationLockAsync,
|
|
47
|
-
getPlatformOrientationLockAsync,
|
|
48
|
-
supportsOrientationLockAsync,
|
|
49
|
-
addOrientationChangeListener,
|
|
50
|
-
removeOrientationChangeListeners,
|
|
51
|
-
removeOrientationChangeListener,
|
|
52
|
-
} = await import('./screen-orientation');
|
|
53
|
-
const { Orientation, OrientationLock, WebOrientationLock } = await import('./types');
|
|
54
|
-
const { Dimensions } = await import('react-native');
|
|
55
|
-
|
|
56
|
-
afterEach(() => {
|
|
57
|
-
fakePlatform.OS = 'ios';
|
|
58
|
-
vi.clearAllMocks();
|
|
59
|
-
removeOrientationChangeListeners();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('lockAsync', () => {
|
|
63
|
-
it('delegates to the native module', async () => {
|
|
64
|
-
await lockAsync(OrientationLock.PORTRAIT_UP);
|
|
65
|
-
|
|
66
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockAsync).toHaveBeenCalledWith(
|
|
67
|
-
OrientationLock.PORTRAIT_UP,
|
|
68
|
-
);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('no-ops on OrientationLock.OTHER without calling the native module', async () => {
|
|
72
|
-
await lockAsync(OrientationLock.OTHER);
|
|
73
|
-
|
|
74
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockAsync).not.toHaveBeenCalled();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('throws a TypeError on an invalid lock value', async () => {
|
|
78
|
-
// @ts-expect-error -- simulating a caller passing a bogus lock value
|
|
79
|
-
await expect(lockAsync(999)).rejects.toThrow('Invalid Orientation Lock');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('throws UnavailabilityError when the native method is absent', async () => {
|
|
83
|
-
const { lockAsync: native } = FAKE_NATIVE_SCREEN_ORIENTATION;
|
|
84
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
85
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.lockAsync = undefined;
|
|
86
|
-
|
|
87
|
-
await expect(lockAsync(OrientationLock.PORTRAIT_UP)).rejects.toThrow(
|
|
88
|
-
'lockAsync is not available on ScreenOrientation',
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.lockAsync = native;
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
describe('lockPlatformAsync', () => {
|
|
96
|
-
it('forwards the Android numeric constant on Android', async () => {
|
|
97
|
-
fakePlatform.OS = 'android';
|
|
98
|
-
|
|
99
|
-
await lockPlatformAsync({ screenOrientationConstantAndroid: 1 });
|
|
100
|
-
|
|
101
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockPlatformAsync).toHaveBeenCalledWith(1);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('forwards the iOS orientation array on iOS', async () => {
|
|
105
|
-
fakePlatform.OS = 'ios';
|
|
106
|
-
|
|
107
|
-
await lockPlatformAsync({ screenOrientationArrayIOS: [Orientation.PORTRAIT_UP] });
|
|
108
|
-
|
|
109
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockPlatformAsync).toHaveBeenCalledWith([
|
|
110
|
-
Orientation.PORTRAIT_UP,
|
|
111
|
-
]);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('forwards the web orientation lock on web', async () => {
|
|
115
|
-
fakePlatform.OS = 'web';
|
|
116
|
-
|
|
117
|
-
await lockPlatformAsync({ screenOrientationLockWeb: WebOrientationLock.LANDSCAPE });
|
|
118
|
-
|
|
119
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockPlatformAsync).toHaveBeenCalledWith(
|
|
120
|
-
WebOrientationLock.LANDSCAPE,
|
|
121
|
-
);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('throws a TypeError on an invalid iOS orientation entry', async () => {
|
|
125
|
-
fakePlatform.OS = 'ios';
|
|
126
|
-
|
|
127
|
-
// @ts-expect-error -- simulating a caller passing a bogus orientation value
|
|
128
|
-
await expect(lockPlatformAsync({ screenOrientationArrayIOS: [999] })).rejects.toThrow(
|
|
129
|
-
'is not a valid Orientation',
|
|
130
|
-
);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('throws a TypeError when no matching platform option is supplied', async () => {
|
|
134
|
-
fakePlatform.OS = 'ios';
|
|
135
|
-
|
|
136
|
-
await expect(lockPlatformAsync({})).rejects.toThrow(
|
|
137
|
-
'cannot be called with undefined option properties',
|
|
138
|
-
);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('throws UnavailabilityError when the native method is absent', async () => {
|
|
142
|
-
const { lockPlatformAsync: native } = FAKE_NATIVE_SCREEN_ORIENTATION;
|
|
143
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
144
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.lockPlatformAsync = undefined;
|
|
145
|
-
|
|
146
|
-
await expect(lockPlatformAsync({ screenOrientationConstantAndroid: 1 })).rejects.toThrow(
|
|
147
|
-
'lockPlatformAsync is not available on ScreenOrientation',
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.lockPlatformAsync = native;
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe('unlockAsync', () => {
|
|
155
|
-
it('delegates to lockAsync with OrientationLock.DEFAULT', async () => {
|
|
156
|
-
await unlockAsync();
|
|
157
|
-
|
|
158
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.lockAsync).toHaveBeenCalledWith(OrientationLock.DEFAULT);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
describe('getOrientationAsync', () => {
|
|
163
|
-
it('delegates to the native module', async () => {
|
|
164
|
-
await expect(getOrientationAsync()).resolves.toBe(1);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it('throws UnavailabilityError when the native method is absent', async () => {
|
|
168
|
-
const { getOrientationAsync: native } = FAKE_NATIVE_SCREEN_ORIENTATION;
|
|
169
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
170
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getOrientationAsync = undefined;
|
|
171
|
-
|
|
172
|
-
await expect(getOrientationAsync()).rejects.toThrow();
|
|
173
|
-
|
|
174
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getOrientationAsync = native;
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('getOrientationLockAsync', () => {
|
|
179
|
-
it('delegates to the native module when present', async () => {
|
|
180
|
-
await expect(getOrientationLockAsync()).resolves.toBe(0);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('falls back to the last lock set via lockAsync when the native method is absent', async () => {
|
|
184
|
-
await lockAsync(OrientationLock.LANDSCAPE);
|
|
185
|
-
const { getOrientationLockAsync: native } = FAKE_NATIVE_SCREEN_ORIENTATION;
|
|
186
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
187
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getOrientationLockAsync = undefined;
|
|
188
|
-
|
|
189
|
-
await expect(getOrientationLockAsync()).resolves.toBe(OrientationLock.LANDSCAPE);
|
|
190
|
-
|
|
191
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getOrientationLockAsync = native;
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
describe('getPlatformOrientationLockAsync', () => {
|
|
196
|
-
it('wraps a numeric native value as screenOrientationConstantAndroid on Android', async () => {
|
|
197
|
-
fakePlatform.OS = 'android';
|
|
198
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getPlatformOrientationLockAsync.mockResolvedValueOnce(1);
|
|
199
|
-
|
|
200
|
-
await expect(getPlatformOrientationLockAsync()).resolves.toEqual({
|
|
201
|
-
screenOrientationConstantAndroid: 1,
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('wraps an array native value as screenOrientationArrayIOS on iOS', async () => {
|
|
206
|
-
fakePlatform.OS = 'ios';
|
|
207
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getPlatformOrientationLockAsync.mockResolvedValueOnce([
|
|
208
|
-
Orientation.LANDSCAPE_LEFT,
|
|
209
|
-
]);
|
|
210
|
-
|
|
211
|
-
await expect(getPlatformOrientationLockAsync()).resolves.toEqual({
|
|
212
|
-
screenOrientationArrayIOS: [Orientation.LANDSCAPE_LEFT],
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('wraps a string native value as screenOrientationLockWeb on web', async () => {
|
|
217
|
-
fakePlatform.OS = 'web';
|
|
218
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.getPlatformOrientationLockAsync.mockResolvedValueOnce(
|
|
219
|
-
WebOrientationLock.ANY,
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
await expect(getPlatformOrientationLockAsync()).resolves.toEqual({
|
|
223
|
-
screenOrientationLockWeb: WebOrientationLock.ANY,
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
describe('supportsOrientationLockAsync', () => {
|
|
229
|
-
it('delegates to the native module', async () => {
|
|
230
|
-
await expect(supportsOrientationLockAsync(OrientationLock.PORTRAIT)).resolves.toBe(true);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('throws a TypeError on an invalid lock value', async () => {
|
|
234
|
-
// @ts-expect-error -- simulating a caller passing a bogus lock value
|
|
235
|
-
await expect(supportsOrientationLockAsync(999)).rejects.toThrow('Invalid Orientation Lock');
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('throws UnavailabilityError when the native method is absent', async () => {
|
|
239
|
-
const { supportsOrientationLockAsync: native } = FAKE_NATIVE_SCREEN_ORIENTATION;
|
|
240
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
241
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.supportsOrientationLockAsync = undefined;
|
|
242
|
-
|
|
243
|
-
await expect(supportsOrientationLockAsync(OrientationLock.PORTRAIT)).rejects.toThrow();
|
|
244
|
-
|
|
245
|
-
FAKE_NATIVE_SCREEN_ORIENTATION.supportsOrientationLockAsync = native;
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('addOrientationChangeListener', () => {
|
|
250
|
-
it('subscribes through the native expoDidUpdateDimensions event on iOS', () => {
|
|
251
|
-
fakePlatform.OS = 'ios';
|
|
252
|
-
const listener = vi.fn();
|
|
253
|
-
|
|
254
|
-
addOrientationChangeListener(listener);
|
|
255
|
-
|
|
256
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.addListener).toHaveBeenCalledWith(
|
|
257
|
-
'expoDidUpdateDimensions',
|
|
258
|
-
expect.any(Function),
|
|
259
|
-
);
|
|
260
|
-
expect(Dimensions.addEventListener).not.toHaveBeenCalled();
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('subscribes through RN Dimensions.addEventListener on Android', () => {
|
|
264
|
-
fakePlatform.OS = 'android';
|
|
265
|
-
const listener = vi.fn();
|
|
266
|
-
|
|
267
|
-
addOrientationChangeListener(listener);
|
|
268
|
-
|
|
269
|
-
expect(Dimensions.addEventListener).toHaveBeenCalledWith('change', expect.any(Function));
|
|
270
|
-
expect(FAKE_NATIVE_SCREEN_ORIENTATION.addListener).not.toHaveBeenCalled();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
it('throws a TypeError when the listener is not a function', () => {
|
|
274
|
-
// @ts-expect-error -- simulating a caller passing a non-function listener
|
|
275
|
-
expect(() => addOrientationChangeListener('not-a-function')).toThrow();
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
describe('removeOrientationChangeListener / removeOrientationChangeListeners', () => {
|
|
280
|
-
it('removes a single subscription', () => {
|
|
281
|
-
const subscription = addOrientationChangeListener(vi.fn());
|
|
282
|
-
const removeSpy = vi.spyOn(subscription, 'remove');
|
|
283
|
-
|
|
284
|
-
removeOrientationChangeListener(subscription);
|
|
285
|
-
|
|
286
|
-
expect(removeSpy).toHaveBeenCalledTimes(1);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('throws a TypeError when passed an invalid subscription', () => {
|
|
290
|
-
// @ts-expect-error -- simulating a caller passing a bogus subscription
|
|
291
|
-
expect(() => removeOrientationChangeListener(null)).toThrow(
|
|
292
|
-
'Must pass in a valid subscription',
|
|
293
|
-
);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('removes every registered subscription', () => {
|
|
297
|
-
const first = addOrientationChangeListener(vi.fn());
|
|
298
|
-
const second = addOrientationChangeListener(vi.fn());
|
|
299
|
-
const firstRemove = vi.spyOn(first, 'remove');
|
|
300
|
-
const secondRemove = vi.spyOn(second, 'remove');
|
|
301
|
-
|
|
302
|
-
removeOrientationChangeListeners();
|
|
303
|
-
|
|
304
|
-
expect(firstRemove).toHaveBeenCalledTimes(1);
|
|
305
|
-
expect(secondRemove).toHaveBeenCalledTimes(1);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// Co-located React-driven test (ADR 0025) for useScreenOrientation. See network's
|
|
2
|
-
// use-network-state.test.tsx for the shared rationale (mocks `core`, not expo-modules-core
|
|
3
|
-
// internals).
|
|
4
|
-
|
|
5
|
-
import { createElement, type ReactElement } from 'react';
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
-
import { mount, unmount, View } from '@symbiote-native/react';
|
|
8
|
-
import { installFabric } from '@symbiote-native/test-utils';
|
|
9
|
-
import { useScreenOrientation } from './index';
|
|
10
|
-
|
|
11
|
-
type IScreenOrientationState = { orientation: number; orientationLock: number };
|
|
12
|
-
type IOrientationChangeEvent = {
|
|
13
|
-
orientationLock: number;
|
|
14
|
-
orientationInfo: { orientation: number };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const { addListener, getOrientationAsync, getOrientationLockAsync, remove } = vi.hoisted(() => {
|
|
18
|
-
const remove = vi.fn();
|
|
19
|
-
return {
|
|
20
|
-
addListener: vi.fn((_listener: (event: IOrientationChangeEvent) => void) => ({ remove })),
|
|
21
|
-
getOrientationAsync: vi.fn(async () => 1),
|
|
22
|
-
getOrientationLockAsync: vi.fn(async () => 0),
|
|
23
|
-
remove,
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
vi.mock('../../../core', () => ({
|
|
28
|
-
addOrientationChangeListener: addListener,
|
|
29
|
-
getOrientationAsync,
|
|
30
|
-
getOrientationLockAsync,
|
|
31
|
-
Orientation: { UNKNOWN: 0, PORTRAIT_UP: 1 },
|
|
32
|
-
OrientationLock: { UNKNOWN: 9, DEFAULT: 0 },
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
const ROOT_TAG = 954;
|
|
36
|
-
|
|
37
|
-
const results: IScreenOrientationState[] = [];
|
|
38
|
-
|
|
39
|
-
function Probe(): ReactElement {
|
|
40
|
-
results.push(useScreenOrientation());
|
|
41
|
-
return createElement(View);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const fabric = installFabric();
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
fabric.reset();
|
|
48
|
-
results.length = 0;
|
|
49
|
-
vi.clearAllMocks();
|
|
50
|
-
getOrientationAsync.mockResolvedValue(1);
|
|
51
|
-
getOrientationLockAsync.mockResolvedValue(0);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
afterEach(() => unmount(ROOT_TAG));
|
|
55
|
-
|
|
56
|
-
describe('useScreenOrientation', () => {
|
|
57
|
-
it('reports OrientationLock/Orientation UNKNOWN before the initial fetch resolves', () => {
|
|
58
|
-
mount(ROOT_TAG, createElement(Probe));
|
|
59
|
-
|
|
60
|
-
expect(results[results.length - 1]).toEqual({ orientation: 0, orientationLock: 9 });
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('reports the fetched state once the initial getOrientationAsync()/getOrientationLockAsync() resolve', async () => {
|
|
64
|
-
mount(ROOT_TAG, createElement(Probe));
|
|
65
|
-
|
|
66
|
-
await vi.waitFor(() =>
|
|
67
|
-
expect(results[results.length - 1]).toEqual({ orientation: 1, orientationLock: 0 }),
|
|
68
|
-
);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('updates when the native listener fires', async () => {
|
|
72
|
-
mount(ROOT_TAG, createElement(Probe));
|
|
73
|
-
await vi.waitFor(() => expect(results[results.length - 1].orientation).toBe(1));
|
|
74
|
-
|
|
75
|
-
const listener = addListener.mock.calls[0][0];
|
|
76
|
-
listener({ orientationLock: 5, orientationInfo: { orientation: 3 } });
|
|
77
|
-
|
|
78
|
-
await vi.waitFor(() =>
|
|
79
|
-
expect(results[results.length - 1]).toEqual({
|
|
80
|
-
orientation: 3,
|
|
81
|
-
orientationLock: 5,
|
|
82
|
-
}),
|
|
83
|
-
);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('unsubscribes from the native listener on unmount', () => {
|
|
87
|
-
mount(ROOT_TAG, createElement(Probe));
|
|
88
|
-
|
|
89
|
-
unmount(ROOT_TAG);
|
|
90
|
-
|
|
91
|
-
expect(remove).toHaveBeenCalledTimes(1);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// Co-located Vue-driven test (ADR 0025) for useScreenOrientation. See network's
|
|
2
|
-
// use-network-state.test.ts for the shared rationale.
|
|
3
|
-
|
|
4
|
-
import { defineComponent, h, type Ref } from '@vue/runtime-core';
|
|
5
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
-
import { mount, unmount } from '@symbiote-native/vue';
|
|
7
|
-
import { installFabric } from '@symbiote-native/test-utils';
|
|
8
|
-
import { useScreenOrientation } from './index';
|
|
9
|
-
|
|
10
|
-
const ROOT_TAG = 9954;
|
|
11
|
-
|
|
12
|
-
type IScreenOrientationState = { orientation: number; orientationLock: number };
|
|
13
|
-
type IOrientationChangeEvent = {
|
|
14
|
-
orientationLock: number;
|
|
15
|
-
orientationInfo: { orientation: number };
|
|
16
|
-
};
|
|
17
|
-
type IListener = (event: IOrientationChangeEvent) => void;
|
|
18
|
-
|
|
19
|
-
let registeredListener: IListener | undefined;
|
|
20
|
-
const removeMock = vi.fn();
|
|
21
|
-
const addListenerMock = vi.fn((listener: IListener) => {
|
|
22
|
-
registeredListener = listener;
|
|
23
|
-
return { remove: removeMock };
|
|
24
|
-
});
|
|
25
|
-
const getOrientationAsyncMock = vi.fn(async () => 1);
|
|
26
|
-
const getOrientationLockAsyncMock = vi.fn(async () => 0);
|
|
27
|
-
|
|
28
|
-
vi.mock('../../../core', () => ({
|
|
29
|
-
addOrientationChangeListener: (listener: IListener) => addListenerMock(listener),
|
|
30
|
-
getOrientationAsync: () => getOrientationAsyncMock(),
|
|
31
|
-
getOrientationLockAsync: () => getOrientationLockAsyncMock(),
|
|
32
|
-
Orientation: { UNKNOWN: 0, PORTRAIT_UP: 1 },
|
|
33
|
-
OrientationLock: { UNKNOWN: 9, DEFAULT: 0 },
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
const fabric = installFabric();
|
|
37
|
-
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
fabric.reset();
|
|
40
|
-
registeredListener = undefined;
|
|
41
|
-
addListenerMock.mockClear();
|
|
42
|
-
removeMock.mockClear();
|
|
43
|
-
getOrientationAsyncMock.mockClear();
|
|
44
|
-
getOrientationLockAsyncMock.mockClear();
|
|
45
|
-
getOrientationAsyncMock.mockResolvedValue(1);
|
|
46
|
-
getOrientationLockAsyncMock.mockResolvedValue(0);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
afterEach(() => unmount(ROOT_TAG));
|
|
50
|
-
|
|
51
|
-
function mountScreenOrientation(): Ref<IScreenOrientationState> {
|
|
52
|
-
let screenOrientation: Ref<IScreenOrientationState> | undefined;
|
|
53
|
-
mount(
|
|
54
|
-
ROOT_TAG,
|
|
55
|
-
defineComponent({
|
|
56
|
-
setup: () => {
|
|
57
|
-
screenOrientation = useScreenOrientation();
|
|
58
|
-
return () => h('symbiote-text', {}, 'screen-orientation');
|
|
59
|
-
},
|
|
60
|
-
}),
|
|
61
|
-
);
|
|
62
|
-
if (screenOrientation === undefined) {
|
|
63
|
-
throw new Error('setup() did not run');
|
|
64
|
-
}
|
|
65
|
-
return screenOrientation;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
describe('useScreenOrientation (Vue)', () => {
|
|
69
|
-
it('starts at Orientation/OrientationLock UNKNOWN before the initial fetch resolves', () => {
|
|
70
|
-
const screenOrientation = mountScreenOrientation();
|
|
71
|
-
|
|
72
|
-
expect(screenOrientation.value).toEqual({ orientation: 0, orientationLock: 9 });
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('updates to the fetched value once getOrientationAsync()/getOrientationLockAsync() resolve', async () => {
|
|
76
|
-
const screenOrientation = mountScreenOrientation();
|
|
77
|
-
|
|
78
|
-
await vi.waitFor(() =>
|
|
79
|
-
expect(screenOrientation.value).toEqual({ orientation: 1, orientationLock: 0 }),
|
|
80
|
-
);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('updates the ref when the native listener fires', async () => {
|
|
84
|
-
const screenOrientation = mountScreenOrientation();
|
|
85
|
-
await vi.waitFor(() => expect(screenOrientation.value.orientation).toBe(1));
|
|
86
|
-
|
|
87
|
-
registeredListener?.({ orientationLock: 5, orientationInfo: { orientation: 3 } });
|
|
88
|
-
|
|
89
|
-
expect(screenOrientation.value).toEqual({ orientation: 3, orientationLock: 5 });
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('removes the subscription on unmount', () => {
|
|
93
|
-
mountScreenOrientation();
|
|
94
|
-
unmount(ROOT_TAG);
|
|
95
|
-
|
|
96
|
-
expect(removeMock).toHaveBeenCalledTimes(1);
|
|
97
|
-
});
|
|
98
|
-
});
|