@ray-js/ipc-player-integration 0.0.53-beta.0 → 0.0.53-beta.10

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.
Files changed (36) hide show
  1. package/lib/ctx/ctx.autoClarity.test.d.ts +1 -0
  2. package/lib/ctx/ctx.autoClarity.test.js +150 -0
  3. package/lib/ctx/ctx.composition.js +1 -6
  4. package/lib/ctx/ctx.js +94 -7
  5. package/lib/features/initPlayerWidgets/index.js +0 -9
  6. package/lib/i18n/index.d.ts +20 -4
  7. package/lib/i18n/strings.d.ts +10 -2
  8. package/lib/i18n/strings.js +10 -2
  9. package/lib/interface.d.ts +4 -7
  10. package/lib/ui/constant.d.ts +0 -7
  11. package/lib/ui/constant.js +0 -8
  12. package/lib/ui/ui.js +50 -7
  13. package/lib/utils/captureResult.d.ts +6 -1
  14. package/lib/utils/captureResult.js +15 -13
  15. package/lib/utils/captureResult.test.js +42 -15
  16. package/lib/utils/ttt.autoClarity.test.d.ts +1 -0
  17. package/lib/utils/ttt.autoClarity.test.js +75 -0
  18. package/lib/utils/ttt.d.ts +18 -4
  19. package/lib/utils/ttt.js +83 -32
  20. package/lib/widgets/captureResult/captureResult.js +6 -10
  21. package/lib/widgets/captureResult/captureResult.less +59 -14
  22. package/lib/widgets/captureResult/captureResult.test.d.ts +1 -0
  23. package/lib/widgets/captureResult/captureResult.test.js +80 -0
  24. package/lib/widgets/recordVideo/recordVideo.js +5 -1
  25. package/lib/widgets/resolution/index.d.ts +0 -1
  26. package/lib/widgets/resolution/index.js +1 -2
  27. package/lib/widgets/resolution/resolution.js +0 -1
  28. package/lib/widgets/resolution/resolution.less +0 -4
  29. package/lib/widgets/screenshot/screenshot.js +5 -1
  30. package/lib/widgets/videoBitKBP/videoBitKBP.js +36 -37
  31. package/lib/widgets/videoBitKBP/videoBitKBP.less +2 -5
  32. package/lib/widgets/videoBitKBP/videoBitKBP.test.d.ts +1 -0
  33. package/lib/widgets/videoBitKBP/videoBitKBP.test.js +112 -0
  34. package/package.json +2 -2
  35. package/lib/widgets/resolution/autoClarity.d.ts +0 -13
  36. package/lib/widgets/resolution/autoClarity.js +0 -110
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,15 +21,45 @@ 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';
25
28
  import { updatePlayerWidgetProps } from '../features';
26
- import { getNgRawData, getSmartImageQualityState, isLowPhone, isOfflineForStream } from '../utils/ttt';
29
+ import { getNgRawData, getSmartImageQualityState, isLowPhone, notifyOfflineShown } from '../utils/ttt';
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
@@ -153,10 +186,10 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
153
186
  });
154
187
  }, []);
155
188
 
156
- // 设备离线时通知宿主视频流状态;isOfflineForStream 内部兼容没有该 TTT 方法的宿主。
189
+ // 监听设备在线状态,离线提示展示时通知宿主;notifyOfflineShown 内部兼容没有该 TTT 方法的宿主。
157
190
  useEffect(() => {
158
191
  if (!deviceOnline) {
159
- isOfflineForStream(devId);
192
+ notifyOfflineShown(devId);
160
193
  }
161
194
  }, [deviceOnline, devId]);
162
195
 
@@ -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
  }
@@ -24,14 +24,33 @@ describe('getCaptureResultSummary', () => {
24
24
  }
25
25
  }
26
26
  });
27
- await expect(getCaptureResultSummary(createCaptureResult(basePath), undefined, 'dev-1')).resolves.toEqual({
27
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
28
+ multiLens: true,
29
+ devId: 'dev-1'
30
+ })).resolves.toEqual({
28
31
  count: 4,
29
32
  isMultiLens: true,
30
33
  thumbnailPath: 'thingfile://tmp/capture_123_lens1.jpg'
31
34
  });
32
35
  });
