Related
I need to delete the users profile from firebase, thing is I have 3 collections petfiles, petsdetails and users which need to be deleted. As in when a user signs up, they can create a pet and create records for their pet. But when having to delete the user, it should delete all the pets and records the pet has (it could be up to any amount)
I havent tried anything as I dont really know how to solve this but this is my code
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_picker/image_picker.dart';
import 'package:vet_bookr/oScreens/petFiles.dart';
import '../constant.dart';
class UserDetails extends StatefulWidget {
UserDetails({Key? key, required this.details}) : super(key: key);
Map<String, dynamic> details;
#override
State<UserDetails> createState() => _UserDetailsState();
}
class _UserDetailsState extends State<UserDetails> {
List<String> labels = ["Email", "Phone Number"];
bool editableText = false;
String imageUrl = "";
List<String> petIds = [];
#override
void initState() {
// TODO: implement initState
nameController.text = widget.details["name"];
ageController.text = widget.details["age"];
super.initState();
}
Future<void> uploadImages({required String path}) async {
try {
final imageRef = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await imageRef.putFile(File(path));
imageUrl = await imageRef.getDownloadURL();
setState(() {});
//print(imageRef.getDownloadURL());
} on FirebaseException catch (e) {
print("Function does work");
SnackBar snackBar = SnackBar(content: Text(e.message!));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
bool isLoading = false;
final nameController = TextEditingController();
final ageController = TextEditingController();
XFile? profilePic;
ImagePicker imagePicker = ImagePicker();
final storageRef = FirebaseStorage.instance.ref();
TextEditingController controllerChanger(index) {
if (index == 0) {
return nameController;
}
if (index == 1) {
return ageController;
}
return TextEditingController();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.dark,
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
Padding(
padding: EdgeInsets.only(right: 5.sp),
child: PopupMenuButton(
icon: Icon(
Icons.more_vert,
color: Colors.black,
),
itemBuilder: (context) {
return [
PopupMenuItem<int>(
value: 0,
child: Text("Edit Profile"),
),
PopupMenuItem<int>(
value: 1,
child: Text("Delete Profile"),
),
];
},
onSelected: (value) async {
if (value == 0) {
setState(() {
editableText = true;
});
print(editableText);
} else if (value == 1) {
setState(() {
isLoading = true;
});
final ref = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await ref.delete();
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.delete();
DocumentSnapshot<Map<dynamic, dynamic>> snap =
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.get();
await FirebaseFirestore.instance
.collection("petDetails")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!),
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayUnion(snap.data()!["pets"]!),
});
setState(() {
isLoading = false;
});
Navigator.pop(context);
}
},
))
],
),
extendBodyBehindAppBar: true,
backgroundColor: kBackgroundColor,
body: isLoading
? Container(
width: 1.sw,
height: 0.4.sh,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 15.sp,
width: 15.sp,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Color(0xffFF8B6A),
),
),
],
),
)
: SafeArea(
child: Container(
//alignment: Alignment.center,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(15.sp),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// sBox(h: 10),
Text(
'Pet Information',
style: TextStyle(
color: Color(0xffF08519), fontSize: 0.05.sw),
),
// myPetTile()
SizedBox(
height: 0.05.sh,
),
Stack(
children: [
CircleAvatar(
radius: 0.095.sh,
backgroundColor: Color(0xffFF8B6A),
backgroundImage: profilePic == null
? NetworkImage(
widget.details["profilePicture"],
)
: null,
child: profilePic == null
? Container(
width: 0,
height: 0,
)
: ClipRRect(
borderRadius:
BorderRadius.circular(100),
child: Image.file(
File(
"${profilePic?.path}",
),
),
),
),
editableText
? Positioned(
right: 0.025.sw,
bottom: 0.005.sh,
child: GestureDetector(
onTap: () async {
profilePic = await ImagePicker()
.pickImage(
source: ImageSource.gallery);
setState(() {});
},
child: CircleAvatar(
backgroundColor: Color(0xffFF8B6A),
radius: 0.02.sh,
child: Icon(
Icons.camera_alt_outlined,
size: 0.05.sw,
color: Colors.white,
),
),
),
)
: Container(
width: 0,
height: 0,
)
],
),
SizedBox(
height: 0.02.sh,
),
...List.generate(
2,
(index) => Padding(
padding: EdgeInsets.only(
top: 0.02.sh, left: 0.05.sw, right: 0.05.sw),
child: TextField(
enabled: editableText,
controller: controllerChanger(index),
style: TextStyle(fontSize: 0.017.sh),
cursorColor: Colors.black,
decoration: InputDecoration(
label: Text(labels[index],
style: TextStyle(fontSize: 0.02.sh)),
labelStyle: TextStyle(color: Colors.black54),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10.sp),
borderSide:
BorderSide(color: Color(0xffFF8B6A))),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.sp),
),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10.sp),
borderSide:
BorderSide(color: Color(0xffFF8B6A))),
contentPadding:
EdgeInsets.symmetric(horizontal: 10.sp),
hintStyle: TextStyle(color: Colors.grey),
),
),
),
),
buttonWidget()
],
),
),
),
),
),
),
);
}
bool isLoadingEdit = false;
Widget buttonWidget() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 0.4.sw,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
backgroundColor: Color(0xffFF8B6A),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.sp),
),
),
onPressed: () async {
if (editableText) {
setState(() {
isLoadingEdit = true;
});
if (profilePic != null) {
final ref = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await ref.delete();
await uploadImages(path: profilePic!.path);
}
await FirebaseFirestore.instance
.collection("petsDetails")
.doc(widget.details["id"])
.update({
'name': nameController.text,
'age': ageController.text,
'breed': breedController.text,
'weight': weightController.text,
'profilePicture': profilePic != null
? imageUrl
: widget.details["profilePicture"],
'lastVaccinationDate':
widget.details["lastVaccinationDate"]
});
DocumentSnapshot<Map<String, dynamic>> snap =
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.get();
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!)
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!),
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayUnion(snap.data()!["pets"]!),
});
Navigator.pop(context);
setState(() {
isLoadingEdit = false;
editableText = false;
});
const snackBar = SnackBar(
content: Text("Your pet's details have been changed"),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PetFiles(
petId: widget.details["id"],
),
),
);
}
},
child: isLoadingEdit
? Container(
height: 15.sp,
width: 15.sp,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2.sp,
),
)
: Text(
editableText ? "Save Changes" : "Pet Health Records",
style:
TextStyle(color: Colors.white, fontSize: 0.03.sw),
),
),
),
],
),
SizedBox(
height: 0.01.sh,
),
],
);
}
}
You can check out their official docs for deleting collections here.
Or you can upgrade your project to blaze plan and use this extension which takes care of it for you.
Alternatively you can use NodeJS and FirebaseFunctions to do this task for you. Use this code snippet
async function deleteCollection(db, collectionPath, batchSize) {
const collectionRef = db.collection(collectionPath);
const query = collectionRef.orderBy('__name__').limit(batchSize);
return new Promise((resolve, reject) => {
deleteQueryBatch(db, query, resolve).catch(reject);
});
}
async function deleteQueryBatch(db, query, resolve) {
const snapshot = await query.get();
const batchSize = snapshot.size;
if (batchSize === 0) {
// When there are no documents left, we are done
resolve();
return;
}
// Delete documents in a batch
const batch = db.batch();
snapshot.docs.forEach((doc) => {
batch.delete(doc.ref);
});
await batch.commit();
// Recurse on the next process tick, to avoid
// exploding the stack.
process.nextTick(() => {
deleteQueryBatch(db, query, resolve);
});
}
index.js
import 'dart:convert';
import 'package:cmail/globals.dart' as globals;
import 'package:cmail/Background/seeMailBackground.dart';
import 'package:cmail/UIs/floatingactingbutton.dart';
import 'package:cmail/fontss/MyFlutterApp.dart';
import 'package:cmail/DrawerClass.dart';
import 'package:cmail/UIs/inboxUI.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import '../UIs/shimmirLoading.dart';
class mailList extends StatefulWidget {
int employeeId;
//String username;
mailList({Key? key, required this.employeeId}) : super(key: key);
#override
State<mailList> createState() => _mailListState();
}
class _mailListState extends State<mailList> {
late List<dynamic> mails;
TextEditingController subjectController = TextEditingController();
// final scrollController=ScrollController();
// late int start;
// late int limit;
bool flag1 = false;
bool flag2 = false;
bool icon1 = false;
bool icon2 = false;
int x = 4;
#override
void initState() {
super.initState();
flag1 = false;
flag2 = false;
icon1 = false;
icon2 = false;
}
Future<List<dynamic>> showList(int buttonPressed, String subject) async {
int sortBy = 1, sortType = 1;
if (buttonPressed == 0) {
if (flag1 == false) {
sortBy = 1;
sortType = 0;
flag1 = true;
} else {
sortBy = 1;
sortType = 1;
flag1 = false;
}
}
if (buttonPressed == 1) {
if (flag2 == false) {
sortBy = 0;
sortType = 0;
flag2 = true;
} else {
sortBy = 0;
sortType = 1;
flag2 = false;
}
}
try {
final String currentTimeZone =
await FlutterNativeTimezone.getLocalTimezone();
var response = await http.post(
Uri.parse(
"https://www.myciright.com/Ciright/api/cirightMailApp/m1351188"),
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
'Charset': 'utf-8',
'Authorization':
'Basic bWVodWwua0BjaXJpZ2h0LmNvbTpDaXJpZ2h0QDEyMw=='
},
body: jsonEncode({
"employeeId": widget.employeeId,
"start": 0,
"limit": 1000,
"verticalId": 18,
"subject": subject,
"sortBy": sortBy,
"sortType": sortType,
"timeZone": currentTimeZone
}));
var data = jsonDecode(response.body.toString());
if (response.statusCode == 200) {
mails = await data['data']['mailList'];
print(mails);
print('List successful');
return Future.value(mails);
} else {
print('failed');
return [];
}
} catch (e) {
print(e.toString());
return [];
}
}
#override
Widget build(BuildContext context) {
return seeMailBackground(
background: globals.background,
child: floatingactionbutton(
employeeid: widget.employeeId,
child: Scaffold(
drawer: DrawerClass(lemployeeId: widget.employeeId),
appBar: AppBar(
title: Text(
'Inbox',
style: TextStyle(color: Colors.black),
),
iconTheme: IconThemeData(
color: Colors.black, //change your color here
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: () {
setState(() {
x = 1;
icon1 = !icon1;
});
},
icon: icon1
? Icon(
MyFlutterApp.sort_name_down,
color: Colors.black,
size: 20,
)
: Icon(
MyFlutterApp.sort_name_up,
color: Colors.black,
size: 20,
)),
IconButton(
onPressed: () {
setState(() {
x = 0;
icon2 = !icon2;
});
},
icon: icon2
? Icon(MyFlutterApp.sort_number_down,
color: Colors.black, size: 20)
: Icon(MyFlutterApp.sort_number_up,
color: Colors.black, size: 20)),
],
),
SizedBox(
width: 25,
)
],
backgroundColor: Colors.white,
elevation: 3,
),
body: Column(
children: [
SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.0),
child: TextField(
cursorColor: Colors.grey,
controller: subjectController,
onSubmitted: (value) {
setState(() {
showList(x, subjectController.text);
});
},
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(vertical: 1, horizontal: 20),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.greenAccent),
),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.grey, fontSize: 18),
),
),
),
Expanded(
child: RefreshIndicator(
onRefresh: () {
return Future.delayed(
Duration(seconds: 1),
() {
setState(() {
showList(4, "");
});
},
);
},
child: FutureBuilder<List<dynamic>>(
future: showList(x, subjectController.text),
builder: (ctx, snapshot) {
List<dynamic>? mail = snapshot.data;
switch (snapshot.connectionState) {
case ConnectionState.done:
if(mail!.isEmpty){
return Center(child: Text("No Inbox Mails...",style: TextStyle(color: Colors.grey,fontSize: 20),),);
}
return _buildListView(mail!);
default:
return _buildShimmerScreen();
}
},
),
),
),
],
),
),
),
);
}
Widget _buildListView(List<dynamic> contacts) {
return ListView.builder(
itemBuilder: (ctx, idx) {
return inboxUI(
SenderSubject: contacts[idx]['subject'],
senderName: contacts[idx]['employeeName'],
date: contacts[idx]['createdDate'].toString(),
empid: contacts[idx]['employeeId'],
isStarred: contacts[idx]['isStarred'],
mailId: contacts[idx]['mailId'],
starMailId: contacts[idx]['starMailId'],
loginempid: widget.employeeId,
isAttachment: contacts[idx]['isAttachment'],
subject: contacts[idx]['subject'],
mailContent: contacts[idx]['mailContent'],
isRead: contacts[idx]['isRead']);
},
itemCount: contacts.length,
);
}
Widget _buildShimmerScreen() {
return ListView.builder(
itemBuilder: (ctx, idx) {
return shimmirLoading();
},
itemCount: 9,
);
}
// Widget _buildLoadingScreen() {
// return Center(
// child: Container(
// width: 50,
// height: 50,
// child: CircularProgressIndicator(),
// ),
// );
// }
}
I want to paginate for 10 mails at a time and change the variable start and limit by 10 when the user reaches the limit of seeing 10 mails. I tried using the scroll controller in listview builder but i am not able to achieve what is expected. Please help me out and thank you in advance for any inputs.
Keyboard triggers the api calling while closing and opening
I have search bar I didn't pass anything inside the search bar but when I click the search bar The api call will run.
I don't know why that thing was happen I tried several ways but It won't work
Even Inside the keyboard I choose the one hand keyboard that time also api will run
Also tried the Focusnode also.
class PopupNaviagator extends StatefulWidget {
var body;
String leadsName = "";
Map<String, dynamic> listValues;
PopupNaviagator(this.listValues);
var data;
String pageData = "";
double totalPageCount = 0;
int pageIncrementer = 1;
#override
_PopupNavigatorState createState() => _PopupNavigatorState();
}
class _PopupNavigatorState extends State<PopupNaviagator> {
Utils util = new Utils();
bool isSearching = false;
#override
void initState() {
super.initState();
}
String searchingText = "";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
titleSpacing: 0,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: util.getColors(1001),
stops: [0.1, 5.0],
),
),
),
title: !isSearching
? Text("Select Search Type")
: TextField(
autofocus: true,
autocorrect: true,
onChanged: (value) {
searchingText = value;
},
cursorColor: Colors.white,
onSubmitted: (value) {
searchingText = value;
campaignAPI(
widget.listValues["colname"].toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
},
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
icon: Icon(Icons.search),
hintText: "Search ",
hintStyle: TextStyle(color: Colors.white)),
),
actions: <Widget>[
isSearching
? IconButton(
icon: Icon(Icons.cancel),
onPressed: () {
setState(() {
searchingText = "";
this.isSearching = false;
campaignAPI(
widget.listValues["colname"].toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
/* filteredCountries = countries;*/
});
},
)
: IconButton(
icon: Icon(Icons.search),
onPressed: () {
setState(() {
this.isSearching = true;
});
},
)
],
),
body: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5))),
child: Scaffold(
body: FutureBuilder(
future: campaignAPI(widget.listValues["colname"].toString(), "1",
searchingText, 0),
builder: (context, snapshot) {
if (snapshot.hasData) {
var body;
if (widget.data == null) {
body = snapshot.data;
} else {
body = widget.data;
}
final records = body["list_records"];
widget.pageData = body["PageValues"];
widget.totalPageCount =
(body["TotalRecordCount"] / 5).toDouble();
return Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (records.length != 0) ...[
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(
top: 0,
bottom: 0,
),
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: records.length,
itemBuilder: (context, index) {
Map<String, dynamic> pickerValues =
records[index];
String titleName =
pickerValues["viewcol_value"]
.toString();
return Container(
margin: const EdgeInsets.all(5.00),
decoration: new BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.grey, width: 1.0),
borderRadius: new BorderRadius.all(
Radius.circular(3.0)),
),
child: FlatButton(
padding: EdgeInsets.all(8.0),
onPressed: () {
setState(() {
List<String> strArr = [
titleName,
pickerValues["rec_id"].toString(),
widget.listValues["colname"]
];
Navigator.pop(context, strArr);
});
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(titleName.toString()),
Icon(
Icons.check_circle_outlined,
color: Colors.grey,
),
]),
),
);
}),
),
] else ...[
Container(
height: MediaQuery.of(context).size.height / 1.4,
child: Center(
child: Container(
padding: EdgeInsets.all(65),
child: Text(
"No Record Found",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.black),
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
width: 2,
),
)),
),
),
],
if (records.length != 0) ...[
Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
if (widget.pageIncrementer > 1) {
widget.pageIncrementer--;
campaignAPI(
widget.listValues["colname"]
.toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
setState(() {});
} else {
util.showToast("No records to show");
}
},
child: Icon(Icons.arrow_left_rounded,
size: 50, color: Colors.white),
),
Text(
widget.pageData,
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
InkWell(
onTap: () {
if (widget.totalPageCount > 1 &&
widget.totalPageCount >=
widget.pageIncrementer) {
widget.pageIncrementer++;
campaignAPI(
widget.listValues["colname"]
.toString(),
widget.pageIncrementer.toString(),
searchingText, // search key
1, // flag
);
} else {
util.showToast("No reocrds to show");
}
},
child: Icon(Icons.arrow_right_rounded,
size: 50, color: Colors.white),
),
],
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: util.getColors(1001),
stops: [0.1, 5.0],
),
),
)
]
],
),
),
);
} else if (snapshot.hasError) {
return Text('${snapshot.error.toString()}');
}
return Center(
child: CircularProgressIndicator(),
);
},
),
),
));
}
campaignAPI(
String field_col, String page_no, String searchValue, int flag) async {
Utils util = new Utils();
SharedPreferences prefs = await SharedPreferences.getInstance();
final accessKey = prefs.getString('access_key');
final companyName = prefs.getString('company_name');
Object requestParam = {
"companyname": companyName,
"access_key": accessKey.toString(),
"field_col": field_col,
"page_no": page_no,
"searchValue": searchValue,
};
print(requestParam.toString());
APIS apis = new APIS();
Uri url = Uri.parse(apis.searchquickcreate);
util.prints(url);
util.prints(requestParam);
final response = await http.post(url, body: requestParam);
if (response.statusCode == 200) {
final body = json.decode(response.body);
print(body);
String status = body["status"];
if (status != "failed") {
if (flag == 1) {
setState(() {
widget.data = body;
});
}
return body;
} else {
util.logOut(context);
return body;
}
} else {
Navigator.pop(context);
util.showToast("Server Error !");
throw Exception("Server Error !");
}
}
}
I have a screen to add a customer's details. Name, company, mobile no.,email,profile picture. I have added validator to all the fields. Validator is working for all the fields but not for one field, the top one(Name). I dont know why. When I place the field below all the fields then the validator works but I want to keep the field on top. I want Name field to contain some value.
add_person.dart
import 'dart:io';
import 'package:email_validator/email_validator.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/models/language.dart';
import 'package:vers2cts/models/languages_widget.dart';
import 'package:vers2cts/models/languages_model.dart';
import 'package:vers2cts/screens/people_list.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/form_helper.dart';
import 'search_contacts.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:image_picker/image_picker.dart';
class AddPerson extends StatefulWidget {
String uname;
final String appBarTitle;
final CustomerModel customer;
AddPerson(this.uname,this.customer,this.appBarTitle);
#override
State<StatefulWidget> createState() {
return AddPersonState(uname,customer,appBarTitle);
}
}
class AddPersonState extends State<AddPerson> {
GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();
String uname,email,mobnum;
AddPersonState(this.uname,this.customer,this.appBarTitle);
bool engcheckbox=false;
String appBarTitle;
CustomerModel customer=new CustomerModel();
LanguagesModel langs=new LanguagesModel();
DBService dbService=new DBService();
bool showPassword = false;
DateTime _date=DateTime.now();
TextEditingController datefield=TextEditingController();
PickedFile _imageFile;
final ImagePicker _picker=ImagePicker();
TextEditingController custfNameController = TextEditingController();
TextEditingController custlNameController = TextEditingController();
TextEditingController custMobileNoController = TextEditingController();
TextEditingController custCompanyController = TextEditingController();
TextEditingController addrController = TextEditingController();
TextEditingController custEmailController = TextEditingController();
void getImage(ImageSource source) async{
final pickedFile=await _picker.getImage(
source:source);
setState(() {
_imageFile=pickedFile;
customer.cust_photo = _imageFile.path;
});
}
Future<Null> _selectDate(BuildContext context)async {
DateTime _datePicker = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime(1947),
lastDate: DateTime(2030),);
if (_datePicker != null && _datePicker != _date) {
setState(() {
_date = _datePicker;
String formattedDate = DateFormat('dd-MM-yyyy').format(_date);
datefield.text=formattedDate.toString();
print(datefield.text);
});
}
}
#override
Widget build(BuildContext context){
var selectedLanguages = languages.where((element) => element.selected);
TextStyle textStyle=Theme.of(context).textTheme.title;
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
var _minimumPadding = 5.0;
custfNameController.text = customer.first_name;
custlNameController.text = customer.last_name;
custMobileNoController.text = customer.mob_num;
custCompanyController.text=customer.org_name;
addrController.text=customer.addr;
custEmailController.text=customer.email_id;
return WillPopScope(
onWillPop: () {
moveToLastScreen();
},
child: Scaffold(
appBar: AppBar(
title: Text(appBarTitle),
elevation: 1,
actions: [
IconButton(
icon: Icon(
Icons.search,
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => SearchContacts()));
},
),
],
),
body:Form(
key: globalFormKey,
child: Container(
padding: EdgeInsets.only(left: 16, top: 25, right: 16),
child:
GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: ListView(
children: [
ImageProfile(customer.cust_photo),
SizedBox(
height: 35,
),
buildTextField("Name",custfNameController,
(value) => updatefName(value),(value)=>checkfname(value)),
buildTextField("Mobile",custMobileNoController,
(value) => updateMobile(value),(value)=>checkmobile(value)),
buildTextField("Company",custCompanyController,
(value) => updateCompany(value),(value)=>checkempty(value)),
buildTextField("Email",custEmailController,
(value) => updateEmail(value),(value)=>checkmail(value)),
Text("Address"),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: addrController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: const BorderSide(width: 2.0),)),
keyboardType: TextInputType.multiline,
minLines: 5,//Normal textInputField will be displayed
maxLines: 5, // when user presses enter it will adapt to it
onChanged: (value) {
this.customer.addr = value;
},
),
),
SizedBox(
height: height * 0.02,
),
Divider(),
SizedBox(
height: height * 0.02,
),
Row(
children: <Widget>[
Expanded(
child: Text("Show on Call",
style: textStyle,
)
),
SizedBox(
height: height * 0.02,
),
SizedBox(
height: 35,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
OutlineButton(
padding: EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
onPressed: () {},
child: Text("CANCEL",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.black)),
),
RaisedButton(
onPressed: () {
setState(() {
_saveCustomer();
});
},
//color: Colors.purpleAccent,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.symmetric(horizontal: 50),
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
child: Text(
"SAVE",
style: TextStyle(
fontSize: 14,
letterSpacing: 2.2,
color: Colors.white),
),
)
],
)
],
),
),
),
)));
}
Widget bottomSheet(){
return Container(
height: 100,
width: MediaQuery.of(context).size.width ,
margin: EdgeInsets.symmetric(
horizontal:20,
vertical:20,
),
child: Column(
children: <Widget>[
Text("Choose profile photo",
style: TextStyle(fontSize: 20.0),),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
onPressed: (){
getImage(ImageSource.camera);
},
icon:Icon(Icons.camera,color: Theme.of(context).primaryColor,), label:Text("camera")),
FlatButton.icon(
onPressed: (){
getImage(ImageSource.gallery);
},
icon:Icon(Icons.photo_library), label:Text("Gallery"))
],
)
],
),
);
}
//This is for 1st 3 Textfields name,mobile,company
Widget buildTextField(String labelText,tController,Function onChanged,Function validator) {
return Padding(
padding: const EdgeInsets.only(bottom: 35.0),
child: TextFormField(
controller:tController,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 3),
labelText: labelText,
labelStyle:TextStyle(),
floatingLabelBehavior: FloatingLabelBehavior.always,
),
onChanged: (String value) {
return onChanged(value);
},
validator:(String value) {
return validator(value);
},
),
);
}
void moveToLastScreen() {
Navigator.pop(context, true);
}
bool validateAndSave() {
final form = globalFormKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
void _saveCustomer() async {
if (validateAndSave()) {
var result;
var res;
var mob = await dbService.checkcustMobno(mobnum,uname);
var mail = await dbService.checkcustEmail(email,uname);
if (mob != null) {
FormHelper.showAlertDialog(
context, 'Error',
'Customer with this mobile number already exists');
}
else if (mail != null) {
FormHelper.showAlertDialog(
context, 'Error',
'Customer with this email id already exists');
}else {
if (customer.cust_id != null) { // Case 1: Update operation
result = await dbService.updateCustomer(customer);
} else { // Case 2: Insert Operation
result = await dbService.insertCustomer(customer);
}
if (result != 0) { // Success
moveToLastScreen();
FormHelper.showAlertDialog(
context, 'Status', 'Customer Saved Successfully');
} else { // Failure
FormHelper.showAlertDialog(
context, 'Status', 'Problem Saving Customer');
}
languages.forEach((lang) async {
print("${lang.name} : ${lang.selected}");
if (lang.selected) {
LanguagesModel language = LanguagesModel(lang: lang.name);
print("customer id from lang");
print(customer.cust_id);
await dbService.insertLanguages(language);
}
});
}
}
}
String updatefName(String value) {
customer.first_name = custfNameController.text;
customer.cre_by=uname;
print(uname);
}
String updatelName(String value) {
if(value.isEmpty)
customer.last_name = " ";
else
customer.last_name = custlNameController.text;
}
String updateMobile(value) {
customer.mob_num = custMobileNoController.text;
mobnum=value;
}
String updateEmail(value) {
customer.email_id = custEmailController.text;
email=value;
}
String updateCompany(String value) {
customer.org_name = custCompanyController.text;
}
String checkfname(String value){
if(value.isEmpty)
{
return "First name can't be null";
}
return null;
}
String checkempty(String value){
print("checkempty called");
if(value.isEmpty)
{
return "Can't be null";
}
return null;
}
String checkmobile(String value) {
print("checkmobile called");
if(value.isEmpty)
{
return 'Please enter phone no.';
}
if(value.length<6)
{
return 'Please enter a valid phone no.';
}
return null;
}
String checkmail(String value){
print("checkmail called");
if(value.isEmpty)
{
return 'Please Enter E-mail address';
}
if (!EmailValidator.validate(value)) {
return 'Please enter a valid Email';
}
return null;
}
}
Replace the ListView (that the buildTextFields are its children) with a Column and wrap the Column with a SingleChildScrollView.
Firstly when i downloaded the plugin for Flutter Bluetooth serial few months ago, it was working fine.
But now, when i run the app it throws the following exceptions and errors.
1.When i choose the devices and try to connect them this error occurs
When i tap on the refresh button this error occurred
Here is the code for Bluetooth plugin.
import 'dart:async';
import 'dart:convert';
// For using PlatformException
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
class BluetoothApp extends StatefulWidget {
#override
_BluetoothAppState createState() => _BluetoothAppState();
}
class _BluetoothAppState extends State<BluetoothApp> {
// Initializing the Bluetooth connection state to be unknown
BluetoothState _bluetoothState = BluetoothState.UNKNOWN;
// Initializing a global key, as it would help us in showing a SnackBar later
final GlobalKey<ScaffoldMessengerState> _scaffoldKey = new GlobalKey<ScaffoldMessengerState>();
// Get the instance of the Bluetooth
FlutterBluetoothSerial _bluetooth = FlutterBluetoothSerial.instance;
// Track the Bluetooth connection with the remote device
BluetoothConnection connection;
int _deviceState;
bool isDisconnecting = false;
Map<String, Color> colors = {
'onBorderColor': Colors.green,
'offBorderColor': Colors.red,
'neutralBorderColor': Colors.transparent,
'onTextColor': Colors.green[700],
'offTextColor': Colors.red[700],
'neutralTextColor': Colors.blue,
};
// To track whether the device is still connected to Bluetooth
bool get isConnected => connection != null && connection.isConnected;
// Define some variables, which will be required later
List<BluetoothDevice> _devicesList = [];
BluetoothDevice _device;
bool _connected = false;
bool _isButtonUnavailable = false;
#override
void initState() {
super.initState();
// Get current state
FlutterBluetoothSerial.instance.state.then((state) {
setState(() {
_bluetoothState = state;
});
});
_deviceState = 0; // neutral
// If the bluetooth of the device is not enabled,
// then request permission to turn on bluetooth
// as the app starts up
enableBluetooth();
// Listen for further state changes
FlutterBluetoothSerial.instance
.onStateChanged()
.listen((BluetoothState state) {
setState(() {
_bluetoothState = state;
if (_bluetoothState == BluetoothState.STATE_OFF) {
_isButtonUnavailable = true;
}
getPairedDevices();
});
});}
#override
void dispose() {
// Avoid memory leak and disconnect
if (isConnected) {
isDisconnecting = true;
connection.dispose();
connection = null;
}
super.dispose();}
// Request Bluetooth permission from the user
Future<void> enableBluetooth() async {
// Retrieving the current Bluetooth state
_bluetoothState = await FlutterBluetoothSerial.instance.state;
// If the bluetooth is off, then turn it on first
// and then retrieve the devices that are paired.
if (_bluetoothState == BluetoothState.STATE_OFF) {
await FlutterBluetoothSerial.instance.requestEnable();
await getPairedDevices();
return true;
} else {
await getPairedDevices();
}
return false;}
// For retrieving and storing the paired devices
// in a list.
Future<void> getPairedDevices() async {
List<BluetoothDevice> devices = [];
// To get the list of paired devices
try {
devices = await _bluetooth.getBondedDevices();
} on PlatformException {
print("Error");}
// It is an error to call [setState] unless [mounted] is true.
if (!mounted) {
return;}
// Store the [devices] list in the [_devicesList] for accessing
// the list outside this class
setState(() {
_devicesList = devices;
});}
// Now, its time to build the UI
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("Pair Bluetooth Device"),
backgroundColor: Colors.green[900],
actions: <Widget>[
FlatButton.icon(
icon: Icon(
Icons.refresh,
color: Colors.white,
),
label: Text(
"Refresh",
style: TextStyle(
color: Colors.white,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
splashColor: Colors.deepPurple,
onPressed: () async {
// So, that when new devices are paired
// while the app is running, user can refresh
// the paired devices list.
await getPairedDevices().then((_) {
show('Device list refreshed');
});
},
),
],
),
body: Container(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Visibility(
visible: _isButtonUnavailable &&
_bluetoothState == BluetoothState.STATE_ON,
child: LinearProgressIndicator(
backgroundColor: Colors.yellow,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
),
),
Padding(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(
'Enable Bluetooth',
style: TextStyle(
color: Colors.black,
fontSize: 16,
),
),
),
Switch(
value: _bluetoothState.isEnabled,
onChanged: (bool value) {
future() async {
if (value) {
await FlutterBluetoothSerial.instance
.requestEnable();
} else {
await FlutterBluetoothSerial.instance
.requestDisable();
}
await getPairedDevices();
_isButtonUnavailable = false;
if (_connected) {
_disconnect();
}
}
future().then((_) {
setState(() {});
});
},
)
],
),
),
Stack(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(
"PAIRED DEVICES",
style: TextStyle(fontSize: 24, color: Colors.blue,
fontFamily: 'RussoOne'
),
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Device:',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
DropdownButton(
items: _getDeviceItems(),
onChanged: (value) =>
setState(() => _device = value),
value: _devicesList.isNotEmpty ? _device : null,
),
ElevatedButton(
onPressed: _isButtonUnavailable
? null
: _connected ? _disconnect : _connect,
child:
Text(_connected ? 'Disconnect' : 'Connect'),
),
],
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Card(
shape: RoundedRectangleBorder(
side: new BorderSide(
color: _deviceState == 0
? colors['neutralBorderColor']
: _deviceState == 1
? colors['onBorderColor']
: colors['offBorderColor'],
width: 3,
),
borderRadius: BorderRadius.circular(4.0),
),
elevation: _deviceState == 0 ? 4 : 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
"DEVICE 1",
style: TextStyle(
fontSize: 20,
color: _deviceState == 0
? colors['neutralTextColor']
: _deviceState == 1
? colors['onTextColor']
: colors['offTextColor'],
),
),
),
TextButton(
onPressed: _connected
? _sendOnMessageToBluetooth
: null,
child: Text("ON"),
),
TextButton(
onPressed: _connected
? _sendOffMessageToBluetooth
: null,
child: Text("OFF"),
),
],
),
),
),
),
],
),
Container(
color: Colors.blue,
),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"NOTE: If you cannot find the device in the list, please pair the device by going to the bluetooth settings",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
SizedBox(height: 15),
TextButton.icon(
//color: Colors.blueAccent,
style: TextButton.styleFrom(
elevation: 2,
backgroundColor: Colors.blueAccent,
),
icon: Icon(Icons.bluetooth,
color: Colors.white,
),
label: Text("Settings",
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white
),
),
onPressed: () {
FlutterBluetoothSerial.instance.openSettings();
},
),
SizedBox(height: 15),
TextButton(
//color: Colors.black,
style: TextButton.styleFrom(
backgroundColor: Colors.black,
),
child: Text("Home",
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
)
],
),
),
),
);}
// Create the List of devices to be shown in Dropdown Menu
List<DropdownMenuItem<BluetoothDevice>> _getDeviceItems() {
List<DropdownMenuItem<BluetoothDevice>> items = [];
if (_devicesList.isEmpty) {
items.add(DropdownMenuItem(
child: Text('NONE'),
));
} else {
_devicesList.forEach((device) {
items.add(DropdownMenuItem(
child: Text(device.name),
value: device,
));
});
}
return items;}
// Method to connect to bluetooth
void _connect() async {
setState(() {
_isButtonUnavailable = true;
});
if (_device == null) {
show('No device selected');
} else {
if (!isConnected) {
await BluetoothConnection.toAddress(_device.address)
.then((_connection) {
print('Connected to the device');
connection = _connection;
setState(() {
_connected = true;
});
connection.input.listen(null).onDone(() {
if (isDisconnecting) {
print('Disconnecting locally!');
} else {
print('Disconnected remotely!');
}
if (this.mounted) {
setState(() {});
}
});
}).catchError((error) {
print('Cannot connect, exception occurred');
print(error);
});
show('Device connected');
setState(() => _isButtonUnavailable = false);
}} }
// void _onDataReceived(Uint8List data) {
// // Allocate buffer for parsed data
// int backspacesCounter = 0;
// data.forEach((byte) {
// if (byte == 8 || byte == 127) {
// backspacesCounter++;
// }
// });
// Uint8List buffer = Uint8List(data.length - backspacesCounter);
// int bufferIndex = buffer.length;
// // Apply backspace control character
// backspacesCounter = 0;
// for (int i = data.length - 1; i >= 0; i--) {
// if (data[i] == 8 || data[i] == 127) {
// backspacesCounter++;
// } else {
// if (backspacesCounter > 0) {
// backspacesCounter--;
// } else {
// buffer[--bufferIndex] = data[i];
// }
// }
// }
// }
// Method to disconnect bluetooth
void _disconnect() async {
setState(() {
_isButtonUnavailable = true;
_deviceState = 0;
});
await connection.close();
show('Device disconnected');
if (!connection.isConnected) {
setState(() {
_connected = false;
_isButtonUnavailable = false;
});
}}
// Method to send message,
// for turning the Bluetooth device on
void _sendOnMessageToBluetooth() async {
connection.output.add(utf8.encode("1" + "\r\n"));
await connection.output.allSent;
show('Device Turned On');
setState(() {
_deviceState = 1; // device on
});}
// Method to send message,
// for turning the Bluetooth device off
void _sendOffMessageToBluetooth() async {
connection.output.add(utf8.encode("0" + "\r\n"));
await connection.output.allSent;
show('Device Turned Off');
setState(() {
_deviceState = -1; // device off
});}
// Method to show a Snackbar,
// taking message as the text
Future show(
String message, {
Duration duration: const Duration(seconds: 3),
}) async {
await new Future.delayed(new Duration(milliseconds: 100));
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content:Text(
message,
),
duration: duration,
),
); }}
I have searched a lot about these errors on internet but didn't find a satisfactory solution.
Please solve this problem.
I will be very grateful.
Thanks in advance.
Try making the call conditional (using '?.') or adding a null check to the target ('!').
_scaffoldKey.currentState?.showSnackBar(
SnackBar(
content:Text(
message,
),
duration: duration,
),