@ray-js/ipc-player-integration 0.0.35-beta.3 → 0.0.35-beta.31

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
@@ -1,6 +1,7 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import "core-js/modules/esnext.iterator.constructor.js";
3
3
  import "core-js/modules/esnext.iterator.filter.js";
4
+ import "core-js/modules/esnext.iterator.find.js";
4
5
  import "core-js/modules/esnext.iterator.map.js";
5
6
  import React, { useContext, useState, useRef, useMemo, useEffect, useImperativeHandle } from 'react';
6
7
  import { View, CoverView, getSystemInfoSync, usePageEvent, setNavigationBarBack, setPageOrientation, getCurrentPages } from '@ray-js/ray';
@@ -12,7 +13,7 @@ import { PlayState, PlayerStreamStatus, MultiCameraScreenMode } from '../interfa
12
13
  import { useCtx } from '../ctx/ctx.composition';
13
14
  import { useStore, updateAtom } from '../ctx/store';
14
15
  import { UIEventContext } from './context';
15
- import { showAllComponent, hideAllComponent, playerTap, startTimeToHideAllComponent, pauseTimeToHideAllComponent, decodeClarityDic, changeIgnoreHideStopPreview, moveablePtzControlId, tileActionsId, tileTipId, landscapeTipId, multiPtzId, ptzMoveableTipId, showFlowLowTipId, zoomLevelChange, setScaleMultipleEvent } from './constant';
16
+ import { showAllComponent, hideAllComponent, playerTap, startTimeToHideAllComponent, pauseTimeToHideAllComponent, decodeClarityDic, changeIgnoreHideStopPreview, moveablePtzControlId, tileActionsId, tileTipId, landscapeTipId, multiPtzId, ptzMoveableTipId, showFlowLowTipId, zoomLevelChange, setScaleMultipleEvent, trialCountdownEnd, refreshSmartImageQualityEvent } from './constant';
16
17
  import BottomLeftContent from './bottomLeftContent';
17
18
  import BottomRightContent from './bottomRightContent';
18
19
  import TopLeftContent from './topLeftContent';
@@ -22,8 +23,7 @@ import { useMemoizedFn } from '../hooks';
22
23
  import { Storage } from '../utils/storage';
23
24
  import './ui.less';
24
25
  import { updatePlayerWidgetProps } from '../features';
25
- import { isSmallScreen } from '../utils';
26
- import { getSmartImageQualityState } from '../utils/ttt';
26
+ import { getNgRawData, getSmartImageQualityState, isLowPhone } from '../utils/ttt';
27
27
  function getCtxInstance(instance, devId) {
28
28
  if (instance) return instance;
29
29
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -65,12 +65,13 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
65
65
  awakeStatus = undefined,
66
66
  onPlayerTap,
67
67
  playerRoute = 'pages/home/index',
68
- defaultAutoPlay = true,
69
68
  limitFlow = false,
70
69
  showFlowLowTip = false,
71
70
  extend = {},
72
71
  refreshElement = false,
73
- autoWakeUp = false
72
+ autoWakeUp = false,
73
+ previewEnabled = undefined,
74
+ onPreviewEnabledChange
74
75
  } = props;
