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

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.
Files changed (40) hide show
  1. package/lib/ctx/ctx.composition.js +5 -1
  2. package/lib/features/initPlayerWidgets/index.d.ts +1 -0
  3. package/lib/features/initPlayerWidgets/index.js +8 -0
  4. package/lib/i18n/index.d.ts +24 -0
  5. package/lib/i18n/strings.d.ts +12 -0
  6. package/lib/i18n/strings.js +14 -2
  7. package/lib/interface.d.ts +1 -1
  8. package/lib/res/try/try_close.png +0 -0
  9. package/lib/res/try/try_en.png +0 -0
  10. package/lib/res/try/try_open.png +0 -0
  11. package/lib/res/try/try_zh.png +0 -0
  12. package/lib/ui/bottomLeftContent.d.ts +4 -1
  13. package/lib/ui/bottomLeftContent.js +93 -8
  14. package/lib/ui/bottomRightContent.d.ts +3 -1
  15. package/lib/ui/bottomRightContent.js +11 -4
  16. package/lib/ui/constant.d.ts +7 -0
  17. package/lib/ui/constant.js +8 -0
  18. package/lib/ui/index.d.ts +1 -1
  19. package/lib/ui/index.js +1 -1
  20. package/lib/ui/ui.js +103 -56
  21. package/lib/ui/ui.less +5 -1
  22. package/lib/utils/index.d.ts +2 -1
  23. package/lib/utils/index.js +3 -11
  24. package/lib/utils/navigation.d.ts +7 -0
  25. package/lib/utils/navigation.js +23 -0
  26. package/lib/utils/ttt.d.ts +42 -0
  27. package/lib/utils/ttt.js +123 -0
  28. package/lib/widgets/index.d.ts +2 -0
  29. package/lib/widgets/index.js +2 -0
  30. package/lib/widgets/trialBadge/index.d.ts +17 -0
  31. package/lib/widgets/trialBadge/index.js +88 -0
  32. package/lib/widgets/trialBadge/index.less +57 -0
  33. package/lib/widgets/trialBadge/useTrialBadge.d.ts +8 -0
  34. package/lib/widgets/trialBadge/useTrialBadge.js +42 -0
  35. package/lib/widgets/tryExperience/index.d.ts +1 -0
  36. package/lib/widgets/tryExperience/index.js +1 -0
  37. package/lib/widgets/tryExperience/tryExperience.d.ts +14 -0
  38. package/lib/widgets/tryExperience/tryExperience.js +145 -0
  39. package/lib/widgets/tryExperience/tryExperience.less +13 -0
  40. package/package.json +3 -3
