diff --git a/GSOC/2024/BhavikMangla.md b/GSOC/2024/BhavikMangla.md deleted file mode 100644 index 0d93105..0000000 --- a/GSOC/2024/BhavikMangla.md +++ /dev/null @@ -1,67 +0,0 @@ -# Peer-to-Peer Messaging Application GSoC 2024 - -## Chosen Goals -1. Implement on-device user authentication for enhanced security. -2. Complete integration of RSA encryption to secure messaging. -3. Enable seamless sending and viewing of files, images, audio, and video. -4. Enhance the user interface to support intuitive file viewing. -5. Update project dependencies for improved performance and stability. - -## Project Overview -The Peer-to-Peer messaging application aims to create a decentralized messaging platform, eliminating reliance on -centralized servers vulnerable to privacy breaches. By leveraging device networking capabilities, the app ensures -robust communication even in disaster-prone or remote areas with weak cellular connectivity. - -## Detailed Progress and Achievements - -### Security Enhancements -- **User Authentication:** - - Implemented password and fingerprint locks for on-device user authentication using the `local_auth` package. - - Ensured secure access to the app, enhancing user privacy and data protection. - -- **RSA Encryption:** - - Integrated RSA encryption for secure messaging between connected clients. - - Utilized libraries like `rsa_encrypt`, `asn1lib`, `dart:typed_data`, `dart:convert`, and `pointycastle` for - key generation, encryption, and parsing. - - Stored and transmitted public and private keys securely using `flutter_secure_storage` and `flutter_nearby_connections`. - -### File Handling -- **File Sharing:** - - Implemented secure file sharing functionality for sending files, images, audio, and video between users. - - Ensured encryption of transmitted files to prevent unauthorized access. - - Used `file_picker`, `open_file_x`, `permission_handler`, and `path_provider` for file operations. - -- **File Viewing:** - - Developed a user-friendly UI for in-app file previews and viewing. - - Supported all file types for seamless user experience within the chat interface. - -### UI Enhancements -- **Chat Interface:** - - Enhanced the chat UI by adding date indicators and chat bubbles for a more intuitive messaging experience. - - Created a clean and organized UI specifically for viewing shared files within the chat. - -### Dependencies and Testing -- **Dependency Management:** - - Updated all project dependencies and packages to their latest versions. - - Ensured compatibility and stability across multiple devices and platforms through rigorous testing. - -## Next Steps -- **Finalize RSA Encryption for Files:** - - Complete the implementation of RSA encryption specifically for file sharing to bolster security. - -- **UI Refinements:** - - Continue refining the user interface based on user feedback to improve usability and aesthetics. - -- **Testing and Validation:** - - Conduct comprehensive testing to validate the app's security, performance, and user experience. - -- **Prepare for App Publication:** - - Prepare the app for publication on the Google Play Store and Apple App Store. - - Ensure compliance with all guidelines and requirements for app submission. - -## Conclusion -The progress achieved during GSoC 2024 has significantly enhanced the security, functionality, and user experience -of the Peer-to-Peer messaging application. By implementing robust authentication mechanisms, advanced encryption techniques, -and seamless file sharing capabilities, the app is well-positioned to offer users a secure and reliable communication platform. -Moving forward, the focus will be on finalizing remaining features, refining the UI, conducting thorough testing, and -preparing for app publication to reach a broader audience. diff --git a/GSOC/2024/Bhavik_Mangla.md b/GSOC/2024/Bhavik_Mangla.md new file mode 100644 index 0000000..27cb2d0 --- /dev/null +++ b/GSOC/2024/Bhavik_Mangla.md @@ -0,0 +1,94 @@ +## **GSOC AOSSIE 2024** + +## _OpenPeerChat - Peer to Peer Messaging App_ + +## Project Description +The OpenPeerChat app is a secure, peer-to-peer messaging platform designed to prioritize user privacy and data protection. Built using Flutter, it enables users to communicate and share files directly with one another without relying on centralized servers. The application will be hugely beneficial in disaster-prone areas or remote areas where the cellular connections are too weak to communicate through general messaging applications. The app emphasizes robust encryption, secure authentication methods and offer a seamless and user-friendly messaging experience making it an ideal choice for those who value confidentiality in their digital communications. + +## Chosen Idea: +- Implementation of RSA in messages. +- Enabling Sending files, images, audio and video. +- Make the UI suitable to view those files sent. +- Update dependencies. + +## **Updates:** +### User Authentication: +- Added a password lock and a fingerprint lock for on-device authentication of the user using the `local_auth` package. +- Ensured secure and seamless authentication methods to enhance user security. + +### Dependencies and Testing: +- Updated all dependencies and packages to the latest versions. +- Set the version and build number, and upgraded to the latest Kotlin version in `build.gradle`. +- Tested the app's functionality across multiple devices and platforms to ensure compatibility and stability. + +### RSA Encryption: +- Implemented Public and Private Key Generation for secure communications. +- Integrated RSA Encryption, and developed methods for encoding and parsing public/private keys to and from PEM format using libraries such as `asn1lib`, `dart:typed_data`, `dart:convert`, and `pointycastle`. +- Stored primary and public keys securely using `flutter_secure_storage`, `sqflite`, and `flutter_nearby_connections`. +- Shared encrypted public keys between users upon establishing a connection to ensure secure communication. +- Implemented the storage and transmission of encrypted messages in global cache and sqflite tables, decrypting them with the user's private key. +- Added RSA encryption specifically for file sharing to further enhance security. + +### Chat Functionality: +- Improved the Chat Page UI by adding dates and chat bubbles to make it visually similar to WhatsApp chats. (`bubble`) +- Developed a separate, clean UI for file viewing within the chat interface. + +### File Handling: +- Completed the implementation of file viewing, which supports all file types. +- Implemented secure file sharing and storing on device between users, ensuring that files are encrypted during transmission. (`file_picker`, `open_filex`, `permission_handler`, `path_provider`) +- Set a maximum limit for file sizes to ensure quick and efficient file transfers. + +### Additional Enhancements: +- Added a powerful search feature on the home screen, enabling users to quickly find and connect with others in All Chats and Devices pages. +- Enhanced the overall user experience by refining the UI and addressing visual bugs. +- Engaged in regular code reviews and optimizations to maintain code quality and performance. + + +## App Flow: + +- User Authentication: + Upon opening the app, users are prompted to authenticate using a password or fingerprint, ensuring secure access. + +- New User Setup: + New users are prompted to enter their name after successful authentication, establishing their identity within the app. + +- Home Screen: + After setup, users are taken to the home screen, which features a search bar to quickly find and connect with other users or devices. + +- Chat Interface: + The chat page displays conversations with dates and chat bubbles, offering a familiar and intuitive experience similar to WhatsApp. + +- File Viewing and Sharing: + Users can view and share files securely within the chat interface. File transfers are encrypted using RSA encryption, with a maximum file size limit to ensure efficiency. + +- Secure Communication: + RSA-encrypted messages are stored and transmitted securely, with public keys shared between users upon connection. + +## **Future Work:** +- Develop a robust notification system to alert users about new messages, file transfers, and other critical updates, ensuring timely and reliable communication. +- Add an upload progress indicator for larger file transfers, visible on both sender and receiver screens, to improve user experience during file sharing. +- Ensure that changes to a user's profile name are reflected in nearby devices, maintaining consistency in chat history and user identification. +- Verify and enhance cross-platform compatibility, ensuring seamless communication and functionality between Android and iOS devices, fostering a unified user experience across different platforms. +- Prepare for publishing the app on the Google Play Store and Apple App Store, including meeting all necessary guidelines and requirements for app submission. + + +## Demonstration Links +- Video: [OpenPeerChat GSOC 2024](https://drive.google.com/file/d/1cSx_MPT7jJ-pKTPfi6foHkJKkLGvqt3h/view?usp=sharing) +- APK: [OpenPeerChat App](https://drive.google.com/file/d/1Nlz8oKXRIaQC5KVznvr2fus-8CM9JZlv/view?usp=sharing) + + +## Merge Requests +https://github.com/AOSSIE-Org/OpenPeerChat-flutter/pull/21 +https://github.com/AOSSIE-Org/OpenPeerChat-flutter/pull/23 + +## Contributor Details +- Name: Bhavik Mangla +- GitHub: [bhavik-mangla](https://github.com/bhavik-mangla) +- Email: bhavikmangla1234@gmail.com +- LinkedIn: [bhavikmangla](https://www.linkedin.com/in/bhavikmangla/) +- Organization: [Australian Open Source Software Innovation and Education (AOSSIE)](https://aossie.org/) +- Project: [Resonate - Open Source Social Voice Platform](https://github.com/AOSSIE-Org/Resonate) + +## **Conclusion:** +The app has made tremendous strides in improving security, user experience, and overall functionality. By implementing advanced RSA encryption and secure authentication mechanisms, the foundation for safe and private communication has been firmly established. The chat interface has been refined with thoughtful enhancements, making conversations more visually appealing and easier to navigate. File handling capabilities have been expanded to support all file types, with secure sharing and storage features ensuring that user data is protected at every step. +Looking ahead, by introducing a notification system, refining the UI, and enhancing profile management, the app is poised to offer a robust, secure, and user-friendly environment. It will elevate the app’s performance and user customization options, ensuring it remains a secure and versatile tool for communication. \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index d2ffbff..70a1de5 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,3 +1,7 @@ +buildscript { + ext.kotlin_version = '2.0.10' +} + allprojects { repositories { google() diff --git a/android/settings.gradle b/android/settings.gradle index 536165d..9f1b135 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "com.android.application" version "7.3.0" apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false + id "org.jetbrains.kotlin.android" version "2.0.10" apply false } include ":app" diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index a02a2f8..61e51df 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( diff --git a/lib/classes/global.dart b/lib/classes/global.dart index 37ef50f..6af0a7b 100644 --- a/lib/classes/global.dart +++ b/lib/classes/global.dart @@ -83,6 +83,8 @@ class Global extends ChangeNotifier { Future decodeAndStoreFile(String encodedFile, String fileName) async { Uint8List fileBytes = base64.decode(encodedFile); + + //to send files encrypted using RSA // Uint8List fileData = rsaDecrypt(Global.myPrivateKey!, fileBytes); Directory documents ; diff --git a/lib/components/message_panel.dart b/lib/components/message_panel.dart index 02bf542..c5db219 100644 --- a/lib/components/message_panel.dart +++ b/lib/components/message_panel.dart @@ -34,6 +34,8 @@ class _MessagePanelState extends State { return Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( + //multiline text field + maxLines: null, controller: myController, decoration: InputDecoration( icon: const Icon(Icons.person), @@ -112,9 +114,50 @@ class _MessagePanelState extends State { myController.clear(); } + /// This function is used to navigate to the file preview page and check the file size. void _navigateToFilePreviewPage(BuildContext context) async { + //max size of file is 30 MB + double sizeKbs = 0; + const int maxSizeKbs = 30 * 1024; FilePickerResult? result = await FilePicker.platform.pickFiles(); + if(result != null) { + sizeKbs = result.files.single.size / 1024; + } + + if (sizeKbs > maxSizeKbs) { + if (!context.mounted) return; + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('File Size Exceeded'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + //file size in MB + title: Text('File Size: ${(sizeKbs / 1024).ceil()} MB'), + subtitle: const Text( + 'File size should not exceed 30 MB'), + ), + ], + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Close'), + ), + ], + ); + }, + ); + return; + } + +//this function is used to open the file preview dialog if (result != null) { setState(() { _selectedFile = File(result.files.single.path!); @@ -129,11 +172,12 @@ class _MessagePanelState extends State { mainAxisSize: MainAxisSize.min, children: [ ListTile( + title: Text('File Name: ${_selectedFile.path .split('/') - .last}'), + .last}', overflow: TextOverflow.ellipsis,), subtitle: Text( - 'File Size: ${_selectedFile.lengthSync()} bytes'), + 'File Size: ${(sizeKbs / 1024).floor()} MB'), ), ElevatedButton( onPressed: () => FilePreview.openFile(_selectedFile.path), @@ -167,6 +211,7 @@ class _MessagePanelState extends State { } +/// This function is used to send the file message. void _sendFileMessage(BuildContext context, File file) async{ var msgId = nanoid(21); diff --git a/lib/main.dart b/lib/main.dart index bb2629a..67ce4fc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,8 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_nearby_connections_example/pages/home_page.dart'; +import 'package:flutter_nearby_connections_example/pages/auth_fail.dart'; +import 'package:flutter_nearby_connections_example/pages/profile.dart'; +import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; import 'classes/global.dart'; import 'encyption/key_storage.dart'; @@ -53,8 +56,48 @@ class MyApp extends StatelessWidget { } } + +Future _authenticate(BuildContext context) async { + final LocalAuthentication auth = LocalAuthentication(); + bool authenticated = false; + + try { + authenticated = await auth.authenticate( + localizedReason: 'Please authenticate to proceed', + options: const AuthenticationOptions( + stickyAuth: true, + sensitiveTransaction: true, + ), + ); + } catch (e) { + if (kDebugMode) { + print(e); + } + } + if (!context.mounted) return; + if (authenticated) { + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const Profile(onLogin: true)), + ); + } else { + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => AuthFailedPage(onRetry: () => _authenticate(context))), + ); + } +} + Route generateRoute(RouteSettings settings) { return MaterialPageRoute( - builder: (_) => const HomePage(), + builder: (context) { + _authenticate(context); + return const Scaffold( + body: Center( + child: CircularProgressIndicator(), + ), + ); + }, ); } + diff --git a/lib/p2p/adhoc_housekeeping.dart b/lib/p2p/adhoc_housekeeping.dart index 8ece80c..77b0ffe 100644 --- a/lib/p2p/adhoc_housekeeping.dart +++ b/lib/p2p/adhoc_housekeeping.dart @@ -148,11 +148,12 @@ void broadcast(BuildContext context) async { File file = File(message['filePath']); Uint8List encryptedBytes = await file.readAsBytes(); - // // Encrypt the message + //to send the file encrypted with the RSA + // Encrypt the message // Uint8List encryptedMessage = rsaEncrypt(publicKey, encryptedBytes); - // // Encode the message to base64 + // Encode the message to base64 // String encodedMessage = base64.encode(encryptedMessage); - // + String encodedMessage = base64.encode(encryptedBytes); @@ -297,6 +298,7 @@ void checkDevices(BuildContext context) { // The the protocol service. It receives the messages from the // dataReceivedSubscription service and decode it. void init(BuildContext context) async { + initiateNearbyService(); checkDevices(context); @@ -385,6 +387,7 @@ void initiateNearbyService() async { strategy: Strategy.P2P_CLUSTER, callback: (isRunning) async { if (isRunning) { + startAdvertising(); startBrowsing(); diff --git a/lib/pages/auth_fail.dart b/lib/pages/auth_fail.dart new file mode 100644 index 0000000..b0850aa --- /dev/null +++ b/lib/pages/auth_fail.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class AuthFailedPage extends StatelessWidget { + final VoidCallback onRetry; + + const AuthFailedPage({Key? key, required this.onRetry}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Authentication Failed'), + ), + body: Center( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Authentication didn\'t succeed.\nPlease try again.', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18), + ), + const SizedBox(height: 20), + ElevatedButton( + onPressed: onRetry, + child: const Text('Try Again'), + ), + ], + ), + ), + ), + ); + } +} + diff --git a/lib/pages/chat_list_screen.dart b/lib/pages/chat_list_screen.dart index 38cbf66..9fe4289 100644 --- a/lib/pages/chat_list_screen.dart +++ b/lib/pages/chat_list_screen.dart @@ -17,11 +17,38 @@ class ChatListScreen extends StatefulWidget { class _ChatListScreenState extends State { bool isLoading = false; List conversers = []; + List filteredConversers = []; + TextEditingController searchController = TextEditingController(); + + // In the init state, we need to update the cache everytime. @override void initState() { super.initState(); readAllUpdateCache(); + searchController.addListener(_filterConversers); + } + + + @override + void dispose() { + searchController.removeListener(_filterConversers); + searchController.dispose(); + super.dispose(); + } + + + void _filterConversers() { + setState(() { + if (searchController.text.isEmpty) { + filteredConversers = conversers; + } else { + filteredConversers = conversers + .where((converser) => + converser.toLowerCase().contains(searchController.text.toLowerCase())) + .toList(); + } + }); } @override @@ -34,11 +61,15 @@ class _ChatListScreenState extends State { Provider.of(context).conversations.forEach((key, value) { conversers.add(key); }); + if (searchController.text.isEmpty) { + filteredConversers = conversers; + } return Column( children: [ Padding( padding: const EdgeInsets.only(top: 16, left: 16, right: 16), child: TextField( + controller: searchController, decoration: InputDecoration( hintText: "Search...", hintStyle: TextStyle(color: Colors.grey.shade600), @@ -51,32 +82,33 @@ class _ChatListScreenState extends State { fillColor: Colors.grey.shade100, contentPadding: const EdgeInsets.all(8), enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - borderSide: BorderSide(color: Colors.grey.shade100)), + borderRadius: BorderRadius.circular(20), + borderSide: BorderSide(color: Colors.grey.shade100), + ), ), ), ), - Expanded( - child: ListView.builder( - itemCount: conversers.length, - shrinkWrap: true, - itemBuilder: (context, index) { - return ListTile( - title: Text(conversers[index]), - onTap: () { - // Whenever tapped on the Device tile, it navigates to the - // chatpage - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ChatPage( - converser: conversers[index], - ), - ), - ); - }, - ); - }), + Expanded( + child: ListView.builder( + itemCount: filteredConversers.length, + shrinkWrap: true, + itemBuilder: (context, index) { + return ListTile( + title: Text(filteredConversers[index]), + onTap: () { + // Navigate to the chat page + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatPage( + converser: filteredConversers[index], + ), + ), + ); + }, + ); + }, + ), ) ], ); diff --git a/lib/pages/chat_page.dart b/lib/pages/chat_page.dart index 77ce43f..33a2518 100644 --- a/lib/pages/chat_page.dart +++ b/lib/pages/chat_page.dart @@ -67,7 +67,7 @@ class ChatPageState extends State { return Scaffold( appBar: AppBar( - title: Text('Chat with ${widget.converser}'), + title: Text(widget.converser), ), body: Column( children: [ @@ -154,11 +154,14 @@ class ChatPageState extends State { return Row( mainAxisSize: MainAxisSize.min, children: [ - Text( - fileName, - style: const TextStyle( - // fontWeight: FontWeight.bold, - color: Colors.black87, + Flexible( + child: Text( + fileName, + style: const TextStyle( + color: Colors.black87, + ), + overflow: TextOverflow.visible, + ), ), IconButton( diff --git a/lib/pages/device_list_screen.dart b/lib/pages/device_list_screen.dart index aa86472..a1a5f92 100644 --- a/lib/pages/device_list_screen.dart +++ b/lib/pages/device_list_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_nearby_connections/flutter_nearby_connections.dart'; import 'package:provider/provider.dart'; import '../classes/global.dart'; @@ -28,19 +29,49 @@ class _DevicesListScreenState extends State { bool isLoading = false; + TextEditingController searchController = TextEditingController(); + List filteredDevices = []; + + @override void initState() { super.initState(); + searchController.addListener(_filterDevices); } + @override + void dispose() { + searchController.removeListener(_filterDevices); + searchController.dispose(); + super.dispose(); + } + + void _filterDevices() { + setState(() { + if (searchController.text.isEmpty) { + filteredDevices = Provider.of(context, listen: false).devices; + } else { + filteredDevices = Provider.of(context, listen: false) + .devices + .where((device) => device.deviceName.toLowerCase().contains(searchController.text.toLowerCase())) + .toList(); + } + }); + } + + @override Widget build(BuildContext context) { + if (filteredDevices.isEmpty && searchController.text.isEmpty) { + filteredDevices = Provider.of(context).devices; + } return SingleChildScrollView( child: Column( children: [ Padding( padding: const EdgeInsets.only(top: 16, left: 16, right: 16), child: TextField( + controller: searchController, decoration: InputDecoration( hintText: "Search...", hintStyle: TextStyle(color: Colors.grey.shade600), @@ -60,7 +91,7 @@ class _DevicesListScreenState extends State { ), ListView.builder( // Builds a screen with list of devices in the proximity - itemCount: Provider.of(context).devices.length, + itemCount: filteredDevices.length, shrinkWrap: true, itemBuilder: (context, index) { // Getting a device from the provider @@ -76,11 +107,14 @@ class _DevicesListScreenState extends State { // to connect/disconnect with any device onTap: () => connectToDevice(device), child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: getButtonColor(device.state), + ), margin: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.all(8.0), height: 35, width: 100, - color: getButtonColor(device.state), child: Center( child: Text( getButtonStateName(device.state), diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart deleted file mode 100644 index 684f524..0000000 --- a/lib/pages/home_page.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:local_auth/local_auth.dart'; -import 'profile.dart'; - -class HomePage extends StatefulWidget { - const HomePage({Key? key}) : super(key: key); - - @override - State createState() => _HomePageState(); -} - -class _HomePageState extends State { - late final LocalAuthentication auth; - bool _supportState = false; - - @override - void initState() { - super.initState(); - auth = LocalAuthentication(); - auth - .isDeviceSupported() - .then((isSupported) => setState(() => _supportState = isSupported)); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Authentication'), - ), - body: Center( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (_supportState) - const Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: Text( - 'Authentication is supported', - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18), - ), - ), - ElevatedButton( - onPressed: _supportState ? _authenticate : _authenticate2, - child: const Text('Authenticate'), - ), - ], - ), - ), - ), - ); - } - Future _authenticate2() async { - if (kDebugMode) { - print('Authentication is not supported'); - } - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const Profile(onLogin: true), - ), - ); - } - - Future _authenticate() async { - try { - bool authenticated = await auth.authenticate( - localizedReason: 'Authenticate for access', - options: const AuthenticationOptions( - stickyAuth: true, - sensitiveTransaction: true, - ), - ); - if (kDebugMode) { - print(authenticated); - } - if (authenticated) { - if (mounted) { - Navigator.pushReplacement( - context, - MaterialPageRoute( - builder: (context) => const Profile(onLogin: true), - ), - ); - } - } - } catch (e) { - if (kDebugMode) { - print(e); - } - } - } -} diff --git a/lib/pages/home_screen.dart b/lib/pages/home_screen.dart index fc2775b..ea87b16 100644 --- a/lib/pages/home_screen.dart +++ b/lib/pages/home_screen.dart @@ -60,10 +60,10 @@ class _HomeScreenState extends State { child: Scaffold( key: Global.scaffoldKey, appBar: AppBar( - title: const Text("P2P Messaging - AOSSIE"), + title: const Text("AOSSIE"), actions: [ IconButton( - icon: const Icon(Icons.settings), + icon: const Icon(Icons.person), onPressed: () { Navigator.push( context, diff --git a/lib/pages/profile.dart b/lib/pages/profile.dart index 9bb985d..6e344e7 100644 --- a/lib/pages/profile.dart +++ b/lib/pages/profile.dart @@ -87,9 +87,9 @@ class _ProfileState extends State { replacement: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Text("Your Username will be your name+$customLengthId"), + Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(10.0), child: TextFormField( controller: myName, decoration: const InputDecoration( @@ -100,8 +100,8 @@ class _ProfileState extends State { ), validator: (String? value) { return (value != null && - value.contains('@') && - value.length > 3) + value.contains('@') && + value.length > 3) ? 'Do not use the @ char and name length should be greater than 3' : null; }, @@ -127,4 +127,4 @@ class _ProfileState extends State { ), ); } -} +} \ No newline at end of file diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 35ac0be..d0e7f79 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,10 @@ #include "generated_plugin_registrant.h" -#include +#include void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) flutter_secure_storage_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStoragePlugin"); - flutter_secure_storage_plugin_register_with_registrar(flutter_secure_storage_registrar); + 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); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index af79c3c..b29e9ba 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,7 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST - flutter_secure_storage + flutter_secure_storage_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index eefcc6d..14cd431 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,11 +5,15 @@ import FlutterMacOS import Foundation +import flutter_secure_storage_macos +import local_auth_darwin import path_provider_foundation import shared_preferences_foundation import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + FLALocalAuthPlugin.register(with: registry.registrar(forPlugin: "FLALocalAuthPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/pubspec.yaml b/pubspec.yaml index 0b6c780..b3040f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,31 +8,33 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: sdk: '>=2.12.0 <3.0.0' +version: 1.0.0+0 + dependencies: flutter: sdk: flutter path: any - flutter_styled_toast: ^2.0.0 - flutter_nearby_connections: ^1.0.11 - cupertino_icons: ^1.0.2 + flutter_styled_toast: ^2.2.1 + flutter_nearby_connections: ^1.1.2 + cupertino_icons: ^1.0.8 bubble: ^1.2.1 nanoid: ^1.0.0 - sqflite: ^2.0.0+3 + sqflite: ^2.3.3+1 intl: ^0.19.0 - pointycastle: ^3.0.1 - shared_preferences: ^2.0.15 - provider: ^6.0.3 - flutter_secure_storage: + pointycastle: ^3.9.1 + shared_preferences: ^2.3.2 + provider: ^6.1.2 + flutter_secure_storage: ^9.2.2 encrypt: ^5.0.3 - asn1lib: - local_auth: - file_picker: - open_filex: ^4.4.0 + asn1lib: ^1.5.3 + local_auth: ^2.3.0 + file_picker: ^8.1.2 + open_filex: ^4.5.0 permission_handler: ^11.3.1 - path_provider: ^2.1.2 + path_provider: ^2.1.4 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: flutter_test: sdk: flutter diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 09406a7..16383da 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); LocalAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalAuthPlugin")); PermissionHandlerWindowsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ec8f02e..7badb8c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_windows local_auth_windows permission_handler_windows )