@ray-js/ipc-player-integration 0.0.52-beta.3 → 0.0.52-beta.5

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/lib/ui/ui.js CHANGED
@@ -653,9 +653,9 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
653
653
  ipcTTTOperatorLog('hide: 调用停止录制方法');
654
654
  setRecording(false, true);
655
655
  setIntercom(false, true);
656
- instance === null || instance === void 0 || instance.stopRecordingOnUnload().then(result => {
656
+ instance === null || instance === void 0 || instance.stopRecordingOnUnload().then(async result => {
657
657
  var _instance$multiCamera;
658
- const summary = 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);
658
+ 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);
659
659
  ipcTTTOperatorLog(summary !== null && summary !== void 0 && summary.isMultiLens ? `hide: stop recording succeeded with ${summary.count} files` : 'hide: 调用停止录制方法成功');
660
660
  }).catch(() => {
661
661
  ipcTTTOperatorLog('hide: 调用停止录制方法失败');
@@ -5,5 +5,5 @@ export type CaptureResultSummary = {
5
5
  thumbnailPath: string;
6
6
  };
7
7
  /** 从新多目高级能力配置获取当前设备的总镜头数 */
8
- export declare function getMultiLensCountFromAbility(): number;
9
- export declare function getCaptureResultSummary(result: CaptureResult, fallbackCount?: number): CaptureResultSummary | null;
8
+ export declare function getMultiLensCountFromAbility(devId: string): Promise<number>;
9
+ export declare function getCaptureResultSummary(result: CaptureResult, fallbackCount: number | undefined, devId: string): Promise<CaptureResultSummary | null>;
@@ -1,10 +1,16 @@
1
- import { getDevInfo } from '@ray-js/ray-ipc-utils';
1
+ /* eslint-disable camelcase */
2
+
3
+ import { getDeviceInfo } from './device';
4
+ const MULTI_LENS_ABILITY_CODE = 'tyabimr4v3';
5
+ const LENS_SUFFIX_PATTERN = /_lens\d+(?=\.[^./?#]+(?:[?#].*)?$)/;
6
+ const FILE_EXTENSION_PATTERN = /(\.[^./?#]+)([?#].*)?$/;
2
7
  /** 从新多目高级能力配置获取当前设备的总镜头数 */
3
- export function getMultiLensCountFromAbility() {
8
+ export async function getMultiLensCountFromAbility(devId) {
9
+ if (!devId) return 0;
4
10
  try {
5
11
  var _devInfo$configMetas;
6
- const devInfo = getDevInfo();
7
- const raw = devInfo === null || devInfo === void 0 || (_devInfo$configMetas = devInfo.configMetas) === null || _devInfo$configMetas === void 0 ? void 0 : _devInfo$configMetas.tyabimr4v3;
12
+ const devInfo = await getDeviceInfo(devId);
13
+ const raw = devInfo === null || devInfo === void 0 || (_devInfo$configMetas = devInfo.configMetas) === null || _devInfo$configMetas === void 0 ? void 0 : _devInfo$configMetas[MULTI_LENS_ABILITY_CODE];
8
14
  if (raw) {
9
15
  const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
10
16
  const count = Number(parsed === null || parsed === void 0 ? void 0 : parsed.total_split_num) || (Array.isArray(parsed === null || parsed === void 0 ? void 0 : parsed.split_info) ? parsed.split_info.length : 0);
@@ -17,13 +23,17 @@ export function getMultiLensCountFromAbility() {
17
23
  }
18
24
  return 0;
19
25
  }
26
+ const normalizeMultiLensThumbnailPath = path => {
27
+ if (!path || LENS_SUFFIX_PATTERN.test(path)) return path;
28
+ return path.replace(FILE_EXTENSION_PATTERN, '_lens1$1$2');
29
+ };
20
30
  const extractPath = item => {
21
31
  if (!item) return '';
22
32
  if (typeof item === 'string') return item;
23
33
  if (typeof (item === null || item === void 0 ? void 0 : item.value) === 'string') return item.value;
24
34
  return '';
25
35
  };
26
- export function getCaptureResultSummary(result, fallbackCount) {
36
+ export async function getCaptureResultSummary(result, fallbackCount, devId) {
27
37
  if (!result || typeof result === 'boolean') return null;
28
38
  const rawResult = result;
29
39
  const singleThumb = extractPath(rawResult.tempImagePath) || extractPath(rawResult.thumbPath) || extractPath(rawResult.filePath) || '';
@@ -36,14 +46,18 @@ export function getCaptureResultSummary(result, fallbackCount) {
36
46
  thumbnailPath: firstThumb
37
47
  };
38
48
  }
49
+ const legacySplitCount = fallbackCount && fallbackCount > 1 ? fallbackCount : 0;
50
+ const multiLensAbilityCount = await getMultiLensCountFromAbility(devId);
39
51
 
40
- // 根据新多目高级能力获取总镜头数(从协议传入的 fallbackCount 或从设备能力元数据获取)
41
- const multiCount = fallbackCount && fallbackCount > 1 ? fallbackCount : getMultiLensCountFromAbility();
52
+ // The native multi-lens snapshot can return one object while writing lens-specific
53
+ // files. Use the ability result to distinguish that file-name convention from the
54
+ // legacy split protocol.
55
+ const multiCount = legacySplitCount || multiLensAbilityCount;
42
56
  if (multiCount > 1) {
43
57
  return {
44
58
  count: multiCount,
45
59
  isMultiLens: true,
46
- thumbnailPath: singleThumb
60
+ thumbnailPath: multiLensAbilityCount > 1 ? normalizeMultiLensThumbnailPath(singleThumb) : singleThumb
47
61
  };
48
62
  }
49
63
  return {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,90 @@
1
+ import { getCaptureResultSummary } from './captureResult';
2
+ import { getDeviceInfo } from './device';
3
+ jest.mock('./device', () => ({
4
+ getDeviceInfo: jest.fn()
5
+ }));
6
+ const mockGetDeviceInfo = getDeviceInfo;
7
+ const basePath = 'thingfile://tmp/capture_123.jpg';
8
+ const createCaptureResult = tempImagePath => ({
9
+ tempImagePath,
10
+ filePath: tempImagePath
11
+ });
12
+ describe('getCaptureResultSummary', () => {
13
+ beforeEach(() => {
14
+ mockGetDeviceInfo.mockReset();
15
+ mockGetDeviceInfo.mockResolvedValue({
16
+ configMetas: {}
17
+ });
18
+ });
19
+ it('normalizes the thumbnail path for the new multi-lens ability', async () => {
20
+ mockGetDeviceInfo.mockResolvedValue({
21
+ configMetas: {
22
+ tyabimr4v3: {
23
+ total_split_num: 4
24
+ }
25
+ }
26
+ });
27
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), undefined, 'dev-1')).resolves.toEqual({
28
+ count: 4,
29
+ isMultiLens: true,
30
+ thumbnailPath: 'thingfile://tmp/capture_123_lens1.jpg'
31
+ });
32
+ });
33
+ it('keeps the legacy path when the ability is unavailable', async () => {
34
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), 4, 'dev-1')).resolves.toEqual({
35
+ count: 4,
36
+ isMultiLens: true,
37
+ thumbnailPath: basePath
38
+ });
39
+ expect(mockGetDeviceInfo).toHaveBeenCalledWith('dev-1');
40
+ });
41
+ it('uses the lens path when both multi-lens sources are present', async () => {
42
+ mockGetDeviceInfo.mockResolvedValue({
43
+ configMetas: {
44
+ tyabimr4v3: {
45
+ total_split_num: 4
46
+ }
47
+ }
48
+ });
49
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), 4, 'dev-1')).resolves.toEqual({
50
+ count: 4,
51
+ isMultiLens: true,
52
+ thumbnailPath: 'thingfile://tmp/capture_123_lens1.jpg'
53
+ });
54
+ });
55
+ it('does not add a duplicate lens suffix', async () => {
56
+ mockGetDeviceInfo.mockResolvedValue({
57
+ configMetas: {
58
+ tyabimr4v3: JSON.stringify({
59
+ total_split_num: 4
60
+ })
61
+ }
62
+ });
63
+ const path = 'thingfile://tmp/capture_123_lens1.jpg';
64
+ await expect(getCaptureResultSummary(createCaptureResult(path), undefined, 'dev-1')).resolves.toEqual({
65
+ count: 4,
66
+ isMultiLens: true,
67
+ thumbnailPath: path
68
+ });
69
+ });
70
+ it('keeps a mono result unchanged', async () => {
71
+ await expect(getCaptureResultSummary(createCaptureResult(basePath), undefined, 'dev-1')).resolves.toEqual({
72
+ count: 1,
73
+ isMultiLens: false,
74
+ thumbnailPath: basePath
75
+ });
76
+ });
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({
85
+ count: 1,
86
+ isMultiLens: true,
87
+ thumbnailPath: basePath
88
+ });
89
+ });
90
+ });
@@ -107,10 +107,18 @@ export function RecordVideo(props) {
107
107
  shotUrl: '',
108
108
  shotCount: 0
109
109
  });
