@xorgate/react-native 0.2.0 → 0.3.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/CHANGELOG.md +64 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/replay-video.d.ts +0 -14
- package/dist/replay-video.d.ts.map +1 -1
- package/dist/replay-video.js +33 -2
- package/dist/replay-video.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +28 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,16 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
Tracks `@xorgate/react` 0.3.0 (live scope) and `@xorgate/sdk` 0.7.0 (device
|
|
6
|
+
transfer). No native change: the same `dist`, plus re-exports.
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **`useLiveScope()` and `useDeviceScope(deviceId)`**, re-exported unchanged
|
|
11
|
+
from `@xorgate/react`. A device can be transferred to another workspace or
|
|
12
|
+
organization while a viewer is open; the vended live credential is cached for
|
|
13
|
+
up to ~50 minutes, and neither plane fails loudly when it goes stale —
|
|
14
|
+
telemetry simply stops arriving and video keeps flowing until the next
|
|
15
|
+
reconnect. `useDeviceScope` turns that into a typed `DEVICE_OUT_OF_SCOPE`,
|
|
16
|
+
re-vending once first. `useLiveScope().invalidate()` makes every open live
|
|
17
|
+
consumer re-resolve after you transfer a device yourself.
|
|
18
|
+
|
|
19
|
+
**This matters more on a phone than on the web.** A backgrounded app resumes
|
|
20
|
+
onto the same cached credential, and `appStateWake` nudges the live planes
|
|
21
|
+
back up — straight onto the stale scope. The scope guard is what makes the
|
|
22
|
+
resume honest.
|
|
23
|
+
|
|
24
|
+
- The transfer vocabulary from `@xorgate/sdk` (`TransferSummary`,
|
|
25
|
+
`TransferPreview`, `TransferOffer`, `TransferOfferPreview`,
|
|
26
|
+
`TransferAdoption`, `ScopeAttributeResult` and the rest), so a screen and a
|
|
27
|
+
server route pass the same objects around.
|
|
28
|
+
|
|
29
|
+
### Unchanged, and checked
|
|
30
|
+
|
|
31
|
+
- **Replay carries no tenancy assumption.** Segment playback runs on presigned
|
|
32
|
+
URLs minted per manifest and refreshed from `manifest.urlExpiresAt`; nothing
|
|
33
|
+
in `replay-engine.ts` caches an organization or workspace id, so a transfer
|
|
34
|
+
cannot strand a replay. (Replay does become unreadable to the OLD owner once
|
|
35
|
+
the device moves — media is device-keyed and travels with it — but that shows
|
|
36
|
+
up as a plain 404 from the manifest route, not as a stale URL.)
|
|
37
|
+
|
|
38
|
+
## 0.2.1
|
|
39
|
+
|
|
40
|
+
- **Fix: a replay lane froze for a whole segment at a time on Android.** The
|
|
41
|
+
seam is an opacity flip between two overlapping views, and `expo-video` draws
|
|
42
|
+
into a `SurfaceView` by default — a layer the system composites rather than
|
|
43
|
+
one the view hierarchy draws, so `opacity: 0` does not hide it and `zIndex`
|
|
44
|
+
does not order it against its sibling. The hidden PRELOAD therefore won: it
|
|
45
|
+
parked on the first frame of the next segment, that still frame covered the
|
|
46
|
+
player that was actually running, and the picture held for the whole segment
|
|
47
|
+
while the clock, the map and the readouts carried on. It looked like the
|
|
48
|
+
engine had stalled; the engine was never involved. `ReplayVideo` now renders
|
|
49
|
+
into a `TextureView` on Android (`surfaceType`), which is an ordinary view,
|
|
50
|
+
so alpha and z-order mean what they say. iOS is untouched — `AVPlayerLayer`
|
|
51
|
+
is a real layer and the prop is Android's alone.
|
|
52
|
+
|
|
53
|
+
Measured on an API 36 emulator against a six-segment recording, sampling the
|
|
54
|
+
lane every ~1.5 s for three minutes: **11 distinct frames out of 80 before,
|
|
55
|
+
79 out of 80 after**, over three segment boundaries either way. Each freeze
|
|
56
|
+
began within ~1.5 s of the hidden player reporting ready, and the LAST
|
|
57
|
+
segment of a replay always played correctly — by then there is nothing left
|
|
58
|
+
to preload on top of it. The engine's own trace was clean throughout, every
|
|
59
|
+
boundary a 0-131 ms seam.
|
|
60
|
+
|
|
3
61
|
## 0.2.0
|
|
4
62
|
|
|
5
63
|
Replay: the recorded-media player, over `expo-video`.
|
|
6
64
|
|
|
7
|
-
-
|
|
8
|
-
takes the player CORE rather than the browser wrapper —
|
|
9
|
-
React Native player drive replay telemetry at all. The
|
|
10
|
-
`^0.2.0-next.1
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
player)` will not typecheck. Publish `@xorgate/react` 0.2.1 first.
|
|
65
|
+
- **`@xorgate/react` `^0.2.1`**, up from `^0.2.0-next.1`. 0.2.1 is where
|
|
66
|
+
`useReplayTelemetry` takes the player CORE rather than the browser wrapper —
|
|
67
|
+
the change that lets a React Native player drive replay telemetry at all. The
|
|
68
|
+
0.2.0 tarball shipped with the looser `^0.2.0-next.1`, which resolves to 0.2.1
|
|
69
|
+
on any fresh install and is wrong only for a lockfile pinned at the
|
|
70
|
+
pre-release; the range was tightened as soon as 0.2.1 existed to be named.
|
|
14
71
|
- **`expo-video` is a new required peer.** It is the native player; there is no
|
|
15
72
|
way to play a recorded segment without it, and an optional peer whose absence
|
|
16
73
|
fails deep inside a lane is worse than one line of install (the same call
|
package/dist/index.d.ts
CHANGED
|
@@ -27,5 +27,5 @@ export { LiveVideo, type LiveVideoProps } from "./live-video.js";
|
|
|
27
27
|
export { ExpoVideoReplayEngine, type ExpoVideoReplayEngineOptions, } from "./replay-engine.js";
|
|
28
28
|
export { useReplayPlayer, type UseReplayPlayer, type UseReplayPlayerNativeOptions, type ReplayLaneMedia, type ReplayLaneState, type ReplayLaneStatus, type UseReplayPlayerOptions, } from "./use-replay-player.js";
|
|
29
29
|
export { ReplayVideo, type ReplayVideoProps } from "./replay-video.js";
|
|
30
|
-
export { XorgateProvider, useXorgate, useXorgateTenancy, DEFAULT_BASE_URL, type XorgateProviderProps, type XorgateConfig, type XorgateAuth, type FirstPartyAuth, type SessionTokenAuth, type ApiKeyAuth, type LiveCredentialsAuth, type LiveCredentials, type LiveUnavailableReason, type Awaitable, type XorgatePlatform, XorgateError, isXorgateError, type Device, type DeviceModel, type LatestByMetric, type LatestReading, type MediaSession, type Me, type MetricName, type Organization, type PageMeta, type RecordingRun, type ReplayGap, type ReplayManifest, type ReplaySegment, type ReplaySession, type StreamKey, type TelemetryHistory, type TelemetryReading, type VideoChannel, type Workspace, type XorgateClient, useMe, useOrganizations, useWorkspaces, useDevices, useDevice, useDeviceModel, useTelemetryLatest, useTelemetryHistory, useVideoChannels, useRecordingRuns, useSessions, type QueryResult, type QueryOptions, type UseDevicesParams, type UseDevicesResult, type UseTelemetryHistoryParams, type UseSessionsParams, type UseRunsResult, type UseSessionsResult, useLiveTelemetry, useLivePlane, useLiveCredentials, parseTelemetryPayload, presignIotWssUrl, type UseLiveTelemetry, type UseLiveTelemetryOptions, type LiveStatus, type TelemetryPoint, type TelemetrySnapshot, type TelemetryFeedDeps, type MqttLikeClient, type MqttConnectionSpec, type ResolvedLiveCredentials, type ParsedTelemetryPayload, type TelemetryRecordingStatus, type TelemetryMediaStatus, type TelemetryStreamStatus, type LiveBlockPayload, useLiveBlock, resolveLiveBlock, liveBlockElapsedMs, LIVE_BLOCK_STALE_MS, type LiveBlockReason, type LiveBlockOpenReason, type LiveBlockState, type ResolveLiveBlockInput, useLiveVideoSession, type UseLiveVideoSession, type UseLiveVideoSessionOptions, type LiveVideoStatus, type LiveVideoStats, type WebRtcPlatform, type PeerConnectionLike, type SignalingLike, type TimerHost, useReplayManifest, useReplayPlayerCore, useReplayTelemetry, buildTimeline, segmentEnd, segmentAt, hasCoverageAt, gapAt, nextSegmentAfter, prevBoundary, nextBoundary, clampTs, buildLanes, buildClockTimeline, segmentUrlKey, ReplayClock, REPLAY_RATES, parseSegmentMediaInfo, seriesFromReadings, floorIndex, latestWithin, metricGroup, stalenessMs, overviewStalenessMs, chooseIntervalSeconds, windowBoundsFor, windowNeedsRefetch, buildTrace, traceLines, traveledLines, positionAt, GROUP_STALENESS_MS, DEFAULT_STALENESS_MS, WINDOW_SPAN_MS, WINDOW_MIN_SPAN_MS, type UseReplayManifestParams, type UseReplayManifestResult, type UseReplayPlayerCore, type UseReplayTelemetry, type UseReplayTelemetryOptions, type ReplayEngine, type ReplayEngineOptions, type ReplayEngineFactory, type ReplayTimeline, type ReplayLane, type LaneSegment, type ReplayClockState, type ReplayRate, type PacerCandidate, type GapSkipEvent, type SegmentMediaInfo, type MetricSeries, type GpsTrace, type WindowBounds, type PositionResolution, } from "@xorgate/react";
|
|
30
|
+
export { XorgateProvider, useXorgate, useXorgateTenancy, DEFAULT_BASE_URL, type XorgateProviderProps, type XorgateConfig, type XorgateAuth, type FirstPartyAuth, type SessionTokenAuth, type ApiKeyAuth, type LiveCredentialsAuth, type LiveCredentials, type LiveUnavailableReason, type Awaitable, type XorgatePlatform, XorgateError, isXorgateError, type AcceptedTransferOffer, type BulkTransferItem, type CreatedTransferOffer, type Device, type DeviceModel, type LatestByMetric, type LatestReading, type MediaSession, type Me, type MetricName, type Organization, type PageMeta, type RecordingRun, type ReplayGap, type ReplayManifest, type ReplaySegment, type ReplaySession, type StreamKey, type TelemetryHistory, type TelemetryReading, type TransferAdoption, type TransferBlocker, type TransferBlockerCode, type TransferDeviceInput, type TransferOffer, type TransferOfferPreview, type TransferOfferStatus, type TransferPreview, type TransferResult, type TransferSummary, type TransferTenancy, type ScopeAttributeResult, type VideoChannel, type Workspace, type XorgateClient, useMe, useOrganizations, useWorkspaces, useDevices, useDevice, useDeviceModel, useTelemetryLatest, useTelemetryHistory, useVideoChannels, useRecordingRuns, useSessions, type QueryResult, type QueryOptions, type UseDevicesParams, type UseDevicesResult, type UseTelemetryHistoryParams, type UseSessionsParams, type UseRunsResult, type UseSessionsResult, useLiveTelemetry, useLivePlane, useLiveCredentials, useLiveScope, useDeviceScope, type UseLiveScope, type UseDeviceScope, type UseDeviceScopeOptions, type DeviceScopeStatus, type LiveScope, parseTelemetryPayload, presignIotWssUrl, type UseLiveTelemetry, type UseLiveTelemetryOptions, type LiveStatus, type TelemetryPoint, type TelemetrySnapshot, type TelemetryFeedDeps, type MqttLikeClient, type MqttConnectionSpec, type ResolvedLiveCredentials, type ParsedTelemetryPayload, type TelemetryRecordingStatus, type TelemetryMediaStatus, type TelemetryStreamStatus, type LiveBlockPayload, useLiveBlock, resolveLiveBlock, liveBlockElapsedMs, LIVE_BLOCK_STALE_MS, type LiveBlockReason, type LiveBlockOpenReason, type LiveBlockState, type ResolveLiveBlockInput, useLiveVideoSession, type UseLiveVideoSession, type UseLiveVideoSessionOptions, type LiveVideoStatus, type LiveVideoStats, type WebRtcPlatform, type PeerConnectionLike, type SignalingLike, type TimerHost, useReplayManifest, useReplayPlayerCore, useReplayTelemetry, buildTimeline, segmentEnd, segmentAt, hasCoverageAt, gapAt, nextSegmentAfter, prevBoundary, nextBoundary, clampTs, buildLanes, buildClockTimeline, segmentUrlKey, ReplayClock, REPLAY_RATES, parseSegmentMediaInfo, seriesFromReadings, floorIndex, latestWithin, metricGroup, stalenessMs, overviewStalenessMs, chooseIntervalSeconds, windowBoundsFor, windowNeedsRefetch, buildTrace, traceLines, traveledLines, positionAt, GROUP_STALENESS_MS, DEFAULT_STALENESS_MS, WINDOW_SPAN_MS, WINDOW_MIN_SPAN_MS, type UseReplayManifestParams, type UseReplayManifestResult, type UseReplayPlayerCore, type UseReplayTelemetry, type UseReplayTelemetryOptions, type ReplayEngine, type ReplayEngineOptions, type ReplayEngineFactory, type ReplayTimeline, type ReplayLane, type LaneSegment, type ReplayClockState, type ReplayRate, type PacerCandidate, type GapSkipEvent, type SegmentMediaInfo, type MetricSeries, type GpsTrace, type WindowBounds, type PositionResolution, } from "@xorgate/react";
|
|
31
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,eAAe,CAAC;AAMvB,OAAO,EACL,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAMjE,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,GAClC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAMvE,OAAO,EAEL,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACd,KAAK,eAAe,EAGpB,YAAY,EACZ,cAAc,EACd,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,EAAE,EACP,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,EAGlB,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAGtB,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,14 @@ XorgateError, isXorgateError,
|
|
|
47
47
|
// Data hooks
|
|
48
48
|
useMe, useOrganizations, useWorkspaces, useDevices, useDevice, useDeviceModel, useTelemetryLatest, useTelemetryHistory, useVideoChannels, useRecordingRuns, useSessions,
|
|
49
49
|
// Live telemetry and the live plane
|
|
50
|
-
useLiveTelemetry, useLivePlane, useLiveCredentials,
|
|
50
|
+
useLiveTelemetry, useLivePlane, useLiveCredentials,
|
|
51
|
+
// Live SCOPE: a device can be transferred to another workspace or
|
|
52
|
+
// organization while a viewer is open, and a vended credential is cached for
|
|
53
|
+
// up to ~50 minutes. On a phone that window is longer in practice, because a
|
|
54
|
+
// backgrounded app resumes onto the same cached credential. Neither plane
|
|
55
|
+
// fails loudly: telemetry simply stops arriving and video keeps flowing until
|
|
56
|
+
// the next reconnect. `useDeviceScope` is how that becomes a typed error.
|
|
57
|
+
useLiveScope, useDeviceScope, parseTelemetryPayload, presignIotWssUrl,
|
|
51
58
|
// Live-block policy
|
|
52
59
|
useLiveBlock, resolveLiveBlock, liveBlockElapsedMs, LIVE_BLOCK_STALE_MS,
|
|
53
60
|
// The video session core and its platform boundary
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,OAAO,EAAE,cAAc,EAA8B,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,qBAAqB,GAEtB,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E,OAAO,EACL,YAAY,GAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAuB,MAAM,iBAAiB,CAAC;AAEjE,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,OAAO,EACL,qBAAqB,GAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,GAOhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAmB,CAAC;AAEvE,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E,OAAO;AACL,uBAAuB;AACvB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,gBAAgB;AAahB,oCAAoC;AACpC,YAAY,EACZ,cAAc;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,OAAO,EAAE,cAAc,EAA8B,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,qBAAqB,GAEtB,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E,OAAO,EACL,YAAY,GAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAuB,MAAM,iBAAiB,CAAC;AAEjE,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,OAAO,EACL,qBAAqB,GAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,eAAe,GAOhB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAmB,CAAC;AAEvE,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E,OAAO;AACL,uBAAuB;AACvB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,gBAAgB;AAahB,oCAAoC;AACpC,YAAY,EACZ,cAAc;AAqCd,aAAa;AACb,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW;AAUX,oCAAoC;AACpC,gBAAgB,EAChB,YAAY,EACZ,kBAAkB;AAClB,kEAAkE;AAClE,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,8EAA8E;AAC9E,0EAA0E;AAC1E,YAAY,EACZ,cAAc,EAMd,qBAAqB,EACrB,gBAAgB;AAgBhB,oBAAoB;AACpB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB;AAMnB,mDAAmD;AACnD,mBAAmB;AAUnB,4EAA4E;AAC5E,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,SAAS,EACT,aAAa,EACb,KAAK,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,GAqBnB,MAAM,gBAAgB,CAAC"}
|
package/dist/replay-video.d.ts
CHANGED
|
@@ -9,19 +9,5 @@ export interface ReplayVideoProps extends Omit<ViewProps, "children"> {
|
|
|
9
9
|
/** Defaults to "contain", matching the web component's object-fit. */
|
|
10
10
|
contentFit?: VideoContentFit;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
* One replay lane's picture, and nothing else: no transport bar, no scrubber,
|
|
14
|
-
* no gap overlay, no loading state. Same minimalism as `LiveVideo` and as the
|
|
15
|
-
* web `ReplayVideo` — read `player.laneState(streamKey)` and render those
|
|
16
|
-
* yourself.
|
|
17
|
-
*
|
|
18
|
-
* What it does that a single `VideoView` cannot is hold BOTH of the lane's
|
|
19
|
-
* players mounted, the hidden one already loaded with the next segment. The
|
|
20
|
-
* boundary is then an opacity flip between two live views rather than a
|
|
21
|
-
* source change on one, which is the whole of why the seam is a picture
|
|
22
|
-
* change instead of a reload. `nativeControls` is off: the clock owns the
|
|
23
|
-
* transport, and a native scrubber would drive one segment's file rather than
|
|
24
|
-
* the replay.
|
|
25
|
-
*/
|
|
26
12
|
export declare function ReplayVideo(props: ReplayVideoProps): ReactNode;
|
|
27
13
|
//# sourceMappingURL=replay-video.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-video.d.ts","sourceRoot":"","sources":["../src/replay-video.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACnE,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,sEAAsE;IACtE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"replay-video.d.ts","sourceRoot":"","sources":["../src/replay-video.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACnE,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,sEAAsE;IACtE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AA6CD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CA0B9D"}
|
package/dist/replay-video.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { StyleSheet, View } from "react-native";
|
|
2
|
+
import { Platform, StyleSheet, View } from "react-native";
|
|
3
3
|
import { VideoView } from "expo-video";
|
|
4
4
|
/**
|
|
5
5
|
* One replay lane's picture, and nothing else: no transport bar, no scrubber,
|
|
@@ -14,17 +14,48 @@ import { VideoView } from "expo-video";
|
|
|
14
14
|
* change instead of a reload. `nativeControls` is off: the clock owns the
|
|
15
15
|
* transport, and a native scrubber would drive one segment's file rather than
|
|
16
16
|
* the replay.
|
|
17
|
+
*
|
|
18
|
+
* On Android the two views are `TextureView`s rather than the default
|
|
19
|
+
* `SurfaceView`s, and that is load-bearing — see {@link ANDROID_SURFACE}.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* What the lane's two views are rendered INTO on Android, and the one thing
|
|
23
|
+
* about this component that is not cosmetic.
|
|
24
|
+
*
|
|
25
|
+
* The seam is an opacity flip between two overlapping views, and `expo-video`
|
|
26
|
+
* draws into a `SurfaceView` by default. A `SurfaceView`'s picture is not
|
|
27
|
+
* drawn by the view hierarchy at all — it is a separate layer the system
|
|
28
|
+
* composites — so `opacity: 0` does not hide it and `zIndex` does not order it
|
|
29
|
+
* against a sibling surface. Two stacked lanes then fight over the same
|
|
30
|
+
* pixels, and the PRELOAD is the one that wins: the hidden player parks on the
|
|
31
|
+
* first frame of the NEXT segment, that still frame covers the player that is
|
|
32
|
+
* actually running, and the lane freezes for a whole segment while the clock,
|
|
33
|
+
* the map and the readouts carry on. Measured on an API 36 emulator before
|
|
34
|
+
* this line existed: 11 distinct frames in three minutes, each freeze starting
|
|
35
|
+
* within a second and a half of the hidden player reporting ready — and the
|
|
36
|
+
* LAST segment of a replay playing normally, because by then there is nothing
|
|
37
|
+
* left to preload on top of it.
|
|
38
|
+
*
|
|
39
|
+
* A `TextureView` is an ordinary view in the hierarchy, so alpha and z-order
|
|
40
|
+
* mean what they say. It costs a GPU copy per frame and cannot show
|
|
41
|
+
* DRM-protected media; a recorded lane is neither hot nor protected. iOS has
|
|
42
|
+
* no such split — `AVPlayerLayer` is a real layer — and the prop is Android's
|
|
43
|
+
* alone, so it is spread in rather than passed at all elsewhere.
|
|
17
44
|
*/
|
|
45
|
+
const ANDROID_SURFACE = { surfaceType: "textureView" };
|
|
18
46
|
export function ReplayVideo(props) {
|
|
19
47
|
const { player, streamKey, contentFit = "contain", style, ...viewProps } = props;
|
|
20
48
|
const media = player.laneMedia(streamKey);
|
|
49
|
+
// Read per render rather than once at module load: it costs nothing, and a
|
|
50
|
+
// constant frozen at import time cannot be asserted from the other platform.
|
|
51
|
+
const surface = Platform.OS === "android" ? ANDROID_SURFACE : undefined;
|
|
21
52
|
return (_jsx(View, { style: style, ...viewProps, children: media?.players.map((lanePlayer, index) => (_jsx(VideoView
|
|
22
53
|
// Positional and stable: the pair is the same two objects for the
|
|
23
54
|
// life of the lane, and only their order on screen changes.
|
|
24
55
|
, { player: lanePlayer, style: [
|
|
25
56
|
StyleSheet.absoluteFill,
|
|
26
57
|
index === media.activeIndex ? styles.front : styles.behind,
|
|
27
|
-
], contentFit: contentFit, nativeControls: false }, index))) }));
|
|
58
|
+
], contentFit: contentFit, nativeControls: false, ...surface }, index))) }));
|
|
28
59
|
}
|
|
29
60
|
const styles = StyleSheet.create({
|
|
30
61
|
front: { opacity: 1, zIndex: 2 },
|
package/dist/replay-video.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay-video.js","sourceRoot":"","sources":["../src/replay-video.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"replay-video.js","sourceRoot":"","sources":["../src/replay-video.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAYvC;;;;;;;;;;;;;;;;GAgBG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,eAAe,GAAG,EAAE,WAAW,EAAE,aAAa,EAAW,CAAC;AAEhE,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;IACjF,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,2EAA2E;IAC3E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;IAExE,OAAO,CACL,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,KAAM,SAAS,YAC9B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,CACzC,KAAC,SAAS;QACR,kEAAkE;QAClE,4DAA4D;YAE5D,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE;gBACL,UAAU,CAAC,YAAY;gBACvB,KAAK,KAAK,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM;aAC3D,EACD,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,KAAK,KACjB,OAAO,IARN,KAAK,CASV,CACH,CAAC,GACG,CACR,CAAC;AACJ,CAAC;AAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAC/B,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;IAChC,yEAAyE;IACzE,0CAA0C;IAC1C,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;CAClC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xorgate/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "React Native adapters for @xorgate/react: live telemetry over MQTT, live video over WebRTC (react-native-webrtc / RTCView), and the recorded-media replay player over expo-video.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Epye Labs",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@aws-crypto/sha256-js": "^5.2.0",
|
|
80
|
-
"@xorgate/react": "^0.
|
|
80
|
+
"@xorgate/react": "^0.3.0"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@testing-library/react": "^16.3.3",
|
package/readme.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @xorgate/react-native
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@xorgate/react-native)
|
|
4
|
+
[](https://github.com/epyelabs/xorgate-react-native/actions/workflows/ci.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
3
7
|
React Native adapters for [`@xorgate/react`](https://www.npmjs.com/package/@xorgate/react).
|
|
4
8
|
Live telemetry over MQTT-over-WebSocket, live video over WebRTC rendered by
|
|
5
9
|
`react-native-webrtc`'s `RTCView`, and recorded-media replay over `expo-video`
|
|
@@ -209,6 +213,27 @@ Unchanged from the web package — `mqtt.js` 5 runs on React Native's global
|
|
|
209
213
|
const { latest, history, status, receivedAt } = useLiveTelemetry(deviceId)
|
|
210
214
|
```
|
|
211
215
|
|
|
216
|
+
### Live scope
|
|
217
|
+
|
|
218
|
+
A device can be transferred to another workspace or organization while a screen
|
|
219
|
+
is open. The vended live credential encodes the old tenancy and is cached for up
|
|
220
|
+
to ~50 minutes, and **nothing fails**: telemetry simply stops arriving and video
|
|
221
|
+
keeps flowing until the next reconnect. On a phone that window is effectively
|
|
222
|
+
longer, because a backgrounded app resumes onto the same cached credential and
|
|
223
|
+
`appStateWake` nudges the live planes straight back onto the stale scope.
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
const scope = useDeviceScope(deviceId)
|
|
227
|
+
const live = useLiveTelemetry(scope.outOfScope ? null : deviceId)
|
|
228
|
+
|
|
229
|
+
if (scope.error) return <Text>{scope.error.message}</Text> // DEVICE_OUT_OF_SCOPE
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`useDeviceScope` re-vends once before complaining, since the ordinary cause is
|
|
233
|
+
just a stale cached credential. If your app moves devices itself, call
|
|
234
|
+
`useLiveScope().invalidate()` afterwards and every open live consumer
|
|
235
|
+
re-resolves immediately.
|
|
236
|
+
|
|
212
237
|
Read freshness off `receivedAt`, not `status`. A phone that loses signal keeps
|
|
213
238
|
a socket that reads `connected` until the OS surfaces the close, which can take
|
|
214
239
|
20 s or more; the age of the last frame is the honest signal, and the web app
|
|
@@ -266,8 +291,9 @@ The transport (`play`, `pause`, `toggle`, `seek`, `setRate`, `setSkipGaps`,
|
|
|
266
291
|
`stepBoundary`), the clock, the lanes and the per-lane `laneState` are the same
|
|
267
292
|
ones the web package exposes — `useReplayPlayer` here is `useReplayPlayerCore`
|
|
268
293
|
with native media bound to it. Everything is driven by wall-clock epoch ms, so
|
|
269
|
-
`useReplayTelemetry(
|
|
270
|
-
|
|
294
|
+
`useReplayTelemetry(deviceId, player)` tracks the video without either side
|
|
295
|
+
knowing about the other: it takes the player CORE, reads a timeline and a
|
|
296
|
+
playhead, and has no idea what is playing the video.
|
|
271
297
|
|
|
272
298
|
The manifest comes from `useReplayManifest(deviceId, …)`, or from your own API
|
|
273
299
|
on the vended-direct auth mode — same rule as `useVideoChannels` above.
|