@ray-js/ipc-player-integration 0.0.52-beta.2 → 0.0.52-beta.4

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/ctx/ctx.js CHANGED
@@ -254,13 +254,9 @@ export const createUseCtx = _ref => {
254
254
  });
255
255
  };
256
256
  const stopRecording = showError => {
257
- const sessionMultiLens = recordingMultiLensRef.current;
258
257
  return new Promise((resolve, reject) => {
259
- IPCPlayerInstance.current.stopRecord(_objectSpread(_objectSpread({
260
- saveToAlbum
261
- }, sessionMultiLens ? {
262
- multiLens: true
263
- } : {}), {}, {
258
+ IPCPlayerInstance.current.stopRecord({
259
+ saveToAlbum,
264
260
  success: res => {
265
261
  recordingMultiLensRef.current = false;
266
262
  updateAtom(recording, false);
@@ -278,7 +274,7 @@ export const createUseCtx = _ref => {
278
274
  });
279
275
  }
280
276
  }
281
- }));
277
+ });
282
278
  });
283
279
  };
284
280
  const multiCameraCtx = useMultiCameraCtx({
@@ -437,15 +433,10 @@ export const createUseCtx = _ref => {
437
433
  }
438
434
  if (!target) return stopRecording(true);
439
435
  return new Promise((resolve, reject) => {
440
- const sessionMultiLens = multiLens;
441
436
  const startRecord = () => {
442
- IPCPlayerInstance.current.startRecord(_objectSpread(_objectSpread({
443
- saveToAlbum
444
- }, sessionMultiLens ? {
445
- multiLens: true
446
- } : {}), {}, {
437
+ IPCPlayerInstance.current.startRecord({
438
+ saveToAlbum,
447
439
  success: () => {
448
- recordingMultiLensRef.current = sessionMultiLens;
449
440
  updateAtom(recording, true);
450
441
  resolve(true);
451
442
  },
@@ -453,7 +444,7 @@ export const createUseCtx = _ref => {
453
444
  eventRef.current.emit(changeIgnoreHideStopPreview, false);
454
445
  reject(err);
455
446
  }
456
- }));
447
+ });
457
448
  };
458
449
  // 写入相册
459
450
  ty.authorizeStatus({
package/lib/ui/ui.js CHANGED
@@ -653,8 +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 => {
657
- const summary = getCaptureResultSummary(result);
656
+ instance === null || instance === void 0 || instance.stopRecordingOnUnload().then(async result => {
657
+ var _instance$multiCamera;
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);
658
659
  ipcTTTOperatorLog(summary !== null && summary !== void 0 && summary.isMultiLens ? `hide: stop recording succeeded with ${summary.count} files` : 'hide: 调用停止录制方法成功');
659
660
  }).catch(() => {
660
661
  ipcTTTOperatorLog('hide: 调用停止录制方法失败');
@@ -1118,17 +1119,17 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
1118
1119
  // 这一下起,自动隐藏倒计时才开始生效
1119
1120
  hasUserTappedPlayerRef.current = true;
1120
1121
  if (instance.multiCameraCtx.isSupport) {
1121
- var _instance$multiCamera, _instance$multiCamera2;
1122
- const preTapIndex = (_instance$multiCamera = (_instance$multiCamera2 = instance.multiCameraCtx.selectedLenInfoRef.current) === null || _instance$multiCamera2 === void 0 ? void 0 : _instance$multiCamera2.index) !== null && _instance$multiCamera !== void 0 ? _instance$multiCamera : prevSelectedIndexRef.current;
1122
+ var _instance$multiCamera2, _instance$multiCamera3;
1123
+ const preTapIndex = (_instance$multiCamera2 = (_instance$multiCamera3 = instance.multiCameraCtx.selectedLenInfoRef.current) === null || _instance$multiCamera3 === void 0 ? void 0 : _instance$multiCamera3.index) !== null && _instance$multiCamera2 !== void 0 ? _instance$multiCamera2 : prevSelectedIndexRef.current;
1123
1124
  const wasHidden = componentHideState;
1124
1125
  instance.multiCameraCtx.selectVideoFiredRef.current = false;
1125
1126
  if (multiTapTimerRef.current) {
1126
1127
  clearTimeout(multiTapTimerRef.current);
1127
1128
  }
1128
1129
  multiTapTimerRef.current = setTimeout(() => {
1129
- var _instance$multiCamera3, _instance$multiCamera4;
1130
+ var _instance$multiCamera4, _instance$multiCamera5;
1130
1131
  const selectFired = !!instance.multiCameraCtx.selectVideoFiredRef.current;
1131
- const currentIndex = (_instance$multiCamera3 = (_instance$multiCamera4 = instance.multiCameraCtx.selectedLenInfoRef.current) === null || _instance$multiCamera4 === void 0 ? void 0 : _instance$multiCamera4.index) !== null && _instance$multiCamera3 !== void 0 ? _instance$multiCamera3 : preTapIndex;
1132
+ const currentIndex = (_instance$multiCamera4 = (_instance$multiCamera5 = instance.multiCameraCtx.selectedLenInfoRef.current) === null || _instance$multiCamera5 === void 0 ? void 0 : _instance$multiCamera5.index) !== null && _instance$multiCamera4 !== void 0 ? _instance$multiCamera4 : preTapIndex;
1132
1133
  if (selectFired && currentIndex === preTapIndex) {
1133
1134
  if (wasHidden) {
1134
1135
  showComponents();
@@ -4,4 +4,6 @@ export type CaptureResultSummary = {
4
4
  isMultiLens: boolean;
5
5
  thumbnailPath: string;
6
6
  };
7
- export declare function getCaptureResultSummary(result: CaptureResult): CaptureResultSummary | null;
7
+ /** 从新多目高级能力配置获取当前设备的总镜头数 */
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,17 +1,67 @@
1
- export function getCaptureResultSummary(result) {
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 = /(\.[^./?#]+)([?#].*)?$/;
7
+ /** 从新多目高级能力配置获取当前设备的总镜头数 */
8
+ export async function getMultiLensCountFromAbility(devId) {
9
+ if (!devId) return 0;
10
+ try {
11
+ var _devInfo$configMetas;
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];
14
+ if (raw) {
15
+ const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
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
+ if (count > 1) {
18
+ return count;
19
+ }
20
+ }
21
+ } catch (e) {
22
+ // ignore
23
+ }
24
+ return 0;
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
+ };
30
+ const extractPath = item => {
31
+ if (!item) return '';
32
+ if (typeof item === 'string') return item;
33
+ if (typeof (item === null || item === void 0 ? void 0 : item.value) === 'string') return item.value;
34
+ return '';
35
+ };
36
+ export async function getCaptureResultSummary(result, fallbackCount, devId) {
2
37
  if (!result || typeof result === 'boolean') return null;
3
- if ('items' in result) {
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) {
4
41
  const firstItem = result.items[0];
5
- if (!firstItem) return null;
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;
6
43
  return {
7
44
  count: result.items.length,
8
45
  isMultiLens: true,
9
- thumbnailPath: firstItem.tempImagePath || firstItem.thumbPath || firstItem.filePath
46
+ thumbnailPath: firstThumb
47
+ };
48
+ }
49
+ const legacySplitCount = fallbackCount && fallbackCount > 1 ? fallbackCount : 0;
50
+ const multiLensAbilityCount = legacySplitCount ? 0 : await getMultiLensCountFromAbility(devId);
51
+
52
+ // Preserve the legacy split protocol as a count fallback without applying the
53
+ // new multi-lens file-name convention to it.
54
+ const multiCount = legacySplitCount || multiLensAbilityCount;
55
+ if (multiCount > 1) {
56
+ return {
57
+ count: multiCount,
58
+ isMultiLens: true,
59
+ thumbnailPath: multiLensAbilityCount > 1 ? normalizeMultiLensThumbnailPath(singleThumb) : singleThumb
10
60
  };
11
61
  }
12
62
  return {
13
63
  count: 1,
14
64
  isMultiLens: false,
15
- thumbnailPath: result.tempImagePath || result.thumbPath || result.filePath
65
+ thumbnailPath: singleThumb
16
66
  };
17
67
  }
@@ -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('does not apply the new file-name convention to the legacy split protocol', 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).not.toHaveBeenCalled();
40
+ });
41
+ it('keeps the legacy 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: basePath
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,8 +107,18 @@ export function RecordVideo(props) {
107
107
  shotUrl: '',
108
108
  shotCount: 0
109
109
  });
110
- const showRecordResult = recordInfo => {
111
- const summary = getCaptureResultSummary(recordInfo);
110
+ const recordResultRequestIdRef = useRef(0);
111
+ useEffect(() => {
112
+ return () => {
113
+ recordResultRequestIdRef.current += 1;
114
+ };
115
+ }, []);
116
+ const showRecordResult = async recordInfo => {
117
+ var _props$multiCameraCtx;
118
+ const requestId = ++recordResultRequestIdRef.current;
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;
120
+ const summary = await getCaptureResultSummary(recordInfo, splitNum, devId);
121
+ if (requestId !== recordResultRequestIdRef.current) return;
112
122
  if (!summary) return;
113
123
  setState({
114
124
  showTimer: false,
@@ -129,7 +139,7 @@ export function RecordVideo(props) {
129
139
  showTimer: false
130
140
  });
131
141
  const recordInfo = await setRecording(false);
132
- showRecordResult(recordInfo);
142
+ await showRecordResult(recordInfo);
133
143
  } catch {
134
144
  // setRecording reports the native failure through the configured toast.
135
145
  }
@@ -245,6 +255,7 @@ export function RecordVideo(props) {
245
255
  if (recordingDisabled) {
246
256
  return false;
247
257
  }
258
+ recordResultRequestIdRef.current += 1;
248
259
  if (state.showShot && _recording) {
249
260
  setState({
250
261
  showShot: false
@@ -268,7 +279,7 @@ export function RecordVideo(props) {
268
279
  timeToResetRecordDisabled();
269
280
  } else {
270
281
  props.event ? props.event.emit(changeIgnoreHideStopPreview, false) : event.emit(changeIgnoreHideStopPreview, false);
271
- showRecordResult(recordInfo);
282
+ await showRecordResult(recordInfo);
272
283
  }
273
284
  } catch (err) {
274
285
  props.event ? props.event.emit(changeIgnoreHideStopPreview, false) : event.emit(changeIgnoreHideStopPreview, false);
@@ -1,5 +1,4 @@
1
- import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import React, { useContext, useRef } from 'react';
1
+ import React, { useContext, useEffect, useRef } from 'react';
3
2
  import { View, Text, showModal, openAppSystemSettingPage, getSystemInfoSync } from '@ray-js/ray';
4
3
  import { useSetState, useUpdateEffect, useMemoizedFn } from 'ahooks';
5
4
  import clsx from 'clsx';
@@ -40,6 +39,12 @@ export function Screenshot(props) {
40
39
  shotUrl: '',
41
40
  shotCount: 0
42
41
  });
42
+ const snapshotRequestIdRef = useRef(0);
43
+ useEffect(() => {
44
+ return () => {
45
+ snapshotRequestIdRef.current += 1;
46
+ };
47
+ }, []);
43
48
  useUpdateEffect(() => {
44
49
  if (state.showShot && screenType) {
45
50
  showShotToast();
@@ -127,14 +132,15 @@ export function Screenshot(props) {
127
132
  });
128
133
  };
129
134
  const takeSnapshot = () => {
130
- IPCPlayerContext.snapshot(_objectSpread(_objectSpread({
131
- saveToAlbum
132
- }, props.multiLens ? {
133
- multiLens: true
134
- } : {}), {}, {
135
- success: res => {
135
+ const requestId = ++snapshotRequestIdRef.current;
136
+ IPCPlayerContext.snapshot({
137
+ saveToAlbum,
138
+ success: async res => {
139
+ var _props$multiCameraCtx;
136
140
  setIgnoreHideStopPreview(false);
137
- const summary = getCaptureResultSummary(res);
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;
142
+ const summary = await getCaptureResultSummary(res, splitNum, devId);
143
+ if (requestId !== snapshotRequestIdRef.current) return;
138
144
  if (!summary) {
139
145
  handleSnapshotFail({});
140
146
  return;
@@ -146,7 +152,7 @@ export function Screenshot(props) {
146
152
  });
147
153
  },
148
154
  fail: handleSnapshotFail
149
- }));
155
+ });
150
156
  };
151
157
  ty.authorizeStatus({
152
158
  // 相册写入权限
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/ipc-player-integration",
3
- "version": "0.0.52-beta.2",
3
+ "version": "0.0.52-beta.4",
4
4
  "description": "IPC 融合播放器",
5
5
  "main": "lib/index",
6
6
  "files": [