@ledvance/base 1.3.103 → 1.3.104
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/localazy.json +9 -1
- package/package.json +1 -1
- package/src/components/AdvanceCard.tsx +13 -5
- package/src/components/AdvanceList.tsx +16 -8
- package/src/components/Marquee.tsx +99 -0
- package/src/composeLayout.tsx +7 -3
- package/src/i18n/strings.ts +253 -13
- package/src/models/TuyaApi.ts +60 -43
- package/src/models/modules/NativePropsSlice.tsx +14 -3
- package/translateKey.txt +9 -1
package/localazy.json
CHANGED
|
@@ -1291,7 +1291,15 @@
|
|
|
1291
1291
|
"MATCH:infobutton_randomtimecycle",
|
|
1292
1292
|
"MATCH:infobutton_timer",
|
|
1293
1293
|
"MATCH:infobutton_poweronbehavior",
|
|
1294
|
-
"MATCH:infobutton_history"
|
|
1294
|
+
"MATCH:infobutton_history",
|
|
1295
|
+
"MATCH:country_JO",
|
|
1296
|
+
"MATCH:country_CV",
|
|
1297
|
+
"MATCH:country_PA",
|
|
1298
|
+
"MATCH:country_northern_ireland",
|
|
1299
|
+
"MATCH:country_wales",
|
|
1300
|
+
"MATCH:country_BA",
|
|
1301
|
+
"MATCH:country_north_macedonia",
|
|
1302
|
+
"MATCH:country_werder_bremen"
|
|
1295
1303
|
],
|
|
1296
1304
|
"replacements": {
|
|
1297
1305
|
"REGEX:% %1\\$s.*?\\)%": "{0}",
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { Utils } from 'tuya-panel-kit'
|
|
|
4
4
|
import Card from './Card'
|
|
5
5
|
import Spacer from './Spacer'
|
|
6
6
|
import ThemeType from '../config/themeType'
|
|
7
|
+
import Marquee from './Marquee'
|
|
7
8
|
|
|
8
9
|
const { convertX: cx } = Utils.RatioUtils
|
|
9
10
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -47,6 +48,8 @@ export interface AdvanceCardProps extends PropsWithChildren<ViewProps> {
|
|
|
47
48
|
|
|
48
49
|
const AdvanceCard = (props: AdvanceCardProps) => {
|
|
49
50
|
const {statusColor} = props.data;
|
|
51
|
+
const subtitles = props.data.subtitles
|
|
52
|
+
const subtitleStyle = {...styles.subtitle, color: props.theme?.global.secondFontColor};
|
|
50
53
|
return (
|
|
51
54
|
<Card
|
|
52
55
|
style={styles.itemContainer}
|
|
@@ -68,9 +71,15 @@ const AdvanceCard = (props: AdvanceCardProps) => {
|
|
|
68
71
|
<Text style={{...styles.title, color: props.theme?.global.fontColor}}>{props.data.title}</Text>
|
|
69
72
|
<Spacer height={cx(8)} />
|
|
70
73
|
{
|
|
71
|
-
(!!
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
(!!subtitles && subtitles.length > 0) && (
|
|
75
|
+
subtitles.length === 1 ? (
|
|
76
|
+
// 如果只有一个subtitle,静态显示
|
|
77
|
+
<Text style={subtitleStyle}>{subtitles[0]}</Text>
|
|
78
|
+
) : (
|
|
79
|
+
// 如果有多个subtitle,使用Marquee组件
|
|
80
|
+
<Marquee subtitles={subtitles} textStyle={subtitleStyle} />
|
|
81
|
+
)
|
|
82
|
+
)
|
|
74
83
|
}
|
|
75
84
|
</View>
|
|
76
85
|
}
|
|
@@ -85,7 +94,7 @@ const styles = StyleSheet.create({
|
|
|
85
94
|
},
|
|
86
95
|
itemContent: {},
|
|
87
96
|
titleBg: {
|
|
88
|
-
height: cx(
|
|
97
|
+
height: cx(80),
|
|
89
98
|
justifyContent: 'center',
|
|
90
99
|
alignItems: 'center',
|
|
91
100
|
},
|
|
@@ -98,7 +107,6 @@ const styles = StyleSheet.create({
|
|
|
98
107
|
subtitle: {
|
|
99
108
|
fontSize: cx(10),
|
|
100
109
|
textAlign: 'center',
|
|
101
|
-
fontFamily: 'helvetica_neue_lt_std_roman',
|
|
102
110
|
},
|
|
103
111
|
dotBg: {
|
|
104
112
|
position: 'absolute',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { useIsPad } from '../models/modules/NativePropsSlice'
|
|
1
2
|
import { useNavigation } from '@react-navigation/core'
|
|
2
|
-
import React, { useCallback } from 'react'
|
|
3
|
+
import React, { useCallback, useState } from 'react'
|
|
3
4
|
import { FlatList, Image, StyleSheet, View } from 'react-native'
|
|
4
5
|
import { Utils } from 'tuya-panel-kit'
|
|
5
6
|
import { getMicrophoneAccess } from '../api/native'
|
|
@@ -16,6 +17,8 @@ export interface AdvanceListProps {
|
|
|
16
17
|
|
|
17
18
|
function AdvanceList(props: AdvanceListProps) {
|
|
18
19
|
const navigation = useNavigation()
|
|
20
|
+
const isPad = useIsPad()
|
|
21
|
+
const [columns, setColumns] = useState(isPad ? 3 : 2)
|
|
19
22
|
|
|
20
23
|
const { advanceData = [] } = props
|
|
21
24
|
|
|
@@ -72,27 +75,32 @@ function AdvanceList(props: AdvanceListProps) {
|
|
|
72
75
|
container: {
|
|
73
76
|
marginHorizontal: cx(14),
|
|
74
77
|
},
|
|
78
|
+
columnContainer: {
|
|
79
|
+
justifyContent: 'space-between'
|
|
80
|
+
},
|
|
75
81
|
item: {
|
|
76
|
-
flex: 0
|
|
77
|
-
|
|
78
|
-
alignItems: '
|
|
82
|
+
flex: 0,
|
|
83
|
+
marginHorizontal: cx(10),
|
|
84
|
+
alignItems: 'flex-start',
|
|
79
85
|
},
|
|
80
86
|
iconContainer: {
|
|
81
|
-
height: cx(
|
|
87
|
+
height: cx(80),
|
|
82
88
|
justifyContent: 'center' as const,
|
|
83
89
|
alignItems: 'center' as const,
|
|
84
90
|
},
|
|
85
91
|
iconImage: {
|
|
86
|
-
width: cx(
|
|
87
|
-
height: cx(
|
|
92
|
+
width: cx(50),
|
|
93
|
+
height: cx(50),
|
|
88
94
|
}
|
|
89
95
|
})
|
|
90
96
|
|
|
91
97
|
return (
|
|
92
98
|
<FlatList
|
|
99
|
+
key={`flatlist-columns-${columns}`}
|
|
93
100
|
scrollEnabled={false}
|
|
94
|
-
numColumns={
|
|
101
|
+
numColumns={columns}
|
|
95
102
|
style={styles.container}
|
|
103
|
+
columnWrapperStyle={styles.columnContainer}
|
|
96
104
|
data={advanceData}
|
|
97
105
|
renderItem={renderItem}
|
|
98
106
|
keyExtractor={keyExtractor}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { View, Text, Animated, StyleSheet, StyleProp, TextStyle } from 'react-native';
|
|
3
|
+
import { Utils } from 'tuya-panel-kit';
|
|
4
|
+
|
|
5
|
+
const { convertX: cx } = Utils.RatioUtils;
|
|
6
|
+
|
|
7
|
+
// 定义每个字幕项的固定高度
|
|
8
|
+
const SUBTITLE_HEIGHT = cx(14);
|
|
9
|
+
// 动画切换的持续时间
|
|
10
|
+
const ANIMATION_DURATION = 500;
|
|
11
|
+
// 每个字幕停留显示的时间
|
|
12
|
+
const PAUSE_DURATION = 2000;
|
|
13
|
+
|
|
14
|
+
interface MarqueeProps {
|
|
15
|
+
subtitles: string[];
|
|
16
|
+
textStyle: StyleProp<TextStyle>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Marquee: React.FC<MarqueeProps> = ({ subtitles, textStyle }) => {
|
|
20
|
+
const scrollY = useRef(new Animated.Value(0)).current;
|
|
21
|
+
|
|
22
|
+
// 复制第一个元素到末尾以实现无缝循环
|
|
23
|
+
const displaySubtitles = [...subtitles, subtitles[0]];
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let animation: Animated.CompositeAnimation | null = null;
|
|
27
|
+
|
|
28
|
+
const animate = (index: number) => {
|
|
29
|
+
const nextIndex = index + 1;
|
|
30
|
+
|
|
31
|
+
animation = Animated.sequence([
|
|
32
|
+
Animated.delay(PAUSE_DURATION),
|
|
33
|
+
Animated.timing(scrollY, {
|
|
34
|
+
toValue: -nextIndex * SUBTITLE_HEIGHT,
|
|
35
|
+
duration: ANIMATION_DURATION,
|
|
36
|
+
useNativeDriver: true,
|
|
37
|
+
}),
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
animation.start(({ finished }) => {
|
|
41
|
+
if (finished) {
|
|
42
|
+
if (nextIndex >= subtitles.length) {
|
|
43
|
+
// 当滚动到复制的最后一项后,无动画地重置到起点
|
|
44
|
+
scrollY.setValue(0);
|
|
45
|
+
// 从头开始循环
|
|
46
|
+
animate(0);
|
|
47
|
+
} else {
|
|
48
|
+
// 继续下一次滚动
|
|
49
|
+
animate(nextIndex);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// 仅当有多个字幕时才启动动画
|
|
56
|
+
if (subtitles.length > 1) {
|
|
57
|
+
animate(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
if (animation) {
|
|
62
|
+
animation.stop();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}, [subtitles]);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<View style={styles.marqueeContainer}>
|
|
69
|
+
<Animated.View
|
|
70
|
+
style={{
|
|
71
|
+
transform: [{ translateY: scrollY }],
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{displaySubtitles.map((subtitle, index) => (
|
|
75
|
+
<Text
|
|
76
|
+
key={`${subtitle}_${index}`}
|
|
77
|
+
style={[textStyle, styles.subtitleText]}
|
|
78
|
+
numberOfLines={1}
|
|
79
|
+
>
|
|
80
|
+
{subtitle}
|
|
81
|
+
</Text>
|
|
82
|
+
))}
|
|
83
|
+
</Animated.View>
|
|
84
|
+
</View>
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const styles = StyleSheet.create({
|
|
89
|
+
marqueeContainer: {
|
|
90
|
+
height: SUBTITLE_HEIGHT, // 容器高度被限制为只能显示一个字幕
|
|
91
|
+
overflow: 'hidden', // 超出部分隐藏
|
|
92
|
+
},
|
|
93
|
+
subtitleText: {
|
|
94
|
+
height: SUBTITLE_HEIGHT, // 确保每个Text元素有相同的高度
|
|
95
|
+
lineHeight: SUBTITLE_HEIGHT, // **【关键】** 让lineHeight等于height,实现文本在行内垂直居中
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export default Marquee;
|
package/src/composeLayout.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import _ from 'lodash'
|
|
|
2
2
|
import React, { Component } from 'react'
|
|
3
3
|
import { Provider } from 'react-redux'
|
|
4
4
|
import { DevInfo, DpValue, Theme, TYSdk } from 'tuya-panel-kit'
|
|
5
|
-
import { actions, store } from '
|
|
5
|
+
import { actions, store } from '@models'
|
|
6
6
|
import { addListener, nativeEventEmitter, removeListener } from './api/nativeEventEmitter'
|
|
7
7
|
import { getSystemTimeFormat, getTimeZone, NativeApi } from './api/native'
|
|
8
8
|
import {
|
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
NativeProps,
|
|
11
11
|
setGroupDevices,
|
|
12
12
|
setGroupNativeProps,
|
|
13
|
-
setNativeProps,
|
|
13
|
+
setNativeProps,
|
|
14
|
+
setNewPalette,
|
|
15
|
+
setIsPad,
|
|
14
16
|
setSystemTimeFormat,
|
|
15
17
|
setTimeZone,
|
|
16
18
|
UAGroupInfo,
|
|
@@ -27,6 +29,7 @@ interface Props {
|
|
|
27
29
|
uaGroupInfo: UAGroupInfoProps
|
|
28
30
|
colorScheme?: string
|
|
29
31
|
newPalette?: boolean
|
|
32
|
+
isPad?: boolean
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
interface LdvDevInfo extends DeviceInfo {
|
|
@@ -138,6 +141,7 @@ const composeLayout = (component: React.ComponentType) => {
|
|
|
138
141
|
})
|
|
139
142
|
|
|
140
143
|
dispatch(setNewPalette(!!props.newPalette))
|
|
144
|
+
dispatch(setIsPad(!!props.isPad))
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
initReduxDeviceNativeProps(ldvDevInfo: LdvDevInfo) {
|
|
@@ -162,7 +166,7 @@ const composeLayout = (component: React.ComponentType) => {
|
|
|
162
166
|
familyName: ldvDevInfo.familyName,
|
|
163
167
|
role: ldvDevInfo.role,
|
|
164
168
|
moods: [],
|
|
165
|
-
is24HourClock: true
|
|
169
|
+
is24HourClock: true,
|
|
166
170
|
}
|
|
167
171
|
NativeApi.showObj(nativeProps)
|
|
168
172
|
console.log('Redux 初始数据:', JSON.stringify(nativeProps))
|