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

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, trialCountdownEnd } 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,7 +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 { getSmartImageQualityState } from '../utils/ttt';
26
+ import { getNgRawData, getSmartImageQualityState, isLowPhone } from '../utils/ttt';
26
27
  function getCtxInstance(instance, devId) {
27
28
  if (instance) return instance;
28
29
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -64,12 +65,13 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
64
65
  awakeStatus = undefined,
65
66
  onPlayerTap,
66
67
  playerRoute = 'pages/home/index',
67
- defaultAutoPlay = true,
68
68
  limitFlow = false,
69
69
  showFlowLowTip = false,
70
70
  extend = {},
71
71
  refreshElement = false,
72
- autoWakeUp = false
72
+ autoWakeUp = false,
73
+ previewEnabled = undefined,
74
+ onPreviewEnabledChange
73
75
  } = props;
74
76
  const {
75
77
  event
@@ -111,6 +113,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
111
113
  // 是否需要忽略进入后台停止预览
112
114
  const [ignoreStopOnHide, setIgnoreStopOnHide] = useState(ignoreHideStopPreview);
113
115
  const [verticalCoverZoom, setVerticalCoverZoom] = useState(-2);
116
+ const isLowPhoneRef = useRef(false);
117
+ useEffect(() => {
118
+ isLowPhone().then(res => {
119
+ isLowPhoneRef.current = !!res;
120
+ });
121
+ }, []);
114
122
 
115
123
  // 展示顶部内容
116
124
  const [showTopContent, setShowTopContent] = useState(true);
@@ -209,7 +217,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
209
217
  return () => {
210
218
  var _ty3;
211
219
  if (typeof ((_ty3 = ty) === null || _ty3 === void 0 ? void 0 : _ty3.offOrientationChange) === 'function') {
212
- ty.offOrientationChange(handleOrientationChange);
220
+ var _ty4;
221
+ (_ty4 = ty) === null || _ty4 === void 0 || _ty4.offOrientationChange(handleOrientationChange);
213
222
  }
214
223
  };
215
224
  }, []);
@@ -438,24 +447,45 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
438
447
  setBrandColor(brandColor);
439
448
  setVerticalMic(verticalMic);
440
449
  }, [brandColor, verticalMic]);
441
- const refreshSmartImageQuality = useMemoizedFn(() => {
442
- getSmartImageQualityState(devId).then(res => {
443
- if (res === undefined) return;
444
- updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience', {
445
- isPurchase: res.isPurchase,
446
- buttonState: res.buttonState,
447
- trialRemainingSec: res.trialRemainingSec,
448
- refreshToken: Date.now()
449
- }).catch(() => {
450
- // ignore
451
- });
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
452
481
  });
453
482
  });
483
+
484
+ // 首次进入即执行;hideSmartImageQualityState 变化时重新执行。
485
+ // 是否隐藏的判定在 refreshSmartImageQuality 内部,hide 为 true 时方法内直接 return。
454
486
  useEffect(() => {
455
- if (playState === PlayState.PLAYING) {
456
- refreshSmartImageQuality();
457
- }
458
- }, [playState]);
487
+ refreshSmartImageQuality();
488
+ }, [hideSmartImageQualityState]);
459
489
  const refreshBottomLeft = () => {
460
490
  event.current.emit(startTimeToHideAllComponent);
461
491
  event.current.emit(showAllComponent);
@@ -492,6 +522,33 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
492
522
  setIsSmallScreen(computeIsSmallScreen());
493
523
  });
494
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
+
495
552
  /**
496
553
  * 监听屏幕布局变化
497
554
  */
@@ -660,14 +717,18 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
660
717
 
661
718
  /**
662
719
  * 右下角可见按钮数 → 右下角组件宽度(左下角同时用作右侧预留宽度)
663
- * 1 个按钮: 115px / 2 个按钮: 132px / 0 个按钮: 0
720
+ * - 横屏: 固定 40%(用百分比,左下角自动按 100% - 40% = 60% 可视,溢出走横向滚动)
721
+ * - 竖屏: 1 个按钮 115px / 2+ 个按钮 132px / 0 个按钮 0
664
722
  */
