@ray-js/ipc-player-integration 0.0.53-beta.1 → 0.0.53-beta.11

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.
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, useRef, useState } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import { View, Text, usePageEvent } from '@ray-js/ray';
3
3
  import clsx from 'clsx';
4
4
  import { getVideoBitrateKbps, requestWifiSignal } from '@ray-js/ray-ipc-utils';
@@ -7,8 +7,6 @@ import { PlayState } from '../../interface';
7
7
  import './videoBitKBP.less';
8
8
  import { useStore } from '../../ctx/store';
9
9
  import Strings from '../../i18n';
10
- import { UIEventContext } from '../../ui/context';
11
- import { autoClarityChange } from '../../ui/constant';
12
10
  export const VideoBitKBP = props => {
13
11
  const {
14
12
  devId,
@@ -19,32 +17,12 @@ export const VideoBitKBP = props => {
19
17
  } = props;
20
18
  const [bitKBP, setBitKBP] = useState('');
21
19
  const [signalStrength, setSignalStrength] = useState(null);
22
- // 自动清晰度当前实际档位:null 表示未开启自动模式,不展示
23
- const [autoClarity, setAutoClarity] = useState(null);
24
20
  const store = useStore({
25
21
  playState,
26
- resolution: props.resolution
22
+ resolution: props.resolution,
23
+ autoClarity: props.autoClarity
27
24
  });
28
- const {
29
- event
30
- } = useContext(UIEventContext);
31
25
  const timerRef = useRef();
32
-
33
- // 监听 Resolution 控件广播的自动清晰度状态
34
- useEffect(() => {
35
- const onAutoClarityChange = payload => {
36
- setAutoClarity(payload.enabled ? payload.clarity : null);
37
- };
38
- event.on(autoClarityChange, onAutoClarityChange);
39
- return () => {
40
- event.off(autoClarityChange, onAutoClarityChange);
41
- };
42
- }, [event]);
43
- useEffect(() => {
44
- if (store.resolution !== ClarityType.AUTO) {
45
- setAutoClarity(null);
46
- }
47
- }, [store.resolution]);
48
26
  useEffect(() => {
49
27
  if (store.playState === PlayState.PLAYING && (!hideKbsMenu || !hideSignalMenu)) {
50
28
  init();
@@ -78,12 +56,34 @@ export const VideoBitKBP = props => {
78
56
  }
79
57
  }
80
58
  };
81
- const hasKbps = !hideKbsMenu && bitKBP !== '' && bitKBP !== '0';
82
- const hasSignal = !hideSignalMenu && signalStrength !== null;
83
- if (!hasKbps && !hasSignal || store.playState !== PlayState.PLAYING) {
59
+ const isPlaying = store.playState === PlayState.PLAYING;
60
+ const hasKbps = isPlaying && !hideKbsMenu && bitKBP !== '' && bitKBP !== '0';
61
+ const hasSignal = isPlaying && !hideSignalMenu && signalStrength !== null;
62
+ const activeClarity = store.resolution === ClarityType.AUTO ? store.autoClarity : null;
63
+ const hasClarity = Boolean(activeClarity);
64
+ const bitrateLabel = [activeClarity ? (clarity => {
65
+ switch (clarity) {
66
+ case ClarityType.SS:
67
+ return Strings.getLang('ipc_player_resolution_SS');
68
+ case ClarityType.SD:
69
+ return Strings.getLang('ipc_player_resolution_SD');
70
+ case ClarityType.HD:
71
+ return Strings.getLang('ipc_player_resolution_HD');
72
+ case ClarityType.UD:
73
+ return Strings.getLang('ipc_player_resolution_UD');
74
+ case ClarityType.SSP:
75
+ return Strings.getLang('ipc_player_resolution_SSP');
76
+ case ClarityType.AUTO:
77
+ return Strings.getLang('ipc_player_resolution_AUTO');
78
+ case ClarityType.AUDIO:
79
+ return Strings.getLang('ipc_player_resolution_AUDIO');
80
+ default:
81
+ return clarity;
82
+ }
83
+ })(activeClarity) : '', hasKbps ? `${bitKBP} KB/S` : ''].filter(Boolean).join(' ');
84
+ if (!hasKbps && !hasSignal && !hasClarity) {
84
85
  return null;
85
86
  }
86
- if (hideKbsMenu && hideSignalMenu) return null;
87
87
  return /*#__PURE__*/React.createElement(View, {
88
88
  className: clsx({
89
89
  'ipc-player-plugin-videoBitKBP-container': true,
@@ -91,19 +91,21 @@ export const VideoBitKBP = props => {
91
91
  })
92
92
  }, /*#__PURE__*/React.createElement(View, {
93
93
  className: "ipc-player-plugin-videoBitKBP"
94
+ }, /*#__PURE__*/React.createElement(View, {
95
+ className: "ipc-player-plugin-videoBitKBP-content"
94
96
  }, hasSignal && /*#__PURE__*/React.createElement(View, {
95
97
  className: "ipc-player-plugin-videoBitKBP-signal"
96
98
  }, /*#__PURE__*/React.createElement(Text, {
97
99
  className: clsx('icon-panel', 'icon-panel-wi-Fi', 'ipc-player-plugin-videoBitKBP-signal-icon')
98
- }), /*#__PURE__*/React.createElement(Text, null, signalStrength), /*#__PURE__*/React.createElement(Text, {
99
- className: "ipc-player-plugin-videoBitKBP-unit-percent"
100
- }, signalStrength > 0 ? '%' : 'dBm')), hasSignal && hasKbps && /*#__PURE__*/React.createElement(View, {
100
+ }), /*#__PURE__*/React.createElement(Text, {
101
+ className: "ipc-player-plugin-videoBitKBP-signal-text"
102
+ }, signalStrength), /*#__PURE__*/React.createElement(Text, {
103
+ className: "ipc-player-plugin-videoBitKBP-signal-text ipc-player-plugin-videoBitKBP-unit-percent"
104
+ }, signalStrength > 0 ? '%' : 'dBm')), hasSignal && (hasKbps || hasClarity) && /*#__PURE__*/React.createElement(View, {
101
105
  className: "ipc-player-plugin-videoBitKBP-divider"
102
- }), hasKbps && /*#__PURE__*/React.createElement(View, {
106
+ }), (hasKbps || hasClarity) && /*#__PURE__*/React.createElement(View, {
103
107
  className: "ipc-player-plugin-videoBitKBP-kbps"
104
- }, autoClarity && /*#__PURE__*/React.createElement(Text, {
105
- className: "ipc-player-plugin-videoBitKBP-clarity"
106
- }, autoClarity === 'HD' ? Strings.getLang('ipc_player_resolution_HD') : Strings.getLang('ipc_player_resolution_SD')), /*#__PURE__*/React.createElement(Text, null, bitKBP), /*#__PURE__*/React.createElement(Text, {
107
- className: "ipc-player-plugin-videoBitKBP-unit-kbs"
108
- }, "KB/S"))));
108
+ }, /*#__PURE__*/React.createElement(Text, {
109
+ className: "ipc-player-plugin-videoBitKBP-kbps-text"
110
+ }, bitrateLabel)))));
109
111
  };
