diff --git a/frontend/app/android/app/src/main/AndroidManifest.xml b/frontend/app/android/app/src/main/AndroidManifest.xml index e8847cc..996a45e 100644 --- a/frontend/app/android/app/src/main/AndroidManifest.xml +++ b/frontend/app/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/app/lib/main.dart b/frontend/app/lib/main.dart index 42bb5d6..47be75a 100644 --- a/frontend/app/lib/main.dart +++ b/frontend/app/lib/main.dart @@ -1,4 +1,5 @@ -import 'package:app/pages/home_page.dart'; +import 'package:app/pages/start_page.dart'; +import 'package:app/pages_draft/home_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart' show GlobalMaterialLocalizations; @@ -11,6 +12,7 @@ void main() async { localizationsDelegates: const [GlobalMaterialLocalizations.delegate], supportedLocales: const [Locale('en'), Locale('de')], theme: ThemeData().copyWith( + canvasColor: Colors.black, colorScheme: const ColorScheme( brightness: Brightness.dark, primary: Colors.white, @@ -45,9 +47,7 @@ void main() async { backgroundColor: Colors.black, foregroundColor: Colors.white, )), - home: HomePage( - loggedOut: false, - ), + home: StartPage(), ), ); } diff --git a/frontend/app/lib/model/services/auth_service.dart b/frontend/app/lib/model/services/auth_service.dart new file mode 100644 index 0000000..1ef3af9 --- /dev/null +++ b/frontend/app/lib/model/services/auth_service.dart @@ -0,0 +1,43 @@ +import 'package:flutter/services.dart'; +import 'package:local_auth/local_auth.dart'; + +class AuthService { + static Future authenticateWithBiometrics() async { + //initialize Local Authentication plugin. + final LocalAuthentication localAuthentication = LocalAuthentication(); + //status of authentication. + bool isAuthenticated = false; + //check if device supports biometrics authentication. + bool isBiometricSupported = await localAuthentication.isDeviceSupported(); + //check if user has enabled biometrics. + //check + bool canCheckBiometrics = await localAuthentication.canCheckBiometrics; + + //if device supports biometrics and user has enabled biometrics, then authenticate. + if (isBiometricSupported && canCheckBiometrics) { + // ignore: use_build_context_synchronously + // final messenger = ScaffoldMessenger.of(context); + try { + isAuthenticated = await localAuthentication.authenticate( + localizedReason: 'Scan your fingerprint to authenticate', + options: const AuthenticationOptions( + biometricOnly: false, + useErrorDialogs: true, + stickyAuth: true, + ), + ); + } on PlatformException catch (err) { + print(err); + // messenger.showSnackBar(SnackBar( + // backgroundColor: CustomColors.error, + // content: Text( + // 'Fehler beim Einrichten der Biometrie: $err', + // style: const TextStyle(color: Colors.white), + // ), + // )); + } + } + print(isAuthenticated); + return isAuthenticated; + } +} diff --git a/frontend/app/lib/model/view_model/account_vm.dart b/frontend/app/lib/model/view_model/account_vm.dart index 1457964..bbdbbac 100644 --- a/frontend/app/lib/model/view_model/account_vm.dart +++ b/frontend/app/lib/model/view_model/account_vm.dart @@ -22,7 +22,7 @@ class AccountViewModel extends BaseViewModel { } void _init() async { - super.init(); + // super.init(); // try { // _apiResponse = ApiResponse.completed(await _service.getAccount()); // } catch (e) { diff --git a/frontend/app/lib/model/view_model/base_vm.dart b/frontend/app/lib/model/view_model/base_vm.dart index 7745a8e..370e43d 100644 --- a/frontend/app/lib/model/view_model/base_vm.dart +++ b/frontend/app/lib/model/view_model/base_vm.dart @@ -1,12 +1,12 @@ import 'package:app/model/apis/api_response.dart'; import 'package:app/model/services/backend_service.dart'; -import 'package:app/pages/home_page.dart'; +import 'package:app/pages_draft/home_page.dart'; import 'package:app/util/colors.dart'; import 'package:flutter/material.dart'; class BaseViewModel with ChangeNotifier { BaseViewModel() { - init(); + // init(); } ApiResponse _apiResponse = ApiResponse.initial('Keine Daten'); @@ -16,16 +16,16 @@ class BaseViewModel with ChangeNotifier { return _apiResponse; } - void init() async { - // if (await BackendService.isLoggedIn) { - try { - _apiResponse = ApiResponse.completed(await _service.getAccount()); - } catch (e) { - _apiResponse = ApiResponse.error(e.toString()); - } - notifyListeners(); - // } - } + // void init() async { + // // if (await BackendService.isLoggedIn) { + // try { + // _apiResponse = ApiResponse.completed(await _service.getAccount()); + // } catch (e) { + // _apiResponse = ApiResponse.error(e.toString()); + // } + // notifyListeners(); + // // } + // } Future isLoggedIn(BuildContext context) async { final messenger = ScaffoldMessenger.of(context); diff --git a/frontend/app/lib/pages/agb_page.dart b/frontend/app/lib/pages/agb_page.dart new file mode 100644 index 0000000..00378f3 --- /dev/null +++ b/frontend/app/lib/pages/agb_page.dart @@ -0,0 +1,25 @@ +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class AgbPage extends StatelessWidget { + AgbPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + iconTheme: IconThemeData(color: CustomColors.primary), + ), + backgroundColor: Colors.black, + body: const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'TODO: insert AGBs', + textAlign: TextAlign.center, + ) + ], + ), + ); + } +} diff --git a/frontend/app/lib/pages/notifications_page.dart b/frontend/app/lib/pages/notifications_page.dart new file mode 100644 index 0000000..91b2a4e --- /dev/null +++ b/frontend/app/lib/pages/notifications_page.dart @@ -0,0 +1,106 @@ +import 'package:app/pages/registration_page.dart'; +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class NotificationsPage extends StatelessWidget { + const NotificationsPage({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData( + color: CustomColors.primary, + ), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), + child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 80, + ), + Image.asset('assets/chat_bubbles.png'), + const SizedBox( + height: 60, + ), + const Text( + 'Erhalte Mitteilungen', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontWeight: FontWeight.bold, + letterSpacing: 2.0, + fontSize: 25, + ), + ), + const SizedBox( + height: 20, + ), + const Text( + 'Du erhältst z. B. eine Mitteilung sobald wir eine Digitale Spur gefunden haben.', + textAlign: TextAlign.center, + ), + const SizedBox( + height: 20, + ), + const Text( + 'Du kannst die Mitteilungen jederzeit wieder deaktivieren.', + textAlign: TextAlign.center, + ), + const Spacer( + flex: 2, + ), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (builder) => const RegistrationPage(), + // builder: (builder) => SecurityPage(), + ), + ); + }, + child: const SizedBox( + height: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Mitteilungen erhalten', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + const SizedBox( + height: 10, + ), + TextButton( + onPressed: () {}, + child: Text( + 'Später', + style: TextStyle(color: CustomColors.primary), + ), + ), + const Spacer( + flex: 1, + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/registration_page.dart b/frontend/app/lib/pages/registration_page.dart new file mode 100644 index 0000000..feff349 --- /dev/null +++ b/frontend/app/lib/pages/registration_page.dart @@ -0,0 +1,102 @@ +import 'package:app/pages_old/start_page.dart'; +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class RegistrationPage extends StatelessWidget { + const RegistrationPage({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData( + color: CustomColors.primary, + ), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 16), + child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 20, + ), + const Text( + 'Jetzt Registrieren', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontWeight: FontWeight.bold, + letterSpacing: 2.0, + fontSize: 25, + ), + ), + const SizedBox( + height: 20, + ), + const Text( + 'Gib deine E-Mail Adresse ein.', + // textAlign: TextAlign.center, + ), + const SizedBox( + height: 20, + ), + const Text( + 'Du kannst die Mitteilungen jederzeit wieder deaktivieren.', + textAlign: TextAlign.center, + ), + const Spacer( + flex: 2, + ), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (builder) => StartPage(), + // builder: (builder) => SecurityPage(), + ), + ); + }, + child: const SizedBox( + height: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Mitteilungen erhalten', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + const SizedBox( + height: 10, + ), + TextButton( + onPressed: () {}, + child: Text( + 'Später', + style: TextStyle(color: CustomColors.primary), + ), + ), + const Spacer( + flex: 1, + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/security_page.dart b/frontend/app/lib/pages/security_page.dart new file mode 100644 index 0000000..236a1f9 --- /dev/null +++ b/frontend/app/lib/pages/security_page.dart @@ -0,0 +1,126 @@ +import 'package:app/model/services/auth_service.dart'; +import 'package:app/pages/notifications_page.dart'; +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class SecurityPage extends StatelessWidget { + const SecurityPage({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData(color: CustomColors.primary), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(16, 20, 16, 16), + child: Center( + child: Column( + children: [ + const Spacer(), + const Hero( + tag: 'flow-icon', + child: Icon( + Icons.fingerprint, + color: Colors.white, + size: 200, + ), + ), + const Spacer(), + const Text( + 'Deine Sicherheit kommt an erster Stelle', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontSize: 25, + fontWeight: FontWeight.bold), + ), + const SizedBox( + height: 30, + ), + const Text( + 'Schütze dein Konto mit der biometrischen Erkennung deines Geräts oder lege einen Code fest.', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontSize: 18, + fontWeight: FontWeight.bold), + ), + const Spacer(), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () async { + bool isAuthenticated = + await AuthService.authenticateWithBiometrics(); + if (isAuthenticated) { + // ignore: use_build_context_synchronously + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => NotificationsPage()), + ); + } + }, + child: const SizedBox( + height: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'App absichern', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + // const SizedBox( + // height: 10, + // ), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: CustomColors.secondary, + // ), + // onPressed: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (builder) => SecurityPage(), + // ), + // ); + // }, + // child: const SizedBox( + // height: 60, + // child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // 'Eigenen Code festlegen', + // style: TextStyle( + // color: Colors.white, + // fontSize: 22, + // ), + // ), + // ], + // ), + // ), + // ), + const Spacer( + flex: 2, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/start_page.dart b/frontend/app/lib/pages/start_page.dart new file mode 100644 index 0000000..4ed1dee --- /dev/null +++ b/frontend/app/lib/pages/start_page.dart @@ -0,0 +1,112 @@ +import 'package:app/pages/agb_page.dart'; +import 'package:app/pages/security_page.dart'; +import 'package:app/util/colors.dart'; +import 'package:flutter/material.dart'; + +class StartPage extends StatelessWidget { + const StartPage({super.key}); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData(color: CustomColors.primary), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(16, 20, 16, 16), + child: Column( + children: [ + Hero( + tag: 'flow-icon', + child: Image.asset( + 'assets/JPEG.jpg', + height: 180, + ), + ), + const SizedBox( + height: 30, + ), + const Text( + 'Hallo. Digitale Spuren\nentfernen\nper Knopfdruck.', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontWeight: FontWeight.bold, + letterSpacing: 2.0, + fontSize: 25, + ), + ), + const SizedBox( + height: 20, + ), + const Text( + 'Mit uns finden Sie Ihre Digitalen Spuren und können diese entfernen.', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontSize: 18, + ), + ), + const Spacer( + flex: 1, + ), + Hero( + tag: 'flow-button', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: CustomColors.primary, + ), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (builder) => SecurityPage(), + // builder: (builder) => SecurityPage(), + ), + ); + }, + child: const SizedBox( + height: 60, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Weiter', + style: TextStyle( + fontSize: 20, + ), + ), + ], + ), + ), + ), + ), + const Spacer( + flex: 1, + ), + const Text( + 'Mit der weiteren Nutzung stimmst du den folgenden Bedingungen zu:', + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'sans-serif', + fontSize: 16, + ), + ), + TextButton( + onPressed: () { + showDialog( + context: context, builder: (builder) => AgbPage()); + }, + child: Text( + 'AGB - Datenschutzerklärung', + textAlign: TextAlign.center, + style: TextStyle(color: CustomColors.primary), + )) + ], + ), + ), + ), + ); + } +} diff --git a/frontend/app/lib/pages/home_page.dart b/frontend/app/lib/pages_draft/home_page.dart similarity index 94% rename from frontend/app/lib/pages/home_page.dart rename to frontend/app/lib/pages_draft/home_page.dart index 1da69df..0774069 100644 --- a/frontend/app/lib/pages/home_page.dart +++ b/frontend/app/lib/pages_draft/home_page.dart @@ -1,7 +1,8 @@ import 'package:app/model/services/backend_service.dart'; import 'package:app/model/view_model/account_vm.dart'; -import 'package:app/pages/login_overlay.dart'; -import 'package:app/pages/persons_page.dart'; +import 'package:app/model/view_model/base_vm.dart'; +import 'package:app/pages_draft/login_overlay.dart'; +import 'package:app/pages_draft/persons_page.dart'; import 'package:app/widgets/background.dart'; import 'package:app/widgets/bottom_navigation.dart'; import 'package:app/widgets/bottom_navigation_item.dart'; @@ -153,7 +154,7 @@ class _HomePageState extends State { BottomNavigationItem( onPressed: () async { final navigator = Navigator.of(context); - if (await vm.isLoggedIn(context)) { + if (_loggedin) { navigator.push(MaterialPageRoute( builder: (builder) => const PersonsPage())); } else { @@ -179,10 +180,9 @@ class _HomePageState extends State { body: Padding( padding: const EdgeInsets.fromLTRB(16, 45, 16, 16), child: Center( - child: ChangeNotifierProvider( - create: (context) => AccountViewModel(), - child: - Consumer(builder: (context, value, child) { + child: ChangeNotifierProvider( + create: (context) => BaseViewModel(), + child: Consumer(builder: (context, value, child) { // _checkResponse(value.response); if (!widget.loggedOut) { _isLoggedIn(context); diff --git a/frontend/app/lib/pages/login_overlay.dart b/frontend/app/lib/pages_draft/login_overlay.dart similarity index 100% rename from frontend/app/lib/pages/login_overlay.dart rename to frontend/app/lib/pages_draft/login_overlay.dart diff --git a/frontend/app/lib/pages/person_details_page.dart b/frontend/app/lib/pages_draft/person_details_page.dart similarity index 100% rename from frontend/app/lib/pages/person_details_page.dart rename to frontend/app/lib/pages_draft/person_details_page.dart diff --git a/frontend/app/lib/pages/persons_page.dart b/frontend/app/lib/pages_draft/persons_page.dart similarity index 88% rename from frontend/app/lib/pages/persons_page.dart rename to frontend/app/lib/pages_draft/persons_page.dart index e16c89d..1f22ca9 100644 --- a/frontend/app/lib/pages/persons_page.dart +++ b/frontend/app/lib/pages_draft/persons_page.dart @@ -1,8 +1,8 @@ import 'package:app/model/apis/api_response.dart'; import 'package:app/model/services/backend_service.dart'; import 'package:app/model/view_model/persons_vm.dart'; -import 'package:app/pages/home_page.dart'; -import 'package:app/pages/person_details_page.dart'; +import 'package:app/pages_draft/home_page.dart'; +import 'package:app/pages_draft/person_details_page.dart'; import 'package:app/pb/person.pb.dart'; import 'package:app/util/validation.dart'; import 'package:app/widgets/background.dart'; @@ -24,24 +24,25 @@ class _PersonsPageState extends State { @override void initState() { super.initState(); - _init(); + // _init(); } - void _init() async { - _setLoading(true); - _loggedin = await BackendService.isLoggedIn; - _setLoading(false); - } + // void _init() async { + // _setLoading(true); + // _loggedin = await BackendService.isLoggedIn; + // _setLoading(false); + // } - void _setLoading(bool loading) { - setState(() { - _loading = loading; - }); - } + // void _setLoading(bool loading) { + // setState(() { + // _loading = loading; + // }); + // } void _checkResponse(ApiResponse response) { if (response.status == Status.ERROR && - response.message!.contains('unauthenticated')) { + (response.message!.contains('unauthenticated') || + response.message!.contains('blocked'))) { BackendService.logout(); Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute( @@ -52,7 +53,7 @@ class _PersonsPageState extends State { } } - bool _loading = true; + bool _loading = false; bool _loggedin = false; List persons = []; @@ -75,9 +76,11 @@ class _PersonsPageState extends State { list.add(TextButton( onPressed: () async { final Person per = await showPerson(context, person: p); - setState(() { - this.persons.add(per); - }); + if (!per.id.isZero && !persons.contains(per)) { + setState(() { + this.persons.add(per); + }); + } }, child: Card( shape: @@ -87,7 +90,7 @@ class _PersonsPageState extends State { padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 14), child: Row( children: [ - Container( + SizedBox( height: 40, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -127,7 +130,7 @@ class _PersonsPageState extends State { floatingActionButton: FloatingActionButton( onPressed: () async { final p = await showPerson(context); - if (!p.id.isZero) { + if (!p.id.isZero && !persons.contains(p)) { setState(() { persons.add(p); }); @@ -215,7 +218,9 @@ class _PersonsPageState extends State { child: Consumer( builder: (context, value, child) { _checkResponse(value.response); - listPersons(context); + if (persons.isEmpty) { + listPersons(context); + } return _loading ? const CircularProgressIndicator( color: Colors.grey, diff --git a/frontend/app/lib/util/colors.dart b/frontend/app/lib/util/colors.dart index 5c8d297..475a476 100644 --- a/frontend/app/lib/util/colors.dart +++ b/frontend/app/lib/util/colors.dart @@ -8,4 +8,12 @@ class CustomColors { static Color get success { return const Color.fromARGB(200, 55, 125, 55); } + + static Color get primary { + return const Color.fromARGB(255, 51, 217, 178); + } + + static Color get secondary { + return const Color.fromARGB(255, 52, 172, 224); + } } diff --git a/frontend/app/pubspec.lock b/frontend/app/pubspec.lock index 8d5d6cc..9d8b480 100644 --- a/frontend/app/pubspec.lock +++ b/frontend/app/pubspec.lock @@ -115,6 +115,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" flutter_test: dependency: "direct dev" description: flutter @@ -184,6 +192,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: "7e6c63082e399b61e4af71266b012e767a5d4525dd6e9ba41e174fd42d76e115" + url: "https://pub.dev" + source: hosted + version: "2.1.7" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: df4ccb3193525b8a60c78a5ca7bf188a47705bcf77bcc837a6b2cf6da64ae0e2 + url: "https://pub.dev" + source: hosted + version: "1.0.35" + local_auth_ios: + dependency: transitive + description: + name: local_auth_ios + sha256: "8293faf72ef0ac4710f209edd03916c2d4c1eeab0483bdcf9b2e659c2f7d737b" + url: "https://pub.dev" + source: hosted + version: "1.1.5" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: fc5bd537970a324260fda506cfb61b33ad7426f37a8ea5c461cf612161ebba54 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea" + url: "https://pub.dev" + source: hosted + version: "1.0.10" matcher: dependency: transitive description: @@ -224,6 +272,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + url: "https://pub.dev" + source: hosted + version: "2.1.6" pointycastle: dependency: transitive description: @@ -351,4 +407,4 @@ packages: version: "0.1.4-beta" sdks: dart: ">=3.1.4 <4.0.0" - flutter: ">=3.3.0" + flutter: ">=3.10.0" diff --git a/frontend/app/pubspec.yaml b/frontend/app/pubspec.yaml index 3f39504..928928a 100644 --- a/frontend/app/pubspec.yaml +++ b/frontend/app/pubspec.yaml @@ -28,6 +28,7 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: + local_auth: ^2.1.7 async: ^2.2.0 protobuf: ^3.0.0 collection: ^1.15.0-nullsafety.4 @@ -72,6 +73,8 @@ flutter: # To add assets to your application, add an assets section, like this: assets: + - assets/chat_bubbles.png + - assets/JPEG.jpg - lib/assets/logo_300x200.png - lib/assets/hero-pattern-300x200.png # - images/a_dot_burr.jpeg diff --git a/frontend/app/windows/flutter/generated_plugin_registrant.cc b/frontend/app/windows/flutter/generated_plugin_registrant.cc index 8b6d468..7407ddd 100644 --- a/frontend/app/windows/flutter/generated_plugin_registrant.cc +++ b/frontend/app/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + LocalAuthPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("LocalAuthPlugin")); } diff --git a/frontend/app/windows/flutter/generated_plugins.cmake b/frontend/app/windows/flutter/generated_plugins.cmake index b93c4c3..ef187dc 100644 --- a/frontend/app/windows/flutter/generated_plugins.cmake +++ b/frontend/app/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + local_auth_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST