bio login
This commit is contained in:
1 parent
6acec998bc
commit
0ba83858fe
12 files changed
+522
-80
No files matched your search
@@ -1,26 +1,59 @@
|
||||
class auth_token {
|
||||
// Istanza privata statica
|
||||
static final auth_token _instance = auth_token._internal();
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
|
||||
// Variabile per salvare il token
|
||||
class AuthToken {
|
||||
static final AuthToken _instance = AuthToken._internal();
|
||||
static AuthToken get instance => _instance;
|
||||
AuthToken._internal();
|
||||
|
||||
final _storage = const FlutterSecureStorage();
|
||||
String? _token;
|
||||
|
||||
// Costruttore privato
|
||||
auth_token._internal();
|
||||
|
||||
// Factory per ritornare sempre la stessa istanza
|
||||
factory auth_token() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
// Getter e setter per il token
|
||||
String? get token => _token;
|
||||
set token(String? value) {
|
||||
_token = value;
|
||||
|
||||
Future<bool> isMobilePlatform() async {
|
||||
if (kIsWeb) return false;
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
if (defaultTargetPlatform == TargetPlatform.android) return true;
|
||||
if (defaultTargetPlatform == TargetPlatform.iOS) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Metodo per cancellare il token (es. logout)
|
||||
void clear() {
|
||||
Future<void> saveToken(String token) async {
|
||||
_token = token;
|
||||
if (await isMobilePlatform()) {
|
||||
await _storage.write(key: 'AuthToken', value: token);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> loadTokenWithBiometric() async {
|
||||
if (!await isMobilePlatform()) return false;
|
||||
|
||||
final auth = LocalAuthentication();
|
||||
final canAuth =
|
||||
await auth.canCheckBiometrics || await auth.isDeviceSupported();
|
||||
if (!canAuth) return false;
|
||||
|
||||
final authenticated = await auth.authenticate(
|
||||
localizedReason: 'Autenticati per accedere',
|
||||
options: const AuthenticationOptions(biometricOnly: true),
|
||||
);
|
||||
|
||||
if (authenticated) {
|
||||
final stored = await _storage.read(key: 'AuthToken');
|
||||
_token = stored;
|
||||
return stored != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> clear() async {
|
||||
_token = null;
|
||||
if (await isMobilePlatform()) {
|
||||
await _storage.delete(key: 'AuthToken');
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-6
@@ -1,21 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'pages/login_page.dart';
|
||||
import 'entities/auth_token.dart';
|
||||
import 'pages/dashboard_page.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final authToken = AuthToken.instance;
|
||||
|
||||
final isLoggedIn = await authToken.loadTokenWithBiometric();
|
||||
//runApp(const MyApp());
|
||||
runApp(MyApp(startInDashboard: isLoggedIn));
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
final bool startInDashboard;
|
||||
const MyApp({super.key, required this.startInDashboard});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Login App',
|
||||
title: 'Gestione Vigne',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.deepPurple,
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const LoginPage(),
|
||||
home: startInDashboard ? const DashboardPage() : const LoginPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
+139
-39
@@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../services/api_service.dart';
|
||||
import 'dashboard_page.dart';
|
||||
import '../entities/auth_token.dart';
|
||||
import 'dashboard_page.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({super.key});
|
||||
@@ -14,33 +16,65 @@ class _LoginPageState extends State<LoginPage> {
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
bool _loading = false;
|
||||
bool _rememberMe = false;
|
||||
String? _error;
|
||||
|
||||
void _login() async {
|
||||
bool get isMobile {
|
||||
final platform = defaultTargetPlatform;
|
||||
return platform == TargetPlatform.android ||
|
||||
platform == TargetPlatform.iOS ||
|
||||
(kIsWeb && MediaQuery.of(context).size.width < 600);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkRememberedUser();
|
||||
}
|
||||
|
||||
Future<void> _checkRememberedUser() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final token = prefs.getString('token');
|
||||
if (token != null && prefs.getBool('rememberMe') == true) {
|
||||
AuthToken.instance.saveToken(token);
|
||||
if (mounted) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const DashboardPage()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _login() async {
|
||||
setState(() {
|
||||
_loading = true;
|
||||
_error = null;
|
||||
});
|
||||
|
||||
final email = _emailController.text.trim();
|
||||
final password = _passwordController.text;
|
||||
|
||||
try {
|
||||
final token = await ApiService.login(email, password);
|
||||
auth_token().token = token;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Login riuscito! Token: $token')),
|
||||
final token = await ApiService.login(
|
||||
_emailController.text.trim(),
|
||||
_passwordController.text,
|
||||
);
|
||||
await AuthToken.instance.saveToken(token);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (_rememberMe) {
|
||||
await prefs.setString('token', token);
|
||||
await prefs.setBool('rememberMe', true);
|
||||
} else {
|
||||
await prefs.remove('token');
|
||||
await prefs.setBool('rememberMe', false);
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
Navigator.of(context).pushReplacement(
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (_) => const DashboardPage()),
|
||||
);
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
});
|
||||
} finally {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
@@ -48,36 +82,102 @@ class _LoginPageState extends State<LoginPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Login')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
final content = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.eco, size: 64, color: Color(0xFF388E3C)),
|
||||
const SizedBox(height: 12),
|
||||
const Text(
|
||||
'Gestione Vigna',
|
||||
style: TextStyle(
|
||||
fontSize: 26,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF2E7D32)),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
TextField(
|
||||
controller: _emailController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Email o Username',
|
||||
border: OutlineInputBorder(),
|
||||
prefixIcon: Icon(Icons.person),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Password',
|
||||
border: OutlineInputBorder(),
|
||||
prefixIcon: Icon(Icons.lock),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
TextField(
|
||||
controller: _emailController,
|
||||
decoration: const InputDecoration(labelText: 'Email'),
|
||||
Checkbox(
|
||||
value: _rememberMe,
|
||||
activeColor: const Color(0xFF43A047),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_rememberMe = value ?? false;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(labelText: 'Password'),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
if (_error != null)
|
||||
Text(
|
||||
_error!,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
_loading
|
||||
? const CircularProgressIndicator()
|
||||
: ElevatedButton(
|
||||
onPressed: _login,
|
||||
child: const Text('Login'),
|
||||
),
|
||||
const Text("Ricorda accesso"),
|
||||
],
|
||||
),
|
||||
if (_error != null)
|
||||
Text(
|
||||
_error!,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
_loading
|
||||
? const CircularProgressIndicator()
|
||||
: SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
icon: const Icon(Icons.login),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF43A047),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
label: const Text('Login', style: TextStyle(fontSize: 18)),
|
||||
onPressed: _login,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: isMobile ? double.infinity : 400,
|
||||
),
|
||||
child: Card(
|
||||
elevation: isMobile ? 0 : 8,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 24, vertical: 32),
|
||||
child: content,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ class ApiService {
|
||||
if (response.statusCode == 200) {
|
||||
final data = jsonDecode(response.body);
|
||||
_token = data['access_token']; // salva il token in memoria
|
||||
return _token!;
|
||||
AuthToken.instance.saveToken(_token!);
|
||||
return '${response.statusCode}';
|
||||
} else {
|
||||
throw Exception(
|
||||
'Login fallito: ${response.statusCode} - ${response.body}');
|
||||
@@ -37,7 +38,7 @@ class ApiService {
|
||||
}
|
||||
|
||||
static Future<dynamic> checkLogin() async {
|
||||
final token = auth_token().token;
|
||||
final token = AuthToken.instance.token;
|
||||
if (token == null) {
|
||||
throw Exception('Token non disponibile. Effettua il login prima.');
|
||||
}
|
||||
|
||||
@@ -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,6 +5,14 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import device_info_plus
|
||||
import flutter_secure_storage_macos
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
}
|
||||
+288
-3
@@ -49,6 +49,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -57,6 +73,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -78,11 +110,72 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.19"
|
||||
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_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -103,10 +196,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
version: "0.18.1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
latlong2:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -131,6 +232,46 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
local_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: local_auth
|
||||
sha256: "27679ed8e0d7daab2357db6bb7076359e083a56b295c0c59723845301da6aed9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
local_auth_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_android
|
||||
sha256: e0e5b1ea247c5a0951c13a7ee13dc1beae69750e6a2e1910d1ed6a3cd4d56943
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.38"
|
||||
local_auth_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_ios
|
||||
sha256: eb283b530029b334698918f1e282d4483737cbca972ff21b9193be3d6de8e2b8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.6"
|
||||
local_auth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_platform_interface
|
||||
sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.10"
|
||||
local_auth_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_windows
|
||||
sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.11"
|
||||
logger:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -179,6 +320,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
polylabel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -195,6 +400,62 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.5"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
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: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -280,6 +541,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.2.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
wkt_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -288,6 +565,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
sdks:
|
||||
dart: ">=3.2.2 <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
flutter: ">=3.16.0"
|
||||
@@ -32,6 +32,11 @@ dependencies:
|
||||
sdk: flutter
|
||||
flutter_map: ^6.1.0
|
||||
latlong2: ^0.9.0
|
||||
#http: ^0.13.6
|
||||
flutter_secure_storage: ^9.0.0
|
||||
local_auth: ^2.1.6
|
||||
device_info_plus: ^9.1.2
|
||||
shared_preferences: ^2.2.2
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
||||
+1
-13
@@ -13,18 +13,6 @@ import 'package:uwine_portal/main.dart';
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
await tester.pumpWidget(MyApp(startInDashboard: false));
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,12 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <local_auth_windows/local_auth_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
LocalAuthPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_windows
|
||||
local_auth_windows
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
Reference in new issue
Block a user