75
76
  const {
76
77
  event
@@ -104,18 +105,37 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
104
105
  useImperativeHandle(eventRefProp, () => eventRef.current, [eventRef.current]);
105
106
  const timer = useRef();
106
107
  const reGetOrientationTimer = useRef(null);
107
- const [scaleMultiple, setScaleMultiple] = useState(playerFit === 'contain' ? 1 : -2);
108
- const [currentZoomLevel, setCurrentZoomLevel] = useState(playerFit === 'contain' ? 1 : -2);
108
+ // 统一调整为1倍缩放,保证画面展示完全
109
+ const [scaleMultiple, setScaleMultiple] = useState(1);
110
+ // 统一调整为1倍缩放,保证画面展示完全
111
+ const [currentZoomLevel, setCurrentZoomLevel] = useState(1);
109
112
  const [createCtx, setCreateCtx] = useState(false);
110
113
  // 是否需要忽略进入后台停止预览
111
114
  const [ignoreStopOnHide, setIgnoreStopOnHide] = useState(ignoreHideStopPreview);
112
115
  const [verticalCoverZoom, setVerticalCoverZoom] = useState(-2);
113
- // const [verticalCoverZoom, setVerticalCoverZoom] = useState(-2);
114
- // const [verticalZoomLevel, setVerticalZoomLevel] = useState(playerFit === 'contain' ? 1 : -2);
116
+ const isLowPhoneRef = useRef(false);
117
+ useEffect(() => {
118
+ isLowPhone().then(res => {
119
+ isLowPhoneRef.current = !!res;
120
+ });
121
+ }, []);
115
122
 
116
123
  // 展示顶部内容
117
124
  const [showTopContent, setShowTopContent] = useState(true);
118
125
 
126
+ // pad / 折叠屏小窗口展示面板的情况;getSystemInfoSync 在 onLoad 之后才有准确值,
127
+ // 这里给安全默认 false,由 onLoad / onResize 实际计算并更新
128
+ const [isSmallScreen, setIsSmallScreen] = useState(false);
129
+ const computeIsSmallScreen = useMemoizedFn(() => {
130
+ const {
131
+ windowWidth,
132
+ screenWidth,
133
+ windowHeight
134
+ } = getSystemInfoSync();
135
+ // 取小屏值判断是最准确的 pad / 折叠屏小窗口情况
136
+ return !(screenWidth === windowWidth || screenWidth === windowHeight);
137
+ });
138
+
119
139
  // 外部传入的ignoreHideStopPreview变化时,同步更新
120
140
  useEffect(() => {
121
141
  setIgnoreStopOnHide(ignoreHideStopPreview);
@@ -197,7 +217,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
197
217
  return () => {
198
218
  var _ty3;
199
219
  if (typeof ((_ty3 = ty) === null || _ty3 === void 0 ? void 0 : _ty3.offOrientationChange) === 'function') {
200
- ty.offOrientationChange(handleOrientationChange);
220
+ var _ty4;
221
+ (_ty4 = ty) === null || _ty4 === void 0 || _ty4.offOrientationChange(handleOrientationChange);
201
222
  }
202
223
  };
203
224
  }, []);
@@ -407,8 +428,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
407
428
  eventRef.current.emit(showAllComponent);
408
429
  eventRef.current.emit('disablePlayerTap', true);
409
430
  eventRef.current.emit(pauseTimeToHideAllComponent);
410
- // 按宽填充,保证播放流宽度为屏幕宽度,高度自适应
411
- setScaleMultiple(-1);
431
+ // 按宽填充,保证播放流宽度为屏幕宽度,高度自适应设为1倍
432
+ setScaleMultiple(1);
412
433
  } else {
413
434
  // 短屏或横屏时,恢复自动隐藏
414
435
  eventRef.current.emit('disablePlayerTap', false);
@@ -417,27 +438,54 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
417
438
  }, [isVerticalFullLayout, screenType, playerFit]);
418
439
  useEffect(() => {
419
440
  if (createCtx) {
420
- setScaleMultiple(playerFit === 'contain' ? 1 : -2);
421
- setCurrentZoomLevel(playerFit === 'contain' ? 1 : -2);
441
+ // 统一调整为1倍缩放,保证画面展示完全
442
+ setScaleMultiple(1);
443
+ setCurrentZoomLevel(1);
422
444
  }
423
445
  }, [playerFit, createCtx]);
424
446
  useEffect(() => {
425
447
  setBrandColor(brandColor);
426
448
  setVerticalMic(verticalMic);
427
449
  }, [brandColor, verticalMic]);
