Keep login active on flutter

Asked

Viewed 1,814 times

0

I want when the user logs in, even if the application is still logged in. I am using an own api made in Nodejs. Through my researches I saw that you can do this using the plugin Sharedpreferences. The problem is I can’t implement it in my code.

Just below are the login_bloc.Dart codes and login_screen.Dart

import 'dart:async';
import 'package:bloc_pattern/bloc_pattern.dart';
import 'package:localizamed_app/validators/login_validator.dart';
import 'package:rxdart/rxdart.dart';
import 'package:http/http.dart' as http;
//import 'dart:convert';

//estados do login
enum LoginState {IDLE, CARREGANDO, SUCESSO, FALHA}

class LoginBloc extends BlocBase with LoginValidators{

  //controladores
  final _emailController = BehaviorSubject<String>();
  final _senhaController = BehaviorSubject<String>();
  final _stateController = BehaviorSubject<LoginState>();

  Stream<String> get outEmail => _emailController.stream.transform(validaEmail);
  Stream<String> get outSenha => _senhaController.stream.transform(validaSenha);
  Stream<LoginState> get outState => _stateController.stream;
  Stream<bool> get outSubmitValid => Observable.combineLatest2(
      outEmail, outSenha, (a, b) => true
  );

  Function(String) get changeEmail => _emailController.sink.add;
  Function(String) get changePassword => _senhaController.sink.add;

  //Login com a API
  Future<void> login() async{
    final email = _emailController.value;
    final senha = _senhaController.value;    

    _stateController.add(LoginState.CARREGANDO);

    String url = "http://192.168.0.200:8081/login";
    Map<String, String> headers = {"Accept": "application/json"};    

    try {
      http.Response response = await http.post(url,
        headers: headers,
        body: {          
          "email": email,
          "senha": senha
        });  
        if(response.statusCode == 201){
          _stateController.add(LoginState.SUCESSO);
        } else{
          _stateController.add(LoginState.FALHA);
        }

      } catch (erro){  

        print(_emailController);       
        return _stateController.add(LoginState.FALHA);
    }
  }

  @override
  void dispose() {
    _emailController.close();
    _senhaController.close();
    _stateController.close();
  }  

}

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:localizamed_app/blocs/login_bloc.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:localizamed_app/screens/home_screen.dart';
import 'package:outline_material_icons/outline_material_icons.dart';
//import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
//import 'package:passwordfield/passwordfield.dart';

class LoginScreen extends StatefulWidget {
  @override
  LoginScreenState createState() => LoginScreenState();

  final Stream<String> stream;

  LoginScreen({this.stream});
}

class LoginScreenState extends State<LoginScreen> {
  final _loginBloc = LoginBloc();

  bool invisible;

  @override
  void initState() {
    super.initState();

    //estados de acordo com o que é retornado do Bloc -> API -> Banco
    _loginBloc.outState.listen((state) {
      switch (state) {
        case LoginState.SUCESSO:
          Navigator.of(context).pushReplacement(
              MaterialPageRoute(builder: (context) => HomeScreen()));
          break;
        case LoginState.FALHA:
          showDialog(
              context: context,
              builder: (context) => AlertDialog(
                    title: Text("Erro"),
                    content: Text(
                        "Sinto muito, mas seu E-mail/Senha estão incorretos!"),
                  ));
          break;
        case LoginState.CARREGANDO:
        case LoginState.IDLE:
      }
    });

    invisible = true;
  }

