From 8871fd8b108a5c86a9c9a8f860dfe8452d9a63fa Mon Sep 17 00:00:00 2001 From: Guy Luz Date: Sat, 6 Jan 2024 16:16:21 +0200 Subject: [PATCH] Added TTS and open URL support --- lib/domain/device/i_device_repository.dart | 19 - lib/infrastructure/device_repository.dart | 94 +---- .../molecules/devices/smart_tv_molecule.dart | 134 ++++++- lib/presentation/molecules/scenes_grid.dart | 10 +- .../organisms/devices_list_view.dart | 2 +- lib/presentation/pages/add_action_page.dart | 270 +++++++------- .../pages/add_scene/add_scene_page.dart | 244 ++++++------ .../choose_automation_type_to_add_page.dart | 350 +++++++++--------- .../pages/home_page/home_page.dart | 135 ++++++- .../scenes_in_folders_tab.dart | 78 +--- .../areas_widgets/areas_list_view_widget.dart | 8 +- .../entities_by_area_tab.dart | 191 ++-------- lib/presentation/pages/plus_button.dart | 154 ++++---- 13 files changed, 806 insertions(+), 883 deletions(-) diff --git a/lib/domain/device/i_device_repository.dart b/lib/domain/device/i_device_repository.dart index 4135abef..537a9357 100644 --- a/lib/domain/device/i_device_repository.dart +++ b/lib/domain/device/i_device_repository.dart @@ -62,12 +62,6 @@ abstract interface class IDeviceRepository { DeviceEntityBase deviceEntity, ); - /// Update document in the database in the following fields - Future> updateDatabase({ - required Map documentPath, - required Map fieldsToUpdate, - }); - Future> updateWithDeviceEntity({ required DeviceEntityBase deviceEntity, }); @@ -115,11 +109,6 @@ abstract interface class IDeviceRepository { required List? devicesId, }); - Future> openUrlOnDevices({ - required List? devicesId, - required String url, - }); - Future> closeStateDevices({ required List? devicesId, }); @@ -132,10 +121,6 @@ abstract interface class IDeviceRepository { required List? devicesId, }); - Future> skipVideoDevices({ - required List? devicesId, - }); - Future> changeVolumeDevices({ required List? devicesId, }); @@ -148,10 +133,6 @@ abstract interface class IDeviceRepository { required List? devicesId, }); - Future> delete( - DeviceEntityBase deviceEntity, - ); - BehaviorSubject> allResponseFromTheHubStreamController = BehaviorSubject>(); diff --git a/lib/infrastructure/device_repository.dart b/lib/infrastructure/device_repository.dart index 1a41c9f0..f2da2154 100644 --- a/lib/infrastructure/device_repository.dart +++ b/lib/infrastructure/device_repository.dart @@ -251,44 +251,11 @@ class _DeviceRepository implements IDeviceRepository { } } - @override - Future> updateDatabase({ - required Map documentPath, - required Map fieldsToUpdate, - String? forceUpdateLocation, - }) async { - try { - // await documentPath.update(fieldsToUpdate); - return right(unit); - } on PlatformException catch (e) { - if (e.message!.contains('NOT_FOUND')) { - return left(const DevicesFailure.unableToUpdate()); - } else { - // log.error(e.toString()); - return left(const DevicesFailure.unexpected()); - } - } - } - @override Future> updateWithDeviceEntity({ required DeviceEntityBase deviceEntity, }) async { - const String updateLocation = 'L'; - - try { - if (updateLocation == 'L') { - return updateComputer(deviceEntity); - } - return updateRemoteDB(deviceEntity); - } on PlatformException catch (e) { - if (e.message!.contains('NOT_FOUND')) { - return left(const DevicesFailure.unableToUpdate()); - } else { - // log.error(e.toString()); - return left(const DevicesFailure.unexpected()); - } - } + return left(const DevicesFailure.unexpected()); } @override @@ -852,44 +819,6 @@ class _DeviceRepository implements IDeviceRepository { throw UnimplementedError(); } - @override - Future> openUrlOnDevices({ - required List? devicesId, - required String url, - }) async { - final List deviceEntityListToUpdate = - await getDeviceEntityListFromId(devicesId!); - - try { - for (final DeviceEntityBase? deviceEntity in deviceEntityListToUpdate) { - if (deviceEntity == null) { - continue; - } - if (deviceEntity is GenericSmartTvDE) { - deviceEntity.openUrl = GenericSmartTvOpenUrl(url); - } else { - logger.w( - 'Open url action not supported for' - ' ${deviceEntity.entityTypes.getOrCrash()} type', - ); - continue; - } - - updateWithDeviceEntity(deviceEntity: deviceEntity); - } - } on PlatformException catch (e) { - if (e.message!.contains('PERMISSION_DENIED')) { - return left(const DevicesFailure.insufficientPermission()); - } else if (e.message!.contains('NOT_FOUND')) { - return left(const DevicesFailure.unableToUpdate()); - } else { - // log.error(e.toString()); - return left(const DevicesFailure.unexpected()); - } - } - return right(unit); - } - @override Future> closeStateDevices({ List? devicesId, @@ -1085,27 +1014,6 @@ class _DeviceRepository implements IDeviceRepository { return right(unit); } - @override - Future> skipVideoDevices({ - required List? devicesId, - }) async { - // TODO: implement skipVideoDevices - throw UnimplementedError(); - } - - @override - Future> delete( - DeviceEntityBase deviceEntity, - ) async { - return left(const DevicesFailure.unexpected()); - } - - Future> updateRemoteDB( - DeviceEntityBase deviceEntity, - ) async { - return left(const DevicesFailure.unexpected()); - } - Future> updateComputer( DeviceEntityBase deviceEntity, ) async { diff --git a/lib/presentation/molecules/devices/smart_tv_molecule.dart b/lib/presentation/molecules/devices/smart_tv_molecule.dart index 74b005cf..52429214 100644 --- a/lib/presentation/molecules/devices/smart_tv_molecule.dart +++ b/lib/presentation/molecules/devices/smart_tv_molecule.dart @@ -103,7 +103,11 @@ class _SmartTvMoleculeState extends State { ); } - void playVideo(String url) { + void openUrl(String? url) { + if (url == null) { + return; + } + FlushbarHelper.createLoading( message: 'Open the url', linearProgressIndicator: const LinearProgressIndicator(), @@ -111,14 +115,30 @@ class _SmartTvMoleculeState extends State { setEntityState( EntityProperties.openUrl, - EntityActions.open, + EntityActions.openUrl, value: HashMap.from({ActionValues.url: url}), ); } + void sendTtl(String? text) { + if (text == null) { + return; + } + + FlushbarHelper.createLoading( + message: 'Send tts text', + linearProgressIndicator: const LinearProgressIndicator(), + ).show(context); + + setEntityState( + EntityProperties.speekers, + EntityActions.speek, + value: HashMap.from({ActionValues.text: text}), + ); + } + void openUrlPopUp() { - String url = - 'http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4'; + String? url; showDialog( context: context, @@ -149,7 +169,6 @@ class _SmartTvMoleculeState extends State { Container( padding: const EdgeInsets.all(8.0), child: TextFormField( - initialValue: url, onChanged: (textInUrl) { url = textInUrl; }, @@ -167,7 +186,77 @@ class _SmartTvMoleculeState extends State { child: ElevatedButton( onPressed: () { Navigator.pop(context); - playVideo(url); + openUrl(url); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.black, + // fixedSize: Size(250, 50), + ), + child: const TextAtom( + "Submit", + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); + } + + void ttsPopUp() { + String? text = 'Welcome Home'; + + showDialog( + context: context, + builder: (context) { + return AlertDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular( + 20.0, + ), + ), + ), + contentPadding: const EdgeInsets.only( + top: 10.0, + ), + title: const TextAtom( + 'Text To Speech', + style: TextStyle(fontSize: 24.0), + ), + content: SizedBox( + height: 400, + child: SingleChildScrollView( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.all(8.0), + child: TextFormField( + initialValue: 'Welcome Home', + onChanged: (textInUrl) { + text = textInUrl; + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + hintText: 'Enter TTS here', + labelText: 'Text', + ), + ), + ), + Container( + width: double.infinity, + height: 60, + padding: const EdgeInsets.all(8.0), + child: ElevatedButton( + onPressed: () { + Navigator.pop(context); + sendTtl(text); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.black, @@ -308,11 +397,40 @@ class _SmartTvMoleculeState extends State { onPressed: openUrlPopUp, child: Tab( icon: FaIcon( - FontAwesomeIcons.video, + FontAwesomeIcons.globe, + color: Theme.of(context).textTheme.bodyLarge!.color, + ), + child: TextAtom( + 'Open URL', + style: TextStyle( + color: Theme.of(context).textTheme.bodyLarge!.color, + fontSize: 16, + ), + ), + ), + ), + const SeparatorAtom(), + TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Colors.grey, + ), + side: MaterialStateProperty.all( + BorderSide.lerp( + const BorderSide(color: Colors.white60), + const BorderSide(color: Colors.white60), + 22, + ), + ), + ), + onPressed: ttsPopUp, + child: Tab( + icon: FaIcon( + FontAwesomeIcons.globe, color: Theme.of(context).textTheme.bodyLarge!.color, ), child: TextAtom( - 'Video', + 'TTS', style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, fontSize: 16, diff --git a/lib/presentation/molecules/scenes_grid.dart b/lib/presentation/molecules/scenes_grid.dart index 4ad77696..131fbb10 100644 --- a/lib/presentation/molecules/scenes_grid.dart +++ b/lib/presentation/molecules/scenes_grid.dart @@ -18,19 +18,19 @@ class _ScenesGridState extends State { Widget build(BuildContext context) { final Size screenSize = MediaQuery.of(context).size; + final ThemeData themeData = Theme.of(context); + final TextTheme textTheme = themeData.textTheme; + int gridCrossAxisCount = 2; if (screenSize.width > 700) { gridCrossAxisCount = 4; } if (widget.scenes.isEmpty) { - return const Center( + return Center( child: TextAtom( 'You can add automations in the plus button', - style: TextStyle( - fontSize: 18, - color: Colors.black, - ), + style: textTheme.bodyLarge, ), ); } diff --git a/lib/presentation/organisms/devices_list_view.dart b/lib/presentation/organisms/devices_list_view.dart index 74762b4f..98811f2c 100644 --- a/lib/presentation/organisms/devices_list_view.dart +++ b/lib/presentation/organisms/devices_list_view.dart @@ -51,7 +51,7 @@ class DevicesListView extends StatelessWidget { geEntitiesByType(); return ListViewMolecule( - ListViewVeriant.builder, + ListViewVeriant.separated, shrinkWrap: true, itemBuilder: (context, index) { final EntityTypes type = entitiesByType.keys.elementAt(index); diff --git a/lib/presentation/pages/add_action_page.dart b/lib/presentation/pages/add_action_page.dart index 2598f1d9..61b19e62 100644 --- a/lib/presentation/pages/add_action_page.dart +++ b/lib/presentation/pages/add_action_page.dart @@ -4,10 +4,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:cbj_integrations_controller/integrations_controller.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; import 'package:cybearjinni/presentation/core/snack_bar_service.dart'; -import 'package:cybearjinni/presentation/molecules/molecules.dart'; +import 'package:cybearjinni/presentation/organisms/organisms.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:hexcolor/hexcolor.dart'; @RoutePage() class AddActionPage extends StatefulWidget { @@ -44,155 +42,145 @@ class _AddActionPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - TopBarMolecule( - pageName: 'Add Action', - leftIcon: FontAwesomeIcons.arrowLeft, - leftIconFunction: (_) => context.router.pop(), - ), - SingleChildScrollView( - child: Container( - color: HexColor('#3A3A3A'), - margin: const EdgeInsets.symmetric(horizontal: 10), - child: Column( + return PageOrganism( + pageName: 'Add Action', + child: SingleChildScrollView( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + children: [ + const SizedBox( + height: 30, + ), + const SizedBox( + height: 70, + ), + const Row( children: [ - const SizedBox( - height: 30, + TextAtom( + 'Choose Action', + style: TextStyle(fontSize: 27), ), - const SizedBox( - height: 70, - ), - const Row( - children: [ - TextAtom( - 'Choose Action', - style: TextStyle(fontSize: 27), - ), - ], - ), - DropdownButton( - dropdownColor: Colors.black, - style: const TextStyle(color: Colors.white), - icon: const Icon(Icons.arrow_drop_down), - hint: TextAtom( - selectedEntity?.cbjEntityName.getOrCrash() ?? - 'Choose Entity', - style: const TextStyle(color: Colors.white), - ), - elevation: 16, - underline: Container( - height: 2, - ), - onChanged: (value) => onEntitySelect(value!), - items: widget.entities.values + ], + ), + DropdownButton( + dropdownColor: Colors.black, + style: const TextStyle(color: Colors.white), + icon: const Icon(Icons.arrow_drop_down), + hint: TextAtom( + selectedEntity?.cbjEntityName.getOrCrash() ?? 'Choose Entity', + style: const TextStyle(color: Colors.white), + ), + elevation: 16, + underline: Container( + height: 2, + ), + onChanged: (value) => onEntitySelect(value!), + items: + widget.entities.values.map>((e) { + return DropdownMenuItem( + value: e.getCbjDeviceId, + child: TextAtom(e.cbjEntityName.getOrCrash()!), + ); + }).toList(), + ), + const SizedBox( + height: 40, + ), + DropdownButton( + dropdownColor: Colors.black, + style: const TextStyle(color: Colors.white), + icon: const Icon(Icons.arrow_drop_down), + hint: TextAtom( + selectedProperty?.name ?? 'Select Property', + style: const TextStyle(color: Colors.white), + ), + elevation: 16, + underline: Container( + height: 2, + ), + onChanged: (value) => _onPropertySelected(value!), + items: selectedEntity + ?.getListOfPropertiesToChange() .map>((e) { return DropdownMenuItem( - value: e.getCbjDeviceId, - child: TextAtom(e.cbjEntityName.getOrCrash()!), + value: e.index.toString(), + child: TextAtom(e.name), ); - }).toList(), - ), - const SizedBox( - height: 40, - ), - DropdownButton( - dropdownColor: Colors.black, - style: const TextStyle(color: Colors.white), - icon: const Icon(Icons.arrow_drop_down), - hint: TextAtom( - selectedProperty?.name ?? 'Select Property', - style: const TextStyle(color: Colors.white), - ), - elevation: 16, - underline: Container( - height: 2, - ), - onChanged: (value) => _onPropertySelected(value!), - items: selectedEntity - ?.getListOfPropertiesToChange() - .map>((e) { - return DropdownMenuItem( - value: e.index.toString(), - child: TextAtom(e.name), - ); - }).toList() ?? - >[ - const DropdownMenuItem( - value: 'Choose entity first', - child: TextAtom('Choose entity first'), - ), - ], - ), - const SizedBox( - height: 40, - ), - DropdownButton( - dropdownColor: Colors.black, - style: const TextStyle(color: Colors.white), - icon: const Icon(Icons.arrow_drop_down), - hint: TextAtom( - selectedAction?.name ?? 'Choose Action', - style: const TextStyle(color: Colors.white), - ), - elevation: 16, - underline: Container( - height: 2, - ), - onChanged: (value) => onActionSelected(value!), - items: (selectedProperty != null && - selectedProperty!.getActions.isNotEmpty) - ? selectedProperty!.getActions - .map>((e) { - return DropdownMenuItem( - value: e.index.toString(), - child: TextAtom(e.name), - ); - }).toList() - : const >[ - DropdownMenuItem( - value: 'Choose property first', - child: TextAtom('Choose property first'), - ), - ], - ), - const SizedBox( - height: 70, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - SnackBarService().show(context, 'Add action'); - if (selectedEntity == null || - selectedProperty == null || - selectedAction == null) { - return; - } - final EntityActionObject entityActionObject = - EntityActionObject( - entity: selectedEntity!, - property: selectedProperty!, - action: selectedAction!, - ); - // TODO: Add pop - context.router - .pop(entityActionObject); - }, - child: const TextAtom( - 'Done', - style: TextStyle(fontSize: 20), - ), + }).toList() ?? + >[ + const DropdownMenuItem( + value: 'Choose entity first', + child: TextAtom('Choose entity first'), ), ], + ), + const SizedBox( + height: 40, + ), + DropdownButton( + dropdownColor: Colors.black, + style: const TextStyle(color: Colors.white), + icon: const Icon(Icons.arrow_drop_down), + hint: TextAtom( + selectedAction?.name ?? 'Choose Action', + style: const TextStyle(color: Colors.white), + ), + elevation: 16, + underline: Container( + height: 2, + ), + onChanged: (value) => onActionSelected(value!), + items: (selectedProperty != null && + selectedProperty!.getActions.isNotEmpty) + ? selectedProperty!.getActions + .map>((e) { + return DropdownMenuItem( + value: e.index.toString(), + child: TextAtom(e.name), + ); + }).toList() + : const >[ + DropdownMenuItem( + value: 'Choose property first', + child: TextAtom('Choose property first'), + ), + ], + ), + const SizedBox( + height: 70, + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + SnackBarService().show(context, 'Add action'); + if (selectedEntity == null || + selectedProperty == null || + selectedAction == null) { + return; + } + final EntityActionObject entityActionObject = + EntityActionObject( + entity: selectedEntity!, + property: selectedProperty!, + action: selectedAction!, + ); + // TODO: Add pop + context.router + .pop(entityActionObject); + }, + child: const TextAtom( + 'Done', + style: TextStyle(fontSize: 20), + ), ), ], ), - ), + ], ), - ], + ), ), ); } diff --git a/lib/presentation/pages/add_scene/add_scene_page.dart b/lib/presentation/pages/add_scene/add_scene_page.dart index b4817286..cce9e4f8 100644 --- a/lib/presentation/pages/add_scene/add_scene_page.dart +++ b/lib/presentation/pages/add_scene/add_scene_page.dart @@ -7,12 +7,11 @@ import 'package:cybearjinni/domain/connections_service.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; import 'package:cybearjinni/presentation/core/snack_bar_service.dart'; -import 'package:cybearjinni/presentation/molecules/molecules.dart'; +import 'package:cybearjinni/presentation/organisms/organisms.dart'; import 'package:cybearjinni/presentation/pages/add_action_page.dart'; import 'package:cybearjinni/presentation/pages/add_scene/widgets/scene_action_widget.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:hexcolor/hexcolor.dart'; /// Page for adding new scene @RoutePage() @@ -109,138 +108,125 @@ class _AddScenePageState extends State { return const CircularProgressIndicatorAtom(); } - return Scaffold( - body: ColoredBox( - color: HexColor('#FBF5F9'), + return PageOrganism( + pageName: 'Add Scene', + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 20), child: Column( children: [ - TopBarMolecule( - pageName: 'Add Scene', - rightIconFunction: context.router.pop, - leftIcon: FontAwesomeIcons.arrowLeft, - leftIconFunction: context.router.pop, + const SizedBox( + height: 30, ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 20), - child: Column( - children: [ - const SizedBox( - height: 30, - ), - TextFormField( - decoration: const InputDecoration( - prefixIcon: FaIcon(FontAwesomeIcons.fileSignature), - labelText: 'Scene Name', + TextFormField( + decoration: const InputDecoration( + prefixIcon: FaIcon(FontAwesomeIcons.fileSignature), + labelText: 'Scene Name', + ), + style: const TextStyle(color: Colors.black), + onChanged: _sceneNameChange, + ), + SizedBox( + height: 300, + width: 500, + child: ListView.builder( + itemCount: entitiesWithActions.length, + itemBuilder: (BuildContext context, int index) { + final EntityActionObject currentDevice = + entitiesWithActions.elementAt(index); + + return Container( + margin: const EdgeInsets.symmetric(vertical: 1), + child: SceneActionWidget( + entity: currentDevice.entity, + propertyToChange: currentDevice.property, + actionToChange: currentDevice.action, ), - style: const TextStyle(color: Colors.black), - onChanged: _sceneNameChange, - ), - SizedBox( - height: 300, - width: 500, - child: ListView.builder( - itemCount: entitiesWithActions.length, - itemBuilder: (BuildContext context, int index) { - final EntityActionObject currentDevice = - entitiesWithActions.elementAt(index); - - return Container( - margin: const EdgeInsets.symmetric(vertical: 1), - child: SceneActionWidget( - entity: currentDevice.entity, - propertyToChange: currentDevice.property, - actionToChange: currentDevice.action, + ); + }, + ), + ), + const SizedBox(height: 30), + DecoratedBox( + decoration: BoxDecoration( + color: Colors.lightBlueAccent.withOpacity(0.5), + // Red border with the width is equal to 5 + border: Border.all(), + ), + child: TextButton( + onPressed: () { + showAdaptiveActionSheet( + context: context, + actions: [ + BottomSheetAction( + title: const TextAtom( + 'Add device action', + style: TextStyle( + color: Colors.blueGrey, + fontSize: 23, ), - ); - }, - ), - ), - const SizedBox(height: 30), - DecoratedBox( - decoration: BoxDecoration( - color: Colors.lightBlueAccent.withOpacity(0.5), - // Red border with the width is equal to 5 - border: Border.all(), - ), - child: TextButton( - onPressed: () { - showAdaptiveActionSheet( - context: context, - actions: [ - BottomSheetAction( - title: const TextAtom( - 'Add device action', - style: TextStyle( - color: Colors.blueGrey, - fontSize: 23, - ), - ), - onPressed: (_) async { - final EntityActionObject? actionList = - await context.router - .push( - AddActionRoute(entities: entities!), - ); - if (actionList != null) { - _addFullAction(actionList); - } - }, - ), - BottomSheetAction( - title: TextAtom( - 'Add service action', - style: TextStyle( - color: Colors.green.shade600, - fontSize: 23, - ), - ), - onPressed: (_) { - SnackBarService().show( - context, - 'Adding service action will be added in the future', - ); - }, - ), - BottomSheetAction( - title: const TextAtom( - 'Add time based action', - style: TextStyle( - color: Colors.blue, - fontSize: 23, - ), - ), - onPressed: (_) { - SnackBarService().show( - context, - 'Adding time based action will be added in the future', - ); - }, - ), - ], - ); - }, - child: const TextAtom('+ Add action'), - ), - ), - const SizedBox(height: 10), - DecoratedBox( - decoration: BoxDecoration( - color: Colors.lightBlueAccent.withOpacity(0.5), - // Red border with the width is equal to 5 - border: Border.all(), - ), - child: TextButton( - onPressed: () { - SnackBarService().show( - context, - 'Adding Scene', - ); - _sendSceneToHub(); - }, - child: const TextAtom('Add Scene'), - ), - ), - ], + ), + onPressed: (_) async { + final EntityActionObject? actionList = + await context.router.push( + AddActionRoute(entities: entities!), + ); + if (actionList != null) { + _addFullAction(actionList); + } + }, + ), + BottomSheetAction( + title: TextAtom( + 'Add service action', + style: TextStyle( + color: Colors.green.shade600, + fontSize: 23, + ), + ), + onPressed: (_) { + SnackBarService().show( + context, + 'Adding service action will be added in the future', + ); + }, + ), + BottomSheetAction( + title: const TextAtom( + 'Add time based action', + style: TextStyle( + color: Colors.blue, + fontSize: 23, + ), + ), + onPressed: (_) { + SnackBarService().show( + context, + 'Adding time based action will be added in the future', + ); + }, + ), + ], + ); + }, + child: const TextAtom('+ Add action'), + ), + ), + const SizedBox(height: 10), + DecoratedBox( + decoration: BoxDecoration( + color: Colors.lightBlueAccent.withOpacity(0.5), + // Red border with the width is equal to 5 + border: Border.all(), + ), + child: TextButton( + onPressed: () { + SnackBarService().show( + context, + 'Adding Scene', + ); + _sendSceneToHub(); + }, + child: const TextAtom('Add Scene'), ), ), ], diff --git a/lib/presentation/pages/choose_automation_type_to_add_page.dart b/lib/presentation/pages/choose_automation_type_to_add_page.dart index 8390a294..f93c6564 100644 --- a/lib/presentation/pages/choose_automation_type_to_add_page.dart +++ b/lib/presentation/pages/choose_automation_type_to_add_page.dart @@ -2,9 +2,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; -import 'package:cybearjinni/presentation/molecules/molecules.dart'; +import 'package:cybearjinni/presentation/organisms/organisms.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; /// Page for the user to decide what kind of Scene he wants to add @RoutePage() @@ -15,226 +14,215 @@ class ChooseAutomationTypeToAddPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - TopBarMolecule( - pageName: 'Add Automations', - - // FontAwesomeIcons.magnifyingGlass, - rightIconFunction: backButtonFunction, - leftIcon: FontAwesomeIcons.arrowLeft, - leftIconFunction: backButtonFunction, - ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 10), - child: Column( - children: [ - const SizedBox( - height: 20, - ), - const TextAtom( - 'Do several things at once or start actions' - ' automatically by adding a trigger.', - style: TextStyle( - color: Colors.black, - ), - ), - const SizedBox( - height: 13, - ), - const TextAtom( - 'Please choose your automation trigger', - style: TextStyle( - color: Colors.black, - fontSize: 18, - ), - ), - const SizedBox( - height: 30, - ), - SingleChildScrollView( - child: Column( - children: [ - Container( - decoration: BoxDecoration( - color: Colors.lightBlueAccent.withOpacity(0.5), - // Red border with the width is equal to 5 - border: Border.all(), - ), - padding: const EdgeInsets.all(10), - child: TextButton( - onPressed: () { - context.router.push(const AddSceneRoute()); - }, - child: const Column( + return PageOrganism( + pageName: 'Add Automations', + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + children: [ + const SizedBox( + height: 20, + ), + const TextAtom( + 'Do several things at once or start actions' + ' automatically by adding a trigger.', + style: TextStyle( + color: Colors.black, + ), + ), + const SizedBox( + height: 13, + ), + const TextAtom( + 'Please choose your automation trigger', + style: TextStyle( + color: Colors.black, + fontSize: 18, + ), + ), + const SizedBox( + height: 30, + ), + SingleChildScrollView( + child: Column( + children: [ + Container( + decoration: BoxDecoration( + color: Colors.lightBlueAccent, + // Red border with the width is equal to 5 + border: Border.all(), + ), + padding: const EdgeInsets.all(10), + child: TextButton( + onPressed: () { + context.router.push(const AddSceneRoute()); + }, + child: const Column( + children: [ + Row( children: [ - Row( - children: [ - TextAtom( - 'Scenes - ', - style: TextStyle( - color: Colors.black, - fontSize: 25, - ), - ), - AutoSizeText( - 'Triggered by user click', - maxFontSize: 18, - style: TextStyle( - color: Colors.black, - ), - ), - ], - ), TextAtom( - 'Combining a number of actions in a big button.', + 'Scenes - ', style: TextStyle( color: Colors.black, - fontSize: 13, + fontSize: 25, ), ), - TextAtom( - 'Example:\n"Arriving Home" button that will turn on some lights and turn up all the blinds when you click on it.', + AutoSizeText( + 'Triggered by user click', + maxFontSize: 18, style: TextStyle( color: Colors.black, - fontSize: 15, ), ), ], ), - ), - ), - const SizedBox( - height: 20, + TextAtom( + 'Combining a number of actions in a big button.', + style: TextStyle( + color: Colors.black, + fontSize: 13, + ), + ), + TextAtom( + 'Example:\n"Arriving Home" button that will turn on some lights and turn up all the blinds when you click on it.', + style: TextStyle( + color: Colors.black, + fontSize: 15, + ), + ), + ], ), - Container( - decoration: BoxDecoration( - color: Colors.yellow.withOpacity(0.5), - // Red border with the width is equal to 5 - border: Border.all(), - ), - padding: const EdgeInsets.all(10), - child: TextButton( - onPressed: () { - // showDialog( - // context: context, - // builder: (_) => const AlertDialog( - // title: TextAtom( - // 'Not supported yet', - // ), - // ), - // ); - context.router.push(const PickRepeatTimeRoute()); - }, - child: const Column( + ), + ), + const SizedBox( + height: 20, + ), + Container( + decoration: BoxDecoration( + color: Colors.yellow, + // Red border with the width is equal to 5 + border: Border.all(), + ), + padding: const EdgeInsets.all(10), + child: TextButton( + onPressed: () { + // showDialog( + // context: context, + // builder: (_) => const AlertDialog( + // title: TextAtom( + // 'Not supported yet', + // ), + // ), + // ); + context.router.push(const PickRepeatTimeRoute()); + }, + child: const Column( + children: [ + Row( children: [ - Row( - children: [ - TextAtom( - 'Routines - ', - style: TextStyle( - color: Colors.black, - fontSize: 25, - ), - ), - AutoSizeText( - 'Triggered by time', - maxFontSize: 18, - style: TextStyle( - color: Colors.black, - ), - ), - ], - ), TextAtom( - 'Like alarm clock but for triggering actions.', + 'Routines - ', style: TextStyle( color: Colors.black, - fontSize: 13, + fontSize: 25, ), ), - TextAtom( - 'Example:\nTurn on the thermostat for an hour and open all blinds each day at 7:00am.', + AutoSizeText( + 'Triggered by time', + maxFontSize: 18, style: TextStyle( color: Colors.black, - fontSize: 15, ), ), ], ), - ), - ), - const SizedBox( - height: 20, + TextAtom( + 'Like alarm clock but for triggering actions.', + style: TextStyle( + color: Colors.black, + fontSize: 13, + ), + ), + TextAtom( + 'Example:\nTurn on the thermostat for an hour and open all blinds each day at 7:00am.', + style: TextStyle( + color: Colors.black, + fontSize: 15, + ), + ), + ], ), - Container( - decoration: BoxDecoration( - color: Colors.greenAccent.withOpacity(0.5), - // Red border with the width is equal to 5 - border: Border.all(), - ), - padding: const EdgeInsets.all(10), - child: TextButton( - onPressed: () { - showDialog( - context: context, - builder: (_) => const AlertDialog( - title: TextAtom( - 'Not supported yet', - ), - ), - ); - // context.router - // .push(const AddRoutineDeleteRoute()); - // context.router - // .push(const AddBindingRoute()); - }, - child: const Column( + ), + ), + const SizedBox( + height: 20, + ), + Container( + decoration: BoxDecoration( + color: Colors.greenAccent, + // Red border with the width is equal to 5 + border: Border.all(), + ), + padding: const EdgeInsets.all(10), + child: TextButton( + onPressed: () { + showDialog( + context: context, + builder: (_) => const AlertDialog( + title: TextAtom( + 'Not supported yet', + ), + ), + ); + // context.router + // .push(const AddRoutineDeleteRoute()); + // context.router + // .push(const AddBindingRoute()); + }, + child: const Column( + children: [ + Row( children: [ - Row( - children: [ - TextAtom( - 'Bindings - ', - style: TextStyle( - color: Colors.black, - fontSize: 25, - ), - ), - AutoSizeText( - 'Triggered by external action', - maxFontSize: 18, - style: TextStyle( - color: Colors.black, - ), - ), - ], - ), TextAtom( - 'Trigger actions whenever an external action occurs.', + 'Bindings - ', style: TextStyle( color: Colors.black, - fontSize: 13, + fontSize: 25, ), ), - TextAtom( - 'Example:\nIf the home door got opened from 3:00am - 6:00am trigger anti-thief alarm system.', + AutoSizeText( + 'Triggered by external action', + maxFontSize: 18, style: TextStyle( color: Colors.black, - fontSize: 15, ), ), ], ), - ), + TextAtom( + 'Trigger actions whenever an external action occurs.', + style: TextStyle( + color: Colors.black, + fontSize: 13, + ), + ), + TextAtom( + 'Example:\nIf the home door got opened from 3:00am - 6:00am trigger anti-thief alarm system.', + style: TextStyle( + color: Colors.black, + fontSize: 15, + ), + ), + ], ), - ], + ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/presentation/pages/home_page/home_page.dart b/lib/presentation/pages/home_page/home_page.dart index 4f83e0f2..8bf51c08 100644 --- a/lib/presentation/pages/home_page/home_page.dart +++ b/lib/presentation/pages/home_page/home_page.dart @@ -1,4 +1,9 @@ +import 'dart:async'; +import 'dart:collection'; + import 'package:auto_route/auto_route.dart'; +import 'package:cbj_integrations_controller/integrations_controller.dart'; +import 'package:cybearjinni/domain/connections_service.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; import 'package:cybearjinni/presentation/molecules/molecules.dart'; @@ -19,23 +24,114 @@ class _HomePageState extends State { @override void initState() { super.initState(); + _watchEntities(); + _watchAreas(); + initializedScenes(); } - /// Tab num, value will be the default tab to show - int _currentTabNum = 1; - final _pages = [ - ScenesInFoldersTab(), - EntitiesByAreaTab(), - // BindingsPage(), - ]; - final _pageController = PageController(initialPage: 1); - @override void dispose() { + entitiesStream?.cancel(); + areasStream?.cancel(); _pageController.dispose(); super.dispose(); } + HashMap? scenes; + + StreamSubscription>? entitiesStream; + StreamSubscription>? areasStream; + + HashMap? areas; + HashMap? entities; + + Future initializedScenes() async { + final HashMap scenecsTemp = + await ConnectionsService.instance.getScenes(); + + setState(() { + scenes = scenecsTemp; + }); + } + + Future _watchAreas() async { + await areasStream?.cancel(); + + areasStream = ConnectionsService.instance.watchAreas().listen((areaEntery) { + if (!mounted) { + return; + } + + setState(() { + areas ??= HashMap(); + areas!.addEntries([areaEntery]); + }); + }); + _initialzeAreas(); + } + + Future _initialzeAreas() async { + final HashMap areasTemp = + await ConnectionsService.instance.getAllAreas; + setState(() { + areas ??= HashMap(); + + areas!.addAll(areasTemp); + }); + } + + Future _watchEntities() async { + await entitiesStream?.cancel(); + + entitiesStream = ConnectionsService.instance + .watchEntities() + .listen((MapEntry entityEntery) { + if (!mounted || + supportedDeviceType(entityEntery.value.entityTypes.type)) { + return; + } + + setState(() { + entities ??= HashMap(); + entities!.addEntries([entityEntery]); + }); + }); + _initialzeEntities(); + } + + Future _initialzeEntities() async { + final HashMap entitiesTemp = + await ConnectionsService.instance.getAllEntities; + entitiesTemp.removeWhere( + (key, value) => + value.entityTypes.type == EntityTypes.smartTypeNotSupported || + value.entityTypes.type == EntityTypes.emptyEntity, + ); + setState(() { + entities ??= HashMap(); + entities!.addAll(entitiesTemp); + }); + } + + HashMap getSupportedEnities( + HashMap entities, + ) { + entities.removeWhere( + (key, value) => supportedDeviceType(value.entityTypes.type), + ); + return entities; + } + + bool supportedDeviceType(EntityTypes type) { + return type == EntityTypes.smartTypeNotSupported || + type == EntityTypes.emptyEntity; + } + + /// Tab num, value will be the default tab to show + int _currentTabNum = 1; + + final _pageController = PageController(initialPage: 1); + static List getBottomNavigationBarItems() { return [ BottomNavigationBarItemAtom( @@ -72,6 +168,12 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { + if (entities == null || areas == null || scenes == null) { + return const Scaffold( + body: CircularProgressIndicatorAtom(), + ); + } + return Scaffold( body: Stack( children: [ @@ -83,19 +185,22 @@ class _HomePageState extends State { }); }, controller: _pageController, - children: _pages, + children: [ + ScenesInFoldersTab(scenes), + EntitiesByAreaTab(areas: areas!, entities: entities!), + // BindingsPage(), + ], ), bottomNavigationBar: BottomNavigationBarMolecule( bottomNaviList: getBottomNavigationBarItems(), onTap: changeByTabNumber, pageIndex: _currentTabNum, ), - // BottomNavigationBarHomePage(callback, _currentTabNum), ), Column( children: [ const Expanded( - child: TextAtom(''), + child: SizedBox(), ), SizedBox( height: 55, @@ -103,8 +208,10 @@ class _HomePageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( - onTap: () { - context.router.push(const PlusButtonRoute()); + onTap: () async { + await context.router.push(const PlusButtonRoute()); + _initialzeAreas(); + initializedScenes(); }, child: CircleAvatar( backgroundColor: Colors.blue.withOpacity(0.9), diff --git a/lib/presentation/pages/home_page/tabs/scenes_in_folders_tab/scenes_in_folders_tab.dart b/lib/presentation/pages/home_page/tabs/scenes_in_folders_tab/scenes_in_folders_tab.dart index a0416311..577f77a2 100644 --- a/lib/presentation/pages/home_page/tabs/scenes_in_folders_tab/scenes_in_folders_tab.dart +++ b/lib/presentation/pages/home_page/tabs/scenes_in_folders_tab/scenes_in_folders_tab.dart @@ -1,68 +1,16 @@ import 'dart:collection'; -import 'package:adaptive_action_sheet/adaptive_action_sheet.dart'; -import 'package:cybearjinni/domain/connections_service.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:cbj_integrations_controller/integrations_controller.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; -import 'package:cybearjinni/presentation/core/snack_bar_service.dart'; +import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; import 'package:cybearjinni/presentation/molecules/molecules.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:cbj_integrations_controller/integrations_controller.dart'; -import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; - -class ScenesInFoldersTab extends StatefulWidget { - @override - State createState() => _ScenesInFoldersTabState(); -} - -class _ScenesInFoldersTabState extends State { - /// Execute when user press the icon in top right side - void userCogFunction(BuildContext context) { - showAdaptiveActionSheet( - context: context, - actions: [ - BottomSheetAction( - title: const TextAtom( - '⚙️ Scenes Settings', - style: TextStyle( - color: Colors.blueGrey, - fontSize: 23, - ), - ), - onPressed: (_) { - SnackBarService().show( - context, - 'Settings page will be added in the future', - ); - }, - ), - ], - ); - } - - void leftIconFunction(BuildContext context) { - Scaffold.of(context).openDrawer(); - } - - void rightSecondFunction(BuildContext context) {} - - HashMap? scenes; - - @override - void initState() { - super.initState(); - _initialized(); - } - Future _initialized() async { - final HashMap scenecsTemp = - await ConnectionsService.instance.getScenes(); - - setState(() { - scenes = scenecsTemp; - }); - } +class ScenesInFoldersTab extends StatelessWidget { + const ScenesInFoldersTab(this.scenes); + final HashMap? scenes; Widget scenesFoldersWidget( BuildContext context, @@ -130,13 +78,13 @@ class _ScenesInFoldersTabState extends State { @override Widget build(BuildContext context) { if (scenes == null || scenes!.isEmpty) { - return const Center( + final ThemeData themeData = Theme.of(context); + final TextTheme textTheme = themeData.textTheme; + + return Center( child: TextAtom( 'You can add automations in the plus button', - style: TextStyle( - fontSize: 18, - color: Colors.black, - ), + style: textTheme.bodyLarge, ), ); } @@ -145,12 +93,8 @@ class _ScenesInFoldersTabState extends State { children: [ TopBarMolecule( pageName: 'Automations', - - rightIconFunction: userCogFunction, leftIcon: FontAwesomeIcons.sitemap, leftIconFunction: (BuildContext context) {}, - // rightSecondIcon: FontAwesomeIcons.magnifyingGlass, - // rightSecondFunction: rightSecondFunction, ), Expanded( child: ScenesGrid( diff --git a/lib/presentation/pages/home_page/tabs/smart_devices_tab/areas_widgets/areas_list_view_widget.dart b/lib/presentation/pages/home_page/tabs/smart_devices_tab/areas_widgets/areas_list_view_widget.dart index c97cb5bd..ec395a85 100644 --- a/lib/presentation/pages/home_page/tabs/smart_devices_tab/areas_widgets/areas_list_view_widget.dart +++ b/lib/presentation/pages/home_page/tabs/smart_devices_tab/areas_widgets/areas_list_view_widget.dart @@ -47,7 +47,13 @@ class AreasListViewWidget extends StatelessWidget { area: area, areas: areas, entities: HashMap.fromEntries( - entitiesInTheArea.map((e) => MapEntry(e, entities[e]!)), + entitiesInTheArea.map((e) { + final DeviceEntityBase? eneity = entities[e]; + if (eneity == null) { + return null; + } + return MapEntry(e, eneity); + }).nonNulls, ), ); }, diff --git a/lib/presentation/pages/home_page/tabs/smart_devices_tab/entities_by_area_tab.dart b/lib/presentation/pages/home_page/tabs/smart_devices_tab/entities_by_area_tab.dart index dcc790b0..964a62ac 100644 --- a/lib/presentation/pages/home_page/tabs/smart_devices_tab/entities_by_area_tab.dart +++ b/lib/presentation/pages/home_page/tabs/smart_devices_tab/entities_by_area_tab.dart @@ -1,187 +1,56 @@ -import 'dart:async'; import 'dart:collection'; -import 'package:adaptive_action_sheet/adaptive_action_sheet.dart'; -import 'package:auto_route/auto_route.dart'; import 'package:cbj_integrations_controller/integrations_controller.dart'; -import 'package:cybearjinni/domain/connections_service.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; -import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; -import 'package:cybearjinni/presentation/core/snack_bar_service.dart'; import 'package:cybearjinni/presentation/molecules/molecules.dart'; -import 'package:cybearjinni/presentation/organisms/organisms.dart'; import 'package:cybearjinni/presentation/pages/home_page/tabs/smart_devices_tab/areas_widgets/areas_list_view_widget.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -class EntitiesByAreaTab extends StatefulWidget { - @override - State createState() => _EntitiesByAreaTabState(); -} +class EntitiesByAreaTab extends StatelessWidget { + const EntitiesByAreaTab({ + required this.areas, + required this.entities, + }); -class _EntitiesByAreaTabState extends State { - HashMap areas = HashMap(); - HashMap entities = HashMap(); + final HashMap areas; + final HashMap entities; @override - void initState() { - super.initState(); - - _watchEntities(); - _watchAreas(); - } - - @override - void dispose() { - entitiesStream?.cancel(); - areasStream?.cancel(); - super.dispose(); - } - - StreamSubscription>? entitiesStream; - StreamSubscription>? areasStream; - - Future _watchAreas() async { - await areasStream?.cancel(); - - areasStream = ConnectionsService.instance.watchAreas().listen((areaEntery) { - if (!mounted) { - return; - } - - setState(() { - areas.addEntries([areaEntery]); - }); - }); - _initialzeAreas(); - } - - Future _initialzeAreas() async { - final HashMap areasTemp = - await ConnectionsService.instance.getAllAreas; - setState(() { - areas.addAll(areasTemp); - }); - } - - Future _watchEntities() async { - await entitiesStream?.cancel(); - - entitiesStream = ConnectionsService.instance - .watchEntities() - .listen((MapEntry entityEntery) { - if (!mounted || - supportedDeviceType(entityEntery.value.entityTypes.type)) { - return; - } - - setState(() { - entities.addEntries([entityEntery]); - }); - }); - _initialzeEntities(); - } - - Future _initialzeEntities() async { - final HashMap entitiesTemp = - await ConnectionsService.instance.getAllEntities; - - setState(() { - entities.addAll(entitiesTemp); - }); - } - - HashMap getSupportedEnities( - HashMap entities, - ) { - entities.removeWhere( - (key, value) => supportedDeviceType(value.entityTypes.type), - ); - return entities; - } - - bool supportedDeviceType(EntityTypes type) { - return type == EntityTypes.smartTypeNotSupported || - type == EntityTypes.emptyEntity; - } - - void userCogFunction(BuildContext context) { - showAdaptiveActionSheet( - context: context, - actions: [ - BottomSheetAction( - title: const TextAtom( - '⚙️ Change Area For Entities', - style: TextStyle(color: Colors.blueGrey, fontSize: 23), - ), - onPressed: (_) async { - await context.router.push(const ChangeAreaForDevicesRoute()); - _initialzeAreas(); - }, - ), - ], - ); - } + Widget build(BuildContext context) { + final ThemeData themeData = Theme.of(context); + final TextTheme textTheme = themeData.textTheme; + final ColorScheme colorScheme = themeData.colorScheme; - Widget tabFrame({required Widget child}) { return Column( children: [ TopBarMolecule( pageName: 'Entities', - rightIcon: Icons.more_vert, - rightIconFunction: userCogFunction, leftIcon: FontAwesomeIcons.solidLightbulb, leftIconFunction: (BuildContext context) {}, - // rightSecondIcon: FontAwesomeIcons.magnifyingGlass, - // rightSecondFunction: rightSecondFunction, ), Expanded( - child: child, - ), - ], - ); - } - - @override - Widget build(BuildContext context) { - if (entities.isEmpty || areas.isEmpty) { - return tabFrame( - child: GestureDetector( - onTap: () { - SnackBarService().show( - context, - 'Add new device by pressing the plus button', - ); - }, - child: EmptyOpenAreaOrganism(), - ), - ); - } - - final ThemeData themeData = Theme.of(context); - final TextTheme textTheme = themeData.textTheme; - final ColorScheme colorScheme = themeData.colorScheme; - - return tabFrame( - child: SingleChildScrollView( - reverse: true, - child: Column( - children: [ - TextAtom( - 'Areas', - style: - textTheme.headlineLarge!.copyWith(color: colorScheme.primary), + child: SingleChildScrollView( + reverse: true, + child: Column( + children: [ + TextAtom( + 'Areas', + style: textTheme.headlineLarge! + .copyWith(color: colorScheme.primary), + ), + const SeparatorAtom(variant: SeparatorVariant.farAppart), + MarginedExpandedAtom( + child: AreasListViewWidget( + entities: entities, + areas: areas, + ), + ), + ], ), - const SeparatorAtom(variant: SeparatorVariant.farAppart), - MarginedExpandedAtom( - child: AreasListViewWidget( - entities: entities, - areas: areas, - ), - ), - ], + ), ), - ), + ], ); } } diff --git a/lib/presentation/pages/plus_button.dart b/lib/presentation/pages/plus_button.dart index 70926494..cc95ceb5 100644 --- a/lib/presentation/pages/plus_button.dart +++ b/lib/presentation/pages/plus_button.dart @@ -1,7 +1,5 @@ import 'package:auto_route/auto_route.dart'; -import 'package:cbj_integrations_controller/integrations_controller.dart'; import 'package:cybearjinni/domain/connections_service.dart'; -import 'package:cybearjinni/domain/i_hub_connection_repository.dart'; import 'package:cybearjinni/presentation/atoms/atoms.dart'; import 'package:cybearjinni/presentation/core/routes/app_router.gr.dart'; import 'package:cybearjinni/presentation/molecules/molecules.dart'; @@ -9,7 +7,6 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:iconify_flutter/iconify_flutter.dart'; import 'package:iconify_flutter/icons/simple_icons.dart'; -import 'package:url_launcher/url_launcher.dart'; @RoutePage() class PlusButtonPage extends StatelessWidget { @@ -53,27 +50,25 @@ class PlusButtonPage extends StatelessWidget { color: Colors.white, child: Column( children: [ - const SizedBox(height: 1), + const SizedBox( + height: 1, + ), ColoredBox( - color: Colors.indigoAccent.withOpacity(0.7), + color: Colors.teal.withOpacity(0.9), child: ListTile( leading: FaIcon( - FontAwesomeIcons.camera, + FontAwesomeIcons.solidLightbulb, color: colorScheme.background, ), title: TextAtom( - 'Turn Phone To a Security Camera', + 'Manage Entities', style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, ), ), - onTap: () async { - context.router - .push(const SmartCameraContainerRoute()); - await IHubConnectionRepository.instance - .closeConnection(); - }, + onTap: () => context.router + .push(const ChangeAreaForDevicesRoute()), ), ), const SizedBox( @@ -83,11 +78,11 @@ class PlusButtonPage extends StatelessWidget { color: Colors.brown.withOpacity(0.9), child: ListTile( leading: FaIcon( - FontAwesomeIcons.solidLightbulb, + FontAwesomeIcons.arrowRightToBracket, color: colorScheme.background, ), title: TextAtom( - 'Add Entity', + 'Login To Vendor', style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, @@ -99,44 +94,72 @@ class PlusButtonPage extends StatelessWidget { }, ), ), + if (ConnectionsService.getCurrentConnectionType() == + ConnectionType.hub) ...[ + const SizedBox(height: 1), + ColoredBox( + color: Colors.blue, + child: ListTile( + leading: FaIcon( + FontAwesomeIcons.globe, + color: colorScheme.background, + ), + title: TextAtom( + 'Add Remote Control Support', + style: TextStyle( + color: Theme.of(context) + .textTheme + .bodyLarge! + .color, + ), + ), + onTap: () { + context.router.push(const RemotePipesRoute()); + }, + ), + ), + ], const SizedBox(height: 1), ColoredBox( - color: Colors.blue, + color: Colors.purple.withOpacity(0.7), child: ListTile( leading: FaIcon( - FontAwesomeIcons.globe, + FontAwesomeIcons.sitemap, color: colorScheme.background, ), title: TextAtom( - 'Add Remote Control Support', + 'Add Automation', style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, ), ), onTap: () { - context.router.push(const RemotePipesRoute()); + context.router + .push(const ChooseAutomationTypeToAddRoute()); }, ), ), const SizedBox(height: 1), ColoredBox( - color: Colors.purple.withOpacity(0.7), + color: Colors.indigoAccent.withOpacity(0.7), child: ListTile( leading: FaIcon( - FontAwesomeIcons.sitemap, + FontAwesomeIcons.camera, color: colorScheme.background, ), title: TextAtom( - 'Add Automation', + 'Turn Phone To a Security Camera', style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, ), ), - onTap: () { + onTap: () async { context.router - .push(const ChooseAutomationTypeToAddRoute()); + .push(const SmartCameraContainerRoute()); + // await IHubConnectionRepository.instance + // .closeConnection(); }, ), ), @@ -183,47 +206,52 @@ class PlusButtonPage extends StatelessWidget { .push(const EntitiesInNetworkRoute()), ), ), - const SizedBox( - height: 1, - ), - ColoredBox( - color: Colors.redAccent.withOpacity(0.9), - child: ListTile( - leading: Iconify( - SimpleIcons.node_red, - color: colorScheme.background, - ), - title: TextAtom( - 'Open Node-RED of Hub', - style: TextStyle( - color: - Theme.of(context).textTheme.bodyLarge!.color, + if (ConnectionsService.getCurrentConnectionType() == + ConnectionType.hub) ...[ + const SizedBox( + height: 1, + ), + ColoredBox( + color: Colors.redAccent.withOpacity(0.9), + child: ListTile( + leading: Iconify( + SimpleIcons.node_red, + color: colorScheme.background, + ), + title: TextAtom( + 'Open Node-RED of Hub', + style: TextStyle( + color: Theme.of(context) + .textTheme + .bodyLarge! + .color, + ), ), + onTap: () { + // final HubEntity? hubEntity = + // IHubConnectionRepository.hubEntity; + // if (hubEntity != null && + // hubEntity.lastKnownIp.isValid()) { + // final String lastKnownIp = + // hubEntity.lastKnownIp.getOrCrash(); + // launchUrl( + // Uri.parse('http://$lastKnownIp:1880'), + // mode: LaunchMode.externalApplication, + // ); + // } else { + // showDialog( + // context: context, + // builder: (_) => const AlertDialog( + // title: TextAtom( + // "Can't find Hub/Node-Red IP to connect to", + // ), + // ), + // ); + // } + }, ), - onTap: () { - final HubEntity? hubEntity = - IHubConnectionRepository.hubEntity; - if (hubEntity != null && - hubEntity.lastKnownIp.isValid()) { - final String lastKnownIp = - hubEntity.lastKnownIp.getOrCrash(); - launchUrl( - Uri.parse('http://$lastKnownIp:1880'), - mode: LaunchMode.externalApplication, - ); - } else { - showDialog( - context: context, - builder: (_) => const AlertDialog( - title: TextAtom( - "Can't find Hub/Node-Red IP to connect to", - ), - ), - ); - } - }, ), - ), + ], const SizedBox( height: 1, ), @@ -253,7 +281,7 @@ class PlusButtonPage extends StatelessWidget { color: Colors.greenAccent, child: ListTile( leading: FaIcon( - FontAwesomeIcons.rightFromBracket, + FontAwesomeIcons.personThroughWindow, color: colorScheme.background, ), title: TextAtom(