4_scene&6_scene

This commit is contained in:
mohammad
2024-11-18 09:09:47 +03:00
parent b547a126ed
commit ec7b351a82
76 changed files with 8584 additions and 130 deletions

View File

@ -0,0 +1,314 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
import 'package:syncrow_app/features/devices/model/sex_scene_question_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
final String sixSceneId;
SixSceneBloc({
required this.sixSceneId,
}) : super(const SixSceneState()) {
on<SixSceneInitial>(_fetchStatus);
on<ReportLogsInitial>(fetchLogsForLastMonth);
on<ToggleNotificationEvent>(_toggleNotification);
on<ChangeNameEvent>(_changeName);
on<SearchFaqEvent>(_onSearchFaq);
on<FetchRoomsEvent>(_fetchRoomsAndDevices);
on<ChangeSwitchStatusEvent>(changeSwitchStatus);
on<LoadScenes>(_onLoadScenes);
on<SelectSceneEvent>(_selectScene);
on<SearchScenesEvent>(searchScene);
on<SaveSelectionEvent>(_onSaveSelection);
on<SelectOptionEvent>(_onOptionSelected);
on<AddDeviceToGroup>(_addDeviceToGroup); // Register handler here
on<RemoveDeviceFromGroup>(_removeDeviceFromGroup);
}
final TextEditingController nameController =
TextEditingController(text: '${'firstName'}');
bool isSaving = false;
bool editName = false;
final FocusNode focusNode = FocusNode();
bool closingReminder = false;
bool waterAlarm = false;
SixSceneModel deviceStatus =
SixSceneModel(waterContactState: 'normal', batteryPercentage: 0);
void _fetchStatus(SixSceneInitial event, Emitter<SixSceneState> emit) async {
emit(SixSceneLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(sixSceneId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = SixSceneModel.fromJson(
statusModelList,
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(SixSceneFailedState(errorMessage: e.toString()));
return;
}
}
void _onSearchFaq(SearchFaqEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
// Filter FAQ questions based on search query
List<SixSceneQuestionModel> _faqQuestions = faqQuestions.where((question) {
return question.question
.toLowerCase()
.contains(event.query.toLowerCase());
}).toList();
print(_faqQuestions);
emit(FaqSearchState(filteredFaqQuestions: _faqQuestions));
}
void _changeName(ChangeNameEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
editName = event.value!;
if (editName) {
Future.delayed(const Duration(milliseconds: 500), () {
focusNode.requestFocus();
});
} else {
focusNode.unfocus();
}
emit(NameEditingState(editName: editName));
}
void _toggleNotification(
ToggleNotificationEvent event, Emitter<SixSceneState> emit) async {
emit(LoadingNewSate(sosSensor: deviceStatus));
try {
closingReminder = event.isClosingEnabled;
emit(UpdateState(sensor: deviceStatus));
// API call to update the state, if necessary
// await DevicesAPI.controlDevice(
// DeviceControlModel(
// deviceId: sosId,
// code: 'closing_reminder',
// value: closingReminder,
// ),
// sosId,
// );
} catch (e) {
emit(SixSceneFailedState(errorMessage: e.toString()));
}
}
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<SixSceneState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
int startTime = lastMonth.millisecondsSinceEpoch;
int endTime = now.millisecondsSinceEpoch;
try {
emit(SixSceneLoadingState());
var response = await DevicesAPI.getReportLogs(
startTime: startTime.toString(),
endTime: endTime.toString(),
deviceUuid: sixSceneId,
code: 'sossensor_state',
);
recordGroups = response;
emit(UpdateState(sensor: deviceStatus));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(SixSceneFailedState(errorMessage: e.toString()));
}
}
final List<SixSceneQuestionModel> faqQuestions = [
SixSceneQuestionModel(
id: 1,
question: 'How does an SOS emergency button work?',
answer:
'The SOS emergency button sends an alert to your contacts when pressed.',
),
SixSceneQuestionModel(
id: 2,
question: 'How long will an SOS alarm persist?',
answer:
'The SOS alarm will persist until it is manually turned off or after a set time.',
),
SixSceneQuestionModel(
id: 3,
question: 'What should I do if the SOS button is unresponsive?',
answer: 'Try restarting the device. If it persists, contact support.',
),
SixSceneQuestionModel(
id: 4,
question: 'Can I use the SOS feature without a network connection?',
answer:
'No, a network connection is required to send the alert to your contacts.',
),
SixSceneQuestionModel(
id: 5,
question: 'How often should I check the SOS battery?',
answer:
'Check the SOS battery at least once a month to ensure it is operational.',
),
];
Future<void> _onSixSceneInitial(
SixSceneInitialQuestion event, Emitter<SixSceneState> emit) async {
emit(SixSceneLoadingState());
emit(FaqLoadedState(filteredFaqQuestions: faqQuestions));
}
List<DeviceModel> allDevices = [];
void _fetchRoomsAndDevices(
FetchRoomsEvent event, Emitter<SixSceneState> emit) async {
try {
emit(SixSceneLoadingState());
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const SixSceneFailedState(errorMessage: 'Something went wrong'));
return;
}
}
bool switchStatus = true;
void changeSwitchStatus(
ChangeSwitchStatusEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
switchStatus = !switchStatus;
emit(ChangeSwitchState(isEnable: switchStatus));
}
// List<ScenesModel> allScenes = [];
Future<void> _onLoadScenes(
LoadScenes event, Emitter<SixSceneState> emit) async {
emit(SixSceneLoadingState());
try {
if (event.unitId.isNotEmpty) {
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
showInDevice: event.showInDevice);
emit(SceneLoaded(
allScenes,
));
filteredScenes = allScenes;
} else {
emit(const SixSceneFailedState(errorMessage: 'Unit ID is empty'));
}
} catch (e) {
emit(const SixSceneFailedState(errorMessage: 'Something went wrong'));
}
}
bool selecedScene = false;
String selectedSceneId = '';
_selectScene(SelectSceneEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
selecedScene = !selecedScene;
emit(SelectedSceneState());
}
List<ScenesModel> allScenes = [];
List<ScenesModel> filteredScenes = [];
void searchScene(SearchScenesEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
filteredScenes = event.query.isEmpty
? allScenes
: allScenes.where((scene) {
final sceneName = scene.name?.toLowerCase() ?? '';
return sceneName.contains(event.query.toLowerCase());
}).toList();
emit(SearchResultsState());
}
String _selectedOption = '';
bool _hasSelectionChanged = false;
void _onOptionSelected(SelectOptionEvent event, Emitter<SixSceneState> emit) {
emit(SixSceneLoadingState());
_selectedOption = event.selectedOption;
_hasSelectionChanged = true;
emit(OptionSelectedState(
selectedOption: _selectedOption,
hasSelectionChanged: _hasSelectionChanged));
}
void _onSaveSelection(SaveSelectionEvent event, Emitter<SixSceneState> emit) {
if (_hasSelectionChanged) {
print('Save button clicked with selected option: $_selectedOption');
_hasSelectionChanged = false;
emit(SaveSelectionSuccessState());
}
}
//addDevicesIcon
List<GroupDevicesModel> groupDevices = [
GroupDevicesModel(
dec: 'Syncroom', icon: Assets.minusIcon, name: '6 Scene Switch')
];
List<GroupDevicesModel> devices = [
GroupDevicesModel(
dec: 'Syncroom', icon: Assets.addDevicesIcon, name: '6 Scene Switch')
];
// @override
// Stream<SixSceneState> mapEventToState(SixSceneEvent event) async* {
// if (event is AddDeviceToGroup) {
// devices.remove(event.device);
// groupDevices.add(event.device);
// yield UpdateStateList(groupDevices: groupDevices, devices: devices);
// } else if (event is RemoveDeviceFromGroup) {
// groupDevices.remove(event.device);
// devices.add(event.device);
// yield UpdateStateList(groupDevices: groupDevices, devices: devices);
// }
// }
// Handler for AddDeviceToGroup
void _addDeviceToGroup(AddDeviceToGroup event, Emitter<SixSceneState> emit) {
devices.remove(event.device);
groupDevices.add(event.device);
for (var device in groupDevices) {
device.icon = event.icon;
}
emit(UpdateStateList(groupDevices: groupDevices, devices: devices));
}
// Handler for RemoveDeviceFromGroup
void _removeDeviceFromGroup(
RemoveDeviceFromGroup event, Emitter<SixSceneState> emit) {
groupDevices.remove(event.device);
devices.add(event.device);
for (var device in groupDevices) {
device.icon = event.icon;
}
emit(UpdateStateList(groupDevices: groupDevices, devices: devices));
}
}

View File

