@ledvance/base 1.3.66 → 1.3.68
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/package.json +1 -1
- package/src/components/ColorAdjustView.tsx +11 -77
- package/src/components/ColorTempAdjustView.tsx +6 -75
- package/src/composeLayout.tsx +1 -3
- package/src/models/TuyaApi.ts +0 -132
- package/src/models/modules/NativePropsSlice.tsx +2 -13
- package/src/components/rect-color-and-bright-picker/ColourPicker.tsx +0 -266
- package/src/components/rect-color-and-bright-picker/RectPicker.tsx +0 -398
- package/src/components/rect-color-and-bright-picker/Slider.tsx +0 -468
- package/src/components/rect-color-and-bright-picker/Thumb.tsx +0 -78
- package/src/components/rect-color-and-bright-picker/WhitePicker.tsx +0 -400
- package/src/components/rect-color-and-bright-picker/brightness-icons/index.ts +0 -8
- package/src/components/rect-color-and-bright-picker/index.tsx +0 -5
- package/src/components/rect-color-and-bright-picker/res/index.ts +0 -3
- package/src/components/rect-color-and-bright-picker/res/thumb-mask@2x.png +0 -0
- package/src/components/rect-color-and-bright-picker/res/thumb-mask@3x.png +0 -0
- package/src/components/rect-color-and-bright-picker/utils/color.ts +0 -73
- package/src/components/rect-color-and-bright-picker/utils/storage.ts +0 -97
package/package.json
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import {View} from 'react-native'
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react'
|
|
3
3
|
import LdvColorSlider from './ldvColorSlider'
|
|
4
4
|
import {hex2Hsv, hsv2Hex} from '../utils'
|
|
5
5
|
import LdvPresetView from './ldvPresetView'
|
|
6
6
|
import LdvSaturation from './ldvSaturation'
|
|
7
7
|
import LdvColorBrightness from './ldvColorBrightness'
|
|
8
8
|
import I18n from '../i18n/index'
|
|
9
|
-
import RectColorAndBrightPicker from './rect-color-and-bright-picker'
|
|
10
|
-
import {Utils} from "tuya-panel-kit";
|
|
11
|
-
import {useReactive, useUpdateEffect} from "ahooks";
|
|
12
|
-
import {useNewPalette} from "../models/modules/NativePropsSlice";
|
|
13
|
-
|
|
14
|
-
const cx = Utils.RatioUtils.convertX
|
|
15
|
-
const scaleUp = (value) => value * 10
|
|
16
|
-
const scaleDown = (value) => Math.round(value / 10)
|
|
17
|
-
const width = Utils.RatioUtils.width - cx(80)
|
|
18
9
|
|
|
19
10
|
export interface ColorAdjustViewProps {
|
|
20
11
|
h: number
|
|
@@ -28,59 +19,7 @@ export interface ColorAdjustViewProps {
|
|
|
28
19
|
onHSVChangeComplete: (h: number, s: number, v: number) => void
|
|
29
20
|
}
|
|
30
21
|
|
|
31
|
-
const
|
|
32
|
-
const { h = 0, s = 100, v = 100, minBrightness = 10, onHSVChange, onHSVChangeComplete } = props
|
|
33
|
-
const state = useReactive({
|
|
34
|
-
hue: h,
|
|
35
|
-
saturation: scaleUp(s),
|
|
36
|
-
value: scaleUp(v),
|
|
37
|
-
moving: false
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
useUpdateEffect(() => {
|
|
41
|
-
if (!state.moving) {
|
|
42
|
-
state.hue = h
|
|
43
|
-
state.saturation = scaleUp(s)
|
|
44
|
-
state.value = scaleUp(v)
|
|
45
|
-
}
|
|
46
|
-
}, [h, s, v])
|
|
47
|
-
|
|
48
|
-
const handleMove = useCallback((v) => {
|
|
49
|
-
onHSVChange?.(v.hue, scaleDown(v.saturation), scaleDown(v.value))
|
|
50
|
-
}, [onHSVChange])
|
|
51
|
-
|
|
52
|
-
const handleComplete = useCallback((v) => {
|
|
53
|
-
onHSVChangeComplete?.(v.hue, scaleDown(v.saturation), scaleDown(v.value))
|
|
54
|
-
state.moving = false
|
|
55
|
-
}, [onHSVChangeComplete])
|
|
56
|
-
|
|
57
|
-
const { hue, saturation, value } = state;
|
|
58
|
-
const hsv = { hue, saturation, value };
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<View style={{justifyContent: 'center', alignItems: 'center'}}>
|
|
62
|
-
<View style={{
|
|
63
|
-
width: width,
|
|
64
|
-
height: cx(200),
|
|
65
|
-
borderRadius: cx(10),
|
|
66
|
-
borderColor: '#eeeeef',
|
|
67
|
-
borderWidth: 1,
|
|
68
|
-
overflow: 'hidden'
|
|
69
|
-
}}>
|
|
70
|
-
<RectColorAndBrightPicker.ColourPicker
|
|
71
|
-
value={hsv}
|
|
72
|
-
brightOption={{min: minBrightness, minPercent: minBrightness ? 1 : 0}}
|
|
73
|
-
onGrant={() => state.moving = true}
|
|
74
|
-
onMove={handleMove}
|
|
75
|
-
onRelease={handleComplete}
|
|
76
|
-
onPress={handleComplete}
|
|
77
|
-
/>
|
|
78
|
-
</View>
|
|
79
|
-
</View>
|
|
80
|
-
)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
const OldColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
22
|
+
const ColorAdjustView = (props: ColorAdjustViewProps) => {
|
|
84
23
|
return (
|
|
85
24
|
<View>
|
|
86
25
|
<LdvColorSlider
|
|
@@ -103,14 +42,14 @@ const OldColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
|
103
42
|
}
|
|
104
43
|
}}/>
|
|
105
44
|
{!props.hideSat && <LdvSaturation
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
45
|
+
value={props.s}
|
|
46
|
+
minSaturation={props.minSaturation}
|
|
47
|
+
onValueChange={s => {
|
|
48
|
+
props.onHSVChange && props.onHSVChange(props.h, s, props.v)
|
|
49
|
+
}}
|
|
50
|
+
onSlidingComplete={s => {
|
|
51
|
+
props.onHSVChangeComplete(props.h, s, props.v)
|
|
52
|
+
}}/>}
|
|
114
53
|
<LdvColorBrightness
|
|
115
54
|
minBrightness={props.minBrightness}
|
|
116
55
|
value={props.v}
|
|
@@ -122,11 +61,6 @@ const OldColorPicker = React.memo((props: ColorAdjustViewProps) => {
|
|
|
122
61
|
}}/>
|
|
123
62
|
</View>
|
|
124
63
|
)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const ColorAdjustView = (props: ColorAdjustViewProps) => {
|
|
128
|
-
const newPalette = useNewPalette()
|
|
129
|
-
return newPalette ? <NewColorPicker {...props} /> : <OldColorPicker {...props} />
|
|
130
64
|
}
|
|
131
65
|
|
|
132
|
-
export default ColorAdjustView
|
|
66
|
+
export default ColorAdjustView
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {View} from 'react-native'
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react'
|
|
3
3
|
import LdvColorSlider from './ldvColorSlider'
|
|
4
4
|
import Spacer from './Spacer'
|
|
5
5
|
import LdvPresetView from './ldvPresetView'
|
|
@@ -7,17 +7,13 @@ import LdvSlider from './ldvSlider'
|
|
|
7
7
|
import {Utils} from 'tuya-panel-kit'
|
|
8
8
|
import I18n from '../i18n/index'
|
|
9
9
|
import {cctToColor} from '../utils/cctUtils'
|
|
10
|
-
import
|
|
11
|
-
import {useReactive, useUpdateEffect} from 'ahooks'
|
|
12
|
-
import { useNewPalette } from 'models/modules/NativePropsSlice'
|
|
10
|
+
import ThemeType from '../config/themeType'
|
|
13
11
|
|
|
14
12
|
const {convertX: cx} = Utils.RatioUtils
|
|
15
|
-
|
|
16
|
-
const scaleUp = (value: number) => value * 10;
|
|
17
|
-
const scaleDown = (value: number) => Math.round(value / 10);
|
|
18
|
-
const width = Utils.RatioUtils.width - cx(80);
|
|
13
|
+
const { withTheme } = Utils.ThemeUtils
|
|
19
14
|
|
|
20
15
|
export interface ColorTempAdjustViewProps {
|
|
16
|
+
theme?: ThemeType
|
|
21
17
|
colorTemp: number
|
|
22
18
|
brightness: number
|
|
23
19
|
minBrightness?: number
|
|
@@ -29,67 +25,7 @@ export interface ColorTempAdjustViewProps {
|
|
|
29
25
|
onBrightnessChangeComplete: (brightness: number) => void
|
|
30
26
|
}
|
|
31
27
|
|
|
32
|
-
const
|
|
33
|
-
const {
|
|
34
|
-
colorTemp = 0,
|
|
35
|
-
brightness = 100,
|
|
36
|
-
isSupportTemperature,
|
|
37
|
-
onCCTChange,
|
|
38
|
-
onCCTChangeComplete,
|
|
39
|
-
onBrightnessChange,
|
|
40
|
-
onBrightnessChangeComplete,
|
|
41
|
-
} = props
|
|
42
|
-
const state = useReactive({
|
|
43
|
-
temperature: scaleUp(colorTemp),
|
|
44
|
-
brightness: scaleUp(brightness),
|
|
45
|
-
moving: false
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
useUpdateEffect(() => {
|
|
49
|
-
if (!state.moving) {
|
|
50
|
-
state.temperature = scaleUp(colorTemp)
|
|
51
|
-
state.brightness = scaleUp(brightness)
|
|
52
|
-
}
|
|
53
|
-
}, [colorTemp, brightness])
|
|
54
|
-
|
|
55
|
-
const handleMove = useCallback((v) => {
|
|
56
|
-
onCCTChange?.(scaleDown(v.temperature))
|
|
57
|
-
onBrightnessChange?.(scaleDown(v.brightness))
|
|
58
|
-
}, [onCCTChange, onBrightnessChange])
|
|
59
|
-
|
|
60
|
-
const handleComplete = useCallback((v) => {
|
|
61
|
-
onCCTChangeComplete?.(scaleDown(v.temperature))
|
|
62
|
-
onBrightnessChangeComplete?.(scaleDown(v.brightness))
|
|
63
|
-
state.moving = false
|
|
64
|
-
}, [onCCTChangeComplete, onBrightnessChangeComplete])
|
|
65
|
-
|
|
66
|
-
const { temperature, brightness: stateBrightness } = state
|
|
67
|
-
const white = { temperature, brightness: stateBrightness }
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<View style={{justifyContent: 'center', alignItems: 'center'}}>
|
|
71
|
-
<View style={{
|
|
72
|
-
width: width,
|
|
73
|
-
height: cx(isSupportTemperature? 200 : 50),
|
|
74
|
-
borderRadius: cx(10),
|
|
75
|
-
borderColor: '#eeeeef',
|
|
76
|
-
borderWidth: 1,
|
|
77
|
-
overflow: 'hidden'
|
|
78
|
-
}}>
|
|
79
|
-
<RectColorAndBrightPicker.WhitePicker
|
|
80
|
-
hideTemp={!isSupportTemperature}
|
|
81
|
-
value={white}
|
|
82
|
-
onGrant={() => state.moving = true}
|
|
83
|
-
onMove={handleMove}
|
|
84
|
-
onRelease={handleComplete}
|
|
85
|
-
onPress={handleComplete}
|
|
86
|
-
/>
|
|
87
|
-
</View>
|
|
88
|
-
</View>
|
|
89
|
-
)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
const OldColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
28
|
+
const ColorTempAdjustView = (props: ColorTempAdjustViewProps) => {
|
|
93
29
|
return (
|
|
94
30
|
<View>
|
|
95
31
|
{props.isSupportTemperature &&
|
|
@@ -120,11 +56,6 @@ const OldColorTempPicker = React.memo((props: ColorTempAdjustViewProps) => {
|
|
|
120
56
|
onSlidingComplete={props.onBrightnessChangeComplete}/>}
|
|
121
57
|
</View>
|
|
122
58
|
)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
const ColorTempAdjustView = (props: ColorTempAdjustViewProps) => {
|
|
126
|
-
const newPalette = useNewPalette()
|
|
127
|
-
return newPalette ? <NewColorTempPicker {...props} /> : <OldColorTempPicker {...props} />
|
|
128
59
|
}
|
|
129
60
|
|
|
130
|
-
export default ColorTempAdjustView
|
|
61
|
+
export default withTheme(ColorTempAdjustView)
|
package/src/composeLayout.tsx
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
NativeProps,
|
|
11
11
|
setGroupDevices,
|
|
12
12
|
setGroupNativeProps,
|
|
13
|
-
setNativeProps,
|
|
13
|
+
setNativeProps,
|
|
14
14
|
setSystemTimeFormat,
|
|
15
15
|
setTimeZone,
|
|
16
16
|
UAGroupInfo,
|
|
@@ -26,7 +26,6 @@ interface Props {
|
|
|
26
26
|
ldvDevInfo: LdvDevInfo
|
|
27
27
|
uaGroupInfo: UAGroupInfoProps
|
|
28
28
|
colorScheme?: string
|
|
29
|
-
newPalette?: boolean
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
interface LdvDevInfo extends DeviceInfo {
|
|
@@ -132,7 +131,6 @@ const composeLayout = (component: React.ComponentType) => {
|
|
|
132
131
|
dispatch(setTimeZone(timeZone))
|
|
133
132
|
})
|
|
134
133
|
|
|
135
|
-
dispatch(setNewPalette(!!props.newPalette))
|
|
136
134
|
}
|
|
137
135
|
|
|
138
136
|
initReduxDeviceNativeProps(ldvDevInfo: LdvDevInfo) {
|
package/src/models/TuyaApi.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {commonApi} from '@tuya/tuya-panel-api'
|
|
2
2
|
import { IGetDpResultByHourResponse, IGetDpResultByMonthResponse } from '@tuya/tuya-panel-api/lib/common/interface'
|
|
3
3
|
import {sendAppEvent} from "../api/native";
|
|
4
|
-
import {retryWithBackoff} from "../utils/index";
|
|
5
|
-
import {TYSdk} from "tuya-panel-kit";
|
|
6
4
|
|
|
7
5
|
export interface PagingResult<T> {
|
|
8
6
|
data: T
|
|
@@ -150,133 +148,3 @@ export async function getDpResultByHour(
|
|
|
150
148
|
}
|
|
151
149
|
}
|
|
152
150
|
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* 获取设备所有数据点记录(支持失败重试)
|
|
156
|
-
* @param commonApi API实例
|
|
157
|
-
* @param devId 设备ID
|
|
158
|
-
* @param dpIds 数据点ID,如 '19'
|
|
159
|
-
* @param sortType 排序方式
|
|
160
|
-
* @param retryOptions 重试选项
|
|
161
|
-
* @returns 所有数据点记录
|
|
162
|
-
*/
|
|
163
|
-
export async function getAllDpReportLogs(
|
|
164
|
-
devId: string,
|
|
165
|
-
dpIds: string[],
|
|
166
|
-
sortType: 'ASC' | 'DESC' = 'ASC',
|
|
167
|
-
retryOptions: {
|
|
168
|
-
maxRetries?: number;
|
|
169
|
-
initialDelay?: number;
|
|
170
|
-
maxDelay?: number;
|
|
171
|
-
backoffFactor?: number;
|
|
172
|
-
} = {}
|
|
173
|
-
): Promise<DpReportSataData[]> {
|
|
174
|
-
const limit = 100; // 每次请求的数据量
|
|
175
|
-
let offset = 1;
|
|
176
|
-
let hasNext = true;
|
|
177
|
-
const allDps: DpReportSataData[] = [];
|
|
178
|
-
|
|
179
|
-
while (hasNext) {
|
|
180
|
-
try {
|
|
181
|
-
// 使用重试函数包装API调用
|
|
182
|
-
const res: DpReportSataResData = await retryWithBackoff(
|
|
183
|
-
() => commonApi.statApi.getDpReportLog({
|
|
184
|
-
devId,
|
|
185
|
-
dpIds: dpIds.join(','),
|
|
186
|
-
offset,
|
|
187
|
-
limit,
|
|
188
|
-
sortType
|
|
189
|
-
}),
|
|
190
|
-
{
|
|
191
|
-
...retryOptions,
|
|
192
|
-
// 自定义判断哪些错误需要重试
|
|
193
|
-
shouldRetry: (error) => {
|
|
194
|
-
// 网络错误、超时错误或服务器错误(5xx)通常需要重试
|
|
195
|
-
const isNetworkError = error.name === 'NetworkError' ||
|
|
196
|
-
error.name === 'TimeoutError' ||
|
|
197
|
-
(error.response && error.response.status >= 500);
|
|
198
|
-
|
|
199
|
-
// 对于特定的业务错误码也可以在这里添加判断
|
|
200
|
-
return isNetworkError;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
allDps.push(...res.dps);
|
|
206
|
-
|
|
207
|
-
if (res.hasNext) {
|
|
208
|
-
offset += limit;
|
|
209
|
-
} else {
|
|
210
|
-
hasNext = false;
|
|
211
|
-
}
|
|
212
|
-
} catch (error) {
|
|
213
|
-
console.error('获取数据点记录失败,不再继续获取:', error);
|
|
214
|
-
hasNext = false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return allDps;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export const saveDeviceExtInfo = async (devId: string, key: string, value: string): Promise<boolean> => {
|
|
222
|
-
try {
|
|
223
|
-
return await new Promise<any>((resolve, reject) => {
|
|
224
|
-
TYSdk.native.apiRNRequest(
|
|
225
|
-
{
|
|
226
|
-
v: "1.0",
|
|
227
|
-
postData: {
|
|
228
|
-
value: value,
|
|
229
|
-
key: key,
|
|
230
|
-
devId: devId
|
|
231
|
-
},
|
|
232
|
-
a: "tuya.m.solution.device.storage.save"
|
|
233
|
-
},
|
|
234
|
-
(success: any) => {
|
|
235
|
-
console.log('tuya.m.solution.device.storage.save success', success)
|
|
236
|
-
resolve(success)
|
|
237
|
-
},
|
|
238
|
-
(error: any) => {
|
|
239
|
-
console.log('tuya.m.solution.device.storage.save error', error)
|
|
240
|
-
reject(error)
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
})
|
|
244
|
-
} catch (error) {
|
|
245
|
-
console.log('saveDeviceExtInfo error', error)
|
|
246
|
-
return false
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export const getDeviceExtInfo = async (devId: string, key: string): Promise<string | null> => {
|
|
251
|
-
try {
|
|
252
|
-
const success = await new Promise<any>((resolve, reject) => {
|
|
253
|
-
TYSdk.native.apiRNRequest(
|
|
254
|
-
{
|
|
255
|
-
v: "1.0",
|
|
256
|
-
postData: {
|
|
257
|
-
"key": key,
|
|
258
|
-
"devId": devId
|
|
259
|
-
},
|
|
260
|
-
a: "tuya.m.solution.device.storage.get"
|
|
261
|
-
},
|
|
262
|
-
(success: any) => {
|
|
263
|
-
console.log('tuya.m.solution.device.storage.get success', success)
|
|
264
|
-
resolve(success)
|
|
265
|
-
},
|
|
266
|
-
(error: any) => {
|
|
267
|
-
console.log('tuya.m.solution.device.storage.get error', error)
|
|
268
|
-
reject(error)
|
|
269
|
-
}
|
|
270
|
-
)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
let data = success
|
|
274
|
-
if (typeof success === 'string') {
|
|
275
|
-
data = JSON.parse(success)
|
|
276
|
-
}
|
|
277
|
-
return data.value
|
|
278
|
-
} catch (error) {
|
|
279
|
-
console.log('getDeviceExtInfo error', error)
|
|
280
|
-
return null
|
|
281
|
-
}
|
|
282
|
-
}
|
|
@@ -24,7 +24,6 @@ export interface NativeProps {
|
|
|
24
24
|
is24HourClock: boolean
|
|
25
25
|
timeZone: string
|
|
26
26
|
gestureControlValues: GestureControlType
|
|
27
|
-
newPalette?: boolean
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
interface FlagModeState {
|
|
@@ -88,8 +87,7 @@ const initialState: NativeProps = {
|
|
|
88
87
|
timeZone: 'Europe/Berlin',
|
|
89
88
|
gestureControlValues: {
|
|
90
89
|
isEnd: false
|
|
91
|
-
}
|
|
92
|
-
newPalette: false
|
|
90
|
+
}
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
// energy generation
|
|
@@ -190,9 +188,6 @@ const nativePropsSlice = createSlice({
|
|
|
190
188
|
keys.forEach(key => {
|
|
191
189
|
state.gestureControlValues[key] = action.payload[key]
|
|
192
190
|
})
|
|
193
|
-
},
|
|
194
|
-
setNewPalette(state, action: PayloadAction<boolean>) {
|
|
195
|
-
state.newPalette = action.payload
|
|
196
191
|
}
|
|
197
192
|
},
|
|
198
193
|
})
|
|
@@ -484,10 +479,6 @@ function useGestureControl<K extends keyof GestureControlType>(key: K): [Gesture
|
|
|
484
479
|
return [value]
|
|
485
480
|
}
|
|
486
481
|
|
|
487
|
-
const useNewPalette = () => {
|
|
488
|
-
return useSelector(store => store.ldvModules.newPalette)
|
|
489
|
-
}
|
|
490
|
-
|
|
491
482
|
export const useFanMaxSpeed = () => {
|
|
492
483
|
const { productId } = useDeviceInfo()
|
|
493
484
|
return fanProductList.includes(productId) ? 20 : 3
|
|
@@ -514,7 +505,6 @@ export const {
|
|
|
514
505
|
setTimeZone,
|
|
515
506
|
setEnergieverbrauch,
|
|
516
507
|
setGestureControlValues,
|
|
517
|
-
setNewPalette,
|
|
518
508
|
} = nativePropsSlice.actions
|
|
519
509
|
|
|
520
510
|
export {
|
|
@@ -541,6 +531,5 @@ export {
|
|
|
541
531
|
useTimeZoneCity,
|
|
542
532
|
useEnergieverbrauch,
|
|
543
533
|
useGestureControl,
|
|
544
|
-
useDeviceCategory
|
|
545
|
-
useNewPalette
|
|
534
|
+
useDeviceCategory
|
|
546
535
|
}
|