forked from eatvio/eatvio_app
feat: webview registration
This commit is contained in:
@@ -13,7 +13,7 @@ if (keystorePropertiesFile.exists()) {
|
||||
android {
|
||||
namespace = "com.eatvioapp.app"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = "27.0.12077973"
|
||||
ndkVersion = "25.1.8937393"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:eatvio_app/core/initialization_cubit/ws_manager.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/auth_screen/auth_screen.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/pages/auth_screen.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/pages/blog_post_screen.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/presentation/pages/blog_post_create_screen.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart';
|
||||
@@ -34,6 +34,7 @@ import 'package:eatvio_app/features/profile/presentation/pages/subs_screen.dart'
|
||||
import 'package:eatvio_app/features/recipes/presentation/pages/about_recipes_screen.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/features/registration/presentation/pages/registration_screen.dart';
|
||||
import 'package:eatvio_app/features/registration/presentation/pages/webview_registration_screen.dart';
|
||||
import 'package:eatvio_app/features/settings/entities/settings_entity.dart';
|
||||
import 'package:eatvio_app/features/settings/presentation/pages/change_email_screen.dart';
|
||||
import 'package:eatvio_app/features/settings/presentation/pages/change_password_screen.dart';
|
||||
@@ -64,18 +65,13 @@ class AppRouter {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
builder: (context, state) {
|
||||
final bool needLogout;
|
||||
if (state.extra == null) {
|
||||
needLogout = false;
|
||||
} else {
|
||||
needLogout = true;
|
||||
}
|
||||
return AuthScreen(
|
||||
needLogout: needLogout,
|
||||
);
|
||||
},
|
||||
builder: (context, state) => const AuthScreen(),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'webView-registration-screen',
|
||||
name: 'webViewRegistrationScreen',
|
||||
builder: (context, state) => const WebViewRegistrationScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: 'registration-screen',
|
||||
name: 'registrationScreen',
|
||||
|
||||
@@ -2,6 +2,9 @@ import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/initialization_cubit/ws_manager.dart';
|
||||
import 'package:eatvio_app/core/initialization_cubit/ws_service.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit.dart';
|
||||
import 'package:eatvio_app/features/auth/repositories/auth_repository.dart';
|
||||
import 'package:eatvio_app/features/auth/services/auth_service.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
|
||||
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
|
||||
@@ -104,6 +107,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<MyPlansCubit>(() => MyPlansCubit(myPlansRepository: sl()));
|
||||
sl.registerFactory<UserDetailsCubit>(() => UserDetailsCubit(profileRepository: sl()));
|
||||
sl.registerFactory<ConsultantsCubit>(() => ConsultantsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<AuthCubit>(() => AuthCubit(authRepository: sl()));
|
||||
|
||||
// Repository
|
||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||
@@ -123,6 +127,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<PlanRepository>(() => PlanRepository(planService: sl()));
|
||||
sl.registerLazySingleton<MyDietsRepository>(() => MyDietsRepository(myDietsService: sl()));
|
||||
sl.registerLazySingleton<MyPlansRepository>(() => MyPlansRepository(myPlansService: sl()));
|
||||
sl.registerLazySingleton<AuthRepository>(() => AuthRepository(authService: sl()));
|
||||
|
||||
// Services
|
||||
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
||||
@@ -143,6 +148,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<MyDietsService>(() => MyDietsService(sl()));
|
||||
sl.registerLazySingleton<MyPlansService>(() => MyPlansService(sl()));
|
||||
sl.registerLazySingleton<WsService>(() => WsService(sl()));
|
||||
sl.registerLazySingleton<AuthService>(() => AuthService(sl()));
|
||||
|
||||
// External
|
||||
sl.registerLazySingleton(
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/credentials_storage.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/const/strings.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class AuthScreen extends StatefulWidget {
|
||||
final bool needLogout;
|
||||
|
||||
const AuthScreen({
|
||||
this.needLogout = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AuthScreen> createState() => _AuthScreenState();
|
||||
}
|
||||
|
||||
class _AuthScreenState extends State<AuthScreen> {
|
||||
bool checkboxState = false;
|
||||
bool hidePassword = true;
|
||||
final baseUrlController = TextEditingController();
|
||||
late final WebViewController _controller;
|
||||
|
||||
String email = '';
|
||||
String password = '';
|
||||
bool needLogout = false;
|
||||
|
||||
Future<void> logoutFromWeb() async {
|
||||
await CredentialsStorage.removeCredentials();
|
||||
await _controller.runJavaScript('''
|
||||
document.querySelector('.header-list__link button[type="submit"]').click();
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> loginInApplication() async {
|
||||
final credentialsFromStorage = await CredentialsStorage.getCredentialsFromStorage();
|
||||
final Map<String, String> credentials = {
|
||||
'email': credentialsFromStorage['email']!,
|
||||
'password': credentialsFromStorage['password']!,
|
||||
};
|
||||
final response = await http.post(
|
||||
Uri.parse(baseUrl + '/api/login'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode(credentials),
|
||||
encoding: utf8,
|
||||
);
|
||||
var res = await jsonDecode(response.body);
|
||||
final token = res['token'];
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
await Future.delayed(Duration.zero, () => GoRouter.of(context).go('/my-profile-screen'));
|
||||
await sl<ProfileAvatarCubit>().getMyProfile();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
needLogout = widget.needLogout;
|
||||
|
||||
_controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..addJavaScriptChannel(
|
||||
'FlutterChannel',
|
||||
onMessageReceived: (JavaScriptMessage message) {
|
||||
final data = jsonDecode(message.message);
|
||||
email = data['email'];
|
||||
password = data['password'];
|
||||
},
|
||||
)
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onPageFinished: (String url) async {
|
||||
final bool tokenInStorage = await TokenStorage.haveTokenInStorage();
|
||||
final bool credentialsInStorage = await CredentialsStorage.haveCredentialsInStorage();
|
||||
|
||||
if (needLogout) {
|
||||
await logoutFromWeb();
|
||||
needLogout = false;
|
||||
} else if (!url.contains('profile') && !url.contains('registration')) {
|
||||
await _controller.runJavaScript(jsChannelAuthScript);
|
||||
} else if (url.contains('profile')) {
|
||||
if (credentialsInStorage) {
|
||||
await loginInApplication();
|
||||
} else {
|
||||
if (email.isNotEmpty && password.isNotEmpty) {
|
||||
await CredentialsStorage.saveCredentials(email, password);
|
||||
await loginInApplication();
|
||||
} else {
|
||||
await logoutFromWeb();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tokenInStorage && credentialsInStorage) {
|
||||
GoRouter.of(context).go('/my-profile-screen');
|
||||
} else if (!tokenInStorage && credentialsInStorage) {
|
||||
await loginInApplication();
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
..loadRequest(Uri.parse(baseUrl));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
FlutterNativeSplash.remove();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: WebViewWidget(controller: _controller),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
const String jsChannelAuthScript = '''
|
||||
function initializeListeners() {
|
||||
const emailInput = document.getElementById("inputEmail_main");
|
||||
const passwordInput = document.getElementById("inputPassword_main");
|
||||
if (emailInput && passwordInput) {
|
||||
function sendToFlutter() {
|
||||
const email = emailInput.value;
|
||||
const password = passwordInput.value;
|
||||
const data = JSON.stringify({ email: email, password: password });
|
||||
if (window.FlutterChannel) {
|
||||
window.FlutterChannel.postMessage(data);
|
||||
}
|
||||
}
|
||||
emailInput.addEventListener("input", sendToFlutter);
|
||||
passwordInput.addEventListener("input", sendToFlutter);
|
||||
} else {
|
||||
console.error("Email or Password input not found.");
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", initializeListeners);
|
||||
initializeListeners();
|
||||
''';
|
||||
15
lib/features/auth/models/credentials_model.dart
Normal file
15
lib/features/auth/models/credentials_model.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'credentials_model.freezed.dart';
|
||||
|
||||
part 'credentials_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class CredentialsModel with _$CredentialsModel {
|
||||
const factory CredentialsModel({
|
||||
required String email,
|
||||
required String password,
|
||||
}) = _CredentialsModel;
|
||||
|
||||
factory CredentialsModel.fromJson(Map<String, Object?> json) => _$CredentialsModelFromJson(json);
|
||||
}
|
||||
184
lib/features/auth/models/credentials_model.freezed.dart
Normal file
184
lib/features/auth/models/credentials_model.freezed.dart
Normal file
@@ -0,0 +1,184 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'credentials_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
CredentialsModel _$CredentialsModelFromJson(Map<String, dynamic> json) {
|
||||
return _CredentialsModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$CredentialsModel {
|
||||
String get email => throw _privateConstructorUsedError;
|
||||
String get password => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this CredentialsModel to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of CredentialsModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$CredentialsModelCopyWith<CredentialsModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $CredentialsModelCopyWith<$Res> {
|
||||
factory $CredentialsModelCopyWith(
|
||||
CredentialsModel value, $Res Function(CredentialsModel) then) =
|
||||
_$CredentialsModelCopyWithImpl<$Res, CredentialsModel>;
|
||||
@useResult
|
||||
$Res call({String email, String password});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$CredentialsModelCopyWithImpl<$Res, $Val extends CredentialsModel>
|
||||
implements $CredentialsModelCopyWith<$Res> {
|
||||
_$CredentialsModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of CredentialsModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? email = null,
|
||||
Object? password = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
email: null == email
|
||||
? _value.email
|
||||
: email // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
password: null == password
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$CredentialsModelImplCopyWith<$Res>
|
||||
implements $CredentialsModelCopyWith<$Res> {
|
||||
factory _$$CredentialsModelImplCopyWith(_$CredentialsModelImpl value,
|
||||
$Res Function(_$CredentialsModelImpl) then) =
|
||||
__$$CredentialsModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String email, String password});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$CredentialsModelImplCopyWithImpl<$Res>
|
||||
extends _$CredentialsModelCopyWithImpl<$Res, _$CredentialsModelImpl>
|
||||
implements _$$CredentialsModelImplCopyWith<$Res> {
|
||||
__$$CredentialsModelImplCopyWithImpl(_$CredentialsModelImpl _value,
|
||||
$Res Function(_$CredentialsModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of CredentialsModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? email = null,
|
||||
Object? password = null,
|
||||
}) {
|
||||
return _then(_$CredentialsModelImpl(
|
||||
email: null == email
|
||||
? _value.email
|
||||
: email // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
password: null == password
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$CredentialsModelImpl implements _CredentialsModel {
|
||||
const _$CredentialsModelImpl({required this.email, required this.password});
|
||||
|
||||
factory _$CredentialsModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$CredentialsModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String email;
|
||||
@override
|
||||
final String password;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CredentialsModel(email: $email, password: $password)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$CredentialsModelImpl &&
|
||||
(identical(other.email, email) || other.email == email) &&
|
||||
(identical(other.password, password) ||
|
||||
other.password == password));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, email, password);
|
||||
|
||||
/// Create a copy of CredentialsModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$CredentialsModelImplCopyWith<_$CredentialsModelImpl> get copyWith =>
|
||||
__$$CredentialsModelImplCopyWithImpl<_$CredentialsModelImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$CredentialsModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _CredentialsModel implements CredentialsModel {
|
||||
const factory _CredentialsModel(
|
||||
{required final String email,
|
||||
required final String password}) = _$CredentialsModelImpl;
|
||||
|
||||
factory _CredentialsModel.fromJson(Map<String, dynamic> json) =
|
||||
_$CredentialsModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get email;
|
||||
@override
|
||||
String get password;
|
||||
|
||||
/// Create a copy of CredentialsModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$CredentialsModelImplCopyWith<_$CredentialsModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
21
lib/features/auth/models/credentials_model.g.dart
Normal file
21
lib/features/auth/models/credentials_model.g.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'credentials_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$CredentialsModelImpl _$$CredentialsModelImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$CredentialsModelImpl(
|
||||
email: json['email'] as String,
|
||||
password: json['password'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$CredentialsModelImplToJson(
|
||||
_$CredentialsModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'email': instance.email,
|
||||
'password': instance.password,
|
||||
};
|
||||
14
lib/features/auth/models/token_model.dart
Normal file
14
lib/features/auth/models/token_model.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'token_model.freezed.dart';
|
||||
|
||||
part 'token_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class TokenModel with _$TokenModel {
|
||||
const factory TokenModel({
|
||||
required String token,
|
||||
}) = _TokenModel;
|
||||
|
||||
factory TokenModel.fromJson(Map<String, Object?> json) => _$TokenModelFromJson(json);
|
||||
}
|
||||
164
lib/features/auth/models/token_model.freezed.dart
Normal file
164
lib/features/auth/models/token_model.freezed.dart
Normal file
@@ -0,0 +1,164 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'token_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
TokenModel _$TokenModelFromJson(Map<String, dynamic> json) {
|
||||
return _TokenModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TokenModel {
|
||||
String get token => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this TokenModel to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of TokenModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$TokenModelCopyWith<TokenModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $TokenModelCopyWith<$Res> {
|
||||
factory $TokenModelCopyWith(
|
||||
TokenModel value, $Res Function(TokenModel) then) =
|
||||
_$TokenModelCopyWithImpl<$Res, TokenModel>;
|
||||
@useResult
|
||||
$Res call({String token});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$TokenModelCopyWithImpl<$Res, $Val extends TokenModel>
|
||||
implements $TokenModelCopyWith<$Res> {
|
||||
_$TokenModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of TokenModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? token = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
token: null == token
|
||||
? _value.token
|
||||
: token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$TokenModelImplCopyWith<$Res>
|
||||
implements $TokenModelCopyWith<$Res> {
|
||||
factory _$$TokenModelImplCopyWith(
|
||||
_$TokenModelImpl value, $Res Function(_$TokenModelImpl) then) =
|
||||
__$$TokenModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String token});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$TokenModelImplCopyWithImpl<$Res>
|
||||
extends _$TokenModelCopyWithImpl<$Res, _$TokenModelImpl>
|
||||
implements _$$TokenModelImplCopyWith<$Res> {
|
||||
__$$TokenModelImplCopyWithImpl(
|
||||
_$TokenModelImpl _value, $Res Function(_$TokenModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of TokenModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? token = null,
|
||||
}) {
|
||||
return _then(_$TokenModelImpl(
|
||||
token: null == token
|
||||
? _value.token
|
||||
: token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$TokenModelImpl implements _TokenModel {
|
||||
const _$TokenModelImpl({required this.token});
|
||||
|
||||
factory _$TokenModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$TokenModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String token;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TokenModel(token: $token)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$TokenModelImpl &&
|
||||
(identical(other.token, token) || other.token == token));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, token);
|
||||
|
||||
/// Create a copy of TokenModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$TokenModelImplCopyWith<_$TokenModelImpl> get copyWith =>
|
||||
__$$TokenModelImplCopyWithImpl<_$TokenModelImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$TokenModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _TokenModel implements TokenModel {
|
||||
const factory _TokenModel({required final String token}) = _$TokenModelImpl;
|
||||
|
||||
factory _TokenModel.fromJson(Map<String, dynamic> json) =
|
||||
_$TokenModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get token;
|
||||
|
||||
/// Create a copy of TokenModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$TokenModelImplCopyWith<_$TokenModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
17
lib/features/auth/models/token_model.g.dart
Normal file
17
lib/features/auth/models/token_model.g.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'token_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$TokenModelImpl _$$TokenModelImplFromJson(Map<String, dynamic> json) =>
|
||||
_$TokenModelImpl(
|
||||
token: json['token'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$TokenModelImplToJson(_$TokenModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'token': instance.token,
|
||||
};
|
||||
37
lib/features/auth/presentation/bloc/auth_cubit.dart
Normal file
37
lib/features/auth/presentation/bloc/auth_cubit.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
import 'package:eatvio_app/core/app_router.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_state.dart';
|
||||
import 'package:eatvio_app/features/auth/repositories/auth_repository.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class AuthCubit extends Cubit<AuthState> {
|
||||
final AuthRepository authRepository;
|
||||
|
||||
AuthCubit({
|
||||
required this.authRepository,
|
||||
}) : super(AuthState());
|
||||
|
||||
getTokenByCredentials(String email, String password) async {
|
||||
emit(AuthState.loading());
|
||||
try {
|
||||
final String token = (await authRepository.getTokenByCredentials(
|
||||
email,
|
||||
password,
|
||||
))
|
||||
.token;
|
||||
emit(
|
||||
AuthState.loaded(
|
||||
token: token,
|
||||
),
|
||||
);
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
await sl<ProfileAvatarCubit>().getMyProfile();
|
||||
AppRouter.navigatorKey.currentContext?.go('/my-profile-screen');
|
||||
} catch (e) {
|
||||
emit(AuthState.error(errorMessage: '$e'));
|
||||
}
|
||||
}
|
||||
}
|
||||
18
lib/features/auth/presentation/bloc/auth_state.dart
Normal file
18
lib/features/auth/presentation/bloc/auth_state.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'auth_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class AuthState with _$AuthState {
|
||||
const factory AuthState() = _AuthState;
|
||||
|
||||
const factory AuthState.loading() = AuthStateLoading;
|
||||
|
||||
const factory AuthState.loaded({
|
||||
required String token,
|
||||
}) = AuthStateLoaded;
|
||||
|
||||
const factory AuthState.error({
|
||||
required String errorMessage,
|
||||
}) = AuthStateError;
|
||||
}
|
||||
632
lib/features/auth/presentation/bloc/auth_state.freezed.dart
Normal file
632
lib/features/auth/presentation/bloc/auth_state.freezed.dart
Normal file
@@ -0,0 +1,632 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'auth_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AuthState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String token) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String token)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String token)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AuthState value) $default, {
|
||||
required TResult Function(AuthStateLoading value) loading,
|
||||
required TResult Function(AuthStateLoaded value) loaded,
|
||||
required TResult Function(AuthStateError value) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AuthState value)? $default, {
|
||||
TResult? Function(AuthStateLoading value)? loading,
|
||||
TResult? Function(AuthStateLoaded value)? loaded,
|
||||
TResult? Function(AuthStateError value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AuthState value)? $default, {
|
||||
TResult Function(AuthStateLoading value)? loading,
|
||||
TResult Function(AuthStateLoaded value)? loaded,
|
||||
TResult Function(AuthStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $AuthStateCopyWith<$Res> {
|
||||
factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) =
|
||||
_$AuthStateCopyWithImpl<$Res, AuthState>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState>
|
||||
implements $AuthStateCopyWith<$Res> {
|
||||
_$AuthStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AuthStateImplCopyWith<$Res> {
|
||||
factory _$$AuthStateImplCopyWith(
|
||||
_$AuthStateImpl value, $Res Function(_$AuthStateImpl) then) =
|
||||
__$$AuthStateImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AuthStateImplCopyWithImpl<$Res>
|
||||
extends _$AuthStateCopyWithImpl<$Res, _$AuthStateImpl>
|
||||
implements _$$AuthStateImplCopyWith<$Res> {
|
||||
__$$AuthStateImplCopyWithImpl(
|
||||
_$AuthStateImpl _value, $Res Function(_$AuthStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AuthStateImpl implements _AuthState {
|
||||
const _$AuthStateImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$AuthStateImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String token) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return $default();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String token)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return $default?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String token)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AuthState value) $default, {
|
||||
required TResult Function(AuthStateLoading value) loading,
|
||||
required TResult Function(AuthStateLoaded value) loaded,
|
||||
required TResult Function(AuthStateError value) error,
|
||||
}) {
|
||||
return $default(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AuthState value)? $default, {
|
||||
TResult? Function(AuthStateLoading value)? loading,
|
||||
TResult? Function(AuthStateLoaded value)? loaded,
|
||||
TResult? Function(AuthStateError value)? error,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AuthState value)? $default, {
|
||||
TResult Function(AuthStateLoading value)? loading,
|
||||
TResult Function(AuthStateLoaded value)? loaded,
|
||||
TResult Function(AuthStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AuthState implements AuthState {
|
||||
const factory _AuthState() = _$AuthStateImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AuthStateLoadingImplCopyWith<$Res> {
|
||||
factory _$$AuthStateLoadingImplCopyWith(_$AuthStateLoadingImpl value,
|
||||
$Res Function(_$AuthStateLoadingImpl) then) =
|
||||
__$$AuthStateLoadingImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AuthStateLoadingImplCopyWithImpl<$Res>
|
||||
extends _$AuthStateCopyWithImpl<$Res, _$AuthStateLoadingImpl>
|
||||
implements _$$AuthStateLoadingImplCopyWith<$Res> {
|
||||
__$$AuthStateLoadingImplCopyWithImpl(_$AuthStateLoadingImpl _value,
|
||||
$Res Function(_$AuthStateLoadingImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AuthStateLoadingImpl implements AuthStateLoading {
|
||||
const _$AuthStateLoadingImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$AuthStateLoadingImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String token) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String token)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String token)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AuthState value) $default, {
|
||||
required TResult Function(AuthStateLoading value) loading,
|
||||
required TResult Function(AuthStateLoaded value) loaded,
|
||||
required TResult Function(AuthStateError value) error,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AuthState value)? $default, {
|
||||
TResult? Function(AuthStateLoading value)? loading,
|
||||
TResult? Function(AuthStateLoaded value)? loaded,
|
||||
TResult? Function(AuthStateError value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AuthState value)? $default, {
|
||||
TResult Function(AuthStateLoading value)? loading,
|
||||
TResult Function(AuthStateLoaded value)? loaded,
|
||||
TResult Function(AuthStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AuthStateLoading implements AuthState {
|
||||
const factory AuthStateLoading() = _$AuthStateLoadingImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AuthStateLoadedImplCopyWith<$Res> {
|
||||
factory _$$AuthStateLoadedImplCopyWith(_$AuthStateLoadedImpl value,
|
||||
$Res Function(_$AuthStateLoadedImpl) then) =
|
||||
__$$AuthStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String token});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AuthStateLoadedImplCopyWithImpl<$Res>
|
||||
extends _$AuthStateCopyWithImpl<$Res, _$AuthStateLoadedImpl>
|
||||
implements _$$AuthStateLoadedImplCopyWith<$Res> {
|
||||
__$$AuthStateLoadedImplCopyWithImpl(
|
||||
_$AuthStateLoadedImpl _value, $Res Function(_$AuthStateLoadedImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? token = null,
|
||||
}) {
|
||||
return _then(_$AuthStateLoadedImpl(
|
||||
token: null == token
|
||||
? _value.token
|
||||
: token // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AuthStateLoadedImpl implements AuthStateLoaded {
|
||||
const _$AuthStateLoadedImpl({required this.token});
|
||||
|
||||
@override
|
||||
final String token;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.loaded(token: $token)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AuthStateLoadedImpl &&
|
||||
(identical(other.token, token) || other.token == token));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, token);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AuthStateLoadedImplCopyWith<_$AuthStateLoadedImpl> get copyWith =>
|
||||
__$$AuthStateLoadedImplCopyWithImpl<_$AuthStateLoadedImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String token) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loaded(token);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String token)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loaded?.call(token);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String token)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(token);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AuthState value) $default, {
|
||||
required TResult Function(AuthStateLoading value) loading,
|
||||
required TResult Function(AuthStateLoaded value) loaded,
|
||||
required TResult Function(AuthStateError value) error,
|
||||
}) {
|
||||
return loaded(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AuthState value)? $default, {
|
||||
TResult? Function(AuthStateLoading value)? loading,
|
||||
TResult? Function(AuthStateLoaded value)? loaded,
|
||||
TResult? Function(AuthStateError value)? error,
|
||||
}) {
|
||||
return loaded?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AuthState value)? $default, {
|
||||
TResult Function(AuthStateLoading value)? loading,
|
||||
TResult Function(AuthStateLoaded value)? loaded,
|
||||
TResult Function(AuthStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AuthStateLoaded implements AuthState {
|
||||
const factory AuthStateLoaded({required final String token}) =
|
||||
_$AuthStateLoadedImpl;
|
||||
|
||||
String get token;
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$AuthStateLoadedImplCopyWith<_$AuthStateLoadedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AuthStateErrorImplCopyWith<$Res> {
|
||||
factory _$$AuthStateErrorImplCopyWith(_$AuthStateErrorImpl value,
|
||||
$Res Function(_$AuthStateErrorImpl) then) =
|
||||
__$$AuthStateErrorImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AuthStateErrorImplCopyWithImpl<$Res>
|
||||
extends _$AuthStateCopyWithImpl<$Res, _$AuthStateErrorImpl>
|
||||
implements _$$AuthStateErrorImplCopyWith<$Res> {
|
||||
__$$AuthStateErrorImplCopyWithImpl(
|
||||
_$AuthStateErrorImpl _value, $Res Function(_$AuthStateErrorImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? errorMessage = null,
|
||||
}) {
|
||||
return _then(_$AuthStateErrorImpl(
|
||||
errorMessage: null == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AuthStateErrorImpl implements AuthStateError {
|
||||
const _$AuthStateErrorImpl({required this.errorMessage});
|
||||
|
||||
@override
|
||||
final String errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthState.error(errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AuthStateErrorImpl &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, errorMessage);
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AuthStateErrorImplCopyWith<_$AuthStateErrorImpl> get copyWith =>
|
||||
__$$AuthStateErrorImplCopyWithImpl<_$AuthStateErrorImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String token) loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String token)? loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return error?.call(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String token)? loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AuthState value) $default, {
|
||||
required TResult Function(AuthStateLoading value) loading,
|
||||
required TResult Function(AuthStateLoaded value) loaded,
|
||||
required TResult Function(AuthStateError value) error,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AuthState value)? $default, {
|
||||
TResult? Function(AuthStateLoading value)? loading,
|
||||
TResult? Function(AuthStateLoaded value)? loaded,
|
||||
TResult? Function(AuthStateError value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AuthState value)? $default, {
|
||||
TResult Function(AuthStateLoading value)? loading,
|
||||
TResult Function(AuthStateLoaded value)? loaded,
|
||||
TResult Function(AuthStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AuthStateError implements AuthState {
|
||||
const factory AuthStateError({required final String errorMessage}) =
|
||||
_$AuthStateErrorImpl;
|
||||
|
||||
String get errorMessage;
|
||||
|
||||
/// Create a copy of AuthState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$AuthStateErrorImplCopyWith<_$AuthStateErrorImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
151
lib/features/auth/presentation/pages/auth_screen.dart
Normal file
151
lib/features/auth/presentation/pages/auth_screen.dart
Normal file
@@ -0,0 +1,151 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/image_constant.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class AuthScreen extends StatefulWidget {
|
||||
const AuthScreen();
|
||||
|
||||
@override
|
||||
State<AuthScreen> createState() => _AuthScreenState();
|
||||
}
|
||||
|
||||
class _AuthScreenState extends State<AuthScreen> {
|
||||
final emailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
bool checkboxState = false;
|
||||
bool hidePassword = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
FlutterNativeSplash.remove();
|
||||
return BlocProvider<AuthCubit>(
|
||||
create: (BuildContext context) => sl<AuthCubit>(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: SvgPicture.asset(
|
||||
ImageConstant.imgLogoEatvio,
|
||||
height: 48,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(s.email),
|
||||
const SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
controller: emailController,
|
||||
textInputAction: TextInputAction.next,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
textInputType: TextInputType.emailAddress,
|
||||
hintText: 'Введите email',
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(s.password),
|
||||
const SizedBox(height: 4),
|
||||
CustomTextFormField(
|
||||
obscureText: hidePassword,
|
||||
controller: passwordController,
|
||||
hintText: 'Введите пароль',
|
||||
suffix: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
hidePassword = !hidePassword;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
hidePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('Нет аккаунта? '),
|
||||
GestureDetector(
|
||||
onTap: () => GoRouter.of(context).goNamed('webViewRegistrationScreen'),
|
||||
child: Text(
|
||||
'Зарегистрироваться',
|
||||
style: TextStyle(
|
||||
color: appTheme.blueA400,
|
||||
decorationColor: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Нажимая "Войти", Вы соглашаетесь с ',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await launchUrl(Uri.parse(baseUrl + '/oferta_bs.pdf'));
|
||||
},
|
||||
child: Text(
|
||||
'Публичной офертой',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.blueA400,
|
||||
decorationColor: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
height: 48,
|
||||
width: MediaQuery.of(context).size.width - 32,
|
||||
child: FloatingActionButton.extended(
|
||||
heroTag: 'authButton',
|
||||
highlightElevation: 0,
|
||||
elevation: 0,
|
||||
focusElevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
backgroundColor: appTheme.blueA400,
|
||||
onPressed: () => context.read<AuthCubit>().getTokenByCredentials(
|
||||
emailController.text,
|
||||
passwordController.text,
|
||||
),
|
||||
label: Text(
|
||||
'Войти',
|
||||
style: theme.textTheme.titleSmall!.copyWith(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
25
lib/features/auth/repositories/auth_repository.dart
Normal file
25
lib/features/auth/repositories/auth_repository.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'package:eatvio_app/features/auth/models/credentials_model.dart';
|
||||
import 'package:eatvio_app/features/auth/models/token_model.dart';
|
||||
import 'package:eatvio_app/features/auth/services/auth_service.dart';
|
||||
|
||||
class AuthRepository {
|
||||
final AuthService authService;
|
||||
|
||||
AuthRepository({required this.authService});
|
||||
|
||||
Future<TokenModel> getTokenByCredentials(
|
||||
String email,
|
||||
String password,
|
||||
) async {
|
||||
try {
|
||||
return await authService.getTokenByCredentials(
|
||||
credentials: CredentialsModel(
|
||||
email: email,
|
||||
password: password,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
lib/features/auth/services/auth_service.dart
Normal file
16
lib/features/auth/services/auth_service.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/auth/models/credentials_model.dart';
|
||||
import 'package:eatvio_app/features/auth/models/token_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'auth_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class AuthService {
|
||||
factory AuthService(Dio dio, {String? baseUrl}) = _AuthService;
|
||||
|
||||
@GET('/api/login')
|
||||
Future<TokenModel> getTokenByCredentials({
|
||||
@Body() required CredentialsModel credentials,
|
||||
});
|
||||
}
|
||||
75
lib/features/auth/services/auth_service.g.dart
Normal file
75
lib/features/auth/services/auth_service.g.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'auth_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RetrofitGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _AuthService implements AuthService {
|
||||
_AuthService(this._dio, {this.baseUrl, this.errorLogger});
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
String? baseUrl;
|
||||
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<TokenModel> getTokenByCredentials({
|
||||
required CredentialsModel credentials,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = credentials;
|
||||
final _options = _setStreamType<TokenModel>(
|
||||
Options(method: 'GET', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/login',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||
late TokenModel _value;
|
||||
try {
|
||||
_value = TokenModel.fromJson(_result.data!);
|
||||
} on Object catch (e, s) {
|
||||
errorLogger?.logError(e, s, _options);
|
||||
rethrow;
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
requestOptions.responseType == ResponseType.stream)) {
|
||||
if (T == String) {
|
||||
requestOptions.responseType = ResponseType.plain;
|
||||
} else {
|
||||
requestOptions.responseType = ResponseType.json;
|
||||
}
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
|
||||
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||
return dioBaseUrl;
|
||||
}
|
||||
|
||||
final url = Uri.parse(baseUrl);
|
||||
|
||||
if (url.isAbsolute) {
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class WebViewRegistrationScreen extends StatefulWidget {
|
||||
const WebViewRegistrationScreen();
|
||||
|
||||
@override
|
||||
State<WebViewRegistrationScreen> createState() => _WebViewRegistrationScreenState();
|
||||
}
|
||||
|
||||
class _WebViewRegistrationScreenState extends State<WebViewRegistrationScreen> {
|
||||
late final WebViewController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onNavigationRequest: (NavigationRequest request) {
|
||||
if (request.url.contains('profile')) {
|
||||
GoRouter.of(context).go('authScreen');
|
||||
}
|
||||
return NavigationDecision.navigate;
|
||||
},
|
||||
),
|
||||
)
|
||||
..loadRequest(Uri.parse(baseUrl + '/registration/step1'));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: WebViewWidget(controller: _controller),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user