This commit is contained in:
mohammad
2024-07-23 16:16:31 +03:00
parent 8a4a158af5
commit e5e839248d
17 changed files with 457 additions and 516 deletions

View File

@ -1,19 +1,21 @@
import 'dart:convert';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_state.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_model.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/time_zone_model.dart';
import 'package:syncrow_app/services/api/profile_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final String userId;
bool isSaving = false;
bool editName = false;
final FocusNode focusNode = FocusNode();
@ -22,12 +24,13 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
String timeZoneSelected = '';
String regionSelected = '';
final TextEditingController searchController = TextEditingController();
final TextEditingController nameController = TextEditingController(text: 'asd alsdkasdd ');
final TextEditingController nameController = TextEditingController(text: '${AuthCubit.user!.firstName} ${AuthCubit.user!.lastName}');
List<TimeZone>? timeZoneList;
List<RegionModel>? regionList;
ProfileBloc({required this.userId}) : super(InitialState()) {
on<InitialEvent>(_fetchUserInfo);
ProfileBloc() : super(InitialState()) {
on<InitialProfileEvent>(_fetchUserInfo);
on<TimeZoneInitialEvent>(_fetchTimeZone);
on<RegionInitialEvent>(_fetchRegion);
on<SaveNameEvent>(saveName);
@ -35,46 +38,18 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
on<ChangeNameEvent>(_changeName);
on<SelectTimeZoneEvent>(selectTimeZone);
on<SearchRegionEvent>(searchRegion);
on<SearchTimeZoneEvent>(searchTimeZone);
on<SelectRegionEvent>(selectRegion);
}
List<Map<String, String>> timeZone=
[
{"name": "GMT-12:00", "offset": "-12:00","id":'1'},
{"name": "GMT-11:00", "offset": "-11:00","id":'2'},
{"name": "GMT-10:00", "offset": "-10:00","id":'3'},
{"name": "GMT-09:00", "offset": "-09:00","id":'4'},
{"name": "GMT-08:00", "offset": "-08:00","id":'5'},
{"name": "GMT-07:00", "offset": "-07:00","id":'6'},
{"name": "GMT-06:00", "offset": "-06:00","id":'7'},
{"name": "GMT-05:00", "offset": "-05:00","id":'8'},
{"name": "GMT-04:00", "offset": "-04:00","id":'9'},
];
List<Map<String, String>> region=
[
{"name": "region 1", "id":'1'},
{"name": "region 2", "id":'2'},
{"name": "region 3","id":'3'},
{"name": "region 4", "id":'4'},
{"name": "region 5","id":'5'},
{"name": "region 6","id":'6'},
{"name": "region 7","id":'7'},
{"name": "region 8", "id":'8'},
];
Uint8List? decodeBase64Image(String? base64String) {
if (base64String != null) {
final startIndex = base64String.indexOf('base64,') + 7;
final pureBase64String = base64String.substring(startIndex);
return base64.decode(pureBase64String);
}
return null;
}
void _changeName(ChangeNameEvent event, Emitter<ProfileState> emit) {
emit(LoadingInitialState());
editName = event.value!;
@ -88,30 +63,21 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
emit(NameEditingState(editName: editName));
}
void _fetchUserInfo(InitialEvent event, Emitter<ProfileState> emit) async {
void _fetchUserInfo(InitialProfileEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
// var response = await ProfileApi.fetchUserInfo(userId);
// List<StatusModel> statusModelList = [];
// for (var status in response['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// }
AuthCubit.user = await ProfileApi.fetchUserInfo(AuthCubit.user!.uuid);
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
Future _fetchTimeZone(
TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
Future _fetchTimeZone(TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
timeZoneList = timeZone.map((zone) => TimeZone.fromJson(zone)).toList();
// List<StatusModel> statusModelList = [];
// for (var status in response['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// }
emit(UpdateState(timeZoneList: timeZoneList!)); // Make sure UpdateState accepts the list
timeZoneList = await ProfileApi.fetchTimeZone();
emit(UpdateState(timeZoneList: timeZoneList!));
return timeZoneList;
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
@ -119,26 +85,25 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future selectTimeZone(SelectTimeZoneEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
timeZoneSelected= event.val;
emit(LoadingInitialState());
timeZoneSelected = event.val;
await ProfileApi.saveTimeZone(regionUuid: event.val);
CustomSnackBar.displaySnackBar('Save Successfully');
Navigator.pop(event.context);
return timeZoneList;
emit(SaveState());
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
Future selectRegion(SelectRegionEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
regionSelected= event.val;
emit(LoadingInitialState());
await ProfileApi.saveRegion(regionUuid:event.val );
CustomSnackBar.displaySnackBar('Save Successfully');
Navigator.pop(event.context);
return timeZoneList;
emit(SaveState());
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
@ -146,26 +111,43 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
Future searchRegion(SearchRegionEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if(event.query.isEmpty){
regionList = region.map((zone) => RegionModel.fromJson(zone)).toList();
}else{
if(event.query.isNotEmpty){
final filteredRegions = regionList?.where((region) {
return region.name.toLowerCase().contains(query);
}).toList() ?? [];
regionList = filteredRegions;// Assume this fetches the regions
emit(RegionsLoadedState(regions: filteredRegions));
}else{
regionList = await ProfileApi.fetchRegion();
emit(RegionsLoadedState(regions: regionList!));
}
}
Future searchTimeZone(SearchTimeZoneEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if(event.query.isNotEmpty){
final filtered = timeZoneList?.where((region) {
return region.name.toLowerCase().contains(query);
}).toList() ?? [];
timeZoneList = filtered;
emit(TimeZoneLoadedState(regions: filtered));
}else{
timeZoneList = await ProfileApi.fetchTimeZone();
emit(UpdateState(timeZoneList: timeZoneList!));
}
}
void _fetchRegion(RegionInitialEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
regionList = region.map((zone) => RegionModel.fromJson(zone)).toList();
emit(UpdateState(timeZoneList: timeZoneList!));
regionList = await ProfileApi.fetchRegion();
emit(RegionsLoadedState(regions: regionList!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
@ -182,7 +164,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
image=null;
CustomSnackBar.displaySnackBar('Image size must be 1 MB or less');
}else{
await saveImage();
await _saveImage();
}
} else {
print('No image selected.');
@ -193,54 +175,15 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future<void> saveImage() async {
Future<void> _saveImage() async {
emit(ChangeImageState());
List<int> imageBytes = image!.readAsBytesSync();
String base64Image = base64Encode(imageBytes);
print(base64Image);
var response = await ProfileApi.saveImage(base64Image);
emit(ImageSelectedState());
}
Future<bool> _requestPermission() async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if (Platform.isAndroid ) {
PermissionStatus status = await Permission.photos.status;
if(androidInfo.version.sdkInt<= 33){
if (status.isDenied) {
PermissionStatus status = await Permission.storage.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}else{
if (status.isGranted) {
return true;
} else if (status.isDenied) {
PermissionStatus status = await Permission.photos.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}
return false;
} else {
SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
bool firstClick = sharedPreferences.getBool('firstPermission') ?? true;
await sharedPreferences.setBool('firstPermission', false);
if (firstClick == false) {
var status = await Permission.photos.status;
return status.isGranted;
} else {
return true;
}
}
}
void _showPermissionDeniedDialog(BuildContext context) {
showDialog(
@ -272,129 +215,72 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
Future<void> saveName(SaveNameEvent event, Emitter<ProfileState> emit) async {
if (_validateInputs()) return;
try {
add(const ChangeNameEvent(value: false));
isSaving = true;
emit(LoadingSaveState());
final fullName = nameController.text;
final nameParts = fullName.split(' ');
final firstName = nameParts[0];
final lastName = nameParts.length > 1 ? nameParts[1] : '';
var response = await ProfileApi.saveName(firstName: firstName, lastName: lastName);
add(InitialProfileEvent());
AuthCubit.get(event.context).fetchUserInfo();
Navigator.of(event.context).pop(true);
CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveState());
} catch (_) {
// Handle the error
} finally {
isSaving = false;
}
}
bool _validateInputs() {
if (nameController.text.length < 7) {
CustomSnackBar.displaySnackBar('Password less than 7');
return true;
}
if (nameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password required');
return true;
}
if (nameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password name required');
if (nameController.text.length < 2) {
CustomSnackBar.displaySnackBar('Name Must More than 2 ');
return true;
}
return false;
}
void showRenameDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: SizedBox(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.only(
top: 25,
),
child: Text(
'Change Name',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const Spacer(),
const Spacer(),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 0.5,
),
top: BorderSide(
color: Colors.grey,
width: 0.5,
),
),
),
child: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'Cancel',
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
),
),
const VerticalDivider(
thickness: 1,
width: 1,
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 0.5,
),
top: BorderSide(
color: Colors.grey,
width: 0.5,
),
),
),
child: TextButton(
onPressed: () {
// Handle save action
},
child: const Text(
'Save',
style: TextStyle(
fontSize: 18,
color: Colors.grey,
),
),
),
),
),
],
),
],
),
),
);
},
);
Future<bool> _requestPermission() async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid ) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
PermissionStatus status = await Permission.photos.status;
if(androidInfo.version.sdkInt<= 33){
if (status.isDenied) {
PermissionStatus status = await Permission.storage.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}else{
if (status.isGranted) {
return true;
} else if (status.isDenied) {
PermissionStatus status = await Permission.photos.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}
return false;
} else {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool firstClick = sharedPreferences.getBool('firstPermission') ?? true;
await sharedPreferences.setBool('firstPermission', false);
if (firstClick == false) {
var status = await Permission.photos.status;
return status.isGranted;
} else {
return true;
}
}
}
}