428
- const refreshSmartImageQuality = useMemoizedFn(() => {
429
- getSmartImageQualityState(devId).then(res => {
430
- console.log('res===getSmartImageQualityState', res);
431
- updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience', {
432
- buttonState: res.buttonState,
433
- trialRemainingSec: res.trialRemainingSec,
434
- refreshToken: Date.now()
435
- });
450
+
451
+ // 是否隐藏画质(试用)功能:取 TryExperience widget 的 hideSmartImageQualityState
452
+ // (由 initPlayerWidgets 的 hideSmartImageQualityState ?? true 映射而来)
453
+ const hideSmartImageQualityState = useMemo(() => {
454
+ var _hideSmartImageQualit, _tryExp$initProps;
455
+ const tryExp = bottomLeftContent === null || bottomLeftContent === void 0 ? void 0 : bottomLeftContent.find(item => item.id === 'TryExperience');
456
+ return (_hideSmartImageQualit = tryExp === null || tryExp === void 0 || (_tryExp$initProps = tryExp.initProps) === null || _tryExp$initProps === void 0 ? void 0 : _tryExp$initProps.hideSmartImageQualityState) !== null && _hideSmartImageQualit !== void 0 ? _hideSmartImageQualit : true;
457
+ }, [bottomLeftContent]);
458
+ const refreshSmartImageQuality = useMemoizedFn(async () => {
459
+ // 隐藏画质功能时直接跳过,不发起请求与更新
460
+ console.log('hideSmartImageQualityState');
461
+ if (hideSmartImageQualityState) return;
462
+ console.log('refreshSmartImageQuality');
463
+ const res = await getSmartImageQualityState(devId);
464
+ if (!res) return;
465
+ // 调试时使用
466
+ // res = {
467
+ // isPurchase: false,
468
+ // buttonState: 0,
469
+ // trialRemainingSec: 20,
470
+ // canOpenSettings: true,
471
+ // };
472
+ const getNgRes = await getNgRawData();
473
+ console.log('res===getSmartImageQualityState', res);
474
+ updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience', {
475
+ isPurchase: res.isPurchase,
476
+ buttonState: res.buttonState,
477
+ trialRemainingSec: res.trialRemainingSec,
478
+ canOpenSettings: res.canOpenSettings,
479
+ gRawData: !!getNgRes,
480
+ isLowPhone: isLowPhoneRef.current
436
481
  });
437
482
  });