  @override
  void dispose() {
    _loginBloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var mediaQuery = MediaQuery.of(context);
    var size = mediaQuery.size;

    return Scaffold(
        body: StreamBuilder<LoginState>(
            stream: _loginBloc.outState,
            initialData: LoginState.IDLE,
            builder: (context, snapshot) {
              switch (snapshot.data) {
                case LoginState.CARREGANDO:
                  return Center(
                    child: CircularProgressIndicator(
                      valueColor: AlwaysStoppedAnimation(
                          Color.fromARGB(255, 23, 29, 255)),
                    ),
                  );
                case LoginState.FALHA:
                case LoginState.SUCESSO:
                case LoginState.IDLE:
                  return SafeArea(
                    child: Container(
                      width: size.width,
                      height: size.height,
                      child:  SingleChildScrollView(
                          child: Column(
                            children: <Widget>[
                              Padding(
                                padding: EdgeInsets.only(
                                    left: size.width / 3.1,
                                    top: size.height / 60),
                                child: Row(
                                  children: <Widget>[
                                    Text("LocalizaMed",
                                        style: TextStyle(
                                          fontSize: size.width / 20,
                                        )),
                                    Image(
                                      image: AssetImage('images/pin.png'),
                                      width: size.width / 20,
                                      height: size.height / 20,
                                    ),
                                  ],
                                ),
                              ),

                              SizedBox(
                                height: size.height / 15,
                              ),
                              //label de BEM-VINDO
                              Padding(
                                  padding: EdgeInsets.only(
                                      bottom: size.height / 30,
                                      top: size.height / 30,
                                      right: size.width / 2,
                                      left: size.width / 15),
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: <Widget>[
                                      Text(
                                        "Bem",
                                        style: TextStyle(
                                          fontSize: size.width / 8,
                                        ),
                                      ),
                                      Row(
                                        children: <Widget>[
                                          Text(
                                            "Vindo",
                                            style: TextStyle(
                                              fontSize: size.width / 8,
                                            ),
                                          ),
                                          Text(
                                            ".",
                                            style: TextStyle(
                                                fontSize: size.width / 8,
                                                color: Theme.of(context)
                                                    .primaryColor),
                                          ),
                                        ],
                                      )
                                    ],
                                  )),

                              //campo de email
                              Padding(
                                  padding: EdgeInsets.only(
                                      left: size.width / 12,
                                      right: size.width / 20,
                                      top: 0),
                                  child: Column(
                                    children: <Widget>[
                                      StreamBuilder<String>(
                                          stream: _loginBloc.outEmail,
                                          builder: (context, snapshot) {
                                            return TextFormField(
                                              onChanged: _loginBloc.changeEmail,
                                              decoration: InputDecoration(
                                                  errorText: snapshot.hasError
                                                      ? snapshot.error
                                                      : null,
                                                  labelText: "E-mail"),
                                            );
                                          }),
                                      GestureDetector(
                                        child: StreamBuilder<String>(
                                            stream: _loginBloc.outSenha,
                                            builder: (context, snapshot) {
                                              return TextFormField(
                                                onChanged:
                                                    _loginBloc.changePassword,
                                                obscureText: invisible,
                                                decoration: InputDecoration(
                                                    errorText: snapshot.hasError
                                                        ? snapshot.error
                                                        : null,
                                                    labelText: 'Senha',
                                                    suffixIcon: IconButton(
                                                      icon: Icon(
                                                        invisible
                                                            ? Icons
                                                                .visibility_off
                                                            : Icons.visibility,
                                                        size: 20.0,
                                                      ),
                                                      onPressed: () {
                                                        setState(() {
                                                          invisible =
                                                              !invisible;
                                                        });
                                                      },
                                                    )),
                                              );
                                            }),
                                      ),

                                      //botão de ESQUECER A SENHA
                                      Container(
                                        alignment: Alignment.centerRight,
                                        child: FlatButton(
                                          onPressed: () {},
                                          child: Text(
                                            "Esqueceu a senha?",
                                            style: TextStyle(
                                                color: Theme.of(context)
                                                    .primaryColor,
                                                fontSize: size.width / 25),
                                          ),
                                        ),
                                      ),
                                      SizedBox(
                                        height: size.height / 50,
                                      ),
                                      //botão de LOGIN
                                      StreamBuilder<bool>(
                                          stream: _loginBloc.outSubmitValid,
                                          builder: (context, snapshot) {
                                            return RaisedButton(
                                                padding: EdgeInsets.symmetric(
                                                    vertical: size.height / 55,
                                                    horizontal:
                                                        size.width / 3.29),
                                                color: Color.fromARGB(
                                                    255, 23, 29, 255),
                                                shape: RoundedRectangleBorder(
                                                    borderRadius:
                                                        BorderRadius.circular(
                                                            23)),
                                                onPressed: snapshot.hasData
                                                    ? _loginBloc.login
                                                    : null,
                                                disabledColor: Colors.blue[300],
                                                child: Text("Login",
                                                    textAlign: TextAlign.center,
                                                    style: TextStyle(
                                                        color: Colors.white,
                                                        fontSize:
                                                            size.width / 25,
                                                        fontWeight:
                                                            FontWeight.bold)));
                                          }),

                                      SizedBox(
                                        height: size.height / 50,
                                      ),
                                      //botão de LOGAR PELO FACEBOOK
                                      Container(
                                        width: size.width / 1.4,
                                        child: RaisedButton(
                                          padding: EdgeInsets.symmetric(
                                              vertical: size.height / 55,
                                              horizontal: size.width / 8.4),
                                          color: Colors.white,
                                          shape: RoundedRectangleBorder(
                                              borderRadius:
                                                  BorderRadius.circular(23),
                                              side: BorderSide(
                                                  color: Colors.black,
                                                  width: 2)),
                                          onPressed: () {},
                                          child: Row(
                                            children: <Widget>[
                                              Image(
                                                image: AssetImage(
                                                    'images/facebook_logo1.png'),
                                                width: 15,
                                                height: 15,
                                              ),
                                              Text(
                                                "Logar pelo Facebook",
                                                textAlign: TextAlign.center,
                                                style: TextStyle(
                                                    color: Colors.black,
                                                    fontSize: size.width / 28,
                                                    fontWeight:
                                                        FontWeight.bold),
                                              ),
                                            ],
                                          ),
                                        ),
                                      ),

                                      SizedBox(
                                        height: size.height / 20,
                                      ),
                                      //Botão de se CADASTRAR
                                      Container(
                                        child: Center(
                                          child: Row(
                                            mainAxisAlignment:
                                                MainAxisAlignment.center,
                                            children: <Widget>[
                                              Text(
                                                "Não tem uma conta?",
                                                style: TextStyle(
                                                    fontSize: size.width / 25),
                                              ),
                                              SizedBox(
                                                width: 1,
                                              ),
                                              FlatButton(
                                                padding: EdgeInsets.all(0),
                                                onPressed: () {},
                                                child: Text("Cadastre-se",
                                                    style: TextStyle(
                                                        color: Theme.of(context)
                                                            .primaryColor,
                                                        fontSize:
                                                            size.width / 25)),
                                              )
                                            ],
                                          ),
                                        ),
                                      ),
                                    ],
                                  )),
                            ],
                          ),
                        ),
                    )
                  );
              }
            }));
  }
}

