Why Bottom Tab is still visible when I navigate to another screen? - firebase

This is the signin page in the app and my app contains 2 more screens under bottom tab after signing in but when I try to logout and Navigate back to signin screen ,it does navigate but the bottom tab bar still remains in the bottom which is not in the SignIn page.
FlatButton.icon(
onPressed: () => {
_auth.signOutGoogle(),
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignIn()))
},
icon: Icon(Icons.exit_to_app),
label: Text('Sign Out'))
This is my logout button and below is my main.dart file where I defined all the routes.
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider.value(value: AuthService().user),
],
child: Consumer<User>(
builder: (ctx, auth, _) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Wrapper(),
routes: {
'/homescreen': (ctx) => HomeScreen(),
'/signin': (ctx) => SignIn(),
'/dashboard': (ctx) => DashBoard(),
'/status': (ctx) => Status()
},
)),
);
}
}
Thank You.

FlatButton.icon(
onPressed: () => {
_auth.signOutGoogle(),
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => SignIn()),
(Route<dynamic> route) => false,);
},
icon: Icon(Icons.exit_to_app),
label: Text('Sign Out'))
if above solution doesn't work check this 2nd solution
FlatButton.icon(
onPressed: () => {
_auth.signOutGoogle(),
Navigator.of(context, rootNavigator: true).pushReplacement(
MaterialPageRoute(builder: (context) => SignIn()));
},
icon: Icon(Icons.exit_to_app),
label: Text('Sign Out'))

Related

Flutter streamprovider issue with userdata from Firebase

I've been stuck in this issue for sometime now and after lots of tries, now i don't know where the issue is.
The problem is i'm using StreamProvider to get userData from firebase and then use that userData through provider throughout my project, Now everything works fine but the issue arises when i try to log out. Actually even logout works perfectly, untill i close the app using the backbutton of my phone and then reopen the app from open apps list, then when i try to logout it doesn't work correctly. When i refresh the app the user is logged out but initially it doesn't navigate to the login screen.
here is the logout code.
InkWell(
onTap: () async {
await showDialog(
context: context,
useRootNavigator: false,
builder: (ctx) => AlertDialog(
title: const Text("Are you Sure?"),
content: const Text("Do You want to logout?"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
"No",
style: TextStyle(
color: ColorConstant.appColor,
),
),
),
TextButton(
onPressed: () async {
Navigator.of(context).pop(true);
await AuthService().signOut();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: ((context) =>
const LoginScreen())),
(route) => false);
},
child: const Text(
"Yes",
style: TextStyle(
color: ColorConstant.appColor,
),
),
),
],
),
);
},
And here is the main.dart i've defined StreamProvider.
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
final _auth = AuthService();
final String? _userId = _auth.user?.uid;
return MultiProvider(
providers: [
StreamProvider<List<Packages>>(
create: (_) => DatabaseService().packages, initialData: const []),
StreamProvider<UserModel?>(
create: (_) => DatabaseService().userData(_userId),
initialData: null,
),
],
builder: (context, child) {
return MaterialApp(
title: 'DreamaX',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: ColorConstant.appColor,
errorColor: Colors.red,
),
home: const Wrapper(),
);
},
);
}
}
Also one another thing that when i'm logging in, i navigate to MyApp so that the StreamProvider can get the userId and initialize the streamprovider.
here is the login code
try {
await _authService.signIn(
emailCont: _emailCont.text.trim(),
passCont: _passCont.text.trim());
Navigator.of(context)
.pushAndRemoveUntil(
MaterialPageRoute(
builder: ((context) =>
const MyApp())),
(route) => false);
} on FirebaseAuthException catch (e) {
So i'm really confused now what could be the cause here?

Flutter Firebase Auth - change home widget if the user is logged in

I'm building an app that supports only google login using google_sign_in package. When the app is run, it first checks if FirebaseAuth is alive. If user in FirebaseAuth.instance.authStateChanges().listen((User? user) is not null, HomePage() should be shown. If the user is null it should go to AuthPage() which has a google sign-in button.
The code for main.dart is shown below.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
Widget _defaultHome = HomePage();
// Check if user already logged in
FirebaseAuth auth = FirebaseAuth.instance;
auth.authStateChanges().listen((User? user) {
if (user == null) {
_defaultHome = AuthPage();
}
print(user);
});
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SignInProvider()),
ChangeNotifierProvider(create: (_) => DataProvider()),
],
child: new MaterialApp(
title: 'Mentea',
home: _defaultHome,
routes: {
'auth': (context) => AuthPage(),
'home': (context) => HomePage(),
},
),
));
}
But when I run it, console gives
I/flutter (14933): null
which means no logged in user, but the emulator shows HomePage() instead of AuthPage(). Anybody know how to fix this? I tried changing 'home:' attribute to 'initialRoute:', but it doesn't work either (directs to HomePage() while printing null).
String _defaultHome = 'home';
...
auth.authStateChanges().listen((User? user) {
if (user == null) {
_defaultHome = 'auth;
}
});
...
child: new MaterialApp(
title: 'Mentea',
initialRoute: _defaultHome,
routes: {
'auth': (context) => AuthPage(),
'home': (context) => HomePage(),
},
),
We can assign a StreamBuilder that listens to FirebaseAuth state changes, to the home property:
StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (user) {
return user == null ? AuthPage() : HomePage(),
}
),
Follows a full example:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SignInProvider()),
ChangeNotifierProvider(create: (_) => DataProvider()),
],
child: MaterialApp(
title: 'Mentea',
home: StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (user) {
return user == null ? AuthPage() : HomePage(),
},
),
routes: {
'auth': (context) => AuthPage(),
'home': (context) => HomePage(),
},
),
));
}