665
723
  const bottomRightWidth = useMemo(() => {
724
+ if (screenType === 'full') {
725
+ return '40%';
726
+ }
666
727
  const visibleCount = (bottomRightContent || []).filter(item => !item.hidden).length;
667
728
  if (visibleCount <= 0) return 0;
668
729
  if (visibleCount === 1) return 115;
669
730
  return 132;
670
- }, [bottomRightContent]);
731
+ }, [bottomRightContent, screenType]);
671
732
 
672
733
  /**
673
734
  * 视频流加载状态封装
@@ -774,9 +835,10 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
774
835
  setScaleMultiple(value);
775
836
  };
776
837
  const onTrialCountdownEnd = useMemoizedFn(() => {
777
- updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience', {
778
- buttonState: 2
779
- });
838
+ // updatePlayerWidgetProps(instance, 'bottomLeft', 'TryExperience' as any, {
839
+ // buttonState: 2,
840
+ // });
841
+ refreshSmartImageQuality();
780
842
  });
781
843
  useEffect(() => {
782
844
  eventRef.current.on(startTimeToHideAllComponent, listenStart);
@@ -788,6 +850,7 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
788
850
  eventRef.current.on(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
789
851
  eventRef.current.on(setScaleMultipleEvent, onSetScaleMultiple);
790
852
  eventRef.current.on(trialCountdownEnd, onTrialCountdownEnd);
853
+ eventRef.current.on(refreshSmartImageQualityEvent, refreshSmartImageQuality);
791
854
  return () => {
792
855
  eventRef.current.off(startTimeToHideAllComponent, listenStart);
793
856
  eventRef.current.off(pauseTimeToHideAllComponent, listenPause);
@@ -798,6 +861,7 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
798
861
  eventRef.current.off(changeIgnoreHideStopPreview, onChangeIgnoreHideStopPreview);
799
862
  eventRef.current.off(setScaleMultipleEvent, onSetScaleMultiple);
800
863
  eventRef.current.off(trialCountdownEnd, onTrialCountdownEnd);
864
+ eventRef.current.off(refreshSmartImageQualityEvent, refreshSmartImageQuality);
801
865
  if (multiTapTimerRef.current) {
802
866
  clearTimeout(multiTapTimerRef.current);
803
867
  multiTapTimerRef.current = null;
@@ -896,12 +960,12 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
896
960
  ,
897
961
  privateState: privateState,
898
962
  onPlayerTap: data => {
899
- console.log('sdhsajdhsahdsa=========');
963
+ console.log('playerTap event');
900
964
  if (disablePlayerTap.current) {
901
965
  console.log('playerTap 事件已禁止');
902
966
  return;
903
967
  }
904
- console.log('res===on onVideoTap', data);
968
+ console.log('res===on onVideoTap1', data);
905
969
  if (instance.multiCameraCtx.isSupport) {
906
970
  var _instance$multiCamera, _instance$multiCamera2;
907
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;
@@ -952,7 +1016,8 @@ export const IPCPlayerIntegration = /*#__PURE__*/React.memo(props => {
952
1016
  ,
953
1017
  brandColor: brandColor,
954
1018
  playerRoute: playerRoute,
955
- defaultAutoPlay: defaultAutoPlay,
1019
+ previewEnabled: previewEnabled,
1020
+ onPreviewEnabledChange: onPreviewEnabledChange,
956
1021
  limitFlow: limitFlow,
957
1022
  autoWakeUp: autoWakeUp,
958
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
  // 右下角子元素容器
@@ -11,7 +11,7 @@ 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) {
@@ -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,8 +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 getAIFrameFeature(devId: string): Promise<GetAIFrameFeatureResult | null>;
37
38
  export declare function setAIFrameFeature(params: SetAIFrameFeatureParams): Promise<any>;
38
- export declare function getDeviceInfoRay(devId: string): Promise<unknown>;
39
- export declare function getCurrentHomeInfoRay(): Promise<unknown>;
40
39
  export declare function setTrailFinish(devId: string): Promise<unknown>;
40
+ export declare function isLowPhone(): Promise<boolean>;
41
+ export declare function getNgRawData(): Promise<unknown>;
package/lib/utils/ttt.js CHANGED
@@ -1,25 +1,37 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  export function getSmartImageQualityState(devId) {
3
3
  return new Promise(resolve => {
4
+ var _ty$ipc;
5
+ const isSupport = typeof ((_ty$ipc = ty.ipc) === null || _ty$ipc === void 0 ? void 0 : _ty$ipc.getSmartImageQualityState) === 'function';
6
+ if (!isSupport) {
7
+ resolve(null);
8
+ return;
9
+ }
4
10
  try {
5
- ty.ipc.getSmartImageQualityState({
11
+ var _ty;
12
+ (_ty = ty) === null || _ty === void 0 || (_ty = _ty.ipc) === null || _ty === void 0 || _ty.getSmartImageQualityState({
6
13
  devId,
7
14
  scene: 'inPreview',
8
15
  success: data => {
9
- console.log('res===getSmartImageQualityState data', data);
10
16
  resolve(data);
11
17
  },
12
18
  fail: () => {
13
- resolve(undefined);
19
+ resolve(null);
14
20
  }
15
21
  });
16
22
  } catch (e) {
17
- resolve(undefined);
23
+ resolve(null);
18
24
  }
19
25
  });
20
26
  }
21
27
  export function getAIFrameFeature(devId) {
22
28
  return new Promise(resolve => {
29
+ var _ty$ipc2;
30
+ const isSupport = typeof ((_ty$ipc2 = ty.ipc) === null || _ty$ipc2 === void 0 ? void 0 : _ty$ipc2.getAIFrameFeature) === 'function';
31
+ if (!isSupport) {
32
+ resolve(null);
33
+ return;
34
+ }
23
35
  try {
24
36
  ty.ipc.getAIFrameFeature({
25
37
  devId,
@@ -29,16 +41,22 @@ export function getAIFrameFeature(devId) {
29
41
  },
30
42
  fail: e => {
31
43
  console.warn('res===getAIFrameFeature fail', e);
32
- resolve(undefined);
44
+ resolve(null);
33
45
  }
34
46
  });
35
47
  } catch (e) {
36
- resolve(undefined);
48
+ resolve(null);
37
49
  }
38
50
  });
39
51
  }
40
52
  export function setAIFrameFeature(params) {
41
53
  return new Promise(resolve => {
54
+ var _ty$ipc3;
55
+ const isSupport = typeof ((_ty$ipc3 = ty.ipc) === null || _ty$ipc3 === void 0 ? void 0 : _ty$ipc3.setAIFrameFeature) === 'function';
56
+ if (!isSupport) {
57
+ resolve(null);
58
+ return;
59
+ }
42
60
  try {
43
61
  ty.ipc.setAIFrameFeature(_objectSpread(_objectSpread({}, params), {}, {
44
62
  success: data => {
@@ -47,61 +65,81 @@ export function setAIFrameFeature(params) {
47
65
  },
48
66
  fail: e => {
49
67
  console.warn('res===setAIFrameFeature fail', e);
50
- resolve(undefined);
68
+ resolve(null);
51
69
  }
52
70
  }));
53
71
  } catch (e) {
54
- resolve(undefined);
72
+ resolve(null);
55
73
  }
56
74
  });
57
75
  }
58
- export function getDeviceInfoRay(devId) {
76
+ export function setTrailFinish(devId) {
59
77
  return new Promise(resolve => {
78
+ var _ty$ipc4;
79
+ const isSupport = typeof ((_ty$ipc4 = ty.ipc) === null || _ty$ipc4 === void 0 ? void 0 : _ty$ipc4.setTrailFinish) === 'function';
80
+ if (!isSupport) {
81
+ resolve(null);
82
+ return;
83
+ }
60
84
  try {
61
- ty.device.getDeviceInfo({
62
- deviceId: devId,
85
+ var _ty2;
86
+ (_ty2 = ty) === null || _ty2 === void 0 || (_ty2 = _ty2.ipc) === null || _ty2 === void 0 || _ty2.setTrailFinish({
87
+ devId,
63
88
  success: res => {
64
89
  resolve(res);
65
90
  },
66
91
  fail: () => {
67
- resolve(undefined);
92
+ resolve(null);
68
93
  }
69
94
  });
70
95
  } catch (e) {
71
- resolve(undefined);
96
+ resolve(null);
72
97
  }
73
98
  });
74
99
  }
75
- export function getCurrentHomeInfoRay() {
100
+ export function isLowPhone() {
76
101
  return new Promise(resolve => {
102
+ var _ty$ipc5;
103
+ const isSupport = typeof ((_ty$ipc5 = ty.ipc) === null || _ty$ipc5 === void 0 ? void 0 : _ty$ipc5.isLowPhone) === 'function';
104
+ if (!isSupport) {
105
+ resolve(false);
106
+ return;
107
+ }
77
108
  try {
78
- ty.home.getCurrentHomeInfo({
109
+ ty.ipc.isLowPhone({
79
110
  success: res => {
80
- resolve(res);
111
+ var _res$isLow;
112
+ resolve((_res$isLow = res === null || res === void 0 ? void 0 : res.isLow) !== null && _res$isLow !== void 0 ? _res$isLow : false);
81
113
  },
82
114
  fail: () => {
83
- resolve(undefined);
115
+ resolve(false);
84
116
  }
85
117
  });
86
118
  } catch (e) {
87
- resolve(undefined);
119
+ resolve(false);
88
120
  }
89
121
  });
90
122
  }
91
- export function setTrailFinish(devId) {
123
+ export function getNgRawData() {
92
124
  return new Promise(resolve => {
125
+ var _ty3;
126
+ const isSupport = typeof ((_ty3 = ty) === null || _ty3 === void 0 ? void 0 : _ty3.getNgRawData) === 'function';
127
+ if (!isSupport) {
128
+ resolve(false);
129
+ return;
130
+ }
93
131
  try {
94
- ty.ipc.setTrailFinish({
95
- devId,
132
+ ty.getNgRawData({
133
+ rawKey: 'is_smart_image_quality',
96
134
  success: res => {
97
- resolve(res);
135
+ resolve((res === null || res === void 0 ? void 0 : res.rawData) === 'true');
98
136
  },
99
137
  fail: () => {
100
- resolve(undefined);
138
+ resolve(false);
101
139
  }
102
140
  });
103
141
  } catch (e) {
104
- resolve(undefined);
142
+ resolve(false);
105
143
  }
106
144
  });
107
145
  }
@@ -6,12 +6,10 @@ type Props = {
6
6
  brandColor?: string;
7
7
  /** 试看倒计时初始秒数,来源于 smartImageQualityState.trialRemainingSec */
8
8
  trialRemainingSec?: number;
9
- /** 刷新令牌,变化时重置倒计时状态 */
10
- refreshToken?: number;
11
9
  /** 点击「开通」按钮回调 */
12
10
  onSubscribe?: () => void;
13
11
  /** 倒计时归零时触发,本组件保证整个生命周期内只回调一次 */
14
12
  onCountdownEnd?: () => void;
15
13
  };
16
- export declare const TrialBadge: ({ className, brandColor, trialRemainingSec, refreshToken, onSubscribe, onCountdownEnd, }: Props) => React.JSX.Element;
14
+ export declare const TrialBadge: ({ className, brandColor, trialRemainingSec, onSubscribe, onCountdownEnd, }: Props) => React.JSX.Element;
17
15
  export { useTrialBadge } from './useTrialBadge';
@@ -18,21 +18,24 @@ export const TrialBadge = _ref => {
18
18
  className,
19
19
  brandColor = FALLBACK_BRAND_COLOR,
20
20
  trialRemainingSec = 0,
21
- refreshToken,
22
21
  onSubscribe,
23
22
  onCountdownEnd
24
23
  } = _ref;
25
24
  const [remainingSec, setRemainingSec] = useState(Math.max(0, Math.floor(trialRemainingSec)));
26
- /** 防止 onCountdownEnd 被重复触发;同时持有最新回调,避免依赖变化导致 effect 重跑 */
27
25
  const endedRef = useRef(false);
28
26
  const onCountdownEndRef = useRef(onCountdownEnd);
29
27
  onCountdownEndRef.current = onCountdownEnd;
28
+ const startTimeRef = useRef(Date.now());
29
+ const initialSecRef = useRef(Math.max(0, Math.floor(trialRemainingSec)));
30
30
  useEffect(() => {
31
+ const sec = Math.max(0, Math.floor(trialRemainingSec));
31
32
  endedRef.current = false;
32
- setRemainingSec(Math.max(0, Math.floor(trialRemainingSec)));
33
- }, [trialRemainingSec, refreshToken]);
33
+ initialSecRef.current = sec;
34
+ startTimeRef.current = Date.now();
35
+ setRemainingSec(sec);
36
+ }, [trialRemainingSec]);
34
37
  useEffect(() => {
35
- if (remainingSec <= 0) {
38
+ if (trialRemainingSec <= 0) {
36
39
  if (!endedRef.current) {
37
40
  var _onCountdownEndRef$cu;
38
41
  endedRef.current = true;
@@ -41,22 +44,20 @@ export const TrialBadge = _ref => {
41
44
  return undefined;
42
45
  }
43
46
  const timer = setInterval(() => {
44
- setRemainingSec(prev => {
45
- const next = prev - 1;
46
- if (next <= 0) {
47
- clearInterval(timer);
48
- if (!endedRef.current) {
49
- var _onCountdownEndRef$cu2;
50
- endedRef.current = true;
51
- (_onCountdownEndRef$cu2 = onCountdownEndRef.current) === null || _onCountdownEndRef$cu2 === void 0 || _onCountdownEndRef$cu2.call(onCountdownEndRef);
52
- }
53
- return 0;
47
+ const elapsed = Math.floor((Date.now() - startTimeRef.current) / 1000);
48
+ const next = Math.max(0, initialSecRef.current - elapsed);
49
+ setRemainingSec(next);
50
+ if (next <= 0) {
51
+ clearInterval(timer);
52
+ if (!endedRef.current) {
53
+ var _onCountdownEndRef$cu2;
54
+ endedRef.current = true;
55
+ (_onCountdownEndRef$cu2 = onCountdownEndRef.current) === null || _onCountdownEndRef$cu2 === void 0 || _onCountdownEndRef$cu2.call(onCountdownEndRef);
54
56
  }
55
- return next;
56
- });
57
+ }
57
58
  }, 1000);
58
59
  return () => clearInterval(timer);
59
- }, [trialRemainingSec, refreshToken]);
60
+ }, [trialRemainingSec]);
60
61
  const countdownText = formatCountdown(remainingSec);
61
62
  return /*#__PURE__*/React.createElement(View, {
62
63
  className: clsx('ipc-player-trial-badge', className)
@@ -75,10 +76,7 @@ export const TrialBadge = _ref => {
75
76
  style: {
76
77
  backgroundColor: brandColor
77
78
  },
78
- onClick: e => {
79
- if (e && typeof e.stopPropagation === 'function') {
80
- e.stopPropagation();
81
- }
79
+ onClick: () => {
82
80
  onSubscribe === null || onSubscribe === void 0 || onSubscribe();
83
81
  }
84
82
  }, /*#__PURE__*/React.createElement(Text, {
@@ -1,13 +1,23 @@
1
+ @keyframes ipc-player-trial-badge-slide-in {
2
+ from {
3
+ transform: translateX(-100%);
4
+ }
5
+ to {
6
+ transform: translateX(0);
7
+ }
8
+ }
9
+
1
10
  .ipc-player-trial-badge {
2
11
  display: inline-flex;
3
12
  align-items: center;
4
- height: 28px;
5
- padding: 0 4px 0 8px;
6
- border-radius: 6px;
13
+ height: 32px;
14
+ padding: 0 6px 0 8px;
15
+ border-radius: 8px;
7
16
  background: rgba(0, 0, 0, 0.65);
8
17
  flex-shrink: 0;
9
18
  vertical-align: middle;
10
19
  white-space: nowrap;
20
+ animation: ipc-player-trial-badge-slide-in 0.3s linear;
11
21
  }
12
22
 
13
23
  .ipc-player-trial-badge-icon {
@@ -43,9 +53,10 @@
43
53
  display: inline-flex;
44
54
  align-items: center;
45
55
  justify-content: center;
46
- height: 22px;
47
- padding: 0 10px;
48
- border-radius: 11px;
56
+ min-width: 44px;
57
+ min-height: 28px;
58
+ padding: 0 12px;
59
+ border-radius: 14px;
49
60
  flex-shrink: 0;
50
61
  }
51
62