Image of code that occurs with error
I am going through a udemy Flutter course and I do not understand why the try catch cannot handle the error with the if statement inside inside of the try{}. I have had this problem for this a couple of times and I have just avoided it by running error-free trials.
The code is as follows:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../models/http_exception.dart';
class Auth with ChangeNotifier {
String _token;
//tokens only last about an hour
DateTime _expiryDate;
String _userId;
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final url = 'UrlIsCorrectInMyCode'; //changed on purpose
try {
final response = await http.post(
url,
body: json.encode(
{
'email': email,
'password': password,
'returnSecureToken': true,
},
),
);
final responseData = json.decode(response.body);
if(responseData['error'] != null){
throw HttpException(responseData['error']['message']);
}
} catch (error) {
throw error;
}
}
Future<void> signUp(String email, String password) async {
return _authenticate(email, password, 'signUp');
//in order for the progress indicator to be shown
//it must be returned so that it takes the future of
//_authenticate and not just any future
}
Future<void> login(String email, String password) async {
return _authenticate(email, password, 'signInWithPassword');
}
}
And the class that registers UI and uses Auth:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/auth.dart';
import '../models/http_exception.dart';
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(215, 117, 255, 1).withOpacity(0.5),
Color.fromRGBO(255, 188, 117, 1).withOpacity(0.9),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0, 1],
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.only(bottom: 20.0),
padding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
transform: Matrix4.rotationZ(-8 * pi / 180)
..translate(-10.0),
//transform allows to rotate or scale a box
//the '..' operator allows you to return the matrix4
//object that rotationZ provides instead of the void
//response that .translate provides
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.deepOrange.shade900,
boxShadow: [
BoxShadow(
blurRadius: 8,
color: Colors.black26,
offset: Offset(0, 2),
)
],
),
child: Text(
'MyShop',
style: TextStyle(
color:
Theme.of(context).accentTextTheme.headline6.color,
fontSize: 50,
fontFamily: 'Anton',
fontWeight: FontWeight.normal,
),
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key key,
}) : super(key: key);
#override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
void _showErrorDialog(String message) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text("An error occured"),
content: Text(message),
actions: [
FlatButton(
child: Text("Okay"),
onPressed: () {
Navigator.of(ctx).pop();
},
),
],
),
);
}
Future<void> _submit() async {
if (!_formKey.currentState.validate()) {
// Invalid!
return;
}
_formKey.currentState.save();
setState(() {
_isLoading = true;
});
try {
if (_authMode == AuthMode.Login) {
await Provider.of<Auth>(context, listen: false).login(
_authData['email'],
_authData['password'],
);
} else {
await Provider.of<Auth>(context, listen: false).signUp(
_authData['email'],
_authData['password'],
);
}
} on HttpException catch (error) {
//this means a special type of error is thrown
//this acts as a filter for the type of error
var errorMessage = 'Authentication failed.';
if (error.toString().contains("EMAIL_EXISTS")) {
errorMessage = 'This email address is already in use';
} else if (error.toString().contains('INVALID_EMAIL')) {
errorMessage = 'This is not a valid email address.';
} else if (error.toString().contains('WEAK_PASSWORD')) {
errorMessage = 'This password is too weak.';
} else if (error.toString().contains('EMAIL_NOT_FOUND')) {
errorMessage = 'Could not find a user with that email.';
} else if (error.toString().contains('INVALID_PASSWORD')) {
errorMessage = 'Invalid password.';
}
_showErrorDialog(errorMessage);
} catch (error) {
const errorMessage = 'Could not authenticate. Please try again.';
_showErrorDialog(errorMessage);
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
} else {
setState(() {
_authMode = AuthMode.Login;
});
}
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: Container(
height: _authMode == AuthMode.Signup ? 320 : 260,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Invalid email!';
} else {
return null;
}
},
onSaved: (value) {
_authData['email'] = value;
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value.isEmpty || value.length < 5) {
return 'Password is too short!';
} else {
return null;
}
},
onSaved: (value) {
_authData['password'] = value;
},
),
if (_authMode == AuthMode.Signup)
TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
//this allows stars to mask the input
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
} else {
return null;
}
}
: null,
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
padding:
EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.button.color,
),
FlatButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} INSTEAD'),
onPressed: _switchAuthMode,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
//reduces the amount of surface area that is tappable
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
Related
I have three text form fields on the sign-in page
There are two of them for username and password that work well, I have no problem with them
But the first one is for entering the domain (it is programmed so that each client has its own domain), which is my problem.
I want that when the user enters his domain, the URL of the program, which is in the IP page, is changed and the sign-in page is called only once, without the need to call other pages.
thsis is signIn page code:
I suggest that you pay attention to _signIn and ElevatedButton.
import 'package:flutter/material.dart';
import 'package:mis_project/api/my_api.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mis_project/conts/myString.dart';
import '../auth/auth_page.dart';
import '../conts/colors.dart';
import '../conts/mSize.dart';
class SignIn extends StatefulWidget {
const SignIn({Key key}) : super(key: key);
#override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
String postDomain;
bool isLoading = false;
PageController _pageController;
List<TextEditingController> tecList;
#override
void initState() {
super.initState();
_pageController = PageController();
tecList = List.generate(3, (index) {
return TextEditingController();
});
WidgetsBinding.instance.addPostFrameCallback((_) {
_showModalBottomSheet(context);
});
}
_signIn() async {
print('Sign is is called');
var data = {
'email': tecList[1].text,
'password': tecList[2].text,
};
var jsonResponse = null;
SharedPreferences localStorage = await SharedPreferences.getInstance();
var response = await CallApi().postData(data, 'login');
jsonResponse = json.decode(response.body);
if (jsonResponse != null) {
setState(() {});
localStorage.setString('token', jsonResponse['token']);
Navigator.push(
context, MaterialPageRoute(builder: (context) => AuthPage()));
} else {
setState(() {});
}
}
final _formKey = GlobalKey<FormState>();
#override
void dispose() {
for (var tec in tecList) {
tec.dispose();
}
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: background_page,
body: isLoading
? Center(
child: CircularProgressIndicator(),
)
: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/image/background.jpg'),
fit: BoxFit.cover),
),
),
);
}
void _showModalBottomSheet(BuildContext context) {
showModalBottomSheet<void>(
elevation: 30,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(30),
),
),
context: context,
builder: (BuildContext context) {
return SizedBox(
height: mDeviceSize(context).height * 0.71,
width: mDeviceSize(context).width,
child: PageView.builder(
controller: _pageController,
itemCount: 3,
itemBuilder: (context, index) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
top: 40, left: 25, right: 25, bottom: 15),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
textAlign: TextAlign.left,
textInputAction: TextInputAction.go,
style: TextStyle(color: Color(0xFF000000)),
cursorColor: view_all_color_HP,
controller: tecList[index],
keyboardType: TextInputType.text,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: view_all_color_HP,
),
),
contentPadding: EdgeInsets.symmetric(
vertical: 5.0, horizontal: 10),
labelText: signing_input_label[index],
labelStyle: TextStyle(color: view_all_color_HP),
floatingLabelBehavior: FloatingLabelBehavior.auto,
border: OutlineInputBorder(),
alignLabelWithHint: true,
hintStyle: TextStyle(
color: view_all_color_HP,
fontSize: 15,
fontWeight: FontWeight.normal),
),
autofocus: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
int nextPage = index + 1;
if (nextPage < 3) {
_pageController.animateToPage(nextPage,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
}
if (index == 0) {
postDomain = tecList[0].text;
print('domain post is : $postDomain');
print('domain value is: ${tecList[0].text}');
}
if (index == 1) {
print('email value is: ${tecList[1].text}');
}
if (index == 2) {
print('pass: ${tecList[2].text}');
_signIn();
}
},
child: Text(signing_button_label[index]),
style: ElevatedButton.styleFrom(
elevation: 0,
primary: view_all_color_HP,
fixedSize:
Size(mDeviceSize(context).width * 0.3, 5),
minimumSize: Size(0, 45),
),
),
SizedBox(
height: MediaQuery.of(context).viewInsets.bottom,
),
],
),
),
),
],
);
},
),
);
},
);
}
}
and this is my APi page
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class CallApi{
final String _urlF = 'https://';
final String _urlE = '.lajwardsoftwares.com/api/v1/';
postData(data, apiUrl) async {
var fullUrl = _urlF + _urlE + apiUrl + await _getToken();
print('full url is: $fullUrl');
return await http.post(
Uri.parse(fullUrl),
body: jsonEncode(data),
headers: _setHeaders()
);
}
getData(apiUrl) async {
var fullUrl = _urlF + apiUrl + await _getToken();
return await http.get(
Uri.parse(fullUrl),
headers: _setHeaders()
);
}
_setHeaders() => {
'Content-type' : 'application/json',
'Accept' : 'application/json',
};
_getToken() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
var token = localStorage.getString('token');
return '?token=$token';
// print("saied: getToken ${localStorage.getString('token')}"),};
}
}
i want this .lajwardsoftwares.com to stored from TextFromField
thanks
I am trying to write a simple signup/login page. The following codes are the main.dart, screen page for the view and the auth_controller for the control page of the project.
main.dart:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Auth(),
),
],
child: Consumer<Auth>(
builder: (ctx, auth, _) => MaterialApp(
title: 'MyShop',
theme: ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.deepOrange,
fontFamily: 'Lato',
),
home: auth.isAuth
? MapScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthScreen(),
),
routes: {
MapScreen.routeName: (ctx) => MapScreen(),
},
),
),
);
}
}
auth_screen.dart:
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color.fromRGBO(215, 117, 255, 1).withOpacity(0.5),
const Color.fromRGBO(255, 188, 117, 1).withOpacity(0.9),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: const [0, 1],
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
margin: const EdgeInsets.only(bottom: 20.0),
padding: const EdgeInsets.symmetric(
vertical: 8.0, horizontal: 94.0),
transform: Matrix4.rotationZ(-8 * pi / 180)
..translate(-10.0),
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.deepOrange.shade900,
boxShadow: const [
BoxShadow(
blurRadius: 8,
color: Colors.black26,
offset: Offset(0, 2),
)
],
),
child: Text(
'USmobile',
style: TextStyle(
color: Theme.of(context)
.textSelectionTheme
.selectionColor,
fontSize: 50,
fontFamily: 'Anton',
fontWeight: FontWeight.normal,
),
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: const AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key? key,
}) : super(key: key);
#override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard>
with SingleTickerProviderStateMixin {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
AnimationController? _controller;
Animation<Offset>? _slideAnimation;
Animation<double>? _opacityAnimation;
#override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(
milliseconds: 300,
),
);
_slideAnimation = Tween<Offset>(
begin: const Offset(0, -1.5),
end: const Offset(0, 0),
).animate(
CurvedAnimation(
parent: _controller as Animation<double>,
curve: Curves.fastOutSlowIn,
),
);
_opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller as Animation<double>,
curve: Curves.easeIn,
),
);
// _heightAnimation.addListener(() => setState(() {}));
}
#override
void dispose() {
super.dispose();
_controller!.dispose();
}
void _showErrorDialog(String message) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('An Error Occurred!'),
content: Text(message),
actions: <Widget>[
TextButton(
child: const Text('Okay'),
onPressed: () {
Navigator.of(ctx).pop();
},
)
],
),
);
}
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
// Invalid!
return;
}
_formKey.currentState!.save();
setState(() {
_isLoading = true;
});
try {
if (_authMode == AuthMode.Login) {
// Log user in
await Provider.of<Auth>(context, listen: false).login(
_authData['email'] as String,
_authData['password'] as String,
);
} else {
// Sign user up
await Provider.of<Auth>(context, listen: false).signup(
_authData['email'] as String,
_authData['password'] as String,
);
}
// } on HttpException catch (error) {
// var errorMessage = 'Authentication failed';
// print("this is the auth data");
// print(_authData);
// if (error.toString().contains('EMAIL_EXISTS')) {
// errorMessage = 'This email address is already in use.';
// } else if (error.toString().contains('INVALID_EMAIL')) {
// errorMessage = 'This is not a valid email address';
// } else if (error.toString().contains('WEAK_PASSWORD')) {
// errorMessage = 'This password is too weak.';
// } else if (error.toString().contains('EMAIL_NOT_FOUND')) {
// errorMessage = 'Could not find a user with that email.';
// } else if (error.toString().contains('INVALID_PASSWORD')) {
// errorMessage = 'Invalid password.';
// }
// _showErrorDialog(errorMessage);
} catch (error) {
var errorMessage = 'Could not authenticate you. Please try again later.' +
error.toString();
_showErrorDialog(errorMessage);
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
_controller!.forward();
} else {
setState(() {
_authMode = AuthMode.Login;
});
_controller!.reverse();
}
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
height: _authMode == AuthMode.Signup ? 320 : 260,
// height: _heightAnimation.value.height,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: const InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'Invalid email!';
}
},
onSaved: (value) {
_authData['email'] = value as String;
},
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value as String;
},
),
AnimatedContainer(
constraints: BoxConstraints(
minHeight: _authMode == AuthMode.Signup ? 60 : 0,
maxHeight: _authMode == AuthMode.Signup ? 120 : 0,
),
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
child: FadeTransition(
opacity: _opacityAnimation as Animation<double>,
child: SlideTransition(
position: _slideAnimation as Animation<Offset>,
child: TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: const InputDecoration(
labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
),
),
),
const SizedBox(
height: 20,
),
if (_isLoading)
const CircularProgressIndicator()
else
ElevatedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
primary: Theme.of(context).primaryColor,
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 8.0),
onPrimary:
Theme.of(context).primaryTextTheme.button!.color,
),
),
TextButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} '),
onPressed: _switchAuthMode,
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 4),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
textStyle: TextStyle(color: Theme.of(context).primaryColor),
),
),
],
),
),
),
),
);
}
}
auth_controller.dart:
class Auth with ChangeNotifier {
String? _token;
DateTime? _expiryDate;
String? _userId;
Timer? _authTimer;
bool get isAuth {
return token != null;
}
String? get token {
if (_expiryDate != null &&
_expiryDate!.isAfter(DateTime.now()) &&
_token != null) {
return _token;
}
return null;
}
String? get userId {
return _userId;
}
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final url = Uri.parse('http://10.0.2.2:8000/api/$urlSegment');
try {
final http.Response response = await http.post(
url,
headers: {"Content-Type": "application/json"},
body: json.encode(
{
'email': email,
'password': password,
//'returnSecureToken': true,
},
),
);
print("This is response.body");
print(response.body);
print("This is response.body.runtimeType");
print(response.body.runtimeType);
final responseData = json.decode(response.body);
print("this is responseData");
print(responseData);
print("this is responseData['error']");
print(responseData['error']);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
} else {
print("There wasn't error here!");
}
_token = responseData['idToken'];
print("This is the token");
print(_token);
_userId = responseData['id'];
print("This is userId");
print(_userId);
print("This is expiryDate");
print(responseData['expiresIn']);
_expiryDate = DateTime.now().add(
Duration(
seconds: int.parse(
responseData['expiresIn'],
),
),
);
print("I can no see thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis");
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode(
{
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate!.toIso8601String(),
},
);
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
Future<void> signup(String email, String password) async {
return _authenticate(email, password, 'register');
}
Future<void> login(String email, String password) async {
return _authenticate(email, password, 'verifyPassword');
}
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('userData')) {
return false;
}
final extractedUserData = json.decode(prefs.getString('userData') as String)
as Map<String, Object>;
final expiryDate =
DateTime.parse(extractedUserData['expiryDate'] as String);
if (expiryDate.isBefore(DateTime.now())) {
return false;
}
_token = extractedUserData['token'] as String;
_userId = extractedUserData['userId'] as String;
_expiryDate = expiryDate;
notifyListeners();
_autoLogout();
return true;
}
Future<void> logout() async {
_token = null;
_userId = null;
_expiryDate = null;
if (_authTimer != null) {
_authTimer!.cancel();
_authTimer = null;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
// prefs.remove('userData');
prefs.clear();
}
void _autoLogout() {
if (_authTimer != null) {
_authTimer!.cancel();
}
final timeToExpiry = _expiryDate!.difference(DateTime.now()).inSeconds;
_authTimer = Timer(Duration(seconds: timeToExpiry), logout);
}
}
I know the backend part works fine and the following is the result I do get while running my app and try to register a new user through the Android Emulator:
I/flutter ( 6814): This is response.body
I/flutter ( 6814): {"id":"619c5141e08b15bf9173ab06","name":"","email":"test#testing.com","password":"$2a$10$yYUtDS1PrSAgpQBxoVm7Ae7O8ujR33ONz4gM5t7iHWt6e907pjFrq","idToken":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0QHRlc3RpbmcuY29tIiwiZXhwIjoxNjM5Mjc1NjAzNzQzfQ.LgrlwFNrLhGr5UfHikL83e2tBjbqMyN4OKG6Fz816AeOs6ezfnhvQoXBDAsV2pIt4CWuBVf8qGbBYSXCQxgarw","expiresIn":1639275603743}
I/flutter ( 6814): This is response.body.runtimeType
I/flutter ( 6814): String
I/flutter ( 6814): this is responseData
I/flutter ( 6814): {id: 619c5141e08b15bf9173ab06, name: , email: test#testing.com, password: $2a$10$yYUtDS1PrSAgpQBxoVm7Ae7O8ujR33ONz4gM5t7iHWt6e907pjFrq, idToken: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0QHRlc3RpbmcuY29tIiwiZXhwIjoxNjM5Mjc1NjAzNzQzfQ.LgrlwFNrLhGr5UfHikL83e2tBjbqMyN4OKG6Fz816AeOs6ezfnhvQoXBDAsV2pIt4CWuBVf8qGbBYSXCQxgarw, expiresIn: 1639275603743}
I/flutter ( 6814): this is responseData['error']
I/flutter ( 6814): null
I/flutter ( 6814): There wasn't error here!
I/flutter ( 6814): This is the token
I/flutter ( 6814): eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0QHRlc3RpbmcuY29tIiwiZXhwIjoxNjM5Mjc1NjAzNzQzfQ.LgrlwFNrLhGr5UfHikL83e2tBjbqMyN4OKG6Fz816AeOs6ezfnhvQoXBDAsV2pIt4CWuBVf8qGbBYSXCQxgarw
I/flutter ( 6814): This is userId
I/flutter ( 6814): 619c5141e08b15bf9173ab06
I/flutter ( 6814): This is expiryDate
I/flutter ( 6814): 1639275603743
I see all the print() statements work except this:
print("I can no see thiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiis");
I don't know why? I also see the following error message in my Android Emulator that I can't understand the reason?
type 'int' is not a subtype of type 'String'
I also know the error occures in this part of the code in auth_controller.dart file:
} catch (error) {
print(error);
throw error;
}
int.parse(
responseData['expiresIn'],
)
For the above code to work responseData['expiresIn'] should be a String. But in the response, this comes as an int value. Make sure this is a String.
Or you can just use it like this,
Duration(
seconds: responseData['expiresIn'],
),
My app something like Udemy app, it's developed by Flutter
I was published iOS release to App store and working well
but in Android studio doing strange situation...
When I run app on emulator or real device connected to Android studio every thing working well, but when run it with command
Flutter run --release
or build the apk file or abb file
the raisedbutton with Whatsapp icon shown in image below doesn't work
The big problem in signing page [code shown below] when user try to signin I get this HTTP try get error with message
MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences
Note: I use word (errrrrrrrrrrrrrooooor) in code shown below to show where error message show
after search about this error I get that we get this error when no previous values in shared preferences, but in app first use before signing I don't use shared preferences
So, I don't understand why this happen, specially in apk release and working well in test mode on emulator or real device
Note: I was add Internet permissions in manifest file
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
So, I need help about that
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:connect/models/app_logo.dart';
import 'package:connect/widgets/app_bar_two.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import '../models/common_functions.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/auth.dart';
import '../models/http_exception.dart';
import '../constants.dart';
enum AuthMode { Signup, Login }
class AuthScreen extends StatefulWidget {
static const routeName = '/auth';
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
final _controller = StreamController<AppLogo>();
final searchController = TextEditingController();
fetchMyLogo() async {
var url = BASE_URL +'/api/app_logo';
try {
final response = await http.get(url);
print(response.body);
if (response.statusCode == 200) {
var logo = AppLogo.fromJson(jsonDecode(response.body));
_controller.add(logo);
}
// print(extractedData);
} catch (error) {
throw (error);
}
}
void initState() {
super.initState();
this.fetchMyLogo();
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// final transformConfig = Matrix4.rotationZ(-8 * pi / 180);
// transformConfig.translate(-10.0);
return Scaffold(
appBar: CustomAppBarTwo(),
// resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
child: StreamBuilder<AppLogo>(
stream: _controller.stream,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Container();
} else {
if (snapshot.error != null) {
return Text("Error Occured");
} else {
// saveImageUrlToSharedPref(snapshot.data.darkLogo);
return CachedNetworkImage(
imageUrl: snapshot.data.favicon,
fit: BoxFit.contain,
height: 33,
);
}
}
},
),
),
Container(
margin: EdgeInsets.only(bottom: 20.0),
padding:
EdgeInsets.symmetric(vertical: 4.0, horizontal: 94.0),
child: Text(
'Login',
style: TextStyle(
color: kTextColor,
fontSize: 30,
fontWeight: FontWeight.normal,
),
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
);
}
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key key,
}) : super(key: key);
#override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
Future<void> _submit() async {
if (!_formKey.currentState.validate()) {
// Invalid!
return;
}
_formKey.currentState.save();
setState(() {
_isLoading = true;
});
try {
// Log user in
await Provider.of<Auth>(context, listen: false).login(
_authData['email'],
_authData['password'],
);
String deviceName;
String deviceVersion;
String identifier;
final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
try {
if (Platform.isAndroid) {
var build = await deviceInfoPlugin.androidInfo;
deviceName = build.model;
deviceVersion = build.version.toString();
identifier = build.androidId; //UUID for Android
} else if (Platform.isIOS) {
var data = await deviceInfoPlugin.iosInfo;
deviceName = data.name;
deviceVersion = data.systemVersion;
identifier = data.identifierForVendor; //UUID for iOS
}
} on PlatformException {
print('Failed to get platform version');
}
try{
var response = await http.post(
Uri.parse("https://connect-elearning.com/newVersion/APIs/checkIDntfr.php"),
body: {
'IdentifierPst': identifier,
'userNoPst': _authData['email'],
});
Map<String,dynamic> data = jsonDecode(response.body);
String svdIdentifier = data["svdIdentifier"];
String svdUserID = data["svdUserID"];
String realUserID = data["RealUserID"];
if(svdIdentifier != "notFound"){
if(svdIdentifier == identifier && svdUserID == realUserID){
Navigator.pushNamedAndRemoveUntil(context, '/home', (r) => false);
//CommonFunctions.showSuccessToast('Login Successful');
CommonFunctions.showSuccessToast('Login Successful');
} else if(svdIdentifier != identifier || svdUserID != realUserID){
// SharedPreferences preferences = await SharedPreferences.getInstance();
// await preferences.clear();
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Text('Your account is registered for another device, please contact technical support.'),
//title: Text('Your ${svdIdentifier} ${svdUserID} ${realUserID}'),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context, true), // passing true
child: Text('Exit'),
),
],
);
}).then((exit) {
if (exit == null) {SystemNavigator.pop();}
if (exit) {
SystemNavigator.pop();
} else {
SystemNavigator.pop();
}
});
}
} else {
try{
var response = await http.post(
Uri.parse("https://connect-elearning.com/newVersion/APIs/userIDntfrSv.php"),
body: {
'userNoPst': _authData['email'],
'dvNamePst': deviceName,
//'dvOSPst': deviceVersion,
'dvIdntPst': identifier,
});
} catch (e){
print(e);
}
Navigator.pushNamedAndRemoveUntil(context, '/home', (r) => false);
CommonFunctions.showSuccessToast('Login Successful');
}
} catch (e) {
//print("note that ${e}");
}
} on HttpException catch (error) {
var errorMsg = 'Wrong data, you can contact customers services';
CommonFunctions.showErrorDialog(errorMsg, context);
} catch (error) {
//const errorMsg = 'Could not authenticate!, may you need to contact to customers services via whats-app: +201033040777';
//String errorMsg = 'Done!${error}, Go to My courses page';
Error message shown in the next line
print("errrrrrrrrrrrrrooooor ${error}");
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Container(
height: 360,
constraints: BoxConstraints(minHeight: 260),
width: deviceSize.width * 0.8,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
//labelText: 'Email Address',
labelText: 'Mobile',
prefixIcon: Icon(
//Icons.mail_outline,
Icons.phone_android,
color: Colors.grey,
), // myIcon is a 48px-wide widget.
),
//keyboardType: TextInputType.emailAddress,
keyboardType: TextInputType.phone,
validator: (input) => input.length < 11
? "Enter valid mobile number!"
: null,
/*validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Invalid email!';
}
},*/
onSaved: (value) {
_authData['email'] = value;
},
),
TextFormField(
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(
Icons.vpn_key,
color: Colors.grey,
),
),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value.isEmpty || value.length < 4) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value;
},
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
ButtonTheme(
minWidth: deviceSize.width * 0.8,
child: RaisedButton(
child: Text(
'Sign In',
style: TextStyle(fontWeight: FontWeight.bold),
),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0),
side: BorderSide(color: kBlueColor),
),
splashColor: Colors.blueAccent,
padding:
EdgeInsets.symmetric(horizontal: 50.0, vertical: 20),
color: kBlueColor,
textColor: Colors.white,
),
),
SizedBox(
height: 20,
),
/* ButtonTheme(
minWidth: deviceSize.width * 0.8,
child: RaisedButton(
child: Text(
'Create Account',
style: TextStyle(fontWeight: FontWeight.bold),
),
onPressed: () {
Navigator.of(context).pushNamed(SignUpScreen.routeName);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0),
side: BorderSide(color: kGreyColor),
),
splashColor: Colors.blueAccent,
padding: EdgeInsets.symmetric(horizontal: 50.0, vertical: 20),
color: kGreyColor,
textColor: kTextColor,
),
),*/
],
),
),
),
);
}
}
Edit:
When I try to run app with command
flutter run --release
I get this 2 errors in Terminal
E/flutter (18074): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
E/flutter (18074):
E/flutter (18074): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: MissingPluginException(No implementation found for method checkPermissionStatus on channel flutter.baseflow.com/permi
ssions/methods)
and I try to run
flutter clean
flutter pub get
... etc, and nothing new
Update
when I updated gradle to the last version, app working well except few users still get same error
I don't understand why!
Hi I'm building an app and I'm using authentication using Firebase Auth rest API but the problem is that when I navigate between my tabs my app logOut automatically I don't know if it's expiration of token problem or something else so can some one help with that?
this is my auth part it's in my provider package
class Auth with ChangeNotifier {
String _token;
String _userId;
bool get isAuth {
return token != null;
}
String get token{
return _token;
}
String get userId {
return _userId;
}
Future<void> signup(String email, String password) async {
final url = Uri.parse(
'https://...myurl...'
);
try {
final response = await http.post(url,body: json.encode(
{
'email': email,
'password':password,
'returnSecureToken': true,
},), );
final responseData = json.decode(response.body);
if(responseData['error'] != null){
throw Exception();
}
_token = responseData['idToken'];
_userId = responseData['localId'];
notifyListeners();
} catch (error) {
throw error;
} }
Future<void> login(String email, String password) async {
final url = Uri.parse( 'https://...myurl...' );
try {
final response = await http.post(
url,
body: json.encode(
{
'email': email,
'password':password,
'returnSecureToken': true,
},),);
} catch (error) {
throw error;
} }}
this is the Ath screen:
enum AuthMode { Signup, Login }
class AuthScreen extends StatelessWidget {
static const routeName = '/auth';
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
bool _isLoading= false;
return Scaffold(
backgroundColor: Colors.pinkAccent[100],
body: SizedBox(
height: double.infinity,
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.all(8),
margin: EdgeInsets.all(8),
child: Expanded(
child:
SizedBox(
height: 280,
),
),
),
SingleChildScrollView(
child: Container(
height: deviceSize.height,
width: deviceSize.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 60,
child: LogoBekery(
color1:Colors.white,
color2:Colors.white,
color3:Colors.white,
),
),
SizedBox(
child: ImageSlideshow(
isLoop: true,
width: double.infinity,
height: 250,
initialPage: 0,
indicatorColor: Colors.pink,
indicatorBackgroundColor: Colors.grey,
children: [
Image.asset(
'assets/images/logoA.png',
fit: BoxFit.fill,
),
Image.asset(
'assets/images/logoB.png',
fit: BoxFit.fill,
),
Image.asset(
'assets/images/logoC.png',
fit: BoxFit.fill,
),
Image.asset(
'assets/images/logoD.png',
fit: BoxFit.fill,
),
],
onPageChanged: (value) {
// print('Page changed: $value');
},
autoPlayInterval: 3000,
),
),
Flexible(
flex: deviceSize.width > 600 ? 2 : 1,
child: AuthCard(),
),
],
),
),
),
],
),
),
);
}
void _submitAuthForm(
String email,
String password,
String username,
bool isLogin,
BuildContext ctx,
)
async {
UserCredential authResult; }
}
class AuthCard extends StatefulWidget {
const AuthCard({
Key key,
}) : super(key: key);
#override
_AuthCardState createState() => _AuthCardState();
}
class _AuthCardState extends State<AuthCard> {
final GlobalKey<FormState> _formKey = GlobalKey();
AuthMode _authMode = AuthMode.Login;
Map<String, String> _authData = {
'email': '',
'password': '',
};
var _isLoading = false;
final _passwordController = TextEditingController();
Future<void> _submit() async{
if (!_formKey.currentState.validate()) {
// Invalid!
return;
}
_formKey.currentState.save();
setState(() {
_isLoading = true;
});
try {
if (_authMode == AuthMode.Login) {
await Provider.of<Auth>(context, listen: false).login(
_authData['email'] ,
_authData['password'] );
} else {
await Provider.of<Auth>(context, listen: false).signup(
_authData['email'] ,
_authData['password'] );
}
Navigator.of(context).pushReplacementNamed(ProductOverviewScreen.routeName);
} on Exception catch (error) {
var errorMsg = 'Authentification Failed!';
}catch (error){
var errorMsg = 'Could not authentificate! please try later...';
}
setState(() {
_isLoading = false;
});
}
void _switchAuthMode() {
if (_authMode == AuthMode.Login) {
setState(() {
_authMode = AuthMode.Signup;
});
} else {
setState(() {
_authMode = AuthMode.Login;
});
}
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: Container(
height: _authMode == AuthMode.Signup ? 320 : 260,
constraints:
BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 150 : 260),
width: deviceSize.width * 0.8,
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (!RegExp(r'\S+#\S+\.\S+').hasMatch(value)) {
return 'Invalid email!';
}
return null;
return null;
},
onSaved: (value) {
_authData['email'] = value;
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value;
},
),
if (_authMode == AuthMode.Signup)
TextFormField(
enabled: _authMode == AuthMode.Signup,
decoration: InputDecoration(labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
SizedBox(
height: 20,
),
if (_isLoading)
CircularProgressIndicator()
else
RaisedButton(
child:
Text(_authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'),
onPressed: _submit,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
padding:
EdgeInsets.symmetric(horizontal: 30.0, vertical: 8.0),
color: Theme.of(context).primaryColor,
textColor: Theme.of(context).primaryTextTheme.button.color,
),
FlatButton(
child: Text(
'${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'}'),
onPressed: _switchAuthMode,
padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
),
);
}
}
Your _token and _userId is only set after registering. You don't set it after loging in. Therefore token could be null and isAuth will return false.
I think you should set the value of _token and _userId after the login function.
Future<void> login(String email, String password) async {
final url = Uri.parse('https://...myurl...');
try {
final response = await http.post(
url,
body: json.encode(
{
'email': email,
'password': password,
'returnSecureToken': true,
},
),
);
// added from here
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw Exception();
}
_token = responseData['idToken'];
_userId = responseData['localId'];
// to here.
} catch (error) {
throw 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.