@symbiote-native/screen-orientation 0.2.0 → 1.0.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 +83 -20
- package/build/angular/services/screen-orientation.service/index.js +1 -1
- package/build/core/screen-orientation.js +5 -4
- package/build/solid/index.d.ts +2 -0
- package/build/solid/index.js +5 -0
- package/build/solid/primitives/create-screen-orientation.d.ts +3 -0
- package/build/solid/primitives/create-screen-orientation.js +38 -0
- package/build-ngc/angular/services/screen-orientation.service/index.js +1 -1
- package/build-ngc/angular/services/screen-orientation.service/index.js.map +1 -1
- package/build-ngc/core/native-module.js.map +1 -1
- package/build-ngc/core/screen-orientation.js +5 -4
- package/build-ngc/core/screen-orientation.js.map +1 -1
- package/package.json +40 -14
- package/src/angular/services/screen-orientation.service/index.ts +8 -1
- package/src/core/native-module.ts +12 -6
- package/src/core/screen-orientation.ts +45 -14
- package/src/react/hooks/use-screen-orientation/index.ts +7 -5
- package/src/solid/index.ts +6 -0
- package/src/solid/primitives/create-screen-orientation.ts +57 -0
- package/src/svelte/runes/use-screen-orientation.svelte.ts +11 -7
package/README.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
Port of [`expo-screen-orientation`](https://docs.expo.dev/versions/latest/sdk/screen-orientation/)
|
|
4
4
|
for [SymbioteNative](../../README.md) — orientation locking (`lockAsync`/`lockPlatformAsync`/
|
|
5
5
|
`unlockAsync`), reading the current orientation and lock, and an auto-updating orientation-change
|
|
6
|
-
subscription, reachable from every adapter (React, Vue, Angular), not just
|
|
6
|
+
subscription, reachable from every adapter (React, Vue, Svelte, Solid, Angular), not just
|
|
7
|
+
React.
|
|
7
8
|
|
|
8
9
|
Built the same way as [`@symbiote-native/network`](../network) and
|
|
9
10
|
[`@symbiote-native/device`](../device), an `expo-modules-core`-based wrapper (see the
|
|
@@ -31,12 +32,12 @@ into the native host app **once**, covering this package and every other `expo-m
|
|
|
31
32
|
package (`@symbiote-native/network`, `@symbiote-native/device`, `@symbiote-native/sensors`, ...)
|
|
32
33
|
with zero further changes:
|
|
33
34
|
|
|
34
|
-
| Platform | Touches
|
|
35
|
-
|
|
36
|
-
| iOS
|
|
37
|
-
| iOS
|
|
38
|
-
| Android
|
|
39
|
-
| Android
|
|
35
|
+
| Platform | Touches |
|
|
36
|
+
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| iOS | `ios/Podfile` — add `use_expo_modules!` |
|
|
38
|
+
| iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
|
|
39
|
+
| Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
|
|
40
|
+
| Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
|
|
40
41
|
|
|
41
42
|
Full mechanics — the Podfile pieces that normally ship inside the `expo` package, the `expo`
|
|
42
43
|
peer-dependency exclusion list — live in the `symbiote-expo-native-module` skill. Reference
|
|
@@ -55,23 +56,29 @@ src/core/ screen-orientation.ts — lock*/unlock/get* functions +
|
|
|
55
56
|
Orientation/OrientationLock/SizeClassIOS/WebOrientationLock/WebOrientation
|
|
56
57
|
enums, PlatformOrientationInfo, ScreenOrientationInfo,
|
|
57
58
|
OrientationChangeEvent, hand-ported from ScreenOrientation.types.ts, plus
|
|
58
|
-
ScreenOrientationState (
|
|
59
|
+
ScreenOrientationState (the shape every adapter's wrapper returns).
|
|
59
60
|
src/react/hooks/ @symbiote-native/screen-orientation/react — useScreenOrientation
|
|
60
61
|
src/vue/composables/ @symbiote-native/screen-orientation/vue — useScreenOrientation (same name)
|
|
62
|
+
src/svelte/runes/ @symbiote-native/screen-orientation/svelte — useScreenOrientation (same name)
|
|
63
|
+
src/solid/primitives/ @symbiote-native/screen-orientation/solid — createScreenOrientation
|
|
64
|
+
(returns an Accessor; Solid reserves `use*` for consuming existing state)
|
|
61
65
|
src/angular/services/ @symbiote-native/screen-orientation/angular — ScreenOrientationService
|
|
62
66
|
(`.connect()` returns a Signal)
|
|
63
67
|
```
|
|
64
68
|
|
|
65
|
-
Each adapter's hook/composable/service is a thin lifecycle wrapper (seed from
|
|
66
|
-
`getOrientationAsync()`/`getOrientationLockAsync()` calls, subscribe to
|
|
69
|
+
Each adapter's hook/composable/rune/primitive/service is a thin lifecycle wrapper (seed from
|
|
70
|
+
one-shot `getOrientationAsync()`/`getOrientationLockAsync()` calls, subscribe to
|
|
67
71
|
`addOrientationChangeListener`, unsubscribe on unmount) over the same `core` functions — the
|
|
68
|
-
subscription logic is written once and shared by all
|
|
72
|
+
subscription logic is written once and shared by all of them.
|
|
69
73
|
|
|
70
74
|
## Use it
|
|
71
75
|
|
|
72
76
|
```tsx
|
|
73
77
|
// React — examples/expo-react/screens/ScreenOrientationScreen.tsx
|
|
74
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
lockAsync,
|
|
80
|
+
OrientationLock,
|
|
81
|
+
} from '@symbiote-native/screen-orientation';
|
|
75
82
|
import { useScreenOrientation } from '@symbiote-native/screen-orientation/react';
|
|
76
83
|
|
|
77
84
|
function ScreenOrientationScreen() {
|
|
@@ -81,7 +88,10 @@ function ScreenOrientationScreen() {
|
|
|
81
88
|
<>
|
|
82
89
|
<Text>Orientation: {orientation}</Text>
|
|
83
90
|
<Text>Lock: {orientationLock}</Text>
|
|
84
|
-
<Button
|
|
91
|
+
<Button
|
|
92
|
+
title="Lock landscape"
|
|
93
|
+
onPress={() => lockAsync(OrientationLock.LANDSCAPE)}
|
|
94
|
+
/>
|
|
85
95
|
</>
|
|
86
96
|
);
|
|
87
97
|
}
|
|
@@ -91,7 +101,10 @@ function ScreenOrientationScreen() {
|
|
|
91
101
|
<!-- Vue — examples/expo-vue-sfc/screens/ScreenOrientationScreen.vue -->
|
|
92
102
|
<script setup lang="ts">
|
|
93
103
|
import { Text } from '@symbiote-native/vue';
|
|
94
|
-
import {
|
|
104
|
+
import {
|
|
105
|
+
lockAsync,
|
|
106
|
+
OrientationLock,
|
|
107
|
+
} from '@symbiote-native/screen-orientation';
|
|
95
108
|
import { useScreenOrientation } from '@symbiote-native/screen-orientation/vue';
|
|
96
109
|
|
|
97
110
|
const screenOrientation = useScreenOrientation(); // Ref<ScreenOrientationState>
|
|
@@ -102,6 +115,24 @@ const screenOrientation = useScreenOrientation(); // Ref<ScreenOrientationState>
|
|
|
102
115
|
</template>
|
|
103
116
|
```
|
|
104
117
|
|
|
118
|
+
```svelte
|
|
119
|
+
<!-- Svelte — examples/expo-svelte/screens/ScreenOrientationScreen.svelte -->
|
|
120
|
+
<script lang="ts">
|
|
121
|
+
import {
|
|
122
|
+
lockAsync,
|
|
123
|
+
OrientationLock,
|
|
124
|
+
} from '@symbiote-native/screen-orientation';
|
|
125
|
+
import { useScreenOrientation } from '@symbiote-native/screen-orientation/svelte';
|
|
126
|
+
|
|
127
|
+
// The rune hands back a boxed getter, so `.current` is what a `$derived` subscribes to —
|
|
128
|
+
// Svelte's twin of unwrapping Vue's Ref via `.value`.
|
|
129
|
+
const screenOrientation = useScreenOrientation();
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<Text>Orientation: {screenOrientation.current.orientation}</Text>
|
|
133
|
+
<Text>Lock: {screenOrientation.current.orientationLock}</Text>
|
|
134
|
+
```
|
|
135
|
+
|
|
105
136
|
```ts
|
|
106
137
|
// Angular — examples/expo-angular/src/screens/ScreenOrientationScreen.ts
|
|
107
138
|
import { Component, inject } from '@angular/core';
|
|
@@ -118,6 +149,31 @@ export class ScreenOrientationScreen {
|
|
|
118
149
|
}
|
|
119
150
|
```
|
|
120
151
|
|
|
152
|
+
```tsx
|
|
153
|
+
// Solid — the accessor is CALLED; a Solid component body runs once, so a snapshot would freeze.
|
|
154
|
+
import { Text } from '@symbiote-native/solid';
|
|
155
|
+
import {
|
|
156
|
+
lockAsync,
|
|
157
|
+
OrientationLock,
|
|
158
|
+
} from '@symbiote-native/screen-orientation';
|
|
159
|
+
import { createScreenOrientation } from '@symbiote-native/screen-orientation/solid';
|
|
160
|
+
|
|
161
|
+
function ScreenOrientationScreen() {
|
|
162
|
+
const screenOrientation = createScreenOrientation(); // Accessor<ScreenOrientationState>
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<>
|
|
166
|
+
<Text>Orientation: {screenOrientation().orientation}</Text>
|
|
167
|
+
<Text>Lock: {screenOrientation().orientationLock}</Text>
|
|
168
|
+
<Button
|
|
169
|
+
title="Lock landscape"
|
|
170
|
+
onPress={() => lockAsync(OrientationLock.LANDSCAPE)}
|
|
171
|
+
/>
|
|
172
|
+
</>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
121
177
|
## API
|
|
122
178
|
|
|
123
179
|
A mix of stateless async functions and one listener-based subscription
|
|
@@ -143,19 +199,26 @@ Plus `Orientation` (enum: `UNKNOWN`/`PORTRAIT_UP`/`PORTRAIT_DOWN`/`LANDSCAPE_LEF
|
|
|
143
199
|
`OrientationChangeEvent` — ported from upstream's `ScreenOrientation.types.ts`.
|
|
144
200
|
|
|
145
201
|
```ts
|
|
146
|
-
import {
|
|
202
|
+
import {
|
|
203
|
+
getOrientationAsync,
|
|
204
|
+
addOrientationChangeListener,
|
|
205
|
+
} from '@symbiote-native/screen-orientation';
|
|
147
206
|
|
|
148
207
|
// framework-scoped entry points re-export the same free functions, plus a lifecycle
|
|
149
208
|
// hook/composable/service:
|
|
150
209
|
import { useScreenOrientation } from '@symbiote-native/screen-orientation/react';
|
|
151
210
|
import { useScreenOrientation } from '@symbiote-native/screen-orientation/vue';
|
|
211
|
+
import { useScreenOrientation } from '@symbiote-native/screen-orientation/svelte';
|
|
212
|
+
import { createScreenOrientation } from '@symbiote-native/screen-orientation/solid';
|
|
152
213
|
import { ScreenOrientationService } from '@symbiote-native/screen-orientation/angular';
|
|
153
214
|
```
|
|
154
215
|
|
|
155
|
-
`useScreenOrientation` seeds its initial value
|
|
156
|
-
orientationLock: OrientationLock.UNKNOWN }`) from one-shot
|
|
157
|
-
`getOrientationLockAsync()` calls, then subscribes to
|
|
158
|
-
and unsubscribes on unmount.
|
|
216
|
+
`useScreenOrientation` (Solid: `createScreenOrientation`) seeds its initial value
|
|
217
|
+
(`{ orientation: Orientation.UNKNOWN, orientationLock: OrientationLock.UNKNOWN }`) from one-shot
|
|
218
|
+
`getOrientationAsync()`/`getOrientationLockAsync()` calls, then subscribes to
|
|
219
|
+
`addOrientationChangeListener` for updates, and unsubscribes on unmount. The Solid primitive
|
|
220
|
+
returns an `Accessor<ScreenOrientationState>` and subscribes from its body rather than an effect,
|
|
221
|
+
so nothing can slip between the seed and the subscription.
|
|
159
222
|
|
|
160
223
|
**Note (Android):** `expo-screen-orientation` doesn't emit its own `expoDidUpdateDimensions`
|
|
161
224
|
event on Android — the module piggybacks on RN's own `Dimensions.addEventListener('change', ...)`
|
|
@@ -167,7 +230,7 @@ subscribe to the native `expoDidUpdateDimensions` event directly.
|
|
|
167
230
|
No Fabric/Descriptor angle at all — screen-orientation is a pure async-function + `EventEmitter`
|
|
168
231
|
listener surface, never a view. Tests inject a fake native-module object in place of the real
|
|
169
232
|
`requireNativeModule` resolution (`src/core/screen-orientation.test.ts`,
|
|
170
|
-
`src/{react,vue,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
|
|
233
|
+
`src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
|
|
171
234
|
`@symbiote-native/network`/`@symbiote-native/device`/`@symbiote-native/sensors` use — no
|
|
172
235
|
`installFabric()`, no ViewConfig. Native rendering itself is verified on-device — see the parent
|
|
173
236
|
[README](../../README.md).
|
|
@@ -32,7 +32,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
32
|
}
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
|
-
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
|
|
35
|
+
import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
|
|
36
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.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts
|
|
2
2
|
// (sdk-57). Unlike battery, upstream ScreenOrientation throws UnavailabilityError when the
|
|
3
3
|
// native method is absent — same convention as packages/network/src/core/network.ts.
|
|
4
|
-
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
4
|
+
import { Platform, UnavailabilityError, } from 'expo-modules-core';
|
|
5
5
|
import { Dimensions } from 'react-native';
|
|
6
|
-
import { expoScreenOrientation } from './native-module.js';
|
|
6
|
+
import { expoScreenOrientation, } from './native-module.js';
|
|
7
7
|
import { Orientation, OrientationLock, WebOrientationLock, } from './types.js';
|
|
8
8
|
const NATIVE_MODULE_NAME = 'ScreenOrientation';
|
|
9
9
|
let _orientationChangeSubscribers = [];
|
|
@@ -36,7 +36,7 @@ export async function lockPlatformAsync(options) {
|
|
|
36
36
|
if (!expoScreenOrientation.lockPlatformAsync) {
|
|
37
37
|
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'lockPlatformAsync');
|
|
38
38
|
}
|
|
39
|
-
const { screenOrientationConstantAndroid, screenOrientationArrayIOS, screenOrientationLockWeb } = options;
|
|
39
|
+
const { screenOrientationConstantAndroid, screenOrientationArrayIOS, screenOrientationLockWeb, } = options;
|
|
40
40
|
let platformOrientationParam;
|
|
41
41
|
if (Platform.OS === 'android' && screenOrientationConstantAndroid) {
|
|
42
42
|
if (isNaN(screenOrientationConstantAndroid)) {
|
|
@@ -94,7 +94,8 @@ export async function getOrientationLockAsync() {
|
|
|
94
94
|
/** Gets the current orientation lock as a platform-specific value. */
|
|
95
95
|
export async function getPlatformOrientationLockAsync() {
|
|
96
96
|
const platformOrientationLock = await expoScreenOrientation.getPlatformOrientationLockAsync?.();
|
|
97
|
-
if (Platform.OS === 'android' &&
|
|
97
|
+
if (Platform.OS === 'android' &&
|
|
98
|
+
typeof platformOrientationLock === 'number') {
|
|
98
99
|
return { screenOrientationConstantAndroid: platformOrientationLock };
|
|
99
100
|
}
|
|
100
101
|
if (Platform.OS === 'ios' && Array.isArray(platformOrientationLock)) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @symbiote-native/screen-orientation/solid: the Solid entry over the framework-agnostic core —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/solid/src/primitives (never
|
|
3
|
+
// `hooks`/`composables`/`runes`, those are React's, Vue's and Svelte's terms).
|
|
4
|
+
export { createScreenOrientation } from './primitives/create-screen-orientation.js';
|
|
5
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// createScreenOrientation — the Solid twin of React's `useScreenOrientation` hook, Vue's
|
|
2
|
+
// composable and Svelte's rune, over the framework-agnostic core (core/screen-orientation.ts).
|
|
3
|
+
// Seeds with one-shot getOrientationAsync()/getOrientationLockAsync() calls before the first
|
|
4
|
+
// native event fires, mirroring packages/network's createNetworkState.
|
|
5
|
+
//
|
|
6
|
+
// `primitives/` and `create*`, never `hooks/`+`use*`: Solid's ecosystem calls a composable
|
|
7
|
+
// reactive function a PRIMITIVE and reserves `use*` for consuming something that already exists.
|
|
8
|
+
// Full rationale in adapters/solid/src/primitives/create-color-scheme.ts.
|
|
9
|
+
//
|
|
10
|
+
// Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned object
|
|
11
|
+
// would pin the caller to the boot orientation.
|
|
12
|
+
//
|
|
13
|
+
// Outside a component or `createRoot` there is no owner for `onCleanup` — Solid warns and the
|
|
14
|
+
// native listener lives for the process. The accessor still tracks; only the teardown is lost.
|
|
15
|
+
import { createSignal, onCleanup } from 'solid-js';
|
|
16
|
+
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../core/index.js';
|
|
17
|
+
export function createScreenOrientation() {
|
|
18
|
+
const [screenOrientation, setScreenOrientation] = createSignal({
|
|
19
|
+
orientation: Orientation.UNKNOWN,
|
|
20
|
+
orientationLock: OrientationLock.UNKNOWN,
|
|
21
|
+
});
|
|
22
|
+
Promise.all([getOrientationAsync(), getOrientationLockAsync()]).then(([orientation, orientationLock]) => {
|
|
23
|
+
setScreenOrientation({ orientation, orientationLock });
|
|
24
|
+
});
|
|
25
|
+
// Subscribed from the primitive body, not from an effect: React/Vue/Svelte start listening a
|
|
26
|
+
// tick after their seed runs, so a rotation landing in that window is lost. Both statements
|
|
27
|
+
// here run in one synchronous tick and nothing can interleave.
|
|
28
|
+
const subscription = addOrientationChangeListener(event => {
|
|
29
|
+
setScreenOrientation({
|
|
30
|
+
orientation: event.orientationInfo.orientation,
|
|
31
|
+
orientationLock: event.orientationLock,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
onCleanup(() => {
|
|
35
|
+
subscription.remove();
|
|
36
|
+
});
|
|
37
|
+
return screenOrientation;
|
|
38
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
|
|
1
|
+
import { effect, inject, Injectable, Injector, signal, } from '@angular/core';
|
|
2
2
|
import { addOrientationChangeListener, getOrientationAsync, getOrientationLockAsync, Orientation, OrientationLock, } from '../../../core';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
// Angular twin of React's `useScreenOrientation` hook and Vue's `useScreenOrientation`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/screen-orientation.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/screen-orientation.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,GAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,EACvB,WAAW,EACX,eAAe,GAEhB,MAAM,eAAe,CAAC;;AAEvB,uFAAuF;AACvF,cAAc;AACd,EAAE;AACF,6EAA6E;AAC7E,uDAAuD;AAEvD,MAAM,OAAO,wBAAwB;IAClB,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,iBAAiB,GAAG,MAAM,CAAyB;YACvD,WAAW,EAAE,WAAW,CAAC,OAAO;YAChC,eAAe,EAAE,eAAe,CAAC,OAAO;SACzC;8FAAC,CAAC;QAEH,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,OAAO,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,EAAE,uBAAuB,EAAE,CAAC,CAAC,CAAC,IAAI,CAClE,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,EAAE,CACjC,iBAAiB,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAC1D,CAAC;YACF,MAAM,YAAY,GAAG,4BAA4B,CAAC,KAAK,CAAC,EAAE,CACxD,iBAAiB,CAAC,GAAG,CAAC;gBACpB,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,WAAW;gBAC9C,eAAe,EAAE,KAAK,CAAC,eAAe;aACvC,CAAC,CACH,CAAC;YACF,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B,CAAC;QAEF,OAAO,iBAAiB,CAAC,UAAU,EAAE,CAAC;IACxC,CAAC;uGA3BU,wBAAwB;2GAAxB,wBAAwB,cADX,MAAM;;2FACnB,wBAAwB;kBADpC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AASxD,MAAM,mCAAmC,GAAG,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AASxD,MAAM,mCAAmC,GAAG,uBAAuB,CAAC;AA6BpE,MAAM,CAAC,MAAM,qBAAqB,GAChC,mBAAmB,CACjB,mCAAmC,CACpC,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts
|
|
2
2
|
// (sdk-57). Unlike battery, upstream ScreenOrientation throws UnavailabilityError when the
|
|
3
3
|
// native method is absent — same convention as packages/network/src/core/network.ts.
|
|
4
|
-
import { Platform, UnavailabilityError } from 'expo-modules-core';
|
|
4
|
+
import { Platform, UnavailabilityError, } from 'expo-modules-core';
|
|
5
5
|
import { Dimensions } from 'react-native';
|
|
6
|
-
import { expoScreenOrientation } from './native-module';
|
|
6
|
+
import { expoScreenOrientation, } from './native-module';
|
|
7
7
|
import { Orientation, OrientationLock, WebOrientationLock, } from './types';
|
|
8
8
|
const NATIVE_MODULE_NAME = 'ScreenOrientation';
|
|
9
9
|
let _orientationChangeSubscribers = [];
|
|
@@ -36,7 +36,7 @@ export async function lockPlatformAsync(options) {
|
|
|
36
36
|
if (!expoScreenOrientation.lockPlatformAsync) {
|
|
37
37
|
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'lockPlatformAsync');
|
|
38
38
|
}
|
|
39
|
-
const { screenOrientationConstantAndroid, screenOrientationArrayIOS, screenOrientationLockWeb } = options;
|
|
39
|
+
const { screenOrientationConstantAndroid, screenOrientationArrayIOS, screenOrientationLockWeb, } = options;
|
|
40
40
|
let platformOrientationParam;
|
|
41
41
|
if (Platform.OS === 'android' && screenOrientationConstantAndroid) {
|
|
42
42
|
if (isNaN(screenOrientationConstantAndroid)) {
|
|
@@ -94,7 +94,8 @@ export async function getOrientationLockAsync() {
|
|
|
94
94
|
/** Gets the current orientation lock as a platform-specific value. */
|
|
95
95
|
export async function getPlatformOrientationLockAsync() {
|
|
96
96
|
const platformOrientationLock = await expoScreenOrientation.getPlatformOrientationLockAsync?.();
|
|
97
|
-
if (Platform.OS === 'android' &&
|
|
97
|
+
if (Platform.OS === 'android' &&
|
|
98
|
+
typeof platformOrientationLock === 'number') {
|
|
98
99
|
return { screenOrientationConstantAndroid: platformOrientationLock };
|
|
99
100
|
}
|
|
100
101
|
if (Platform.OS === 'ios' && Array.isArray(platformOrientationLock)) {
|
|
@@ -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,
|
|
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,8 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/screen-orientation",
|
|
3
|
-
"version": "0.
|
|
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.",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "expo-screen-orientation wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, 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
|
+
"keywords": [
|
|
7
|
+
"react-native",
|
|
8
|
+
"symbiote-native",
|
|
9
|
+
"expo-screen-orientation",
|
|
10
|
+
"react",
|
|
11
|
+
"vue",
|
|
12
|
+
"svelte",
|
|
13
|
+
"solid",
|
|
14
|
+
"angular",
|
|
15
|
+
"orientation-lock",
|
|
16
|
+
"orientation"
|
|
17
|
+
],
|
|
6
18
|
"repository": {
|
|
7
19
|
"type": "git",
|
|
8
20
|
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
@@ -34,6 +46,10 @@
|
|
|
34
46
|
"types": "./build/svelte/index.d.ts",
|
|
35
47
|
"default": "./build/svelte/index.js"
|
|
36
48
|
},
|
|
49
|
+
"./solid": {
|
|
50
|
+
"types": "./build/solid/index.d.ts",
|
|
51
|
+
"default": "./build/solid/index.js"
|
|
52
|
+
},
|
|
37
53
|
"./angular": {
|
|
38
54
|
"types": "./build-ngc/angular/index.d.ts",
|
|
39
55
|
"react-native": "./build-ngc/angular/index.js",
|
|
@@ -57,17 +73,19 @@
|
|
|
57
73
|
"expo-modules-core": "57.0.5"
|
|
58
74
|
},
|
|
59
75
|
"peerDependencies": {
|
|
60
|
-
"@symbiote-native/angular": ">=0.6.2",
|
|
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",
|
|
65
76
|
"@angular/core": ">=20",
|
|
66
77
|
"@vue/runtime-core": "^3.5.13",
|
|
67
78
|
"react": ">=19.0.0",
|
|
68
79
|
"react-native": ">=0.86",
|
|
80
|
+
"solid-js": ">=1.9.0",
|
|
69
81
|
"svelte": ">=5.56.0",
|
|
70
|
-
"vue": ">=3.5.0"
|
|
82
|
+
"vue": ">=3.5.0",
|
|
83
|
+
"@symbiote-native/angular": "^1.0.0",
|
|
84
|
+
"@symbiote-native/engine": "^0.4.0",
|
|
85
|
+
"@symbiote-native/react": "^1.0.0",
|
|
86
|
+
"@symbiote-native/solid": "^1.0.0",
|
|
87
|
+
"@symbiote-native/svelte": "^1.0.0",
|
|
88
|
+
"@symbiote-native/vue": "^1.0.0"
|
|
71
89
|
},
|
|
72
90
|
"peerDependenciesMeta": {
|
|
73
91
|
"@symbiote-native/angular": {
|
|
@@ -76,6 +94,9 @@
|
|
|
76
94
|
"@symbiote-native/react": {
|
|
77
95
|
"optional": true
|
|
78
96
|
},
|
|
97
|
+
"@symbiote-native/solid": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
79
100
|
"@symbiote-native/svelte": {
|
|
80
101
|
"optional": true
|
|
81
102
|
},
|
|
@@ -91,6 +112,9 @@
|
|
|
91
112
|
"react": {
|
|
92
113
|
"optional": true
|
|
93
114
|
},
|
|
115
|
+
"solid-js": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
94
118
|
"svelte": {
|
|
95
119
|
"optional": true
|
|
96
120
|
},
|
|
@@ -106,14 +130,16 @@
|
|
|
106
130
|
"@types/react": "^19.2.0",
|
|
107
131
|
"@vue/runtime-core": "^3.5.13",
|
|
108
132
|
"react": "19.2.3",
|
|
133
|
+
"solid-js": "^1.9.14",
|
|
109
134
|
"svelte": "^5.56.0",
|
|
110
135
|
"typescript": "~6.0.0",
|
|
111
|
-
"@symbiote-native/angular": "0.
|
|
112
|
-
"@symbiote-native/engine": "0.
|
|
113
|
-
"@symbiote-native/react": "0.
|
|
114
|
-
"@symbiote-native/
|
|
115
|
-
"@symbiote-native/
|
|
116
|
-
"@symbiote-native/
|
|
136
|
+
"@symbiote-native/angular": "1.0.0",
|
|
137
|
+
"@symbiote-native/engine": "0.4.0",
|
|
138
|
+
"@symbiote-native/react": "1.0.0",
|
|
139
|
+
"@symbiote-native/solid": "1.0.0",
|
|
140
|
+
"@symbiote-native/svelte": "1.0.0",
|
|
141
|
+
"@symbiote-native/test-utils": "0.3.0",
|
|
142
|
+
"@symbiote-native/vue": "1.0.0"
|
|
117
143
|
},
|
|
118
144
|
"scripts": {
|
|
119
145
|
"typecheck": "tsc --build",
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
effect,
|
|
3
|
+
inject,
|
|
4
|
+
Injectable,
|
|
5
|
+
Injector,
|
|
6
|
+
signal,
|
|
7
|
+
type Signal,
|
|
8
|
+
} from '@angular/core';
|
|
2
9
|
import {
|
|
3
10
|
addOrientationChangeListener,
|
|
4
11
|
getOrientationAsync,
|
|
@@ -12,7 +12,8 @@ const EXPO_SCREEN_ORIENTATION_MODULE_NAME = 'ExpoScreenOrientation';
|
|
|
12
12
|
// The platform-specific lock param/return shape is a genuine per-platform union (Android sends/
|
|
13
13
|
// returns a numeric constant, iOS an Orientation[], web a WebOrientationLock string) — never `any`,
|
|
14
14
|
// so screen-orientation.ts can narrow it with typeof/Array.isArray instead of casting.
|
|
15
|
-
export type IPlatformOrientationParam =
|
|
15
|
+
export type IPlatformOrientationParam =
|
|
16
|
+
number | Orientation[] | WebOrientationLock;
|
|
16
17
|
|
|
17
18
|
// Every method is optional for the same reason every sibling package's native module type is
|
|
18
19
|
// (network, device, battery) — each call site in screen-orientation.ts checks for the method's
|
|
@@ -20,17 +21,22 @@ export type IPlatformOrientationParam = number | Orientation[] | WebOrientationL
|
|
|
20
21
|
// capability checks rather than assuming the native module implements the whole surface.
|
|
21
22
|
export type INativeScreenOrientationModule = {
|
|
22
23
|
lockAsync?(orientationLock: OrientationLock): Promise<void>;
|
|
23
|
-
lockPlatformAsync?(
|
|
24
|
+
lockPlatformAsync?(
|
|
25
|
+
platformOrientationParam: IPlatformOrientationParam,
|
|
26
|
+
): Promise<void>;
|
|
24
27
|
getOrientationAsync?(): Promise<Orientation>;
|
|
25
28
|
getOrientationLockAsync?(): Promise<OrientationLock>;
|
|
26
29
|
getPlatformOrientationLockAsync?(): Promise<IPlatformOrientationParam>;
|
|
27
|
-
supportsOrientationLockAsync?(
|
|
30
|
+
supportsOrientationLockAsync?(
|
|
31
|
+
orientationLock: OrientationLock,
|
|
32
|
+
): Promise<boolean>;
|
|
28
33
|
addListener(
|
|
29
34
|
eventName: 'expoDidUpdateDimensions',
|
|
30
35
|
listener: (event: OrientationChangeEvent) => void,
|
|
31
36
|
): EventSubscription;
|
|
32
37
|
};
|
|
33
38
|
|
|
34
|
-
export const expoScreenOrientation =
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
export const expoScreenOrientation =
|
|
40
|
+
requireNativeModule<INativeScreenOrientationModule>(
|
|
41
|
+
EXPO_SCREEN_ORIENTATION_MODULE_NAME,
|
|
42
|
+
);
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// Hand-ported from .vendors/expo/packages/expo-screen-orientation/src/ScreenOrientation.ts
|
|
2
2
|
// (sdk-57). Unlike battery, upstream ScreenOrientation throws UnavailabilityError when the
|
|
3
3
|
// native method is absent — same convention as packages/network/src/core/network.ts.
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Platform,
|
|
6
|
+
UnavailabilityError,
|
|
7
|
+
type EventSubscription,
|
|
8
|
+
} from 'expo-modules-core';
|
|
5
9
|
import { Dimensions } from 'react-native';
|
|
6
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
expoScreenOrientation,
|
|
12
|
+
type IPlatformOrientationParam,
|
|
13
|
+
} from './native-module';
|
|
7
14
|
import {
|
|
8
15
|
Orientation,
|
|
9
16
|
OrientationLock,
|
|
@@ -19,7 +26,9 @@ let _orientationChangeSubscribers: EventSubscription[] = [];
|
|
|
19
26
|
let _lastOrientationLock: OrientationLock = OrientationLock.UNKNOWN;
|
|
20
27
|
|
|
21
28
|
/** Locks the screen to the given orientation. */
|
|
22
|
-
export async function lockAsync(
|
|
29
|
+
export async function lockAsync(
|
|
30
|
+
orientationLock: OrientationLock,
|
|
31
|
+
): Promise<void> {
|
|
23
32
|
if (!expoScreenOrientation.lockAsync) {
|
|
24
33
|
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'lockAsync');
|
|
25
34
|
}
|
|
@@ -43,12 +52,17 @@ export async function lockAsync(orientationLock: OrientationLock): Promise<void>
|
|
|
43
52
|
// Ported verbatim for parity; do NOT fix without recording a deliberate divergence.
|
|
44
53
|
/** Locks the screen to a platform-specific orientation param — Android constant, iOS
|
|
45
54
|
* orientation array, or web `WebOrientationLock`. */
|
|
46
|
-
export async function lockPlatformAsync(
|
|
55
|
+
export async function lockPlatformAsync(
|
|
56
|
+
options: PlatformOrientationInfo,
|
|
57
|
+
): Promise<void> {
|
|
47
58
|
if (!expoScreenOrientation.lockPlatformAsync) {
|
|
48
59
|
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'lockPlatformAsync');
|
|
49
60
|
}
|
|
50
|
-
const {
|
|
51
|
-
|
|
61
|
+
const {
|
|
62
|
+
screenOrientationConstantAndroid,
|
|
63
|
+
screenOrientationArrayIOS,
|
|
64
|
+
screenOrientationLockWeb,
|
|
65
|
+
} = options;
|
|
52
66
|
let platformOrientationParam: IPlatformOrientationParam | undefined;
|
|
53
67
|
if (Platform.OS === 'android' && screenOrientationConstantAndroid) {
|
|
54
68
|
if (isNaN(screenOrientationConstantAndroid)) {
|
|
@@ -75,12 +89,16 @@ export async function lockPlatformAsync(options: PlatformOrientationInfo): Promi
|
|
|
75
89
|
} else if (Platform.OS === 'web' && screenOrientationLockWeb) {
|
|
76
90
|
const webOrientationLocks = Object.values(WebOrientationLock);
|
|
77
91
|
if (!webOrientationLocks.includes(screenOrientationLockWeb)) {
|
|
78
|
-
throw new TypeError(
|
|
92
|
+
throw new TypeError(
|
|
93
|
+
`Invalid Web Orientation Lock: ${screenOrientationLockWeb}`,
|
|
94
|
+
);
|
|
79
95
|
}
|
|
80
96
|
platformOrientationParam = screenOrientationLockWeb;
|
|
81
97
|
}
|
|
82
98
|
if (!platformOrientationParam) {
|
|
83
|
-
throw new TypeError(
|
|
99
|
+
throw new TypeError(
|
|
100
|
+
'lockPlatformAsync cannot be called with undefined option properties',
|
|
101
|
+
);
|
|
84
102
|
}
|
|
85
103
|
await expoScreenOrientation.lockPlatformAsync(platformOrientationParam);
|
|
86
104
|
_lastOrientationLock = OrientationLock.OTHER;
|
|
@@ -113,8 +131,12 @@ export async function getOrientationLockAsync(): Promise<OrientationLock> {
|
|
|
113
131
|
|
|
114
132
|
/** Gets the current orientation lock as a platform-specific value. */
|
|
115
133
|
export async function getPlatformOrientationLockAsync(): Promise<PlatformOrientationInfo> {
|
|
116
|
-
const platformOrientationLock =
|
|
117
|
-
|
|
134
|
+
const platformOrientationLock =
|
|
135
|
+
await expoScreenOrientation.getPlatformOrientationLockAsync?.();
|
|
136
|
+
if (
|
|
137
|
+
Platform.OS === 'android' &&
|
|
138
|
+
typeof platformOrientationLock === 'number'
|
|
139
|
+
) {
|
|
118
140
|
return { screenOrientationConstantAndroid: platformOrientationLock };
|
|
119
141
|
}
|
|
120
142
|
if (Platform.OS === 'ios' && Array.isArray(platformOrientationLock)) {
|
|
@@ -131,7 +153,10 @@ export async function supportsOrientationLockAsync(
|
|
|
131
153
|
orientationLock: OrientationLock,
|
|
132
154
|
): Promise<boolean> {
|
|
133
155
|
if (!expoScreenOrientation.supportsOrientationLockAsync) {
|
|
134
|
-
throw new UnavailabilityError(
|
|
156
|
+
throw new UnavailabilityError(
|
|
157
|
+
NATIVE_MODULE_NAME,
|
|
158
|
+
'supportsOrientationLockAsync',
|
|
159
|
+
);
|
|
135
160
|
}
|
|
136
161
|
const orientationLocks = Object.values(OrientationLock);
|
|
137
162
|
if (!orientationLocks.includes(orientationLock)) {
|
|
@@ -145,7 +170,9 @@ export function addOrientationChangeListener(
|
|
|
145
170
|
listener: OrientationChangeListener,
|
|
146
171
|
): EventSubscription {
|
|
147
172
|
if (typeof listener !== 'function') {
|
|
148
|
-
throw new TypeError(
|
|
173
|
+
throw new TypeError(
|
|
174
|
+
`addOrientationChangeListener cannot be called with ${listener}`,
|
|
175
|
+
);
|
|
149
176
|
}
|
|
150
177
|
const subscription = createDidUpdateDimensionsSubscription(listener);
|
|
151
178
|
_orientationChangeSubscribers.push(subscription);
|
|
@@ -162,12 +189,16 @@ export function removeOrientationChangeListeners(): void {
|
|
|
162
189
|
}
|
|
163
190
|
|
|
164
191
|
/** Removes a single orientation-change listener's subscription. */
|
|
165
|
-
export function removeOrientationChangeListener(
|
|
192
|
+
export function removeOrientationChangeListener(
|
|
193
|
+
subscription: EventSubscription,
|
|
194
|
+
): void {
|
|
166
195
|
if (!subscription || !subscription.remove) {
|
|
167
196
|
throw new TypeError('Must pass in a valid subscription');
|
|
168
197
|
}
|
|
169
198
|
subscription.remove();
|
|
170
|
-
_orientationChangeSubscribers = _orientationChangeSubscribers.filter(
|
|
199
|
+
_orientationChangeSubscribers = _orientationChangeSubscribers.filter(
|
|
200
|
+
sub => sub !== subscription,
|
|
201
|
+
);
|
|
171
202
|
}
|
|
172
203
|
|
|
173
204
|
// IMPORTANT: Android doesn't emit `expoDidUpdateDimensions` — RN's own Dimensions module does,
|
|
@@ -12,14 +12,16 @@ import {
|
|
|
12
12
|
} from '../../../core';
|
|
13
13
|
|
|
14
14
|
export function useScreenOrientation(): ScreenOrientationState {
|
|
15
|
-
const [screenOrientation, setScreenOrientation] =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const [screenOrientation, setScreenOrientation] =
|
|
16
|
+
useState<ScreenOrientationState>({
|
|
17
|
+
orientation: Orientation.UNKNOWN,
|
|
18
|
+
orientationLock: OrientationLock.UNKNOWN,
|
|
19
|
+
});
|
|
19
20
|
|
|
20
21
|
useEffect(() => {
|
|
21
22
|
Promise.all([getOrientationAsync(), getOrientationLockAsync()]).then(
|
|
22
|
-
([orientation, orientationLock]) =>
|
|
23
|
+
([orientation, orientationLock]) =>
|
|
24
|
+
setScreenOrientation({ orientation, orientationLock }),
|
|
23
25
|
);
|
|
24
26
|
const subscription = addOrientationChangeListener(event =>
|
|
25
27
|
setScreenOrientation({
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @symbiote-native/screen-orientation/solid: the Solid entry over the framework-agnostic core —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/solid/src/primitives (never
|
|
3
|
+
// `hooks`/`composables`/`runes`, those are React's, Vue's and Svelte's terms).
|
|
4
|
+
|
|
5
|
+
export { createScreenOrientation } from './primitives/create-screen-orientation';
|
|
6
|
+
export * from '../core';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// createScreenOrientation — the Solid twin of React's `useScreenOrientation` hook, Vue's
|
|
2
|
+
// composable and Svelte's rune, over the framework-agnostic core (core/screen-orientation.ts).
|
|
3
|
+
// Seeds with one-shot getOrientationAsync()/getOrientationLockAsync() calls before the first
|
|
4
|
+
// native event fires, mirroring packages/network's createNetworkState.
|
|
5
|
+
//
|
|
6
|
+
// `primitives/` and `create*`, never `hooks/`+`use*`: Solid's ecosystem calls a composable
|
|
7
|
+
// reactive function a PRIMITIVE and reserves `use*` for consuming something that already exists.
|
|
8
|
+
// Full rationale in adapters/solid/src/primitives/create-color-scheme.ts.
|
|
9
|
+
//
|
|
10
|
+
// Returns an ACCESSOR, never a snapshot: a Solid component body runs ONCE, so a returned object
|
|
11
|
+
// would pin the caller to the boot orientation.
|
|
12
|
+
//
|
|
13
|
+
// Outside a component or `createRoot` there is no owner for `onCleanup` — Solid warns and the
|
|
14
|
+
// native listener lives for the process. The accessor still tracks; only the teardown is lost.
|
|
15
|
+
|
|
16
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
17
|
+
import {
|
|
18
|
+
addOrientationChangeListener,
|
|
19
|
+
getOrientationAsync,
|
|
20
|
+
getOrientationLockAsync,
|
|
21
|
+
Orientation,
|
|
22
|
+
OrientationLock,
|
|
23
|
+
type EventSubscription,
|
|
24
|
+
type ScreenOrientationState,
|
|
25
|
+
} from '../../core';
|
|
26
|
+
|
|
27
|
+
export function createScreenOrientation(): Accessor<ScreenOrientationState> {
|
|
28
|
+
const [screenOrientation, setScreenOrientation] =
|
|
29
|
+
createSignal<ScreenOrientationState>({
|
|
30
|
+
orientation: Orientation.UNKNOWN,
|
|
31
|
+
orientationLock: OrientationLock.UNKNOWN,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
Promise.all([getOrientationAsync(), getOrientationLockAsync()]).then(
|
|
35
|
+
([orientation, orientationLock]) => {
|
|
36
|
+
setScreenOrientation({ orientation, orientationLock });
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Subscribed from the primitive body, not from an effect: React/Vue/Svelte start listening a
|
|
41
|
+
// tick after their seed runs, so a rotation landing in that window is lost. Both statements
|
|
42
|
+
// here run in one synchronous tick and nothing can interleave.
|
|
43
|
+
const subscription: EventSubscription = addOrientationChangeListener(
|
|
44
|
+
event => {
|
|
45
|
+
setScreenOrientation({
|
|
46
|
+
orientation: event.orientationInfo.orientation,
|
|
47
|
+
orientationLock: event.orientationLock,
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
onCleanup(() => {
|
|
53
|
+
subscription.remove();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return screenOrientation;
|
|
57
|
+
}
|
|
@@ -17,7 +17,9 @@ import {
|
|
|
17
17
|
type ScreenOrientationState,
|
|
18
18
|
} from '../../core';
|
|
19
19
|
|
|
20
|
-
export function useScreenOrientation(): {
|
|
20
|
+
export function useScreenOrientation(): {
|
|
21
|
+
readonly current: ScreenOrientationState;
|
|
22
|
+
} {
|
|
21
23
|
let screenOrientation = $state<ScreenOrientationState>({
|
|
22
24
|
orientation: Orientation.UNKNOWN,
|
|
23
25
|
orientationLock: OrientationLock.UNKNOWN,
|
|
@@ -31,12 +33,14 @@ export function useScreenOrientation(): { readonly current: ScreenOrientationSta
|
|
|
31
33
|
screenOrientation = { orientation, orientationLock };
|
|
32
34
|
},
|
|
33
35
|
);
|
|
34
|
-
const subscription: EventSubscription = addOrientationChangeListener(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const subscription: EventSubscription = addOrientationChangeListener(
|
|
37
|
+
event => {
|
|
38
|
+
screenOrientation = {
|
|
39
|
+
orientation: event.orientationInfo.orientation,
|
|
40
|
+
orientationLock: event.orientationLock,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
);
|
|
40
44
|
return () => subscription.remove();
|
|
41
45
|
});
|
|
42
46
|
|