@ledvance/group-ui-biz-bundle 1.0.0 → 1.0.1

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 CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "@ledvance/group-ui-biz-bundle",
5
5
  "pid": [],
6
6
  "uiid": "",
7
- "version": "1.0.0",
7
+ "version": "1.0.1",
8
8
  "scripts": {},
9
9
  "dependencies": {
10
10
  "@ledvance/base": "^1.x",
@@ -47,7 +47,6 @@ const DynamicMoodEditorPage = () => {
47
47
  sceneMode: moduleParams.isStringLight ? stringLightSceneMode : moduleParams.isStripLight ? stripLightSceneMode : lightSceneMode
48
48
  })
49
49
 
50
- const canDelete = useMemo(() => (role === 0 || role === 2), [role])
51
50
  useEffect(() => {
52
51
  state.headline = Strings.getLang(params.mode ? 'add_new_dynamic_mood_headline_text' : 'edit_static_mood_headline_text')
53
52
  }, [params.mode])
@@ -423,7 +422,7 @@ const DynamicMoodEditorPage = () => {
423
422
  state.mood.fanSpeed = fanSpeed
424
423
  }}
425
424
  style={styles.fanAdjustCard} />}
426
- {params.mode === 'edit' && canDelete &&
425
+ {params.mode === 'edit' &&
427
426
  <View style={{ marginTop: cx(20), marginHorizontal: cx(24) }}>
428
427
  <TextButton
429
428
  style={styles.deleteBtn}
@@ -85,6 +85,7 @@ const MoodPage = () => {
85
85
  isSupportUVC: params.isSupportUVC
86
86
  }).then(res => {
87
87
  if (res.success && res.data) {
88
+ console.log(res.data, '< --- res.datatata')
88
89
  setMoods(res.data)
89
90
  // @ts-ignore
90
91
  state.scenes = cloneDeep(res.data)
@@ -93,11 +94,11 @@ const MoodPage = () => {
93
94
  }
94
95
  }, [])
95
96
 
96
- const checkedMood = (currentMood?: SceneUIState): SceneUIState | undefined=>{
97
- if(currentMood){
97
+ const checkedMood = (currentMood?: SceneUIState): SceneUIState | undefined => {
98
+ if (currentMood) {
98
99
  return {
99
100
  ...currentMood,
100
- nodes: currentMood.nodes.map(node =>({
101
+ nodes: currentMood.nodes.map(node => ({
101
102
  ...node,
102
103
  h: node.h,
103
104
  s: node.isColorNode ? node.s : 50,
@@ -126,15 +127,15 @@ const MoodPage = () => {
126
127
  const checkedMood = {
127
128
  ...currentMood,
128
129
  nodes: currentMood.nodes.map(node => {
129
- if(mode !== 'del'){
130
- if(node.isColorNode){
130
+ if (mode !== 'del') {
131
+ if (node.isColorNode) {
131
132
  node.brightness = 0
132
133
  node.colorTemp = 0
133
- }else{
134
+ } else {
134
135
  node.h = 0
135
136
  node.s = 0
136
137
  node.v = 0
137
- if(!params.isSupportTemperature){
138
+ if (!params.isSupportTemperature) {
138
139
  node.colorTemp = 100 // 适配dim灯
139
140
  }
140
141
  }
@@ -190,23 +191,6 @@ const MoodPage = () => {
190
191
  state.showAddMoodPopover = false
191
192
  }, [state.scenes])
192
193
 
193
- const getCustomList = (isFantasyScene: boolean) =>{
194
- const customList = [
195
- {
196
- text: Strings.getLang('mood_overview_add_mood_text'),
197
- value: true,
198
- },
199
- {
200
- text: Strings.getLang('mood_overview_add_mood_text2'),
201
- value: false,
202
- },
203
- ]
204
- if(isFantasyScene){
205
- return customList.filter(c => !c.value)
206
- }
207
- return customList
208
- }
209
-
210
194
  useEffect(() => {
211
195
  state.filteredMoods = state.scenes.filter(item => {
212
196
  return (state.staticTagChecked && state.dynamicTagChecked) ||
@@ -218,7 +202,8 @@ const MoodPage = () => {
218
202
 
219
203
  const gradientMode = useMemo(() => (
220
204
  params.isStringLight ? SceneMode.StringGradient : params.isStripLight ? SceneMode.StripGradient : SceneMode.SourceGradient
221
- ), [params.isStringLight, params.isStripLight, SceneMode])
205
+ ), [params.isStringLight, params.isStripLight, SceneMode])
206
+
222
207
  return (
223
208
  <>
224
209
  <Page
@@ -226,7 +211,11 @@ const MoodPage = () => {
226
211
  headlineText={Strings.getLang('mood_overview_headline_text')}
227
212
  headlineIcon={state.scenes.length < MAX_MOOD_COUNT ? res.add : undefined}
228
213
  onHeadlineIconClick={() => {
229
- state.showAddMoodPopover = !state.showAddMoodPopover
214
+ if (params.isStringLight || params.isStripLight) {
215
+ onAddMoodDialogItemClick(false, 1)
216
+ } else {
217
+ state.showAddMoodPopover = !state.showAddMoodPopover
218
+ }
230
219
  }}
231
220
  loading={state.loading}>
232
221
  <View style={styles.tagLine}>
@@ -283,15 +272,7 @@ const MoodPage = () => {
283
272
  }}
284
273
  ListHeaderComponent={() => (<Spacer height={cx(10)} />)}
285
274
  ItemSeparatorComponent={() => (<Spacer />)}
286
- ListFooterComponent={() => (
287
- <View style={styles.infoLine}>
288
- <Spacer />
289
- <InfoText
290
- icon={res.ic_info}
291
- text={Strings.getLang('mood_overview_information_text')} />
292
- <Spacer height={cx(40)} />
293
- </View>
294
- )}
275
+ ListFooterComponent={() => (<Spacer />)}
295
276
  keyExtractor={item => `${item.id}`} />
296
277
  </Page>
297
278
  <CustomListDialog
@@ -301,7 +282,16 @@ const MoodPage = () => {
301
282
  onDismiss={() => {
302
283
  state.showAddMoodPopover = false
303
284
  }}
304
- data={getCustomList(!!(params.isStringLight || params.isStripLight))}
285
+ data={[
286
+ {
287
+ text: Strings.getLang('mood_overview_add_mood_text'),
288
+ value: true,
289
+ },
290
+ {
291
+ text: Strings.getLang('mood_overview_add_mood_text2'),
292
+ value: false,
293
+ },
294
+ ]}
305
295
  onItemPress={onAddMoodDialogItemClick} />
306
296
  </>
307
297
  )
@@ -51,7 +51,7 @@ const StaticMoodEditorPage = () => {
51
51
  currentNode: params.currentMood.nodes[0],
52
52
  loading: false
53
53
  })
54
- const canDelete = useMemo(() => (role === 0 || role === 2), [role])
54
+
55
55
  useEffect(() => {
56
56
  state.headline = I18n.getLang(params.mode === 'add' ? 'add_new_static_mood_headline_text' : 'edit_static_mood_headline_text')
57
57
  }, [params.mode])
@@ -180,7 +180,7 @@ const StaticMoodEditorPage = () => {
180
180
  state.mood.fanSpeed = fanSpeed
181
181
  }}
182
182
  style={styles.fanAdjustCard} />}
183
- {params.mode === 'edit' && canDelete &&
183
+ {params.mode === 'edit' &&
184
184
  <View style={{ marginTop: cx(20), marginHorizontal: cx(24) }}>
185
185
  <TextButton
186
186
  style={styles.deleteBtn}
@@ -82,4 +82,9 @@ export interface IModDeleteTaskByIds {
82
82
  bizType?: string;
83
83
  ids: string;
84
84
  status?: number;
85
+ }
86
+
87
+ export enum UVCFanMode {
88
+ Nature = 'nature',
89
+ Normal = 'normal'
85
90
  }
@@ -2,8 +2,9 @@ import React from "react";
2
2
  import { ViewStyle, View, Text, StyleSheet } from "react-native";
3
3
  import Card from "@ledvance/base/src/components/Card";
4
4
  import { SwitchButton, Utils } from 'tuya-panel-kit';
5
- import { loopText } from '@ledvance/base/src/utils/common';
5
+ import { convertTo12HourFormat, loopText } from '@ledvance/base/src/utils/common';
6
6
  import { Timer } from "./Interface";
7
+ import { useSystemTimeFormate } from "@ledvance/base/src/models/modules/NativePropsSlice";
7
8
  const { convertX: cx } = Utils.RatioUtils;
8
9
 
9
10
  interface ScheduleCardProps {
@@ -16,6 +17,7 @@ interface ScheduleCardProps {
16
17
 
17
18
  const ScheduleCard = (props: ScheduleCardProps) => {
18
19
  const { item, style, onEnableChange, onPress } = props;
20
+ const is24HourClock = useSystemTimeFormate()
19
21
  return (
20
22
  <Card
21
23
  style={styles.card}
@@ -28,7 +30,7 @@ const ScheduleCard = (props: ScheduleCardProps) => {
28
30
  // onLongPress(item);
29
31
  }}>
30
32
  <View style={styles.infoContainer}>
31
- <Text style={styles.time}>{item.time}</Text>
33
+ <Text style={styles.time}>{is24HourClock ? item.time : convertTo12HourFormat(item.time)}</Text>
32
34
  <Text style={styles.loop}>
33
35
  {loopText(item.loops.split('').map(loop => parseInt(loop)), item.time)}
34
36
  </Text>
@@ -1,10 +1,10 @@
1
1
  import { commonApi } from "@tuya/tuya-panel-api"
2
- import { IAddSingleTime, IQueryTimerTasks, IModifySingleTimer, IModDeleteTaskByIds } from "./Interface"
2
+ import { IAddSingleTime, IQueryTimerTasks, IModifySingleTimer, IModDeleteTaskByIds, UVCFanMode } from "./Interface"
3
3
  import { flatMapDeep } from "lodash";
4
-
4
+ import I18n from "@ledvance/base/src/i18n";
5
5
 
6
6
  export const addTimeSchedule = async (props: IAddSingleTime) => {
7
- try{
7
+ try {
8
8
  const res = await commonApi.timerApi.addSingleTimer({
9
9
  ...props,
10
10
  bizType: '1'
@@ -17,7 +17,7 @@ export const addTimeSchedule = async (props: IAddSingleTime) => {
17
17
  return {
18
18
  success: false
19
19
  }
20
- }catch(err){
20
+ } catch (err) {
21
21
  return {
22
22
  success: false
23
23
  }
@@ -25,7 +25,7 @@ export const addTimeSchedule = async (props: IAddSingleTime) => {
25
25
  }
26
26
 
27
27
  export const getTimeSchedule = async (props: IQueryTimerTasks) => {
28
- try{
28
+ try {
29
29
  const res = await commonApi.timerApi.queryTimerTasks({
30
30
  ...props,
31
31
  bizType: '1',
@@ -40,7 +40,7 @@ export const getTimeSchedule = async (props: IQueryTimerTasks) => {
40
40
  return {
41
41
  success: false
42
42
  }
43
- }catch(err){
43
+ } catch (err) {
44
44
  return {
45
45
  success: false
46
46
  }
@@ -48,7 +48,7 @@ export const getTimeSchedule = async (props: IQueryTimerTasks) => {
48
48
  }
49
49
 
50
50
  export const modifyTimeSchedule = async (props: IModifySingleTimer) => {
51
- try{
51
+ try {
52
52
  const status = await commonApi.timerApi.modifySingleTimer({
53
53
  ...props,
54
54
  bizType: '1',
@@ -56,15 +56,15 @@ export const modifyTimeSchedule = async (props: IModifySingleTimer) => {
56
56
  return {
57
57
  success: status
58
58
  }
59
- }catch(err){
59
+ } catch (err) {
60
60
  return {
61
61
  success: false
62
62
  }
63
63
  }
64
64
  }
65
65
 
66
- export const modDelTimeSchedule = async (props: IModDeleteTaskByIds) =>{
67
- try{
66
+ export const modDelTimeSchedule = async (props: IModDeleteTaskByIds) => {
67
+ try {
68
68
  const status = await commonApi.timerApi.modDeleteTaskByIds({
69
69
  ...props,
70
70
  bizType: '1',
@@ -73,9 +73,20 @@ export const modDelTimeSchedule = async (props: IModDeleteTaskByIds) =>{
73
73
  return {
74
74
  success: status
75
75
  }
76
- }catch(err){
76
+ } catch (err) {
77
77
  return {
78
78
  success: false
79
79
  }
80
80
  }
81
- }
81
+ }
82
+
83
+ export const fanModeOption = [
84
+ {
85
+ label: I18n.getLang('ceiling_fan_mode_info_option_1_headline'),
86
+ value: UVCFanMode.Normal,
87
+ },
88
+ {
89
+ label: I18n.getLang('ceiling_fan_mode_info_option_2_headline'),
90
+ value: UVCFanMode.Nature,
91
+ },
92
+ ]
@@ -9,14 +9,14 @@ import { useCreation, useReactive } from "ahooks";
9
9
  import { SwitchButton, TimerPicker, Utils } from "tuya-panel-kit";
10
10
  import Spacer from "@ledvance/base/src/components/Spacer";
11
11
  import LdvWeekView from '@ledvance/base/src/components/weekSelect'
12
- import { loopText, showDialog } from "@ledvance/base/src/utils/common";
12
+ import { convertTo12HourFormat, loopText, showDialog } from "@ledvance/base/src/utils/common";
13
13
  import Card from "@ledvance/base/src/components/Card";
14
14
  import LdvSwitch from "@ledvance/base/src/components/ldvSwitch";
15
15
  import ApplyForDeviceList from '@ledvance/base/src/components/ApplyForDeviceList'
16
16
  import LampAdjustView from "@ledvance/base/src/components/LampAdjustView";
17
- import { Timer } from './Interface'
17
+ import { Timer, UVCFanMode } from './Interface'
18
18
  import res from "@ledvance/base/src/res";
19
- import { useGroupDevices, useMoods, useUAGroupInfo } from "@ledvance/base/src/models/modules/NativePropsSlice";
19
+ import { useGroupDevices, useMoods, useSystemTimeFormate, useUAGroupInfo } from "@ledvance/base/src/models/modules/NativePropsSlice";
20
20
  import { TimeSchedulePageParams } from "./TimeSchedulePage";
21
21
  import { Result } from "@ledvance/base/src/models/modules/Result";
22
22
  import DeleteButton from "@ledvance/base/src/components/DeleteButton";
@@ -28,8 +28,10 @@ import { dp2Obj, getRemoteSceneList, obj2Dp, stripDp2Obj, stripObj2Dp } from "..
28
28
  import FanAdjustView from "@ledvance/base/src/components/FanAdjustView";
29
29
  import { SceneMode } from "../mood/SceneInfo";
30
30
  import StripAdjustView, { ColorList } from "@ledvance/base/src/components/StripAdjustView"
31
+ import SocketItem from '@ledvance/base/src/components/SocketItem'
31
32
  import { WorkMode } from "@ledvance/base/src/utils/interface";
32
33
  import { Buffer } from 'buffer'
34
+ import { fanModeOption } from "./TimeScheduleActions";
33
35
 
34
36
  const { convertX: cx } = Utils.RatioUtils;
35
37
  const { toFixedString } = Utils.NumberUtils;
@@ -42,16 +44,22 @@ interface TimeScheduleDetailPageParams extends TimeSchedulePageParams {
42
44
  const TimeScheduleDetailPage = () => {
43
45
  const navigation = useNavigation()
44
46
  const uaGroupInfo = useUAGroupInfo()
47
+ const is24HourClock = useSystemTimeFormate()
45
48
  const [groupDevices] = useGroupDevices()
46
49
  const [moods, setMoods] = useMoods()
47
50
  const props = cloneDeep(useRoute().params) as TimeScheduleDetailPageParams
48
51
  const state = useReactive({
49
52
  timeSchedule: props.mode === 'add' ? newTimeSchedule() : cloneDeep(props.timeSchedule),
50
53
  isManual: true, // manual ,mood
51
- isColorMode: true,
54
+ isColorMode: !!props.colorDataCode,
52
55
  switchLed: true, // light
53
- switchSocket: true,
56
+ switchSocket1: true,
57
+ switchSocket2: true,
58
+ switchSocket3: true,
59
+ switchSocketUSB: true,
54
60
  switchFan: true,
61
+ fanMode: UVCFanMode.Normal,
62
+ fanSpeed: 1,
55
63
  brightness: 100,
56
64
  temperature: 0,
57
65
  hsv: defaultHsv(),
@@ -76,6 +84,10 @@ const TimeScheduleDetailPage = () => {
76
84
  return tabs
77
85
  }, [])
78
86
 
87
+ const isPowerStrip = useMemo(() => {
88
+ return !!(props.switchSocket3 || props.switchSocketUSB)
89
+ }, [])
90
+
79
91
  const getSceneByDp = (sceneDp: string) => {
80
92
  if (props.sceneDataDp2Obj) {
81
93
  return props.sceneDataDp2Obj(sceneDp)
@@ -122,30 +134,59 @@ const TimeScheduleDetailPage = () => {
122
134
  if (props.switchLedCode && dps.hasOwnProperty(props.switchLedCode)) {
123
135
  state.switchLed = dps[props.switchLedCode]
124
136
  }
137
+ if (props.switchSocket1 && dps.hasOwnProperty(props.switchSocket1)) {
138
+ state.switchSocket1 = dps[props.switchSocket1]
139
+ }
140
+ if (props.switchSocket2 && dps.hasOwnProperty(props.switchSocket2)) {
141
+ state.switchSocket2 = dps[props.switchSocket2]
142
+ }
143
+ if (props.switchSocket3 && dps.hasOwnProperty(props.switchSocket3)) {
144
+ state.switchSocket3 = dps[props.switchSocket3]
145
+ }
146
+ if (props.switchSocketUSB && dps.hasOwnProperty(props.switchSocketUSB)) {
147
+ state.switchSocketUSB = dps[props.switchSocketUSB]
148
+ }
149
+ if (props.switchFan && dps.hasOwnProperty(props.switchFan)) {
150
+ state.switchFan = dps[props.switchFan]
151
+ }
152
+ if (props.fanModeCode && dps.hasOwnProperty(props.fanModeCode)) {
153
+ state.fanMode = dps[props.fanModeCode]
154
+ }
155
+ if (props.fanSpeedCode && dps.hasOwnProperty(props.fanSpeedCode)) {
156
+ state.fanSpeed = dps[props.fanSpeedCode]
157
+ }
125
158
  if (props.tempValueCode && dps.hasOwnProperty(props.tempValueCode)) {
126
- state.temperature = Math.round(dps[props.tempValueCode] / 10)
159
+ if (props.tempValueParser) {
160
+ state.temperature = props.tempValueParser(dps[props.tempValueCode])
161
+ } else {
162
+ state.temperature = Math.round(dps[props.tempValueCode] / 10)
163
+ }
127
164
  state.isColorMode = false
128
165
  }
129
166
  if (props.brightValueCode && dps.hasOwnProperty(props.brightValueCode)) {
130
- state.brightness = Math.round(dps[props.brightValueCode] / 10)
167
+ if (props.brightValueParser) {
168
+ state.brightness = props.brightValueParser(dps[props.brightValueCode])
169
+ } else {
170
+ state.brightness = Math.round(dps[props.brightValueCode] / 10)
171
+ }
131
172
  state.isColorMode = false
132
173
  }
133
174
  if (props.colorDataCode && dps.hasOwnProperty(props.colorDataCode)) {
134
175
  if (props.colorDataDp2Obj) {
135
176
  const color = props.colorDataDp2Obj(dps[props.colorDataCode])
177
+ state.hsv = cloneDeep(color)
178
+ if(props.isMatterLight && props.brightValueCode && dps.hasOwnProperty(props.brightValueCode) && props.brightValueParser){
179
+ state.hsv.v = props.brightValueParser(dps[props.brightValueCode])
180
+ }
181
+ } else {
182
+ const hsv = getHSVByHex(dps[props.colorDataCode])
136
183
  state.hsv = {
137
- h: color.h,
138
- s: Math.round(color.s / 10),
139
- v: Math.round(color.v / 10),
184
+ h: hsv.h,
185
+ s: Math.round(hsv.s / 10),
186
+ v: Math.round(hsv.v / 10),
140
187
  }
141
- return
142
- }
143
- const hsv = getHSVByHex(dps[props.colorDataCode])
144
- state.hsv = {
145
- h: hsv.h,
146
- s: Math.round(hsv.s / 10),
147
- v: Math.round(hsv.v / 10),
148
188
  }
189
+ state.isColorMode = true
149
190
  }
150
191
  if (props.sceneDataCode && dps.hasOwnProperty(props.sceneDataCode)) {
151
192
  if (dps[props.sceneDataCode]) {
@@ -196,8 +237,8 @@ const TimeScheduleDetailPage = () => {
196
237
  off.push(I18n.getLang('light_sources_tile_tw_lighting_headline'))
197
238
  }
198
239
  }
199
- if (props.switchSocket) {
200
- if (state.switchSocket) {
240
+ if (props.switchSocket1) {
241
+ if (state.switchSocket1) {
201
242
  on.push(I18n.getLang('feature_summary_action_component_5'))
202
243
  } else {
203
244
  off.push(I18n.getLang('feature_summary_action_component_5'))
@@ -213,7 +254,7 @@ const TimeScheduleDetailPage = () => {
213
254
  return {
214
255
  on, off
215
256
  }
216
- }, [state.switchLed, state.switchSocket, state.switchFan])
257
+ }, [state.switchLed, state.switchSocket1, state.switchFan])
217
258
 
218
259
  const getActions = useCallback(() => {
219
260
  const actions = {
@@ -231,7 +272,7 @@ const TimeScheduleDetailPage = () => {
231
272
  isColor: state.isColorMode
232
273
  })
233
274
  const whiteMode = props.isStringLight ? !state.isColorMode : state.stripState.activeKey === 0
234
- actions.dps[props.workModeCode] = whiteMode ? WorkMode.White : WorkMode.Colour
275
+ if (props.workModeCode) actions.dps[props.workModeCode] = whiteMode ? WorkMode.White : WorkMode.Colour
235
276
 
236
277
  } else if (state.isColorMode) {
237
278
  if (props.colorDataCode) {
@@ -242,25 +283,57 @@ const TimeScheduleDetailPage = () => {
242
283
  }
243
284
  if (props.colorDataObj2Dp) {
244
285
  actions.dps[props.colorDataCode] = props.colorDataObj2Dp(hsv)
286
+ if(props.isMatterLight && props.brightValueCode && props.brightValueFormatter) {
287
+ actions.dps[props.brightValueCode] = props.brightValueFormatter(state.hsv.v)
288
+ }
245
289
  } else {
246
290
  const hex = getHexByHSV(hsv)
247
291
  actions.dps[props.colorDataCode] = hex
248
292
  }
249
293
  }
250
- actions.dps[props.workModeCode] = WorkMode.Colour
294
+ if (props.workModeCode) actions.dps[props.workModeCode] = WorkMode.Colour
251
295
  } else {
252
296
  if (props.brightValueCode) {
253
- actions.dps[props.brightValueCode] = state.brightness * 10
297
+ if (props.brightValueFormatter) {
298
+ actions.dps[props.brightValueCode] = props.brightValueFormatter(state.brightness)
299
+ } else {
300
+ actions.dps[props.brightValueCode] = state.brightness * 10
301
+ }
254
302
  }
255
303
  if (props.tempValueCode) {
256
- actions.dps[props.tempValueCode] = state.temperature * 10
304
+ if (props.tempValueFormatter) {
305
+ actions.dps[props.tempValueCode] = props.tempValueFormatter(state.temperature)
306
+ } else {
307
+ actions.dps[props.tempValueCode] = state.temperature * 10
308
+ }
257
309
  }
258
- actions.dps[props.workModeCode] = WorkMode.White
310
+ if (props.workModeCode) actions.dps[props.workModeCode] = WorkMode.White
259
311
  }
260
312
  }
261
313
  if (props.switchLedCode) {
262
314
  actions.dps[props.switchLedCode] = state.switchLed
263
315
  }
316
+ if (props.switchSocket1) {
317
+ actions.dps[props.switchSocket1] = state.switchSocket1
318
+ }
319
+ if (props.switchSocket2) {
320
+ actions.dps[props.switchSocket2] = state.switchSocket2
321
+ }
322
+ if (props.switchSocket3) {
323
+ actions.dps[props.switchSocket3] = state.switchSocket3
324
+ }
325
+ if (props.switchSocketUSB) {
326
+ actions.dps[props.switchSocketUSB] = state.switchSocketUSB
327
+ }
328
+ if (props.switchFan) {
329
+ actions.dps[props.switchFan] = state.switchFan
330
+ if (props.fanModeCode && state.switchFan) {
331
+ actions.dps[props.fanModeCode] = state.fanMode
332
+ }
333
+ if (props.fanSpeedCode && state.switchFan) {
334
+ actions.dps[props.fanSpeedCode] = state.fanSpeed
335
+ }
336
+ }
264
337
  } else {
265
338
  if (props.sceneDataCode) {
266
339
  actions.dps[props.sceneDataCode] = state.scene
@@ -273,7 +346,7 @@ const TimeScheduleDetailPage = () => {
273
346
  console.log(state, '< --- state')
274
347
  console.log(actions, '< --- actions')
275
348
  return JSON.stringify(actions)
276
- }, [state.timeSchedule.time, state.switchLed, state.brightness, state.temperature])
349
+ }, [JSON.stringify(state)])
277
350
 
278
351
  const isModify = useMemo(() => {
279
352
  const schedule = props.mode === 'add' ? newTimeSchedule() : props.timeSchedule
@@ -319,8 +392,6 @@ const TimeScheduleDetailPage = () => {
319
392
  headlineText={I18n.getLang(props.mode === 'add' ? 'motion_detection_add_time_schedule_headline_text' : 'edit_timeschedule_headline_text')}
320
393
  rightButtonIcon={allowSubmit ? res.ic_check : res.ic_uncheck}
321
394
  rightButtonIconClick={async () => {
322
- getActions()
323
- return
324
395
  if (!allowSubmit || state.loading) return
325
396
  state.loading = true
326
397
  const res = await props.modDeleteTimeSchedule(props.mode, {
@@ -357,8 +428,10 @@ const TimeScheduleDetailPage = () => {
357
428
  <TimerPicker
358
429
  itemTextColor='#aeadb5'
359
430
  style={{ paddingVertical: cx(0), marginVertical: cx(0) }}
360
- is12Hours={false}
431
+ is12Hours={!is24HourClock}
361
432
  singlePicker={true}
433
+ amText={I18n.getLang('manage_user_calendar_label_am')}
434
+ pmText={I18n.getLang('manage_user_calendar_label_pm')}
362
435
  startTime={getFormateTime(state.timeSchedule.time) as number}
363
436
  symbol={''}
364
437
  onTimerChange={(startTime) => {
@@ -389,99 +462,185 @@ const TimeScheduleDetailPage = () => {
389
462
  <Spacer height={cx(10)} />
390
463
  {state.isManual ?
391
464
  <>
392
- {!!props.switchLedCode && <Card
393
- style={styles.cardContainer}
394
- >
395
- <LdvSwitch
396
- title={I18n.getLang('light_sources_tile_tw_lighting_headline')}
397
- color={'#fff'}
398
- colorAlpha={1}
399
- enable={state.switchLed}
400
- setEnable={(enable: boolean) => {
401
- state.switchLed = enable
402
- }}
403
- />
404
- {state.switchLed && (props.isStripLight ?
405
- <StripAdjustView
406
- lampTabs={tabList}
407
- onColorDiskChange={(color, idx: K) => {
408
- state.stripState = {
409
- ...state.stripState,
410
- colors: color,
411
- colorDiskActiveKey: idx
412
- }
413
- }}
414
- colorDiskActiveKey={state.stripState.colorDiskActiveKey}
415
- activeKey={state.stripState.activeKey}
416
- onActiveKeyChange={(v) => {
417
- state.stripState = {
418
- ...state.stripState,
419
- activeKey: Number(v) as K
420
- }
465
+ {!!props.switchLedCode && <>
466
+ <Card
467
+ style={styles.cardContainer}
468
+ >
469
+ <LdvSwitch
470
+ title={I18n.getLang('light_sources_tile_tw_lighting_headline')}
471
+ color={'#fff'}
472
+ colorAlpha={1}
473
+ enable={state.switchLed}
474
+ setEnable={(enable: boolean) => {
475
+ state.switchLed = enable
421
476
  }}
422
- isSupportTemperature={props.isSupportTemperature}
423
- isSupportBrightness={props.isSupportBrightness}
424
- h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
425
- onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
426
- onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
427
- colorTemp={state.temperature}
428
- brightness={state.brightness}
429
- onCCTChange={() => { }}
430
- onCCTChangeComplete={(cct) => { state.temperature = cct }}
431
- onBrightnessChange={() => { }}
432
- onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
433
- /> :
434
- <LampAdjustView
435
- reserveSV={true}
436
- isSupportBrightness={props.isSupportBrightness}
437
- isSupportColor={props.isSupportColor}
438
- isSupportTemperature={props.isSupportTemperature}
439
- isColorMode={state.isColorMode}
440
- setIsColorMode={(v) => { state.isColorMode = v }}
441
- h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
442
- colorTemp={state.temperature}
443
- brightness={state.brightness}
444
- onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
445
- onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
446
- onCCTChangeComplete={(cct) => { state.temperature = cct }}
447
- onCCTChange={(cct) => { state.temperature = cct }}
448
- onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
449
- onBrightnessChange={(bright) => { state.brightness = bright }}
450
- />)}
451
- <ApplyForDeviceList
452
- devices={cloneDeep(groupDevices)}
453
- />
454
- <Spacer height={cx(16)} />
455
- </Card>}
477
+ />
478
+ {state.switchLed && (props.isStripLight ?
479
+ <StripAdjustView
480
+ lampTabs={tabList}
481
+ onColorDiskChange={(color, idx: K) => {
482
+ state.stripState = {
483
+ ...state.stripState,
484
+ colors: color,
485
+ colorDiskActiveKey: idx
486
+ }
487
+ }}
488
+ colorDiskActiveKey={state.stripState.colorDiskActiveKey}
489
+ activeKey={state.stripState.activeKey}
490
+ onActiveKeyChange={(v) => {
491
+ state.stripState = {
492
+ ...state.stripState,
493
+ activeKey: Number(v) as K
494
+ }
495
+ }}
496
+ isSupportTemperature={props.isSupportTemperature}
497
+ isSupportBrightness={props.isSupportBrightness}
498
+ h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
499
+ onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
500
+ onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
501
+ colorTemp={state.temperature}
502
+ brightness={state.brightness}
503
+ onCCTChange={() => { }}
504
+ onCCTChangeComplete={(cct) => { state.temperature = cct }}
505
+ onBrightnessChange={() => { }}
506
+ onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
507
+ /> :
508
+ <LampAdjustView
509
+ reserveSV={true}
510
+ isSupportBrightness={props.isSupportBrightness}
511
+ isSupportColor={props.isSupportColor}
512
+ isSupportTemperature={props.isSupportTemperature}
513
+ isColorMode={state.isColorMode}
514
+ setIsColorMode={(v) => { state.isColorMode = v }}
515
+ h={state.hsv.h} s={state.hsv.s} v={state.hsv.v}
516
+ colorTemp={state.temperature}
517
+ brightness={state.brightness}
518
+ onHSVChangeComplete={(h, s, v) => { state.hsv = { h, s, v } }}
519
+ onHSVChange={(h, s, v) => { state.hsv = { h, s, v } }}
520
+ onCCTChangeComplete={(cct) => { state.temperature = cct }}
521
+ onCCTChange={(cct) => { state.temperature = cct }}
522
+ onBrightnessChangeComplete={(bright) => { state.brightness = bright }}
523
+ onBrightnessChange={(bright) => { state.brightness = bright }}
524
+ />)}
525
+ <ApplyForDeviceList
526
+ devices={cloneDeep(groupDevices)}
527
+ />
528
+ <Spacer height={cx(16)} />
529
+ </Card>
530
+ <Spacer />
531
+ </>}
456
532
 
457
533
  {/* socket */}
458
- {!!props.switchSocket && <Card
459
- style={styles.cardContainer}
460
- >
461
- <LdvSwitch
462
- title={I18n.getLang('feature_summary_action_component_5')}
463
- color={'#fff'}
464
- colorAlpha={1}
465
- enable={state.switchSocket}
466
- setEnable={(enable: boolean) => {
467
- state.switchSocket = enable
534
+ {!!props.switchSocket1 && <>
535
+ {isPowerStrip ?
536
+ <SocketItem
537
+ title={I18n.getLang('feature_summary_action_component_6')}
538
+ name=""
539
+ icon={{ uri: res.switch_1 }}
540
+ onNameChange={() => { }}
541
+ enabled={state.switchSocket1}
542
+ disabledEdit={true}
543
+ onSwitchChange={enable => {
544
+ state.switchSocket1 = enable
545
+ }}
546
+ >
547
+ <ApplyForDeviceList
548
+ devices={cloneDeep(groupDevices)}
549
+ />
550
+ <Spacer height={cx(16)} />
551
+ </SocketItem> :
552
+ <Card
553
+ style={styles.cardContainer}
554
+ >
555
+ <LdvSwitch
556
+ title={I18n.getLang('feature_summary_action_component_5')}
557
+ color={'#fff'}
558
+ colorAlpha={1}
559
+ enable={state.switchSocket1}
560
+ setEnable={(enable: boolean) => {
561
+ state.switchSocket1 = enable
562
+ }}
563
+ />
564
+ <ApplyForDeviceList
565
+ devices={cloneDeep(groupDevices)}
566
+ />
567
+ <Spacer height={cx(16)} />
568
+ </Card>
569
+ }
570
+ <Spacer />
571
+ </>}
572
+ {!!props.switchSocket2 && <>
573
+ <SocketItem
574
+ title={I18n.getLang('feature_summary_action_component_7')}
575
+ name=""
576
+ icon={{ uri: res.switch_2 }}
577
+ onNameChange={() => { }}
578
+ enabled={state.switchSocket2}
579
+ disabledEdit={true}
580
+ onSwitchChange={enable => {
581
+ state.switchSocket2 = enable
468
582
  }}
469
- />
470
- <ApplyForDeviceList
471
- devices={cloneDeep(groupDevices)}
472
- />
473
- <Spacer height={cx(16)} />
474
- </Card>}
583
+ >
584
+ <ApplyForDeviceList
585
+ devices={cloneDeep(groupDevices)}
586
+ />
587
+ <Spacer height={cx(16)} />
588
+ </SocketItem>
589
+ <Spacer />
590
+ </>}
591
+ {!!props.switchSocket3 && <>
592
+ <SocketItem
593
+ title={I18n.getLang('feature_summary_action_component_8')}
594
+ name=""
595
+ icon={{ uri: res.switch_3 }}
596
+ onNameChange={() => { }}
597
+ enabled={state.switchSocket3}
598
+ disabledEdit={true}
599
+ onSwitchChange={enable => {
600
+ state.switchSocket3 = enable
601
+ }}
602
+ >
603
+ <ApplyForDeviceList
604
+ devices={cloneDeep(groupDevices)}
605
+ />
606
+ <Spacer height={cx(16)} />
607
+ </SocketItem>
608
+ <Spacer />
609
+ </>}
610
+ {!!props.switchSocketUSB && <>
611
+ <SocketItem
612
+ title={I18n.getLang('feature_summary_action_component_9')}
613
+ name=""
614
+ icon={{ uri: res.switch_4 }}
615
+ onNameChange={() => { }}
616
+ enabled={state.switchSocketUSB}
617
+ disabledEdit={true}
618
+ onSwitchChange={enable => {
619
+ state.switchSocketUSB = enable
620
+ }}
621
+ >
622
+ <ApplyForDeviceList
623
+ devices={cloneDeep(groupDevices)}
624
+ />
625
+ <Spacer height={cx(16)} />
626
+ </SocketItem>
627
+ <Spacer />
628
+ </>}
475
629
 
476
630
  {/* Fan */}
477
631
  {props.isSupportFan && <FanAdjustView
632
+ style={styles.cardContainer}
478
633
  fanEnable={state.switchFan}
479
- fanSpeed={1}
480
- onFanSpeedChangeComplete={() => { }}
634
+ fanSpeed={state.fanSpeed}
635
+ modeValue={state.fanMode}
636
+ modeOptions={fanModeOption}
637
+ modeChange={(v: any) => state.fanMode = v}
638
+ maxFanSpeed={props.isSupportUVC ? 20 : 3}
639
+ onFanSpeedChangeComplete={(v) => state.fanSpeed = v}
481
640
  onFanSwitch={(enable) => {
482
641
  state.switchFan = enable
483
642
  }}
484
- isSupportMode={true}
643
+ isSupportMode={props.isSupportUVC}
485
644
  />}
486
645
  </> :
487
646
  <FlatList
@@ -507,7 +666,7 @@ const TimeScheduleDetailPage = () => {
507
666
  </View>)}
508
667
  keyExtractor={item => `${item.id}`} />
509
668
  }
510
- <Spacer height={cx(30)} />
669
+ <Spacer height={cx(20)} />
511
670
  <Text style={[styles.itemTitle, styles.cardContainer]}>{I18n.getLang('timeschedule_add_schedule_subheadline4_text')}</Text>
512
671
  <View style={[styles.switchButton, styles.cardContainer]}>
513
672
  <Text style={styles.text}>{I18n.getLang('timeschedule_add_schedule_text2')}</Text>
@@ -543,7 +702,7 @@ const TimeScheduleDetailPage = () => {
543
702
  style={styles.summaryLeft}
544
703
  />
545
704
  <View style={styles.summaryRight}>
546
- <Text style={styles.rightItem}>{state.timeSchedule.time}</Text>
705
+ <Text style={styles.rightItem}>{is24HourClock ? state.timeSchedule.time : convertTo12HourFormat(state.timeSchedule.time)}</Text>
547
706
  </View>
548
707
  </View>
549
708
  <View style={[styles.summaryContainer, { alignItems: 'flex-start' }]}>
@@ -42,14 +42,24 @@ export interface TimeSchedulePageParams {
42
42
  isSupportMood?: boolean
43
43
  isStringLight?: boolean
44
44
  isStripLight?: boolean
45
+ isMatterLight?: boolean
45
46
  isSupportFan?: boolean
46
47
  isSupportUVC?: boolean
47
48
  switchLedCode?: string
48
- switchSocket?: string
49
+ switchSocket1?: string
50
+ switchSocket2?: string
51
+ switchSocket3?: string
52
+ switchSocketUSB?: string
49
53
  switchFan?: string
54
+ fanModeCode?: string
55
+ fanSpeedCode?: string
50
56
  workModeCode: string
51
57
  brightValueCode?: string
58
+ brightValueFormatter?: (bright: number) => number
59
+ brightValueParser?: (bright: number) => number
52
60
  tempValueCode?: string
61
+ tempValueFormatter?: (temp: number) => number
62
+ tempValueParser?: (temp: number) => number
53
63
  sceneDataCode?: string
54
64
  sceneDataDp2Obj?: (sceneDp: string) => SceneInfo
55
65
  sceneDataObj2Dp?: (scene: any) => string
@@ -2,8 +2,7 @@ import { useFeatureHook } from '@ledvance/base/src/models/modules/NativePropsSli
2
2
  import { Result } from '@ledvance/base/src/models/modules/Result'
3
3
  import dayjs from 'dayjs'
4
4
  import { useCountDown, useReactive } from 'ahooks'
5
- import { useEffect } from 'react'
6
- import { cloneDeep } from 'lodash'
5
+ import { useEffect, useMemo } from 'react'
7
6
 
8
7
  export interface TimerTask {
9
8
  name: string
@@ -29,7 +28,8 @@ export interface TimerConfig {
29
28
  timerTasks: TimerTask[]
30
29
  }
31
30
 
32
- export function useTimerTasks(timerSettableDps: TimerSettableDp[]): [TimerTask[], (value: TimerTask[]) => Promise<Result<any>>] {
31
+ export function useTimerTasks(timerSettableDps: TimerSettableDp[]):
32
+ [TimerTask[], (value: TimerTask[]) => Promise<Result<any>>, (tasks: TimerTask[]) => void] {
33
33
  const countdowns = timerSettableDps.map(dps => {
34
34
  const [countdown, setTargetDate] = useCountDown({ interval: 1000 })
35
35
  return {
@@ -40,18 +40,21 @@ export function useTimerTasks(timerSettableDps: TimerSettableDp[]): [TimerTask[]
40
40
  },
41
41
  }
42
42
  })
43
- const [tasks, setTasks] = useFeatureHook<TimerConfig, TimerTask[]>(
43
+
44
+ const defTasks = useMemo(() => timerSettableDps.map(timerSettableDp => ({
45
+ name: timerSettableDp.label,
46
+ startTime: 0,
47
+ duration: 0,
48
+ timeLeft: 0,
49
+ dp: timerSettableDp.dp,
50
+ status: TaskStatus.NoSelected,
51
+ stringOn: timerSettableDp.stringOn,
52
+ stringOff: timerSettableDp.stringOff,
53
+ })), [JSON.stringify(timerSettableDps)])
54
+
55
+ const [remoteTasks, setTasks] = useFeatureHook<TimerConfig, TimerTask[]>(
44
56
  'timerTasks',
45
- timerSettableDps.map(timerSettableDp => ({
46
- name: timerSettableDp.label,
47
- startTime: 0,
48
- duration: 0,
49
- timeLeft: 0,
50
- dp: timerSettableDp.dp,
51
- status: TaskStatus.NoSelected,
52
- stringOn: timerSettableDp.stringOn,
53
- stringOff: timerSettableDp.stringOff,
54
- })),
57
+ defTasks,
55
58
  () => undefined,
56
59
  timerTasks => {
57
60
  const dps = {}
@@ -62,10 +65,15 @@ export function useTimerTasks(timerSettableDps: TimerSettableDp[]): [TimerTask[]
62
65
  },
63
66
  )
64
67
 
65
- const state = useReactive({ tasks: cloneDeep(tasks) })
68
+ const tasks = defTasks.map(defTask => {
69
+ const findTask = remoteTasks.find(remoteTask => remoteTask.dp.code === defTask.dp.code)
70
+ return findTask ? { ...findTask } : defTask
71
+ })
72
+
73
+ const state = useReactive({ tasks: tasks })
66
74
 
67
75
  useEffect(() => {
68
- state.tasks = cloneDeep(tasks)
76
+ state.tasks = tasks
69
77
  .map(task => {
70
78
  const taskEndTime = dayjs.unix(task.startTime)
71
79
  .add(task.duration, 'second')
@@ -99,17 +107,29 @@ export function useTimerTasks(timerSettableDps: TimerSettableDp[]): [TimerTask[]
99
107
  state.tasks.forEach(task => {
100
108
  if (task.dp.code === cd.dpCode) {
101
109
  task.timeLeft = Math.trunc(cd.countdown.value / 1000)
102
- if (task.timeLeft <= 0) {
103
- task.status = TaskStatus.NoSelected
104
- } else {
110
+ if (task.timeLeft > 0) {
105
111
  task.status = TaskStatus.Started
112
+ } else {
113
+ if (task.status === TaskStatus.Started) {
114
+ task.status = TaskStatus.NoSelected
115
+ }
106
116
  }
107
117
  }
108
118
  })
109
119
  })
110
120
  }, [JSON.stringify(countdowns.map(c => c.countdown.value))])
111
121
 
112
- return [state.tasks, setTasks]
122
+ const changeTasks = (timerTasks: TimerTask[]) => {
123
+ timerTasks.forEach(newTask => {
124
+ state.tasks.forEach(task => {
125
+ if (task.dp.code === newTask.dp.code) {
126
+ task.status = newTask.status
127
+ }
128
+ })
129
+ })
130
+ }
131
+
132
+ return [state.tasks, setTasks, changeTasks]
113
133
  }
114
134
 
115
135
  export function getTaskLeftover(timerTask: TimerTask): number {
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo } from 'react'
1
+ import React, { useEffect } from 'react'
2
2
  import { FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
3
3
  import I18n from '@ledvance/base/src/i18n'
4
4
  import Page from '@ledvance/base/src/components/Page'
@@ -23,7 +23,7 @@ const TimerPage = () => {
23
23
  const devInfo = useDeviceInfo()
24
24
 
25
25
  const params = useParams<TimerPageParams>()
26
- const [timerTasks, setTimerTasks] = useTimerTasks(params.timerSettableDps)
26
+ const [timerTasks, setTimerTasks, changeTimerTasks] = useTimerTasks(params.timerSettableDps)
27
27
 
28
28
  const state = useReactive({
29
29
  hour: '00',
@@ -35,15 +35,13 @@ const TimerPage = () => {
35
35
  useEffect(() => {
36
36
  state.tasks = cloneDeep(timerTasks)
37
37
  .map(task => {
38
- const newStatus = timerTasks.length === 1 && task.status !== TaskStatus.Started
38
+ const newStatus = params.timerSettableDps.length === 1 && task.status !== TaskStatus.Started
39
39
  ? TaskStatus.Selected : task.status
40
40
  return { ...task, status: newStatus }
41
41
  })
42
42
  }, [JSON.stringify(timerTasks)])
43
43
 
44
- const tasksByStatus = useMemo(() => {
45
- return groupBy(state.tasks, 'status')
46
- }, [JSON.stringify(state.tasks)])
44
+ const tasksByStatus = groupBy(state.tasks, 'status')
47
45
 
48
46
  const noSelectedTasks = tasksByStatus[TaskStatus.NoSelected] || []
49
47
  const selectedTasks = tasksByStatus[TaskStatus.Selected] || []
@@ -87,6 +85,7 @@ const TimerPage = () => {
87
85
  <TouchableOpacity
88
86
  onPress={() => {
89
87
  item.status = TaskStatus.NoSelected
88
+ changeTimerTasks([cloneDeep(item)])
90
89
  }}>
91
90
  <Image style={styles.taskItemIcon} source={GroupBizRes.ic_arrows_nav_clear}/>
92
91
  </TouchableOpacity>}
@@ -109,6 +108,7 @@ const TimerPage = () => {
109
108
  style={styles.noSelectTaskItem}
110
109
  onPress={() => {
111
110
  item.status = TaskStatus.Selected
111
+ changeTimerTasks([cloneDeep(item)])
112
112
  }}>
113
113
  <Spacer width={cx(8)}/>
114
114
  <Text style={styles.noSelectTaskText}>{item.name}</Text>
@@ -120,6 +120,7 @@ const TimerPage = () => {
120
120
  <Spacer/>
121
121
  <DeleteButton
122
122
  text={I18n.getLang('timer_sockets_button_text')}
123
+ disabled={selectedTasks.length === 0}
123
124
  onPress={async () => {
124
125
  state.loading = true
125
126
  const tasks = selectedTasks.map(task => {
@@ -130,6 +131,7 @@ const TimerPage = () => {
130
131
  status: TaskStatus.Started,
131
132
  }
132
133
  })
134
+ tasks.push(...cloneDeep(startedTasks))
133
135
  await setTimerTasks(cloneDeep(tasks))
134
136
  state.loading = false
135
137
  }}
@@ -137,7 +139,7 @@ const TimerPage = () => {
137
139
  style={{ backgroundColor: !startEnable ? '#FFE0D4' : '#f60' }}/>
138
140
  </View>
139
141
  }
140
- {startedTasks.length > 0 && state.tasks.length > 1 &&
142
+ {startedTasks.length > 0 && params.timerSettableDps.length > 1 &&
141
143
  <>
142
144
  <Spacer height={cx(30)}/>
143
145
  <View style={styles.content}>
@@ -148,8 +150,18 @@ const TimerPage = () => {
148
150
  <FlatList
149
151
  data={startedTasks}
150
152
  renderItem={({ item }) => {
151
- return ActiveTimerItem(item, () => {
152
- item.status = TaskStatus.NoSelected
153
+ return ActiveTimerItem(item, async () => {
154
+ state.loading = true
155
+ const tasks = cloneDeep(startedTasks)
156
+ tasks.forEach(task => {
157
+ if (task.dp.code === item.dp.code) {
158
+ task.status = TaskStatus.NoSelected
159
+ task.startTime = 0
160
+ task.duration = 0
161
+ }
162
+ })
163
+ await setTimerTasks(tasks)
164
+ state.loading = false
153
165
  })
154
166
  }}
155
167
  keyExtractor={item => item.dp.key}
@@ -159,7 +171,7 @@ const TimerPage = () => {
159
171
  </>
160
172
  }
161
173
  {
162
- startedTasks.length === 1 && state.tasks.length === 1 &&
174
+ startedTasks.length === 1 && params.timerSettableDps.length === 1 &&
163
175
  <View style={{ justifyContent: 'center', marginHorizontal: cx(24) }}>
164
176
  <Spacer height={cx(116)}/>
165
177
  <View
@@ -219,17 +231,17 @@ function ActiveTimerItem(task: TimerTask, onCancel: () => void) {
219
231
  <View style={styles.activeTaskHeadLine}>
220
232
  <Spacer width={cx(20)}/>
221
233
  <CircularProgress
222
- progress={25}
234
+ progress={(task.timeLeft / task.duration) * 100}
223
235
  size={cx(24)}
224
236
  strokeWidth={cx(2)}/>
225
237
  <Spacer width={cx(16)}/>
226
- <Text style={styles.activeTaskTimeText}>{'2h 12 min'}</Text>
238
+ <Text style={styles.activeTaskTimeText}>{I18n.formatValue(task.stringOn, timeFormat(task.timeLeft))}</Text>
227
239
  <Spacer width={cx(20)}/>
228
240
  </View>
229
241
  <Spacer/>
230
242
  <View style={{ marginHorizontal: cx(20) }}>
231
243
  <Text style={styles.activeTaskDesc}>{
232
- I18n.getLang(task.stringOn)
244
+ I18n.formatValue(task.stringOn, timeFormat(task.timeLeft))
233
245
  }</Text>
234
246
  </View>
235
247
  <Spacer height={cx(22)}/>