@ -0,0 +1,173 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
abstract class SixSceneEvent extends Equatable {
const SixSceneEvent();
@override
List<Object> get props => [];
}
class SixSceneLoading extends SixSceneEvent {}
class SixSceneSwitch extends SixSceneEvent {
final String switchD;
final String deviceId;
final String productId;
const SixSceneSwitch(
{required this.switchD, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [switchD, deviceId, productId];
}
class SixSceneUpdated extends SixSceneEvent {}
class SixSceneInitial extends SixSceneEvent {
const SixSceneInitial();
}
class ReportLogsInitial extends SixSceneEvent {
const ReportLogsInitial();
}
class SixSceneChangeStatus extends SixSceneEvent {}
class GetCounterEvent extends SixSceneEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@override
List<Object> get props => [deviceCode];
}
class ToggleEnableAlarmEvent extends SixSceneEvent {
final bool isLowBatteryEnabled;
const ToggleEnableAlarmEvent(this.isLowBatteryEnabled);
@override
List<Object> get props => [isLowBatteryEnabled];
}
class ToggleNotificationEvent extends SixSceneEvent {
final bool isClosingEnabled;
const ToggleNotificationEvent(this.isClosingEnabled);
@override
List<Object> get props => [isClosingEnabled];
}
class ToggleSixSceneAlarmEvent extends SixSceneEvent {
final bool isSixSceneAlarmEnabled;
const ToggleSixSceneAlarmEvent(this.isSixSceneAlarmEnabled);
@override
List<Object> get props => [isSixSceneAlarmEnabled];
}
class SetCounterValue extends SixSceneEvent {
final Duration duration;
final String deviceCode;
const SetCounterValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends SixSceneEvent {
final int duration;
const StartTimer(this.duration);
@override
List<Object> get props => [duration];
}
class TickTimer extends SixSceneEvent {
final int remainingTime;
const TickTimer(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class StopTimer extends SixSceneEvent {}
class OnClose extends SixSceneEvent {}
class ChangeNameEvent extends SixSceneEvent {
final bool? value;
const ChangeNameEvent({this.value});
}
class SearchFaqEvent extends SixSceneEvent {
final String query;
const SearchFaqEvent(this.query);
}
class SixSceneInitialQuestion extends SixSceneEvent {
const SixSceneInitialQuestion();
}
class ChangeSwitchStatusEvent extends SixSceneEvent {}
class FetchRoomsEvent extends SixSceneEvent {
final SpaceModel unit;
const FetchRoomsEvent({required this.unit});
@override
List<Object> get props => [unit];
}
class LoadScenes extends SixSceneEvent {
final String unitId;
final bool showInDevice;
final SpaceModel unit;
const LoadScenes(
{required this.unitId, required this.unit, this.showInDevice = false});
@override
List<Object> get props => [unitId, showInDevice];
}
class SelectSceneEvent extends SixSceneEvent {
final String unitId;
const SelectSceneEvent({
required this.unitId,
});
}
class SearchScenesEvent extends SixSceneEvent {
final String query;
const SearchScenesEvent({
required this.query,
});
}
class SaveSelectionEvent extends SixSceneEvent {}
class SelectOptionEvent extends SixSceneEvent {
dynamic selectedOption;
SelectOptionEvent({
this.selectedOption,
});
}
class AddDeviceToGroup extends SixSceneEvent {
final GroupDevicesModel device;
final String icon;
AddDeviceToGroup(this.device, this.icon);
}
class RemoveDeviceFromGroup extends SixSceneEvent {
final GroupDevicesModel device;
final String icon;
RemoveDeviceFromGroup(this.device, this.icon);
}

View File

@ -0,0 +1,113 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
import 'package:syncrow_app/features/devices/model/sex_scene_question_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
class SixSceneState extends Equatable {
const SixSceneState();
@override
List<Object> get props => [];
}
class SixSceneInitialState extends SixSceneState {}
class SixSceneLoadingState extends SixSceneState {}
class SixSceState extends SixSceneState {}
class UpdateStateList extends SixSceneState {
final List<GroupDevicesModel> groupDevices;
final List<GroupDevicesModel> devices;
const UpdateStateList({required this.groupDevices, required this.devices});
}
class SixSceneFailedState extends SixSceneState {
final String errorMessage;
const SixSceneFailedState({required this.errorMessage});
@override
List<Object> get props => [errorMessage];
}
class UpdateState extends SixSceneState {
final SixSceneModel sensor;
const UpdateState({required this.sensor});
@override
List<Object> get props => [sensor];
}
class LoadingNewSate extends SixSceneState {
final SixSceneModel sosSensor;
const LoadingNewSate({required this.sosSensor});
@override
List<Object> get props => [sosSensor];
}
class NameEditingState extends SixSceneState {
final bool editName;
NameEditingState({required this.editName});
}
class FaqLoadedState extends SixSceneState {
final List<SixSceneQuestionModel> filteredFaqQuestions;
FaqLoadedState({this.filteredFaqQuestions = const []});
}
class FaqSearchState extends SixSceneState {
final List<SixSceneQuestionModel> filteredFaqQuestions;
const FaqSearchState({this.filteredFaqQuestions = const []});
}
class FetchRoomsState extends SixSceneState {
final List<SubSpaceModel> roomsList;
final List<DeviceModel> devicesList;
const FetchRoomsState({required this.devicesList, required this.roomsList});
@override
List<Object> get props => [devicesList];
}
class ChangeSwitchState extends SixSceneState {
final bool isEnable;
const ChangeSwitchState({required this.isEnable});
}
class SceneLoaded extends SixSceneState {
final List<ScenesModel> scenes;
final String? loadingSceneId;
final Map<String, bool> loadingStates;
const SceneLoaded(this.scenes,
{this.loadingSceneId, this.loadingStates = const {}});
}
class SelectedSceneState extends SixSceneState {}
class SearchResultsState extends SixSceneState {}
class SaveSelectionSuccessState extends SixSceneState {}
class OptionSelectedState extends SixSceneState {
final String selectedOption;
final bool hasSelectionChanged;
OptionSelectedState({
required this.selectedOption,
required this.hasSelectionChanged,
});
@override
List<Object> get props => [selectedOption, hasSelectionChanged];
}

View File

@ -0,0 +1,370 @@
import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_question_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
import 'package:syncrow_app/features/devices/model/scene_switch_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
final String fourSceneId;
FourSceneBloc({
required this.fourSceneId,
}) : super(const FourSceneState()) {
on<FourSceneInitial>(_fetchStatus);
on<FourSceneInitialInfo>(fetchDeviceData);
on<ReportLogsInitial>(fetchLogsForLastMonth);
on<ToggleNotificationEvent>(_toggleNotification);
on<ChangeNameEvent>(_changeName);
on<SearchFaqEvent>(_onSearchFaq);
on<FetchRoomsEvent>(_fetchRoomsAndDevices);
on<ChangeSwitchStatusEvent>(changeSwitchStatus);
on<LoadScenes>(_onLoadScenes);
on<SelectSceneEvent>(_selectScene);
on<SearchScenesEvent>(searchScene);
on<SaveSelectionEvent>(_onSaveSelection);
on<SelectOptionEvent>(_onOptionSelected);
on<AddDeviceToGroup>(_addDeviceToGroup); // Register handler here
on<RemoveDeviceFromGroup>(_removeDeviceFromGroup);
}
final TextEditingController nameController =
TextEditingController(text: '${'firstName'}');
bool isSaving = false;
bool editName = false;
final FocusNode focusNode = FocusNode();
bool closingReminder = false;
bool waterAlarm = false;
FourSceneModel deviceStatus = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: false);
SceneSwitch sceneInfo = SceneSwitch(
activeTime: 1728118263,
category: "",
categoryName: "",
createTime: 1728118263,
gatewayId: "",
icon: "",
ip: "",
lat: "",
localKey: "",
lon: "",
model: "",
name: "",
nodeId: "",
online: true,
ownerId: "",
productName: "",
sub: true,
timeZone: "",
updateTime: 0,
uuid: "",
productUuid: "",
productType: "",
permissionType: "",
macAddress: "",
subspace: Subspace(
uuid: "",
createdAt: "",
updatedAt: "",
subspaceName: "",
),
);
void _fetchStatus(
FourSceneInitial event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(fourSceneId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = FourSceneModel.fromJson(
statusModelList,
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
return;
}
}
Future fetchDeviceData(
FourSceneInitialInfo event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
var response = await DevicesAPI.getDeviceInfo(fourSceneId);
if (response.statusCode == 200) {
Map<String, dynamic> jsonData = jsonDecode(response.body);
sceneInfo = SceneSwitch.fromJson(jsonData);
emit(LoadingDeviceInfo(sosSensor: sceneInfo));
} else {
throw Exception('Failed to load device data: ${response.reasonPhrase}');
}
}
void _onSearchFaq(SearchFaqEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
List<FourSceneQuestionModel> _faqQuestions = faqQuestions.where((question) {
return question.question
.toLowerCase()
.contains(event.query.toLowerCase());
}).toList();
print(_faqQuestions);
emit(FaqSearchState(filteredFaqQuestions: _faqQuestions));
}
void _changeName(ChangeNameEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
editName = event.value!;
if (editName) {
Future.delayed(const Duration(milliseconds: 500), () {
focusNode.requestFocus();
});
} else {
focusNode.unfocus();
}
emit(NameEditingState(editName: editName));
}
void _toggleNotification(
ToggleNotificationEvent event, Emitter<FourSceneState> emit) async {
emit(LoadingNewSate(sosSensor: deviceStatus));
try {
closingReminder = event.isClosingEnabled;
emit(UpdateState(sensor: deviceStatus));
// API call to update the state, if necessary
// await DevicesAPI.controlDevice(
// DeviceControlModel(
// deviceId: sosId,
// code: 'closing_reminder',
// value: closingReminder,
// ),
// sosId,
// );
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
}
}
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<FourSceneState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
int startTime = lastMonth.millisecondsSinceEpoch;
int endTime = now.millisecondsSinceEpoch;
try {
emit(FourSceneLoadingState());
var response = await DevicesAPI.getReportLogs(
startTime: startTime.toString(),
endTime: endTime.toString(),
deviceUuid: fourSceneId,
code: 'sossensor_state',
);
recordGroups = response;
emit(UpdateState(sensor: deviceStatus));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FourSceneFailedState(errorMessage: e.toString()));
}
}
final List<FourSceneQuestionModel> faqQuestions = [
FourSceneQuestionModel(
id: 1,
question: 'How does an SOS emergency button work?',
answer:
'The SOS emergency button sends an alert to your contacts when pressed.',
),
FourSceneQuestionModel(
id: 2,
question: 'How long will an SOS alarm persist?',
answer:
'The SOS alarm will persist until it is manually turned off or after a set time.',
),
FourSceneQuestionModel(
id: 3,
question: 'What should I do if the SOS button is unresponsive?',
answer: 'Try restarting the device. If it persists, contact support.',
),
FourSceneQuestionModel(
id: 4,
question: 'Can I use the SOS feature without a network connection?',
answer:
'No, a network connection is required to send the alert to your contacts.',
),
FourSceneQuestionModel(
id: 5,
question: 'How often should I check the SOS battery?',
answer:
'Check the SOS battery at least once a month to ensure it is operational.',
),
];
Future<void> _onFourSceneInitial(
FourSceneInitialQuestion event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
emit(FaqLoadedState(filteredFaqQuestions: faqQuestions));
}
List<DeviceModel> allDevices = [];
void _fetchRoomsAndDevices(
FetchRoomsEvent event, Emitter<FourSceneState> emit) async {
try {
emit(FourSceneLoadingState());
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const FourSceneFailedState(errorMessage: 'Something went wrong'));
return;
}
}
bool switchStatus = true;
void changeSwitchStatus(
ChangeSwitchStatusEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
switchStatus = !switchStatus;
emit(ChangeSwitchState(isEnable: switchStatus));
}
// List<ScenesModel> allScenes = [];
Future<void> _onLoadScenes(
LoadScenes event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
try {
if (event.unitId.isNotEmpty) {
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
showInDevice: event.showInDevice);
emit(SceneLoaded(
allScenes,
));
filteredScenes = allScenes;
} else {
emit(const FourSceneFailedState(errorMessage: 'Unit ID is empty'));
}
} catch (e) {
emit(const FourSceneFailedState(errorMessage: 'Something went wrong'));
}
}
bool selecedScene = false;
String selectedSceneId = '';
_selectScene(SelectSceneEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
selecedScene = !selecedScene;
emit(SelectedSceneState());
}
List<ScenesModel> allScenes = [];
List<ScenesModel> filteredScenes = [];
void searchScene(SearchScenesEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
filteredScenes = event.query.isEmpty
? allScenes
: allScenes.where((scene) {
final sceneName = scene.name?.toLowerCase() ?? '';
return sceneName.contains(event.query.toLowerCase());
}).toList();
emit(SearchResultsState());
}
String _selectedOption = '';
bool _hasSelectionChanged = false;
void _onOptionSelected(
SelectOptionEvent event, Emitter<FourSceneState> emit) {
emit(FourSceneLoadingState());
_selectedOption = event.selectedOption;
_hasSelectionChanged = true;
emit(OptionSelectedState(
selectedOption: _selectedOption,
hasSelectionChanged: _hasSelectionChanged));
}
void _onSaveSelection(
SaveSelectionEvent event, Emitter<FourSceneState> emit) {
if (_hasSelectionChanged) {
print('Save button clicked with selected option: $_selectedOption');
_hasSelectionChanged = false;
emit(SaveSelectionSuccessState());
}
}
//addDevicesIcon
List<GroupDevicesModel> groupDevices = [
GroupDevicesModel(
dec: 'Syncroom', icon: Assets.minusIcon, name: '6 Scene Switch')
];
List<GroupDevicesModel> devices = [
GroupDevicesModel(
dec: 'Syncroom', icon: Assets.addDevicesIcon, name: '6 Scene Switch')
];
// @override
// Stream<FourSceneState> mapEventToState(FourSceneEvent event) async* {
// if (event is AddDeviceToGroup) {
// devices.remove(event.device);
// groupDevices.add(event.device);
// yield UpdateStateList(groupDevices: groupDevices, devices: devices);
// } else if (event is RemoveDeviceFromGroup) {
// groupDevices.remove(event.device);
// devices.add(event.device);
// yield UpdateStateList(groupDevices: groupDevices, devices: devices);
// }
// }
// Handler for AddDeviceToGroup
void _addDeviceToGroup(AddDeviceToGroup event, Emitter<FourSceneState> emit) {
devices.remove(event.device);
groupDevices.add(event.device);
for (var device in groupDevices) {
device.icon = event.icon;
}
emit(UpdateStateList(groupDevices: groupDevices, devices: devices));
}
// Handler for RemoveDeviceFromGroup
void _removeDeviceFromGroup(
RemoveDeviceFromGroup event, Emitter<FourSceneState> emit) {
groupDevices.remove(event.device);
devices.add(event.device);
for (var device in groupDevices) {
device.icon = event.icon;
}
emit(UpdateStateList(groupDevices: groupDevices, devices: devices));
}
}

View File

@ -0,0 +1,174 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
abstract class FourSceneEvent extends Equatable {
const FourSceneEvent();
@override
List<Object> get props => [];
}
class FourSceneLoading extends FourSceneEvent {}
class FourSceneSwitch extends FourSceneEvent {
final String switchD;
final String deviceId;
final String productId;
const FourSceneSwitch(
{required this.switchD, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [switchD, deviceId, productId];
}
class FourSceneUpdated extends FourSceneEvent {}
class FourSceneInitialInfo extends FourSceneEvent {}
class FourSceneInitial extends FourSceneEvent {
const FourSceneInitial();
}
class ReportLogsInitial extends FourSceneEvent {
const ReportLogsInitial();
}
class FourSceneChangeStatus extends FourSceneEvent {}
class GetCounterEvent extends FourSceneEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@override
List<Object> get props => [deviceCode];
}
class ToggleEnableAlarmEvent extends FourSceneEvent {
final bool isLowBatteryEnabled;
const ToggleEnableAlarmEvent(this.isLowBatteryEnabled);
@override
List<Object> get props => [isLowBatteryEnabled];
}
class ToggleNotificationEvent extends FourSceneEvent {
final bool isClosingEnabled;
const ToggleNotificationEvent(this.isClosingEnabled);
@override
List<Object> get props => [isClosingEnabled];
}
class ToggleFourSceneAlarmEvent extends FourSceneEvent {
final bool isFourSceneAlarmEnabled;
const ToggleFourSceneAlarmEvent(this.isFourSceneAlarmEnabled);
@override
List<Object> get props => [isFourSceneAlarmEnabled];
}
class SetCounterValue extends FourSceneEvent {
final Duration duration;
final String deviceCode;
const SetCounterValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends FourSceneEvent {
final int duration;
const StartTimer(this.duration);
@override
List<Object> get props => [duration];
}
class TickTimer extends FourSceneEvent {
final int remainingTime;
const TickTimer(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class StopTimer extends FourSceneEvent {}
class OnClose extends FourSceneEvent {}
class ChangeNameEvent extends FourSceneEvent {
final bool? value;
const ChangeNameEvent({this.value});
}
class SearchFaqEvent extends FourSceneEvent {
final String query;
const SearchFaqEvent(this.query);
}
class FourSceneInitialQuestion extends FourSceneEvent {
const FourSceneInitialQuestion();
}
class ChangeSwitchStatusEvent extends FourSceneEvent {}
class FetchRoomsEvent extends FourSceneEvent {
final SpaceModel unit;
const FetchRoomsEvent({required this.unit});
@override
List<Object> get props => [unit];
}
class LoadScenes extends FourSceneEvent {
final String unitId;
final bool showInDevice;
final SpaceModel unit;
const LoadScenes(
{required this.unitId, required this.unit, this.showInDevice = false});
@override
List<Object> get props => [unitId, showInDevice];
}
class SelectSceneEvent extends FourSceneEvent {
final String unitId;
const SelectSceneEvent({
required this.unitId,
});
}
class SearchScenesEvent extends FourSceneEvent {
final String query;
const SearchScenesEvent({
required this.query,
});
}
class SaveSelectionEvent extends FourSceneEvent {}
class SelectOptionEvent extends FourSceneEvent {
dynamic selectedOption;
SelectOptionEvent({
this.selectedOption,
});
}
class AddDeviceToGroup extends FourSceneEvent {
final GroupDevicesModel device;
final String icon;
AddDeviceToGroup(this.device, this.icon);
}
class RemoveDeviceFromGroup extends FourSceneEvent {
final GroupDevicesModel device;
final String icon;
RemoveDeviceFromGroup(this.device, this.icon);
}

View File

@ -0,0 +1,123 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_question_model.dart';
import 'package:syncrow_app/features/devices/model/group_devices_model.dart';
import 'package:syncrow_app/features/devices/model/scene_switch_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
class FourSceneState extends Equatable {
const FourSceneState();
@override
List<Object> get props => [];
}
class FourSceneInitialState extends FourSceneState {}
class FourSceneLoadingState extends FourSceneState {}
class FourSceState extends FourSceneState {}
class UpdateStateList extends FourSceneState {
final List<GroupDevicesModel> groupDevices;
final List<GroupDevicesModel> devices;
const UpdateStateList({required this.groupDevices, required this.devices});
}
class FourSceneFailedState extends FourSceneState {
final String errorMessage;
const FourSceneFailedState({required this.errorMessage});
@override
List<Object> get props => [errorMessage];
}
class UpdateState extends FourSceneState {
final FourSceneModel sensor;
const UpdateState({required this.sensor});
@override
List<Object> get props => [sensor];
}
class LoadingNewSate extends FourSceneState {
final FourSceneModel sosSensor;
const LoadingNewSate({required this.sosSensor});
@override
List<Object> get props => [sosSensor];
}
class NameEditingState extends FourSceneState {
final bool editName;
NameEditingState({required this.editName});
}
class FaqLoadedState extends FourSceneState {
final List<FourSceneQuestionModel> filteredFaqQuestions;
FaqLoadedState({this.filteredFaqQuestions = const []});
}
class FaqSearchState extends FourSceneState {
final List<FourSceneQuestionModel> filteredFaqQuestions;
const FaqSearchState({this.filteredFaqQuestions = const []});
}
class FetchRoomsState extends FourSceneState {
final List<SubSpaceModel> roomsList;
final List<DeviceModel> devicesList;
const FetchRoomsState({required this.devicesList, required this.roomsList});
@override
List<Object> get props => [devicesList];
}
class ChangeSwitchState extends FourSceneState {
final bool isEnable;
const ChangeSwitchState({required this.isEnable});
}
class SceneLoaded extends FourSceneState {
final List<ScenesModel> scenes;
final String? loadingSceneId;
final Map<String, bool> loadingStates;
const SceneLoaded(this.scenes,
{this.loadingSceneId, this.loadingStates = const {}});
}
class SelectedSceneState extends FourSceneState {}
class SearchResultsState extends FourSceneState {}
class SaveSelectionSuccessState extends FourSceneState {}
class OptionSelectedState extends FourSceneState {
final String selectedOption;
final bool hasSelectionChanged;
OptionSelectedState({
required this.selectedOption,
required this.hasSelectionChanged,
});
@override
List<Object> get props => [selectedOption, hasSelectionChanged];
}
class LoadingDeviceInfo extends FourSceneState {
final SceneSwitch sosSensor;
const LoadingDeviceInfo({required this.sosSensor});
@override
List<Object> get props => [sosSensor];
}

View File

@ -0,0 +1,52 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class FourSceneModel {
dynamic scene_1;
dynamic scene_2;
dynamic scene_3;
dynamic scene_4;
dynamic scene_id_group_id;
dynamic switch_backlight;
FourSceneModel({
required this.scene_1,
required this.scene_2,
required this.scene_3,
required this.scene_4,
required this.scene_id_group_id,
required this.switch_backlight,
});
factory FourSceneModel.fromJson(List<StatusModel> jsonList) {
late dynamic _scene_1;
late dynamic _scene_2;
late dynamic _scene_3;
late dynamic _scene_4;
late dynamic _scene_id_group_id;
late dynamic _switch_backlight;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'scene_1') {
_scene_1 = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'scene_2') {
_scene_2 = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'scene_3') {
_scene_3 = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'scene_4') {
_scene_4 = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'scene_id_group_id') {
_scene_id_group_id = jsonList[i].value ?? 0;
} else if (jsonList[i].code == 'switch_backlight') {
_switch_backlight = jsonList[i].value ?? false;
}
}
return FourSceneModel(
scene_1: _scene_1,
scene_2: _scene_2,
scene_3: _scene_3,
scene_4: _scene_4,
scene_id_group_id: _scene_id_group_id,
switch_backlight: _switch_backlight,
);
}
}

View File

@ -0,0 +1,11 @@
class FourSceneQuestionModel {
final int id;
final String question;
final String answer;
FourSceneQuestionModel({
required this.id,
required this.question,
required this.answer,
});
}

View File

@ -0,0 +1,6 @@
class GroupDevicesModel {
String? icon;
final String? name;
final String? dec;
GroupDevicesModel({this.icon, this.name, this.dec});
}

View File

@ -0,0 +1,149 @@
import 'dart:convert';
class SceneSwitch {
final int activeTime;
final String category;
final String categoryName;
final int createTime;
final String gatewayId;
final String icon;
final String ip;
final String lat;
final String localKey;
final String lon;
final String model;
final String name;
final String nodeId;
final bool online;
final String ownerId;
final String productName;
final bool sub;
final String timeZone;
final int updateTime;
final String uuid;
final String productUuid;
final String productType;
final String permissionType;
final String macAddress;
final Subspace subspace;
SceneSwitch({
required this.activeTime,
required this.category,
required this.categoryName,
required this.createTime,
required this.gatewayId,
required this.icon,
required this.ip,
required this.lat,
required this.localKey,
required this.lon,
required this.model,
required this.name,
required this.nodeId,
required this.online,
required this.ownerId,
required this.productName,
required this.sub,
required this.timeZone,
required this.updateTime,
required this.uuid,
required this.productUuid,
required this.productType,
required this.permissionType,
required this.macAddress,
required this.subspace,
});
factory SceneSwitch.fromJson(Map<String, dynamic> json) {
return SceneSwitch(
activeTime: json['activeTime'],
category: json['category'],
categoryName: json['categoryName'],
createTime: json['createTime'],
gatewayId: json['gatewayId'],
icon: json['icon'],
ip: json['ip'] ?? "",
lat: json['lat'],
localKey: json['localKey'],
lon: json['lon'],
model: json['model'],
name: json['name'],
nodeId: json['nodeId'],
online: json['online'],
ownerId: json['ownerId'],
productName: json['productName'],
sub: json['sub'],
timeZone: json['timeZone'],
updateTime: json['updateTime'],
uuid: json['uuid'],
productUuid: json['productUuid'],
productType: json['productType'],
permissionType: json['permissionType'],
macAddress: json['macAddress'],
subspace: Subspace.fromJson(json['subspace']),
);
}
Map<String, dynamic> toJson() {
return {
'activeTime': activeTime,
'category': category,
'categoryName': categoryName,
'createTime': createTime,
'gatewayId': gatewayId,
'icon': icon,
'ip': ip,
'lat': lat,
'localKey': localKey,
'lon': lon,
'model': model,
'name': name,
'nodeId': nodeId,
'online': online,
'ownerId': ownerId,
'productName': productName,
'sub': sub,
'timeZone': timeZone,
'updateTime': updateTime,
'uuid': uuid,
'productUuid': productUuid,
'productType': productType,
'permissionType': permissionType,
'macAddress': macAddress,
'subspace': subspace.toJson(),
};
}
}
class Subspace {
final String uuid;
final String createdAt;
final String updatedAt;
final String subspaceName;
Subspace({
required this.uuid,
required this.createdAt,
required this.updatedAt,
required this.subspaceName,
});
factory Subspace.fromJson(Map<String, dynamic> json) {
return Subspace(
uuid: json['uuid'],
createdAt: json['createdAt'],
updatedAt: json['updatedAt'],
subspaceName: json['subspaceName'],
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'createdAt': createdAt,
'updatedAt': updatedAt,
'subspaceName': subspaceName,
};
}
}

View File

@ -0,0 +1,11 @@
class SixSceneQuestionModel {
final int id;
final String question;
final String answer;
SixSceneQuestionModel({
required this.id,
required this.question,
required this.answer,
});
}

View File

@ -0,0 +1,28 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class SixSceneModel {
String waterContactState;
int batteryPercentage;
SixSceneModel({
required this.waterContactState,
required this.batteryPercentage,
});
factory SixSceneModel.fromJson(List<StatusModel> jsonList) {
late String _waterContactState;
late int _batteryPercentage;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'sossensor_state') {
_waterContactState = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'battery_percentage') {
_batteryPercentage = jsonList[i].value ?? 0;
}
}
return SixSceneModel(
waterContactState: _waterContactState,
batteryPercentage: _batteryPercentage,
);
}
}