483
+
484
+ // 首次进入即执行;hideSmartImageQualityState 变化时重新执行。
485
+ // 是否隐藏的判定在 refreshSmartImageQuality 内部,hide 为 true 时方法内直接 return。
438
486
  useEffect(() => {
439
487
  refreshSmartImageQuality();
440
- }, [instance]);
488
+ }, [hideSmartImageQualityState]);
441
489
  const refreshBottomLeft = () => {
442
490
  event.current.emit(startTimeToHideAllComponent);
443
491
  event.current.emit(showAllComponent);
@@ -467,6 +515,40 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
467
515
  * 监听播放器实例创建完成
468
516
  */
469
517
 
518
+ /**
519
+ * 页面 onLoad 后才能拿到准确的 systemInfo,这里第一次确定小屏状态
520
+ */
521
+ usePageEvent('onLoad', () => {
522
+ setIsSmallScreen(computeIsSmallScreen());
523
+ });
524
+
525
+ // 页面是否处于前台;自动隐藏倒计时要等播放器正常出流(PLAYING)后再启动
526
+ const pageShownRef = useRef(false);
527
+ // 用 ref 同步最新 playState,避免 usePageEvent 回调闭包拿到过期值
528
+ const playStateRef = useRef(playState);
529
+ playStateRef.current = playState;
530
+ usePageEvent('onShow', () => {
531
+ pageShownRef.current = true;
532
+ // 回到前台时刷新画质(试用)状态(方法内部会按 hideSmartImageQualityState 自行短路)
533
+ refreshSmartImageQuality();
534
+ // 已经在出流就直接启动;否则等 playState 变为 PLAYING 的 effect 再启动
535
+ if (playStateRef.current === PlayState.PLAYING) {
536
+ eventRef.current.emit(startTimeToHideAllComponent);
537
+ }
538
+ });
539
+ // 进入后台 停止播放器元素动画计时
540
+ usePageEvent('onHide', () => {
541
+ pageShownRef.current = false;
542
+ eventRef.current.emit(pauseTimeToHideAllComponent);
543
+ });
544
+
545
+ // 播放器正常出流后再开始自动隐藏倒计时(仅在前台时)
546
+ useEffect(() => {
547
+ if (pageShownRef.current && playState === PlayState.PLAYING) {
548
+ eventRef.current.emit(startTimeToHideAllComponent);
549
+ }
550
+ }, [playState]);
551
+
470
552
  /**
471
553
  * 监听屏幕布局变化
472
554
  */
@@ -480,8 +562,13 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
480
562
  const {
481
563
  type
482
564
  } = sizeData;
565
+
566
+ // 折叠屏展开/收起、pad 多窗口拖拽等场景,需要重新计算并同步
567
+ const small = computeIsSmallScreen();
568
+ setIsSmallScreen(small);
569
+
483
570
  // 针对pad 和折叠屏展开的情况暂不支持横屏,且在ios pad模式下 会触发onResize事件, 待解决
484
- if (isSmallScreen) {
571
+ if (small) {
485
572
  setScreenType('vertical');
486
573
  } else {
487
574
  setScreenType(type === 'landscape' ? 'full' : 'vertical');
@@ -496,19 +583,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
496
583
  }
497
584
  triggerEvent(showAllComponent);
498
585
  }
499
- // 若为全屏模式并且要求按宽填充,即横屏时充满,主动设置模式为-1即可
500
- if (type === 'landscape' && landscapeMode === 'fill') {
501
- console.log(scaleMultiple, '===========fill');
502
- setScaleMultiple(-1);
503
- } else if (type === 'landscape' && landscapeMode === 'standard') {
504
- console.log(scaleMultiple, '===========landscape');
505
- setScaleMultiple(-2);
506
- } else {
507
- // 竖屏时 将屏幕播放比例设为按宽按高
508
-
509
- console.log(scaleMultiple, '===========landscape');
510
- setScaleMultiple(playerFit === 'contain' ? scaleMultiple === 1 ? -1 : 1 : -2);
511
- }
586
+ // 横屏(fill/standard)与竖屏均统一调整为 1 倍缩放,保证画面完整展示
587
+ setScaleMultiple(1);
512
588
  } catch (err) {
513
589
  console.log(err, 'err');
514
590
  }
@@ -641,14 +717,18 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
641
717
 
642
718
  /**
643
719
  * 右下角可见按钮数 → 右下角组件宽度(左下角同时用作右侧预留宽度)
644
- * 1 个按钮: 115px / 2 个按钮: 132px / 0 个按钮: 0
720
+ * - 横屏: 固定 40%(用百分比,左下角自动按 100% - 40% = 60% 可视,溢出走横向滚动)
721
+ * - 竖屏: 1 个按钮 115px / 2+ 个按钮 132px / 0 个按钮 0
645
722
  */
646
723
  const bottomRightWidth = useMemo(() => {
724
+ if (screenType === 'full') {
725
+ return '40%';
726
+ }
647
727
  const visibleCount = (bottomRightContent || []).filter(item => !item.hidden).length;
648
728
  if (visibleCount <= 0) return 0;
649
729
  if (visibleCount === 1) return 115;
650
730
  return 132;
651
- }, [bottomRightContent]);
731
+ }, [bottomRightContent, screenType]);
652
732
 
