@ray-js/ray-ipc-player 2.1.1-beta.1 → 2.1.1-beta.2

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.
@@ -43,7 +43,8 @@ export const usePlayerProps = props => {
43
43
  hideHelpButton = false,
44
44
  hideFeedBackButton = false,
45
45
  playerRoute = '',
46
- defaultAutoPlay = true,
46
+ previewEnabled,
47
+ onPreviewEnabledChange,
47
48
  limitFlow = false,
48
49
  autoWakeUp = false
49
50
  } = props;
@@ -84,7 +85,8 @@ export const usePlayerProps = props => {
84
85
  hideHelpButton,
85
86
  hideFeedBackButton,
86
87
  playerRoute,
87
- defaultAutoPlay,
88
+ previewEnabled,
89
+ onPreviewEnabledChange,
88
90
  limitFlow,
89
91
  autoWakeUp,
90
92
  // 样式相关
package/lib/index.js CHANGED
@@ -54,7 +54,8 @@ const Player = props => {
54
54
  hideHelpButton,
55
55
  hideFeedBackButton,
56
56
  playerRoute,
57
- defaultAutoPlay,
57
+ previewEnabled,
58
+ onPreviewEnabledChange,
58
59
  limitFlow,
59
60
  autoWakeUp,
60
61
  borderRadius,
@@ -95,8 +96,9 @@ const Player = props => {
95
96
  const privateLowPowerDeviceTimeOutRef = useRef(null);
96
97
  const privateWakeOutTimeRef = useRef(null);
97
98
  const privateDeviceWakeNeedPublishTimeRef = useRef(null);
98
- // 内部维护首次组件渲染时,自动播放状态,一旦调用重试,触发拉流后,将其状态设为true
99
- const [autoPlay, setAutoPlay] = useState(defaultAutoPlay);
99
+ /** 传入 previewEnabled 为受控;未传时 previewOn 为 true(自动拉流) */
100
+ const isPreviewControlled = previewEnabled !== undefined;
101
+ const previewOn = previewEnabled !== null && previewEnabled !== void 0 ? previewEnabled : true;
100
102
 
101
103
  // connectChangeRef
102
104
  useRef(null);
@@ -104,6 +106,8 @@ const Player = props => {
104
106
 
105
107
  // 标记是否进入内存缓存/后台(onPause、onHide 设为 true,onShow 还原为 false),拉流时若为 true 则拦截
106
108
  const isInBackgroundRef = useRef(false);
109
+ /** 受控 previewEnabled:因 onHide/onPause 已通知父级 false,回到前台时需恢复 true 并拉流 */
110
+ const previewPausedByLifecycleRef = useRef(false);
107
111
 
108
112
  // 自定义计时老低功耗方案设备在线状态, 用于短暂时间报上下线的UI展示兼容 待实现
109
113
  const [lowPowerDeviceOnlineState, setLowPowerDeviceOnlineState] = useState(onlineStatus);
@@ -172,6 +176,66 @@ const Player = props => {
172
176
  });
173
177
  }
174
178
  });