33
- it('keeps the legacy path when the ability is unavailable', async () => {
34
- await expect(getCaptureResultSummary(createCaptureResult(basePath), 4, 'dev-1')).resolves.toEqual({
36
+ it('keeps the single-lens result for a legacy multi-camera device', async () => {
37
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
38
+ multiLens: false,
39
+ protocolCount: 4,
40
+ devId: 'dev-1'
41
+ })).resolves.toEqual({
42
+ count: 1,
43
+ isMultiLens: false,
44
+ thumbnailPath: basePath
45
+ });
46
+ expect(mockGetDeviceInfo).not.toHaveBeenCalled();
47
+ });
48
+ it('uses the protocol count when the multi-lens mode is enabled', async () => {
49
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
50
+ multiLens: true,
51
+ protocolCount: 4,
52
+ devId: 'dev-1'
53
+ })).resolves.toEqual({
35
54
  count: 4,
36
55
  isMultiLens: true,
37
56
  thumbnailPath: basePath
@@ -46,7 +65,11 @@ describe('getCaptureResultSummary', () => {
46
65
  }
47
66
  }
48
67
  });
49
- await expect(getCaptureResultSummary(createCaptureResult(basePath), 4, 'dev-1')).resolves.toEqual({
68
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
69
+ multiLens: true,
70
+ protocolCount: 4,
71
+ devId: 'dev-1'
72
+ })).resolves.toEqual({
50
73
  count: 4,
51
74
  isMultiLens: true,
52
75
  thumbnailPath: 'thingfile://tmp/capture_123_lens1.jpg'
@@ -61,29 +84,33 @@ describe('getCaptureResultSummary', () => {
61
84
  }
62
85
  });
63
86
  const path = 'thingfile://tmp/capture_123_lens1.jpg';
64
- await expect(getCaptureResultSummary(createCaptureResult(path), undefined, 'dev-1')).resolves.toEqual({
87
+ await expect(getCaptureResultSummary(createCaptureResult(path), {
88
+ multiLens: true,
89
+ devId: 'dev-1'
90
+ })).resolves.toEqual({
65
91
  count: 4,
66
92
  isMultiLens: true,
67
93
  thumbnailPath: path
68
94
  });
69
95
  });
70
96
  it('keeps a mono result unchanged', async () => {
71
- await expect(getCaptureResultSummary(createCaptureResult(basePath), undefined, 'dev-1')).resolves.toEqual({
97
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
98
+ multiLens: false,
99
+ devId: 'dev-1'
100
+ })).resolves.toEqual({
72
101
  count: 1,
73
102
  isMultiLens: false,
74
103
  thumbnailPath: basePath
75
104
  });
76
105
  });