653
733
  /**
654
734
  * 视频流加载状态封装
@@ -672,10 +752,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
672
752
  }
673
753
  }
674
754
  if (playState === PlayState.PLAYING) {
675
- // 仅在第一次播放成功时,针对竖屏并且为cover模式时,设置为-2
755
+ // 仅在第一次播放成功时,针对竖屏并且为cover模式时,设置为-2 修改为只针对第一次播放成功时
676
756
  console.log('Playing状态');
677
- if (screenType === 'vertical' && playerFit === 'cover' && !hasPlayedRef.current) {
678
- setScaleMultiple(-2);
757
+ // if (screenType === 'vertical' && playerFit === 'cover' && !hasPlayedRef.current) {
758
+ if (!hasPlayedRef.current) {
759
+ // 统一调整为1倍缩放,保证画面展示完全
760
+ setScaleMultiple(1);
679
761
  hasPlayedRef.current = true;
680
762
  }
681
763
  }
@@ -752,6 +834,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
752
834
  const onSetScaleMultiple = value => {
753
835
  setScaleMultiple(value);
754
836
  };
837
+ const onTrialCountdownEnd = useMemoizedFn(() => {
838
+ // updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience' as any, {
839
+ // buttonState: 2,
840
+ // });
841
+ refreshSmartImageQuality();
842
+ });
755
843
  useEffect(() => {
756
844
  eventRef.current.on(startTimeToHideAllComponent, listenStart);
757
845
  eventRef.current.on(pauseTimeToHideAllComponent, listenPause);
@@ -761,6 +849,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
761
849
  eventRef.current.on('refreshBottomLeft', refreshBottomLeft);
762
850
  eventRef.current.on(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
763
851
  eventRef.current.on(setScaleMultipleEvent, onSetScaleMultiple);
852
+ eventRef.current.on(trialCountdownEnd, onTrialCountdownEnd);
853
+ eventRef.current.on(refreshSmartImageQualityEvent, refreshSmartImageQuality);
764
854
  return () => {
765
855
  eventRef.current.off(startTimeToHideAllComponent, listenStart);
766
856
  eventRef.current.off(pauseTimeToHideAllComponent, listenPause);
@@ -770,6 +860,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
770
860
  eventRef.current.off('refreshBottomLeft', refreshBottomLeft);
771
861
  eventRef.current.off(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
772
862
  eventRef.current.off(setScaleMultipleEvent, onSetScaleMultiple);
863
+ eventRef.current.off(trialCountdownEnd, onTrialCountdownEnd);
864
+ eventRef.current.off(refreshSmartImageQualityEvent, refreshSmartImageQuality);
773
865
  if (multiTapTimerRef.current) {
774
866
  clearTimeout(multiTapTimerRef.current);
775
867
  multiTapTimerRef.current = null;
@@ -784,14 +876,6 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
784
876
  /**
785
877
  * 监听当前的zoom比例状态
786
878
  */