View File

@ -0,0 +1,151 @@
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/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/sex_scene_question_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/question_page.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FaqSixScenePage extends StatelessWidget {
final DeviceModel? device;
const FaqSixScenePage({super.key, this.device});
@override
Widget build(BuildContext context) {
TextEditingController _searchController = TextEditingController();
return DefaultScaffold(
title: 'FAQ',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitialQuestion()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
List<SixSceneQuestionModel> displayedQuestions = [];
if (state is FaqSearchState) {
displayedQuestions = state.filteredFaqQuestions;
} else if (state is FaqLoadedState) {
displayedQuestions = state.filteredFaqQuestions;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
// sensor.add(const SosInitial());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
DefaultContainer(
padding: const EdgeInsets.all(5),
child: TextFormField(
controller: _searchController,
onChanged: (value) {
sensor.add(SearchFaqEvent(value));
},
decoration: InputDecoration(
hintText: 'Enter your questions',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
suffixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.04,
),
BodyMedium(
text: _searchController.text.isEmpty
? 'Device Related FAQs'
: '${displayedQuestions.length} Help Topics',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
Expanded(
child: DefaultContainer(
child: ListView.builder(
shrinkWrap: true,
itemCount: displayedQuestions.length,
itemBuilder: (context, index) {
final faq = displayedQuestions[index];
return InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => QuestionPage(
questionModel: faq,
)),
);
},
child: SizedBox(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: BodyMedium(
fontSize: 14,
fontWeight: FontWeight.w400,
text: faq.question,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
),
],
),
),
const Divider(
color: ColorsManager.dividerColor,
),
],
),
),
);
},
)),
),
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,197 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class LocationSixScenePage extends StatefulWidget {
final SpaceModel? space;
LocationSixScenePage({super.key, this.space});
@override
_LocationSixScenePageState createState() => _LocationSixScenePageState();
}
class _LocationSixScenePageState extends State<LocationSixScenePage> {
String _selectedOption = 'Conference Room';
bool _hasSelectionChanged = false;
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Location',
actions: [
InkWell(
onTap: _hasSelectionChanged
? () {
print('Save button clicked');
}
: null,
child: BodyMedium(
text: 'Save',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: _hasSelectionChanged
? ColorsManager.slidingBlueColor
: ColorsManager.primaryTextColor,
),
),
const SizedBox(width: 20),
],
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: '')
..add(FetchRoomsEvent(unit: widget.space!)),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
List<SubSpaceModel>? rooms = [];
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is FetchRoomsState) {
rooms = state.roomsList;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 20),
children: [
const BodyMedium(
text: 'Smart Device Location',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 5),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: rooms!.length,
itemBuilder: (context, index) {
final room = rooms![index];
return Column(
children: [
_buildCheckboxOption(
label: room.name!,
onTap: (v) {
setState(() {
_selectedOption = v;
_hasSelectionChanged = true;
});
},
),
if (index < rooms.length - 1) ...[
const SizedBox(height: 10),
const Divider(
color: ColorsManager.dividerColor,
),
const SizedBox(height: 10),
],
],
);
},
),
),
],
),
);
},
),
),
);
}
Widget _buildCheckboxOption(
{required String label, required Function(String) onTap}) {
return Padding(
padding: const EdgeInsets.only(bottom: 10, top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(
text: label,
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w400),
),
CircularCheckbox(
value: _selectedOption == label,
onChanged: (bool? value) {
if (value == true) {
setState(() {
_selectedOption = label;
_hasSelectionChanged = true;
});
onTap(label);
}
},
),
],
),
);
}
}
class CircularCheckbox extends StatefulWidget {
final bool value;
final ValueChanged<bool?> onChanged;
CircularCheckbox({required this.value, required this.onChanged});
@override
_CircularCheckboxState createState() => _CircularCheckboxState();
}
class _CircularCheckboxState extends State<CircularCheckbox> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
widget.onChanged(!widget.value);
},
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: widget.value
? ColorsManager.primaryColorWithOpacity.withOpacity(0.01)
: Colors.grey,
width: 2.0,
),
color: widget.value
? ColorsManager.primaryColorWithOpacity
: Colors.transparent,
),
width: 24.0,
height: 24.0,
child: widget.value
? const Icon(
Icons.check,
color: Colors.white,
size: 16.0,
)
: null,
),
);
}
}

View File

@ -0,0 +1,144 @@
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/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/sex_scene_question_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class QuestionPage extends StatelessWidget {
final SixSceneQuestionModel? questionModel;
const QuestionPage({super.key, this.questionModel});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'FAQ',
child: BlocProvider(
create: (context) =>
SixSceneBloc(sixSceneId: '')..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: Column(
children: [
DefaultContainer(
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyLarge(
text: questionModel!.question,
fontSize: 22,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
SizedBox(
height: 15,
),
BodyMedium(
text: questionModel!.answer,
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.15,
),
Center(
child: SizedBox(
width: 180,
child: DefaultButton(
backgroundColor: ColorsManager.grayButtonColors,
borderRadius: 50,
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.thumbUp,
fit: BoxFit.fill,
),
SizedBox(
width: 10,
),
BodyMedium(
text: 'Helpful',
fontSize: 12,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
],
)),
),
),
SizedBox(
height: 15,
),
Center(
child: SizedBox(
width: 180,
child: DefaultButton(
backgroundColor: ColorsManager.grayButtonColors,
borderRadius: 50,
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.thumbDown,
fit: BoxFit.fill,
),
SizedBox(
width: 10,
),
BodyMedium(
text: 'Not Helpful',
fontSize: 12,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
],
)),
),
),
],
));
},
),
),
);
}
}

View File

@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class ShareSixScenePage extends StatelessWidget {
final DeviceModel? device;
const ShareSixScenePage({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Share Device',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is LoadingNewSate
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Sharing Method Not Supported',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
const BodyMedium(
text:
'Currently, you cannot use the specified method to share Bluetooth mesh devices Zigbee devices, infrared devices, Bluetooth Beacon Devices, and certain Bluetooth LE devices with other users.',
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Recommended Sharing Method',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
const BodyMedium(
text:
'If the recipient is a home member or a reliable user, tap Me > Home Management > Add Member and add the recipient to your home. Then, devices in the home can be shared with the recipient in bulk.',
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.15,
),
Center(
child: SizedBox(
width: 250,
child: DefaultButton(
backgroundColor: ColorsManager.blueColor1,
borderRadius: 50,
onPressed: () {},
child: Text('Add Home Member')),
),
)
],
));
},
),
),
);
}
}

View File

@ -0,0 +1,208 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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/resource_manager/color_manager.dart';
class SixSceneCreateGroup extends StatelessWidget {
final DeviceModel? device;
const SixSceneCreateGroup({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Create Group',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is LoadingNewSate
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(left: 25, right: 25),
child: BodySmall(
text:
'Devices in the same group can be controlled together',
fontColor: ColorsManager.primaryTextColor,
textAlign: TextAlign.center,
),
),
Flexible(
child: ListView.builder(
itemCount: sensor.groupDevices.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
BlocProvider.of<SixSceneBloc>(context).add(
RemoveDeviceFromGroup(
sensor.groupDevices[index],
Assets.addDevicesIcon));
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
SvgPicture.asset(
sensor.groupDevices[index].icon!,
fit: BoxFit.contain,
),
const SizedBox(
width: 15,
),
BodyMedium(
text: sensor
.groupDevices[index].name!,
fontColor:
ColorsManager.primaryTextColor,
textAlign: TextAlign.center,
fontSize: 15,
),
],
),
BodyMedium(
text: sensor.groupDevices[index].dec!,
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 15,
),
],
),
)),
);
},
),
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Devices to be added',
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 12,
fontWeight: FontWeight.w700,
),
const SizedBox(
height: 5,
),
sensor.devices.isNotEmpty
? Expanded(
child: ListView.builder(
itemCount: sensor.devices.length,
itemBuilder: (context, index) {
final device = sensor.devices[index];
return GestureDetector(
onTap: () {
BlocProvider.of<SixSceneBloc>(
context)
.add(AddDeviceToGroup(device,
Assets.minusIcon));
},
child: DefaultContainer(
child: Padding(
padding:
const EdgeInsets.all(5.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
SvgPicture.asset(
device.icon!,
fit: BoxFit.contain,
),
const SizedBox(
width: 15,
),
BodyMedium(
text: device.name!,
fontColor: ColorsManager
.primaryTextColor,
textAlign:
TextAlign.center,
fontSize: 15,
),
],
),
BodyMedium(
text: device.dec!,
fontColor: ColorsManager
.grayColor,
textAlign:
TextAlign.center,
fontSize: 15,
),
],
),
),
),
);
},
),
)
: const Column(
children: [
BodySmall(
text:
'Currently no devices available to create group',
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 12,
fontWeight: FontWeight.w400,
),
],
),
],
),
),
Spacer()
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,227 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DisconnectDeviceDialog extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const DisconnectDeviceDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Disconnect Device',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.red,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This will disconnect your device from this Application')),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Disconnect',
style: TextStyle(
color: ColorsManager.red,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}
class DisconnectWipeData extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const DisconnectWipeData({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Disconnect and Wipe Data',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.red,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This will disconnect your device from this Application and wipe all the data')),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Disconnect',
style: TextStyle(
color: ColorsManager.red,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,132 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SixSceneInfoPage extends StatelessWidget {
final DeviceModel? device;
const SixSceneInfoPage({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Information',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const BodyLarge(
text: 'Virtual ID',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'bf3575d0e0c8b6e0a6hybl',
fontColor: ColorsManager.primaryTextColor,
),
InkWell(
onTap: () {},
child: const Row(
children: [
Icon(
Icons.copy,
color: ColorsManager.blueColor,
),
BodyMedium(
text: 'Copy',
fontColor: ColorsManager.blueColor,
),
],
),
)
],
),
const Divider(
color: ColorsManager.dividerColor,
),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(
text: 'MAC',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
BodySmall(
text: 'bf3575d0e0c8b6e0a6hybl',
fontColor: ColorsManager.primaryTextColor,
),
],
),
const Divider(
color: ColorsManager.dividerColor,
),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(
text: 'Time Zone',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
BodySmall(
text: 'Asia/Dubai',
fontColor: ColorsManager.primaryTextColor,
),
],
),
]),
)));
},
),
),
);
}
}

View File