77
- it('keeps item paths unchanged', async () => {
78
- await expect(getCaptureResultSummary({
79
- items: [{
80
- index: 1,
81
- tempImagePath: basePath,
82
- filePath: basePath
83
- }]
84
- }, undefined, 'dev-1')).resolves.toEqual({
106
+ it('keeps a single-lens result when multi-lens mode has one lens', async () => {
107
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), {
108
+ multiLens: true,
109
+ protocolCount: 1,
110
+ devId: 'dev-1'
111
+ })).resolves.toEqual({
85
112
  count: 1,
86
- isMultiLens: true,
113
+ isMultiLens: false,
87
114
  thumbnailPath: basePath
88
115
  });
89
116
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
2
+ import { getCachedAutoClarity, setCachedAutoClarity, subscribeClarityChanged } from './ttt';
3
+ jest.mock('@ray-js/ray-ipc-utils/lib/interface', () => ({
4
+ ClarityType: {
5
+ SS: 'SS',
6
+ SD: 'SD',
7
+ HD: 'HD',
8
+ UD: 'UD',
9
+ SSP: 'SSP',
10
+ AUTO: 'AUTO',
11
+ AUDIO: 'AUDIO'
12
+ }
13
+ }));
14
+ describe('auto clarity cache and listener', () => {
15
+ const storage = new Map();
16
+ let listener;
17
+ beforeEach(() => {
18
+ storage.clear();
19
+ globalThis.ty = {
20
+ getStorageSync: jest.fn(_ref => {
21
+ let {
22
+ key
23
+ } = _ref;
24
+ return storage.get(key);
25
+ }),
26
+ setStorageSync: jest.fn(_ref2 => {
27
+ let {
28
+ key,
29
+ data
30
+ } = _ref2;
31
+ return storage.set(key, data);
32
+ }),
33
+ ipc: {
34
+ onClarityChanged: jest.fn(callback => {
35
+ listener = callback;
36
+ }),
37
+ offClarityChanged: jest.fn()
38
+ }
39
+ };
40
+ });
41
+ it('restores the last reported actual clarity only for its device', () => {
42
+ setCachedAutoClarity('camera-1', ClarityType.HD);
43
+ expect(getCachedAutoClarity('camera-1')).toBe(ClarityType.HD);
44
+ expect(getCachedAutoClarity('camera-2')).toBeNull();
45
+ setCachedAutoClarity('camera-1', ClarityType.AUTO);
46
+ expect(getCachedAutoClarity('camera-1')).toBe(ClarityType.HD);
47
+ globalThis.ty.getStorageSync = jest.fn(() => ({
48
+ data: ClarityType.SD
49
+ }));
50
+ expect(getCachedAutoClarity('camera-1')).toBe(ClarityType.SD);
51
+ });
52
+ it('accepts a new actual clarity report for the same device', () => {
53
+ const handler = jest.fn();
54
+ const unsubscribe = subscribeClarityChanged('camera-1', handler);
55
+ listener({
56
+ deviceId: 'camera-2',
57
+ clarity: ClarityType.SD
58
+ });
59
+ listener({
60
+ deviceId: 'camera-1',
61
+ clarity: ClarityType.AUTO
62
+ });
63
+ listener({
64
+ deviceId: 'camera-1',
65
+ clarity: ClarityType.SD
66
+ });
67
+ expect(handler).toHaveBeenCalledTimes(1);
68
+ expect(handler).toHaveBeenCalledWith({
69
+ deviceId: 'camera-1',
70
+ clarity: ClarityType.SD
71
+ });
72
+ unsubscribe();
73
+ expect(globalThis.ty.ipc.offClarityChanged).toHaveBeenCalledWith(listener);
74
+ });
75
+ });
@@ -1,3 +1,4 @@
1
+ import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
1
2
  export type SmartImageQualityResult = {
2
3
  isPurchase: boolean;
3
4
  buttonState: number;
@@ -39,15 +40,28 @@ export declare function setAIFrameFeature(params: SetAIFrameFeatureParams): Prom
39
40
  export declare function setTrailFinish(devId: string): Promise<unknown>;
40
41
  export declare function isLowPhone(): Promise<boolean>;
41
42
  /**
42
- * 通知宿主当前视频流对应的设备已离线。
43
+ * 通知宿主离线提示已经展示。
43
44
  *
44
45
  * 这个 TTT 方法不是所有宿主都提供,因此调用前必须做能力判断;
45
46
  * 老宿主或 Web 环境下直接跳过,不能影响播放器自身的离线处理。
46
47
  */
47
- export declare function isOfflineForStream(devId: string): boolean;
48
+ export declare function notifyOfflineShown(deviceId: string): boolean;
48
49
  export declare function getNgRawData(): Promise<unknown>;
49
50
  export declare function isClarityChangedSupported(): boolean;
50
51
  export type ClarityChangedResult = {
51
- clarity: 'HD' | 'SD';
52
+ deviceId?: string;
53
+ clarity: ClarityType;
52
54
  };
53
- export declare function clarityChanged(devId: string): Promise<ClarityChangedResult | null>;
55
+ export type ClarityChangedHandler = (result: ClarityChangedResult) => void;
56
+ type ClarityChangedListener = (payload: ClarityChangedResult) => void;
57
+ export declare function getCachedAutoClarity(devId: string): ClarityType | null;
58
+ export declare function setCachedAutoClarity(devId: string, clarity: ClarityType): void;
59
+ export declare function offClarityChanged(listener: ClarityChangedListener): void;
60
+ /**
61
+ * 监听自动清晰度变化,返回取消监听函数。
62
+ *
63
+ * onClarityChanged / offClarityChanged 均使用同一个 listener 引用,
64
+ * 否则宿主无法正确移除监听。
65
+ */
66
+ export declare function subscribeClarityChanged(devId: string, handler: ClarityChangedHandler): () => void;
67
+ export {};
package/lib/utils/ttt.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import { ClarityType } from '@ray-js/ray-ipc-utils/lib/interface';
2
3
  export function getSmartImageQualityState(devId) {
3
4
  return new Promise(resolve => {
4
5
  var _ty$ipc;
@@ -122,24 +123,22 @@ export function isLowPhone() {
122
123
  }
123
124
 
124
125
  /**
125
- * 通知宿主当前视频流对应的设备已离线。
126
+ * 通知宿主离线提示已经展示。
126
127
  *
127
128
  * 这个 TTT 方法不是所有宿主都提供,因此调用前必须做能力判断;
128
129
  * 老宿主或 Web 环境下直接跳过,不能影响播放器自身的离线处理。
129
130
  */
130
- export function isOfflineForStream(devId) {
131
+ export function notifyOfflineShown(deviceId) {
131
132
  var _ty3;
132
- const method = (_ty3 = ty) === null || _ty3 === void 0 || (_ty3 = _ty3.ipc) === null || _ty3 === void 0 ? void 0 : _ty3.isOfflineForStream;
133
+ const method = typeof ty !== 'undefined' ? (_ty3 = ty) === null || _ty3 === void 0 || (_ty3 = _ty3.ipc) === null || _ty3 === void 0 ? void 0 : _ty3.notifyOfflineShown : undefined;
133
134
  if (typeof method !== 'function') {
134
135
  return false;
135
136
  }
136
137
  try {
137
- method({
138
- devId
139
- });
138
+ console.warn('res===notifyOfflineShown');
139
+ method(deviceId, 'preview_mini');
140
140
  return true;
141
141
  } catch (error) {
142
- console.warn('res===isOfflineForStream fail', error);
143
142
  return false;
144
143
  }
145
144
  }
@@ -167,35 +166,87 @@ export function getNgRawData() {
167
166
  });
168
167
  }
169
168
 
170
- // 是否支持自动清晰度(ttt 方法 clarityChanged 存在即支持)
169
+ // 是否支持自动清晰度(ttt 方法 onClarityChanged 存在即支持)
171
170
  export function isClarityChangedSupported() {
172
- var _ty$ipc6;
173
- return typeof ((_ty$ipc6 = ty.ipc) === null || _ty$ipc6 === void 0 ? void 0 : _ty$ipc6.clarityChanged) === 'function';
171
+ var _ty5;
172
+ return typeof ty !== 'undefined' && typeof ((_ty5 = ty) === null || _ty5 === void 0 || (_ty5 = _ty5.ipc) === null || _ty5 === void 0 ? void 0 : _ty5.onClarityChanged) === 'function';
174
173
  }
175
- export function clarityChanged(devId) {
176
- return new Promise(resolve => {
177
- var _ty$ipc7;
178
- if (typeof ((_ty$ipc7 = ty.ipc) === null || _ty$ipc7 === void 0 ? void 0 : _ty$ipc7.clarityChanged) !== 'function') {
179
- resolve(null);
174
+ const actualClarityTypes = [ClarityType.SS, ClarityType.SD, ClarityType.HD, ClarityType.UD, ClarityType.SSP];
175
+ const autoClarityStorageKey = devId => `${devId}_auto_clarity`;
176
+ export function getCachedAutoClarity(devId) {
177
+ try {
178
+ const stored = ty.getStorageSync({
179
+ key: autoClarityStorageKey(devId)
180
+ });
181
+ const clarity = typeof stored === 'string' ? stored : stored === null || stored === void 0 ? void 0 : stored.data;
182
+ return actualClarityTypes.includes(clarity) ? clarity : null;
183
+ } catch (error) {
184
+ return null;
185
+ }
186
+ }
187
+ export function setCachedAutoClarity(devId, clarity) {
188
+ if (!actualClarityTypes.includes(clarity)) return;
189
+ try {
190
+ ty.setStorageSync({
191
+ key: autoClarityStorageKey(devId),
192
+ data: clarity
193
+ });
194
+ } catch (error) {
195
+ console.warn('res===setCachedAutoClarity fail', error);
196
+ }
197
+ }
198
+ export function offClarityChanged(listener) {
199
+ var _ty6;
200
+ const ipc = typeof ty !== 'undefined' ? (_ty6 = ty) === null || _ty6 === void 0 ? void 0 : _ty6.ipc : undefined;
201
+ if (!ipc || typeof ipc.offClarityChanged !== 'function') {
202
+ return;
203
+ }
204
+ try {
205
+ ipc.offClarityChanged(listener);
206
+ } catch (error) {
207
+ console.warn('res===offClarityChanged fail', error);
208
+ }
209
+ }
210
+
211
+ /**
212
+ * 监听自动清晰度变化,返回取消监听函数。
213
+ *
214
+ * onClarityChanged / offClarityChanged 均使用同一个 listener 引用,
215
+ * 否则宿主无法正确移除监听。
216
+ */
217
+ export function subscribeClarityChanged(devId, handler) {
218
+ var _ty7;
219
+ const ipc = typeof ty !== 'undefined' ? (_ty7 = ty) === null || _ty7 === void 0 ? void 0 : _ty7.ipc : undefined;
220
+ if (!ipc || typeof ipc.onClarityChanged !== 'function') {
221
+ return () => undefined;
222
+ }
223
+ const listener = payload => {
224
+ console.log('[resolution] onClarityChanged 事件到达', JSON.stringify(payload !== null && payload !== void 0 ? payload : null));
225
+ const {
226
+ deviceId,
227
+ clarity
228
+ } = payload || {};
229
+ if (!actualClarityTypes.includes(clarity)) {
230
+ console.warn('[resolution] onClarityChanged 未返回实际清晰度');
180
231
  return;
181
232
  }
182
- if (!isClarityChangedSupported()) {
183
- resolve(null);
233
+ // 一页多设备时只认自己的;宿主没带 deviceId 就不过滤
234
+ if (deviceId && deviceId !== devId) {
235
+ console.warn('[resolution] onClarityChanged 非本设备,已忽略', `${deviceId} != ${devId}`);
184
236
  return;
185
237
  }
186
- try {
187
- ty.ipc.clarityChanged({
188
- devId,
189
- success: res => {
190
- resolve(res !== null && res !== void 0 ? res : null);
191
- },
192
- fail: e => {
193
- console.warn('res===clarityChanged fail', e);
194
- resolve(null);
195
- }
196
- });
197
- } catch (e) {
198
- resolve(null);
199
- }
200
- });
238
+ handler({
239
+ deviceId,
240
+ clarity
241
+ });
242
+ };
243
+ try {
244
+ ipc.onClarityChanged(listener);
245
+ } catch (error) {
246
+ console.warn('res===onClarityChanged fail', error);
247
+ return () => undefined;
248
+ }
249
+ return () => {
250
+ offClarityChanged(listener);
251
+ };
201
252
  }
@@ -1,11 +1,9 @@
1
- import "core-js/modules/esnext.iterator.constructor.js";
2
- import "core-js/modules/esnext.iterator.map.js";
3
1
  import React from 'react';
4
2
  import { Image, Text, View } from '@ray-js/ray';
5
3
  import clsx from 'clsx';
6
4
  import Strings from '../../i18n';
7
5
  import './captureResult.less';
8
- const THUMBNAIL_LAYERS = ['back', 'middle', 'front'];
6
+ const BACKDROP_LAYERS = ['back', 'middle'];
9
7
  const TEXT_KEYS = {
10
8
  record: {
11
9
  check: 'ipc_player_record_success_check',
@@ -59,14 +57,12 @@ export function CaptureResultToast(_ref) {
59
57
  className: clsx('ipc-player-plugin-capture-result-toast', legacyCls.toast, className)
60
58
  }, /*#__PURE__*/React.createElement(View, {
61
59
  className: clsx('ipc-player-plugin-capture-result-image-box', legacyCls.imageBox, isMultiLens && ['ipc-player-plugin-capture-result-image-box-multi', legacyCls.imageBoxMulti])
62
- }, isMultiLens ? THUMBNAIL_LAYERS.slice(0, count).map((layer, index) => /*#__PURE__*/React.createElement(Image, {
60
+ }, isMultiLens ? /*#__PURE__*/React.createElement(React.Fragment, null, BACKDROP_LAYERS.map(layer => /*#__PURE__*/React.createElement(View, {
63
61
  key: layer,
64
- className: imageClassName,
65
- src: thumbnailPath,
66
- style: {
67
- left: `${index * 5}px`,
68
- zIndex: index + 1
69
- }
62
+ className: clsx('ipc-player-plugin-capture-result-backdrop', `ipc-player-plugin-capture-result-image-${layer}`)
63
+ })), /*#__PURE__*/React.createElement(Image, {
64
+ className: clsx(imageClassName, 'ipc-player-plugin-capture-result-image-front'),
65
+ src: thumbnailPath
70
66
  })) : /*#__PURE__*/React.createElement(Image, {
71
67
  className: imageClassName,
72
68
  src: thumbnailPath