@@ -0,0 +1,88 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { Image, Text, View } from '@ray-js/ray';
3
+ import clsx from 'clsx';
4
+ import Strings from '../../i18n';
5
+ import tryOpen from '../../res/try/try_open.png';
6
+ import './index.less';
7
+ /** 兜底主题色,与 player ctx 中 brandColor 默认值保持一致 */
8
+ const FALLBACK_BRAND_COLOR = '#FF592A';
9
+
10
+ /** 将秒数格式化为 mm:ss */
11
+ const formatCountdown = seconds => {
12
+ const safe = Math.max(0, Math.floor(seconds));
13
+ const m = Math.floor(safe / 60);
14
+ return `${String(m).padStart(2, '0')}:${String(safe % 60).padStart(2, '0')}`;
15
+ };
16
+ export const TrialBadge = _ref => {
17
+ let {
18
+ className,
19
+ brandColor = FALLBACK_BRAND_COLOR,
20
+ trialRemainingSec = 0,
21
+ refreshToken,
22
+ onSubscribe,
23
+ onCountdownEnd
24
+ } = _ref;
25
+ const [remainingSec, setRemainingSec] = useState(Math.max(0, Math.floor(trialRemainingSec)));
26
+ /** 防止 onCountdownEnd 被重复触发;同时持有最新回调,避免依赖变化导致 effect 重跑 */
27
+ const endedRef = useRef(false);
28
+ const onCountdownEndRef = useRef(onCountdownEnd);
29
+ onCountdownEndRef.current = onCountdownEnd;
30
+ useEffect(() => {
31
+ endedRef.current = false;
32
+ setRemainingSec(Math.max(0, Math.floor(trialRemainingSec)));
33
+ }, [trialRemainingSec, refreshToken]);
34
+ useEffect(() => {
35
+ if (remainingSec <= 0) {
36
+ if (!endedRef.current) {
37
+ var _onCountdownEndRef$cu;
38
+ endedRef.current = true;
39
+ (_onCountdownEndRef$cu = onCountdownEndRef.current) === null || _onCountdownEndRef$cu === void 0 || _onCountdownEndRef$cu.call(onCountdownEndRef);
40
+ }
41
+ return undefined;
42
+ }
43
+ 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;
54
+ }
55
+ return next;
56
+ });
57
+ }, 1000);
58
+ return () => clearInterval(timer);
59
+ }, [trialRemainingSec, refreshToken]);
60
+ const countdownText = formatCountdown(remainingSec);
61
+ return /*#__PURE__*/React.createElement(View, {
62
+ className: clsx('ipc-player-trial-badge', className)
63
+ }, /*#__PURE__*/React.createElement(Image, {
64
+ className: "ipc-player-trial-badge-icon",
65
+ src: tryOpen,
66
+ mode: "heightFix"
67
+ }), /*#__PURE__*/React.createElement(Text, {
68
+ className: "ipc-player-trial-badge-status"
69
+ }, Strings.getLang('ipc_player_trial_in_use')), /*#__PURE__*/React.createElement(Text, {
70
+ className: "ipc-player-trial-badge-divider"
71
+ }, "|"), /*#__PURE__*/React.createElement(Text, {
72
+ className: "ipc-player-trial-badge-preview"
73
+ }, `${countdownText} ${Strings.getLang('ipc_player_trial_preview_text')}`), /*#__PURE__*/React.createElement(View, {
74
+ className: "ipc-player-trial-badge-cta",
75
+ style: {
76
+ backgroundColor: brandColor
77
+ },
78
+ onClick: e => {
79
+ if (e && typeof e.stopPropagation === 'function') {
80
+ e.stopPropagation();
81
+ }
82
+ onSubscribe === null || onSubscribe === void 0 || onSubscribe();
83
+ }
84
+ }, /*#__PURE__*/React.createElement(Text, {
85
+ className: "ipc-player-trial-badge-cta-text"
86
+ }, Strings.getLang('ipc_player_trial_subscribe'))));
87
+ };
88
+ export { useTrialBadge } from './useTrialBadge';
@@ -0,0 +1,57 @@
1
+ .ipc-player-trial-badge {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ height: 28px;
5
+ padding: 0 4px 0 8px;
6
+ border-radius: 6px;
7
+ background: rgba(0, 0, 0, 0.65);
8
+ flex-shrink: 0;
9
+ vertical-align: middle;
10
+ white-space: nowrap;
11
+ }
12
+
13
+ .ipc-player-trial-badge-icon {
14
+ display: block;
15
+ height: 20px;
16
+ width: auto;
17
+ margin-right: 6px;
18
+ flex-shrink: 0;
19
+ }
20
+
21
+ .ipc-player-trial-badge-status {
22
+ font-size: 12px;
23
+ color: #ffffff;
24
+ font-weight: 500;
25
+ line-height: 1;
26
+ }
27
+
28
+ .ipc-player-trial-badge-divider {
29
+ margin: 0 6px;
30
+ font-size: 12px;
31
+ color: rgba(255, 255, 255, 0.45);
32
+ line-height: 1;
33
+ }
34
+
35
+ .ipc-player-trial-badge-preview {
36
+ font-size: 12px;
37
+ color: rgba(255, 255, 255, 0.78);
38
+ line-height: 1;
39
+ margin-right: 8px;
40
+ }
41
+
42
+ .ipc-player-trial-badge-cta {
43
+ display: inline-flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ height: 22px;
47
+ padding: 0 10px;
48
+ border-radius: 11px;
49
+ flex-shrink: 0;
50
+ }
51
+
52
+ .ipc-player-trial-badge-cta-text {
53
+ font-size: 12px;
54
+ color: #ffffff;
55
+ font-weight: 600;
56
+ line-height: 1;
57
+ }
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import type { EventInstance } from '../../interface';
3
+ export declare const useTrialBadge: (event: EventInstance, devId: string, trialRemainingSec: number) => {
4
+ showTrialBadge: boolean;
5
+ setShowTrialBadge: import("react").Dispatch<import("react").SetStateAction<boolean>>;
6
+ handleTrialSubscribe: () => Promise<void>;
7
+ handleCountdownEnd: () => Promise<void>;
8
+ };
@@ -0,0 +1,42 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { setTrailFinish } from '../../utils/ttt';
3
+ import { gotoSecurityCloudService2 } from '../../utils';
4
+ import { trialCountdownEnd } from '../../ui/constant';
5
+ import Strings from '../../i18n';
6
+ export const useTrialBadge = (event, devId, trialRemainingSec) => {
7
+ const [showTrialBadge, setShowTrialBadge] = useState(false);
8
+ useEffect(() => {
9
+ if (trialRemainingSec > 0 && trialRemainingSec < 300) {
10
+ setShowTrialBadge(true);
11
+ }
12
+ }, [trialRemainingSec]);
13
+ const handleTrialSubscribe = useCallback(async () => {
14
+ try {
15
+ const res = await gotoSecurityCloudService2(devId);
16
+ console.log('res===gotoSecurityCloudService2', res);
17
+ } catch (error) {
18
+ ty.showToast({
19
+ title: Strings.getLang('ipc_player_fetch_error'),
20
+ icon: 'none'
21
+ });
22
+ }
23
+ }, [devId]);
24
+ const handleCountdownEnd = useCallback(async () => {
25
+ try {
26
+ setShowTrialBadge(false);
27
+ event.emit(trialCountdownEnd);
28
+ await setTrailFinish(devId);
29
+ } catch (error) {
30
+ ty.showToast({
31
+ title: Strings.getLang('ipc_player_fetch_error'),
32
+ icon: 'none'
33
+ });
34
+ }
35
+ }, [devId, event]);
36
+ return {
37
+ showTrialBadge,
38
+ setShowTrialBadge,
39
+ handleTrialSubscribe,
40
+ handleCountdownEnd
41
+ };
42
+ };
@@ -0,0 +1 @@
1
+ export * from './tryExperience';
@@ -0,0 +1 @@
1
+ export * from './tryExperience';
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { ComponentConfigProps } from '../../interface';
3
+ import './tryExperience.less';
4
+ type Props = ComponentConfigProps & {
5
+ className?: string;
6
+ hideTryExperienceMenu?: boolean;
7
+ buttonState?: number;
8
+ trialRemainingSec?: number;
9
+ isPurchase?: boolean;
10
+ canOpenSettings?: boolean;
11
+ isLowPhone?: boolean;
12
+ };
13
+ export declare const TryExperience: (props: Props) => React.JSX.Element | null;
14
+ export {};
@@ -0,0 +1,145 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
+ import { View, Image, getSystemInfoSync, showToast } from '@ray-js/ray';
3
+ import clsx from 'clsx';
4
+ import React, { useState, useEffect, useCallback } from 'react';
5
+ import { useStore } from '../../ctx/store';
6
+ import Strings from '../../i18n';
7
+ import { getAIFrameFeature, gotoAIDrawMiniProgram, setAIFrameFeature } from '../../utils';
8
+ import { refreshSmartImageQualityEvent } from '../../ui/constant';
9
+ import tryZh from '../../res/try/try_zh.png';
10
+ import tryEn from '../../res/try/try_en.png';
11
+ import tryOpen from '../../res/try/try_open.png';
12
+ import tryClose from '../../res/try/try_close.png';
13
+ import './tryExperience.less';
14
+ /** ty.ipc.test1 返回的体验状态 */
15
+ var TryExperienceStatus = /*#__PURE__*/function (TryExperienceStatus) {
16
+ TryExperienceStatus[TryExperienceStatus["Default"] = 0] = "Default";
17
+ TryExperienceStatus[TryExperienceStatus["Open"] = 1] = "Open";
18
+ TryExperienceStatus[TryExperienceStatus["Close"] = 2] = "Close";
19
+ return TryExperienceStatus;
20
+ }(TryExperienceStatus || {});
21
+ const ZH_LANG_REGEX = /^zh(_|-|$)/i;
22
+ const getDefaultLangIcon = () => {
23
+ try {
24
+ const {
25
+ language = ''
26
+ } = getSystemInfoSync() || {};
27
+ return ZH_LANG_REGEX.test(String(language)) ? tryZh : tryEn;
28
+ } catch {
29
+ return tryEn;
30
+ }
31
+ };
32
+ const pickIconByStatus = buttonState => {
33
+ switch (buttonState) {
34
+ case TryExperienceStatus.Open:
35
+ return tryOpen;
36
+ case TryExperienceStatus.Close:
37
+ return tryClose;
38
+ case TryExperienceStatus.Default:
39
+ return getDefaultLangIcon();
40
+ default:
41
+ return '';
42
+ }
43
+ };
44
+ export const TryExperience = props => {
45
+ const {
46
+ className,
47
+ hideTryExperienceMenu,
48
+ buttonState,
49
+ trialRemainingSec,
50
+ isPurchase,
51
+ canOpenSettings,
52
+ isLowPhone,
53
+ devId
54
+ } = props;
55
+ const {
56
+ brandColor,
57
+ recording
58
+ } = useStore({
59
+ brandColor: props.brandColor,
60
+ recording: props.recording
61
+ });
62
+ const [imgSrc, setImgSrc] = useState();
63
+ useEffect(() => {
64
+ console.log('res===buttonState', buttonState);
65
+ if (isLowPhone) {
66
+ setImgSrc(tryClose);
67
+ } else if (buttonState) {
68
+ const iconUrl = pickIconByStatus(buttonState);
69
+ setImgSrc(iconUrl);
70
+ } else {
71
+ setImgSrc(undefined);
72
+ }
73
+ }, [buttonState]);
74
+ const onTryExperience = useCallback(async () => {
75
+ if (isLowPhone) {
76
+ showToast({
77
+ title: Strings.getLang('ipc_player_low_phone_not_support'),
78
+ icon: 'none'
79
+ });
80
+ return;
81
+ }
82
+ if (recording) {
83
+ showToast({
84
+ title: Strings.getLang('ipc_player_recording_now_tip'),
85
+ icon: 'none'
86
+ });
87
+ return;
88
+ }
89
+ try {
90
+ const getAI = await getAIFrameFeature(devId);
91
+ if (buttonState === TryExperienceStatus.Open) {
92
+ var _getAI$aiFrameFeature, _getAI$aiFrameFeature2, _getAI$aiFrameFeature3, _props$event;
93
+ const scope = _objectSpread(_objectSpread({}, (_getAI$aiFrameFeature = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature === void 0 ? void 0 : _getAI$aiFrameFeature.scope), {}, {
94
+ inPreview: false
95
+ });
96
+ await setAIFrameFeature({
97
+ devId,
98
+ scene: 'inPreview',
99
+ // 实时预览场景
100
+ enabled: getAI.enabled,
101
+ aiFrameFeature: {
102
+ scope,
103
+ feature: (_getAI$aiFrameFeature2 = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature2 === void 0 ? void 0 : _getAI$aiFrameFeature2.feature,
104
+ exportEnabled: (_getAI$aiFrameFeature3 = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature3 === void 0 ? void 0 : _getAI$aiFrameFeature3.exportEnabled
105
+ }
106
+ });
107
+ (_props$event = props.event) === null || _props$event === void 0 || _props$event.emit(refreshSmartImageQualityEvent);
108
+ } else if (buttonState === TryExperienceStatus.Close && isPurchase || buttonState === TryExperienceStatus.Close && trialRemainingSec < 300 && trialRemainingSec > 0) {
109
+ var _getAI$aiFrameFeature4, _getAI$aiFrameFeature5, _getAI$aiFrameFeature6, _props$event2;
110
+ const scope = _objectSpread(_objectSpread({}, (_getAI$aiFrameFeature4 = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature4 === void 0 ? void 0 : _getAI$aiFrameFeature4.scope), {}, {
111
+ inPreview: true
112
+ });
113
+ await setAIFrameFeature({
114
+ devId,
115
+ scene: 'inPreview',
116
+ // 实时预览场景
117
+ enabled: getAI.enabled,
118
+ aiFrameFeature: {
119
+ scope,
120
+ feature: (_getAI$aiFrameFeature5 = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature5 === void 0 ? void 0 : _getAI$aiFrameFeature5.feature,
121
+ exportEnabled: (_getAI$aiFrameFeature6 = getAI.aiFrameFeature) === null || _getAI$aiFrameFeature6 === void 0 ? void 0 : _getAI$aiFrameFeature6.exportEnabled
122
+ }
123
+ });
124
+ (_props$event2 = props.event) === null || _props$event2 === void 0 || _props$event2.emit(refreshSmartImageQualityEvent);
125
+ } else {
126
+ gotoAIDrawMiniProgram(devId, brandColor);
127
+ }
128
+ } catch (error) {
129
+ //
130
+ }
131
+ }, [buttonState, recording, isPurchase, trialRemainingSec]);
132
+ if (hideTryExperienceMenu) {
133
+ return null;
134
+ }
135
+ return /*#__PURE__*/React.createElement(React.Fragment, null, imgSrc && canOpenSettings && /*#__PURE__*/React.createElement(View, {
136
+ className: clsx(className),
137
+ onClick: onTryExperience
138
+ }, /*#__PURE__*/React.createElement(View, {
139
+ className: "try-experience-box"
140
+ }, /*#__PURE__*/React.createElement(Image, {
141
+ className: "try-experience-icon",
142
+ src: imgSrc,
143
+ mode: "heightFix"
144
+ }))));
145
+ };
@@ -0,0 +1,13 @@
1
+ .try-experience-box {
2
+ display: inline-flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ min-height: calc(var(--iconBoxSize) * var(--ipc-player-size-scale, 1));
6
+ }
7
+
8
+ .try-experience-icon {
9
+ display: block;
10
+ height: calc(var(--iconBoxSize) * var(--ipc-player-size-scale, 1));
11
+ width: auto;
12
+ flex-shrink: 0;
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/ipc-player-integration",
3
- "version": "0.0.35-beta.1",
3
+ "version": "0.0.35-beta.10",
4
4
  "description": "IPC 融合播放器",
5
5
  "main": "lib/index",
6
6
  "files": [
@@ -37,7 +37,7 @@
37
37
  "dependencies": {
38
38
  "@ray-js/direction-control": "^0.0.8",
39
39
  "@ray-js/ipc-ptz-zoom": "^0.0.3",
40
- "@ray-js/ray-ipc-player": "2.1.1-beta.1",
40
+ "@ray-js/ray-ipc-player": "2.1.1-beta.3",
41
41
  "@ray-js/ray-ipc-utils": "^1.1.15",
42
42
  "@ray-js/svg": "0.2.0",
43
43
  "clsx": "^1.2.1",
@@ -64,7 +64,7 @@
64
64
  "husky": {
65
65
  "hooks": {
66
66
  "commit-msg": "commitlint -E HUSKY_GIT_PARAMS --config commitlint.config.js",
67
- "pre-commit": "lint-staged"
67
+ "pre-commit": "node ./scripts/check-protected-files.js && lint-staged"
68
68
  }
69
69
  },
70
70
  "lint-staged": {