Can someone help me? Thanks in advance ^^

1 answer

0


Sharedpreferences is one of the ways to do it, I’m using it also in my project.
I’ll explain using the model I’m using.

Create a class just to keep things in place LocalSettings

import 'package:shared_preferences/shared_preferences.dart';

class LocalSettings{
  SharedPreferences preferences;

  Future<void> getInstance() async {
    preferences = await SharedPreferences.getInstance();
  }
}

To use do as follows:

class BlocThemes extends BlocBase {
  LocalSettings settings = LocalSettings();

  BlocThemes(){
    getInitialValues();
    _themeController.stream.listen((data){
      settings.preferences.setInt('theme', data.index);
    });
  }

  void getInitialValues() async{
    await settings.getInstance();
    if (settings.preferences.containsKey('theme'))
      inTheme.add(ApplicationTheme.values[settings.preferences.getInt('theme')]);
    else
      inTheme.add(ApplicationTheme.lightTheme);
  }

  @override
  void dispose() {
    _themeController.close();
    super.dispose();
  }

  final BehaviorSubject<ApplicationTheme> _themeController = BehaviorSubject<ApplicationTheme>();
  Stream<ApplicationTheme> get outTheme => _themeController.stream;
  Sink<ApplicationTheme> get inTheme => _themeController.sink;

Explanation

To save values

await SharedPreferences.getInstance().preferences.setInt('theme', data.index);

To pick up values

await SharedPreferences.getInstance().preferences.setInt('theme', data.index);

Application in your case

At the moment the validation is done to know if the user will be redirected to the LOGIN screen or to the HOME you test as follows:

if (settings.preferences.containsKey('conectado'))
  if (settings.preferences.getBool('conectado'))
    HOME
  else
    HOME

Note: Of course you should do a more complete validation, this is just an example of use.

In case I wanted to see more about, take a look at my Github project Equipmentmaintenance

Browser other questions tagged

You are not signed in. Login or sign up in order to post.