@ray-js/ipc-player-integration 0.0.39-beta.1 → 0.0.40-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +337 -8
- package/lib/ui/bottomRightContent.js +1 -1
- package/lib/ui/ui.js +17 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,37 @@ English | [简体中文](./README-zh_CN.md)
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@ray-js/ipc-player-integration) [](https://www.npmjs.com/package/@ray-js/ipc-player-integration)
|
|
6
6
|
|
|
7
|
-
> IPC
|
|
7
|
+
> IPC integrated player — an all-in-one IPC (camera) player feature integration component for the Tuya Ray framework.
|
|
8
|
+
|
|
9
|
+
Built on top of [`@ray-js/ray-ipc-player`](https://www.npmjs.com/package/@ray-js/ray-ipc-player), it wraps a complete set of upper-layer player capabilities: resolution switching, screenshot, recording, mute, two-way talk, PTZ control, zoom, battery / temperature & humidity / signal status display, portrait–landscape switching, multi-camera layouts and more — ready to use out of the box, while remaining highly customizable for both widgets and styles.
|
|
10
|
+
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Features](#features)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Core Concepts](#core-concepts)
|
|
17
|
+
- [API](#api)
|
|
18
|
+
- [`<IPCPlayerIntegration />`](#ipcplayerintegration-)
|
|
19
|
+
- [`useCtx(options)`](#usectxoptions)
|
|
20
|
+
- [`useStore(atoms)`](#usestoreatoms)
|
|
21
|
+
- [`Features`](#features-1)
|
|
22
|
+
- [`Widgets`](#widgets)
|
|
23
|
+
- [`Hooks`](#hooks)
|
|
24
|
+
- [`Utils` & device helpers](#utils--device-helpers)
|
|
25
|
+
- [Custom Styling](#custom-styling)
|
|
26
|
+
- [Events](#events)
|
|
27
|
+
- [Multi-Camera](#multi-camera)
|
|
28
|
+
- [Develop](#develop)
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- 🎥 **Integrated player**: encapsulates preview, connection and play-state management on top of `@ray-js/ray-ipc-player`.
|
|
33
|
+
- 🧩 **Declarative widget orchestration**: initialize default widgets with one call to `Features.initPlayerWidgets`, or add/remove widgets in the four corners and the absolute-positioned area on demand.
|
|
34
|
+
- 🛠 **Rich built-in widgets**: resolution, screenshot, recording, mute, intercom, PTZ, zoom, battery, temperature & humidity, 4G signal, floodlight, siren, trial, and more.
|
|
35
|
+
- 🎨 **Customizable**: tailor brand color, icons and fonts via `brandColor` and `CSSVariable`.
|
|
36
|
+
- 📱 **Portrait / landscape / multi-camera**: supports portrait, fullscreen, landscape, and PiP / tile / grid multi-camera layouts.
|
|
37
|
+
- 🪝 **Hook toolkit**: `useBattery`, `usePtz`, `useTemperature` and others for convenient device-state access.
|
|
8
38
|
|
|
9
39
|
## Installation
|
|
10
40
|
|
|
@@ -14,19 +44,318 @@ $ npm install @ray-js/ipc-player-integration
|
|
|
14
44
|
$ yarn add @ray-js/ipc-player-integration
|
|
15
45
|
```
|
|
16
46
|
|
|
47
|
+
> This component requires `ahooks` (a peerDependency); make sure it is installed in the host project.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import React, { useEffect, useRef } from 'react';
|
|
53
|
+
import { View } from '@ray-js/components';
|
|
54
|
+
import {
|
|
55
|
+
IPCPlayerIntegration,
|
|
56
|
+
useCtx,
|
|
57
|
+
useStore,
|
|
58
|
+
Features,
|
|
59
|
+
EventInstance,
|
|
60
|
+
} from '@ray-js/ipc-player-integration';
|
|
61
|
+
|
|
62
|
+
export default function Home(props) {
|
|
63
|
+
const devId = props.location.query?.deviceId;
|
|
64
|
+
// 1. Create the player context instance
|
|
65
|
+
const instance = useCtx({ devId });
|
|
66
|
+
// 2. Subscribe to the state you want to render reactively
|
|
67
|
+
const { screenType } = useStore({ screenType: instance.screenType });
|
|
68
|
+
const eventRef = useRef<EventInstance>();
|
|
69
|
+
|
|
70
|
+
// 3. Initialize default widgets (resolution / screenshot / record / fullscreen ...)
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
Features.initPlayerWidgets(instance, {
|
|
73
|
+
hideRecordVideoMenu: false,
|
|
74
|
+
hideScreenShotMenu: false,
|
|
75
|
+
hideResolutionMenu: false,
|
|
76
|
+
showToggleVerticalFull: true,
|
|
77
|
+
});
|
|
78
|
+
}, []);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<View>
|
|
82
|
+
<IPCPlayerIntegration
|
|
83
|
+
instance={instance}
|
|
84
|
+
devId={instance.devId}
|
|
85
|
+
eventRef={eventRef}
|
|
86
|
+
deviceOnline
|
|
87
|
+
brandColor="#FF592A"
|
|
88
|
+
landscapeMode="fill"
|
|
89
|
+
playerFit="contain"
|
|
90
|
+
style={{ height: screenType === 'vertical' ? 'calc(100vw * 0.56)' : '100vh' }}
|
|
91
|
+
/>
|
|
92
|
+
</View>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Core Concepts
|
|
98
|
+
|
|
99
|
+
| Concept | Description |
|
|
100
|
+
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| **instance** | Created by `useCtx({ devId })`, it spans the whole player and manages state atoms, the player instance, widget content and the event bus. Pass it to `<IPCPlayerIntegration instance={instance} />`. |
|
|
102
|
+
| **atom** | Based on [jotai](https://jotai.org/). State on the `instance` (e.g. `screenType`, `mute`, `resolution`) are atoms; subscribe via `useStore` to render reactively. |
|
|
103
|
+
| **content areas** | Widgets on the player are distributed across 5 areas: `topLeft`, `topRight`, `bottomLeft`, `bottomRight`, `absolute`. Managed via `addContent` / `deleteContent` / `updateContent`, etc. |
|
|
104
|
+
| **event** | `instance.event` provides `on/off/emit`. Expose it to the page through `eventRef` to listen for clicks, resolution switches and other events. |
|
|
105
|
+
|
|
106
|
+
## API
|
|
107
|
+
|
|
108
|
+
### `<IPCPlayerIntegration />`
|
|
109
|
+
|
|
110
|
+
The main player component.
|
|
111
|
+
|
|
112
|
+
| Prop | Type | Default | Description |
|
|
113
|
+
| ------------------------ | -------------------------------- | -------------------- | ----------------------------------------------------------------- |
|
|
114
|
+
| `devId` | `string` | — | Device ID (required) |
|
|
115
|
+
| `instance` | `ReturnType<useCtx>` | — | The context instance from `useCtx`; created internally if omitted |
|
|
116
|
+
| `eventRef` | `React.RefObject<EventInstance>` | — | Event-bus ref for listening on the page side |
|
|
117
|
+
| `playerFit` | `'contain' \| 'cover'` | `'contain'` | Video fit mode |
|
|
118
|
+
| `landscapeMode` | `'fill' \| 'standard'` | `'standard'` | Landscape display mode |
|
|
119
|
+
| `brandColor` | `string` | `'#FF592A'` | Brand color |
|
|
120
|
+
| `CSSVariable` | `Partial<CSSVariable>` | — | Custom CSS variables, see [Custom Styling](#custom-styling) |
|
|
121
|
+
| `deviceOnline` | `boolean` | `true` | Whether the device is online |
|
|
122
|
+
| `privateState` | `boolean` | `false` | Whether privacy mode (mask) is on |
|
|
123
|
+
| `verticalMic` | `boolean` | `true` | Whether to show the mic intercom in portrait |
|
|
124
|
+
| `isShare` | `boolean` | `false` | Whether it is a shared device |
|
|
125
|
+
| `ignoreHideStopPreview` | `boolean` | `false` | Ignore stop-preview when widgets hide |
|
|
126
|
+
| `awakeStatus` | `boolean` | `undefined` | Wake-up status for low-power devices |
|
|
127
|
+
| `autoWakeUp` | `boolean` | `false` | Auto wake up the device |
|
|
128
|
+
| `limitFlow` | `boolean` | `false` | Whether flow is limited |
|
|
129
|
+
| `showFlowLowTip` | `boolean` | `false` | Show the low-flow tip |
|
|
130
|
+
| `previewEnabled` | `boolean` | `undefined` | Controlled preview switch |
|
|
131
|
+
| `refreshElement` | `boolean` | `false` | Trigger a CoverView height refresh |
|
|
132
|
+
| `playerRoute` | `string` | `'pages/home/index'` | Route the player lives on |
|
|
133
|
+
| `style` / `className` | `CSSProperties` / `string` | — | Container style / className |
|
|
134
|
+
| `onPlayStatus` | `(data: PlayStatusData) => void` | — | Play-state change callback |
|
|
135
|
+
| `onPlayerTap` | `(data) => void` | — | Tap-on-video callback |
|
|
136
|
+
| `onPreviewEnabledChange` | `(enabled: boolean) => void` | — | Preview-switch change callback |
|
|
137
|
+
|
|
138
|
+
### `useCtx(options)`
|
|
139
|
+
|
|
140
|
+
Creates the player context instance.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const instance = useCtx({
|
|
144
|
+
devId: string, // Device ID (required)
|
|
145
|
+
saveToAlbum?: 0 | 1, // 0: system album; 1: IPC album
|
|
146
|
+
showPtzControlTip?: boolean, // Show the PTZ control guide
|
|
147
|
+
videoSplitProtocol?: VideoSplitProtocol, // Multi-camera split protocol
|
|
148
|
+
initTopLeftContent?: ComponentConfig[], // Initial widgets per area
|
|
149
|
+
initTopRightContent?: ComponentConfig[],
|
|
150
|
+
initBottomLeftContent?: ComponentConfig[],
|
|
151
|
+
initBottomRightContent?: ComponentConfig[],
|
|
152
|
+
initAbsoluteContent?: ComponentConfig[],
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The returned `instance` provides:
|
|
157
|
+
|
|
158
|
+
- **State atoms**: `screenType`, `mute`, `intercom`, `recording`, `resolution`, `resolutionList`, `playState`, `brandColor`, `verticalMic`, `isVerticalFullLayout`, etc. (subscribe via `useStore`).
|
|
159
|
+
- **State setters**: `setMute`, `setIntercom`, `setRecording`, `setResolution`, `setScreenType`, `setBrandColor`, `setPlayState`, `changeStreamStatus`, `getStreamStatus`, etc.
|
|
160
|
+
- **Content management**: `addContent(type, config, position?)`, `deleteContent(type, id)`, `updateContent(type, data)`, `getContent()`, `hasContent`, `hideContent`, `showContent`.
|
|
161
|
+
- **Misc**: `IPCPlayerInstance` (the underlying player instance), `event` (event bus), `toast`, `multiCameraCtx` (multi-camera context).
|
|
162
|
+
|
|
163
|
+
### `useStore(atoms)`
|
|
164
|
+
|
|
165
|
+
Subscribes to state atoms on the `instance` and returns a reactive value object.
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
const { screenType, mute, resolution } = useStore({
|
|
169
|
+
screenType: instance.screenType,
|
|
170
|
+
mute: instance.mute,
|
|
171
|
+
resolution: instance.resolution,
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### `Features`
|
|
176
|
+
|
|
177
|
+
Widget-orchestration capabilities, imported via `import { Features } from '@ray-js/ipc-player-integration'`.
|
|
178
|
+
|
|
179
|
+
#### `Features.initPlayerWidgets(instance, options)`
|
|
180
|
+
|
|
181
|
+
Initializes the default widgets based on the device's DP info. Common `options`:
|
|
182
|
+
|
|
183
|
+
| Option | Type | Description |
|
|
184
|
+
| ----------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------ |
|
|
185
|
+
| `hideScreenShotMenu` | `boolean` | Hide the screenshot button |
|
|
186
|
+
| `hideRecordVideoMenu` | `boolean` | Hide the record button |
|
|
187
|
+
| `hideResolutionMenu` | `boolean` | Hide the resolution button |
|
|
188
|
+
| `hideKbsMenu` | `boolean` | Hide the bitrate display |
|
|
189
|
+
| `hideSignalMenu` | `boolean` | Hide the signal-strength button |
|
|
190
|
+
| `hideHorizontalMenu` | `boolean` | Hide the enter-landscape button |
|
|
191
|
+
| `verticalResolutionCustomClick` | `boolean` | Custom click for portrait resolution |
|
|
192
|
+
| `showToggleVerticalFull` | `boolean` | Show the single-cam portrait-fullscreen toggle |
|
|
193
|
+
| `showRealTimeMagnification` | `boolean` | Show the real-time magnification button |
|
|
194
|
+
| `hideSmartImageQualityState` | `boolean` | Hide the smart image-quality state |
|
|
195
|
+
| `directionControlProps` | `object` | Pass-through props for the PTZ direction control |
|
|
196
|
+
| `topLeftContent` / `topRightContent` / `bottomLeftContent` / `bottomRightContent` / `absoluteContent` | `ComponentConfig[]` | Override default widget config |
|
|
197
|
+
|
|
198
|
+
#### `Features.updatePlayerWidgetProps(ctx, area, widgetId, newProps)`
|
|
199
|
+
|
|
200
|
+
Dynamically updates props of a widget in a given area.
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
Features.updatePlayerWidgetProps(instance, 'topRight', 'VideoBitKBP', {
|
|
204
|
+
hideKbsMenu: true,
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
> `area`: `'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'absolute'`; for `widgetId` see the widget list below.
|
|
209
|
+
|
|
210
|
+
### `Widgets`
|
|
211
|
+
|
|
212
|
+
Imported via `import { Widgets } from '@ray-js/ipc-player-integration'`; each widget can be used standalone. Common widgets:
|
|
213
|
+
|
|
214
|
+
| Widget | WidgetId | Description |
|
|
215
|
+
| ------------------------------- | --------------------------------------------- | -------------------------- |
|
|
216
|
+
| `Widgets.VoiceIntercom` | `FullSmallIntercom` / `VerticalSmallIntercom` | Two-way talk button |
|
|
217
|
+
| `Widgets.Screenshot` | `Screenshot` | Screenshot |
|
|
218
|
+
| `Widgets.RecordVideo` | `RecordVideo` | Recording |
|
|
219
|
+
| `Widgets.Muted` | `Muted` | Mute |
|
|
220
|
+
| `Widgets.Resolution` | `Resolution` | Resolution switch |
|
|
221
|
+
| `Widgets.FullScreen` | `FullScreen` | Fullscreen / landscape |
|
|
222
|
+
| `Widgets.Ptz` | `Ptz` | PTZ control |
|
|
223
|
+
| `Widgets.VideoBitKBP` | `VideoBitKBP` | Bitrate / signal |
|
|
224
|
+
| `Widgets.BatteryFull` | `BatteryFull` | Battery |
|
|
225
|
+
| `Widgets.TempHumidity` | `TempHumidity` | Temperature & humidity |
|
|
226
|
+
| `Widgets.Floodlight` | `Floodlight` | Floodlight |
|
|
227
|
+
| `Widgets.Siren` | `Siren` | Siren |
|
|
228
|
+
| `Widgets.TryExperience` | `TryExperience` | Trial |
|
|
229
|
+
| `Widgets.PtzControlTip` | — | PTZ control guide dialog |
|
|
230
|
+
| `Widgets.RealTimeMagnification` | — | Real-time magnification |
|
|
231
|
+
| `Widgets.ToggleVerticalFull` | — | Portrait-fullscreen toggle |
|
|
232
|
+
| `Widgets.FlowLowTip` | — | Low-flow tip |
|
|
233
|
+
|
|
234
|
+
Standalone `VoiceIntercom` example:
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
<Widgets.VoiceIntercom
|
|
238
|
+
ref={intercomRef}
|
|
239
|
+
IPCPlayerContext={instance?.IPCPlayerInstance}
|
|
240
|
+
{...instance}
|
|
241
|
+
mode="circle" // 'verticalSmall' | 'fullSmall' | 'circle'
|
|
242
|
+
disabled={false}
|
|
243
|
+
icon={intercomLightSvg}
|
|
244
|
+
talkingColor="#440F7C"
|
|
245
|
+
/>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Insert the PTZ guide dialog into the `absolute` area:
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
instance.addContent('absolute', {
|
|
252
|
+
id: 'ptzControlTipId',
|
|
253
|
+
content: props => <Widgets.PtzControlTip {...props} />,
|
|
254
|
+
absoluteContentClassName: 'ipc-player-plugin-ptz-control-tip-wrap',
|
|
255
|
+
initProps: { ...props },
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### `Hooks`
|
|
260
|
+
|
|
261
|
+
Convenient device-state access (all exported from the package root):
|
|
262
|
+
|
|
263
|
+
| Hook | Signature | Description |
|
|
264
|
+
| ---------------- | ---------------------------------------------- | ------------------------------ |
|
|
265
|
+
| `useBattery` | `(devId) => { batteryValue, batteryCharging }` | Battery level / charging state |
|
|
266
|
+
| `usePtz` | `(devId) => boolean` | Whether PTZ is supported |
|
|
267
|
+
| `useTemperature` | `(devId) => number` | Temperature |
|
|
268
|
+
| `useHumidity` | `() => number` | Humidity |
|
|
269
|
+
| `useSignal4G` | `(devId) => { dpValue, signalKey }` | 4G signal strength |
|
|
270
|
+
| `useDpState` | — | Read/write DP state |
|
|
271
|
+
| `useDpSupport` | — | DP support check |
|
|
272
|
+
| `useSchemaInfo` | — | Device schema info |
|
|
273
|
+
| `useMemoizedFn` | — | Stable function reference |
|
|
274
|
+
|
|
275
|
+
### `Utils` & device helpers
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { Utils } from '@ray-js/ipc-player-integration';
|
|
279
|
+
// Device helpers are imported from a sub-path
|
|
280
|
+
import {
|
|
281
|
+
getDpValue,
|
|
282
|
+
getDeviceInfo,
|
|
283
|
+
getDpSchemaByCodes,
|
|
284
|
+
getDpSchemaByCodesSync,
|
|
285
|
+
hasDpCode,
|
|
286
|
+
} from '@ray-js/ipc-player-integration/utils/device';
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
- `getDpSchemaByCodes(devId, codes)`: batch-fetch schema by DP code.
|
|
290
|
+
- `hasDpCode(devId, code)`: check whether the device has a given DP.
|
|
291
|
+
- `Utils.radialGradient(color)` / `Utils.adjustBrightness(hex, factor)`: color helpers.
|
|
292
|
+
|
|
293
|
+
## Custom Styling
|
|
294
|
+
|
|
295
|
+
### Brand color
|
|
296
|
+
|
|
297
|
+
Set via the `brandColor` prop or `instance.setBrandColor(color)`.
|
|
298
|
+
|
|
299
|
+
### CSS variables
|
|
300
|
+
|
|
301
|
+
Override via the `CSSVariable` prop:
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
<IPCPlayerIntegration
|
|
305
|
+
CSSVariable={{
|
|
306
|
+
'--iconColor': '#fff',
|
|
307
|
+
'--iconActiveColor': '#ec653c',
|
|
308
|
+
'--iconFontSize': '20px',
|
|
309
|
+
'--bg-color': '#000',
|
|
310
|
+
'--fontColor': '#fff',
|
|
311
|
+
'--fontSize': '12px',
|
|
312
|
+
}}
|
|
313
|
+
/>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Available variables: `--iconColor`, `--iconActiveColor`, `--iconFontSize`, `--iconPlayerSize`, `--iconBoxSize`, `--bg-color`, `--shot-card-bg-color`, `--fontColor`, `--fontSize`.
|
|
317
|
+
|
|
318
|
+
## Events
|
|
319
|
+
|
|
320
|
+
Once you have the event bus through `eventRef`, you can listen to internal player events:
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
const eventRef = useRef<EventInstance>();
|
|
324
|
+
|
|
325
|
+
useEffect(() => {
|
|
326
|
+
const onResolutionClick = () => console.log('resolution button clicked');
|
|
327
|
+
const onWidgetClick = data => console.log('widget clicked', data);
|
|
328
|
+
eventRef.current.on('resolutionBtnControlClick', onResolutionClick);
|
|
329
|
+
eventRef.current.on('widgetClick', onWidgetClick);
|
|
330
|
+
return () => {
|
|
331
|
+
eventRef.current.off('resolutionBtnControlClick', onResolutionClick);
|
|
332
|
+
eventRef.current.off('widgetClick', onWidgetClick);
|
|
333
|
+
};
|
|
334
|
+
}, []);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Multi-Camera
|
|
338
|
+
|
|
339
|
+
Supports PiP, tile, grid and thumbnail multi-camera layouts. Related types are exported from the package root:
|
|
340
|
+
|
|
341
|
+
- `MultiCameraScreenMode`: screen mode (`short` / `full` / `landscape`).
|
|
342
|
+
- `MultiCameraLayoutStyle`: layout style (`pip` / `tile` / `grid` / `thumbnail`).
|
|
343
|
+
- `VideoSplitProtocol`: the multi-camera split protocol, passed via `useCtx({ videoSplitProtocol })`.
|
|
344
|
+
- `MultiCameraLenInfo`: lens info (index, name, whether PTZ / Zoom / Localizer is supported).
|
|
345
|
+
|
|
346
|
+
The multi-camera context is accessible via `instance.multiCameraCtx`.
|
|
347
|
+
|
|
17
348
|
## Develop
|
|
18
349
|
|
|
19
350
|
```sh
|
|
20
351
|
# install deps
|
|
21
352
|
yarn
|
|
22
353
|
|
|
23
|
-
# watch
|
|
354
|
+
# watch & preview the demo (Tuya target)
|
|
24
355
|
yarn start:tuya
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Usage
|
|
28
356
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export default () => <Foo />;
|
|
357
|
+
# build the component
|
|
358
|
+
yarn build
|
|
32
359
|
```
|
|
360
|
+
|
|
361
|
+
Other available scripts: `start:wechat`, `start:web`, `start:native`, `build:tuya`, `build:wechat`, `build:web`, `build:native`.
|
|
@@ -32,7 +32,7 @@ const BottomRightContent = _ref => {
|
|
|
32
32
|
className: clsx('ipc-player-bottom-right-content-wrap'),
|
|
33
33
|
style: _objectSpread({
|
|
34
34
|
paddingLeft: screenType === 'vertical' ? '10px' : '0',
|
|
35
|
-
height: screenType === 'vertical' ? shouldHide ? '49px' : '48px' : shouldHide ? '
|
|
35
|
+
height: screenType === 'vertical' ? shouldHide ? '49px' : '48px' : shouldHide ? '59px' : '58px'
|
|
36
36
|
}, widthStyle)
|
|
37
37
|
}, /*#__PURE__*/React.createElement(View, {
|
|
38
38
|
style: {
|
package/lib/ui/ui.js
CHANGED
|
@@ -11,7 +11,7 @@ import IPCPlayer from '@ray-js/ray-ipc-player';
|
|
|
11
11
|
import { ipcTTTOperatorLog } from '@ray-js/ray-ipc-utils';
|
|
12
12
|
import { PlayState, PlayerStreamStatus, MultiCameraScreenMode } from '../interface';
|
|
13
13
|
import { useCtx } from '../ctx/ctx.composition';
|
|
14
|
-
import { useStore, updateAtom } from '../ctx/store';
|
|
14
|
+
import { useStore, updateAtom, getDefaultStore } from '../ctx/store';
|
|
15
15
|
import { UIEventContext } from './context';
|
|
16
16
|
import { showAllComponent, hideAllComponent, playerTap, startTimeToHideAllComponent, pauseTimeToHideAllComponent, decodeClarityDic, changeIgnoreHideStopPreview, moveablePtzControlId, tileActionsId, tileTipId, landscapeTipId, multiPtzId, ptzMoveableTipId, showFlowLowTipId, zoomLevelChange, setScaleMultipleEvent, trialCountdownEnd, refreshSmartImageQualityEvent } from './constant';
|
|
17
17
|
import BottomLeftContent from './bottomLeftContent';
|
|
@@ -421,6 +421,19 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
|
|
|
421
421
|
|
|
422
422
|
/* ---------------------------------多目相关副作用统一处理结束----------------------------------------- */
|
|
423
423
|
|
|
424
|
+
const disablePlayerTap = useRef(false);
|
|
425
|
+
const handDisablePlayerTap = useMemoizedFn(value => {
|
|
426
|
+
disablePlayerTap.current = !!value;
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// 须在竖屏全屏 effect 之前注册,否则多目首帧 emit('disablePlayerTap') 时 listener 尚未挂载
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
eventRef.current.on('disablePlayerTap', handDisablePlayerTap);
|
|
432
|
+
return () => {
|
|
433
|
+
eventRef.current.off('disablePlayerTap', handDisablePlayerTap);
|
|
434
|
+
};
|
|
435
|
+
}, [handDisablePlayerTap]);
|
|
436
|
+
|
|
424
437
|
// 竖屏全屏副作用处理
|
|
425
438
|
useEffect(() => {
|
|
426
439
|
if (isVerticalFullLayout && screenType === 'vertical') {
|
|
@@ -768,15 +781,10 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
|
|
|
768
781
|
});
|
|
769
782
|
instance.changeStreamStatus(code);
|
|
770
783
|
});
|
|
771
|
-
const disablePlayerTap = useRef(false);
|
|
772
|
-
// 标记正在执行隐藏,防止 playerTap 子组件监听触发 showAllComponent 干扰隐藏
|
|
773
784
|
const isHidingByTapRef = useRef(false);
|
|
774
785
|
const hasInitializedLandscapeMultiRef = useRef(false);
|
|
775
786
|
const multiTapTimerRef = useRef(null);
|
|
776
787
|
const prevSelectedIndexRef = useRef(selectedLenInfo.index);
|
|
777
|
-
const handDisablePlayerTap = value => {
|
|
778
|
-
disablePlayerTap.current = !!value;
|
|
779
|
-
};
|
|
780
788
|
/**
|
|
781
789
|
* 展示所有组件,一段时间后自动关闭
|
|
782
790
|
*/
|
|
@@ -812,8 +820,9 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
|
|
|
812
820
|
// 重新开始计时
|
|
813
821
|
// @ts-ignore
|
|
814
822
|
timer.current = setTimeout(() => {
|
|
815
|
-
//
|
|
816
|
-
|
|
823
|
+
// 定时器触发时从 store 读最新状态,避免启动时闭包拿到过期的 isVerticalFullLayout
|
|
824
|
+
const store = getDefaultStore();
|
|
825
|
+
if (store.get(instance.isVerticalFullLayout) && store.get(instance.screenType) === 'vertical') return;
|
|
817
826
|
triggerEvent(hideAllComponent);
|
|
818
827
|
}, HIDE_COMPONENT_TIME);
|
|
819
828
|
});
|
|
@@ -845,7 +854,6 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
|
|
|
845
854
|
eventRef.current.on(pauseTimeToHideAllComponent, listenPause);
|
|
846
855
|
eventRef.current.on(showAllComponent, listenShowEvent);
|
|
847
856
|
eventRef.current.on(hideAllComponent, listenHideEvent);
|
|
848
|
-
eventRef.current.on('disablePlayerTap', handDisablePlayerTap);
|
|
849
857
|
eventRef.current.on('refreshBottomLeft', refreshBottomLeft);
|
|
850
858
|
eventRef.current.on(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
|
|
851
859
|
eventRef.current.on(setScaleMultipleEvent, onSetScaleMultiple);
|
|
@@ -856,7 +864,6 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
|
|
|
856
864
|
eventRef.current.off(pauseTimeToHideAllComponent, listenPause);
|
|
857
865
|
eventRef.current.off(showAllComponent, listenShowEvent);
|
|
858
866
|
eventRef.current.off(hideAllComponent, listenHideEvent);
|
|
859
|
-
eventRef.current.off('disablePlayerTap', handDisablePlayerTap);
|
|
860
867
|
eventRef.current.off('refreshBottomLeft', refreshBottomLeft);
|
|
861
868
|
eventRef.current.off(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
|
|
862
869
|
eventRef.current.off(setScaleMultipleEvent, onSetScaleMultiple);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/ipc-player-integration",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40-beta.1",
|
|
4
4
|
"description": "IPC 融合播放器",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"files": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ray-js/direction-control": "^0.0.8",
|
|
39
39
|
"@ray-js/ipc-ptz-zoom": "^0.0.3",
|
|
40
|
-
"@ray-js/ray-ipc-player": "^2.1.
|
|
40
|
+
"@ray-js/ray-ipc-player": "^2.1.3",
|
|
41
41
|
"@ray-js/ray-ipc-utils": "^1.1.15",
|
|
42
42
|
"@ray-js/svg": "0.2.0",
|
|
43
43
|
"clsx": "^1.2.1",
|