179
+
180
+ /**
181
+ * 实际发起拉流(隐私唤醒 + P2P/预览),与是否受控无关
182
+ */
183
+ const runPullStream = useMemoizedFn(() => {
184
+ phoneNetworkConnect && onlineStatus && privateState && (!isLowPowerDevice || isVirtualDevice) && handleReWakeCamera();
185
+ phoneNetworkConnect && onlineStatus && privateState && isLowPowerDevice && !isVirtualDevice && handleReWakeCameraLowPowerDevice();
186
+ phoneNetworkConnect && onlineStatus && !privateState && _retry();
187
+ });
188
+ const retry = useMemoizedFn(() => {
189
+ console.log('重新拉流启动');
190
+ // 任何重试拉流时, 将播放器状态还原为loading状态
191
+ setVideoErrCode('');
192
+ setPlayState(d => {
193
+ d.loadingState = true;
194
+ d.errorState = false;
195
+ d.errorMsg = '';
196
+ });
197
+ // 排除默认值为"",不等于播放器路由时, 不进行重试拉流
198
+
199
+ if (playerRoute !== '' && playerRoute !== getPlayerRoute()) {
200
+ console.log('不在播放器路由内, 不进行拉流');
201
+ return;
202
+ }
203
+ if (isInBackgroundRef.current) {
204
+ console.log('处于后台/内存缓存,拦截拉流');
205
+ ipcTTTOperatorLog('VID: isInBackground, block retry');
206
+ return;
207
+ }
208
+ if (isPreviewControlled) {
209
+ onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(true);
210
+ if (previewEnabled) {
211
+ runPullStream();
212
+ }
213
+ return;
214
+ }
215
+ runPullStream();
216
+ });
217
+
218
+ /**
219
+ * 命令式开关:受控走 onPreviewEnabledChange;未传 previewEnabled 时 previewOn 恒为 true,仅支持开启拉流(retry)
220
+ */
221
+ const setPreviewEnabledCommand = useMemoizedFn(enabled => {
222
+ if (isPreviewControlled) {
223
+ onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(enabled);
224
+ return;
225
+ }
226
+ if (enabled) {
227
+ retry();
228
+ }
229
+ });
230
+
231
+ // 创建ipc实例
232
+ const createIpcCtx = () => {
233
+ onCtx && onCtx({
234
+ ctx: ipcCtx.current,
235
+ retry,
236
+ setPreviewEnabled: setPreviewEnabledCommand
237
+ });
238
+ };
175
239
  usePageEvent('onShow', useMemoizedFn(async () => {
176
240
  isInBackgroundRef.current = false;
177
241
  getNetworkType({
@@ -188,8 +252,18 @@ const Player = props => {
188
252
  onChangeIgnoreHideStopPreview && onChangeIgnoreHideStopPreview(false);
189
253
  return;
190
254
  }
255
+ // 受控 preview:后台/隐藏时已把父级置为 false,前台先恢复意图再拉流(不依赖同一帧 previewOn)
256
+ if (previewPausedByLifecycleRef.current && isPreviewControlled) {
257
+ previewPausedByLifecycleRef.current = false;
258
+ onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(true);
259
+ if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow) {
260
+ ipcTTTOperatorLog('VID: onShow_resume_after_hide_pause');
261
+ runPullStream();
262
+ }
263
+ return;
264
+ }
191
265
  // 视图准备就绪
192
- if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow && autoPlay) {
266
+ if (phoneNetworkConnect && playState.initLy && ipcCtx.current && onlineStatus && !privateState && !limitFlow && previewOn) {
193
267
  ipcTTTOperatorLog('VID: onShow_event_to_retry');
194
268
  retry();
195
269
  }
@@ -211,7 +285,7 @@ const Player = props => {
211
285
 
212
286
  // 针对limitFlow
213
287
  useEffect(() => {
214
- if (limitFlow || !autoPlay) {
288
+ if (limitFlow || !previewOn) {
215
289
  setPlayState(d => {
216
290
  return _objectSpread(_objectSpread({}, d), {}, {
217
291
  loadingState: false,
@@ -219,13 +293,13 @@ const Player = props => {
219
293
  errorMessage: ''
220
294
  });
221
295
  });
222
- ipcTTTOperatorLog("limitFlow ~~~~ ".concat(limitFlow, " autoPlay ~~~ ").concat(autoPlay));
296
+ ipcTTTOperatorLog("limitFlow ~~~~ ".concat(limitFlow, " previewOn ~~~ ").concat(previewOn));
223
297
  if (playState.initLy && ipcCtx.current) {
224
298
  stopPreview();
225
299
  disconnect();
226
300
  }
227
301
  }
228
- }, [limitFlow, autoPlay, playState.initLy, ipcCtx.current]);
302
+ }, [limitFlow, previewOn, playState.initLy, ipcCtx.current]);
229
303
  useEffect(() => {
230
304
  registerDeviceListListener({
231
305
  deviceIdList: [devId],
@@ -261,6 +335,10 @@ const Player = props => {
261
335
  if (ignoreHideStopPreview) {
262
336
  return;
263
337
  }
338
+ if (isPreviewControlled && previewOn) {
339
+ previewPausedByLifecycleRef.current = true;
340
+ onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(false);
341
+ }
264
342
  setPlayState(d => {
265
343
  d.loadingState = true;
266
344
  });
@@ -272,6 +350,10 @@ const Player = props => {
272
350
  isInBackgroundRef.current = true;
273
351
  console.log('onPause, 重新拉流');
274
352
  ipcTTTOperatorLog('VID: onPause stopPreview');
353
+ if (!ignoreHideStopPreview && isPreviewControlled && previewOn) {
354
+ previewPausedByLifecycleRef.current = true;
355
+ onPreviewEnabledChange === null || onPreviewEnabledChange === void 0 || onPreviewEnabledChange(false);
356
+ }
275
357
  stopPreview();
276
358
  disconnect();
277
359
  }));
@@ -484,7 +566,7 @@ const Player = props => {
484
566
  d.errorState = true;
485
567
  d.errorMsg = limitFlow ? Strings.getLang('ipc_player_traffic_load_offline_limit_tip') : Strings.getLang('ipc_player_device_offline');
486
568
  });
487
- } else if (!autoPlay) {
569
+ } else if (!previewOn) {
488
570
  setPlayState(d => {
489
571
  d.errorState = true;
490
572
  d.errorMsg = '设备处于休眠中';
@@ -496,50 +578,18 @@ const Player = props => {
496
578
  });
497
579
  } else if (playState.initLy && !privateState) {
498
580
  ipcTTTOperatorLog("VID: privateState_status_change: ".concat(privateState));
499
- retry();
581
+ if (isPreviewControlled) {
582
+ runPullStream();
583
+ } else {
584
+ retry();
585
+ }
500
586
  } else if (playState.initLy && privateState) {
501
587
  stopPreview();
502
588
  // 如果隐私模式为true, 主动推一波流变化的状态码,适配ios不触发connectChange的情况
503
589
  onChangeStreamStatus && onChangeStreamStatus(-1001);
504
590
  }
505
591
  }
506
- }, [phoneNetworkConnect, onlineStatus, playState.initLy, privateState, limitFlow, autoPlay]);
507
- const retry = useMemoizedFn(() => {
508
- console.log('重新拉流启动');
509
- setAutoPlay(true);
510
- // 任何重试拉流时, 将播放器状态还原为loading状态
511
- setVideoErrCode('');
512
- setPlayState(d => {
513
- d.loadingState = true;
514
- d.errorState = false;
515
- d.errorMsg = '';
516
- });
517
- // 排除默认值为"",不等于播放器路由时, 不进行重试拉流
518
-
519
- if (playerRoute !== '' && playerRoute !== getPlayerRoute()) {
520
- console.log('不在播放器路由内, 不进行拉流');
521
- return;
522
- }
523
- if (isInBackgroundRef.current) {
524
- console.log('处于后台/内存缓存,拦截拉流');
525
- ipcTTTOperatorLog('VID: isInBackground, block retry');
526
- return;
527
- }
528
- phoneNetworkConnect && onlineStatus && privateState && (!isLowPowerDevice || isVirtualDevice) && handleReWakeCamera();
529
-
530
- // 低功耗设备隐私模式需单独处理,先进行下发唤醒, 唤醒后再进行下发DP
531
- phoneNetworkConnect && onlineStatus && privateState && isLowPowerDevice && !isVirtualDevice && handleReWakeCameraLowPowerDevice();
532
- phoneNetworkConnect && onlineStatus && !privateState && _retry();
533
- // }, [isLowPowerDevice, phoneNetworkConnect && playState.connectState, privateState, onlineStatus]);
534
- });
535
-
536
- // 创建ipc实例
537
- const createIpcCtx = () => {
538
- onCtx && onCtx({
539
- ctx: ipcCtx.current,
540
- retry
541
- });
542
- };
592
+ }, [phoneNetworkConnect, onlineStatus, playState.initLy, privateState, limitFlow, previewOn, isPreviewControlled, previewEnabled, runPullStream, retry]);
543
593
 
544
594
  // 视图层准备就绪,开始建立连接
545
595
 
@@ -717,7 +767,7 @@ const Player = props => {
717
767
  hideFeedBackButton: hideFeedBackButton,
718
768
  isShare: isShare,
719
769
  limitFlow: limitFlow,
720
- autoPlay: autoPlay
770
+ autoPlay: previewOn
721
771
  }), /*#__PURE__*/React.createElement(FullScreenBackButton, {
722
772
  isVisible: screenType === 'landscape' && (playState.loadingState || playState.errorState),
723
773
  getClassName: getClassName,
@@ -98,10 +98,14 @@ export type IProps = {
98
98
  onCameraNotifyWeakNetwork?: (data) => void;
99
99
  /**
100
100
  * @description.en onCtx
101
- * @description.zh 获取ipcPlayer实例ctx以及重试方法retry
101
+ * @description.zh 获取 ipcPlayer 实例 ctxretry,以及 setPreviewEnabled(与 previewEnabled 受控配合或独立命令式开关拉流)
102
102
  * @default (playerRef) => void
103
103
  */
104
- onCtx?: (playerRef) => void;
104
+ onCtx?: (playerRef: {
105
+ ctx: any;
106
+ retry: () => void;
107
+ setPreviewEnabled: (enabled: boolean) => void;
108
+ }) => void;
105
109
  /**
106
110
  * @description.en onInitPreview
107
111
  * @description.zh 初始化预览成功通知
@@ -217,11 +221,17 @@ export type IProps = {
217
221
  */
218
222
  playerRoute?: string;
219
223
  /**
220
- * @description.en Autoplay by default
221
- * @description.zh 默认是否自动播放
222
- * @default true
224
+ * @description.en Whether to pull preview. If omitted, treated as true (previewOn = previewEnabled ?? true). If passed, controlled mode (isPreviewControlled = true); pair with onPreviewEnabledChange for retry/lifecycle.
225
+ * @description.zh 是否拉流;未传等价 true;传入则为受控(与 onPreviewEnabledChange 配合)。
226
+ * @default undefined
227
+ */
228
+ previewEnabled?: boolean;
229
+ /**
230
+ * @description.en Required for controlled previewEnabled when user retries or lifecycle syncs preview state
231
+ * @description.zh 传入 previewEnabled 受控时建议配置:重试开流、hide/pause 与父级状态同步依赖此回调
232
+ * @default undefined
223
233
  */
224
- defaultAutoPlay?: boolean;
234
+ onPreviewEnabledChange?: (enabled: boolean) => void;
225
235
  /**
226
236
  * @description.en Limit flow for the player
227
237
  * @description.zh 播放器是否限流
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/ray-ipc-player",
3
- "version": "2.1.1-beta.1",
3
+ "version": "2.1.1-beta.2",
4
4
  "description": "ray小程序播放器",
5
5
  "keywords": [
6
6
  "tuya-miniapp",