Flutter_Pinput icon indicating copy to clipboard operation
Flutter_Pinput copied to clipboard

PinnPut androidSmsAutofillMethod is not working on showModalBottomSheet

Open suryamin opened this issue 1 year ago • 9 comments

I was wondering if it would be possible for Pinput to receive sms code on showModalBottomSheet? These codes were working fine on StatefullWidget page but not in showModalBottomSheet. Any help would be appreciated.

Thank you in advance.

Best Regards, SM

an additional info:

Flutter 3.0.5 • channel stable Framework • revision f1875d570e Engine • revision e85ea0e79c Tools • Dart 2.17.6 • DevTools 2.12.2 use: bloc, rxdart pinput: ^2.2.12

my code as follow:

import 'package:flutter/material.dart';
import 'package:pinput/pinput.dart';
import '../../app.dart';
import '../styles/base_style.dart';
import '../styles/button_style.dart';
import '../styles/color_style.dart';
import '../widgets/actionSheetAppBar_widget.dart';
import '../widgets/swipeButton_widget.dart';

Future<bool> otpModalSheet(
    BuildContext context, String phoneNumber, FocusNode focusNode) async {
  final Size _size = MediaQuery.of(context).size;
  final defaultPinTheme = PinTheme(
    width: ButtonStyles.buttonWidth,
    height: ButtonStyles.buttonHeight,
    textStyle: TextStyle(
      fontFamily: 'Poppins',
      color: Colors.white,
      fontWeight: FontWeight.w400,
      fontSize: 20.0,
    ),
    decoration: BoxDecoration(
      color: AppColors.defaultPinTheme,
      borderRadius: BorderRadius.circular(ButtonStyles.buttonHeight),
    ),
  );
  final focusedPinTheme = defaultPinTheme.copyDecorationWith(
    color: AppColors.focusedPinTheme,
  );
  final submittedPinTheme = defaultPinTheme.copyWith(
    decoration: defaultPinTheme.decoration!.copyWith(
      color: AppColors.submittedPinTheme,
    ),
  );
  final errorPinTheme = defaultPinTheme.copyWith(
    decoration: BoxDecoration(
      color: AppColors.errorPinTheme,
    ),
  );

  return await showModalBottomSheet(
    enableDrag: false,
    shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
    backgroundColor: AppColors.actionSheetPrefixIcon,
    context: context,
    isScrollControlled: true,
    builder: (BuildContext context) => SingleChildScrollView(
      padding: MediaQuery.of(context).viewInsets,
      child: Column(
        children: <Widget>[
          SizedBox(height: _size.height * 0.01),
          ActionSheetAppBar(
            title: 'One Time Password',
            onTap: () => Navigator.of(context).pop(false),
          ),
          SizedBox(height: _size.height * 0.01),
          Padding(
            padding: BaseStyles.listPadding,
            child: StreamBuilder<String?>(
              stream: otpBloc.returnOtp,
              initialData: "",
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                return Pinput(
                  length: 6,
                  keyboardType: TextInputType.number,
                  defaultPinTheme: defaultPinTheme,
                  focusedPinTheme: focusedPinTheme,
                  submittedPinTheme: submittedPinTheme,
                  errorPinTheme: errorPinTheme,
                  separator: Container(
                    height: 60,
                    width: 3,
                    color: Colors.white,
                  ),
                  focusNode: focusNode,
                  autofocus: true,
                  pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
                  showCursor: true,
                  pinAnimationType: PinAnimationType.fade,
                  animationDuration: Duration(milliseconds: 300),
                  androidSmsAutofillMethod:
                      AndroidSmsAutofillMethod.smsRetrieverApi,
                  onChanged: otpBloc.returnOtpChange,
                );
              },
            ),
          ),
          StreamBuilder<bool>(
            stream: otpBloc.isValid,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              final bool _isValid = (!snapshot.hasData) ? false : snapshot.data;
              return AppSwipeButton(
                hasData: _isValid,
                buttonText: 'Verify',
                onPressed: () async {
                  //---do something---//
                  Navigator.of(context).pop(true);
                },
              );
            },
          ),
          SizedBox(height: _size.height * 0.02),
        ],
      ),
    ),
  );
}

image

suryamin avatar Aug 11 '22 06:08 suryamin

Check if this code works for you?