@ -0,0 +1,171 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/location_setting.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SixSceneProfilePage extends StatelessWidget {
final DeviceModel? device;
const SixSceneProfilePage({super.key, this.device});
@override
Widget build(BuildContext context) {
var spaces = HomeCubit.getInstance().spaces;
return DefaultScaffold(
title: 'Device Settings',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: ListView(
children: [
CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 55,
backgroundColor: Colors.grey,
child: ClipOval(
child: SvgPicture.asset(
Assets.sosProfileIcon,
fit: BoxFit.fill,
),
),
),
),
const SizedBox(
height: 10,
),
SizedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IntrinsicWidth(
child: ConstrainedBox(
constraints:
const BoxConstraints(maxWidth: 200),
child: TextFormField(
maxLength: 30,
style: const TextStyle(
color: Colors.black,
),
textAlign: TextAlign.center,
focusNode: sensor.focusNode,
controller: sensor.nameController,
enabled: sensor.editName,
onEditingComplete: () {
// sensor.add(SaveNameEvent(context: context));
},
decoration: const InputDecoration(
hintText: "Your Name",
border: InputBorder.none,
fillColor: Colors.white10,
counterText: '',
),
),
),
),
const SizedBox(width: 5),
InkWell(
onTap: () {
sensor
.add(const ChangeNameEvent(value: true));
},
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Icon(
Icons.edit_outlined,
size: 20,
color: ColorsManager.textPrimaryColor,
),
),
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Smart Device Information',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LocationSixScenePage(
space: spaces!.first,
)),
);
},
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
child: Text('Location'),
),
Row(
children: [
SizedBox(
child: BodyMedium(
text: 'Syncroom',
fontColor: ColorsManager.textGray,
),
),
Icon(
Icons.arrow_forward_ios,
size: 15,
color: ColorsManager.textGray,
),
],
)
],
),
),
)
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,520 @@
import 'package:flutter/cupertino.dart';
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/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/faq_six_scene_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/share_six_scene_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_create_group.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_delete_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_info_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_profile_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_update_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_update_page.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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/resource_manager/color_manager.dart';
class SixSceneSettings extends StatelessWidget {
final DeviceModel? device;
const SixSceneSettings({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Settings',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: ListView(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const SixSceneProfilePage(),
),
);
},
child: Stack(
children: [
const Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
SizedBox(height: 20),
DefaultContainer(
borderRadius:
BorderRadius.all(Radius.circular(30)),
child: Padding(
padding: EdgeInsets.all(10.0),
child: Padding(
padding: EdgeInsets.only(left: 90),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
BodyMedium(
text: '6 Scene Switch',
fontWeight: FontWeight.bold,
),
SizedBox(
height: 5,
),
BodySmall(
text: "Room: Syncrow"),
],
),
Icon(Icons.edit_sharp)
],
),
),
),
),
],
),
Positioned(
top: 0,
left: 20,
child: CircleAvatar(
radius: 43,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor:
ColorsManager.backgroundColor,
child: SvgPicture.asset(
Assets.sixSceneIcon,
fit: BoxFit.fill,
),
),
)),
),
],
),
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Device Management',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const SixSceneInfoPage()),
);
},
text: 'Device Information',
icon: Assets.infoIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
ShareSixScenePage(device: device!)),
);
},
text: 'Tap-to Run and Automation',
icon: Assets.tapRunIcon,
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Device Offline Notification',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onChanged: (p0) {},
isNotification: true,
onTap: () {},
text: 'Offline Notification',
icon: Assets.notificationIcon,
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Others',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 5),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
ShareSixScenePage(device: device!)),
);
},
text: 'Share Device',
icon: Assets.shareIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
SixSceneCreateGroup(
device: device!)),
);
},
text: 'Create Group',
icon: Assets.createGroupIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
FaqSixScenePage(device: device!)),
);
},
text: 'Device FAQ',
icon: Assets.faqIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTapUpdate: () {
showDialog(
context: context,
builder: (context) {
return UpdateInfoDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context).pop();
},
);
},
);
},
isUpdate: true,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const SixSceneUpdatePage()),
);
},
text: 'Device Update',
icon: Assets.updateIcon,
),
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: ColorsManager.red,
),
const SizedBox(height: 10),
const SizedBox(
width: 250,
child: Divider(
color: ColorsManager.dividerColor,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectDeviceDialog(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context)
.pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Disconnect Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectWipeData(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context)
.pop();
},
);
},
);
},
child: const BodyMedium(
text:
'Disconnect Device and Wipe Data',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
],
),
);
},
);
},
child: const Center(
child: BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager.red,
),
),
),
],
),
);
},
),
),
);
}
}
class SettingWidget extends StatelessWidget {
final String? text;
final bool? isUpdate;
final bool? isNotification;
final String? icon;
final Function()? onTap;
final Function()? onTapUpdate;
final Function(bool)? onChanged;
const SettingWidget(
{super.key,
this.text,
this.icon,
this.onTap,
this.isUpdate,
this.onChanged,
this.isNotification = false,
this.onTapUpdate});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.all(8),
decoration: const BoxDecoration(
color: ColorsManager.primaryColor,
borderRadius: BorderRadius.all(Radius.circular(20))),
child: SvgPicture.asset(
icon!,
fit: BoxFit.none,
height: 30,
),
),
),
const SizedBox(
width: 8,
),
Expanded(
flex: isUpdate == true ? 5 : 10,
child: BodyMedium(
text: text!,
fontSize: 15,
fontWeight: FontWeight.w400,
)),
],
),
),
isUpdate == true
? InkWell(
onTap: onTapUpdate,
child: BodyMedium(
text: '1 Update Available',
fontSize: 13,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blueColor,
),
)
: SizedBox(),
isNotification == false
? const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.graysColor,
size: 20,
)
: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: onChanged,
applyTheme: true,
),
),
],
),
);
}
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class UpdateInfoDialog extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const UpdateInfoDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
BodyLarge(
text: 'Update Available',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.switchButton.withOpacity(0.6),
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'An update is available for your device. Version 2.1.0 includes new features and important fixes to enhance performance and security.',
textAlign: TextAlign.center,
)),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Remind me later',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Update Now',
style: TextStyle(
color:
ColorsManager.switchButton.withOpacity(0.6),
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class upDateNote extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const upDateNote({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
BodyLarge(
text: 'Update Note',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.switchButton.withOpacity(0.6),
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This update may take a long time. Make sure that the device is fully charged. The device will be unavailable during the update.',
textAlign: TextAlign.center,
)),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Start Update',
style: TextStyle(
color:
ColorsManager.switchButton.withOpacity(0.6),
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,345 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_update_note.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SixSceneUpdatePage extends StatelessWidget {
const SixSceneUpdatePage({super.key});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Update',
child: BlocProvider(
create: (context) =>
SixSceneBloc(sixSceneId: '')..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {},
child: Column(
children: [
// SizedBox(
// height: MediaQuery.of(context).size.height * 0.15,
// ),
DefaultContainer(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 50,
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: SizedBox(
width: 200,
child: Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: const BoxDecoration(
color: ColorsManager
.primaryColor,
borderRadius:
BorderRadius.all(
Radius.circular(50))),
child: SvgPicture.asset(
Assets.checkUpdateIcon,
fit: BoxFit.fill,
height: 25,
),
),
const SizedBox(
width: 10,
),
InkWell(
onTap: () {},
child: const BodyMedium(
text: 'Automatic Update',
fontWeight: FontWeight.normal,
),
),
],
),
),
trailing: Container(
width: 100,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
const BodyMedium(
text: 'Off',
fontColor: ColorsManager.textGray,
),
Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: (value) {},
applyTheme: true,
),
),
],
),
)),
),
],
),
),
const SizedBox(
height: 10,
),
UpdateSosContainerWithProgressBar(
sosDescription:
'Connectivity Issue Resolved Fixed a bug that caused the SOS button to disconnect from the app intermittently.',
sosVersion: 'SOS v2.0.5',
),
// const UpdatedContainer(
// sosVersion: 'SOS v1.0.13',
// sosDescription: 'SOS is up to date',
// ),
// const NewUpdateContainer(
// sosVersion: 'SOS v2.0.5',
// sosDescription:
// 'Connectivity Issue Resolved Fixed a bug that caused the SOS button to disconnect from the app intermittently.',
// ),
const SizedBox(
height: 15,
),
],
));
},
),
));
}
}
class UpdatedContainer extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const UpdatedContainer({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return DefaultContainer(
height: MediaQuery.of(context).size.height * 0.35,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.blackColor,
),
],
),
],
),
),
);
}
}
class NewUpdateContainer extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const NewUpdateContainer({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return DefaultContainer(
height: MediaQuery.of(context).size.height * 0.50,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
const BodyMedium(
text: 'New Update Available Now!',
fontColor: ColorsManager.blueColor,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
Container(
width: MediaQuery.of(context).size.width * 0.7,
child: BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.6,
child: DefaultButton(
borderRadius: 25,
backgroundColor: ColorsManager.blueColor1,
height: 150,
onPressed: () {
showDialog(
context: context,
builder: (context) {
return upDateNote(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
Navigator.of(context).pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Update Now',
fontColor: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w700,
textAlign: TextAlign.center,
),
),
)
],
),
],
),
),
);
}
}
class UpdateSosContainerWithProgressBar extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const UpdateSosContainerWithProgressBar({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
DefaultContainer(
height: MediaQuery.of(context).size.height * 0.50,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
BodyMedium(
text: 'New Update Available Now!',
fontColor: ColorsManager.blueColor,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
LinearPercentIndicator(
barRadius: Radius.circular(10),
width: 170.0,
animation: true,
animationDuration: 1000,
lineHeight: 5.0,
percent: 0.2,
linearStrokeCap: LinearStrokeCap.butt,
progressColor: ColorsManager.blueColor1,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: const BodyMedium(
text: 'Downloading Update please be patient',
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: const BodyMedium(
text:
'Please keep the power of the device connected during the upgrade process.',
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
);
}
}

View File

@ -0,0 +1,286 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.dart';
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SelectSceneSixPage extends StatelessWidget {
SelectSceneSixPage({super.key});
final TextEditingController _searchController = TextEditingController();
final int? selectedSwitchIndex = 0;
final spaces = HomeCubit.getInstance().spaces;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: '')
..add(LoadScenes(
unit: spaces!.first,
unitId: spaces!.first.id,
showInDevice: false,
)),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensorBloc = BlocProvider.of<SixSceneBloc>(context);
return DefaultScaffold(
title: 'Select Scene',
actions: [_buildSaveButton(context, state, sensorBloc)],
child: state is SixSceneLoadingState
? _buildLoadingIndicator()
: _buildSceneContent(context, sensorBloc),
);
},
),
);
}
// Save button builder
Widget _buildSaveButton(
BuildContext context, SixSceneState state, SixSceneBloc sensorBloc) {
final bool canSave =
state is OptionSelectedState && state.hasSelectionChanged;
return GestureDetector(
onTap: canSave
? () {
print('object');
context.read<SixSceneBloc>().add(SaveSelectionEvent());
}
: null,
child: BodyMedium(
text: 'Save',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: canSave
? ColorsManager.slidingBlueColor
: ColorsManager.primaryTextColor,
),
);
}
// Loading indicator
Widget _buildLoadingIndicator() {
return const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
// Main scene content with search bar and grid
Widget _buildSceneContent(BuildContext context, SixSceneBloc sensorBloc) {
return Column(
children: [
_buildSearchBar(sensorBloc),
const SizedBox(height: 20),
Expanded(
child: _buildSceneGrid(sensorBloc),
),
],
);
}
// Search bar widget
Widget _buildSearchBar(SixSceneBloc sensorBloc) {
return TextFormField(
controller: _searchController,
onChanged: (value) {
sensorBloc.add(SearchScenesEvent(query: value));
},
decoration: InputDecoration(
hintText: 'Search',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
suffixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
);
}
// Scene grid builder
Widget _buildSceneGrid(SixSceneBloc sensorBloc) {
final scenes = sensorBloc.filteredScenes;
return GridView.builder(
itemCount: scenes.length + 1,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
mainAxisExtent: 120,
),
itemBuilder: (context, index) {
if (index == scenes.length) {
return InkWell(
onTap: () => Navigator.pushNamed(
NavigationService.navigatorKey.currentContext!,
Routes.sceneTasksRoute,
arguments: SceneSettingsRouteArguments(
sceneType: '',
sceneId: '',
sceneName: '',
),
),
child: CreateSceneItem(),
);
} else {
final scene = scenes[index];
return SceneItem(
id: scene.id,
value: sensorBloc.selectedSceneId == scene.id,
disablePlayButton: false,
onChanged: (isSelected) {
sensorBloc.selectedSceneId = isSelected ? scene.id : 'null';
sensorBloc.add(SelectOptionEvent(selectedOption: scene.id));
},
icon: scene.iconInBytes,
title: scene.name,
);
}
},
);
}
}
class SceneItem extends StatefulWidget {
final String id; // Unique ID for each scene
final Uint8List icon;
final String title;
final bool disablePlayButton;
final bool value;
final Function(bool) onChanged;
const SceneItem({
required this.id,
required this.icon,
required this.title,
this.disablePlayButton = false,
required this.value,
required this.onChanged,
});
@override
State<SceneItem> createState() => _SceneItemState();
}
class _SceneItemState extends State<SceneItem> {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
spreadRadius: 1,
offset: Offset(0, 3),
),
],
),
padding: const EdgeInsets.all(16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!widget.disablePlayButton)
Image.memory(
widget.icon,
height: 32,
width: 32,
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) => Image.asset(
Assets.assetsIconsLogo,
height: 32,
width: 32,
fit: BoxFit.fill),
),
BodyMedium(
text: widget.title,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w700,
color: ColorsManager.secondaryTextColor),
textAlign: TextAlign.center,
),
],
),
CircularCheckbox(
value: widget.value,
onChanged: (isSelected) => widget.onChanged(isSelected!),
),
],
),
);
}
}
// Widget for the static "Create Scene" button
class CreateSceneItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 5,
spreadRadius: 2,
offset: Offset(0, 3),
),
],
),
padding: const EdgeInsets.all(16),
child: const Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.add_circle,
color: ColorsManager.grayButtonColors, size: 36),
BodyMedium(
text: 'Create Scene',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: ColorsManager.secondaryTextColor),
textAlign: TextAlign.center,
),
],
),
);
}
}

View File

@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/switches_card.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SelectSwitchDialog extends StatefulWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const SelectSwitchDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
State<SelectSwitchDialog> createState() => _SelectSwitchDialogState();
}
class _SelectSwitchDialogState extends State<SelectSwitchDialog> {
int? selectedSwitchIndex = 0; // State variable to track selected switch
@override
Widget build(BuildContext context) {
return AlertDialog(
backgroundColor: ColorsManager.onPrimaryColor,
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 10),
const BodyLarge(
text: 'Select Switch',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.primaryColor,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(color: ColorsManager.textGray),
),
const SizedBox(height: 20),
Row(
children: [
SwitchsCard(
switch1Down: selectedSwitchIndex == -1
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch1Up: selectedSwitchIndex == 1
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch2Down: selectedSwitchIndex == -2
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch2Up: selectedSwitchIndex == 2
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
onSwitch1UpTap: () {
setState(() => selectedSwitchIndex = 1);
},
onSwitch1DownTap: () {
setState(() => selectedSwitchIndex = -1);
},
onSwitch2UpTap: () {
setState(() => selectedSwitchIndex = 2);
},
onSwitch2DownTap: () {
setState(() => selectedSwitchIndex = -2);
},
),
],
),
const SizedBox(height: 20),
const Center(
child: Text(
'Please select one of the switches available to continue',
textAlign: TextAlign.center,
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right:
BorderSide(color: ColorsManager.textGray, width: 0.5),
top: BorderSide(color: ColorsManager.textGray, width: 1.0),
)),
child: SizedBox(
child: InkWell(
onTap: widget.cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textPrimaryColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(color: ColorsManager.textGray, width: 0.5),
top: BorderSide(color: ColorsManager.textGray, width: 1.0),
)),
child: InkWell(
onTap: selectedSwitchIndex == 0 ? () {} : widget.confirmTab,
child: Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Next',
style: TextStyle(
color: selectedSwitchIndex == 0
? ColorsManager.textPrimaryColor
.withOpacity(0.6)
: ColorsManager.primaryColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
],
)
],
),
);
}
}

View File

