287 lines
13 KiB
Dart
287 lines
13 KiB
Dart
// ignore_for_file: use_build_context_synchronously
|
|
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hoshan/core/routes/route_generator.dart';
|
|
import 'package:hoshan/core/utils/date_time.dart';
|
|
import 'package:hoshan/data/model/auth/auth_screens_enum.dart';
|
|
import 'package:hoshan/ui/screens/auth/cubit/auth_screens_cubit.dart';
|
|
import 'package:hoshan/ui/screens/auth/register/bloc/register_bloc.dart';
|
|
import 'package:hoshan/ui/screens/auth/verification/bloc/verification_bloc.dart';
|
|
import 'package:hoshan/ui/screens/auth/verification/sms_retriever_impl.dart';
|
|
import 'package:hoshan/ui/screens/splash/cubit/user_info_cubit.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/button/loading_button.dart';
|
|
import 'package:pinput/pinput.dart';
|
|
import 'package:smart_auth/smart_auth.dart';
|
|
import 'package:string_validator/string_validator.dart';
|
|
|
|
ValueNotifier<int> seconds = ValueNotifier(120);
|
|
|
|
class VerificationScreen extends StatefulWidget {
|
|
const VerificationScreen({super.key});
|
|
|
|
@override
|
|
State<VerificationScreen> createState() => _VerificationScreenState();
|
|
}
|
|
|
|
class _VerificationScreenState extends State<VerificationScreen> {
|
|
ValueNotifier<bool> error = ValueNotifier(false);
|
|
ValueNotifier<bool> readOnly = ValueNotifier(false);
|
|
Timer? _timer;
|
|
late final defaultPinTheme = PinTheme(
|
|
textStyle: AppTextStyles.headline5
|
|
.copyWith(color: Theme.of(context).colorScheme.primary),
|
|
width: 56,
|
|
height: 56,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(color: AppColors.gray.defaultShade)));
|
|
|
|
final errorPinTheme = PinTheme(
|
|
textStyle:
|
|
AppTextStyles.headline5.copyWith(color: AppColors.red.defaultShade),
|
|
width: 56,
|
|
height: 56,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(16),
|
|
border: Border.all(color: AppColors.red.defaultShade)));
|
|
|
|
void startTimer() {
|
|
_timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
|
|
seconds.value = seconds.value - 1;
|
|
if (seconds.value == 0) {
|
|
timer.cancel();
|
|
error.value = true;
|
|
readOnly.value = true;
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
startTimer();
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
super.dispose();
|
|
|
|
_timer?.cancel();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocConsumer<VerificationBloc, VerificationState>(
|
|
listener: (context, state) async {
|
|
if (state is VerificationLoading) {
|
|
readOnly.value = true;
|
|
} else {
|
|
readOnly.value = false;
|
|
}
|
|
if (state is VerificationFail) {
|
|
error.value = true;
|
|
} else if (state is VerificationSuccess) {
|
|
if (state.isNew) {
|
|
context.read<AuthScreensCubit>().changeState(AuthScreens.code);
|
|
} else {
|
|
await context.read<UserInfoCubit>().getUserInfo();
|
|
context.go(Routes.giftCredit);
|
|
}
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
return ValueListenableBuilder(
|
|
valueListenable: readOnly,
|
|
builder: (context, readOnlyVal, _) {
|
|
return Column(
|
|
children: [
|
|
Text(
|
|
'کد تایید شش رقمی به ${context.read<AuthScreensCubit>().username.isEmail ? 'ایمیل شما' : 'شماره شما'} ارسال شد.',
|
|
textDirection: TextDirection.rtl,
|
|
style: AppTextStyles.body5.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
color: Theme.of(context).colorScheme.onSurface),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () => context
|
|
.read<AuthScreensCubit>()
|
|
.changeState(AuthScreens.mobile),
|
|
child: Text(
|
|
'تغییر ${context.read<AuthScreensCubit>().username.isEmail ? 'ایمیل' : 'شماره همراه'} ',
|
|
style: AppTextStyles.body5.copyWith(
|
|
color: Theme.of(context).colorScheme.primary),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Icon(
|
|
Icons.edit,
|
|
size: 16,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
)
|
|
],
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 24.0, horizontal: 16),
|
|
child: ValueListenableBuilder(
|
|
valueListenable: error,
|
|
builder: (context, errVal, _) {
|
|
return Column(
|
|
children: [
|
|
Pinput(
|
|
smsRetriever: !kIsWeb && !Platform.isIOS
|
|
? SmsRetrieverImpl(SmartAuth.instance)
|
|
: null,
|
|
readOnly: readOnlyVal,
|
|
forceErrorState: errVal,
|
|
defaultPinTheme: defaultPinTheme,
|
|
focusedPinTheme:
|
|
defaultPinTheme.copyBorderWith(
|
|
border: Border.all(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary)),
|
|
submittedPinTheme:
|
|
defaultPinTheme.copyBorderWith(
|
|
border: Border.all(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary)),
|
|
errorPinTheme: errorPinTheme,
|
|
keyboardType: TextInputType.number,
|
|
length: 6,
|
|
autofocus: true,
|
|
closeKeyboardWhenCompleted: true,
|
|
onChanged: (value) {
|
|
error.value = false;
|
|
},
|
|
onCompleted: (String value) {
|
|
final number = context
|
|
.read<AuthScreensCubit>()
|
|
.username;
|
|
final isNew =
|
|
context.read<AuthScreensCubit>().isNew;
|
|
context.read<VerificationBloc>().add(
|
|
LoginWithOTP(
|
|
number: number,
|
|
otp: value,
|
|
isNew: isNew));
|
|
},
|
|
),
|
|
const SizedBox(
|
|
height: 12,
|
|
),
|
|
if (errVal)
|
|
Text(
|
|
seconds.value == 0
|
|
? 'دوباره تلاش کنید'
|
|
: context.read<VerificationBloc>().state
|
|
is VerificationFail &&
|
|
(state as VerificationFail)
|
|
.errorServer
|
|
? "خطا از طرف سرور"
|
|
: '!کد وارد شده اشتباه است',
|
|
style: errorPinTheme.textStyle,
|
|
),
|
|
const SizedBox(
|
|
height: 12,
|
|
),
|
|
if (state is VerificationLoading ||
|
|
state is VerificationSuccess)
|
|
SpinKitThreeBounce(
|
|
color:
|
|
Theme.of(context).colorScheme.primary,
|
|
size: 32,
|
|
)
|
|
],
|
|
);
|
|
})),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 18.0, horizontal: 16),
|
|
child: readOnlyVal && state is! VerificationLoading
|
|
? BlocConsumer<RegisterBloc, RegisterState>(
|
|
listener: (context, state) {
|
|
if (state is RegisterSuccess) {
|
|
readOnly.value = false;
|
|
error.value = false;
|
|
seconds.value = 120;
|
|
startTimer();
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
return LoadingButton(
|
|
width: MediaQuery.sizeOf(context).width,
|
|
height: 48,
|
|
radius: 100,
|
|
loading: state is RegisterLoading,
|
|
onPressed: () async {
|
|
context.read<RegisterBloc>().add(LoginUser(
|
|
phoneNumber: context
|
|
.read<AuthScreensCubit>()
|
|
.username));
|
|
},
|
|
child: Text(
|
|
'ارسال مجدد کد',
|
|
style: AppTextStyles.body4
|
|
.copyWith(color: Colors.white),
|
|
));
|
|
},
|
|
)
|
|
: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
'تا دریافت مجدد کد',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color:
|
|
Theme.of(context).colorScheme.primary),
|
|
),
|
|
ValueListenableBuilder(
|
|
valueListenable: seconds,
|
|
builder: (context, secVal, _) {
|
|
return Text(
|
|
' ${DateTimeUtils.getTimeFromDuration(secVal)}',
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary));
|
|
}),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Icon(
|
|
CupertinoIcons.clock,
|
|
size: 16,
|
|
color: Theme.of(context).colorScheme.primary,
|
|
)
|
|
],
|
|
),
|
|
)
|
|
],
|
|
);
|
|
});
|
|
},
|
|
);
|
|
}
|
|
}
|