Related
So I made a CRUD app with Firebase Firestore in Flutter. I have this error where it says
Exception caught by gesture
═══════════════════════
a document path must be a non-empty string
'package:cloud_firestore/src/collection_reference.dart':
package:cloud_firestore/src/collection_reference.dart:1
Failed assertion: line 116 pos 14: 'path.isNotEmpty'
I build this app with various tutorial videos in Youtube. I can make the Create, Read, and Delete features but I face this problem with Update features. Here's the code ...or check this Github https://github.com/rayhanyovi/Dapurku
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:dapurkuu/warna.dart';
import 'package:dapurkuu/widget.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
//=====================================
const Color Red = Color(0xFFDA4040);
const Color Blue = Color(0xFF5F52EE);
const Color Black = Color(0xFF3A3A3A);
const Color Grey = Color(0xFF717171);
const Color BGColor = Color(0xFFEEEFF5);
final controllerName = TextEditingController();
final controllerAge = TextEditingController();
final controllerBirthday = TextEditingController();
final updateName = TextEditingController();
final updateAge = TextEditingController();
final updateBirthday = TextEditingController();
//=====================================
class User {
String id;
final String name;
final int age;
final DateTime birthday;
User({
this.id = '',
required this.name,
required this.age,
required this.birthday,
});
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'age': age,
'birthday': birthday,
};
static User fromJson(Map<String, dynamic> json) => User(
id: json['id'],
name: json['name'],
age: json['age'],
birthday: (json['birthday'] as Timestamp).toDate(),
);
}
//=====================================
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(statusBarColor: Colors.transparent));
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Test",
home: Home(),
);
}
}
//=====================================
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final CollectionReference _users =
FirebaseFirestore.instance.collection('users');
#override
Widget build(BuildContext context) {
Future createUser(User user) async {
final docUser = FirebaseFirestore.instance.collection('users').doc();
user.id = docUser.id;
final json = user.toJson();
await docUser.set(json);
Future updateUser(User user) async {
final docUser = FirebaseFirestore.instance.collection('users').doc();
user.id = docUser.id;
final json = user.toJson();
await docUser.update(json);
}
}
Widget buildUser(User user) {
return Container(
margin: EdgeInsets.only(
right: 20,
left: 20,
bottom: 15,
),
child: Material(
child: ListTile(
onTap: () {
print("card");
},
contentPadding:
EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 15),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
tileColor: Colors.white,
title: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(
user.name,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jumlah: ${user.age}',
),
Text(
'Kadaluarsa: ${DateFormat('dd MMMM yyyy').format(user.birthday)}')
],
),
trailing: Wrap(spacing: 0, children: [
IconButton(
icon: Icon(Icons.edit),
iconSize: 24,
color: Colors.black,
onPressed: () async {
await Edit(context, createUser);
},
),
IconButton(
icon: Icon(Icons.delete),
iconSize: 24,
color: Colors.red,
onPressed: () {
final docUser = FirebaseFirestore.instance
.collection('users')
.doc(user.id);
docUser.delete();
},
),
]),
),
),
);
}
return Scaffold(
backgroundColor: BGColor,
appBar: _AppBar(),
body: Column(
children: [
/* JUDUL */
Column(
children: [
Container(
margin: EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
child: SearchBox()),
Container(
margin: EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
child: Text(
'Bahan Dapurmu',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Black,
),
),
)
],
),
/* STREAM BUILDER */
StreamBuilder(
stream: readUsers(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final users = snapshot.data!;
return Expanded(
child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: users.map(buildUser).toList(),
),
);
} else if (snapshot.hasError) {
return Container(
child: Text("data kosong"),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Create(context, createUser);
},
child: Icon(Icons.add),
),
);
}
Edit(BuildContext context, Future<dynamic> updateUser(User user)) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Tambahkan bahan"),
content: Column(
children: [
TextField(
decoration: const InputDecoration(
labelText: 'Nama',
),
controller: updateName,
),
TextField(
decoration: const InputDecoration(
labelText: 'Umur',
),
controller: updateAge,
keyboardType: TextInputType.number,
),
TextField(
controller: updateBirthday,
//editing controller of this TextField
decoration: InputDecoration(
labelText: "Enter Date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1950),
//DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2100));
if (pickedDate != null) {
print(
pickedDate);
//pickedDate output format => 2021-03-10 00:00:00.000
//formatted date output using intl package => 2021-03-16
setState(() {
updateBirthday.text = pickedDate
.toString(); //set output date to TextField value.
});
} else {}
},
),
],
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("Ubah Data"),
onPressed: () {
final user = User(
name: updateName.text,
age: int.parse(updateAge.text),
birthday: DateTime.parse(updateBirthday.text),
);
final docUser = FirebaseFirestore.instance
.collection('users')
.doc(user.id);
updateUser(user);
}),
],
);
});
}
Create(BuildContext context, Future<dynamic> createUser(User user)) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Tambahkan bahan"),
content: Column(
children: [
TextField(
decoration: const InputDecoration(
labelText: 'Nama',
),
controller: controllerName,
),
TextField(
decoration: const InputDecoration(
labelText: 'Umur',
),
controller: controllerAge,
keyboardType: TextInputType.number,
),
TextField(
controller: controllerBirthday,
//editing controller of this TextField
decoration: InputDecoration(
labelText: "Enter Date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1950),
//DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2100));
if (pickedDate != null) {
print(
pickedDate);
//pickedDate output format => 2021-03-10 00:00:00.000
//formatted date output using intl package => 2021-03-16
setState(() {
controllerBirthday.text = pickedDate
.toString(); //set output date to TextField value.
});
} else {}
},
),
],
),
actions: <Widget>[
MaterialButton(
elevation: 5.0,
child: Text("Tambahkan"),
onPressed: () {
final user = User(
name: controllerName.text,
age: int.parse(controllerAge.text),
birthday: DateTime.parse(controllerBirthday.text),
);
createUser(user);
}),
],
);
});
}
Stream<List<User>> readUsers() => FirebaseFirestore.instance
.collection('users')
.snapshots()
.map((snapshot) =>
snapshot.docs.map((doc) => User.fromJson(doc.data())).toList());
}
//=====================================
AppBar _AppBar() {
return AppBar(
elevation: 0,
backgroundColor: BGColor,
title: Center(
child: Text(
"Dapurku",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Black,
),
),
),
);
}
//=====================================
class UpdateButton extends StatelessWidget {
const UpdateButton({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: IconButton(
icon: Icon(Icons.edit),
iconSize: 24,
color: Colors.black,
onPressed: () {},
),
);
}
}
//=====================================
class SearchBox extends StatelessWidget {
const SearchBox({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 10),
child: const TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0),
prefixIcon: Icon(
Icons.search,
color: Black,
size: 20,
),
prefixIconConstraints: BoxConstraints(
maxHeight: 20,
minWidth: 25,
),
border: InputBorder.none,
hintText: "Cari Bahan...",
hintStyle: TextStyle(
color: Grey,
)),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
);
}
}
Can you tell me what I did wrong or help me solve the problem? I've been looking for it anywhere and solving this problem for days. It is for my school assignment :/
ihave this error from server response
this is the models and api
u can find full source code here https://github.com/alihassan75/project
// To parse this JSON data, do
//
// final task = taskFromJson(jsonString);
import 'dart:collection';
import 'dart:core';
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
//List<Task> taskFromJson(String str) => List<Task>.from(json.decode(str).map((x) => Task.fromJson(x)));
//String taskToJson(List<Task> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Project {
Project({
this.id,
required this.project_name,
this.created_at,
// required this.start_date,
//required this.end_date,
required this.user,
});
int? id;
final String? project_name;
DateTime? created_at;
// final DateTime? start_date;
//final DateTime? end_date;
int user;
factory Project.fromJson(Map<String, dynamic> json) => Project(
id: json["id"],
project_name: json["project_name"],
created_at: DateTime.parse(json["created_at"]),
// start_date: DateTime.parse(json["start_date"]),
//end_date: DateTime.parse(json["end_date"]),
user: json["user"],
);
Map<String, dynamic> toJson() => {
"id": id,
"project_name": project_name,
"created_at": created_at?.toIso8601String(),
// "start_date": start_date?.toIso8601String(),
//"end_date": end_date?.toIso8601String(),
"user": user,
};
}
class ProjectProvider with ChangeNotifier{
ProjectProvider(){
this.fetchProject();
}
List<Project> _project = [];
List<Project> get project {
return [..._project];
}
void addProject(Project project) async {
final response = await http.post(Uri.parse('http://mostafahamed.pythonanywhere.com/project/api'),
headers: {"Content-Type": "application/json"}, body: json.encode(project));
if (response.statusCode == 201) {
project.id = json.decode(response.body)['id'];
_project.add(project);
notifyListeners();
print('sucess');
}
else {
print(response.body);
throw Exception('Failed to add project');
}
}
void deleteProject(Project project) async {
final response =
await http.delete(Uri.parse('http://mostafahamed.pythonanywhere.com/project/api${project.id}/'));
if (response.statusCode == 204) {
_project.remove(project);
notifyListeners();
print('sucess');
}
else {
throw Exception('Failed to load tasks');
}
}
fetchProject() async{
final response = await http
.get(Uri.parse('http://mostafahamed.pythonanywhere.com/project/api?format=json'));
if (response.statusCode==200){
var data = json.decode(response.body)as List;
_project=data.map<Project>((json) => Project.fromJson(json)).toList();
notifyListeners();
print('sucess');
}
else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load projects');
}
}
}
here i call back the post method with adding data function
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:project/model/project_model.dart';
//import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:project/model/user_Model.dart';
import 'home_page02.dart';
class NewProject extends StatefulWidget {
const NewProject({Key? key}) : super(key: key);
#override
State<NewProject> createState() => _NewProjectState();
}
class _NewProjectState extends State<NewProject> {
final TextEditingController projectname = TextEditingController();
//TextEditingController datelController = TextEditingController();
//DateTime _selectedDate = DateTime.now();
//DateTime currentDate = DateTime.now();
// Future<void> _selectDate(BuildContext context) async {
// final DateTime? pickedDate = await showDatePicker(
// context: context,
// initialDate: currentDate,
// firstDate: DateTime(2015),
// lastDate: DateTime(2050));
// if (pickedDate != null && pickedDate != currentDate)
// setState(() {
// currentDate = pickedDate;
// });
// else print('empty')
// ;}
void onAdd() {
//final DateTime? textVal = DateTime.parse(datelController.text);
final String desVal = projectname.text;
if (/*textVal != null&&*/ desVal.isNotEmpty) {
final Project project = Project(/*end_date: textVal,*/ project_name: desVal, user: 1, /*start_date: null,*/ );
Provider.of<ProjectProvider>(context, listen: false).addProject(project);
print('$desVal in sucess');
}
else{
print('empty or vaild');
//print('$textVal in vaild');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
// App Bar The upper part in the application
appBar: AppBar(
backgroundColor:const Color(0xff076792),
title: const Padding(
padding: EdgeInsets.only(
left: 50.0,
),
// project Name
child: Text(
'New Project',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 25.0,
shadows: [
Shadow(
color: Color(0xa6A2B6D4),
offset: Offset(7,5),
blurRadius:20),
]
),
),
),
iconTheme: const IconThemeData(
color:Colors.white,
size: 30.0,
),
),
body: SingleChildScrollView(
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(
left: 10.0,
top: 30.0,
),
child: Padding(
padding: EdgeInsets.only(right: 80.0),
child: Text(
'Creating New Project',
style: TextStyle(
fontSize: 25.0,
color: Color(0xff076792),
fontWeight: FontWeight.bold,
),
),
),
),
Container(
margin: const EdgeInsets.fromLTRB(43, 24, 43, 15),
child: SizedBox(
height: 45,
child: TextField(
controller: projectname,
decoration: const InputDecoration(
hintText: "Enter project Name", //اليوسر يدخل اسم المشروع
hintStyle: TextStyle(
fontSize: 20,
color: Color(0xffc9c9c9), /*height: 2.5*/
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(width: 2, color: Color(0xFF09679a))),
),
keyboardType: TextInputType.name,
),
),
),
// Container(
// margin: const EdgeInsets.fromLTRB(43, 0, 43, 20),
// child: SizedBox(
// height: 45,
// child: TextField(
// controller: datelController,
// onTap: () {
// showDatePicker(
// context: context,
// initialDate: DateTime.now(),
// firstDate: DateTime.now(),
// lastDate: DateTime(2050),
// ).then((value) {
// datelController.text = DateFormat("yyyy-MM-dd").format(value!);
// });
// },
// decoration: const InputDecoration(
// hintText: "End Date",
// hintStyle: TextStyle(
// fontSize: 20,
// color: Color(0xffc9c9c9),
// ),
// enabledBorder: OutlineInputBorder(
// borderSide: BorderSide(width: 2, color: Color(0xFF09679a))),
// ),
// keyboardType: TextInputType.datetime,
// ),
// ),
// ),
const SizedBox(
height: 10.0,
),
Container(
width: double.infinity,
height: 54,
margin: const EdgeInsets.fromLTRB(75, 0, 75, 0),
child: ElevatedButton(
onPressed: () {
onAdd();
//_selectDate(context);
//Navigator.of(context).pop();
},
child: const Text(
'Create',
style: TextStyle(fontSize: 26, fontWeight: FontWeight.w400),
),
style: ElevatedButton.styleFrom(
primary: const Color(0xFF09679a),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
// f... flutter buttons!
side: const BorderSide(color: Colors.black, width: 1),
)),
),
),
Container(
alignment: Alignment.center,
child: const Padding(
padding: EdgeInsets.only(left: 60, top: 15.0, right: 60.0),
child: Text(
'By Creating This Project You Will Be Admin Of The Project',
style: TextStyle(
fontSize: 18.0,
fontStyle: FontStyle.italic,
color: Colors.black,
),
),
), //just text
),
// Text(currentDate.toString()),
// ElevatedButton(
// onPressed: () => _selectDate(context),
// child: Text('Select date'),
// ),
],
),
),
);
}
}
this app made to login users and view projects and add projects like todo app on the django server i can add project and view projects regstring with admin mail from python backend server .. in this app i can only view projects but cant add new project its my project for graduation so my life depends on this :D
full source code https://github.com/alihassan75/project
You are not getting the data "user" because you are not saving the "user" after login.
You need to save the user in any local storage. For, the demo purpose I will be saving that on HIVE
Import the hive package in pubspec.yaml
hive: ^2.1.0
In the main function(before run app) initialize and open a box "user"
await Hive.initFlutter();
await Hive.openBox('User');
You can push to user box in login function like this.
box = Hive.box('User');
int userId = responseJson['user']['id'];
box.put('user_id', userId);
You can read the user when ever you want like this.
late Box box;
late int userid;
box = Hive.box('User');
super.initState();
final data = box.get('user_id');
Now you can pass the data to the http api call.
Thank you
so i want to print user name and user username in the profile page and in the end it shows it but for a few seconds there is a red screen that says The following _TypeError was thrown building Profile_page(dirty, state: _Profile_pageState#68414):
type 'Null' is not a subtype of type 'String'
this is the code of main.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:gp1_7_2022/screen/auth/signup/userInfo/name.dart';
import 'package:gp1_7_2022/screen/auth/signup/Questions/question1.dart';
import 'package:gp1_7_2022/screen/auth/signup/Questions/question2.dart';
import 'package:gp1_7_2022/screen/auth/signup/Questions/question3.dart';
import 'package:gp1_7_2022/screen/auth/signup/Questions/question4.dart';
import 'package:gp1_7_2022/screen/auth/signup/Questions/question5.dart';
import 'package:gp1_7_2022/screen/auth/signup/userInfo/photo.dart';
import 'package:gp1_7_2022/screen/home/Profile_Page.dart';
import 'package:firebase_core/firebase_core.dart';
/*pages */
import 'package:gp1_7_2022/screen/auth/signup_login.dart';
import 'package:gp1_7_2022/screen/auth/signup/userAuth/signup.dart';
import 'package:gp1_7_2022/screen/auth/Login/login.dart';
import 'package:gp1_7_2022/screen/auth/signup/userAuth/signupConfirmationCode.dart';
import 'package:gp1_7_2022/screen/auth/signup/userAuth/signupPassword.dart';
import 'package:gp1_7_2022/screen/auth/signup/userInfo/signupBirthday.dart';
import 'package:gp1_7_2022/screen/auth/signup/userInfo/signupUsername.dart';
import 'package:gp1_7_2022/screen/auth/Login/forget_password.dart';
import 'package:gp1_7_2022/screen/settings.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MaterialApp(
initialRoute: "/",
routes: {
"/": (context) => MainPage(),
"/signup": (context)=> Signup(),
'/login':(context)=>Login(),
'/Profile_Page':(context) => Profile_page(uid: FirebaseAuth.instance.currentUser!.uid),
// '/confirmationCode':(context) => ConfirmationCode(),
// '/signupPassword':(context) => signupPassword(),
'/signupBirthday':(context) => SignupBirthday(),
'/signupUsername':(context) => SignupUsername(),
'/forget_password':(context) => forget_password(),
'/name':(context) => name(),
'/question1':(context) => question1(),
'/question2':(context) => question2(),
'/question3':(context) => question3(),
'/question4':(context) => question4(),
'/question5':(context) => question5(),
'/photo':(context) => Photo(),
'/settings':(context) => settings(),
}
)
);
}
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot){
if(snapshot.connectionState==ConnectionState.waiting){
return const Center(child: CircularProgressIndicator());
}else if(snapshot.hasError){
return const Center(child: Text("Something went wrong!"));
}else if(snapshot.hasData){
if(FirebaseAuth.instance.currentUser!.emailVerified && FirebaseAuth.instance.currentUser!.uid != null ){
String uid = FirebaseAuth.instance.currentUser!.uid;
return Profile_page(uid: uid );
}else{
String? x = FirebaseAuth.instance.currentUser!.email;
String y= x??" ";
return ConfirmationCode(email: y);
}
} else{
return const Signup_Login();
}
},
),
);
}
}
this is the code of profile_page.dart
// import 'dart:html';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:focused_menu/focused_menu.dart';
import 'package:focused_menu/modals.dart';
/*pages */
/*colors */
import 'package:gp1_7_2022/config/palette.dart';
import 'package:gp1_7_2022/Widgets/follow_button.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
import 'package:gp1_7_2022/screen/settings.dart';
class Profile_page extends StatefulWidget {
final uid;
const Profile_page({Key? key, required this.uid}) : super(key: key);
#override
State<Profile_page> createState() => _Profile_pageState();
}
class _Profile_pageState extends State<Profile_page> {
var padding= 0.8;
var userData = {};
#override
void initState() {
super.initState();
getData();
}
/* get data method */
getData() async {
try {
if (widget.uid != null) {
var userSnap = await FirebaseFirestore.instance.collection('users').doc(
widget.uid).get();
userData = userSnap.data()!;
setState(() {
});
}
}
catch(e){
Alert(
context: context,
title: "Something went wrong!",
desc: e.toString(),
).show();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Palette.backgroundColor,
appBar: AppBar(
//appBar style
elevation: 0,
backgroundColor: Palette.backgroundColor,
automaticallyImplyLeading: false,//no arrow
//username
title: Padding(
padding: EdgeInsets.fromLTRB(5, 0, 0, 0),
child: Text(
userData['username'],
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
),
//setting icon
actions:[
FocusedMenuHolder(
//
menuWidth: MediaQuery.of(context).size.width * 0.4,
menuOffset: 0,
menuItemExtent: 49,
//list
menuItems: [
FocusedMenuItem(
title: const Text("Log out"),
trailingIcon: const Icon(Icons.logout),
onPressed: (){
/*go to sign up page*/
Navigator.pushNamed(context, '/');
return FirebaseAuth.instance.signOut();
}
),
FocusedMenuItem(
title: const Text("Settings"),
trailingIcon: const Icon(Icons.settings),
onPressed: (){
Navigator.of(context).popAndPushNamed('/settings');
},
),
],
openWithTap: true,
onPressed: (){},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Image.asset(
"assets/menu-icon.png",
height: 25,
width: 25,
),
),
),
],
),
body: ListView(
children: [
Container(
margin: const EdgeInsets.all(16),
child: Column(
children: [
Row(
children: [
//user photo
const Padding(
padding: EdgeInsets.fromLTRB(0, 0, 40, 0),
child: CircleAvatar(
backgroundColor: Colors.white ,
child: Icon(
Icons.account_circle_sharp,
color: Colors.grey,
size: 90,
),
),
),
//end user photo
Expanded(
flex: 7,
child: Column(
children: [
SizedBox(height:40,),
//post, followers and following
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildStatColumn(20, "posts"),
buildStatColumn(150, "Followers"),
buildStatColumn(10, "Following"),
],
),
//end post, followers and following
],
),
),
],
),
//username
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.fromLTRB(10, 40, 0, 0),
child: Text(
userData['name'],
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
//end of username
//bio
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.fromLTRB(10, 1, 0, 0),
child: const Text(
'bio',
style: TextStyle(
fontSize: 16,
),
),
),
//end of bio
//edit profile button
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FollowButton(
text: 'Edit profile',
backgroundColor: Palette.backgroundColor,
borderColor: Palette.grey,
textColor: Colors.black,
function: () {},
)
],
),
//end of button
],
),
),
],
),
);
}
}
// function to show following/followers/# of posts
Column buildStatColumn(int num, String label) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
num.toString(),
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Container(
margin: const EdgeInsets.only(top: 4),
child: Text(
label,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.grey,
),
),
),
],
);
}
enter image description here
Show some other widgets until data is not fully loaded.
class _Profile_pageState extends State<Profile_page> {
...
bool _isloaded = false; // Add this boolean
In getData function
getData() async {
try {
...
setState(() {
_isloaded = true; // when data is loaded update state
});
}
...
In build, return widget according to data(user)
#override
Widget build(BuildContext context) {
return _isloaded == false ?
Center(
child: CircularProgressIndicator(), // Show indicator
)
: Scaffold(
backgroundColor: Palette.backgroundColor,
...
); //Scaffold
You're assuring flutter that the data isn't null which will result in a momentary error. You can try either setting a load bool that sets to true when the data arrives or using the ?? operator. e.g userData['name'] ?? "loading" which will print loading incase the userData['name'] is null
I need to detect when my phoneCall variable changes state this to detect when the call ended and show a modal to the user so he can rate the call. This is the widget code.
import 'dart:convert';
import 'package:avanx/flutter/loading_view.dart';
import 'package:avanx/globals.dart';
import 'package:avanx/models/group.dart';
import 'package:avanx/models/prospect.dart';
import 'package:cool_alert/cool_alert.dart';
import 'package:flutter_phone_state/flutter_phone_state.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:url_launcher/url_launcher.dart';
import '../flutter/theme.dart';
import 'package:avanx/flutter/input_widget.dart';
import '../flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:avanx/flutter/drawer_widget.dart';
import 'package:loading_animations/loading_animations.dart';
import 'package:http/http.dart' as http;
class LeadsHomeWidget extends StatefulWidget {
LeadsHomeWidget({Key key}) : super(key: key);
#override
_LeadsHomeWidgetState createState() => _LeadsHomeWidgetState();
}
class _LeadsHomeWidgetState extends State<LeadsHomeWidget> {
List<dynamic> _leads = [];
List<dynamic> _groups;
var phoneCall;
TextEditingController textController;
final scaffoldKey = GlobalKey<ScaffoldState>();
GlobalKey<FormState> _formKey = GlobalKey();
String _search = '';
_initCall(_number) async {
setState(() {
phoneCall = FlutterPhoneState.startPhoneCall(_number);
});
}
showCallInfo() {
print(phoneCall
.status); // ringing, dialing, cancelled, error, connecting, connected, timedOut, disconnected
print(phoneCall.isComplete); // Whether the call is complete
print(phoneCall
.events); // A list of call events related to this specific call
}
// Metodo para la obtención de los grupos existentes.
getGroups() async {
print("hello");
final response = await http.get(Uri.parse(Globals.avanx + '/groups'),
headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
var groupsList = json.decode(response.body)['groups'];
List<dynamic> groups =
groupsList.map((element) => new Group.fromJson(element)).toList();
setState(() {
_groups = groups;
});
} else {
throw Exception('Failed to load groups');
}
}
getLeads(name) async {
if (name != '') {
String auth = Globals.authUser.user.id.toString();
final response = await http.post(
Uri.parse(Globals.avanx + '/prospects/search/$auth'),
body: {'name': name},
headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
var leadsList = json.decode(response.body)['leads'];
List<dynamic> leads =
leadsList.map((element) => new Prospect.fromJson(element)).toList();
setState(() {
_leads = leads;
});
} else {
throw Exception('Failed to load leads');
}
} else {
setState(() {
_leads = [];
});
}
}
deleteModal(id) {
CoolAlert.show(
context: context,
animType: null,
type: CoolAlertType.warning,
title: '¿Estas Seguro?',
text: "Esta acción no se puede reversar.",
backgroundColor: Color(0xBF35126A),
confirmBtnText: 'Confirmar',
confirmBtnColor: Color(0xBF35126A),
showCancelBtn: true,
cancelBtnText: 'Cancelar',
onConfirmBtnTap: () {
deleteLead(id);
Navigator.pop(context);
});
}
deleteLead(id) async {
final response = await http.delete(
Uri.parse(Globals.avanx + '/prospects/$id'),
headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
_search = '';
this.getLeads(_search);
} else {
throw Exception('Failed to load leads');
}
}
#override
void initState() {
textController = TextEditingController();
this.getGroups();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
backgroundColor: FlutterTheme.tertiaryColor,
appBar: AppBar(
backgroundColor: FlutterTheme.primaryColor,
title: Text(
'Prospectos',
style: TextStyle(fontFamily: 'Montserrat'),
),
centerTitle: true,
),
drawer: DrawerWidget(),
body: _groups == null
? LoadingWidget()
: Align(
alignment: Alignment(0, 0),
child: Padding(
padding: EdgeInsets.fromLTRB(30, 10, 30, 0),
child: ListView(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
children: _groups == null
? []
: [
Form(
key: _formKey,
child: Row(
children: [
Expanded(
flex: 2,
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 15),
child: InputWidget(
label: 'Buscar prospecto?',
keyBoardType: TextInputType.text,
onChanged: (text) {
_search = text;
},
validator: (text) {
if (text.trim().length == 0) {
return "input data";
}
return null;
},
),
),
),
Expanded(
child: ElevatedButton(
child: Text(
'Buscar',
style: TextStyle(
color: FlutterTheme.primaryColor),
),
onPressed: () {
getLeads(_search);
},
style: ElevatedButton.styleFrom(
side: BorderSide(
width: 1.5,
color: FlutterTheme.primaryColor,
),
primary: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
),
),
],
),
),
phoneCall.isComplete
? Container(
child: Text('The call is end!!'),
)
: Container(),
for (var lead in _leads ?? [])
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Container(
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(
'https://ui-avatars.com/api/?name=' +
lead.name +
'&background=35126A&color=fff&size=128'),
),
title: Text(lead.name),
subtitle: Text(
'Grupo: ' + lead.group.name,
style: TextStyle(fontSize: 11),
),
trailing: Container(
width: 100,
child: Row(
children: [
IconButton(
onPressed: () {
_initCall(lead.phone);
},
icon: Icon(
Icons.phone,
size: 35,
color: Color(0xFF35126A),
)),
IconButton(
onPressed: () {
showCallInfo();
},
icon: Icon(
Icons.mail_outline,
size: 35,
color: Color(0xFF35126A),
)),
],
),
),
),
),
secondaryActions: <Widget>[
IconSlideAction(
onTap: () {
Navigator.pushNamed(context, 'leads_edit',
arguments: lead);
},
caption: 'Edit',
color: Color(0xFF35126A),
icon: Icons.edit,
),
IconSlideAction(
onTap: () {
deleteModal(lead.id);
},
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 40, 0, 0),
child: ButtonWidget(
onPressed: () {
Navigator.pushNamed(context, 'leads_add_new');
},
text: 'Agregar Nuevo',
options: ButtonOptions(
width: 130,
height: 40,
color: FlutterTheme.tertiaryColor,
textStyle: FlutterTheme.subtitle2.override(
fontFamily: 'Montserrat',
color: FlutterTheme.primaryColor,
),
borderSide: BorderSide(
color: FlutterTheme.primaryColor,
width: 2,
),
borderRadius: 30,
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 40, 0, 0),
child: Text(
'Grupos',
textAlign: TextAlign.center,
style: FlutterTheme.bodyText1.override(
fontFamily: 'Montserrat',
color: Color(0xBF35126A),
fontSize: 20,
),
),
),
for (var group in _groups)
Padding(
padding: EdgeInsets.fromLTRB(0, 20, 0, 0),
child: ButtonWidget(
onPressed: () {
Navigator.pushNamed(context, 'leads_list',
arguments: group);
},
text: group.name,
options: ButtonOptions(
width: 130,
height: 40,
color: FlutterTheme.primaryColor,
textStyle: FlutterTheme.subtitle2.override(
fontFamily: 'Montserrat',
color: Colors.white,
),
borderSide: BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: 30,
),
),
),
],
),
),
),
);
}
}
The function _initCall is the one in charge of initializing the call, so the variable phoneCall will have the information of the state of the call, I want to launch a modal when the call finishes.
I my project I am using google sign in and i want to maintain persistent sign in how to do it for the below code. The problem is once i sign in and if i close the app then when I reopen the app i have to sign in again.
Once I open the app i get an option to Sign in with google once i sign in with google I got to the first screen where details about me the signed in user are available and then if i close the app without signing in then when I restart the application i have to sign in again how should i sign in once and be signed in until i press the sign out button
main.dart
import 'package:flutter/material.dart';
import 'login_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Login',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(),
);
}
}
login_page.dart
import 'package:chat/sign_in.dart';
import 'package:flutter/material.dart';
import 'first_screen.dart';
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(size: 150),
SizedBox(height: 50),
_signInButton(),
],
),
),
),
);
}
Widget _signInButton() {
return OutlineButton(
splashColor: Colors.grey,
onPressed: () {
signInWithGoogle().whenComplete(
() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
},
);
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("assets/google_logo.png"), height: 35.0),
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
)
],
),
),
);
}
}
sign_in.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
String name;
String email;
String imageUrl;
Future<String> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
// Checking if email and name is null
assert(user.email != null);
assert(user.displayName != null);
assert(user.photoUrl != null);
name = user.displayName;
email = user.email;
imageUrl = user.photoUrl;
// Only taking the first part of the name, i.e., First Name
if (name.contains(" ")) {
name = name.substring(0, name.indexOf(" "),);
}
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
void signOutGoogle() async {
await googleSignIn.signOut();
print("User Sign Out");
}
first_screen.dart
import 'package:chat/login_page.dart';
import 'package:chat/sign_in.dart';
import 'package:flutter/material.dart';
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Colors.blue[100], Colors.blue[400]],
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
imageUrl,
),
radius: 60,
backgroundColor: Colors.transparent,
),
SizedBox(height: 40),
Text(
'NAME',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
name,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Text(
'EMAIL',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
email,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
RaisedButton(
onPressed: () {
signInWithGoogle();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) {
return LoginPage();
},
),
ModalRoute.withName('/'),
);
},
color: Colors.deepPurple,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Sign Out',
style: TextStyle(fontSize: 25, color: Colors.white),
),
),
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40)),
)
],
),
),
),
);
}
}
The main() method is the first method called and it seems that you always go to the LoginPage widget. You can change to a StatefulWidget and check if the user is logged in or not, by using the initState():
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((res) {
print(res);
if (res != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => Home()),
);
}
else
{
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
);
}
});
}
For example, here you check if the user is not equal to null, then go to the details page or home page if not then go to the LoginPage.