@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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,150 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import { act, renderHook } from '@testing-library/react-hooks';
3
+ import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
4
+ import { createUseCtx } from './ctx';
5
+ import { useStore } from './store';
6
+ import { PlayState } from '../interface';
7
+ import { getCachedAutoClarity, setCachedAutoClarity, subscribeClarityChanged } from '../utils/ttt';
8
+ jest.mock('@ray-js/ray', () => ({}));
9
+ jest.mock('@ray-js/ray-ipc-utils/lib/interface', () => ({
10
+ ClarityType: {
11
+ SS: 'SS',
12
+ SD: 'SD',
13
+ HD: 'HD',
14
+ UD: 'UD',
15
+ SSP: 'SSP',
16
+ AUTO: 'AUTO',
17
+ AUDIO: 'AUDIO'
18
+ },
19
+ IntercomMode: {
20
+ OneWay: 'OneWay',
21
+ TwoWay: 'TwoWay'
22
+ }
23
+ }));
24
+ jest.mock('../i18n', () => ({
25
+ __esModule: true,
26
+ default: {
27
+ getLang: key => key
28
+ }
29
+ }));
30
+ jest.mock('./multiCameraCtx', () => ({
31
+ isMultiCameraTileSupported: () => false,
32
+ useMultiCameraCtx: () => ({})
33
+ }));
34
+ jest.mock('../utils/ttt', () => ({
35
+ getCachedAutoClarity: jest.fn(),
36
+ isClarityChangedSupported: () => true,
37
+ setCachedAutoClarity: jest.fn(),
38
+ subscribeClarityChanged: jest.fn(() => () => undefined)
39
+ }));
40
+ const cameraState = resolution => ({
41
+ resolution,
42
+ resolutionList: [ClarityType.HD, ClarityType.SD],
43
+ mute: true,
44
+ intercomMode: 'TwoWay',
45
+ isIntercomSupported: false,
46
+ maxZoomSettings: 6
47
+ });
48
+ describe('cached auto clarity restoration', () => {
49
+ beforeEach(() => {
50
+ jest.clearAllMocks();
51
+ });
52
+ const mountContext = resolution => {
53
+ const setClarity = jest.fn();
54
+ const getMemoryState = jest.fn().mockResolvedValue(cameraState(resolution));
55
+ const useCtx = createUseCtx({
56
+ createPlayContext: () => ({
57
+ setClarity
58
+ }),
59
+ getMemoryState,
60
+ setResolutionMemoryState: jest.fn(),
61
+ setMuteMemoryState: jest.fn(),
62
+ authorizeStatus: jest.fn(),
63
+ toast: jest.fn()
64
+ });
65
+ const hook = renderHook(() => {
66
+ const ctx = useCtx({
67
+ devId: 'camera-1'
68
+ });
69
+ const state = useStore({
70
+ resolution: ctx.resolution,
71
+ autoClarity: ctx.autoClarity
72
+ });
73
+ return _objectSpread(_objectSpread({}, ctx), {}, {
74
+ state
75
+ });
76
+ });
77
+ return _objectSpread(_objectSpread({}, hook), {}, {
78
+ setClarity
79
+ });
80
+ };
81
+ it('shows last listener value on reopening AUTO and refreshes it after preview', async () => {
82
+ getCachedAutoClarity.mockReturnValue(ClarityType.HD);
83
+ const {
84
+ result,
85
+ setClarity,
86
+ unmount
87
+ } = mountContext(ClarityType.AUTO);
88
+ await act(async () => Promise.resolve());
89
+ expect(result.current.state).toEqual({
90
+ resolution: ClarityType.AUTO,
91
+ autoClarity: ClarityType.HD
92
+ });
93
+ act(() => result.current.setPlayState(PlayState.PLAYING));
94
+ await act(async () => Promise.resolve());
95
+ expect(setClarity).toHaveBeenCalledTimes(1);
96
+ expect(setClarity).toHaveBeenCalledWith(expect.objectContaining({
97
+ clarity: 'auto'
98
+ }));
99
+ const onReport = subscribeClarityChanged.mock.calls[0][1];
100
+ act(() => onReport({
101
+ deviceId: 'camera-1',
102
+ clarity: ClarityType.SD
103
+ }));
104
+ expect(result.current.state.autoClarity).toBe(ClarityType.SD);
105
+ expect(setCachedAutoClarity).toHaveBeenCalledWith('camera-1', ClarityType.SD);
106
+ unmount();
107
+ });
108
+ it('does not restore cached actual clarity in manual mode', async () => {
109
+ getCachedAutoClarity.mockReturnValue(ClarityType.HD);
110
+ const {
111
+ result,
112
+ unmount
113
+ } = mountContext(ClarityType.SD);
114
+ await act(async () => Promise.resolve());
115
+ expect(result.current.state).toEqual({
116
+ resolution: ClarityType.SD,
117
+ autoClarity: null
118
+ });
119
+ expect(getCachedAutoClarity).not.toHaveBeenCalled();
120
+ const onReport = subscribeClarityChanged.mock.calls[0][1];
121
+ act(() => onReport({
122
+ deviceId: 'camera-1',
123
+ clarity: ClarityType.HD
124
+ }));
125
+ expect(result.current.state.autoClarity).toBeNull();
126
+ expect(setCachedAutoClarity).not.toHaveBeenCalled();
127
+ unmount();
128
+ });
129
+ it('requests a fresh report when reopening AUTO without an actual clarity cache', async () => {
130
+ getCachedAutoClarity.mockReturnValue(null);
131
+ const {
132
+ result,
133
+ setClarity,
134
+ unmount
135
+ } = mountContext(ClarityType.AUTO);
136
+ await act(async () => Promise.resolve());
137
+ expect(result.current.state.autoClarity).toBeNull();
138
+ act(() => result.current.setPlayState(PlayState.PLAYING));
139
+ expect(setClarity).toHaveBeenCalledWith(expect.objectContaining({
140
+ clarity: 'auto'
141
+ }));
142
+ const onReport = subscribeClarityChanged.mock.calls[0][1];
143
+ act(() => onReport({
144
+ deviceId: 'camera-1',
145
+ clarity: ClarityType.HD
146
+ }));
147
+ expect(result.current.state.autoClarity).toBe(ClarityType.HD);
148
+ unmount();
149
+ });
150
+ });
package/lib/ctx/ctx.js CHANGED
@@ -12,6 +12,7 @@ import { changeIgnoreHideStopPreview } from '../ui/constant';
12
12
  import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