110
- const showRecordResult = recordInfo => {
110
+ const recordResultRequestIdRef = useRef(0);
111
+ useEffect(() => {
112
+ return () => {
113
+ recordResultRequestIdRef.current += 1;
114
+ };
115
+ }, []);
116
+ const showRecordResult = async recordInfo => {
111
117
  var _props$multiCameraCtx;
118
+ const requestId = ++recordResultRequestIdRef.current;
112
119
  const splitNum = (_props$multiCameraCtx = props.multiCameraCtx) === null || _props$multiCameraCtx === void 0 || (_props$multiCameraCtx = _props$multiCameraCtx.protocol) === null || _props$multiCameraCtx === void 0 ? void 0 : _props$multiCameraCtx.total_split_num;
113
- const summary = getCaptureResultSummary(recordInfo, splitNum);
120
+ const summary = await getCaptureResultSummary(recordInfo, splitNum, devId);
121
+ if (requestId !== recordResultRequestIdRef.current) return;
114
122
  if (!summary) return;
115
123
  setState({
116
124
  showTimer: false,
@@ -131,7 +139,7 @@ export function RecordVideo(props) {
131
139
  showTimer: false
132
140
  });
133
141
  const recordInfo = await setRecording(false);
134
- showRecordResult(recordInfo);
142
+ await showRecordResult(recordInfo);
135
143
  } catch {
136
144
  // setRecording reports the native failure through the configured toast.
137
145
  }
@@ -247,6 +255,7 @@ export function RecordVideo(props) {
247
255
  if (recordingDisabled) {
248
256
  return false;
249
257
  }
258
+ recordResultRequestIdRef.current += 1;
250
259
  if (state.showShot && _recording) {
251
260
  setState({
252
261
  showShot: false
@@ -270,7 +279,7 @@ export function RecordVideo(props) {
270
279
  timeToResetRecordDisabled();
271
280
  } else {
272
281
  props.event ? props.event.emit(changeIgnoreHideStopPreview, false) : event.emit(changeIgnoreHideStopPreview, false);
273
- showRecordResult(recordInfo);
282
+ await showRecordResult(recordInfo);
274
283
  }
275
284
  } catch (err) {
276
285
  props.event ? props.event.emit(changeIgnoreHideStopPreview, false) : event.emit(changeIgnoreHideStopPreview, false);
@@ -1,4 +1,4 @@
1
- import React, { useContext, useRef } from 'react';
1
+ import React, { useContext, useEffect, useRef } from 'react';
2
2
  import { View, Text, showModal, openAppSystemSettingPage, getSystemInfoSync } from '@ray-js/ray';
3
3
  import { useSetState, useUpdateEffect, useMemoizedFn } from 'ahooks';
4
4
  import clsx from 'clsx';
@@ -39,6 +39,12 @@ export function Screenshot(props) {
39
39
  shotUrl: '',
40
40
  shotCount: 0
41
41
  });
42
+ const snapshotRequestIdRef = useRef(0);
43
+ useEffect(() => {
44
+ return () => {
45
+ snapshotRequestIdRef.current += 1;
46
+ };
47
+ }, []);
42
48
  useUpdateEffect(() => {
43
49
  if (state.showShot && screenType) {
44
50
  showShotToast();
@@ -126,13 +132,15 @@ export function Screenshot(props) {
126
132
  });
127
133
  };
128
134
  const takeSnapshot = () => {
135
+ const requestId = ++snapshotRequestIdRef.current;
129
136
  IPCPlayerContext.snapshot({
130
137
  saveToAlbum,
131
- success: res => {
138
+ success: async res => {
132
139
  var _props$multiCameraCtx;
133
140
  setIgnoreHideStopPreview(false);
134
141
  const splitNum = (_props$multiCameraCtx = props.multiCameraCtx) === null || _props$multiCameraCtx === void 0 || (_props$multiCameraCtx = _props$multiCameraCtx.protocol) === null || _props$multiCameraCtx === void 0 ? void 0 : _props$multiCameraCtx.total_split_num;
135
- const summary = getCaptureResultSummary(res, splitNum);
142
+ const summary = await getCaptureResultSummary(res, splitNum, devId);
143
+ if (requestId !== snapshotRequestIdRef.current) return;
136
144
  if (!summary) {
137
145
  handleSnapshotFail({});
138
146
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/ipc-player-integration",
3
- "version": "0.0.52-beta.3",
3
+ "version": "0.0.52-beta.5",
4
4
  "description": "IPC 融合播放器",
5
5
  "main": "lib/index",
6
6
  "files": [