Files
syncrow-app/lib/features/app_layout/bloc/home_cubit.dart
2024-06-26 11:53:32 +03:00

429 lines
12 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share_plus/share_plus.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdown.dart';
import 'package:syncrow_app/features/auth/model/user_model.dart';
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/room_model.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
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/scene_view.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
part 'home_state.dart';
class HomeCubit extends Cubit<HomeState> {
HomeCubit._() : super(HomeInitial()) {
checkIfNotificationPermissionGranted();
if (selectedSpace == null) {
fetchUnitsByUserId();
// .then((value) {
// if (selectedSpace != null) {
// fetchRoomsByUnitId(selectedSpace!);
// }
// });
}
}
static HomeCubit? _instance;
static HomeCubit getInstance() {
// If an instance already exists, return it
_instance ??= HomeCubit._();
return _instance!;
}
void emitSafe(HomeState newState) {
final cubit = this;
if (!cubit.isClosed) {
cubit.emit(newState);
}
}
@override
Future<void> close() {
_instance = null;
selectedSpace = null;
selectedRoom = null;
pageIndex = 0;
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
return super.close();
}
static HomeCubit get(context) => BlocProvider.of(context);
List<SpaceModel>? spaces;
SpaceModel? selectedSpace;
RoomModel? selectedRoom;
PageController devicesPageController = PageController();
PageController roomsPageController = PageController();
var duration = const Duration(milliseconds: 300);
void oneSignalPermissionObserver;
void oneSignalSubscriptionObserver;
void oneSignalClickListenerObserver;
// selectSpace(SpaceModel space) async {
// selectedSpace = space;
// emit(SpaceSelected(space));
// }
checkIfNotificationPermissionGranted() async {
try {
OneSignal.initialize('762350c9-1e5d-4d95-a648-16d4dc8a25e1');
//Show native push notification dialog
if (Platform.isIOS) {
await OneSignal.Notifications.permissionNative();
} else {
await OneSignal.Notifications.requestPermission(true);
}
if (await Permission.notification.isGranted == false) {
return;
}
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
if (userUuid.isNotEmpty) {
await OneSignal.login(userUuid);
}
//Enable push notifications
await OneSignal.User.pushSubscription.optIn();
//this function will be called once a user is subscribed
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 {
await _sendSubscriptionId();
});
//check if the player id is sent, if not send it again
await _sendSubscriptionId();
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
//Once the user clicks on the notification
});
} catch (err) {
debugPrint("******* Error");
debugPrint(err.toString());
rethrow;
}
}
_sendSubscriptionId() async {
String? subscriptionId = OneSignal.User.pushSubscription.id ?? '';
//TODO send the subscription id to BE
}
changeSelectedSpace(SpaceModel space) {
selectedSpace = space;
emitSafe(SpaceSelected(space));
fetchRoomsByUnitId(space);
}
roomSliderPageChanged(int index) {
devicesPageController.animateToPage(
index,
duration: duration,
curve: Curves.linear,
);
if (index == 0) {
unselectRoom();
} else {
selectedRoom = selectedSpace!.rooms![index - 1];
emitSafe(RoomSelected(selectedRoom!));
}
}
devicesPageChanged(int index) {
roomsPageController.animateToPage(
index,
duration: const Duration(milliseconds: 300),
curve: Curves.linear,
);
if (index <= 0) {
unselectRoom();
} else {
selectedRoom = selectedSpace!.rooms![index - 1];
emitSafe(RoomSelected(selectedRoom!));
}
}
unselectRoom() {
// selectedRoom = null;
devicesPageController.animateToPage(
0,
duration: duration,
curve: Curves.linear,
);
roomsPageController.animateToPage(
0,
duration: duration,
curve: Curves.linear,
);
emitSafe(RoomUnSelected());
}
//////////////////////////////////////// API ////////////////////////////////////////
generateInvitation(String unitId) async {
try {
final invitationCode = await SpacesAPI.generateInvitationCode(unitId);
if (invitationCode.isNotEmpty) {
Share.share('The invitation code is $invitationCode');
CustomSnackBar.displaySnackBar(
'Invitation code generated successfully the code is: $invitationCode');
} else {
CustomSnackBar.displaySnackBar('Please try again!');
}
} catch (failure) {
CustomSnackBar.displaySnackBar('Something went wrong');
return;
}
}
Future<bool> joinAUnit(String code) async {
try {
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
final success = await SpacesAPI.joinUnit(body);
if (success) {
await fetchUnitsByUserId();
CustomSnackBar.displaySnackBar('Done successfully');
}
return true;
} catch (failure) {
CustomSnackBar.displaySnackBar('Something went wrong');
return false;
}
}
fetchUnitsByUserId() async {
emitSafe(GetSpacesLoading());
try {
spaces = await SpacesAPI.getUnitsByUserId();
} catch (failure) {
emitSafe(GetSpacesError("No units found"));
return;
}
if (spaces != null && spaces!.isNotEmpty) {
selectedSpace = spaces!.first;
await fetchRoomsByUnitId(selectedSpace!);
emitSafe(GetSpacesSuccess(spaces!));
} else {
emitSafe(GetSpacesError("No spaces found"));
}
}
fetchRoomsByUnitId(SpaceModel space) async {
emitSafe(GetSpaceRoomsLoading());
try {
space.rooms = await SpacesAPI.getRoomsBySpaceId(space.id!);
} catch (failure) {
emitSafe(GetSpaceRoomsError(failure.toString()));
return;
}
if (space.rooms != null && space.rooms!.isNotEmpty) {
emitSafe(GetSpaceRoomsSuccess(space.rooms!));
} else {
emitSafe(GetSpaceRoomsError("No rooms found"));
}
}
/////////////////////////////////////// Nav ///////////////////////////////////////
static int pageIndex = 0;
static Map<String, List<Widget>> appBarActions = {
'Dashboard': [
IconButton(
icon: const Icon(
Icons.add,
size: 25,
),
style: ButtonStyle(
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.push(
NavigationService.navigatorKey.currentContext!,
CustomPageRoute(
builder: (context) => CurtainView(
curtain: DeviceModel(
name: "Curtain",
status: [StatusModel(code: "awd", value: 1)],
productType: DeviceType.Curtain,
),
),
),
);
},
),
],
'Devices': [
IconButton(
icon: const Icon(
Icons.add,
size: 25,
),
style: ButtonStyle(
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.more_vert,
size: 25,
),
style: ButtonStyle(
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
],
'Routine': [
// IconButton(
// icon: Image.asset(
// Assets.assetsIconsFilter,
// height: 20,
// width: 20,
// ),
// onPressed: () {},
// ),
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: () {},
),
],
'Menu': [
IconButton(
icon: SvgPicture.asset(
Assets.assetsIconsScan,
height: 20,
width: 20,
),
onPressed: () {},
),
],
};
static Map<String, Widget?> appBarLeading = {
'Dashboard': const AppBarHomeDropdown(),
'Devices': const AppBarHomeDropdown(),
'Routine': const AppBarHomeDropdown(),
'Menu': Padding(
padding: const EdgeInsets.only(left: 15),
child: Image.asset(
Assets.assetsImagesLogoHorizontal,
height: 15,
width: 100,
fit: BoxFit.scaleDown,
),
),
};
static var bottomNavItems = [
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
defaultBottomNavBarItem(icon: Assets.assetsIconsMenu, label: 'Menu'),
];
final List<Widget> pages = [
const DashboardView(),
// const LayoutPage(),
BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: const DevicesViewBody(),
),
const SceneView(),
const MenuView(),
];
void updatePageIndex(int index) {
pageIndex = index;
emitSafe(NavChangePage());
}
void updateDevice(String deviceId) async {
try {
final response = await DevicesAPI.firmwareDevice(
deviceId:deviceId ,
firmwareVersion: '0'
);
if (response['success'] ?? false) {
CustomSnackBar.displaySnackBar('Update Success');
}
} catch (_) {}
}
}
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
return BottomNavigationBarItem(
icon: SvgPicture.asset(icon),
activeIcon: SvgPicture.asset(
icon.replaceAll('.svg', '-fill.svg'),
colorFilter: const ColorFilter.mode(
ColorsManager.primaryColor,
BlendMode.srcIn,
),
),
label: label,
);
}