I have been working on this Getx library for the first time and i don't know why but the initial screen function is not working for some reason. It's not showing any bug in the stack trace so i guess it's gotta be something else. has anyone any idea? Debug shows no error or warnings.
here's the code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tutorial_two/screens/screen_home.dart';
import 'package:tutorial_two/screens/screen_login.dart';
import 'package:velocity_x/velocity_x.dart';
class AuthController extends GetxController {
static AuthController instance =
Get.find(); // auth controller instance; will be called in other widgets
// user instance
late Rx<User?> _user;
// get user data like name, email, password etc
FirebaseAuth auth = FirebaseAuth.instance; // firebase auth instance
#override
void onReady() {
super.onReady();
_user = Rx<User?>(auth.currentUser); // getting current user
_user.bindStream(
auth.userChanges(),
); //notifies app about user login and logout
ever(_user,
_initialScreen); //this funnction will make sure user gets to correct screen
}
_initialScreen(User? user) {
if (user == null) {
Get.offAll(() => const LoginScreen());
} else {
Get.offAll(() => const HomeScreen());
}
}
Future<void> register(
BuildContext context, String email, username, password) async {
try {
await auth.createUserWithEmailAndPassword(
email: email, password: password);
//await Future.delayed(const Duration(seconds: 2));
Future.delayed(
const Duration(
seconds: 1,
), () {
VxToast.show(context,
msg: "Registration Successful",
bgColor: Colors.green.shade100,
textColor: Colors.green.shade500,
textSize: 14,
position: VxToastPosition.center);
});
} catch (e) {
VxToast.show(context,
msg: "Error: $e",
bgColor: Colors.red.shade100,
textColor: Colors.red.shade500,
textSize: 14,
position: VxToastPosition.center);
}
}
Future<void> login(BuildContext context, String email, password) async {
try {
await auth.signInWithEmailAndPassword(email: email, password: password);
//await Future.delayed(const Duration(seconds: 2));
Future.delayed(
const Duration(
seconds: 1,
), () {
VxToast.show(context,
msg: "Login Successful",
bgColor: Colors.green.shade100,
textColor: Colors.green.shade500,
textSize: 14,
position: VxToastPosition.center);
});
} catch (e) {
VxToast.show(context,
msg: "Error: $e",
bgColor: Colors.red.shade100,
textColor: Colors.red.shade500,
textSize: 14,
position: VxToastPosition.center);
}
}
Future<void> logOut(BuildContext context) async {
try {
await auth.signOut();
} catch (e) {
VxToast.show(context,
msg: "Error: $e",
bgColor: Colors.red.shade100,
textColor: Colors.red.shade500,
textSize: 14,
position: VxToastPosition.center);
}
}
}
here's the main code
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:tutorial_two/screens/screen_home.dart';
import 'package:tutorial_two/screens/screen_login.dart';
import 'package:tutorial_two/screens/screen_signup.dart';
import 'package:tutorial_two/screens/screen_splash.dart';
import 'package:tutorial_two/utils/auth_controller.dart';
import 'package:tutorial_two/utils/routes.dart';
import 'package:tutorial_two/widgets/themes.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
Firebase.initializeApp().then((value) {
Get.put(AuthController());
});
runApp(const TutorialTwo());
}
class TutorialTwo extends StatelessWidget {
const TutorialTwo({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
themeMode: ThemeMode.system,
theme: MyTheme.lightTheme(context),
darkTheme: MyTheme.darkTheme(context),
debugShowCheckedModeBanner: false,
home: const SplashScreen(),
routes: {
MyRoutes.homeRoute: (context) => const HomeScreen(),
MyRoutes.loginRoute: (context) => const LoginScreen(),
MyRoutes.signupRoute: (context) => const SignupScreen(),
},
);
}
}
To use Get navigation management, you must use GetMaterialApp instead of MaterialApp,
//Replace the following line
return MaterialApp(
//with this one
return GetMaterialApp(
Related
I'm trying to test a payment gateway method with stripe and I have this error when i try to click the button which it said "[log] {success: false, error: o is not defined}", here is my code. I'm not sure what or how to solve this but I would really need some help on this one. Also I included with the screenshot of the problem
Main.dart
import 'dart:convert';
import 'dart:developer';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:http/http.dart' as http;
Future <void> main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: FirebaseOptions(apiKey: "AIzaSyD7Uhhiv85NCcDjoTEQ-K7T5qU4bNXci8M",
appId: "XXX", messagingSenderId: "XXX",
projectId: "itt632-56973",
));
Stripe.publishableKey = "pk_test_51LHIjvJ5bt4B4CmJ3xTspeufDqv4VojZlmhuBaVvjhUoDbJaoKziiUkFZPOTl3a4CbVcfdmnJKosItZiiweRYfvF00aOI2xKIS";
Stripe.instance.applySettings();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Demo(),
);
}
}
// 'https://us-central1-itt632-56973.cloudfunctions.net/stripePaymentIntentRequest'),
class Demo extends StatelessWidget {
const Demo({Key? key}) : super(key: key);
Future<void> initPayment(
{required String email,
required double amount,
required BuildContext context}) async {
try {
// 1. Create a payment intent on the server
final response = await http.post(
Uri.parse(
'https://us-central1-itt632-56973.cloudfunctions.net/stripePaymentIntentRequest'),
body: {
'email': email,
'amount': amount.toString(),
});
final jsonResponse = jsonDecode(response.body);
log(jsonResponse.toString());
// 2. Initialize the payment sheet
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: jsonResponse['paymentIntent'],
merchantDisplayName: 'Grocery Flutter course',
customerId: jsonResponse['customer'],
customerEphemeralKeySecret: jsonResponse['ephemeralKey'],
testEnv: true,
merchantCountryCode: 'SG',
));
await Stripe.instance.presentPaymentSheet();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Payment is successful'),
),
);
} catch (errorr) {
if (errorr is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('An error occured ${errorr.error.localizedMessage}'),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('An error occured $errorr'),
),
);
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text('Pay 50\$'),
onPressed: () async {
await initPayment(
amount: 50.0, context: context, email: 'JEFRILUQMAN#test.com');
},
)),
);
}
}
Here is the index.js function for the stripe
const functions = require("firebase-functions");
const stripe = require("stripe")("sk_test_51LHIjvJ5bt4B4CmJclvzNcSaSPICuutFIjmg3GZb1sv6fySDehLAhvHOW2hl1W7EWXYM5oqfHkHZyJDeB36rIJpf00ksfQJnWa");
exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => {
try {
let customerId;
//Gets the customer who's email id matches the one sent by the client
const customerList = await stripe.customers.list({
email: req.body.email,
limit: 1
});
//Checks the if the customer exists, if not creates a new customer
if (customerList.data.length !== 0) {
customerId = customerList.data[0].id;
}
else {
const customer = await stripe.customers.create({
email: req.body.email
});
customerId = customer.data.id;
}
//Creates a temporary secret key linked with the customer
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customerId },
{ apiVersion: '2020-08-27' }
);
//Creates a new payment intent with amount passed in from the client
const paymentIntent = await stripe.paymentIntents.create({
amount: parseInt(req.body.amount),
currency: 'usd',
customer: customerId,
})
res.status(200).send({
paymentIntent: paymentIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customerId,
success: true,
})
} catch (error) {
res.status(404).send({ success: false, error: error.message })
}
});
Screenshot
Screenshot2
I'm using the uni_links package which creates a deep_link that when clicked opens exactly the screen I need. Now I am able to automatically open the app from the given link but it doesn't go to the exact screen I need, it just goes to the default page. I also use getX for state management if that helps. If the question is incorrect, please feel free to commend
The page needs to be opened from the link, new_password_page.dart
import 'package:darcy/app/global_widgets/base_button.dart';
import 'package:darcy/app/global_widgets/outline_textfield.dart';
import 'package:darcy/app/modules/forgot_password/forgot_controller_page.dart';
import 'package:darcy/routes/pages.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:uni_links/uni_links.dart';
import '../../../core/theme/app_theme.dart';
class NewPasswordPage extends StatelessWidget {
final ForgotController _homeController = Get.find<ForgotController>();
NewPasswordPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
String newPassword = '';
String confirmPassword = '';
return Scaffold(
backgroundColor: AppTheme.base_background,
appBar: AppBar(
title: Text('New Password'),
elevation: 0.0,
backgroundColor: AppTheme.transparent,
),
body: Container(
width: double.infinity,
height: double.infinity,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.2,
),
OutlinedTextField(
text: newPassword,
labelText: 'New password',
messageText: '',
onTextChange: (value) {
newPassword = value;
},
customIcon: Icons.password_rounded,
obscureText: true,
),
const SizedBox(
height: 16.0,
),
OutlinedTextField(
text: confirmPassword,
labelText: 'Confirm password',
messageText: '',
onTextChange: (value) {
confirmPassword = value;
},
customIcon: Icons.password_rounded,
obscureText: true,
),
const SizedBox(
height: 32.0,
),
SizedBox(
height: 40.0,
width: double.infinity,
child: BaseButton(
buttonText: 'confirm'.tr,
buttonColor: AppTheme.sign_in,
buttonFunction: () {
Get.toNamed(Routes.SUCCESS);
},
)),
],
),
),
),
),
);
}
}
new_password_controller.dart
import 'dart:async';
import 'package:darcy/app/data/network/services/user_api.dart';
import 'package:darcy/core/base_controller/base_controller.dart';
import 'package:darcy/routes/pages.dart';
import 'package:flutter/services.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:get/get.dart';
import 'package:uni_links/uni_links.dart';
class ForgotController extends GetxController with BaseController {
var id = '';
var email = '';
StreamSubscription? sub;
final UserApi _userApi = Get.find<UserApi>();
#override
void onInit() {
// TODO: implement onInit
super.onInit();
initUniLinks();
}
Future<Null> initUniLinks() async {
try {
String? initialLink = await getInitialLink();
// Parse the link and warn the user, if it is not correct,
// but keep in mind it could be `null`.
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
void forgot() async {
showLoading(message: 'Please wait...', barrierDismissible: false);
final Email send_email = Email(
body: 'Đây nè em trai http://flutterbooksample.com',
subject: 'Link khôi phụn password',
recipients: ['samnkse62331#fpt.edu.vn'],
isHTML: false,
);
try {
hideLoading();
await FlutterEmailSender.send(send_email);
} catch (e) {
print("hàng: ${e}");
}
// await _userApi.forgot(email, int.parse(id)).then((value) {
// hideLoading();
// print(value.error);
// if (value.error != true) {
// Get.toNamed(Routes.RECOVERY);
// }
// }).catchError((e) {
// handleErrorWithToast(e);
// });
}
}
method to open the app from link
Future<Null> initUniLinks() async {
try {
String? initialLink = await getInitialLink();
// Parse the link and warn the user, if it is not correct,
// but keep in mind it could be `null`.
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
main.dart
import 'package:darcy/core/lang/localization_service.dart';
import 'package:darcy/core/storage/spref_helper.dart';
import 'package:darcy/core/theme/app_theme.dart';
import 'package:darcy/injector.dart';
import 'package:darcy/routes/pages.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
//forced portrait orientation only
await InitialBinding().setup();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
runApp(const MyApp());
});
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Darcy',
debugShowCheckedModeBanner: false,
getPages: Pages.pages,
initialRoute: Routes.SPLASH,
initialBinding: InitialBinding(),
theme: ThemeData(
primarySwatch: AppTheme.colorPrimarySwatch,
),
locale:
Get.find<SharedPreferencesHelper>().getDefaultLocaleFromLangCode(),
fallbackLocale: LocalizationService.fallbackLocale,
translations: LocalizationService(),
);
}
}
I would suggest that you use named routes.
Let's say your deep link is something like https://my.app/new-password and you have a named route in your app for this page called new-password, then on your function initUnilinks, you get the path of the URI and navigate to the route you want.
Future<void> initUniLinks() async {
try {
Uri? initialLink = await getInitialLink();
if (initalLink != null) {
Navigator.of(context).pushNamed(initialLink.path);
}
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
I'm not familiar with getX, it might have something for routing that you could use.
I am struggling to to show my custom error messages during login/sign up. The error messages that are showing up are the default ones coming from Firebase. I need to display the custom error messages in the code below depending on the error code. Please assist...
I'm not sure what's still missing. Iv'e tried everything but still not winning
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.dart';
import '../widgets/auth/auth_form.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class AuthScreen extends StatefulWidget {
const AuthScreen({Key? key}) : super(key: key);
static const routeName = '/auth_screen';
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
final _auth = FirebaseAuth.instance;
var _isLoading = false;
void _submitAuthForm(
String email,
String password,
String displayName,
String phoneNumber,
bool isLogin,
BuildContext ctx,
) async {
UserCredential authResult;
try {
setState(() {
_isLoading = true;
});
if (isLogin) {
authResult = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else {
authResult = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
await FirebaseFirestore.instance
.collection('userProfile')
.doc(authResult.user!.uid)
.set(
{
'displayName': displayName,
'email': email,
'phoneNumber': phoneNumber,
'uid': authResult.user!.uid,
},
);
}
} on FirebaseAuthException catch (error) {
var message = 'An error has occured.'; // default message
switch (error.code) {
case 'EMAIL_NOT_FOUND':
message = 'There is no user account with the email address provided.';
break;
case 'EMAIL_EXISTS':
message = 'The email address is already in use by another account.';
break;
case 'INVALID_PASSWORD':
message = 'Invalid password. Please enter correct password.';
break;
}
setState(() {
_isLoading = false;
});
showDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: const Text('An error occured'),
content: Text(
error.message.toString(),
),
actions: [
TextButton(
child: const Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
}
}
I think your problem lies in the fact that while you have defined a message variable, you are not using it inside the dialog. You are instead using error.message.toString().
showDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: const Text('An error occured'),
content: Text(
error.message.toString(), /// <-------------- HERE
),
actions: [
TextButton(
child: const Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
Replace that with message and it should work.
I am trying to access userModel.uid from UserProvider inside the ItemProvider so it can load _savedItems.
However, when I call loadUserSavedItems(), _userId is null.
Here is my main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/user.dart';
import 'providers/item.dart';
import 'screens/home.dart';
void main() {
Provider.debugCheckInvalidValueType = null;
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (_) => UserProvider.initialize()),
ChangeNotifierProxyProvider<UserProvider, ItemProvider>(
create: (_) => ItemProvider(),
update: (_, userProvider, itemProvider) => itemProvider,
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
primaryTextTheme: TextTheme(
headline6: TextStyle(color: Colors.black),
),
),
home: Home(),
),
),
);
}
UserProvider.dart
import 'models/user.dart';
import 'services/user.dart';
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class UserProvider extends ChangeNotifier {
FirebaseAuth _auth;
FirebaseUser _user;
Status _status = Status.Uninitialized;
Firestore _firestore = Firestore.instance;
UserServices _userServicse = UserServices();
UserModel _userModel;
// getter
UserModel get userModel => _userModel;
Status get status => _status;
FirebaseUser get user => _user;
UserProvider.initialize() : _auth = FirebaseAuth.instance {
_auth.onAuthStateChanged.listen(_onStateChanged);
notifyListeners();
}
Future<void> _onStateChanged(FirebaseUser firebaseUser) async {
if (firebaseUser == null) {
_status = Status.Unauthenticated;
} else {
_user = firebaseUser;
_status = Status.Authenticated;
_userModel = await _userServicse.getUserById(user.uid);
}
notifyListeners();
}
Future<bool> signIn() async {
bool retVal = false;
try {
_status = Status.Authenticating;
notifyListeners();
AuthResult _authResult = await _auth.signInWithEmailAndPassword(
email: email.text.trim(), password: password.text.trim());
if (_authResult.user != null) {
retVal = true;
}
} catch (e) {
_status = Status.Unauthenticated;
notifyListeners();
print(e.toString());
}
return retVal;
}
}
ItemProvider.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'models/item.dart';
import 'providers/user.dart';
import 'services/item.dart';
class ItemProvider extends ChangeNotifier {
ItemProvider({UserProvider userProvider}) : _userProvider = userProvider;
UserProvider _userProvider;
final databaseReference = Firestore.instance;
ItemServices _itemServices = ItemServices();
List<Item> _items = [];
List<Item> _savedItems = [];
String _userId;
// getter
List<Item> get items => _items;
List<Item> get savedItems => _savedItems;
String get userId => _userId;
UserProvider get userProvider => _userProvider;
//get the items to load when the app is initiated
ItemProvider.initialize() {
loadAllActiveItems();
if (_userProvider.status == Status.Authenticated) {
loadUserSavedItems();
}
}
//get active items from DB
loadAllActiveItems() async {
_items = await _itemServices.getBatchOfActiveItems();
notifyListeners();
}
//get user saved items from DB
loadUserSavedItems() async {
_userId = userProvider.userModel.uid;
_savedItems = await _itemServices.getUserSavedItems(userId);
notifyListeners();
}
}
Can someone help me, I am not quite sure what I am missing, can't userModel object/properties in ItemProvider.dart when implemented as ChangeNotifierProxyProvider.
I finally found a way around, maybe not the best but it worked.
Inside ItemProvider created updates() to receive the userId from
void updates(String userId, Status status) {
this._userId = userId;
}
And then made the changes in main.dart to pass the userId from ChangeNotifierProxyProvider.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/user.dart';
import 'providers/item.dart';
import 'screens/home.dart';
void main() {
Provider.debugCheckInvalidValueType = null;
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (_) => UserProvider.initialize()),
ChangeNotifierProxyProvider<UserProvider, ItemProvider>(
create: (_) => ItemProvider(),
update: (_, userProvider, itemProvider) => itemProvider
..updates(
userProvider.user != null ? userProvider.user.uid : ''),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
primaryTextTheme: TextTheme(
headline6: TextStyle(color: Colors.black),
),
),
home: Home(),
),
),
);
}
Happy to hear what others have done as well.
I have completed the following tutorial https://dev.to/amartyadev/flutter-app-authentication-with-django-backend-1-21cp which although useful, has left me still pretty clueless how to move forward. I am able to login and the user details are saved via a UserRepository class to a sqlite database locally, including the authentication token, but I have no idea how to access this when trying to make repeat requests to the server for data. there are no problems with the existing code but I will present several pages so you can see what I have done and am trying to achieve and how it is put together.
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import './repository/user_repository.dart';
import './bloc/authentication/authentication_bloc.dart';
import './screens/splash_screen.dart';
import './screens/login/login_screen.dart';
import './screens/home_screen.dart';
import './widgets/loading_indicator.dart';
import './widgets/video_widget.dart';
import './screens/home_screen.dart';
const welcomeUrl = 'https://soundjudgement.github.io/static-sf/tour.mp4';
class SimpleBlocDelegate extends BlocDelegate {
#override
void onEvent(Bloc bloc, Object event) {
super.onEvent(bloc, event);
print(event);
}
#override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print(transition);
}
#override
void onError(Bloc bloc, Object error, StackTrace stacktrace) {
super.onError(bloc, error, stacktrace);
}
}
void main() {
BlocSupervisor.delegate = SimpleBlocDelegate();
final userRepository = UserRepository();
runApp(BlocProvider<AuthenticationBloc>(
create: (context) {
return AuthenticationBloc(userRepository: userRepository)
..add(AppStarted());
},
child: SundayFundayApp(userRepository: userRepository),
));
}
class SundayFundayApp extends StatelessWidget {
// This widget is the root of your application.
final UserRepository userRepository;
SundayFundayApp({Key key, #required this.userRepository}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'The Yard Mobile App',
theme: ThemeData(
primarySwatch: Colors.yellow,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is AuthenticationUnintialized) {
return SplashPage();
}
if (state is AuthenticationAuthenticated) {
return HomeScreen();
}
if (state is AuthenticationUnauthenticated) {
return LogInScreen(
userRepository: userRepository,
);
}
if (state is AuthenticationLoading) {
return LoadingIndicator();
}
},
),
);
}
}
user_repository.dart
import 'dart:async';
import '../models/user_model.dart';
import 'package:meta/meta.dart';
import '../models/api_model.dart';
import '../api_connection/api_connection.dart';
import '../dba/user_dba.dart';
class UserRepository {
final userDao = UserDba();
Future<User> authenticate({
#required String username,
#required String password,
}) async {
UserLogin userLogin = UserLogin(username: username, password: password);
Token token = await getToken(userLogin);
User user = User(
id: 0,
username: username,
token: token.token,
);
return user;
}
Future<void> persistToken({#required User user}) async {
// write token with the user to the database
await userDao.createUser(user);
}
Future<void> deleteToken({#required int id}) async {
await userDao.deleteUser(id);
}
Future<bool> hasToken() async {
bool result = await userDao.checkUser(0);
return result;
}
}
user_dao.dart:
import '../database/user_database.dart';
import '../models/user_model.dart';
class UserDao {
final dbProvider = DatabaseProvider.dbProvider;
Future<int> createUser(User user) async {
final db = await dbProvider.database;
var result = db.insert(userTable, user.toDatabaseJson());
return result;
}
Future<int> deleteUser(int id) async {
final db = await dbProvider.database;
var result = await db
.delete(userTable, where: "id = ?", whereArgs: [id]);
return result;
}
Future<bool> checkUser(int id) async {
final db = await dbProvider.database;
try {
List<Map> users = await db
.query(userTable, where: 'id = ?', whereArgs: [id]);
if (users.length > 0) {
return true;
} else {
return false;
}
} catch (error) {
return false;
}
}
}
login_screen.dart:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../repository/user_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../bloc/authentication/authentication_bloc.dart';
import './bloc/login_bloc.dart';
import 'login_form.dart';
class LogInScreen extends StatelessWidget {
final UserRepository userRepository;
LogInScreen({Key key, #required this.userRepository})
: assert(userRepository != null),
super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text('The Yard App'),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/theyardbook.png'),
fit: BoxFit.cover,
)
),
child: BlocProvider(
create: (context) {
return LoginBloc(
authenticationBloc: BlocProvider.of<AuthenticationBloc>(context),
userRepository: userRepository,
);
},
child: Container(
child: Scaffold(
backgroundColor: Colors.transparent,
body: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.transparent,
),
child: Padding(
padding: EdgeInsets.all(23),
child: LoginForm(),
),
),
),
),
),
),
);
}
}
Once the user is logged in, the app takes you to a home screen and it is this screen I have placed a button to take me to another screen which will fetch data from the server to display. For now the only data available is the one single registered user which is fine, I just need to see how it works because I am totally stuck and have been for 3 days. What I need to know, is how do I access the authentication token?? I am assuming (hoping) the process will be the same accessing any data saved to a local db.
TIA
I can copy and paste more code but I feel like there is a lot there and the tutorial is pretty clear, it just help me with this final
So here is the code in the user-dao, which I just need to import in any widget/class I am needing to access the server. Seems obvious and totally straight forward but amongst all the Dart code which I am unfamiliar with and the many files used in the bloc pattern, I think my head was getting confused.
Future<String> getUserToken(int id) async {
final db = await dbProvider.database;
try {
var res = await db.rawQuery("SELECT token FROM userTable WHERE id=0");
return res.isNotEmpty ? (User.fromDatabaseJson(res.first)).token : null;
} catch (err) {
return null;
}
}
Here is the new users_screen code, using FutureBuilder
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../widgets/logout_button.dart';
import '../repository/user_repository.dart';
import 'package:http/http.dart' as http;
import '../dao/user_dao.dart';
import '../api_connection/api_connection.dart';
import '../models/user_model.dart';
class UserScreen extends StatefulWidget {
#override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
Future<User> futureUser;
#override
void initState() {
super.initState();
futureUser = getUser();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('The Yard Users'),
),
body: Container(
child: FutureBuilder( // use a future builder widget
future: futureUser, // assign the future
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
// show your layout if future is done
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 30.0),
child: Text(
'Username: ${snapshot.data.username}', // get the username from the snapshot
style: TextStyle(
fontSize: 24.0,
),
),
),
// Logout button
Padding(
padding: EdgeInsets.fromLTRB(34.0, 20.0, 0.0, 0.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.85,
height: MediaQuery.of(context).size.width * 0.16,
child: LogoutButton()
),
),
],
);
} else {
return CircularProgressIndicator(); // show a progress indicator while future is executing
}
},
),
),
);
}
}