how to pass data between two pages in flutter using bottom navigation bar

i'm new in flutter world. i'm using bottom navigation bar but i don't have idea how to pass data from bottom navigation bar page to homepage since homepage is expecting 1 parameter. i'm passing data between other pages but i couldn't find a way to pass data between bottomnavigation bar and home page. any help would be apprecaited
thanks in advance
this is my navigation page code
import 'package:chat_app/models/user_model.dart';
import 'package:chat_app/screens/call_log_screen.dart';
import 'package:chat_app/screens/chat_screen.dart';
import 'package:chat_app/screens/home_screen.dart';
import 'package:chat_app/screens/search_screen.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class CustomBottomNavigationBar extends StatefulWidget {
UserModel user;
CustomBottomNavigationBar(this.user);
#override
_CustomBottomNavigationBarState createState() =>
_CustomBottomNavigationBarState();
}
class _CustomBottomNavigationBarState extends State<CustomBottomNavigationBar> {
int _selectedIndex = 0;
late final screens = [
HomeScreen(widget.user),
CallLog(),
CallLog(),
CallLog(),
];
void onTapped(int index) {
print(widget.user.name);
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: screens[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.black,
selectedIconTheme: IconThemeData(color: Colors.blue),
currentIndex: 2,
items: [
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.settings,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.home,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.phone,
color: Colors.grey,
),
label: 'hi',
),
BottomNavigationBarItem(
icon: Icon(
CupertinoIcons.chat_bubble_text,
color: Colors.grey,
),
label: 'hi',
),
],
onTap: onTapped,
),
);
}
}
and this is my homepage code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:chat_app/models/user_model.dart';
import 'package:chat_app/screens/chat_screen.dart';
import 'package:chat_app/screens/search_screen.dart';
import 'package:chat_app/widgets/bottom_navigation_bar.dart';
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:google_sign_in/google_sign_in.dart';
import 'package:intl/intl.dart';
import 'auth_screen.dart';
class HomeScreen extends StatefulWidget {
UserModel user;
HomeScreen(this.user);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with WidgetsBindingObserver {
#override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance!.addObserver(this);
setStatus('online');
}
void setStatus(String status) async {
await FirebaseFirestore.instance
.collection('users')
.doc(widget.user.uid)
.update({"userStatus": status});
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
// TODO: implement didChangeAppLifecycleState
if (state == AppLifecycleState.resumed) {
//online
setStatus("online");
} else {
//offline
setStatus('offline');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
centerTitle: true,
backgroundColor: Colors.deepPurple,
actions: [
IconButton(
onPressed: () async {
await GoogleSignIn().signOut();
await FirebaseAuth.instance.signOut();
setStatus('offline');
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => AuthScreen(),
),
(route) => false);
},
icon: Icon(Icons.logout),
),
],
),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('users')
.doc(widget.user.uid)
.collection('messages')
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.docs.length < 1) {
return Center(
child: Text('No Chat Available!!!'),
);
}
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
var friendId = snapshot.data.docs[index].id;
var lastMsg = snapshot.data.docs[index]['last_message'];
var lastMsgTime =
snapshot.data.docs[index]['last_message_time'];
return FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.doc(friendId)
.get(),
builder: (context, AsyncSnapshot asyncSnapShot) {
if (asyncSnapShot.hasData) {
var friend = asyncSnapShot.data;
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(80.0),
child: CachedNetworkImage(
imageUrl: friend['image'],
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
// child: Image.network(
// friend['image'],
// ),
),
trailing: Text(
DateFormat.jm().format(
lastMsgTime.toDate(),
),
),
title: Text(
friend['name'],
),
subtitle: Text(
"$lastMsg",
style: TextStyle(color: Colors.grey),
overflow: TextOverflow.ellipsis,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
currentUser: widget.user,
receiverId: friend['uid'],
receiverImage: friend['image'],
receiverName: friend['name'],
),
),
);
},
);
}
return LinearProgressIndicator();
},
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchScreen(widget.user),
),
);
// Navigator.pushAndRemoveUntil(
// context,
// MaterialPageRoute(
// builder: (context) => SearchScreen(widget.user),
// ),
// (route) => false);
},
child: Icon(CupertinoIcons.search),
),
bottomNavigationBar: CustomBottomNavigationBar(widget.user),
);
}
}
You can't access instance member widget in an initializer.
Try this
class _CustomBottomNavigationBarState extends State<CustomBottomNavigationBar> {
int _selectedIndex = 0;
late final List screens;
#override
void initState() {
super.initState();
screens = [
HomeScreen(widget.user),
CallLog(),
CallLog(),
CallLog(),
];
}
...
// the rest of your code

Logout with Firebase not working after navigating to a particular screen

Logout works fine from the home screen and even when navigating to other screens and then returning to the home screen to logout, however, when starting the assessment from the home screen which takes you to 'assessment_list' and you return to the home screen, logout doesn't work. How would I fix this?
Home Screen
actions: [
...
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: [
const Icon(Icons.exit_to_app),
const Text('Logout'),
const SizedBox(width: 8),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
...
RaisedButton(
child: Text(
'Start Assessment'
),
onPressed: () {
navigateToAssessmentList(context);
},
),
...
Future navigateToAssessmentList(context) async {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AssessmentList()));
}
assessment_list
child: RaisedButton(
padding: EdgeInsets.all(10),
color: const Color(0xfff4f4f4),
child: Text(
'Back To Home',
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => BottomNavBarController()));
}),
You are pushing the same page again in the stack. Please replace the following line
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => BottomNavBarController()));
with this
Navigator.pop(context)