@ -0,0 +1,200 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/6_scene_setting/six_scene_settings.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/select_scene_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/select_switch_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/switches_card.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
class SixSceneScreen extends StatelessWidget {
final DeviceModel? device;
const SixSceneScreen({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: '6 Scene Switch',
actions: [
InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SixSceneSettings(device: device!)),
);
},
child: SvgPicture.asset(Assets.assetsIconsSettings)),
const SizedBox(
width: 10,
)
],
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: ListView(
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height * 0.8,
child: Column(
children: [
SwitchsCard(
switch1Down: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch1Up: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch2Down: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch2Up: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
onSwitch1UpTap: () {
debugPrint("Switch 1 Up tapped");
},
onSwitch1DownTap: () {
debugPrint("Switch 1 Down tapped");
},
onSwitch2UpTap: () {
debugPrint("Switch 2 Up tapped");
},
onSwitch2DownTap: () {
debugPrint("Switch 2 Down tapped");
},
),
Flexible(
child: Row(
children: [
Expanded(
child: DefaultContainer(
onTap: () {
sensor.add(ChangeSwitchStatusEvent());
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.backlightIcon),
),
const SizedBox(
height: 15,
),
const Flexible(
child: FittedBox(
child: BodySmall(
text: 'Backlight',
textAlign: TextAlign.center,
),
),
),
],
),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: DefaultContainer(
onTap: () {
showDialog(
context: context,
builder: (context) {
return SelectSwitchDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
SelectSceneSixPage()),
);
},
);
},
);
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.addSceneIcon),
),
const SizedBox(
height: 15,
),
const Flexible(
child: FittedBox(
child: BodySmall(
text: 'Add Scene',
textAlign: TextAlign.center,
),
),
),
],
),
),
),
],
),
)
],
),
),
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,135 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SwitchsCard extends StatelessWidget {
final String switch1Up;
final String switch1Down;
final String switch2Up;
final String switch2Down;
final VoidCallback onSwitch1UpTap;
final VoidCallback onSwitch1DownTap;
final VoidCallback onSwitch2UpTap;
final VoidCallback onSwitch2DownTap;
SwitchsCard({
required this.switch1Down,
required this.switch1Up,
required this.switch2Down,
required this.switch2Up,
required this.onSwitch1UpTap,
required this.onSwitch1DownTap,
required this.onSwitch2UpTap,
required this.onSwitch2DownTap,
});
@override
Widget build(BuildContext context) {
return Expanded(
flex: 4,
child: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: ColorsManager.onPrimaryColor,
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.1),
blurRadius: 24,
offset: const Offset(-2, -2),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.black.withOpacity(0.11),
blurRadius: 5,
offset: const Offset(2, 0),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.white.withOpacity(0.13),
blurRadius: 10,
offset: const Offset(5, 1),
blurStyle: BlurStyle.inner,
),
],
),
child: SizedBox(
height: 300,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// Switch 1
_buildSwitchColumn(switch1Up, switch1Down,
onSwitch1UpTap, onSwitch1DownTap),
_buildDivider(),
// Switch 2
_buildSwitchColumn(switch2Up, switch2Down,
onSwitch2UpTap, onSwitch2DownTap),
],
),
),
),
),
),
],
),
),
);
}
Widget _buildSwitchColumn(
String switchUp,
String switchDown,
VoidCallback onUpTap,
VoidCallback onDownTap,
) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 30, bottom: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: onUpTap,
child: Container(
height: 20,
width: 20,
child: SvgPicture.asset(switchUp),
),
),
InkWell(
onTap: onDownTap,
child: Container(
height: 20,
width: 20,
child: SvgPicture.asset(switchDown),
),
),
],
),
),
);
}
Widget _buildDivider() {
return Container(
width: 3,
color: ColorsManager.dividerColor,
);
}
}

View File

@ -0,0 +1,204 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_settings.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_select_scene_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_select_switch_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_switches_card.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
class FourSceneScreen extends StatelessWidget {
final DeviceModel? device;
const FourSceneScreen({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: '4 Scene Switch',
actions: [
InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FourSceneSettings(device: device!)),
);
},
child: SvgPicture.asset(Assets.assetsIconsSettings)),
const SizedBox(
width: 10,
)
],
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial())
..add(FourSceneInitialInfo()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: ListView(
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height * 0.8,
child: Column(
children: [
FourSwitchsCard(
switch1Down: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch1Up: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch2Down: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
switch2Up: sensor.switchStatus == true
? Assets.switchOn
: Assets.switchOff,
onSwitch1UpTap: () {
debugPrint("Switch 1 Up tapped");
},
onSwitch1DownTap: () {
debugPrint("Switch 1 Down tapped");
},
onSwitch2UpTap: () {
debugPrint("Switch 2 Up tapped");
},
onSwitch2DownTap: () {
debugPrint("Switch 2 Down tapped");
},
),
Flexible(
child: Row(
children: [
Expanded(
child: DefaultContainer(
onTap: () {
sensor.add(ChangeSwitchStatusEvent());
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.backlightIcon),
),
const SizedBox(
height: 15,
),
const Flexible(
child: FittedBox(
child: BodySmall(
text: 'Backlight',
textAlign: TextAlign.center,
),
),
),
],
),
),
),
const SizedBox(
width: 10,
),
Expanded(
child: DefaultContainer(
onTap: () {
showDialog(
context: context,
builder: (context) {
return FourSelectSwitchDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
FourSelectSceneFourPage()),
);
},
);
},
);
},
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 46, maxWidth: 50),
child: SvgPicture.asset(
Assets.addSceneIcon),
),
const SizedBox(
height: 15,
),
const Flexible(
child: FittedBox(
child: BodySmall(
text: 'Add Scene',
textAlign: TextAlign.center,
),
),
),
],
),
),
),
],
),
)
],
),
),
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,151 @@
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/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_question_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/question_page_four_scene.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FaqFourScenePage extends StatelessWidget {
final DeviceModel? device;
const FaqFourScenePage({super.key, this.device});
@override
Widget build(BuildContext context) {
TextEditingController _searchController = TextEditingController();
return DefaultScaffold(
title: 'FAQ',
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitialQuestion()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
List<FourSceneQuestionModel> displayedQuestions = [];
if (state is FaqSearchState) {
displayedQuestions = state.filteredFaqQuestions;
} else if (state is FaqLoadedState) {
displayedQuestions = state.filteredFaqQuestions;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
// sensor.add(const SosInitial());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
DefaultContainer(
padding: const EdgeInsets.all(5),
child: TextFormField(
controller: _searchController,
onChanged: (value) {
sensor.add(SearchFaqEvent(value));
},
decoration: InputDecoration(
hintText: 'Enter your questions',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
suffixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.04,
),
BodyMedium(
text: _searchController.text.isEmpty
? 'Device Related FAQs'
: '${displayedQuestions.length} Help Topics',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
Expanded(
child: DefaultContainer(
child: ListView.builder(
shrinkWrap: true,
itemCount: displayedQuestions.length,
itemBuilder: (context, index) {
final faq = displayedQuestions[index];
return InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => QuestionPageFourScene(
questionModel: faq,
)),
);
},
child: SizedBox(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: BodyMedium(
fontSize: 14,
fontWeight: FontWeight.w400,
text: faq.question,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
),
],
),
),
const Divider(
color: ColorsManager.dividerColor,
),
],
),
),
);
},
)),
),
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,213 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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/resource_manager/color_manager.dart';
class FourSceneCreateGroup extends StatelessWidget {
final DeviceModel? device;
const FourSceneCreateGroup({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Create Group',
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is LoadingNewSate
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(left: 25, right: 25),
child: BodySmall(
text:
'Devices in the same group can be controlled together',
fontColor: ColorsManager.primaryTextColor,
textAlign: TextAlign.center,
),
),
Flexible(
child: ListView.builder(
itemCount: sensor.groupDevices.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
BlocProvider.of<FourSceneBloc>(context).add(
RemoveDeviceFromGroup(
sensor.groupDevices[index],
Assets.addDevicesIcon));
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
SvgPicture.asset(
sensor.groupDevices[index].icon!,
fit: BoxFit.contain,
),
const SizedBox(
width: 15,
),
BodyMedium(
text: sensor
.groupDevices[index].name!,
fontColor:
ColorsManager.primaryTextColor,
textAlign: TextAlign.center,
fontSize: 15,
),
],
),
BodyMedium(
text: sensor.groupDevices[index].dec!,
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 15,
),
],
),
)),
);
},
),
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Devices to be added',
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 12,
fontWeight: FontWeight.w700,
),
const SizedBox(
height: 5,
),
sensor.devices.isNotEmpty
? Expanded(
child: ListView.builder(
itemCount: sensor.devices.length,
itemBuilder: (context, index) {
final device = sensor.devices[index];
return GestureDetector(
onTap: () {
BlocProvider.of<FourSceneBloc>(
context)
.add(AddDeviceToGroup(device,
Assets.minusIcon));
},
child: DefaultContainer(
child: Padding(
padding:
const EdgeInsets.all(5.0),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
SvgPicture.asset(
device.icon!,
fit: BoxFit.contain,
),
const SizedBox(
width: 15,
),
BodyMedium(
text: device.name!,
fontColor: ColorsManager
.primaryTextColor,
textAlign:
TextAlign.center,
fontSize: 15,
),
],
),
BodyMedium(
text: device.dec!,
fontColor: ColorsManager
.grayColor,
textAlign:
TextAlign.center,
fontSize: 15,
),
],
),
),
),
);
},
),
)
: const Column(
children: [
BodySmall(
text:
'Currently no devices available to create group',
fontColor: ColorsManager.grayColor,
textAlign: TextAlign.center,
fontSize: 12,
fontWeight: FontWeight.w400,
),
],
),
],
),
),
Spacer()
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,227 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class DisconnectDeviceDialog extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const DisconnectDeviceDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Disconnect Device',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.red,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This will disconnect your device from this Application')),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Disconnect',
style: TextStyle(
color: ColorsManager.red,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}
class DisconnectWipeData extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const DisconnectWipeData({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Disconnect and Wipe Data',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.red,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This will disconnect your device from this Application and wipe all the data')),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Disconnect',
style: TextStyle(
color: ColorsManager.red,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,132 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/six_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class SixSceneInfoPage extends StatelessWidget {
final DeviceModel? device;
const SixSceneInfoPage({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Information',
child: BlocProvider(
create: (context) => SixSceneBloc(sixSceneId: device?.uuid ?? '')
..add(const SixSceneInitial()),
child: BlocBuilder<SixSceneBloc, SixSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<SixSceneBloc>(context);
SixSceneModel model = SixSceneModel(
batteryPercentage: 0, waterContactState: 'normal');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is SixSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const SixSceneInitial());
},
child: DefaultContainer(
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const BodyLarge(
text: 'Virtual ID',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodySmall(
text: 'bf3575d0e0c8b6e0a6hybl',
fontColor: ColorsManager.primaryTextColor,
),
InkWell(
onTap: () {},
child: const Row(
children: [
Icon(
Icons.copy,
color: ColorsManager.blueColor,
),
BodyMedium(
text: 'Copy',
fontColor: ColorsManager.blueColor,
),
],
),
)
],
),
const Divider(
color: ColorsManager.dividerColor,
),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(
text: 'MAC',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
BodySmall(
text: 'bf3575d0e0c8b6e0a6hybl',
fontColor: ColorsManager.primaryTextColor,
),
],
),
const Divider(
color: ColorsManager.dividerColor,
),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyLarge(
text: 'Time Zone',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
BodySmall(
text: 'Asia/Dubai',
fontColor: ColorsManager.primaryTextColor,
),
],
),
]),
)));
},
),
),
);
}
}

View File

@ -0,0 +1,175 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/location_setting_four_scene.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FourSceneProfilePage extends StatelessWidget {
final DeviceModel? device;
const FourSceneProfilePage({super.key, this.device});
@override
Widget build(BuildContext context) {
var spaces = HomeCubit.getInstance().spaces;
return DefaultScaffold(
title: 'Device Settings',
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: ListView(
children: [
CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 55,
backgroundColor: Colors.grey,
child: ClipOval(
child: SvgPicture.asset(
Assets.sosProfileIcon,
fit: BoxFit.fill,
),
),
),
),
const SizedBox(
height: 10,
),
SizedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IntrinsicWidth(
child: ConstrainedBox(
constraints:
const BoxConstraints(maxWidth: 200),
child: TextFormField(
maxLength: 30,
style: const TextStyle(
color: Colors.black,
),
textAlign: TextAlign.center,
focusNode: sensor.focusNode,
controller: sensor.nameController,
enabled: sensor.editName,
onEditingComplete: () {
// sensor.add(SaveNameEvent(context: context));
},
decoration: const InputDecoration(
hintText: "Your Name",
border: InputBorder.none,
fillColor: Colors.white10,
counterText: '',
),
),
),
),
const SizedBox(width: 5),
InkWell(
onTap: () {
sensor
.add(const ChangeNameEvent(value: true));
},
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Icon(
Icons.edit_outlined,
size: 20,
color: ColorsManager.textPrimaryColor,
),
),
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Smart Device Information',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => LocationFourScenePage(
space: spaces!.first,
)),
);
},
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
child: Text('Location'),
),
Row(
children: [
SizedBox(
child: BodyMedium(
text: 'Syncroom',
fontColor: ColorsManager.textGray,
),
),
Icon(
Icons.arrow_forward_ios,
size: 15,
color: ColorsManager.textGray,
),
],
)
],
),
),
)
],
),
);
},
),
),
);
}
}

View File

