@desklink/react-native 0.3.1 → 0.4.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 +22 -9
- package/package.json +1 -1
- package/src/protocol.ts +14 -1
- package/src/useDesktopSession.ts +9 -6
package/README.md
CHANGED
|
@@ -58,12 +58,12 @@ changes, and trackpad presses reach the desktop as touches.
|
|
|
58
58
|
## Use
|
|
59
59
|
|
|
60
60
|
```tsx
|
|
61
|
-
import { DesktopView, useDesktopSession
|
|
61
|
+
import { DesktopView, useDesktopSession } from '@desklink/react-native';
|
|
62
62
|
|
|
63
63
|
const desktop = useDesktopSession({
|
|
64
64
|
authorize: async () => ({
|
|
65
65
|
signaling, // your authenticated channel to the host
|
|
66
|
-
session: {
|
|
66
|
+
session: {},
|
|
67
67
|
}),
|
|
68
68
|
});
|
|
69
69
|
|
|
@@ -78,6 +78,13 @@ desktop.setOrientation('landscape'); // Android only; iOS apps configure suppo
|
|
|
78
78
|
await desktop.pasteLocalToRemote(await Clipboard.getStringAsync());
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
Pairing is the only trust boundary. `authorize` is the app's pairing check: it
|
|
82
|
+
returns a channel to a paired computer or throws, and it runs again on every
|
|
83
|
+
reconnect, so a revoked pairing cannot reopen. A paired session has view,
|
|
84
|
+
input and clipboard; there are no in-app grants, and `session.permissions` is
|
|
85
|
+
ignored. Only the operating system's own consent (screen recording,
|
|
86
|
+
accessibility, a screen-sharing prompt) still applies on the computer.
|
|
87
|
+
|
|
81
88
|
A screen that only decides *whether* to offer a desktop does not need the
|
|
82
89
|
session: import the flag from its own entry, which is a constant on web and a
|
|
83
90
|
check for the platform module elsewhere, so the hook and the view stay out of
|
|
@@ -98,7 +105,7 @@ engine only produces frames on change.
|
|
|
98
105
|
Keep the encoded picture inside a 1920×1080 box:
|
|
99
106
|
|
|
100
107
|
```tsx
|
|
101
|
-
session: {
|
|
108
|
+
session: { maxWidth: 1920, maxHeight: 1080 },
|
|
102
109
|
```
|
|
103
110
|
|
|
104
111
|
The engine never upscales, so a smaller desktop is sent at its own size and a
|
|
@@ -212,11 +219,13 @@ heat and battery.
|
|
|
212
219
|
network is still down. Renegotiation transients from a restart the session
|
|
213
220
|
asked for itself are expected, not a new outage: they neither flip the
|
|
214
221
|
status nor trigger another restart for a short grace window.
|
|
215
|
-
- **
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
a
|
|
222
|
+
- **Input starts disarmed.** This is a local arm against accidental touches,
|
|
223
|
+
not a permission: the session already has input. `setInputEnabled(true)` arms
|
|
224
|
+
pointer, keyboard and clipboard input; `setInputEnabled(false)` blocks new
|
|
225
|
+
input, releases held keys and buttons, and resets pending gestures. The app
|
|
226
|
+
decides when to arm it after a deliberate action and must disarm it on
|
|
227
|
+
background or lost readiness; a clipboard write already in flight may still
|
|
228
|
+
finish.
|
|
220
229
|
- **Released state.** The app disables input on background and unmount;
|
|
221
230
|
session close and a lost control channel release what the desktop was holding.
|
|
222
231
|
- **Explicit clipboard.** Two methods, called on a user action while control is
|
|
@@ -278,7 +287,11 @@ What the consuming app — not this package — must get right before review.
|
|
|
278
287
|
|
|
279
288
|
`example/` is the smallest app that shows a desktop: a native (non-Expo Go)
|
|
280
289
|
build with `react-native-webrtc`, connecting to `desklink-host bridge` with the
|
|
281
|
-
URL it is launched with.
|
|
290
|
+
URL it is launched with. Its status line shows plain messages: `Connected`
|
|
291
|
+
once a frame is presented, `Can’t reach your desktop. Reconnecting…` while
|
|
292
|
+
retrying, and `Your desktop ended this session` after revocation. It never
|
|
293
|
+
displays the bridge URL, pairing token, raw failure text or frame metrics.
|
|
294
|
+
`test/ios-flow.mjs` builds it for the iOS simulator on
|
|
282
295
|
a Mac over ssh, serves a private Xvfb desktop from this machine through the
|
|
283
296
|
bridge, and checks that the first frame is presented, that the answer puts
|
|
284
297
|
H.264 first with NACK when the host offers it (VP9 otherwise; both descriptions
|
package/package.json
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
export const PROTOCOL_VERSION = 3;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Pairing is the only trust boundary: a paired session always has
|
|
21
|
+
* view, input and clipboard, so there is nothing to ask for. Kept so 0.3 code
|
|
22
|
+
* compiles; removed at 1.0.
|
|
23
|
+
*/
|
|
19
24
|
export type Permission = 'view' | 'control' | 'clipboard';
|
|
20
25
|
|
|
21
26
|
/**
|
|
@@ -42,7 +47,8 @@ export interface SurfaceGeometry {
|
|
|
42
47
|
|
|
43
48
|
export interface SessionOpenRequest {
|
|
44
49
|
cursor?: 'embedded' | 'hidden';
|
|
45
|
-
|
|
50
|
+
/** @deprecated Ignored: a paired session always has view, input and clipboard. */
|
|
51
|
+
permissions?: Permission[];
|
|
46
52
|
maxWidth?: number;
|
|
47
53
|
maxHeight?: number;
|
|
48
54
|
bitrateKbps?: number;
|
|
@@ -127,6 +133,7 @@ export type SessionStatus =
|
|
|
127
133
|
| 'failed';
|
|
128
134
|
|
|
129
135
|
export type SessionFailure =
|
|
136
|
+
/** The app's `authorize()` refused, or the host did: not paired, or the pairing was revoked. */
|
|
130
137
|
| { code: 'permission'; message: string }
|
|
131
138
|
/** Nobody approved the desktop's own screen-sharing prompt in time. */
|
|
132
139
|
| { code: 'consent'; message: string }
|
|
@@ -146,6 +153,12 @@ export interface SessionSnapshot {
|
|
|
146
153
|
geometry: SurfaceGeometry | null;
|
|
147
154
|
/** True once an authorized, current-generation frame has actually rendered. */
|
|
148
155
|
presented: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* `message` is free text from the app's `authorize()`, the host or the
|
|
158
|
+
* engine and may contain a bridge URL or pairing token. Never display it
|
|
159
|
+
* to people; redact sensitive data before logging it. Choose user-facing
|
|
160
|
+
* text from the session state and `code` instead.
|
|
161
|
+
*/
|
|
149
162
|
failure: SessionFailure | null;
|
|
150
163
|
/** Redacted diagnostics: codec, route, counters. Never identities. */
|
|
151
164
|
diagnostics: Record<string, string | number | boolean>;
|
package/src/useDesktopSession.ts
CHANGED
|
@@ -172,10 +172,10 @@ async function loadPlatform(): Promise<boolean> {
|
|
|
172
172
|
|
|
173
173
|
export interface DesktopSessionOptions {
|
|
174
174
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
175
|
+
* The app's pairing check: return the authenticated channel to the host
|
|
176
|
+
* engine of a paired computer, or throw. Pairing is the only trust
|
|
177
|
+
* boundary, so a paired session has view, input and clipboard. Called again
|
|
178
|
+
* on every reconnect, so a revoked pairing cannot reopen.
|
|
179
179
|
*/
|
|
180
180
|
authorize: () => Promise<{ signaling: Signaling; session: SessionOpenRequest }>;
|
|
181
181
|
onStateChange?: (snapshot: SessionSnapshot) => void;
|
|
@@ -717,7 +717,10 @@ export function useDesktopSession(options: DesktopSessionOptions): DesktopSessio
|
|
|
717
717
|
let openedResult: SessionOpenResult;
|
|
718
718
|
try {
|
|
719
719
|
openedResult = await authorization.signaling.request<SessionOpenResult>('session.open', {
|
|
720
|
-
|
|
720
|
+
// Ignored by 0.4+ engines, whatever the app asked for. A 0.3
|
|
721
|
+
// engine refuses an open without `view`, so the full set stays
|
|
722
|
+
// on the wire until 0.3 hosts leave support.
|
|
723
|
+
permissions: ['view', 'control', 'clipboard'],
|
|
721
724
|
max_width: authorization.session.maxWidth,
|
|
722
725
|
...(authorization.session.cursor === undefined ? {} : { cursor: authorization.session.cursor }),
|
|
723
726
|
max_height: authorization.session.maxHeight,
|
|
@@ -1106,5 +1109,5 @@ function randomId(): string {
|
|
|
1106
1109
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
1107
1110
|
}
|
|
1108
1111
|
|
|
1109
|
-
/**
|
|
1112
|
+
/** @deprecated Ignored: a paired session always has view, input and clipboard. Removed at 1.0. */
|
|
1110
1113
|
export const CONTROL_PERMISSIONS: Permission[] = ['view', 'control', 'clipboard'];
|