@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 +2 -2
- package/lib/utils/captureResult.d.ts +2 -2
- package/lib/utils/captureResult.js +22 -8
- package/lib/utils/captureResult.test.d.ts +1 -0
- package/lib/utils/captureResult.test.js +90 -0
- package/lib/widgets/recordVideo/recordVideo.js +13 -4
- package/lib/widgets/screenshot/screenshot.js +11 -3
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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 =
|
|
7
|
-
const raw = devInfo === null || devInfo === void 0 || (_devInfo$configMetas = devInfo.configMetas) === null || _devInfo$configMetas === void 0 ? void 0 : _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];
|
|
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
|
-
//
|
|
41
|
-
|
|
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
|
|
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;
|