@ -0,0 +1,526 @@
import 'package:flutter/cupertino.dart';
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/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/faq_four_scene_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_create_group.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_delete_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_profile_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_update_dialog.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_update_page.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/share_four_scene_page.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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/resource_manager/color_manager.dart';
class FourSceneSettings extends StatelessWidget {
final DeviceModel? device;
const FourSceneSettings({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Settings',
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: ListView(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const FourSceneProfilePage(),
),
);
},
child: Stack(
children: [
const Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
SizedBox(height: 20),
DefaultContainer(
borderRadius:
BorderRadius.all(Radius.circular(30)),
child: Padding(
padding: EdgeInsets.all(10.0),
child: Padding(
padding: EdgeInsets.only(left: 90),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
BodyMedium(
text: '4 Scene Switch',
fontWeight: FontWeight.bold,
),
SizedBox(
height: 5,
),
BodySmall(
text: "Room: Syncrow"),
],
),
Icon(Icons.edit_sharp)
],
),
),
),
),
],
),
Positioned(
top: 0,
left: 20,
child: CircleAvatar(
radius: 43,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 40,
backgroundColor:
ColorsManager.backgroundColor,
child: SvgPicture.asset(
Assets.sixSceneIcon,
fit: BoxFit.fill,
),
),
)),
),
],
),
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Device Management',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onTap: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// const FourSceneInfoPage()),
// );
},
text: 'Device Information',
icon: Assets.infoIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
ShareFourScenePage(
device: device!)),
);
},
text: 'Tap-to Run and Automation',
icon: Assets.tapRunIcon,
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Device Offline Notification',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onChanged: (p0) {},
isNotification: true,
onTap: () {},
text: 'Offline Notification',
icon: Assets.notificationIcon,
),
],
),
),
const SizedBox(height: 20),
const BodyMedium(
text: 'Others',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 5),
DefaultContainer(
child: Column(
children: [
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
ShareFourScenePage(
device: device!)),
);
},
text: 'Share Device',
icon: Assets.shareIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
FourSceneCreateGroup(
device: device!)),
);
},
text: 'Create Group',
icon: Assets.createGroupIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
FaqFourScenePage(device: device!)),
);
},
text: 'Device FAQ',
icon: Assets.faqIcon,
),
const Divider(
color: ColorsManager.dividerColor,
),
SettingWidget(
onTapUpdate: () {
showDialog(
context: context,
builder: (context) {
return UpdateInfoDialog(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context).pop();
},
);
},
);
},
isUpdate: true,
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
const FourSceneUpdatePage()),
);
},
text: 'Device Update',
icon: Assets.updateIcon,
),
],
),
),
const SizedBox(height: 20),
InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: ColorsManager.red,
),
const SizedBox(height: 10),
const SizedBox(
width: 250,
child: Divider(
color: ColorsManager.dividerColor,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectDeviceDialog(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context)
.pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Disconnect Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) {
return DisconnectWipeData(
cancelTab: () {
Navigator.of(context)
.pop();
},
confirmTab: () {
// context
// .read<
// CreateSceneBloc>()
// .add(DeleteSceneEvent(
// sceneId: sceneId,
// unitUuid: HomeCubit
// .getInstance()
// .selectedSpace!
// .id!,
// ));
Navigator.of(context)
.pop();
},
);
},
);
},
child: const BodyMedium(
text:
'Disconnect Device and Wipe Data',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager
.textPrimaryColor,
),
),
const Icon(
Icons.keyboard_arrow_right,
color: ColorsManager.textGray,
)
],
),
],
),
);
},
);
},
child: const Center(
child: BodyMedium(
text: 'Remove Device',
fontWeight: FontWeight.w400,
fontSize: 15,
fontColor: ColorsManager.red,
),
),
),
],
),
);
},
),
),
);
}
}
class SettingWidget extends StatelessWidget {
final String? text;
final bool? isUpdate;
final bool? isNotification;
final String? icon;
final Function()? onTap;
final Function()? onTapUpdate;
final Function(bool)? onChanged;
const SettingWidget(
{super.key,
this.text,
this.icon,
this.onTap,
this.isUpdate,
this.onChanged,
this.isNotification = false,
this.onTapUpdate});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
padding: EdgeInsets.all(8),
decoration: const BoxDecoration(
color: ColorsManager.primaryColor,
borderRadius: BorderRadius.all(Radius.circular(20))),
child: SvgPicture.asset(
icon!,
fit: BoxFit.none,
height: 30,
),
),
),
const SizedBox(
width: 8,
),
Expanded(
flex: isUpdate == true ? 5 : 10,
child: BodyMedium(
text: text!,
fontSize: 15,
fontWeight: FontWeight.w400,
)),
],
),
),
isUpdate == true
? InkWell(
onTap: onTapUpdate,
child: BodyMedium(
text: '1 Update Available',
fontSize: 13,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blueColor,
),
)
: SizedBox(),
isNotification == false
? const Icon(
Icons.arrow_forward_ios,
color: ColorsManager.graysColor,
size: 20,
)
: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: onChanged,
applyTheme: true,
),
),
],
),
);
}
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class UpdateInfoDialog extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const UpdateInfoDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
BodyLarge(
text: 'Update Available',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.switchButton.withOpacity(0.6),
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'An update is available for your device. Version 2.1.0 includes new features and important fixes to enhance performance and security.',
textAlign: TextAlign.center,
)),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Remind me later',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Update Now',
style: TextStyle(
color:
ColorsManager.switchButton.withOpacity(0.6),
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class upDateNote extends StatelessWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const upDateNote({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
Widget build(BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(
height: 10,
),
BodyLarge(
text: 'Update Note',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.switchButton.withOpacity(0.6),
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(
color: ColorsManager.textGray,
),
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 20, top: 15, bottom: 20),
child: Column(
children: [
Center(
child: Text(
'This update may take a long time. Make sure that the device is fully charged. The device will be unavailable during the update.',
textAlign: TextAlign.center,
)),
],
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: SizedBox(
child: InkWell(
onTap: cancelTab,
child: const Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textGray,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(
color: ColorsManager.textGray,
width: 0.5,
),
top: BorderSide(
color: ColorsManager.textGray,
width: 1.0,
),
)),
child: InkWell(
onTap: confirmTab,
child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Center(
child: Text(
'Start Update',
style: TextStyle(
color:
ColorsManager.switchButton.withOpacity(0.6),
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
)),
))
],
)
],
),
);
}
}

View File

@ -0,0 +1,345 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_setting/four_scene_update_note.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FourSceneUpdatePage extends StatelessWidget {
const FourSceneUpdatePage({super.key});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Update',
child: BlocProvider(
create: (context) =>
FourSceneBloc(fourSceneId: '')..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {},
child: Column(
children: [
// SizedBox(
// height: MediaQuery.of(context).size.height * 0.15,
// ),
DefaultContainer(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 50,
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: SizedBox(
width: 200,
child: Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: const BoxDecoration(
color: ColorsManager
.primaryColor,
borderRadius:
BorderRadius.all(
Radius.circular(50))),
child: SvgPicture.asset(
Assets.checkUpdateIcon,
fit: BoxFit.fill,
height: 25,
),
),
const SizedBox(
width: 10,
),
InkWell(
onTap: () {},
child: const BodyMedium(
text: 'Automatic Update',
fontWeight: FontWeight.normal,
),
),
],
),
),
trailing: Container(
width: 100,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
const BodyMedium(
text: 'Off',
fontColor: ColorsManager.textGray,
),
Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: (value) {},
applyTheme: true,
),
),
],
),
)),
),
],
),
),
const SizedBox(
height: 10,
),
UpdateSosContainerWithProgressBar(
sosDescription:
'Connectivity Issue Resolved Fixed a bug that caused the SOS button to disconnect from the app intermittently.',
sosVersion: 'SOS v2.0.5',
),
// const UpdatedContainer(
// sosVersion: 'SOS v1.0.13',
// sosDescription: 'SOS is up to date',
// ),
// const NewUpdateContainer(
// sosVersion: 'SOS v2.0.5',
// sosDescription:
// 'Connectivity Issue Resolved Fixed a bug that caused the SOS button to disconnect from the app intermittently.',
// ),
const SizedBox(
height: 15,
),
],
));
},
),
));
}
}
class UpdatedContainer extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const UpdatedContainer({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return DefaultContainer(
height: MediaQuery.of(context).size.height * 0.35,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.blackColor,
),
],
),
],
),
),
);
}
}
class NewUpdateContainer extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const NewUpdateContainer({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return DefaultContainer(
height: MediaQuery.of(context).size.height * 0.50,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
const BodyMedium(
text: 'New Update Available Now!',
fontColor: ColorsManager.blueColor,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
Container(
width: MediaQuery.of(context).size.width * 0.7,
child: BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.6,
child: DefaultButton(
borderRadius: 25,
backgroundColor: ColorsManager.blueColor1,
height: 150,
onPressed: () {
showDialog(
context: context,
builder: (context) {
return upDateNote(
cancelTab: () {
Navigator.of(context).pop();
},
confirmTab: () {
Navigator.of(context).pop();
},
);
},
);
},
child: const BodyMedium(
text: 'Update Now',
fontColor: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w700,
textAlign: TextAlign.center,
),
),
)
],
),
],
),
),
);
}
}
class UpdateSosContainerWithProgressBar extends StatelessWidget {
final String? sosVersion;
final String? sosDescription;
const UpdateSosContainerWithProgressBar({
this.sosVersion,
this.sosDescription,
super.key,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
DefaultContainer(
height: MediaQuery.of(context).size.height * 0.50,
child: Padding(
padding: const EdgeInsets.all(25),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SvgPicture.asset(
Assets.emptyUpdateIcon,
fit: BoxFit.fill,
),
BodyMedium(
text: 'New Update Available Now!',
fontColor: ColorsManager.blueColor,
),
BodyMedium(
text: sosVersion!,
fontColor: ColorsManager.primaryTextColor,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: BodyMedium(
text: sosDescription!,
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
LinearPercentIndicator(
barRadius: Radius.circular(10),
width: 170.0,
animation: true,
animationDuration: 1000,
lineHeight: 5.0,
percent: 0.2,
linearStrokeCap: LinearStrokeCap.butt,
progressColor: ColorsManager.blueColor1,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: const BodyMedium(
text: 'Downloading Update please be patient',
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
),
],
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.7,
child: const BodyMedium(
text:
'Please keep the power of the device connected during the upgrade process.',
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
],
);
}
}

View File

@ -0,0 +1,202 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import '../../../../bloc/four_scene_bloc/four_scene_event.dart';
class LocationFourScenePage extends StatefulWidget {
final SpaceModel? space;
LocationFourScenePage({super.key, this.space});
@override
_LocationFourScenePageState createState() => _LocationFourScenePageState();
}
class _LocationFourScenePageState extends State<LocationFourScenePage> {
String _selectedOption = 'Conference Room';
bool _hasSelectionChanged = false;
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Device Location',
actions: [
InkWell(
onTap: _hasSelectionChanged
? () {
print('Save button clicked');
}
: null,
child: BodyMedium(
text: 'Save',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: _hasSelectionChanged
? ColorsManager.slidingBlueColor
: ColorsManager.primaryTextColor,
),
),
const SizedBox(width: 20),
],
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: '')
..add(FetchRoomsEvent(unit: widget.space!)),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
List<SubSpaceModel>? rooms = [];
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is FetchRoomsState) {
rooms = state.roomsList;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 20),
children: [
const BodyMedium(
text: 'Smart Device Location',
fontWeight: FontWeight.w700,
fontSize: 12,
fontColor: ColorsManager.grayColor,
),
const SizedBox(height: 5),
DefaultContainer(
padding: const EdgeInsets.all(20),
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: rooms!.length,
itemBuilder: (context, index) {
final room = rooms![index];
return Column(
children: [
_buildCheckboxOption(
label: room.name!,
onTap: (v) {
setState(() {
_selectedOption = v;
_hasSelectionChanged = true;
});
},
),
if (index < rooms.length - 1) ...[
const SizedBox(height: 10),
const Divider(
color: ColorsManager.dividerColor,
),
const SizedBox(height: 10),
],
],
);
},
),
),
],
),
);
},
),
),
);
}
Widget _buildCheckboxOption(
{required String label, required Function(String) onTap}) {
return Padding(
padding: const EdgeInsets.only(bottom: 10, top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(
text: label,
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w400),
),
CircularCheckbox(
value: _selectedOption == label,
onChanged: (bool? value) {
if (value == true) {
setState(() {
_selectedOption = label;
_hasSelectionChanged = true;
});
onTap(label);
}
},
),
],
),
);
}
}
class CircularCheckbox extends StatefulWidget {
final bool value;
final ValueChanged<bool?> onChanged;
CircularCheckbox({required this.value, required this.onChanged});
@override
_CircularCheckboxState createState() => _CircularCheckboxState();
}
class _CircularCheckboxState extends State<CircularCheckbox> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
widget.onChanged(!widget.value);
},
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: widget.value
? ColorsManager.primaryColorWithOpacity.withOpacity(0.01)
: Colors.grey,
width: 2.0,
),
color: widget.value
? ColorsManager.primaryColorWithOpacity
: Colors.transparent,
),
width: 24.0,
height: 24.0,
child: widget.value
? const Icon(
Icons.check,
color: Colors.white,
size: 16.0,
)
: null,
),
);
}
}

View File

@ -0,0 +1,149 @@
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/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_question_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class QuestionPageFourScene extends StatelessWidget {
final FourSceneQuestionModel? questionModel;
const QuestionPageFourScene({super.key, this.questionModel});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'FAQ',
child: BlocProvider(
create: (context) =>
FourSceneBloc(fourSceneId: '')..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is FourSceneLoadingState
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: Column(
children: [
DefaultContainer(
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyLarge(
text: questionModel!.question,
fontSize: 22,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
SizedBox(
height: 15,
),
BodyMedium(
text: questionModel!.answer,
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.15,
),
Center(
child: SizedBox(
width: 180,
child: DefaultButton(
backgroundColor: ColorsManager.grayButtonColors,
borderRadius: 50,
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.thumbUp,
fit: BoxFit.fill,
),
SizedBox(
width: 10,
),
BodyMedium(
text: 'Helpful',
fontSize: 12,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
],
)),
),
),
SizedBox(
height: 15,
),
Center(
child: SizedBox(
width: 180,
child: DefaultButton(
backgroundColor: ColorsManager.grayButtonColors,
borderRadius: 50,
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.thumbDown,
fit: BoxFit.fill,
),
SizedBox(
width: 10,
),
BodyMedium(
text: 'Not Helpful',
fontSize: 12,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
],
)),
),
),
],
));
},
),
),
);
}
}

View File

@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/four_scene_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class ShareFourScenePage extends StatelessWidget {
final DeviceModel? device;
const ShareFourScenePage({super.key, this.device});
@override
Widget build(BuildContext context) {
return DefaultScaffold(
title: 'Share Device',
child: BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: device?.uuid ?? '')
..add(const FourSceneInitial()),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensor = BlocProvider.of<FourSceneBloc>(context);
FourSceneModel model = FourSceneModel(
scene_1: '',
scene_2: '',
scene_3: '',
scene_4: '',
scene_id_group_id: '',
switch_backlight: '');
if (state is LoadingNewSate) {
model = state.sosSensor;
} else if (state is UpdateState) {
model = state.sensor;
}
return state is LoadingNewSate
? const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator()),
)
: RefreshIndicator(
onRefresh: () async {
sensor.add(const FourSceneInitial());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BodyLarge(
text: 'Sharing Method Not Supported',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
const BodyMedium(
text:
'Currently, you cannot use the specified method to share Bluetooth mesh devices Zigbee devices, infrared devices, Bluetooth Beacon Devices, and certain Bluetooth LE devices with other users.',
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
const SizedBox(
height: 10,
),
const BodyLarge(
text: 'Recommended Sharing Method',
fontSize: 15,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.blackColor,
),
const BodyMedium(
text:
'If the recipient is a home member or a reliable user, tap Me > Home Management > Add Member and add the recipient to your home. Then, devices in the home can be shared with the recipient in bulk.',
fontSize: 14,
fontWeight: FontWeight.w400,
fontColor: ColorsManager.secondaryTextColor,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.15,
),
Center(
child: SizedBox(
width: 250,
child: DefaultButton(
backgroundColor: ColorsManager.blueColor1,
borderRadius: 50,
onPressed: () {},
child: Text('Add Home Member')),
),
)
],
));
},
),
),
);
}
}

View File

