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: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';
|
||||
@ -9,6 +11,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
final String threeGangId;
|
||||
late ThreeGangModel deviceStatus;
|
||||
Timer? _timer;
|
||||
|
||||
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
|
||||
on<InitialEvent>(_fetchThreeGangStatus);
|
||||
@ -17,6 +20,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
||||
on<AllOffEvent>(_allOff);
|
||||
on<AllOnEvent>(_allOn);
|
||||
on<ChangeSlidingSegment>(_changeSliding);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
}
|
||||
|
||||
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||
@ -121,4 +128,74 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
} catch (_) {}
|
||||
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 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
|
||||
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_bloc/flutter_bloc.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/devices_cubit.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/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/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/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/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
@ -1,8 +1,8 @@
|
||||
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: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_bloc.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/generated/assets.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/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/schedule_screen.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/utils/context_extension.dart';
|
||||
@ -228,7 +229,15 @@ class ThreeGangScreen extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {},
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ScheduleScreen(
|
||||
device: device,
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
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 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/images/automation.jpg
|
||||
|
@ -4,8 +4,7 @@ abstract class ColorsManager {
|
||||
static const Color textPrimaryColor = Color(0xFF5D5D5D);
|
||||
static const Color switchOffColor = Color(0x7F8D99AE);
|
||||
static const Color primaryColor = Color(0xFF0030CB);
|
||||
static Color primaryColorWithOpacity =
|
||||
const Color(0xFF023DFE).withOpacity(0.6);
|
||||
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
|
||||
static const Color onPrimaryColor = Colors.white;
|
||||
static const Color secondaryColor = Color(0xFF023DFE);
|
||||
static const Color onSecondaryColor = Color(0xFF023DFE);
|
||||
@ -18,4 +17,7 @@ abstract class ColorsManager {
|
||||
static const Color relaxColor = Color(0xFFFBD288);
|
||||
static const Color readingColor = Color(0xFFF7D69C);
|
||||
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