Cannot get onMessage to show when App is in foreground

I am writing an app where you can press a button and it will send a 'Help' notification to every over app (this will be a closed group of around 100) I need the notifiction to pop up whatever state the app is in, I have the onResume and onLaunch sorted, but I cannot get it to display the notification when the app is in the foreground. There are many screens, I need the notification to show up on whatever screen the user is on.
I have tried many tutorials, but just cannot get it to work. I have the code in my initState on my Main page.
void main() {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
var initializationSettingsAndroid =
new AndroidInitializationSettings('#mipmap/ic_launcher');
var initializationSettingsIOS = IOSInitializationSettings();
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onSelectNotification);
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
showDialog(
context: context,
builder: (context) =>
AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
showDialog(
context: context,
builder: (context) =>
AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
showDialog(
context: context,
builder: (context) =>
AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
},
);
Future onSelectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: ' + payload);
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
importance: Importance.Max, priority: Priority.High,ticker:'ticker');
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'plain title', 'plain body', platformChannelSpecifics,
payload: 'item x');
}
}
// #override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Benidorm or Bust',
theme: ThemeData.dark().copyWith(
primaryColor: Color(0xFF0A0E21),
scaffoldBackgroundColor: Color(0xFF0A0E21),
),
initialRoute: '/',
routes: {
'/': (context) => MyHomePage(),
'/setup': (context) => Setup(),
'/dayinit': (context) => Dayinit(),
'/day1': (context) => Day1(),
'/day2': (context) => Day2(),
'/day3': (context) => Day3(),
'/day4': (context) => Day4(),
'/day5': (context) => Day5(),
'/CheckList': (context) => CheckList(),
'/eveinit': (context) => Eveinit(),
'eve1eve': (context) => Eve1Eve(),
// 'push':(context)=> Push(),
},
);
}
}
I am not getting any error, just nothing happens.
I faced the same issue, just move Firebase related code from "app" MyApp to MyHomePage widget. Inside MyHomePage it will have proper context.
I've used this as an example https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/example/lib/main.dart#L240

Resources