13
13
  import { getEventInstance } from './event';
14
14
  import { isMultiCameraTileSupported, useMultiCameraCtx } from './multiCameraCtx';
15
+ import { getCachedAutoClarity, isClarityChangedSupported, setCachedAutoClarity, subscribeClarityChanged } from '../utils/ttt';
15
16
  const SAVE_TO_ALBUM = 1;
16
17
  export const createUseCtx = _ref => {
17
18
  let {
@@ -74,6 +75,8 @@ export const createUseCtx = _ref => {
74
75
  const [resolution] = useAtom('HD');
75
76
  // resolution 清晰度列表
76
77
  const [resolutionList, setResolutionList] = useAtom([]);
78
+ // 自动模式下宿主上报的实际清晰度,供横竖屏码率区域共用
79
+ const [autoClarity] = useAtom(null);
77
80
 
78
81
  // 单向对讲还是双向对讲
79
82
  const [intercomMode, setIntercomMode] = useAtom(IntercomMode.TwoWay);
@@ -101,22 +104,66 @@ export const createUseCtx = _ref => {
101
104
  const [bottomRightContent] = useAtom(initBottomRightContent || defaultBottomRightContent || []);
102
105
  const [absoluteContent] = useAtom(initAbsoluteContent || defaultAbsoluteContent || []);
103
106
  const {
104
- _playState
107
+ _playState,
108
+ currentResolution
105
109
  } = useStore({
106
- _playState: playState
110
+ _playState: playState,
111
+ currentResolution: resolution
107
112
  });
113
+ const restoredAutoRef = useRef(false);
114
+ const refreshedAutoRef = useRef(false);
115
+ const freshAutoClarityRef = useRef(false);
116
+ const pendingAutoSelectionRef = useRef(false);
117
+ const userSelectedResolutionRef = useRef(false);
118
+ useEffect(() => {
119
+ updateAtom(autoClarity, null);
120
+ restoredAutoRef.current = false;
121
+ refreshedAutoRef.current = false;
122
+ freshAutoClarityRef.current = false;
123
+ userSelectedResolutionRef.current = false;
124
+ if (!devId) return undefined;
125
+ return subscribeClarityChanged(devId, res => {
126
+ if (getDefaultStore().get(resolution) !== ClarityType.AUTO && !pendingAutoSelectionRef.current) {
127
+ return;
128
+ }
129
+ freshAutoClarityRef.current = true;
130
+ updateAtom(autoClarity, res.clarity);
131
+ setCachedAutoClarity(devId, res.clarity);
132
+ });
133
+ }, [autoClarity, devId, resolution]);
108
134
  const eventRef = useRef();
109
135
  if (!eventRef.current) {
110
136
  eventRef.current = getEventInstance();
111
137
  }
112
138
 
113
139
  /**
114
- * 自动清晰度作为独立档位并入清晰度列表:
140
+ * 只有宿主支持自动清晰度事件,且接口返回的清晰度档位数量不少于 2 个时,才展示 AUTO:
115
141
  * 竖屏宿主弹框(由 resolutionList 构建 actionData)与横屏 FullResolutionControl 共用。
116
142
  */
143
+ const canShowAutoClarity = function () {
144
+ let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
145
+ return isClarityChangedSupported() && list.length >= 2;
146
+ };
117
147
  const withAutoClarity = function () {
118
148
  let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
119
- return list.includes(ClarityType.AUTO) ? list : [...list, ClarityType.AUTO];
149
+ const withoutAuto = list.filter(clarity => clarity !== ClarityType.AUTO);
150
+ return canShowAutoClarity(list) ? [...withoutAuto, ClarityType.AUTO] : withoutAuto;
151
+ };
152
+ const normalizeResolution = (resolution, list) => {
153
+ if (resolution !== ClarityType.AUTO || canShowAutoClarity(list)) return resolution;
154
+ return list.find(clarity => clarity !== ClarityType.AUTO) || ClarityType.HD;
155
+ };
156
+ const restoreResolution = (cachedResolution, list) => {
157
+ if (userSelectedResolutionRef.current) return;
158
+ const target = normalizeResolution(cachedResolution, list);
159
+ if (target === ClarityType.AUTO) {
160
+ restoredAutoRef.current = true;
161
+ const cachedClarity = getCachedAutoClarity(devId);
162
+ if (cachedClarity && list.includes(cachedClarity) && !getDefaultStore().get(autoClarity)) {
163
+ updateAtom(autoClarity, cachedClarity);
164
+ }
165
+ }
166
+ _setResolution(target, true);
120
167
  };
121
168
  useEffect(() => {
122
169
  // 初始化获取缓存值
@@ -127,7 +174,7 @@ export const createUseCtx = _ref => {
127
174
  var _res$maxZoomSettings;
128
175
  const res = await getMemoryState(devId);
129
176
  setResolutionList(withAutoClarity(res.resolutionList));
130
- _setResolution(res.resolution, true);
177
+ restoreResolution(res.resolution, res.resolutionList);
131
178
  _setMute(res.mute, true);
132
179
  setIntercomMode(res.intercomMode);
133
180
  setIntercomSupported(res.isIntercomSupported);
@@ -144,7 +191,7 @@ export const createUseCtx = _ref => {
144
191
  var _res$maxZoomSettings2;
145
192
  setResolutionList(withAutoClarity(res.resolutionList));
146
193
  // 传true表示值即可,会取播放器的值
147
- _setResolution(res.resolution, true);
194
+ restoreResolution(res.resolution, res.resolutionList);
148
195
  _setMute(res.mute, true);
149
196
  setIntercomMode(res.intercomMode);
150
197
  setIntercomSupported(res.isIntercomSupported);
@@ -152,6 +199,18 @@ export const createUseCtx = _ref => {
152
199
  });
153
200
  }
154
201
  }, [devId, _playState]);
202
+ useEffect(() => {
203
+ var _IPCPlayerInstance$cu;
204
+ if (!devId || _playState !== PlayState.PLAYING || currentResolution !== ClarityType.AUTO || !restoredAutoRef.current || freshAutoClarityRef.current || refreshedAutoRef.current) {
205
+ return;
206
+ }
207
+ refreshedAutoRef.current = true;
208
+ // 缓存只保证首屏有上次档位;出流后重申自动,让宿主回报本次实际档位。
209
+ (_IPCPlayerInstance$cu = IPCPlayerInstance.current) === null || _IPCPlayerInstance$cu === void 0 || _IPCPlayerInstance$cu.setClarity({
210
+ clarity: 'auto',
211
+ fail: error => console.warn('res===restore auto clarity fail', error)
212
+ });
213
+ }, [devId, _playState, currentResolution]);
155
214
  // 获取content数据
156
215
  const getContent = () => {
157
216
  const store = getDefaultStore();
@@ -246,6 +305,13 @@ export const createUseCtx = _ref => {
246
305
  updateAtom(resolution, target);
247
306
  return false;
248
307
  }
308
+ userSelectedResolutionRef.current = true;
309
+ // 清晰度事件可能在 setClarity 的 success 回调前到达,进入自动前先清掉上次的值。
310
+ restoredAutoRef.current = false;
311
+ if (target === ClarityType.AUTO) {
312
+ pendingAutoSelectionRef.current = true;
313
+ updateAtom(autoClarity, null);
314
+ }
249
315
  return new Promise((resolve, reject) => {
250
316
  const clarityMap = {
251
317
  [ClarityType.SS]: 'ss',
@@ -259,11 +325,13 @@ export const createUseCtx = _ref => {
259
325
  IPCPlayerInstance.current.setClarity({
260
326
  clarity: clarityMap[target] || 'normal',
261
327
  success: () => {
328
+ pendingAutoSelectionRef.current = false;
262
329
  setResolutionMemoryState(devId, target);
263
330
  updateAtom(resolution, target);
264
331
  resolve(true);
265
332
  },
266
333
  fail: err => {
334
+ pendingAutoSelectionRef.current = false;
267
335
  console.log(err, 'setClarity err');
268
336
  // updateAtom(mute, !target);
269
337
  reject(err);
@@ -315,6 +383,7 @@ export const createUseCtx = _ref => {
315
383
  mute,
316
384
  resolution,
317
385
  resolutionList,
386
+ autoClarity,
318
387
  intercom,
319
388
  intercomMode,
320
389
  intercomSupported,
@@ -1,9 +1,13 @@
1
1
  import { kit } from '@ray-js/panel-sdk';
2
2
  declare const Strings: kit.I18N<{
3
3
  en: {
4
+ ipc_player_resolution_SS: string;
4
5
  ipc_player_resolution_HD: string;
5
6
  ipc_player_resolution_SD: string;
7
+ ipc_player_resolution_UD: string;
8
+ ipc_player_resolution_SSP: string;
6
9
  ipc_player_resolution_AUTO: string;
10
+ ipc_player_resolution_AUDIO: string;
7
11
  ipc_player_current_resolution_is_equal: string;
8
12
  ipc_player_screenshot_success_tip: string;
9
13
  ipc_player_screenshot_multi_success_tip: string;
@@ -42,9 +46,13 @@ declare const Strings: kit.I18N<{
42
46
  ipc_player_low_phone_not_support: string;
43
47
  };
44
48
  zh: {
49
+ ipc_player_resolution_SS: string;
45
50
  ipc_player_resolution_HD: string;
46
51
  ipc_player_resolution_SD: string;
52
+ ipc_player_resolution_UD: string;
53
+ ipc_player_resolution_SSP: string;
47
54
  ipc_player_resolution_AUTO: string;
55
+ ipc_player_resolution_AUDIO: string;
48
56
  ipc_player_current_resolution_is_equal: string;
49
57
  ipc_player_screenshot_success_tip: string;
50
58
  ipc_player_screenshot_multi_success_tip: string;
@@ -83,9 +91,13 @@ declare const Strings: kit.I18N<{
83
91
  ipc_player_low_phone_not_support: string;
84
92
  };
85
93
  }, {
94
+ ipc_player_resolution_SS: string;
86
95
  ipc_player_resolution_HD: string;
87
96
  ipc_player_resolution_SD: string;
97
+ ipc_player_resolution_UD: string;
98
+ ipc_player_resolution_SSP: string;
88
99
  ipc_player_resolution_AUTO: string;
100
+ ipc_player_resolution_AUDIO: string;
89
101
  ipc_player_current_resolution_is_equal: string;
90
102
  ipc_player_screenshot_success_tip: string;
91
103
  ipc_player_screenshot_multi_success_tip: string;
@@ -123,9 +135,13 @@ declare const Strings: kit.I18N<{
123
135
  ipc_player_fetch_error: string;
124
136
  ipc_player_low_phone_not_support: string;
125
137
  } | {
138
+ ipc_player_resolution_SS: string;
126
139
  ipc_player_resolution_HD: string;
127
140
  ipc_player_resolution_SD: string;
141
+ ipc_player_resolution_UD: string;
142
+ ipc_player_resolution_SSP: string;
128
143
  ipc_player_resolution_AUTO: string;
144
+ ipc_player_resolution_AUDIO: string;
129
145
  ipc_player_current_resolution_is_equal: string;
130
146
  ipc_player_screenshot_success_tip: string;
131
147
  ipc_player_screenshot_multi_success_tip: string;
@@ -1,8 +1,12 @@
1
1
  declare const _default: {
2
2
  en: {
3
+ ipc_player_resolution_SS: string;
3
4
  ipc_player_resolution_HD: string;
4
5
  ipc_player_resolution_SD: string;
6
+ ipc_player_resolution_UD: string;
7
+ ipc_player_resolution_SSP: string;
5
8
  ipc_player_resolution_AUTO: string;
9
+ ipc_player_resolution_AUDIO: string;
6
10
  ipc_player_current_resolution_is_equal: string;
7
11
  ipc_player_screenshot_success_tip: string;
8
12
  ipc_player_screenshot_multi_success_tip: string;
@@ -41,9 +45,13 @@ declare const _default: {
41
45
  ipc_player_low_phone_not_support: string;
42
46
  };
43
47
  zh: {
48
+ ipc_player_resolution_SS: string;
44
49
  ipc_player_resolution_HD: string;
45
50
  ipc_player_resolution_SD: string;
51
+ ipc_player_resolution_UD: string;
52
+ ipc_player_resolution_SSP: string;
46
53
  ipc_player_resolution_AUTO: string;
54
+ ipc_player_resolution_AUDIO: string;
47
55
  ipc_player_current_resolution_is_equal: string;
48
56
  ipc_player_screenshot_success_tip: string;
49
57
  ipc_player_screenshot_multi_success_tip: string;
@@ -1,8 +1,12 @@
1
1
  export default {
2
2
  en: {
3
+ ipc_player_resolution_SS: 'Data Saver',
3
4
  ipc_player_resolution_HD: 'HD',
4
5
  ipc_player_resolution_SD: 'SD',
6
+ ipc_player_resolution_UD: 'Ultra HD',
7
+ ipc_player_resolution_SSP: 'Super Ultra HD',
5
8
  ipc_player_resolution_AUTO: 'Auto',
9
+ ipc_player_resolution_AUDIO: 'Audio Mode',
6
10
  ipc_player_current_resolution_is_equal: 'Already at current clarity',
7
11
  ipc_player_screenshot_success_tip: 'Screenshot saved to album',
8
12
  ipc_player_screenshot_multi_success_tip: 'Screenshots saved to album',
@@ -41,9 +45,13 @@ export default {
41
45
  ipc_player_low_phone_not_support: 'This feature is not supported on this device'
42
46
  },
43
47
  zh: {
48
+ ipc_player_resolution_SS: '省流量',
44
49
  ipc_player_resolution_HD: '高清',
45
50
  ipc_player_resolution_SD: '标清',
51
+ ipc_player_resolution_UD: '超清',
52
+ ipc_player_resolution_SSP: '超超清',
46
53
  ipc_player_resolution_AUTO: '自动',
54
+ ipc_player_resolution_AUDIO: '音频模式',
47
55
  ipc_player_current_resolution_is_equal: '已是当前清晰度',
48
56
  ipc_player_screenshot_success_tip: '截图已保存在APP相册',
49
57
  ipc_player_screenshot_multi_success_tip: '图片已保存至相册',
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { PrimitiveAtom } from 'jotai';
3
+ import type { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
3
4
  import type { Toast, IntercomMode } from './ports.output';
4
5
  import { useMultiCameraCtx } from './ctx/multiCameraCtx';
5
6
  import type { ZoomSkill } from './widgets/zoomTurntable/lensSkill';
@@ -74,6 +75,7 @@ export type UseCtx = (options: {
74
75
  setZoomLensIndex: (value: number) => void;
75
76
  resolution: RetAtom<string>;
76
77
  resolutionList: RetAtom<string[]>;
78
+ autoClarity: RetAtom<ClarityType | null>;
77
79
  playState: RetAtom<PlayState>;
78
80
  IPCPlayerInstance: IpcContext;
79
81
  topLeftContent: RetAtom<ComponentConfig[]>;
@@ -143,12 +145,7 @@ export type CaptureFileInfo = {
143
145
  height?: number;
144
146
  data?: string;
145
147
  };
146
- export type MultiCaptureFileInfo = CaptureFileInfo & {
147
- index: number;
148
- };
149
- export type CaptureResult = boolean | CaptureFileInfo | {
150
- items: MultiCaptureFileInfo[];
151
- };
148
+ export type CaptureResult = boolean | CaptureFileInfo;
152
149
  export type RecordInfoData = CaptureResult;
153
150
  /**
154
151
  * 多目屏幕模式
@@ -60,12 +60,6 @@ export declare const widgetLabs: {
60
60
  */
61
61
  export declare const bottomLeftContentResize = "bottomLeftContentResize";
62
62
  export declare const zoomLevelChange = "zoomLevelChange";
63
- /**
64
- * 自动清晰度状态变化事件:Resolution 控件检测到清晰度进入/退出自动模式或收到
65
- * clarityChanged 回调结果时触发,携带 { enabled, clarity }(clarity 为 'HD' | 'SD' | null)。
66
- * VideoBitKBP 监听此事件,在码率前展示当前高清/标清文案。
67
- */
68
- export declare const autoClarityChange = "autoClarityChange";
69
63
  export declare const setScaleMultipleEvent = "setScaleMultipleEvent";
70
64
  export declare const decodeClarityDic: {
71
65
  SS: string;
@@ -63,13 +63,6 @@ export const widgetLabs = {
63
63
  */
64
64
  export const bottomLeftContentResize = 'bottomLeftContentResize';
65
65
  export const zoomLevelChange = 'zoomLevelChange';
66
-
67
- /**
68
- * 自动清晰度状态变化事件:Resolution 控件检测到清晰度进入/退出自动模式或收到
69
- * clarityChanged 回调结果时触发,携带 { enabled, clarity }(clarity 为 'HD' | 'SD' | null)。
70
- * VideoBitKBP 监听此事件,在码率前展示当前高清/标清文案。
71
- */
72
- export const autoClarityChange = 'autoClarityChange';
73
66
  export const setScaleMultipleEvent = 'setScaleMultipleEvent';
74
67
  export const decodeClarityDic = {
75
68
  SS: 'ss',
package/lib/ui/ui.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
3
  import "core-js/modules/esnext.iterator.constructor.js";
3
4
  import "core-js/modules/esnext.iterator.filter.js";
4
5
  import "core-js/modules/esnext.iterator.find.js";
5
6
  import "core-js/modules/esnext.iterator.map.js";
7
+ import "core-js/modules/esnext.iterator.some.js";
6
8
  import React, { useContext, useState, useRef, useMemo, useEffect, useImperativeHandle } from 'react';
7
9
  import { View, CoverView, getSystemInfoSync, usePageEvent, setNavigationBarBack, setPageOrientation, getCurrentPages } from '@ray-js/ray';
8
10
  import { unstable_batchedUpdates as batchedUpdates } from '@ray-core/ray';
9
11
  import clsx from 'clsx';
10
12
  import IPCPlayer from '@ray-js/ray-ipc-player';
11
13
  import { ipcTTTOperatorLog } from '@ray-js/ray-ipc-utils';
14
+ import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
12
15
  import { PlayState, PlayerStreamStatus, MultiCameraScreenMode } from '../interface';
13
16
  import { useCtx } from '../ctx/ctx.composition';
14
17
  import { useStore, updateAtom, getDefaultStore } from '../ctx/store';
@@ -18,7 +21,7 @@ import BottomLeftContent from './bottomLeftContent';
18
21
  import BottomRightContent from './bottomRightContent';
19
22
  import TopLeftContent from './topLeftContent';
20
23
  import TopRightContent from './topRightContent';
21
- import { FlowLowTip } from '../widgets';
24
+ import { FlowLowTip, VideoBitKBP } from '../widgets';
22
25
  import { useMemoizedFn } from '../hooks';
23
26
  import { Storage } from '../utils/storage';
24
27
  import './ui.less';
@@ -27,6 +30,36 @@ import { getNgRawData, getSmartImageQualityState, isLowPhone, notifyOfflineShown
27
30
  import { getCaptureResultSummary } from '../utils/captureResult';
28
31
  import { lensCount } from '../widgets/zoomTurntable/lensSkill';
29
32
  import { shouldRenderContent } from './absoluteContent';
33
+ const AutoClarityOnly = _ref => {
34
+ let {
35
+ instance
36
+ } = _ref;
37
+ return /*#__PURE__*/React.createElement(VideoBitKBP, _extends({}, instance, {
38
+ IPCPlayerContext: instance.IPCPlayerInstance,
39
+ className: "top-right-item-container",
40
+ hideKbsMenu: true,
41
+ hideSignalMenu: true
42
+ }));
43
+ };
44
+ const StandaloneAutoClarity = _ref2 => {
45
+ let {
46
+ instance,
47
+ show
48
+ } = _ref2;
49
+ const {
50
+ resolution,
51
+ autoClarity
52
+ } = useStore({
53
+ resolution: instance.resolution,
54
+ autoClarity: instance.autoClarity
55
+ });
56
+ if (!show || resolution !== ClarityType.AUTO || !autoClarity) return null;
57
+ return /*#__PURE__*/React.createElement(TopRightContent, {
58
+ ctx: instance
59
+ }, /*#__PURE__*/React.createElement(AutoClarityOnly, {
60
+ instance: instance
61
+ }));
62
+ };
30
63
  function getCtxInstance(instance, devId) {
31
64
  if (instance) return instance;
32
65
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -661,8 +694,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
661
694
  setRecording(false, true);
662
695
  setIntercom(false, true);
663
696
  instance === null || instance === void 0 || instance.stopRecordingOnUnload().then(async result => {
664
- var _instance$multiCamera;
665
- const summary = await getCaptureResultSummary(result, instance === null || instance === void 0 || (_instance$multiCamera = instance.multiCameraCtx) === null || _instance$multiCamera === void 0 || (_instance$multiCamera = _instance$multiCamera.protocol) === null || _instance$multiCamera === void 0 ? void 0 : _instance$multiCamera.total_split_num, devId);
697
+ var _instance$multiLens, _instance$multiCamera;
698
+ const summary = await getCaptureResultSummary(result, {
699
+ multiLens: (_instance$multiLens = instance === null || instance === void 0 ? void 0 : instance.multiLens) !== null && _instance$multiLens !== void 0 ? _instance$multiLens : false,
700
+ protocolCount: instance === null || instance === void 0 || (_instance$multiCamera = instance.multiCameraCtx) === null || _instance$multiCamera === void 0 || (_instance$multiCamera = _instance$multiCamera.protocol) === null || _instance$multiCamera === void 0 ? void 0 : _instance$multiCamera.total_split_num,
701
+ devId
702
+ });
666
703
  ipcTTTOperatorLog(summary !== null && summary !== void 0 && summary.isMultiLens ? `hide: stop recording succeeded with ${summary.count} files` : 'hide: 调用停止录制方法成功');
667
704
  }).catch(() => {
668
705
  ipcTTTOperatorLog('hide: 调用停止录制方法失败');
@@ -1009,6 +1046,7 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
1009
1046
  };
1010
1047
  }, []);
1011
1048
  const playerReady = playState === PlayState.PLAYING;
1049
+ const hasVisibleBitrateWidget = topRightContent === null || topRightContent === void 0 ? void 0 : topRightContent.some(item => item.id === 'VideoBitKBP' && !item.hidden);
1012
1050
  /**
1013
1051
  * 监听当前的zoom比例状态
1014
1052
  */
@@ -1202,7 +1240,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
1202
1240
  ctx: instance
1203
1241
  }, renderTopLeftContent), /*#__PURE__*/React.createElement(TopRightContent, {
1204
1242
  ctx: instance
1205
- }, renderTopRightContent))), /*#__PURE__*/React.createElement(View, {
1243
+ }, renderTopRightContent, !hasVisibleBitrateWidget && /*#__PURE__*/React.createElement(AutoClarityOnly, {
1244
+ instance: instance
1245
+ })))), /*#__PURE__*/React.createElement(StandaloneAutoClarity, {
1246
+ instance: instance,
1247
+ show: !showTopContent || componentHideState || !playerReady
1248
+ }), /*#__PURE__*/React.createElement(View, {
1206
1249
  className: clsx('ipc-player-bottom-content', {
1207
1250
  'ipc-player-bottom-content-hide': componentHideState,
1208
1251
  'ipc-player-bottom-content-show': !componentHideState,
@@ -4,6 +4,11 @@ export type CaptureResultSummary = {
4
4
  isMultiLens: boolean;
5
5
  thumbnailPath: string;
6
6
  };
7
+ export type CaptureResultOptions = {
8
+ multiLens: boolean;
9
+ protocolCount?: number | string;
10
+ devId: string;
11
+ };
7
12
  /** 从新多目高级能力配置获取当前设备的总镜头数 */
8
13
  export declare function getMultiLensCountFromAbility(devId: string): Promise<number>;
9
- export declare function getCaptureResultSummary(result: CaptureResult, fallbackCount: number | undefined, devId: string): Promise<CaptureResultSummary | null>;
14
+ export declare function getCaptureResultSummary(result: CaptureResult, { multiLens, protocolCount, devId }: CaptureResultOptions): Promise<CaptureResultSummary | null>;
@@ -33,36 +33,38 @@ const extractPath = item => {
33
33
  if (typeof (item === null || item === void 0 ? void 0 : item.value) === 'string') return item.value;
34
34
  return '';
35
35
  };
36
- export async function getCaptureResultSummary(result, fallbackCount, devId) {
36
+ export async function getCaptureResultSummary(result, _ref) {
37
+ let {
38
+ multiLens,
39
+ protocolCount,
40
+ devId
41
+ } = _ref;
37
42
  if (!result || typeof result === 'boolean') return null;
38
- const rawResult = result;
39
- const singleThumb = extractPath(rawResult.tempImagePath) || extractPath(rawResult.thumbPath) || extractPath(rawResult.filePath) || '';
40
- if ('items' in result && Array.isArray(result.items) && result.items.length > 0) {
41
- const firstItem = result.items[0];
42
- const firstThumb = extractPath(firstItem === null || firstItem === void 0 ? void 0 : firstItem.tempImagePath) || extractPath(firstItem === null || firstItem === void 0 ? void 0 : firstItem.thumbPath) || extractPath(firstItem === null || firstItem === void 0 ? void 0 : firstItem.filePath) || singleThumb;
43
+ const thumbnailPath = extractPath(result.tempImagePath) || extractPath(result.thumbPath) || extractPath(result.filePath) || '';
44
+ if (!multiLens) {
43
45
  return {
44
- count: result.items.length,
45
- isMultiLens: true,
46
- thumbnailPath: firstThumb
46
+ count: 1,
47
+ isMultiLens: false,
48
+ thumbnailPath
47
49
  };
48
50
  }
49
- const legacySplitCount = fallbackCount && fallbackCount > 1 ? fallbackCount : 0;
51
+ const splitCount = Number(protocolCount) > 1 ? Number(protocolCount) : 0;
50
52
  const multiLensAbilityCount = await getMultiLensCountFromAbility(devId);
51
53
 
52
54
  // The native multi-lens snapshot can return one object while writing lens-specific
53
55
  // files. Use the ability result to distinguish that file-name convention from the
54
56
  // legacy split protocol.
55
- const multiCount = legacySplitCount || multiLensAbilityCount;
57
+ const multiCount = splitCount || multiLensAbilityCount;
56
58
  if (multiCount > 1) {
57
59
  return {
58
60
  count: multiCount,
59
61
  isMultiLens: true,
60
- thumbnailPath: multiLensAbilityCount > 1 ? normalizeMultiLensThumbnailPath(singleThumb) : singleThumb
62
+ thumbnailPath: multiLensAbilityCount > 1 ? normalizeMultiLensThumbnailPath(thumbnailPath) : thumbnailPath
61
63
  };
62
64
  }
63
65
  return {
64
66
  count: 1,
65
67
  isMultiLens: false,
66
- thumbnailPath: singleThumb
68
+ thumbnailPath
67
69
  };
68
70
  }