push routines style and create scene view

This commit is contained in:
ashrafzarkanisala
2024-06-12 01:54:03 +03:00
parent 76f5c6d325
commit 1045d72bbe
21 changed files with 411 additions and 189 deletions
+62 -36
View File
@@ -18,6 +18,7 @@ import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
import 'package:syncrow_app/features/menu/view/menu_view.dart';
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
@@ -62,9 +63,12 @@ class HomeCubit extends Cubit<HomeState> {
selectedSpace = null;
selectedRoom = null;
pageIndex = 0;
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
OneSignal.User.pushSubscription
.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
OneSignal.Notifications.removePermissionObserver(
(permission) => oneSignalPermissionObserver);
OneSignal.Notifications.removeClickListener(
(event) => oneSignalClickListenerObserver);
return super.close();
}
@@ -106,7 +110,9 @@ class HomeCubit extends Cubit<HomeState> {
return;
}
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
var userUuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
'';
if (userUuid.isNotEmpty) {
await OneSignal.login(userUuid);
}
@@ -114,21 +120,24 @@ class HomeCubit extends Cubit<HomeState> {
await OneSignal.User.pushSubscription.optIn();
//this function will be called once a user is subscribed
oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async {
oneSignalSubscriptionObserver =
OneSignal.User.pushSubscription.addObserver((state) async {
if (state.current.optedIn) {
await _sendSubscriptionId();
}
});
// Send the player id when a user allows notifications
oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
oneSignalPermissionObserver =
OneSignal.Notifications.addPermissionObserver((state) async {
await _sendSubscriptionId();
});
//check if the player id is sent, if not send it again
await _sendSubscriptionId();
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
oneSignalClickListenerObserver =
OneSignal.Notifications.addClickListener((event) async {
//Once the user clicks on the notification
});
} catch (err) {
@@ -215,7 +224,9 @@ class HomeCubit extends Cubit<HomeState> {
Future<bool> joinAUnit(String code) async {
try {
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
'';
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
final success = await SpacesAPI.joinUnit(body);
@@ -275,7 +286,8 @@ class HomeCubit extends Cubit<HomeState> {
size: 25,
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(ColorsManager.textPrimaryColor),
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.push(
@@ -294,26 +306,29 @@ class HomeCubit extends Cubit<HomeState> {
),
],
'Devices': [
IconButton(
icon: const Icon(
Icons.add,
size: 25,
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.more_vert,
size: 25,
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
//TODO: to be checked
// IconButton(
// icon: const Icon(
// Icons.add,
// size: 25,
// ),
// style: ButtonStyle(
// foregroundColor:
// MaterialStateProperty.all(ColorsManager.textPrimaryColor),
// ),
// onPressed: () {},
// ),
// IconButton(
// icon: const Icon(
// Icons.more_vert,
// size: 25,
// ),
// style: ButtonStyle(
// foregroundColor:
// MaterialStateProperty.all(ColorsManager.textPrimaryColor),
// ),
// onPressed: () {},
// ),
],
'Routine': [
// IconButton(
@@ -327,20 +342,29 @@ class HomeCubit extends Cubit<HomeState> {
IconButton(
icon: const Icon(
Icons.add,
size: 25,
size: 32,
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(ColorsManager.textPrimaryColor),
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
onPressed: () {
Navigator.push(
NavigationService.navigatorKey.currentContext!,
CustomPageRoute(
builder: (context) => const CreateSceneView(),
),
);
},
),
IconButton(
icon: const Icon(
Icons.more_vert,
size: 25,
size: 28,
),
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(ColorsManager.textPrimaryColor),
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
@@ -373,7 +397,8 @@ class HomeCubit extends Cubit<HomeState> {
};
static var bottomNavItems = [
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
defaultBottomNavBarItem(
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
@@ -398,7 +423,8 @@ class HomeCubit extends Cubit<HomeState> {
}
}
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
BottomNavigationBarItem defaultBottomNavBarItem(
{required String icon, required String label}) {
return BottomNavigationBarItem(
icon: SvgPicture.asset(icon),
activeIcon: SvgPicture.asset(
@@ -16,21 +16,21 @@ class AppBarHomeDropdown extends StatelessWidget {
builder: (context, state) {
return Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: DropdownButton(
icon: const Icon(
Icons.expand_more,
color: Colors.black,
size: 25,
),
underline: const SizedBox.shrink(),
padding: const EdgeInsets.all(0),
borderRadius: BorderRadius.circular(20),
value: HomeCubit.getInstance().selectedSpace!.id,
items: HomeCubit.getInstance().spaces!.map((space) {
return DropdownMenuItem(
value: space.id,
child: SizedBox(
width: 100,
child: Center(
child: DropdownButton(
icon: const Icon(
Icons.expand_more,
color: ColorsManager.textPrimaryColor,
size: 16,
),
underline: const SizedBox.shrink(),
padding: EdgeInsets.zero,
borderRadius: BorderRadius.circular(20),
value: HomeCubit.getInstance().selectedSpace!.id,
items: HomeCubit.getInstance().spaces!.map((space) {
return DropdownMenuItem(
alignment: AlignmentDirectional.centerStart,
value: space.id,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
@@ -45,7 +45,8 @@ class AppBarHomeDropdown extends StatelessWidget {
),
),
const SizedBox(width: 5),
Expanded(
Flexible(
fit: FlexFit.loose,
child: BodyMedium(
text: space.name ?? "??",
style: context.bodyMedium.copyWith(
@@ -55,19 +56,20 @@ class AppBarHomeDropdown extends StatelessWidget {
),
),
),
const SizedBox(width: 5),
],
),
),
);
}).toList(),
onChanged: (value) {
if (value != null) {
HomeCubit.getInstance().changeSelectedSpace(
HomeCubit.getInstance()
.spaces!
.firstWhere((element) => element.id == value));
}
},
);
}).toList(),
onChanged: (value) {
if (value != null) {
HomeCubit.getInstance().changeSelectedSpace(
HomeCubit.getInstance()
.spaces!
.firstWhere((element) => element.id == value));
}
},
),
),
);
},
@@ -20,9 +20,11 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
leadingWidth: 150,
toolbarHeight: Constants.appBarHeight,
leading: HomeCubit.getInstance().spaces!.isNotEmpty
? HomeCubit.appBarLeading[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]
? HomeCubit.appBarLeading[
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]
: null,
// actions: HomeCubit.appBarActions[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],
actions: HomeCubit.appBarActions[
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],
));
},
);
@@ -0,0 +1 @@
@@ -0,0 +1,28 @@
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_event.dart';
import 'package:syncrow_app/features/scene/model/scene_model.dart';
part 'scene_state.dart';
class SceneBloc extends Bloc<SceneEvent, SceneState> {
SceneBloc() : super(SceneInitial()) {
on<LoadScenes>(_onLoadScenes);
}
void _onLoadScenes(LoadScenes event, Emitter<SceneState> emit) {
emit(SceneLoading());
try {
final scenes = _loadScenes();
emit(SceneLoaded(scenes));
} catch (_) {
emit(SceneError());
}
}
List<SceneModel> _loadScenes() {
//TODO: Load scenes
return [];
}
}
@@ -0,0 +1,9 @@
import 'package:equatable/equatable.dart';
abstract class SceneEvent extends Equatable {
@override
List<Object> get props => [];
}
class LoadScenes extends SceneEvent {}
@@ -0,0 +1,21 @@
part of 'scene_bloc.dart';
abstract class SceneState extends Equatable {
@override
List<Object> get props => [];
}
class SceneInitial extends SceneState {}
class SceneLoading extends SceneState {}
class SceneLoaded extends SceneState {
final List<SceneModel> scenes;
SceneLoaded(this.scenes);
@override
List<Object> get props => [scenes];
}
class SceneError extends SceneState {}
-20
View File
@@ -1,20 +0,0 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/scene/model/scene_model.dart';
part 'scene_state.dart';
class SceneCubit extends Cubit<SceneState> {
SceneCubit() : super(SceneInitial()) {
getScenes();
}
static SceneCubit of(context) => BlocProvider.of<SceneCubit>(context);
void getScenes() {
emit(SceneLoading());
emit(SceneSuccess());
}
List<SceneModel> scenes = [];
}
-11
View File
@@ -1,11 +0,0 @@
part of 'scene_cubit.dart';
abstract class SceneState {}
class SceneInitial extends SceneState {}
class SceneLoading extends SceneState {}
class SceneSuccess extends SceneState {}
class SceneFailure extends SceneState {}
@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
class CreateSceneView extends StatelessWidget {
const CreateSceneView({super.key});
@override
Widget build(BuildContext context) {
return const DefaultScaffold(
title: StringsManager.createScene,
padding: EdgeInsets.only(top: 24),
child: Column(
children: [
DefaultContainer(
width: double.infinity,
margin: EdgeInsets.symmetric(vertical: 4),
child: SceneListTile(
assetPath: Assets.handClickIcon,
title: StringsManager.tapToRun,
subtitle: StringsManager.turnOffAllLights,
),
),
DefaultContainer(
width: double.infinity,
margin: EdgeInsets.symmetric(vertical: 4),
child: SceneListTile(
assetPath: Assets.refreshIcon,
title: StringsManager.whenDeviceStatusChanges,
subtitle: StringsManager.whenUnusualActivityIsDetected,
),
),
],
),
);
}
}
class SceneListTile extends StatelessWidget {
const SceneListTile({
super.key,
required this.assetPath,
required this.title,
required this.subtitle,
});
final String assetPath;
final String title;
final String subtitle;
@override
Widget build(BuildContext context) {
return ListTile(
minLeadingWidth: 40,
leading: SvgPicture.asset(
assetPath,
width: 20,
height: 32,
),
title: BodyMedium(text: title),
subtitle: BodySmall(
text: subtitle,
style: context.bodySmall.copyWith(
fontWeight: FontWeight.w400, color: ColorsManager.greyColor),
),
);
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/scene/bloc/scene_cubit.dart';
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
import 'package:syncrow_app/features/shared_widgets/create_unit.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
@@ -16,8 +16,8 @@ class SceneView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => SceneCubit(),
child: BlocBuilder<SceneCubit, SceneState>(
create: (BuildContext context) => SceneBloc(),
child: BlocBuilder<SceneBloc, SceneState>(
builder: (context, state) {
return HomeCubit.getInstance().spaces?.isEmpty ?? true
? const CreateUnitWidget()
@@ -7,14 +7,22 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class DefaultScaffold extends StatelessWidget {
const DefaultScaffold(
{super.key, required this.child, this.title, this.actions, this.appBar, this.bottomNavBar});
const DefaultScaffold({
super.key,
required this.child,
this.title,
this.actions,
this.appBar,
this.bottomNavBar,
this.padding,
});
final Widget child;
final String? title;
final List<Widget>? actions;
final PreferredSizeWidget? appBar;
final Widget? bottomNavBar;
final EdgeInsetsGeometry? padding;
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
@@ -33,7 +41,7 @@ class DefaultScaffold extends StatelessWidget {
centerTitle: true,
title: BodyLarge(
text: title ?? "",
fontColor: ColorsManager.primaryColor,
fontColor: ColorsManager.secondaryColor,
fontWeight: FontsManager.bold,
),
actions: actions,
@@ -41,7 +49,8 @@ class DefaultScaffold extends StatelessWidget {
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.symmetric(horizontal: Constants.defaultPadding),
padding: padding ??
const EdgeInsets.symmetric(horizontal: Constants.defaultPadding),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(