@ -0,0 +1,286 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.dart';
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FourSelectSceneFourPage extends StatelessWidget {
FourSelectSceneFourPage({super.key});
final TextEditingController _searchController = TextEditingController();
final int? selectedSwitchIndex = 0;
final spaces = HomeCubit.getInstance().spaces;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => FourSceneBloc(fourSceneId: '')
..add(LoadScenes(
unit: spaces!.first,
unitId: spaces!.first.id,
showInDevice: false,
)),
child: BlocBuilder<FourSceneBloc, FourSceneState>(
builder: (context, state) {
final sensorBloc = BlocProvider.of<FourSceneBloc>(context);
return DefaultScaffold(
title: 'Select Scene',
actions: [_buildSaveButton(context, state, sensorBloc)],
child: state is FourSceneLoadingState
? _buildLoadingIndicator()
: _buildSceneContent(context, sensorBloc),
);
},
),
);
}
// Save button builder
Widget _buildSaveButton(
BuildContext context, FourSceneState state, FourSceneBloc sensorBloc) {
final bool canSave =
state is OptionSelectedState && state.hasSelectionChanged;
return GestureDetector(
onTap: canSave
? () {
print('object');
context.read<FourSceneBloc>().add(SaveSelectionEvent());
}
: null,
child: BodyMedium(
text: 'Save',
fontWeight: FontWeight.w700,
fontSize: 16,
fontColor: canSave
? ColorsManager.slidingBlueColor
: ColorsManager.primaryTextColor,
),
);
}
// Loading indicator
Widget _buildLoadingIndicator() {
return const Center(
child: DefaultContainer(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
// Main scene content with search bar and grid
Widget _buildSceneContent(BuildContext context, FourSceneBloc sensorBloc) {
return Column(
children: [
_buildSearchBar(sensorBloc),
const SizedBox(height: 20),
Expanded(
child: _buildSceneGrid(sensorBloc),
),
],
);
}
// Search bar widget
Widget _buildSearchBar(FourSceneBloc sensorBloc) {
return TextFormField(
controller: _searchController,
onChanged: (value) {
sensorBloc.add(SearchScenesEvent(query: value));
},
decoration: InputDecoration(
hintText: 'Search',
hintStyle: const TextStyle(
color: ColorsManager.textGray,
fontSize: 16,
fontWeight: FontWeight.w400),
suffixIcon: Container(
padding: const EdgeInsets.all(5.0),
margin: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
Assets.searchIcon,
fit: BoxFit.contain,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
);
}
// Scene grid builder
Widget _buildSceneGrid(FourSceneBloc sensorBloc) {
final scenes = sensorBloc.filteredScenes;
return GridView.builder(
itemCount: scenes.length + 1,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
mainAxisExtent: 120,
),
itemBuilder: (context, index) {
if (index == scenes.length) {
return InkWell(
onTap: () => Navigator.pushNamed(
NavigationService.navigatorKey.currentContext!,
Routes.sceneTasksRoute,
arguments: SceneSettingsRouteArguments(
sceneType: '',
sceneId: '',
sceneName: '',
),
),
child: CreateSceneItem(),
);
} else {
final scene = scenes[index];
return SceneItem(
id: scene.id,
value: sensorBloc.selectedSceneId == scene.id,
disablePlayButton: false,
onChanged: (isSelected) {
sensorBloc.selectedSceneId = isSelected ? scene.id : 'null';
sensorBloc.add(SelectOptionEvent(selectedOption: scene.id));
},
icon: scene.iconInBytes,
title: scene.name,
);
}
},
);
}
}
class SceneItem extends StatefulWidget {
final String id; // Unique ID for each scene
final Uint8List icon;
final String title;
final bool disablePlayButton;
final bool value;
final Function(bool) onChanged;
const SceneItem({
required this.id,
required this.icon,
required this.title,
this.disablePlayButton = false,
required this.value,
required this.onChanged,
});
@override
State<SceneItem> createState() => _SceneItemState();
}
class _SceneItemState extends State<SceneItem> {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
spreadRadius: 1,
offset: Offset(0, 3),
),
],
),
padding: const EdgeInsets.all(16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!widget.disablePlayButton)
Image.memory(
widget.icon,
height: 32,
width: 32,
fit: BoxFit.fill,
errorBuilder: (context, error, stackTrace) => Image.asset(
Assets.assetsIconsLogo,
height: 32,
width: 32,
fit: BoxFit.fill),
),
BodyMedium(
text: widget.title,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w700,
color: ColorsManager.secondaryTextColor),
textAlign: TextAlign.center,
),
],
),
CircularCheckbox(
value: widget.value,
onChanged: (isSelected) => widget.onChanged(isSelected!),
),
],
),
);
}
}
// Widget for the static "Create Scene" button
class CreateSceneItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 5,
spreadRadius: 2,
offset: Offset(0, 3),
),
],
),
padding: const EdgeInsets.all(16),
child: const Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.add_circle,
color: ColorsManager.grayButtonColors, size: 36),
BodyMedium(
text: 'Create Scene',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: ColorsManager.secondaryTextColor),
textAlign: TextAlign.center,
),
],
),
);
}
}

View File

@ -0,0 +1,145 @@
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/devices/view/widgets/6_scene_switch/switches_card.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FourSelectSwitchDialog extends StatefulWidget {
final Function()? cancelTab;
final Function()? confirmTab;
const FourSelectSwitchDialog({
super.key,
required this.cancelTab,
required this.confirmTab,
});
@override
State<FourSelectSwitchDialog> createState() => _FourSelectSwitchDialogState();
}
class _FourSelectSwitchDialogState extends State<FourSelectSwitchDialog> {
int? selectedSwitchIndex = 0; // State variable to track selected switch
@override
Widget build(BuildContext context) {
return AlertDialog(
backgroundColor: ColorsManager.onPrimaryColor,
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 10),
const BodyLarge(
text: 'Select Switch',
fontWeight: FontWeight.w700,
fontColor: ColorsManager.primaryColor,
fontSize: 16,
),
const Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Divider(color: ColorsManager.textGray),
),
const SizedBox(height: 20),
Row(
children: [
SwitchsCard(
switch1Down: selectedSwitchIndex == -1
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch1Up: selectedSwitchIndex == 1
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch2Down: selectedSwitchIndex == -2
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
switch2Up: selectedSwitchIndex == 2
? Assets.removeSceneIcon
: Assets.addSwitchIcon,
onSwitch1UpTap: () {
setState(() => selectedSwitchIndex = 1);
},
onSwitch1DownTap: () {
setState(() => selectedSwitchIndex = -1);
},
onSwitch2UpTap: () {
setState(() => selectedSwitchIndex = 2);
},
onSwitch2DownTap: () {
setState(() => selectedSwitchIndex = -2);
},
),
],
),
const SizedBox(height: 20),
const Center(
child: Text(
'Please select one of the switches available to continue',
textAlign: TextAlign.center,
),
),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right:
BorderSide(color: ColorsManager.textGray, width: 0.5),
top: BorderSide(color: ColorsManager.textGray, width: 1.0),
)),
child: SizedBox(
child: InkWell(
onTap: widget.cancelTab,
child: const Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Cancel',
style: TextStyle(
color: ColorsManager.textPrimaryColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
left: BorderSide(color: ColorsManager.textGray, width: 0.5),
top: BorderSide(color: ColorsManager.textGray, width: 1.0),
)),
child: InkWell(
onTap: selectedSwitchIndex == 0 ? () {} : widget.confirmTab,
child: Padding(
padding: EdgeInsets.all(15),
child: Center(
child: Text(
'Next',
style: TextStyle(
color: selectedSwitchIndex == 0
? ColorsManager.textPrimaryColor
.withOpacity(0.6)
: ColorsManager.primaryColor,
fontSize: 14,
fontWeight: FontWeight.w400),
),
),
),
),
),
),
],
)
],
),
);
}
}

View File

@ -0,0 +1,131 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class FourSwitchsCard extends StatelessWidget {
final String switch1Up;
final String switch1Down;
final String switch2Up;
final String switch2Down;
final VoidCallback onSwitch1UpTap;
final VoidCallback onSwitch1DownTap;
final VoidCallback onSwitch2UpTap;
final VoidCallback onSwitch2DownTap;
FourSwitchsCard({
required this.switch1Down,
required this.switch1Up,
required this.switch2Down,
required this.switch2Up,
required this.onSwitch1UpTap,
required this.onSwitch1DownTap,
required this.onSwitch2UpTap,
required this.onSwitch2DownTap,
});
@override
Widget build(BuildContext context) {
return Expanded(
flex: 4,
child: InkWell(
overlayColor: MaterialStateProperty.all(Colors.transparent),
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: ColorsManager.onPrimaryColor,
boxShadow: [
BoxShadow(
color: Colors.white.withOpacity(0.1),
blurRadius: 24,
offset: const Offset(-2, -2),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.black.withOpacity(0.11),
blurRadius: 5,
offset: const Offset(2, 0),
blurStyle: BlurStyle.outer,
),
BoxShadow(
color: Colors.white.withOpacity(0.13),
blurRadius: 10,
offset: const Offset(5, 1),
blurStyle: BlurStyle.inner,
),
],
),
child: SizedBox(
height: 300,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildSwitchColumn(switch1Up, switch1Down, onSwitch1UpTap, onSwitch1DownTap),
_buildDivider(),
_buildSwitchColumn(switch2Up, switch2Down, onSwitch2UpTap, onSwitch2DownTap),
],
),
),
),
),
),
],
),
),
);
}
Widget _buildSwitchColumn(
String switchUp,
String switchDown,
VoidCallback onUpTap,
VoidCallback onDownTap,
) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 30, bottom: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: onUpTap,
child: Container(
height: 20,
width: 20,
child: SvgPicture.asset(switchUp),
),
),
InkWell(
onTap: onDownTap,
child: Container(
height: 20,
width: 20,
child: SvgPicture.asset(switchDown),
),
),
],
),
),
);
}
Widget _buildDivider() {
return Container(
width: 3,
color: ColorsManager.dividerColor,
);
}
}

View File

@ -10,6 +10,7 @@ import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_sensor_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/four_scene_switch/four_scene_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_door_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
@ -87,7 +88,6 @@ class RoomPageSwitch extends StatelessWidget {
///
/// The [device] parameter represents the device model.
void showDeviceInterface(DeviceModel device, BuildContext context) {
switch (device.productType) {
case DeviceType.AC:
Navigator.push(
@ -213,6 +213,13 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
pageBuilder: (context, animation1, animation2) =>
WaterLeakScreen(device: device)));
case DeviceType.FourScene:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
FourSceneScreen(device: device)));
break;
default:
}

View File

