Code With Bisky

Build a Real-Time Flutter Chat App with User Last Seen & Online Status | Firebase Tutorial [22]

Key Topics covered:

  • Real-time User Status Updates
  • Displaying User Last Seen Timestamps

Description:

In this tutorial, you will learn how to create a fully functional chat app with exciting features like user last seen and online status using Firebase Realtime Database. Enhance user engagement, keep conversations flowing, and bring life to your chat app with our comprehensive guide.

Add the following dependencies in your pubspec.yaml.


dependencies:
  .........
  timeago_flutter: ^3.5.0
  flutter_fgbg: ^0.3.0
  firebase_database: ^10.2.4


        
        

Firebase Create Database

  • Login on firebase console
  • Select Build Option on Menu Side bar
  • Select Realtime Database
  • Create a New Database
  • Update your rules to true
  • You are done

{
  "rules": {
    ".read": true,
    ".write": true
  }
}
        
        

Code Snippet(FirebaseProvider.dart):

  • lib/core/providers/FirebaseProvider.dart

Add code to handle user presence even the user has been disconnected


class FirebaseProvider{

  StreamSubscription? subscription;
  FirebaseDatabase database = FirebaseDatabase.instance;
  Future<void>  configurePresence() async{
    String myUserId = await LocalStorageService.getString(LocalStorageService.userId) ?? "";
    DatabaseReference con;
    final myConnectionRef = database.ref()
    .child('presence')
    .child(myUserId)
    .child('connections');

    final lastOnlineRef = database.ref()
        .child('presence')
        .child(myUserId)
        .child('lastOnline');

    await database.goOnline();
    subscription = database.ref()
    .child('.info/connected').onValue.listen((event) {
      if(event.snapshot.value != null){
        con = myConnectionRef.push();
        con.onDisconnect().remove();
        con.set(true);
        lastOnlineRef.onDisconnect().set(ServerValue.timestamp);

      }
    });

  }
  void connect(){
    configurePresence();
  }
  disconnect(){
    subscription?.cancel();
    database.goOffline();
  }
}

 
        

Code Snippet(MessageState.dart):

  • lib/model/MessageState.dart

Add onlineStatus on MessageState


 @Default('') String onlineStatus,
 

Don't forget to run the following command in your terminal to generate onlineStatus flutter packages pub run build_runner build

Code Snippet(DashboardPage.dart):

  • lib/pages/dashboard/DashboardPage.dart

Call configurePresence in initaState() method. Disconnect online state when application is in background


// declare
  final firebaseProvider = FirebaseProvider();
  StreamSubscription<FGBGType>? subscription;

// add below code in initState()
  void initState() {
    super.initState();

 firebaseProvider.configurePresence();
    subscription = FGBGEvents.stream.listen((event) {

      if(event == FGBGType.foreground){

        firebaseProvider.connect();
      }else if(event == FGBGType.background){
        firebaseProvider.disconnect();
      }
    });
........
}

 

Code Snippet(MessageScreen.dart):

  • lib/pages/dashboard/chat/MessageScreen.dart

Let's display user online status on AppBar


            // replace the commented code and add this
Expanded(
         child: Text(
           messageState?.onlineStatus ?? '',
           style: TextStyle(
           color: Colors.grey.shade600, fontSize: 13),),
           ),

            // Add below code after this line of code messageNotifier?.initializeMessages(myUserId, friendUserId);
messageNotifier?.getUserPresenceStatus(friendUserId);
 

Code Snippet(MessageViewModel.dart):

  • lib/pages/dashboard/chat/MessageViewModel.dart

Create a method to get user presence and last seen


import 'package:firebase_database/firebase_database.dart' as fd;
import 'package:timeago/timeago.dart' as timeago;

            // declare
fd.FirebaseDatabase database = fd.FirebaseDatabase.instance;

            // add below code to update MessageState online status
Future<void> getUserPresenceStatus(String friendId) async {

    print(friendId);
    final myConnectionRef = database.ref()
        .child('presence')
        .child(friendId)
        .child('connections');
    final friendConnectionUser = await myConnectionRef.get();
    if(friendConnectionUser.exists){
      state = state.copyWith(onlineStatus: 'online');
    }else{
      getUserLastSeen(friendId);
    }
    myConnectionRef.onValue.listen((event) {
      if(event.snapshot.exists){
        state = state.copyWith(onlineStatus: 'online');
      }else{
        getUserLastSeen(friendId);
      }
    });
  }

  Future<void> getUserLastSeen(String friendId) async {

    final lastOnlineRef = database.ref()
        .child('presence')
        .child(friendId)
        .child('lastOnline');
    final friendLastOnlineUser = await lastOnlineRef.get();
    if(friendLastOnlineUser.exists){
      print(friendLastOnlineUser.value);
      int map = friendLastOnlineUser.value as int;
        var date = DateTime.fromMillisecondsSinceEpoch(map).toLocal();
        String dateTime = timeago.format(date);
        print(dateTime);
        state =state.copyWith(onlineStatus: dateTime);
    }else{
      state =state.copyWith(onlineStatus: '');
    }

  }

 

Conclusion:

We managed to implement user online status in Real-time and last seen. In the next tutorial, we will show you how to implement typing indicator. Don't forget to share and join ourDiscord Channel. May you please subscribe to our YouTube Channel.