@@ -18,29 +18,35 @@
18
18
  background-color: rgba(255, 255, 255, 0.2);
19
19
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
20
20
  }
21
- .ipc-player-plugin-videoBitKBP-signal {
21
+ .ipc-player-plugin-videoBitKBP-content {
22
22
  display: flex;
23
- align-items: center;
23
+ align-items: baseline;
24
+ }
25
+ .ipc-player-plugin-videoBitKBP-signal,
26
+ .ipc-player-plugin-videoBitKBP-kbps {
27
+ display: flex;
28
+ align-items: baseline;
29
+ height: calc(16px * var(--ipc-player-size-scale, 1));
30
+ line-height: calc(16px * var(--ipc-player-size-scale, 1));
24
31
  }
25
32
  .ipc-player-plugin-videoBitKBP-signal-icon {
33
+ align-self: center;
26
34
  font-size: calc(14px * var(--ipc-player-size-scale, 1));
27
35
  margin-right: calc(4px * var(--ipc-player-size-scale, 1));
28
36
  }
37
+ .ipc-player-plugin-videoBitKBP-signal-text,
38
+ .ipc-player-plugin-videoBitKBP-kbps-text {
39
+ line-height: calc(16px * var(--ipc-player-size-scale, 1));
40
+ }
29
41
  .ipc-player-plugin-videoBitKBP-divider {
42
+ align-self: center;
30
43
  width: 1px;
31
44
  height: calc(10px * var(--ipc-player-size-scale, 1));
32
45
  background-color: var(--iconColor);
33
46
  margin: 0 calc(4px * var(--ipc-player-size-scale, 1));
34
47
  }
35
- .ipc-player-plugin-videoBitKBP-kbps {
36
- display: flex;
37
- align-items: center;
38
- }
39
- .ipc-player-plugin-videoBitKBP-clarity {
40
- margin-right: calc(4px * var(--ipc-player-size-scale, 1));
41
- }
42
- .ipc-player-plugin-videoBitKBP-unit-kbs {
43
- margin-left: calc(4px * var(--ipc-player-size-scale, 1));
48
+ .ipc-player-plugin-videoBitKBP-kbps-text {
49
+ white-space: nowrap;
44
50
  }
45
51
  .ipc-player-plugin-videoBitKBP-unit-percent {
46
52
  margin-left: calc(2px * var(--ipc-player-size-scale, 1));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,156 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.map.js";
3
+ import React from 'react';
4
+ import ReactDOM from 'react-dom';
5
+ import { renderToStaticMarkup } from 'react-dom/server';
6
+ import { act } from 'react-dom/test-utils';
7
+ import { getVideoBitrateKbps, requestWifiSignal } from '@ray-js/ray-ipc-utils';
8
+ let mockStoreState;
9
+ jest.mock('@ray-js/ray', () => ({
10
+ View: _ref => {
11
+ let {
12
+ children,
13
+ className
14
+ } = _ref;
15
+ return /*#__PURE__*/React.createElement("div", {
16
+ className: className
17
+ }, children);
18
+ },
19
+ Text: _ref2 => {
20
+ let {
21
+ children,
22
+ className
23
+ } = _ref2;
24
+ return /*#__PURE__*/React.createElement("span", {
25
+ className: className
26
+ }, children);
27
+ },
28
+ usePageEvent: () => undefined
29
+ }));
30
+ jest.mock('@ray-js/ray-ipc-utils', () => ({
31
+ getVideoBitrateKbps: jest.fn(),
32
+ requestWifiSignal: jest.fn()
33
+ }));
34
+ jest.mock('@ray-js/ray-ipc-utils/lib/interface', () => ({
35
+ ClarityType: {
36
+ SS: 'SS',
37
+ SD: 'SD',
38
+ HD: 'HD',
39
+ UD: 'UD',
40
+ SSP: 'SSP',
41
+ AUTO: 'AUTO',
42
+ AUDIO: 'AUDIO'
43
+ }
44
+ }));
45
+ jest.mock('../../ctx/store', () => ({
46
+ useStore: () => mockStoreState
47
+ }));
48
+ jest.mock('../../i18n', () => ({
49
+ __esModule: true,
50
+ default: {
51
+ getLang: key => key
52
+ }
53
+ }));
54
+ jest.mock('./videoBitKBP.less', () => ({}));
55
+ const {
56
+ VideoBitKBP
57
+ } = require('./videoBitKBP');
58
+ const renderWidget = function (resolution, autoClarity) {
59
+ let playState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
60
+ let hideKbsMenu = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
61
+ mockStoreState = {
62
+ resolution,
63
+ autoClarity,
64
+ playState
65
+ };
66
+ return renderToStaticMarkup(/*#__PURE__*/React.createElement(VideoBitKBP, {
67
+ devId: 'device',
68
+ playState: {},
69
+ resolution: {},
70
+ autoClarity: {},
71
+ hideKbsMenu,
72
+ hideSignalMenu: true
73
+ }));
74
+ };
75
+ describe('VideoBitKBP auto clarity', () => {
76
+ it('renders clarity, bitrate and unit in one text line', async () => {
77
+ const container = document.createElement('div');
78
+ getVideoBitrateKbps.mockResolvedValue({
79
+ code: 0,
80
+ data: {
81
+ kbps: '128'
82
+ }
83
+ });
84
+ mockStoreState = {
85
+ resolution: 'AUTO',
86
+ autoClarity: 'HD',
87
+ playState: 1
88
+ };
89
+ try {
90
+ await act(async () => {
91
+ ReactDOM.render(/*#__PURE__*/React.createElement(VideoBitKBP, {
92
+ devId: 'device',
93
+ hideKbsMenu: false,
94
+ hideSignalMenu: true
95
+ }), container);
96
+ });
97
+ expect(container.innerHTML).toContain('<span class="ipc-player-plugin-videoBitKBP-kbps-text">ipc_player_resolution_HD 128 KB/S</span>');
98
+ } finally {
99
+ ReactDOM.unmountComponentAtNode(container);
100
+ }
101
+ });
102
+ it('keeps signal and auto clarity in the same bitrate badge', async () => {
103
+ const container = document.createElement('div');
104
+ getVideoBitrateKbps.mockResolvedValue({
105
+ code: 0,
106
+ data: {
107
+ kbps: '128'
108
+ }
109
+ });
110
+ requestWifiSignal.mockResolvedValue({
111
+ code: 0,
112
+ data: '-60'
113
+ });
114
+ mockStoreState = {
115
+ resolution: 'AUTO',
116
+ autoClarity: 'HD',
117
+ playState: 1
118
+ };
119
+ try {
120
+ var _container$querySelec, _container$querySelec2, _container$querySelec3, _container$querySelec4, _container$querySelec5;
121
+ await act(async () => {
122
+ ReactDOM.render(/*#__PURE__*/React.createElement(VideoBitKBP, {
123
+ devId: 'device'
124
+ }), container);
125
+ });
126
+ expect((_container$querySelec = container.querySelector('.ipc-player-plugin-videoBitKBP-signal')) === null || _container$querySelec === void 0 ? void 0 : _container$querySelec.textContent).toBe('-60dBm');
127
+ expect((_container$querySelec2 = container.querySelector('.ipc-player-plugin-videoBitKBP-kbps')) === null || _container$querySelec2 === void 0 ? void 0 : _container$querySelec2.textContent).toBe('ipc_player_resolution_HD 128 KB/S');
128
+ expect(Array.from((_container$querySelec3 = (_container$querySelec4 = container.querySelector('.ipc-player-plugin-videoBitKBP-content')) === null || _container$querySelec4 === void 0 ? void 0 : _container$querySelec4.children) !== null && _container$querySelec3 !== void 0 ? _container$querySelec3 : []).map(element => element.className)).toEqual(['ipc-player-plugin-videoBitKBP-signal', 'ipc-player-plugin-videoBitKBP-divider', 'ipc-player-plugin-videoBitKBP-kbps']);
129
+ mockStoreState = {
130
+ resolution: 'HD',
131
+ autoClarity: 'HD',
132
+ playState: 1
133
+ };
134
+ act(() => {
135
+ ReactDOM.render(/*#__PURE__*/React.createElement(VideoBitKBP, {
136
+ devId: 'device'
137
+ }), container);
138
+ });
139
+ expect((_container$querySelec5 = container.querySelector('.ipc-player-plugin-videoBitKBP-kbps')) === null || _container$querySelec5 === void 0 ? void 0 : _container$querySelec5.textContent).toBe('128 KB/S');
140
+ } finally {
141
+ ReactDOM.unmountComponentAtNode(container);
142
+ }
143
+ });
144
+ it('shows actual clarity independently of bitrate, signal and play state', () => {
145
+ const markup = renderWidget('AUTO', 'HD', 2);
146
+ expect(markup).toContain('ipc_player_resolution_HD');
147
+ expect(markup).not.toContain('KB/S');
148
+ expect(markup).toContain('<span class="ipc-player-plugin-videoBitKBP-kbps-text">ipc_player_resolution_HD</span>');
149
+ });
150
+ it('does not show clarity outside auto mode', () => {
151
+ expect(renderWidget('SD', 'HD')).toBe('');
152
+ });
153
+ it('waits for the native clarity report in auto mode', () => {
154
+ expect(renderWidget('AUTO', null)).toBe('');
155
+ });
156
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/ipc-player-integration",
3
- "version": "0.0.53-beta.1",
3
+ "version": "0.0.53-beta.11",
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.3",
40
+ "@ray-js/ray-ipc-player": "2.1.4-beta.0",
41
41
  "@ray-js/ray-ipc-utils": "^1.1.16",
42
42
  "@ray-js/svg": "0.2.0",
43
43
  "clsx": "^1.2.1",