787
- // useEffect(() => {
788
- // if (screenType === 'vertical') {
789
- // console.log(currentZoomLevel, '竖屏时的缩放比例');
790
- // setVerticalZoomLevel(currentZoomLevel);
791
- // // setScaleMultiple(currentZoomLevel);
792
- // }
793
- // }, [screenType, currentZoomLevel]);
794
-
795
879
  const onZoomChange = useMemoizedFn(data => {
796
880
  const {
797
881
  zoomLevel,
@@ -802,30 +886,19 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
802
886
  if (zoomLevel === 0) {
803
887
  return false;
804
888
  }
805
- /**
806
- * 针对竖屏为cover模式时,横屏为standard模式时,主动设置缩放比例,避免因值不能正常变化
807
- */
808
- if (scaleMode === -2 && playerFit === 'cover' && screenType === 'vertical' && landscapeMode === 'standard') {
809
- console.log('dsadsadsad----', zoomLevel);
810
- setScaleMultiple(zoomLevel);
811
- }
812
889
  /**
813
890
  * 针对竖屏为contain模式时,横屏为fill模式时,主动设置缩放比例,避免因值不能正常变化
814
891
  */
815
- if (scaleMode === -1 && playerFit === 'contain' && screenType === 'vertical' && landscapeMode === 'fill') {
816
- setVerticalCoverZoom(zoomLevel);
817
- }
892
+ // if (
893
+ // scaleMode === -1 &&
894
+ // playerFit === 'contain' &&
895
+ // screenType === 'vertical' &&
896
+ // landscapeMode === 'fill'
897
+ // ) {
898
+ // setVerticalCoverZoom(zoomLevel);
899
+ // }
818
900
 
819
- /**
820
- * 横屏情况下 针对竖屏为contain模式时,横屏为fill模式时,主动设置缩放比例,避免因值不能正常变化
821
- */
822
- if (scaleMode === -2 && playerFit === 'cover' && screenType !== 'vertical' && landscapeMode === 'standard') {
823
- setScaleMultiple(zoomLevel);
824
- }
825
- if (scaleMode === -1 && playerFit === 'contain' && screenType !== 'vertical' && landscapeMode === 'fill') {
826
- setVerticalCoverZoom(zoomLevel);
827
- setScaleMultiple(zoomLevel);
828
- }
901
+ // 直接记录当前缩放比例
829
902
  setCurrentZoomLevel(zoomLevel);
830
903
  instance.event.emit(zoomLevelChange, zoomLevel);
831
904
  return false;
@@ -887,12 +960,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
887
960
  ,
888
961
  privateState: privateState,
889
962
  onPlayerTap: data => {
890
- console.log('sdhsajdhsahdsa=========');
963
+ console.log('playerTap event');
891
964
  if (disablePlayerTap.current) {
892
965
  console.log('playerTap 事件已禁止');
893
966
  return;
894
967
  }
895
- console.log('res===on onVideoTap', data);
968
+ console.log('res===on onVideoTap1', data);
896
969
  if (instance.multiCameraCtx.isSupport) {
897
970
  var _instance$multiCamera, _instance$multiCamera2;
898
971
  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;
@@ -943,7 +1016,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
943
1016
  ,
944
1017
  brandColor: brandColor,
945
1018
  playerRoute: playerRoute,
946
- defaultAutoPlay: defaultAutoPlay,
1019
+ previewEnabled: previewEnabled,
1020
+ onPreviewEnabledChange: onPreviewEnabledChange,
947
1021
  limitFlow: limitFlow,
948
1022
  autoWakeUp: autoWakeUp,
949
1023
  extend: _objectSpread(_objectSpread({
package/lib/ui/ui.less CHANGED
@@ -19,7 +19,7 @@
19
19
  bottom: 0;
20
20
  left: 0;
21
21
  right: 0;
22
- padding-top: 12px;
22
+ // padding-top: 12px;
23
23
  z-index: 90;
24
24
  height: 60px;
25
25
  background: linear-gradient(360deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0) 100%);
@@ -157,7 +157,71 @@
157
157
  // 左下角子元素内容区域样式
158
158
  .ipc-player-bottom-left-content-container {
159
159
  display: flex;
160
- flex-direction: inherit;
160
+ flex-direction: row;
161
+ }
162
+
163
+ // 左下角横滑提示箭头:仅在内容溢出且未滑到对应边缘时由 JS 控制显示
164
+ .ipc-player-bottom-left-scroll-hint-arrow {
165
+ width: 7px;
166
+ height: 7px;
167
+ animation: ipc-player-bottom-left-scroll-hint-pulse 1.4s ease-in-out infinite;
168
+ }
169
+
170
+ .ipc-player-bottom-left-scroll-hint-arrow--right {
171
+ border-top: 2px solid rgba(255, 255, 255, 0.95);
172
+ border-right: 2px solid rgba(255, 255, 255, 0.95);
173
+ transform: rotate(45deg);
174
+ }
175
+
176
+ .ipc-player-bottom-left-scroll-hint-arrow--left {
177
+ border-top: 2px solid rgba(255, 255, 255, 0.95);
178
+ border-left: 2px solid rgba(255, 255, 255, 0.95);
179
+ transform: rotate(-45deg);
180
+ }
181
+
182
+ // button 模式:半透明黑圆底(点击热区)
183
+ .ipc-player-bottom-left-scroll-hint--button {
184
+ background: rgba(0, 0, 0, 0.45);
185
+ border-radius: 50%;
186
+ }
187
+
188
+ // button 模式:白色箭头
189
+ .ipc-player-bottom-left-scroll-hint-arrow--light {
190
+ border-top-color: rgba(255, 255, 255, 0.95);
191
+ border-right-color: rgba(255, 255, 255, 0.95);
192
+ border-left-color: rgba(255, 255, 255, 0.95);
193
+ }
194
+
195
+ // button 模式:常显、不做渐隐渐显动画
196
+ .ipc-player-bottom-left-scroll-hint-arrow--static {
197
+ animation: none;
198
+ opacity: 1;
199
+ }
200
+
201
+ // 右边缘淡出:把没完全露出的元素渐隐到透明。写成静态类,避免内联 mask 在原生层反复重绘闪烁
202
+ .ipc-player-bottom-left-scroll-fademask {
203
+ -webkit-mask-image: linear-gradient(
204
+ to right,
205
+ #000 calc(100% - 72px),
206
+ rgba(0, 0, 0, 0.25) calc(100% - 24px),
207
+ transparent 100%
208
+ );
209
+ mask-image: linear-gradient(
210
+ to right,
211
+ #000 calc(100% - 72px),
212
+ rgba(0, 0, 0, 0.25) calc(100% - 24px),
213
+ transparent 100%
214
+ );
215
+ }
216
+
217
+ @keyframes ipc-player-bottom-left-scroll-hint-pulse {
218
+ 0%,
219
+ 100% {
220
+ opacity: 0.55;
221
+ }
222
+ 50% {
223
+ opacity: 1;
224
+ }
161
225
  }
162
226
 
163
227
  // 右下角子元素内容区域样式
@@ -233,20 +297,20 @@
233
297
 
234
298
  // 左下角全屏子元素容器
235
299
  .bottom-left-item-full-container {
236
- padding: 0 24px !important;
300
+ padding: 0 20px !important;
237
301
  flex-shrink: 0;
238
302
  }
239
303
 
240
304
  .bottom-left-item-full-container:first-of-type {
241
- padding: 0 24px 0 16px !important;
305
+ padding: 0 20px 0 12px !important;
242
306
  }
243
307
 
244
308
  .bottom-left-item-full-container:last-of-type {
245
- padding: 0 0 0 24px !important;
309
+ padding: 0 0 0 20px !important;
246
310
  }
247
311
 
248
312
  .bottom-left-item-full-container:only-of-type {
249
- padding: 0 0 0 16px !important;
313
+ padding: 0 0 0 12px !important;
250
314
  }
251
315
 
252
316
  // 右下角子元素容器
@@ -1,5 +1,4 @@
1
1
  /// <reference types="jest" />
2
- export declare const isSmallScreen: boolean;
3
2
  /**
4
3
  * 麦克风对讲按钮径向渐变
5
4
  */
@@ -1,14 +1,4 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import { getSystemInfoSync } from '@ray-js/ray';
3
- const {
4
- windowWidth,
5
- screenWidth,
6
- windowHeight
7
- } = getSystemInfoSync();
8
-
9
- // pad和折叠屏小窗口展示面板的情况
10
- export const isSmallScreen = !(screenWidth === windowWidth || screenWidth === windowHeight);
11
-
12
2
  /**
13
3
  * 麦克风对讲按钮径向渐变
14
4
  */
@@ -4,3 +4,4 @@ export declare const miniIdLabs: {
4
4
  };
5
5
  export declare function gotoAIDrawMiniProgram(devId: string, brandColor: string): void;
6
6
  export declare function gotoSecurityCloudService(homeId: string, uuid: string): Promise<void>;
7
+ export declare function gotoSecurityCloudService2(devId: string): Promise<import("@ray-js/ray-ipc-utils/lib/interface").IRes<unknown>>;
@@ -1,4 +1,4 @@
1
- import { goToMiniProgramByShortLink } from '@ray-js/ray-ipc-utils';
1
+ import { getServiceUrl, goToMiniProgramByShortLink } from '@ray-js/ray-ipc-utils';
2
2
  import Color from 'color';
3
3
 
4
4
  // 小程序ID集合
@@ -11,10 +11,13 @@ export const miniIdLabs = {
11
11
  export function gotoAIDrawMiniProgram(devId, brandColor) {
12
12
  const color = new Color(brandColor);
13
13
  const rgbColor = color.rgb().toString();
14
- const url = `godzilla://${miniIdLabs.aiDrawMini}${'/pages/home/index'}?deviceId=${devId}&themeColor=${rgbColor}`;
14
+ const url = `godzilla://${miniIdLabs.aiDrawMini}?deviceId=${devId}&themeColor=${rgbColor}`;
15
15
  goToMiniProgramByShortLink(url, 'right');
16
16
  }
17
17
  export async function gotoSecurityCloudService(homeId, uuid) {
18
18
  const url = `godzilla://${miniIdLabs.securityCloudService}${'/pages/serviceList/index'}?homeId=${homeId}&deviceId=${uuid}&categoryCode=${'security_cloud_service'}`;
19
19
  goToMiniProgramByShortLink(url, 'right');
20
+ }
21
+ export async function gotoSecurityCloudService2(devId) {
22
+ return getServiceUrl(devId, 'security_cloud_service', {}, true);
20
23
  }
@@ -4,7 +4,7 @@ export type SmartImageQualityResult = {
4
4
  trialRemainingSec: number;
5
5
  canOpenSettings: boolean;
6
6
  };
7
- export declare function getSmartImageQualityState(devId: string): Promise<SmartImageQualityResult>;
7
+ export declare function getSmartImageQualityState(devId: string): Promise<SmartImageQualityResult | null>;
8
8
  export type AIFrameFeatureScope = {
9
9
  inPreview: boolean;
10
10
  inMessage: boolean;
@@ -25,6 +25,7 @@ export type SetAIFrameFeatureParams = {
25
25
  devId: string;
26
26
  enabled: boolean;
27
27
  aiFrameFeature: AIFrameFeatureConfig;
28
+ scene: string;
28
29
  };
29
30
  export type GetAIFrameFeatureResult = {
30
31
  enabled: boolean;
@@ -33,7 +34,8 @@ export type GetAIFrameFeatureResult = {
33
34
  localPath: string;
34
35
  thingFileUri: string;
35
36
  };
36
- export declare function getAIFrameFeature(devId: string): Promise<GetAIFrameFeatureResult>;
37
- export declare function setAIFrameFeature(devId: string, params: Omit<SetAIFrameFeatureParams, 'devId'>): Promise<any>;
38
- export declare function getDeviceInfoRay(devId: string): Promise<unknown>;
39
- export declare function getCurrentHomeInfoRay(): Promise<unknown>;
37
+ export declare function getAIFrameFeature(devId: string): Promise<GetAIFrameFeatureResult | null>;
38
+ export declare function setAIFrameFeature(params: SetAIFrameFeatureParams): Promise<any>;
39
+ export declare function setTrailFinish(devId: string): Promise<unknown>;
40
+ export declare function isLowPhone(): Promise<boolean>;
41
+ export declare function getNgRawData(): Promise<unknown>;