fix&feat:fixing auth and secure token also initian for userpin preparation
This commit is contained in:
parent
4af31d867e
commit
de39c9d7fd
|
@ -1,23 +1,71 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
|
||||
class ApiService {
|
||||
final String baseUrl = dotenv.get('BASE_URL');
|
||||
final String apiKey = dotenv.get('API_KEY');
|
||||
final FlutterSecureStorage _secureStorage = FlutterSecureStorage();
|
||||
|
||||
static const Map<String, String> _headers = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
Future<String?> _getAuthToken() async {
|
||||
return await _secureStorage.read(key: 'token');
|
||||
}
|
||||
|
||||
Future<Map<String, String>> _getHeaders() async {
|
||||
final token = await _getAuthToken();
|
||||
return {
|
||||
..._headers,
|
||||
'x-api-key': apiKey,
|
||||
if (token != null) 'Authorization': 'Bearer $token',
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _processResponse(http.Response response) {
|
||||
if (response.body.isEmpty) {
|
||||
throw Exception('Empty response body');
|
||||
}
|
||||
|
||||
try {
|
||||
final responseJson = jsonDecode(response.body);
|
||||
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
return responseJson;
|
||||
case 400:
|
||||
throw BadRequestException(
|
||||
'Bad request. The server could not process your request.',
|
||||
);
|
||||
case 401:
|
||||
throw UnauthorizedException(
|
||||
'Unauthorized. Please check your credentials.',
|
||||
);
|
||||
case 404:
|
||||
throw NotFoundException(
|
||||
'Not found. The requested resource could not be found.',
|
||||
);
|
||||
case 500:
|
||||
throw ServerException(
|
||||
'Internal server error. Please try again later.',
|
||||
);
|
||||
default:
|
||||
throw Exception('Failed with status code: ${response.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Error parsing response: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> get(String endpoint) async {
|
||||
try {
|
||||
final headers = await _getHeaders();
|
||||
final url = Uri.parse('$baseUrl$endpoint');
|
||||
final response = await http.get(
|
||||
url,
|
||||
headers: {..._headers, 'API_KEY': apiKey},
|
||||
);
|
||||
final response = await http.get(url, headers: headers);
|
||||
|
||||
return _processResponse(response);
|
||||
} catch (e) {
|
||||
|
@ -27,26 +75,24 @@ class ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> post(String endpoint, Map<String, dynamic> body) async {
|
||||
Future<Map<String, dynamic>> post(
|
||||
String endpoint,
|
||||
Map<String, dynamic> body,
|
||||
) async {
|
||||
try {
|
||||
final headers = await _getHeaders();
|
||||
final url = Uri.parse('$baseUrl$endpoint');
|
||||
|
||||
// Debugging URL dan Body Request
|
||||
debugPrint('Request URL: $url');
|
||||
debugPrint('Request Body: ${jsonEncode(body)}');
|
||||
debugPrint('API_KEY: $apiKey');
|
||||
|
||||
final response = await http.post(
|
||||
url,
|
||||
headers: {
|
||||
..._headers, // Menggunakan _headers untuk Content-Type
|
||||
'x-api-key': apiKey, // Pastikan API_KEY dimasukkan dengan benar di sini
|
||||
},
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
debugPrint('Response: ${response.body}'); // Debugging Response
|
||||
|
||||
debugPrint('Response: ${response.body}');
|
||||
return _processResponse(response);
|
||||
} catch (e) {
|
||||
debugPrint('Error during API request: $e');
|
||||
|
@ -61,15 +107,22 @@ class ApiService {
|
|||
Map<String, dynamic> body,
|
||||
) async {
|
||||
try {
|
||||
final headers = await _getHeaders();
|
||||
final url = Uri.parse('$baseUrl$endpoint');
|
||||
|
||||
debugPrint('Request URL: $url');
|
||||
debugPrint('Request Body: ${jsonEncode(body)}');
|
||||
|
||||
final response = await http.put(
|
||||
url,
|
||||
headers: {..._headers, 'API_KEY': apiKey},
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
debugPrint('Response: ${response.body}');
|
||||
return _processResponse(response);
|
||||
} catch (e) {
|
||||
debugPrint('Error during API request: $e');
|
||||
throw NetworkException(
|
||||
'Failed to connect to the server. Please check your internet connection.',
|
||||
);
|
||||
|
@ -81,15 +134,22 @@ class ApiService {
|
|||
Map<String, dynamic> body,
|
||||
) async {
|
||||
try {
|
||||
final headers = await _getHeaders();
|
||||
final url = Uri.parse('$baseUrl$endpoint');
|
||||
|
||||
debugPrint('Request URL: $url');
|
||||
debugPrint('Request Body: ${jsonEncode(body)}');
|
||||
|
||||
final response = await http.patch(
|
||||
url,
|
||||
headers: {..._headers, 'API_KEY': apiKey},
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
|
||||
debugPrint('Response: ${response.body}');
|
||||
return _processResponse(response);
|
||||
} catch (e) {
|
||||
debugPrint('Error during API request: $e');
|
||||
throw NetworkException(
|
||||
'Failed to connect to the server. Please check your internet connection.',
|
||||
);
|
||||
|
@ -98,11 +158,9 @@ class ApiService {
|
|||
|
||||
Future<Map<String, dynamic>> delete(String endpoint) async {
|
||||
try {
|
||||
final headers = await _getHeaders();
|
||||
final url = Uri.parse('$baseUrl$endpoint');
|
||||
final response = await http.delete(
|
||||
url,
|
||||
headers: {..._headers, 'API_KEY': apiKey},
|
||||
);
|
||||
final response = await http.delete(url, headers: headers);
|
||||
|
||||
return _processResponse(response);
|
||||
} catch (e) {
|
||||
|
@ -111,29 +169,6 @@ class ApiService {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> _processResponse(http.Response response) {
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
return jsonDecode(response.body);
|
||||
case 400:
|
||||
throw BadRequestException(
|
||||
'Bad request. The server could not process your request.',
|
||||
);
|
||||
case 401:
|
||||
throw UnauthorizedException(
|
||||
'Unauthorized. Please check your credentials.',
|
||||
);
|
||||
case 404:
|
||||
throw NotFoundException(
|
||||
'Not found. The requested resource could not be found.',
|
||||
);
|
||||
case 500:
|
||||
throw ServerException('Internal server error. Please try again later.');
|
||||
default:
|
||||
throw Exception('Failed with status code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkException implements Exception {
|
||||
|
|
|
@ -18,13 +18,6 @@ final router = GoRouter(
|
|||
builder: (context, state) => OnboardingPageScreen(),
|
||||
),
|
||||
GoRoute(path: '/login', builder: (context, state) => LoginScreen()),
|
||||
GoRoute(
|
||||
path: '/navigasi',
|
||||
builder: (context, state) {
|
||||
dynamic data = state.extra;
|
||||
return NavigationPage(data: data);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/verif-otp',
|
||||
builder: (context, state) {
|
||||
|
@ -32,6 +25,17 @@ final router = GoRouter(
|
|||
return VerifotpScreen(phone: phone!);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/inputpin',
|
||||
builder: (context, state) => OnboardingPageScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/navigasi',
|
||||
builder: (context, state) {
|
||||
dynamic data = state.extra;
|
||||
return NavigationPage(data: data);
|
||||
},
|
||||
),
|
||||
GoRoute(path: '/home', builder: (context, state) => HomeScreen()),
|
||||
GoRoute(path: '/activity', builder: (context, state) => ActivityScreen()),
|
||||
GoRoute(
|
||||
|
|
|
@ -1,40 +1,27 @@
|
|||
import 'package:rijig_mobile/core/api_services.dart';
|
||||
import 'package:rijig_mobile/model/response_model.dart';
|
||||
|
||||
class AuthModel {
|
||||
final int status;
|
||||
final String message;
|
||||
|
||||
AuthModel({required this.status, required this.message});
|
||||
|
||||
factory AuthModel.fromJson(Map<String, dynamic> json) {
|
||||
return AuthModel(
|
||||
status: json['meta']?['status'] ?? 0,
|
||||
message: json['meta']?['message'] ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AuthService {
|
||||
final ApiService _apiService = ApiService();
|
||||
|
||||
Future<AuthModel?> login(String phone) async {
|
||||
Future<ResponseModel?> login(String phone) async {
|
||||
try {
|
||||
var response = await _apiService.post('/authmasyarakat/auth', {
|
||||
'phone': phone,
|
||||
});
|
||||
return AuthModel.fromJson(response);
|
||||
return ResponseModel.fromJson(response);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> verifyOtp(String phone, String otp) async {
|
||||
Future<ResponseModel?> verifyOtp(String phone, String otp) async {
|
||||
try {
|
||||
var response = await _apiService.post('/authmasyarakat/verify-otp', {
|
||||
'phone': phone,
|
||||
'otp': otp,
|
||||
});
|
||||
return response;
|
||||
return ResponseModel.fromJson(response);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
class ResponseModel {
|
||||
final int status;
|
||||
final String message;
|
||||
final Map<String, dynamic>? data;
|
||||
|
||||
ResponseModel({required this.status, required this.message, this.data});
|
||||
|
||||
factory ResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
return ResponseModel(
|
||||
status: json['meta']?['status'] ?? 0,
|
||||
message: json['meta']?['message'] ?? '',
|
||||
data: json['data'],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:rijig_mobile/core/api_services.dart';
|
||||
import 'package:rijig_mobile/model/response_model.dart';
|
||||
|
||||
class AuthService {
|
||||
final ApiService _apiService = ApiService();
|
||||
|
||||
Future<ResponseModel?> cekPinStatus(String userid) async {
|
||||
try {
|
||||
var response = await _apiService.get('/cek-pin-status');
|
||||
return ResponseModel.fromJson(response);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> verifyOtp(String phone, String otp) async {
|
||||
try {
|
||||
var response = await _apiService.post('/authmasyarakat/verify-otp', {
|
||||
'phone': phone,
|
||||
'otp': otp,
|
||||
});
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +1,42 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:rijig_mobile/core/guide.dart';
|
||||
import 'package:rijig_mobile/core/router.dart';
|
||||
import 'package:rijig_mobile/viewmodel/auth_vmod.dart';
|
||||
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||
import 'package:rijig_mobile/widget/formfiled.dart';
|
||||
|
||||
class LoginScreen extends StatelessWidget {
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
LoginScreenState createState() => LoginScreenState();
|
||||
}
|
||||
|
||||
class LoginScreenState extends State<LoginScreen> {
|
||||
final _phoneController = TextEditingController();
|
||||
|
||||
LoginScreen({super.key});
|
||||
@override
|
||||
void dispose() {
|
||||
_phoneController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: PaddingCustom().paddingHorizontalVertical(15, 30),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 30),
|
||||
child: Consumer<AuthViewModel>(
|
||||
builder: (context, userVM, child) {
|
||||
if (userVM.authModel?.status == 200) {
|
||||
Future.delayed(Duration.zero, () {
|
||||
debugPrint('AuthModel Status: ${userVM.authModel?.status}');
|
||||
|
||||
if (userVM.authModel?.status == 200 && !userVM.isLoading) {
|
||||
debugPrint(
|
||||
'OTP Sent Successfully. Navigating to Verif-OTP Screen.',
|
||||
);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
router.go('/verif-otp', extra: _phoneController.text);
|
||||
});
|
||||
}
|
||||
|
@ -36,10 +52,20 @@ class LoginScreen extends StatelessWidget {
|
|||
keyboardType: TextInputType.phone,
|
||||
errorText: userVM.errorMessage,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
userVM.isLoading
|
||||
? CircularProgressIndicator()
|
||||
? CardButtonOne(
|
||||
textButton: 'Sending OTP...',
|
||||
fontSized: 16,
|
||||
colorText: Colors.white,
|
||||
borderRadius: 12,
|
||||
horizontal: double.infinity,
|
||||
vertical: 50,
|
||||
onTap: () {},
|
||||
loadingTrue: true,
|
||||
usingRow: false,
|
||||
)
|
||||
: CardButtonOne(
|
||||
textButton: 'Send OTP',
|
||||
fontSized: 16,
|
||||
|
@ -49,21 +75,27 @@ class LoginScreen extends StatelessWidget {
|
|||
vertical: 50,
|
||||
onTap: () {
|
||||
if (_phoneController.text.isNotEmpty) {
|
||||
debugPrint(
|
||||
'Sending OTP to: ${_phoneController.text}',
|
||||
);
|
||||
userVM.login(_phoneController.text);
|
||||
}
|
||||
},
|
||||
loadingTrue: userVM.isLoading,
|
||||
loadingTrue: false,
|
||||
usingRow: false,
|
||||
),
|
||||
|
||||
if (userVM.authModel != null)
|
||||
Text(
|
||||
userVM.authModel!.message,
|
||||
style: TextStyle(
|
||||
color:
|
||||
userVM.authModel!.status == 200
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Text(
|
||||
userVM.authModel!.message,
|
||||
style: TextStyle(
|
||||
color:
|
||||
userVM.authModel!.status == 200
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:rijig_mobile/model/response_model.dart';
|
||||
import 'package:rijig_mobile/model/auth_model.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class AuthViewModel extends ChangeNotifier {
|
||||
final AuthService _authService = AuthService();
|
||||
final AuthModel _authModel = AuthModel();
|
||||
final FlutterSecureStorage _secureStorage = FlutterSecureStorage();
|
||||
bool isLoading = false;
|
||||
String? errorMessage;
|
||||
AuthModel? authModel;
|
||||
ResponseModel? authModel;
|
||||
|
||||
Future<void> login(String phone) async {
|
||||
try {
|
||||
|
@ -14,10 +17,15 @@ class AuthViewModel extends ChangeNotifier {
|
|||
errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
authModel = await _authService.login(phone);
|
||||
final response = await _authModel.login(phone);
|
||||
|
||||
if (authModel?.status != 200) {
|
||||
errorMessage = authModel?.message ?? 'Failed to send OTP';
|
||||
if (response != null && response.status == 200) {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('isLoggedIn', false);
|
||||
|
||||
authModel = response;
|
||||
} else {
|
||||
errorMessage = response?.message ?? 'Failed to send OTP';
|
||||
}
|
||||
} catch (e) {
|
||||
errorMessage = 'Error: $e';
|
||||
|
@ -33,18 +41,28 @@ class AuthViewModel extends ChangeNotifier {
|
|||
errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
var response = await _authService.verifyOtp(phone, otp);
|
||||
var response = await _authModel.verifyOtp(phone, otp);
|
||||
|
||||
if (response != null && response.status == 200) {
|
||||
await _secureStorage.write(
|
||||
key: 'token',
|
||||
value: response.data?['token'],
|
||||
);
|
||||
await _secureStorage.write(
|
||||
key: 'user_id',
|
||||
value: response.data?['user_id'],
|
||||
);
|
||||
await _secureStorage.write(
|
||||
key: 'user_role',
|
||||
value: response.data?['user_role'],
|
||||
);
|
||||
|
||||
if (response['meta'] != null && response['meta']['status'] == 200) {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('token', response['data']['token']);
|
||||
await prefs.setString('user_id', response['data']['user_id']);
|
||||
await prefs.setString('user_role', response['data']['user_role']);
|
||||
await prefs.setBool('isLoggedIn', true);
|
||||
|
||||
authModel = AuthModel.fromJson(response['data']);
|
||||
authModel = response;
|
||||
} else {
|
||||
errorMessage = response['meta']?['message'] ?? 'Failed to verify OTP';
|
||||
errorMessage = response?.message ?? 'Failed to verify OTP';
|
||||
}
|
||||
} catch (e) {
|
||||
errorMessage = 'Error: $e';
|
||||
|
@ -53,4 +71,31 @@ class AuthViewModel extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getAuthToken() async {
|
||||
return await _secureStorage.read(key: 'token');
|
||||
}
|
||||
|
||||
Future<String?> getUserId() async {
|
||||
return await _secureStorage.read(key: 'user_id');
|
||||
}
|
||||
|
||||
Future<String?> getUserRole() async {
|
||||
return await _secureStorage.read(key: 'user_role');
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _secureStorage.delete(key: 'token');
|
||||
await _secureStorage.delete(key: 'user_id');
|
||||
await _secureStorage.delete(key: 'user_role');
|
||||
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('isLoggedIn');
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> isUserLoggedIn() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getBool('isLoggedIn') ?? false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import flutter_secure_storage_macos
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
}
|
||||
|
|
64
pubspec.lock
64
pubspec.lock
|
@ -126,6 +126,54 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.9.3"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.2.4"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_macos
|
||||
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
flutter_secure_storage_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_platform_interface
|
||||
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_secure_storage_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_web
|
||||
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
flutter_secure_storage_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_windows
|
||||
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -200,6 +248,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -541,6 +597,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.12.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
sdk: flutter
|
||||
flutter_dotenv: ^5.2.1
|
||||
flutter_screenutil: ^5.9.3
|
||||
flutter_secure_storage: ^9.2.4
|
||||
flutter_svg: ^2.1.0
|
||||
gap: ^3.0.1
|
||||
go_router: ^15.1.1
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_windows
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
|
Loading…
Reference in New Issue