@ -3,7 +3,8 @@ class Assets {
/// Assets for assetsFontsAftikaRegular
/// assets/fonts/AftikaRegular.ttf
static const String assetsFontsAftikaRegular = "assets/fonts/AftikaRegular.ttf";
static const String assetsFontsAftikaRegular =
"assets/fonts/AftikaRegular.ttf";
/// Assets for assetsIcons3GangSwitch
/// assets/icons/3GangSwitch.svg
@ -19,82 +20,98 @@ class Assets {
/// Assets for assetsIconsAutomatedClock
/// assets/icons/automated_clock.svg
static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg";
static const String assetsIconsAutomatedClock =
"assets/icons/automated_clock.svg";
static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
static const String
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff
/// assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
"assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff
/// assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg
static const String assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
static const String
assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
"assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg";
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOnstlowpmdmOff
@ -104,37 +121,44 @@ class Assets {
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn
/// assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg
static const String assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
static const String
assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
"assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOnstlowpmdmOn
@ -144,37 +168,44 @@ class Assets {
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn
/// assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
"assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn
/// assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg
static const String assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
static const String
assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
"assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg";
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOnstlowpmdmOn
@ -218,7 +249,8 @@ class Assets {
static const String assetsIconsCurtainsIconVerticalBlade =
"assets/icons/curtainsIcon/left_vertical_blade.svg";
static const String rightVerticalBlade = "assets/icons/curtainsIcon/right_vertical_blade.svg";
static const String rightVerticalBlade =
"assets/icons/curtainsIcon/right_vertical_blade.svg";
/// Assets for assetsIconsDashboard
/// assets/icons/dashboard.svg
@ -228,7 +260,8 @@ class Assets {
/// Assets for assetsIconsDashboardFill
/// assets/icons/dashboard-fill.svg
static const String assetsIconsDashboardFill = "assets/icons/dashboard-fill.svg";
static const String assetsIconsDashboardFill =
"assets/icons/dashboard-fill.svg";
/// Assets for assetsIconsDevices
/// assets/icons/Devices.svg
@ -244,7 +277,8 @@ class Assets {
/// Assets for assetsIconsDoorLockLinkage
/// assets/icons/DoorLockLinkage.svg
static const String assetsIconsDoorLockLinkage = "assets/icons/DoorLockLinkage.svg";
static const String assetsIconsDoorLockLinkage =
"assets/icons/DoorLockLinkage.svg";
/// Assets for assetsIconsDoorLockLock
/// assets/icons/DoorLockLock.svg
@ -252,15 +286,18 @@ class Assets {
/// Assets for assetsIconsDoorLockMembers
/// assets/icons/DoorLockMembers.svg
static const String assetsIconsDoorLockMembers = "assets/icons/DoorLockMembers.svg";
static const String assetsIconsDoorLockMembers =
"assets/icons/DoorLockMembers.svg";
/// Assets for assetsIconsDoorLockPassword
/// assets/icons/DoorLockPassword.svg
static const String assetsIconsDoorLockPassword = "assets/icons/DoorLockPassword.svg";
static const String assetsIconsDoorLockPassword =
"assets/icons/DoorLockPassword.svg";
/// Assets for assetsIconsDoorLockRecords
/// assets/icons/DoorLockRecords.svg
static const String assetsIconsDoorLockRecords = "assets/icons/DoorLockRecords.svg";
static const String assetsIconsDoorLockRecords =
"assets/icons/DoorLockRecords.svg";
/// Assets for assetsIconsDoorlockAssetsBatteryIndicator
/// assets/icons/doorlock-assets/BatteryIndicator.svg
@ -281,7 +318,8 @@ class Assets {
/// assets/icons/doorlock-assets/lockIcon.svg
static const String assetsIconsDoorlockAssetsLockIcon =
"assets/icons/doorlock-assets/lockIcon.svg";
static const String doorUnlockIcon = "assets/icons/doorlock-assets/door_un_look_ic.svg";
static const String doorUnlockIcon =
"assets/icons/doorlock-assets/door_un_look_ic.svg";
/// Assets for assetsIconsDoorlockAssetsMembersManagement
/// assets/icons/doorlock-assets/members-management.svg
@ -369,11 +407,13 @@ class Assets {
/// Assets for assetsIconsLightSwitchOff
/// assets/icons/lightSwitchOff.svg
static const String assetsIconsLightSwitchOff = "assets/icons/lightSwitchOff.svg";
static const String assetsIconsLightSwitchOff =
"assets/icons/lightSwitchOff.svg";
/// Assets for assetsIconsLightSwitchOn
/// assets/icons/lightSwitchOn.svg
static const String assetsIconsLightSwitchOn = "assets/icons/lightSwitchOn.svg";
static const String assetsIconsLightSwitchOn =
"assets/icons/lightSwitchOn.svg";
/// Assets for assetsIconsLinkageIconsDoorLockAlarm
/// assets/icons/linkageIcons/doorLockAlarm.svg
@ -382,7 +422,8 @@ class Assets {
/// Assets for assetsIconsLinkTimeLimitedPasswordIcon
/// assets/icons/timeLimitedPasswordIcon.svg
static const String timeLimitedPasswordIcon = "assets/icons/timeLimitedPasswordIcon.svg";
static const String timeLimitedPasswordIcon =
"assets/icons/timeLimitedPasswordIcon.svg";
/// Assets for assetsIconsoneTimePassword
/// assets/icons/oneTimePassword.svg
@ -390,7 +431,8 @@ class Assets {
/// Assets for assetsIconsTimeLimitedPassword
/// assets/icons/timeLimitedPassword.svg
static const String timeLimitedPassword = "assets/icons/timeLimitedPassword.svg";
static const String timeLimitedPassword =
"assets/icons/timeLimitedPassword.svg";
/// Assets for assetsIconsNoValidPasswords
/// assets/icons/noValidPasswords.svg
@ -559,11 +601,13 @@ class Assets {
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/space_type_icon.svg
static const String spaceTypeIcon = "assets/icons/presence-sensor-assets/space_type_icon.svg";
static const String spaceTypeIcon =
"assets/icons/presence-sensor-assets/space_type_icon.svg";
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/space_type_icon.svg
static const String sensitivityIcon = "assets/icons/presence-sensor-assets/Sensitivity.svg";
static const String sensitivityIcon =
"assets/icons/presence-sensor-assets/Sensitivity.svg";
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
/// assets/icons/presence-sensor-assets/maximum_distance.svg
@ -596,7 +640,8 @@ class Assets {
/// Assets for assetsIconsRoutinesFill
/// assets/icons/Routines-fill.svg
static const String assetsIconsRoutinesFill = "assets/icons/Routines-fill.svg";
static const String assetsIconsRoutinesFill =
"assets/icons/Routines-fill.svg";
/// Assets for assetsIconsScan
/// assets/icons/Scan.svg
@ -628,7 +673,8 @@ class Assets {
/// Assets for assetsIconsSustainability
/// assets/icons/sustainability.svg
static const String assetsIconsSustainability = "assets/icons/sustainability.svg";
static const String assetsIconsSustainability =
"assets/icons/sustainability.svg";
/// Assets for assetsIconsUnlockingMethodsIconsFace
/// assets/icons/unlockingMethodsIcons/face.svg
@ -724,7 +770,8 @@ class Assets {
/// Assets for assetsImagesHorizintalBlade
/// assets/images/HorizintalBlade.png
static const String assetsImagesHorizintalBlade = "assets/images/HorizintalBlade.png";
static const String assetsImagesHorizintalBlade =
"assets/images/HorizintalBlade.png";
/// Assets for assetsImagesLogo
/// assets/images/Logo.svg
@ -732,7 +779,8 @@ class Assets {
/// Assets for assetsImagesLogoHorizontal
/// assets/images/logo_horizontal.png
static const String assetsImagesLogoHorizontal = "assets/images/logo_horizontal.png";
static const String assetsImagesLogoHorizontal =
"assets/images/logo_horizontal.png";
/// Assets for assetsImagesPause
/// assets/images/Pause.png
@ -762,7 +810,8 @@ class Assets {
/// assets/images/Window.png
static const String assetsImagesWindow = "assets/images/window_img.svg";
static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg";
static const String assetsSensitivityFunction =
"assets/icons/functions_icons/sensitivity.svg";
//assets/icons/functions_icons/sesitivity_operation_icon.svg
static const String assetsSensitivityOperationIcon =
@ -770,59 +819,73 @@ class Assets {
//assets/icons/functions_icons/ac_power.svg
static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg";
static const String assetsAcPower =
"assets/icons/functions_icons/ac_power.svg";
//assets/icons/functions_icons/ac_power_off.svg
static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg";
static const String assetsAcPowerOFF =
"assets/icons/functions_icons/ac_power_off.svg";
//assets/icons/functions_icons/child_lock.svg
static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg";
static const String assetsChildLock =
"assets/icons/functions_icons/child_lock.svg";
//assets/icons/functions_icons/cooling.svg
static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg";
static const String assetsFreezing =
"assets/icons/functions_icons/freezing.svg";
//assets/icons/functions_icons/fan_speed.svg
static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg";
static const String assetsFanSpeed =
"assets/icons/functions_icons/fan_speed.svg";
//assets/icons/functions_icons/ac_cooling.svg
static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg";
static const String assetsAcCooling =
"assets/icons/functions_icons/ac_cooling.svg";
//assets/icons/functions_icons/ac_heating.svg
static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg";
static const String assetsAcHeating =
"assets/icons/functions_icons/ac_heating.svg";
//assets/icons/functions_icons/celsius_degrees.svg
static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg";
static const String assetsCelsiusDegrees =
"assets/icons/functions_icons/celsius_degrees.svg";
//assets/icons/functions_icons/tempreture.svg
static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg";
static const String assetsTempreture =
"assets/icons/functions_icons/tempreture.svg";
//assets/icons/functions_icons/ac_fan_low.svg
static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg";
static const String assetsAcFanLow =
"assets/icons/functions_icons/ac_fan_low.svg";
//assets/icons/functions_icons/ac_fan_middle.svg
static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg";
static const String assetsAcFanMiddle =
"assets/icons/functions_icons/ac_fan_middle.svg";
//assets/icons/functions_icons/ac_fan_high.svg
static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg";
static const String assetsAcFanHigh =
"assets/icons/functions_icons/ac_fan_high.svg";
//assets/icons/functions_icons/ac_fan_auto.svg
static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg";
static const String assetsAcFanAuto =
"assets/icons/functions_icons/ac_fan_auto.svg";
//assets/icons/functions_icons/scene_child_lock.svg
static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg";
static const String assetsSceneChildLock =
"assets/icons/functions_icons/scene_child_lock.svg";
//assets/icons/functions_icons/scene_child_unlock.svg
@ -831,15 +894,18 @@ class Assets {
//assets/icons/functions_icons/scene_refresh.svg
static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg";
static const String assetsSceneRefresh =
"assets/icons/functions_icons/scene_refresh.svg";
//assets/icons/functions_icons/light_countdown.svg
static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg";
static const String assetsLightCountdown =
"assets/icons/functions_icons/light_countdown.svg";
//assets/icons/functions_icons/far_detection.svg
static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg";
static const String assetsFarDetection =
"assets/icons/functions_icons/far_detection.svg";
//assets/icons/functions_icons/far_detection_function.svg
@ -848,11 +914,13 @@ class Assets {
//assets/icons/functions_icons/indicator.svg
static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg";
static const String assetsIndicator =
"assets/icons/functions_icons/indicator.svg";
//assets/icons/functions_icons/motion_detection.svg
static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg";
static const String assetsMotionDetection =
"assets/icons/functions_icons/motion_detection.svg";
//assets/icons/functions_icons/motionless_detection.svg
@ -861,15 +929,18 @@ class Assets {
//assets/icons/functions_icons/nobody_time.svg
static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg";
static const String assetsNobodyTime =
"assets/icons/functions_icons/nobody_time.svg";
//assets/icons/functions_icons/factory_reset.svg
static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg";
static const String assetsFactoryReset =
"assets/icons/functions_icons/factory_reset.svg";
//assets/icons/functions_icons/master_state.svg
static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg";
static const String assetsMasterState =
"assets/icons/functions_icons/master_state.svg";
//assets/icons/functions_icons/switch_alarm_sound.svg
@ -878,7 +949,8 @@ class Assets {
//assets/icons/functions_icons/reset_off.svg
static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg";
static const String assetsResetOff =
"assets/icons/functions_icons/reset_off.svg";
//assets/icons/functions_icons/automation_functions/card_unlock.svg
@ -952,7 +1024,8 @@ class Assets {
//assets/icons/functions_icons/automation_functions/motion.svg
static const String assetsMotion = "assets/icons/functions_icons/automation_functions/motion.svg";
static const String assetsMotion =
"assets/icons/functions_icons/automation_functions/motion.svg";
//assets/icons/functions_icons/automation_functions/current_temp.svg
@ -974,27 +1047,33 @@ class Assets {
static const String waterHeaterOn = "assets/icons/water_heater_on.svg";
static const String waterHeaterOff = "assets/icons/water_heater_off.svg";
static const String scheduleCelenderIcon = "assets/icons/schedule_celender_icon.svg";
static const String scheduleCirculateIcon = "assets/icons/schedule_circulate_icon.svg";
static const String scheduleInchingIcon = "assets/icons/schedule_Inching_icon.svg";
static const String scheduleCelenderIcon =
"assets/icons/schedule_celender_icon.svg";
static const String scheduleCirculateIcon =
"assets/icons/schedule_circulate_icon.svg";
static const String scheduleInchingIcon =
"assets/icons/schedule_Inching_icon.svg";
static const String scheduleTimeIcon = "assets/icons/schedule_time_icon.svg";
static const String waterHeaterIcon = "assets/icons/water_heater_icon.svg";
static const String doorOpen = "assets/icons/opened_door.svg";
static const String doorClose = "assets/icons/closed_door.svg";
static const String doorNotificationSetting = "assets/icons/door_notification_setting_icon.svg";
static const String doorNotificationSetting =
"assets/icons/door_notification_setting_icon.svg";
static const String doorRecordsIcon = "assets/icons/door_records_icon.svg";
static const String doorSensorIcon = "assets/icons/door_sensor_icon.svg";
static const String closedGarageIcon = "assets/icons/closed_garage_door.svg";
static const String openGarageIcon = "assets/icons/open_garage_door.svg";
static const String garageCountdown = "assets/icons/garage_countdown.svg";
static const String garagePreferencesIcon = "assets/icons/garage_preferences_icon.svg";
static const String garagePreferencesIcon =
"assets/icons/garage_preferences_icon.svg";
static const String garageSchedule = "assets/icons/garage_schedule.svg";
static const String garageIcon = "assets/icons/garageIcon.svg";
static const String normalWaterLeak = "assets/icons/normal_water_leak.svg";
static const String detectedWaterLeak = "assets/icons/detected_water_leak.svg";
static const String detectedWaterLeak =
"assets/icons/detected_water_leak.svg";
static const String waterLeakIcon = "assets/icons/waterleak_icon.svg";
static const String leakDetectedIcon = "assets/icons/leak_detected.svg";
@ -1012,5 +1091,32 @@ class Assets {
static const String powerClampIcon = "assets/icons/power_clamp.svg";
static const String automationIcon = "assets/icons/automation_ic.svg";
static const String redSos = "assets/icons/red_sos.svg";
static const String greenSos = "assets/icons/green_sos.svg";
static const String emptyLog = "assets/icons/empty_log.svg";
static const String sosProfileIcon = "assets/icons/sos_profile_icon.svg";
static const String sosEditProfile = "assets/icons/edit_sos_icon.svg";
static const String thumbUp = "assets/icons/thumb_up.svg";
static const String thumbDown = "assets/icons/thumb_down.svg";
static const String shareIcon = "assets/icons/share_icon.svg";
static const String infoIcon = "assets/icons/info.svg";
static const String notificationIcon = "assets/icons/notification_icon.svg";
static const String faqIcon = "assets/icons/faq_icon.svg";
static const String updateIcon = "assets/icons/update_icon.svg";
static const String emptyUpdateIcon = "assets/icons/empty_update_icon.svg";
static const String checkUpdateIcon = "assets/icons/check_update_icon.svg";
static const String switchOn = "assets/icons/switch_on.svg";
static const String switchOff = "assets/icons/switch_off.svg";
static const String backlightIcon = "assets/icons/backlight_icon.svg";
static const String addSwitchIcon = "assets/icons/add_switch_icon.svg";
static const String addSceneIcon = "assets/icons/add_scene_icon.svg";
static const String removeSceneIcon = "assets/icons/remove_scene_icon.svg";
static const String tapRunIcon = "assets/icons/tap_run_icon.svg";
static const String createGroupIcon = "assets/icons/create_group_icon.svg";
static const String sixSceneIcon = "assets/icons/six_scene_icon.svg";
static const String minusIcon = "assets/icons/minus_icon.svg";
static const String addDevicesIcon = "assets/icons/add_devices_icon.svg";
//powerClampIcon
}

View File

@ -65,7 +65,7 @@ class DevicesAPI {
showServerMessage: false,
expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json),
);
return response;
}
@ -75,6 +75,7 @@ class DevicesAPI {
.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
print('json==#$json');
return json;
},
);
@ -121,6 +122,16 @@ class DevicesAPI {
return response;
}
static Future getDeviceInfo(String deviceId) async {
final response = await _httpService.get(
path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
});
return response;
}
static Future<List<DeviceModel>> getDeviceByGroupName(
String unitId, String groupName) async {
final response = await _httpService.get(

View File

@ -31,5 +31,8 @@ abstract class ColorsManager {
static const Color switchButton = Color(0xff023DFE);
static const Color grayBox = Color(0xffF5F5F5);
static const Color chart = Color(0xff023DFE);
static const Color blueColor = Color(0xff5481F3);
static const Color blueColor1 = Color(0xff0A7AFF);
static const Color grayButtonColors = Color(0xffCCCCCC);
}
//background: #F5F5F5;023DFE

View File

@ -56,6 +56,7 @@ enum DeviceType {
GarageDoor,
WaterLeak,
PC,
FourScene,
Other,
}
@ -88,11 +89,14 @@ Map<String, DeviceType> devicesTypesMap = {
"GD": DeviceType.GarageDoor,
"WL": DeviceType.WaterLeak,
"PC": DeviceType.PC,
"4S": DeviceType.FourScene,
};
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
DeviceType.AC: [
FunctionModel(
code: 'switch', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'mode',
type: functionTypesMap['Enum'],
@ -115,7 +119,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
// "range": ["low", "middle", "high", "auto"]
})),
FunctionModel(
code: 'child_lock', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'child_lock',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
],
DeviceType.Gateway: [
FunctionModel(
@ -129,7 +135,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
"range": ["normal", "alarm"]
})),
FunctionModel(
code: 'factory_reset', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'factory_reset',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'alarm_active',
type: functionTypesMap['String'],
@ -139,7 +147,8 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
FunctionModel(
code: 'sensitivity',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
],
DeviceType.DoorLock: [
FunctionModel(
@ -147,7 +156,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'remote_no_dp_key', type: functionTypesMap['Raw'], values: ValueModel.fromJson({})),
code: 'remote_no_dp_key',
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'normal_open_switch',
type: functionTypesMap['Boolean'],
@ -157,64 +168,87 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
FunctionModel(
code: 'far_detection',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
values: ValueModel.fromJson(
{"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
FunctionModel(
code: 'presence_time',
type: functionTypesMap['Integer'],
values:
ValueModel.fromJson({"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
FunctionModel(
code: 'motion_sensitivity_value',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
FunctionModel(
code: 'motionless_sensitivity',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
FunctionModel(
code: 'indicator', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'indicator',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
],
DeviceType.OneGang: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
],
DeviceType.TwoGang: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_2',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_2',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
],
DeviceType.ThreeGang: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_2',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_3', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_3',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_2',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_3',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
],
DeviceType.Curtain: [
FunctionModel(
@ -226,15 +260,19 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
FunctionModel(
code: 'percent_control',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})),
],
DeviceType.WH: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'relay_status',
type: functionTypesMap['Enum'],
@ -258,7 +296,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
],
DeviceType.DS: [
FunctionModel(
code: 'doorcontact_state', type: functionTypesMap['Raw'], values: ValueModel.fromJson({})),
code: 'doorcontact_state',
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'battery_percentage',
type: functionTypesMap['Integer'],
@ -266,11 +306,14 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
],
DeviceType.OneTouch: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'relay_status',
type: functionTypesMap['Enum'],
@ -292,17 +335,23 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
],
DeviceType.TowTouch: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_2',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_2',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'relay_status',
type: functionTypesMap['Enum'],
@ -330,23 +379,32 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
],
DeviceType.ThreeTouch: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_2',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_3', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_3',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_2',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_3',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
FunctionModel(
code: 'relay_status',
type: functionTypesMap['Enum'],
@ -380,19 +438,24 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
],
DeviceType.GarageDoor: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
FunctionModel(
code: 'tr_timecon',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_alarm',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
FunctionModel(
code: 'door_control_1',
type: functionTypesMap['Enum'],
@ -413,19 +476,24 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
DeviceType.WaterLeak: [],
DeviceType.PC: [
FunctionModel(
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
code: 'switch_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'countdown_1',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
FunctionModel(
code: 'tr_timecon',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
FunctionModel(
code: 'countdown_alarm',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
values: ValueModel.fromJson(
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
FunctionModel(
code: 'door_control_1',
type: functionTypesMap['Enum'],
@ -443,6 +511,40 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
"range": ["unclosed_time", "close_time_alarm", "none"]
})),
],
DeviceType.FourScene: [
FunctionModel(
code: 'scene_1',
type: functionTypesMap['Boolean'],
values: ValueModel.fromJson({
"range": ["scene"]
})),
FunctionModel(
code: 'scene_2',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({
"range": ["scene"]
})),
FunctionModel(
code: 'scene_3',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({
"range": ["scene"]
})),
FunctionModel(
code: 'scene_4',
type: functionTypesMap['Integer'],
values: ValueModel.fromJson({
"range": ["scene"]
})),
FunctionModel(
code: 'scene_id_group_id',
type: functionTypesMap['Raw'],
values: ValueModel.fromJson({})),
FunctionModel(
code: 'switch_backlight',
type: functionTypesMap['Enum'],
values: ValueModel.fromJson({})),
]
};
enum TempModes { hot, cold, wind }
@ -588,7 +690,11 @@ List<Map<String, Object>> menuSections = [
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsMessages,
'page': null
},
{'title': 'FAQs', 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs, 'page': null},
{
'title': 'FAQs',
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs,
'page': null
},
{
'title': 'Help & Feedback',
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsHelpAndFeedback,
@ -618,7 +724,11 @@ List<Map<String, Object>> menuSections = [
'title': 'Legal Information',
'color': const Color(0xFF001B72),
'buttons': [
{'title': 'About', 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout, 'page': null},
{
'title': 'About',
'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout,
'page': null
},
{
'title': 'Privacy Policy',
'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsPrivacyPolicy,