fix: the login request into dio and fix the model
This commit is contained in:
parent
f479acac91
commit
837823f937
|
@ -1,9 +1,11 @@
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/data/providers/dio_client.dart';
|
import 'package:quiz_app/data/providers/dio_client.dart';
|
||||||
|
import 'package:quiz_app/data/services/user_storage_service.dart';
|
||||||
|
|
||||||
class InitialBindings extends Bindings {
|
class InitialBindings extends Bindings {
|
||||||
@override
|
@override
|
||||||
void dependencies() {
|
void dependencies() {
|
||||||
|
Get.put<UserStorageService>(UserStorageService());
|
||||||
Get.putAsync(() => ApiClient().init());
|
Get.putAsync(() => ApiClient().init());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get_navigation/src/routes/route_middleware.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||||
|
import 'package:quiz_app/data/services/user_storage_service.dart';
|
||||||
|
|
||||||
class AuthMiddleware extends GetMiddleware {
|
class AuthMiddleware extends GetMiddleware {
|
||||||
@override
|
@override
|
||||||
RouteSettings? redirect(String? route) {
|
RouteSettings? redirect(String? route) {
|
||||||
if (route != null) return RouteSettings(name: AppRoutes.loginPage);
|
final UserStorageService _storageService = Get.find();
|
||||||
|
if (!_storageService.isLogged) {
|
||||||
|
return const RouteSettings(name: AppRoutes.loginPage);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
class BaseResponseModel<T> {
|
||||||
|
final String message;
|
||||||
|
final T? data;
|
||||||
|
final dynamic meta;
|
||||||
|
|
||||||
|
BaseResponseModel({
|
||||||
|
required this.message,
|
||||||
|
this.data,
|
||||||
|
this.meta,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory BaseResponseModel.fromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
T Function(Map<String, dynamic>) fromJsonT,
|
||||||
|
) {
|
||||||
|
return BaseResponseModel<T>(
|
||||||
|
message: json['message'],
|
||||||
|
data: json['data'] != null ? fromJsonT(json['data']) : null,
|
||||||
|
meta: json['meta'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
class LoginRequestModel {
|
||||||
|
final String email;
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
LoginRequestModel({
|
||||||
|
required this.email,
|
||||||
|
required this.password,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory LoginRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return LoginRequestModel(
|
||||||
|
email: json['email'] ?? '',
|
||||||
|
password: json['password'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'email': email,
|
||||||
|
'password': password,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
class LoginResponseModel {
|
||||||
|
final String? id;
|
||||||
|
final String? googleId;
|
||||||
|
final String email;
|
||||||
|
final String name;
|
||||||
|
final DateTime? birthDate;
|
||||||
|
final String? picUrl;
|
||||||
|
final String? phone;
|
||||||
|
final String locale;
|
||||||
|
// final DateTime? createdAt;
|
||||||
|
// final DateTime? updatedAt;
|
||||||
|
|
||||||
|
LoginResponseModel({
|
||||||
|
this.id,
|
||||||
|
this.googleId,
|
||||||
|
required this.email,
|
||||||
|
required this.name,
|
||||||
|
this.birthDate,
|
||||||
|
this.picUrl,
|
||||||
|
this.phone,
|
||||||
|
this.locale = "en-US",
|
||||||
|
// this.createdAt,
|
||||||
|
// this.updatedAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory LoginResponseModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return LoginResponseModel(
|
||||||
|
id: json['_id'],
|
||||||
|
googleId: json['google_id'],
|
||||||
|
email: json['email'],
|
||||||
|
name: json['name'],
|
||||||
|
birthDate: json['birth_date'] != null ? DateTime.parse(json['birth_date']) : null,
|
||||||
|
picUrl: json['pic_url'],
|
||||||
|
phone: json['phone'],
|
||||||
|
locale: json['locale'] ?? 'en-US',
|
||||||
|
// createdAt: json['created_at'] != null ? DateTime.parse(json['created_at']) : null,
|
||||||
|
// updatedAt: json['updated_at'] != null ? DateTime.parse(json['updated_at']) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'_id': id,
|
||||||
|
'google_id': googleId,
|
||||||
|
'email': email,
|
||||||
|
'name': name,
|
||||||
|
'birth_date': birthDate?.toIso8601String(),
|
||||||
|
'pic_url': picUrl,
|
||||||
|
'phone': phone,
|
||||||
|
'locale': locale,
|
||||||
|
// 'created_at': createdAt?.toIso8601String(),
|
||||||
|
// 'updated_at': updatedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/core/endpoint/api_endpoint.dart';
|
import 'package:quiz_app/core/endpoint/api_endpoint.dart';
|
||||||
|
import 'package:quiz_app/data/models/base/base_model.dart';
|
||||||
|
import 'package:quiz_app/data/models/login/login_request_model.dart';
|
||||||
|
import 'package:quiz_app/data/models/login/login_response_model.dart';
|
||||||
import 'package:quiz_app/data/models/register/register_request.dart';
|
import 'package:quiz_app/data/models/register/register_request.dart';
|
||||||
import 'package:quiz_app/data/providers/dio_client.dart';
|
import 'package:quiz_app/data/providers/dio_client.dart';
|
||||||
|
|
||||||
|
@ -13,11 +16,47 @@ class AuthService extends GetxService {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> register(RegisterRequestModel request) async {
|
Future<bool> register(RegisterRequestModel request) async {
|
||||||
var data = await _dio.post(
|
var data = await _dio.post(
|
||||||
APIEndpoint.register,
|
APIEndpoint.register,
|
||||||
data: request.toJson(),
|
data: request.toJson(),
|
||||||
);
|
);
|
||||||
print(data);
|
if (data.statusCode == 200) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw Exception("Registration failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<LoginResponseModel> loginWithEmail(LoginRequestModel request) async {
|
||||||
|
final data = request.toJson();
|
||||||
|
final response = await _dio.post(APIEndpoint.login, data: data);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final baseResponse = BaseResponseModel<LoginResponseModel>.fromJson(
|
||||||
|
response.data,
|
||||||
|
(json) => LoginResponseModel.fromJson(json),
|
||||||
|
);
|
||||||
|
return baseResponse.data!;
|
||||||
|
} else {
|
||||||
|
throw Exception("Login failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<LoginResponseModel> loginWithGoogle(String idToken) async {
|
||||||
|
final response = await _dio.post(
|
||||||
|
APIEndpoint.loginGoogle,
|
||||||
|
data: {"token_id": idToken},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final baseResponse = BaseResponseModel<LoginResponseModel>.fromJson(
|
||||||
|
response.data,
|
||||||
|
(json) => LoginResponseModel.fromJson(json),
|
||||||
|
);
|
||||||
|
return baseResponse.data!;
|
||||||
|
} else {
|
||||||
|
throw Exception("Google login failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:quiz_app/data/models/login/login_response_model.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class UserStorageService {
|
||||||
|
static const _userKey = 'user_data';
|
||||||
|
bool isLogged = false;
|
||||||
|
|
||||||
|
Future<void> saveUser(LoginResponseModel user) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString(_userKey, jsonEncode(user.toJson()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<LoginResponseModel?> loadUser() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final jsonString = prefs.getString(_userKey);
|
||||||
|
|
||||||
|
if (jsonString == null) return null;
|
||||||
|
return LoginResponseModel.fromJson(jsonDecode(jsonString));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> clearUser() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.remove(_userKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> isLoggedIn() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.containsKey(_userKey);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
import 'package:get/get_core/get_core.dart';
|
import 'package:get/get_core/get_core.dart';
|
||||||
import 'package:get/get_instance/get_instance.dart';
|
import 'package:get/get_instance/get_instance.dart';
|
||||||
|
import 'package:quiz_app/data/services/auth_service.dart';
|
||||||
|
import 'package:quiz_app/data/services/user_storage_service.dart';
|
||||||
import 'package:quiz_app/feature/login/controllers/login_controller.dart';
|
import 'package:quiz_app/feature/login/controllers/login_controller.dart';
|
||||||
|
|
||||||
class LoginBinding extends Bindings {
|
class LoginBinding extends Bindings {
|
||||||
@override
|
@override
|
||||||
void dependencies() {
|
void dependencies() {
|
||||||
Get.lazyPut(() => LoginController());
|
Get.lazyPut(() => AuthService());
|
||||||
|
Get.lazyPut(() => LoginController(Get.find<AuthService>(), Get.find<UserStorageService>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,26 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:http/http.dart' as http;
|
|
||||||
import 'package:google_sign_in/google_sign_in.dart';
|
import 'package:google_sign_in/google_sign_in.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||||
import 'package:quiz_app/core/endpoint/api_endpoint.dart';
|
|
||||||
import 'package:quiz_app/core/utils/logger.dart';
|
import 'package:quiz_app/core/utils/logger.dart';
|
||||||
|
import 'package:quiz_app/data/models/login/login_request_model.dart';
|
||||||
|
import 'package:quiz_app/data/models/login/login_response_model.dart';
|
||||||
|
import 'package:quiz_app/data/services/auth_service.dart';
|
||||||
|
import 'package:quiz_app/data/services/user_storage_service.dart';
|
||||||
|
|
||||||
class LoginController extends GetxController {
|
class LoginController extends GetxController {
|
||||||
|
final AuthService _authService;
|
||||||
|
final UserStorageService _userStorageService;
|
||||||
|
|
||||||
|
LoginController(this._authService, this._userStorageService);
|
||||||
final TextEditingController emailController = TextEditingController();
|
final TextEditingController emailController = TextEditingController();
|
||||||
final TextEditingController passwordController = TextEditingController();
|
final TextEditingController passwordController = TextEditingController();
|
||||||
|
|
||||||
var isPasswordHidden = true.obs;
|
var isPasswordHidden = true.obs;
|
||||||
var isLoading = false.obs; // Loading state for UI
|
var isLoading = false.obs;
|
||||||
final GoogleSignIn _googleSignIn = GoogleSignIn(
|
final GoogleSignIn _googleSignIn = GoogleSignIn(
|
||||||
scopes: ['email', 'profile', 'openid'],
|
scopes: ['email', 'profile', 'openid'],
|
||||||
); // Singleton instance
|
);
|
||||||
|
|
||||||
void togglePasswordVisibility() {
|
void togglePasswordVisibility() {
|
||||||
isPasswordHidden.value = !isPasswordHidden.value;
|
isPasswordHidden.value = !isPasswordHidden.value;
|
||||||
|
@ -34,19 +39,18 @@ class LoginController extends GetxController {
|
||||||
try {
|
try {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|
||||||
var response = await http.post(
|
LoginResponseModel response = await _authService.loginWithEmail(
|
||||||
Uri.parse("${APIEndpoint.baseUrl}${APIEndpoint.login}"),
|
LoginRequestModel(
|
||||||
body: jsonEncode({"email": email, "password": password}),
|
email: email,
|
||||||
headers: {"Content-Type": "application/json"},
|
password: password,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
await _userStorageService.saveUser(response);
|
||||||
var data = jsonDecode(response.body);
|
|
||||||
} else {
|
_userStorageService.isLogged = true;
|
||||||
var errorMsg = jsonDecode(response.body)['message'] ?? "Invalid credentials";
|
|
||||||
logC.i(errorMsg);
|
Get.toNamed(AppRoutes.homePage);
|
||||||
Get.snackbar("Error", errorMsg);
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
logC.e(e, stackTrace: stackTrace);
|
logC.e(e, stackTrace: stackTrace);
|
||||||
Get.snackbar("Error", "Failed to connect to server");
|
Get.snackbar("Error", "Failed to connect to server");
|
||||||
|
@ -63,10 +67,6 @@ class LoginController extends GetxController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logC.i("Google User ID: ${googleUser.id}");
|
|
||||||
logC.i("Google User Email: ${googleUser.email}");
|
|
||||||
logC.i("Google User Display Name: ${googleUser.displayName}");
|
|
||||||
|
|
||||||
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
|
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
|
||||||
|
|
||||||
if (googleAuth.idToken == null || googleAuth.idToken!.isEmpty) {
|
if (googleAuth.idToken == null || googleAuth.idToken!.isEmpty) {
|
||||||
|
@ -75,25 +75,13 @@ class LoginController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
String idToken = googleAuth.idToken!;
|
String idToken = googleAuth.idToken!;
|
||||||
logC.i("Google ID Token: $idToken");
|
|
||||||
|
|
||||||
// Send ID Token to backend
|
final response = await _authService.loginWithGoogle(idToken);
|
||||||
var response = await http.post(
|
await _userStorageService.saveUser(response);
|
||||||
Uri.parse("${APIEndpoint.baseUrl}${APIEndpoint.loginGoogle}"),
|
|
||||||
body: jsonEncode({"token_id": idToken}),
|
|
||||||
headers: {"Content-Type": "application/json"},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
_userStorageService.isLogged = true;
|
||||||
var data = jsonDecode(response.body);
|
|
||||||
|
|
||||||
Get.snackbar("Success", "Google login successful!");
|
Get.toNamed(AppRoutes.homePage);
|
||||||
// logC.i("Backend Auth Token: $backendToken");
|
|
||||||
} else {
|
|
||||||
var errorMsg = jsonDecode(response.body)['message'] ?? "Google login failed";
|
|
||||||
Get.snackbar("Error", errorMsg);
|
|
||||||
logC.i(errorMsg);
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
logC.e("Google Sign-In Error: $e", stackTrace: stackTrace);
|
logC.e("Google Sign-In Error: $e", stackTrace: stackTrace);
|
||||||
Get.snackbar("Error", "Google sign-in error");
|
Get.snackbar("Error", "Google sign-in error");
|
||||||
|
|
|
@ -2,21 +2,36 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||||
import 'package:quiz_app/component/app_name.dart';
|
import 'package:quiz_app/component/app_name.dart';
|
||||||
|
import 'package:quiz_app/data/services/user_storage_service.dart';
|
||||||
|
|
||||||
class SplashScreenView extends StatelessWidget {
|
class SplashScreenView extends StatelessWidget {
|
||||||
const SplashScreenView({super.key});
|
const SplashScreenView({super.key});
|
||||||
|
|
||||||
|
void _navigate() async {
|
||||||
|
final storageService = Get.find<UserStorageService>();
|
||||||
|
final isLoggedIn = await storageService.isLoggedIn();
|
||||||
|
storageService.isLogged = isLoggedIn;
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
|
||||||
|
if (isLoggedIn) {
|
||||||
|
Get.offNamed(AppRoutes.homePage);
|
||||||
|
} else {
|
||||||
|
Get.offNamed(AppRoutes.loginPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Delay navigation after the first frame is rendered
|
// Jalankan navigasi setelah frame pertama selesai dirender
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
_navigate();
|
||||||
Get.offNamed(AppRoutes.homePage);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return Scaffold(
|
return const Scaffold(
|
||||||
body: Center(child: AppName()),
|
body: Center(
|
||||||
|
child: AppName(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
116
pubspec.lock
116
pubspec.lock
|
@ -73,6 +73,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.3"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -161,7 +177,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.4+3"
|
version: "0.12.4+3"
|
||||||
http:
|
http:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
||||||
|
@ -248,6 +264,38 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.6"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -256,6 +304,62 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
version: "2.1.8"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.3"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.10"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.4"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.3"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -341,6 +445,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.6.0 <4.0.0"
|
dart: ">=3.6.0 <4.0.0"
|
||||||
flutter: ">=3.24.0"
|
flutter: ">=3.27.0"
|
||||||
|
|
|
@ -39,6 +39,7 @@ dependencies:
|
||||||
google_sign_in: ^6.2.2
|
google_sign_in: ^6.2.2
|
||||||
flutter_dotenv: ^5.2.1
|
flutter_dotenv: ^5.2.1
|
||||||
dio: ^5.8.0+1
|
dio: ^5.8.0+1
|
||||||
|
shared_preferences: ^2.5.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in New Issue