Future<bool> otpModalSheet(BuildContext context) async {
  final Size _size = MediaQuery.of(context).size;
  final defaultPinTheme = PinTheme(
    width: 40,
    height: 40,
    textStyle: TextStyle(
      fontFamily: 'Poppins',
      color: Colors.white,
      fontWeight: FontWeight.w400,
      fontSize: 20.0,
    ),
    decoration: BoxDecoration(
      color: Colors.red,
      borderRadius: BorderRadius.circular(20),
    ),
  );
  final focusedPinTheme = defaultPinTheme.copyDecorationWith(
    color: Colors.red,
  );
  final submittedPinTheme = defaultPinTheme.copyWith(
    decoration: defaultPinTheme.decoration!.copyWith(
      color: Colors.red,
    ),
  );
  final errorPinTheme = defaultPinTheme.copyWith(
    decoration: BoxDecoration(
      color: Colors.red,
    ),
  );

  return await showModalBottomSheet(
    enableDrag: false,
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
    backgroundColor: Colors.white,
    context: context,
    isScrollControlled: true,
    builder: (BuildContext context) => SingleChildScrollView(
      padding: MediaQuery.of(context).viewInsets,
      child: Column(
        children: <Widget>[
          SizedBox(height: _size.height * 0.01),
          SizedBox(height: _size.height * 0.01),
          Pinput(
            length: 6,
            keyboardType: TextInputType.number,
            defaultPinTheme: defaultPinTheme,
            focusedPinTheme: focusedPinTheme,
            submittedPinTheme: submittedPinTheme,
            errorPinTheme: errorPinTheme,
            separator: Container(height: 60, width: 3, color: Colors.white),
            autofocus: true,
            pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
            showCursor: true,
            pinAnimationType: PinAnimationType.fade,
            animationDuration: Duration(milliseconds: 300),
            androidSmsAutofillMethod: AndroidSmsAutofillMethod.smsRetrieverApi,
          ),
          SizedBox(height: _size.height * 0.02),
        ],
      ),
    ),
  );
}

Tkko avatar Aug 11 '22 06:08 Tkko

Hi Tkko,

Thank you for your quick response. I've took out focusNode and onChanged followed yours. And it doesn't work.

Performing hot reload... Reloaded 0 libraries in 646ms. W/System (10675): Ignoring header X-Firebase-Locale because its value was null. I/flutter (10675): [OTP] Please Enter the code sent to your mobile I/flutter (10675): ...smsCode:926902 I/flutter (10675): Pinput: App Signature for SMS Retriever API Is: LsSqYw/SMKs

Thank you.

suryamin avatar Aug 11 '22 07:08 suryamin

How your SMS looks like?

Tkko avatar Aug 11 '22 08:08 Tkko

sms code come with 6 digits, produced by verifyPhoneNumber (firebase auth).

...smsCode:926902 -> print to screen for debug

suryamin avatar Aug 11 '22 08:08 suryamin

I used android phone for testing

suryamin avatar Aug 11 '22 08:08 suryamin

If you are using firebase_auth you don't need to use smsRetrieverApi because firebase_auth support automatic SMS code resolution. you have just to obtain OTP from firebase and set it via TextEditingController

BTW - All of this are documented in the readme

Tkko avatar Aug 11 '22 08:08 Tkko

Thanks, I am not successfully implemented sms retrieval from verifyPhoneNumber. I'll go back to firebase_auth verifyPhoneNumber, see what I can get. If you have a handy example for sms code with firebase_auth, It will be very helpful. Thank you Tkko for you very quick response, much appreciated.

Cheers

suryamin avatar Aug 11 '22 08:08 suryamin

Try something like this:

final pinController = TextEditingController();
Widget _pinput (){
  return Pinput(controller: pinController);
}

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) async {
     pinController.setText(credential.smsCode); 
  },
);

Tkko avatar Aug 11 '22 08:08 Tkko

Thank Tkko, I'll update you later for the result.

Cheers,

suryamin avatar Aug 11 '22 08:08 suryamin

Hi Tkko,

I've finally got it right by changing the logic, smsCode as a returned code and passing it to the controller.text Before I used smsCode as a generated code and user key-in as a returned code then compared it. If it was equal then sign in or link.

Thank you for the clue.

Cheers,

suryamin avatar Aug 26 '22 00:08 suryamin