mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-08-26 07:49:40 +00:00
Implemented 3 gange count down timer
This commit is contained in:
55
assets/icons/pause_ic.svg
Normal file
55
assets/icons/pause_ic.svg
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<svg width="100" height="101" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_d_805_1166)">
|
||||||
|
<g filter="url(#filter1_i_805_1166)">
|
||||||
|
<path d="M80 50C80 33.4315 66.5685 20 50 20C33.4315 20 20 33.4315 20 50C20 66.5685 33.4315 80 50 80C66.5685 80 80 66.5685 80 50Z" fill="#EBECED"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter2_ddi_805_1166)">
|
||||||
|
<path d="M70.2842 50.2842C70.2842 39.2385 61.3299 30.2842 50.2842 30.2842C39.2385 30.2842 30.2842 39.2385 30.2842 50.2842C30.2842 61.3299 39.2385 70.2842 50.2842 70.2842C61.3299 70.2842 70.2842 61.3299 70.2842 50.2842Z" fill="#F9F9F9"/>
|
||||||
|
</g>
|
||||||
|
<rect x="42" y="42" width="16" height="16" rx="2" fill="#023DFE" fill-opacity="0.6"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d_805_1166" x="17" y="17" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="1" dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_805_1166"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_805_1166" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_i_805_1166" x="20" y="20" width="65" height="65" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_805_1166"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_ddi_805_1166" x="-4.71582" y="-4.71582" width="105" height="105" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="12.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_805_1166"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="-5" dy="-5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect1_dropShadow_805_1166" result="effect2_dropShadow_805_1166"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_805_1166" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_805_1166"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
55
assets/icons/play_ic.svg
Normal file
55
assets/icons/play_ic.svg
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<svg width="100" height="105" viewBox="0 0 100 105" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_d_805_1168)">
|
||||||
|
<g filter="url(#filter1_i_805_1168)">
|
||||||
|
<path d="M80 55C80 38.4315 66.5685 25 50 25C33.4315 25 20 38.4315 20 55C20 71.5685 33.4315 85 50 85C66.5685 85 80 71.5685 80 55Z" fill="#EBECED"/>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#filter2_ddi_805_1168)">
|
||||||
|
<path d="M70.2842 55.2842C70.2842 44.2385 61.3299 35.2842 50.2842 35.2842C39.2385 35.2842 30.2842 44.2385 30.2842 55.2842C30.2842 66.3299 39.2385 75.2842 50.2842 75.2842C61.3299 75.2842 70.2842 66.3299 70.2842 55.2842Z" fill="#F9F9F9"/>
|
||||||
|
</g>
|
||||||
|
<path d="M59.5 52.9019C61.5 54.0566 61.5 56.9434 59.5 58.0981L48.25 64.5933C46.25 65.748 43.75 64.3046 43.75 61.9952L43.75 49.0048C43.75 46.6954 46.25 45.252 48.25 46.4067L59.5 52.9019Z" fill="#023DFE" fill-opacity="0.6"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d_805_1168" x="17" y="22" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="1" dy="1"/>
|
||||||
|
<feGaussianBlur stdDeviation="2"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_805_1168"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_805_1168" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter1_i_805_1168" x="20" y="25" width="65" height="65" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_805_1168"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="filter2_ddi_805_1168" x="-4.71582" y="0.28418" width="105" height="105" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="12.5"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_805_1168"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="-5" dy="-5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="out"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
|
||||||
|
<feBlend mode="normal" in2="effect1_dropShadow_805_1168" result="effect2_dropShadow_805_1168"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_805_1168" result="shape"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||||
|
<feOffset dx="5" dy="5"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
|
||||||
|
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_805_1168"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||||
@ -9,6 +11,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
|
|||||||
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||||
final String threeGangId;
|
final String threeGangId;
|
||||||
late ThreeGangModel deviceStatus;
|
late ThreeGangModel deviceStatus;
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
|
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchThreeGangStatus);
|
on<InitialEvent>(_fetchThreeGangStatus);
|
||||||
@ -17,6 +20,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
||||||
on<AllOffEvent>(_allOff);
|
on<AllOffEvent>(_allOff);
|
||||||
on<AllOnEvent>(_allOn);
|
on<AllOnEvent>(_allOn);
|
||||||
|
on<ChangeSlidingSegment>(_changeSliding);
|
||||||
|
on<SetCounterValue>(_setCounterValue);
|
||||||
|
on<GetCounterEvent>(_getCounterValue);
|
||||||
|
on<TickTimer>(_onTickTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||||
@ -121,4 +128,74 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
emit(UpdateState(threeGangModel: deviceStatus));
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
|
||||||
|
emit(ChangeSlidingSegmentState(value: event.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async {
|
||||||
|
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||||
|
try {
|
||||||
|
int seconds = (event.duration.inHours * 60 * 60) + (event.duration.inMinutes * 60);
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds),
|
||||||
|
threeGangId);
|
||||||
|
|
||||||
|
if (response['success'] ?? false) {
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown = seconds;
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown = seconds;
|
||||||
|
} else if (event.deviceCode == 'countdown_3') {
|
||||||
|
deviceStatus.thirdCountDown = seconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(threeGangId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = ThreeGangModel.fromJson(statusModelList);
|
||||||
|
|
||||||
|
if (event.deviceCode == 'countdown_1') {
|
||||||
|
deviceStatus.firstCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.firstCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||||
|
} else if (event.deviceCode == 'countdown_2') {
|
||||||
|
deviceStatus.secondCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.secondCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
|
||||||
|
} else if (event.deviceCode == 'countdown_3') {
|
||||||
|
deviceStatus.thirdCountDown > 0
|
||||||
|
? _onStartTimer(deviceStatus.thirdCountDown)
|
||||||
|
: emit(UpdateTimerState(seconds: deviceStatus.thirdCountDown));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState(error: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onStartTimer(int seconds) {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
add(TickTimer(seconds - timer.tick));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onTickTimer(TickTimer event, Emitter<ThreeGangState> emit) {
|
||||||
|
if (event.remainingTime > 0) {
|
||||||
|
emit(TimerRunInProgress(event.remainingTime));
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(TimerRunComplete());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,3 +35,45 @@ class ChangeThirdSwitchStatusEvent extends ThreeGangEvent {
|
|||||||
class AllOffEvent extends ThreeGangEvent {}
|
class AllOffEvent extends ThreeGangEvent {}
|
||||||
|
|
||||||
class AllOnEvent extends ThreeGangEvent {}
|
class AllOnEvent extends ThreeGangEvent {}
|
||||||
|
|
||||||
|
class ChangeSlidingSegment extends ThreeGangEvent {
|
||||||
|
final int value;
|
||||||
|
const ChangeSlidingSegment({required this.value});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetCounterEvent extends ThreeGangEvent {
|
||||||
|
final String deviceCode;
|
||||||
|
const GetCounterEvent({required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetCounterValue extends ThreeGangEvent {
|
||||||
|
final Duration duration;
|
||||||
|
final String deviceCode;
|
||||||
|
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration, deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartTimer extends ThreeGangEvent {
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
const StartTimer(this.duration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TickTimer extends ThreeGangEvent {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TickTimer(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StopTimer extends ThreeGangEvent {}
|
||||||
|
@ -36,3 +36,31 @@ class FailedState extends ThreeGangState {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [error];
|
List<Object> get props => [error];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ChangeSlidingSegmentState extends ThreeGangState {
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
const ChangeSlidingSegmentState({required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateTimerState extends ThreeGangState {
|
||||||
|
final int seconds;
|
||||||
|
const UpdateTimerState({required this.seconds});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [seconds];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunInProgress extends ThreeGangState {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TimerRunInProgress(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimerRunComplete extends ThreeGangState {}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
|
// import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
// import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
|
// import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
// import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
|
// import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
// import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
@ -0,0 +1,174 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/timer_screen.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class ScheduleScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
const ScheduleScreen({required this.device, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 48,
|
||||||
|
),
|
||||||
|
DefaultContainer(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) => TimerScreen(
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_1',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Bedside Light",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) => TimerScreen(
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_2',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Ceiling Light",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.dividerColor,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) => TimerScreen(
|
||||||
|
device: device,
|
||||||
|
deviceCode: 'countdown_3',
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: "Spotlight",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.textPrimaryColor,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 18,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_sta
|
|||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
|
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/three_gang/schedule_screen.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
@ -228,7 +229,15 @@ class ThreeGangScreen extends StatelessWidget {
|
|||||||
borderRadius: BorderRadius.circular(100),
|
borderRadius: BorderRadius.circular(100),
|
||||||
),
|
),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
ScheduleScreen(
|
||||||
|
device: device,
|
||||||
|
)));
|
||||||
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
159
lib/features/devices/view/widgets/three_gang/timer_screen.dart
Normal file
159
lib/features/devices/view/widgets/three_gang/timer_screen.dart
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class TimerScreen extends StatelessWidget {
|
||||||
|
final DeviceModel device;
|
||||||
|
final String deviceCode;
|
||||||
|
const TimerScreen({required this.device, required this.deviceCode, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnnotatedRegion(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
|
extendBodyBehindAppBar: true,
|
||||||
|
extendBody: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const BodyLarge(
|
||||||
|
text: 'Schedule',
|
||||||
|
fontColor: ColorsManager.primaryColor,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) => ThreeGangBloc(threeGangId: device.uuid ?? '')
|
||||||
|
..add(GetCounterEvent(deviceCode: deviceCode)),
|
||||||
|
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
Duration duration = Duration();
|
||||||
|
int countNum = 0;
|
||||||
|
if (state is UpdateTimerState) {
|
||||||
|
countNum = state.seconds;
|
||||||
|
} else if (state is TimerRunInProgress) {
|
||||||
|
countNum = state.remainingTime;
|
||||||
|
}
|
||||||
|
return state is LoadingInitialState
|
||||||
|
? const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
decoration: const ShapeDecoration(
|
||||||
|
color: ColorsManager.slidingBlueColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: CupertinoSlidingSegmentedControl<int>(
|
||||||
|
thumbColor: ColorsManager.slidingBlueColor,
|
||||||
|
onValueChanged: (value) {
|
||||||
|
BlocProvider.of<ThreeGangBloc>(context)
|
||||||
|
.add(ChangeSlidingSegment(value: value ?? 0));
|
||||||
|
},
|
||||||
|
groupValue: state is ChangeSlidingSegmentState ? state.value : 0,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
children: <int, Widget>{
|
||||||
|
0: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: BodySmall(
|
||||||
|
text: 'Countdown',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
1: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: Text(
|
||||||
|
'Schedule',
|
||||||
|
style: context.bodySmall.copyWith(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
countNum > 0
|
||||||
|
? BodyLarge(text: _formatDuration(countNum))
|
||||||
|
: Container(
|
||||||
|
child: CupertinoTimerPicker(
|
||||||
|
mode: CupertinoTimerPickerMode.hm,
|
||||||
|
initialTimerDuration: Duration(hours: 2, minutes: 20),
|
||||||
|
onTimerDurationChanged: (Duration newDuration) {
|
||||||
|
duration = newDuration;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (countNum > 0) {
|
||||||
|
BlocProvider.of<ThreeGangBloc>(context).add(SetCounterValue(
|
||||||
|
deviceCode: deviceCode, duration: Duration.zero));
|
||||||
|
} else {
|
||||||
|
BlocProvider.of<ThreeGangBloc>(context).add(SetCounterValue(
|
||||||
|
deviceCode: deviceCode, duration: duration));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
countNum > 0 ? Assets.pauseIcon : Assets.playIcon))
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _formatDuration(int seconds) {
|
||||||
|
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
|
||||||
|
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
||||||
|
final secs = (seconds % 60).toString().padLeft(2, '0');
|
||||||
|
return '$hours:$minutes:$secs';
|
||||||
|
}
|
||||||
|
}
|
@ -649,6 +649,8 @@ class Assets {
|
|||||||
|
|
||||||
static const String blueCheckboxIcon = "assets/icons/blue_checkbox_ic.svg";
|
static const String blueCheckboxIcon = "assets/icons/blue_checkbox_ic.svg";
|
||||||
static const String emptyCheckboxIcon = "assets/icons/empty_checkbox_ic.svg";
|
static const String emptyCheckboxIcon = "assets/icons/empty_checkbox_ic.svg";
|
||||||
|
static const String pauseIcon = "assets/icons/pause_ic.svg";
|
||||||
|
static const String playIcon = "assets/icons/play_ic.svg";
|
||||||
|
|
||||||
/// Assets for assetsImagesAutomation
|
/// Assets for assetsImagesAutomation
|
||||||
/// assets/images/automation.jpg
|
/// assets/images/automation.jpg
|
||||||
|
@ -4,8 +4,7 @@ abstract class ColorsManager {
|
|||||||
static const Color textPrimaryColor = Color(0xFF5D5D5D);
|
static const Color textPrimaryColor = Color(0xFF5D5D5D);
|
||||||
static const Color switchOffColor = Color(0x7F8D99AE);
|
static const Color switchOffColor = Color(0x7F8D99AE);
|
||||||
static const Color primaryColor = Color(0xFF0030CB);
|
static const Color primaryColor = Color(0xFF0030CB);
|
||||||
static Color primaryColorWithOpacity =
|
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
|
||||||
const Color(0xFF023DFE).withOpacity(0.6);
|
|
||||||
static const Color onPrimaryColor = Colors.white;
|
static const Color onPrimaryColor = Colors.white;
|
||||||
static const Color secondaryColor = Color(0xFF023DFE);
|
static const Color secondaryColor = Color(0xFF023DFE);
|
||||||
static const Color onSecondaryColor = Color(0xFF023DFE);
|
static const Color onSecondaryColor = Color(0xFF023DFE);
|
||||||
@ -18,4 +17,7 @@ abstract class ColorsManager {
|
|||||||
static const Color relaxColor = Color(0xFFFBD288);
|
static const Color relaxColor = Color(0xFFFBD288);
|
||||||
static const Color readingColor = Color(0xFFF7D69C);
|
static const Color readingColor = Color(0xFFF7D69C);
|
||||||
static const Color energizingColor = Color(0xFFEDEDED);
|
static const Color energizingColor = Color(0xFFEDEDED);
|
||||||
|
static const Color dividerColor = Color(0xFFEBEBEB);
|
||||||
|
static const Color slidingBlueColor = Color(0x99023DFE);
|
||||||
|
static const Color blackColor = Color(0xFF000000);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user