diff --git a/.DS_Store b/.DS_Store index 689bda0..5bf01bd 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/nexuschat/android/app/src/main/AndroidManifest.xml b/nexuschat/android/app/src/main/AndroidManifest.xml index 4d95412..f0ef625 100644 --- a/nexuschat/android/app/src/main/AndroidManifest.xml +++ b/nexuschat/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ + { final ScrollController _scrollController = ScrollController(); final FocusNode _focusNode = FocusNode(); - List> messages = []; + List> messages = []; String? expediteur; late String destinataire; int idConversation = 0; @@ -133,6 +134,45 @@ class _ChatScreenState extends State { } } + Future> _chiffrerMessage(String message) async { + final uri = + Uri.parse('https://nexuschat.derickexm.be/messages/crypt_message/') + .replace(queryParameters: {'message': message}); + final response = await http.post(uri); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + print("Chiffrement → encrypted_message: ${data['encrypted_message']}"); + print("Chiffrement → key: ${data['key']}"); + return { + 'encrypted_message': data['encrypted_message'] ?? message, + 'key': data['key'] ?? '' + }; + } else { + print("Erreur chiffrement: ${response.body}"); + return {'encrypted_message': message, 'key': ''}; + } + } + + Future _dechiffrerMessage(String encryptedMessage, String key) async { + final uri = + Uri.parse('https://nexuschat.derickexm.be/messages/uncrypt_message/'); + final response = await http.post( + uri, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'encrypted_message': encryptedMessage, + 'key': key, + }), + ); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + return data['decrypted_message'] ?? encryptedMessage; + } else { + print("Erreur déchiffrement: ${response.body}"); + return encryptedMessage; + } + } + Future _fetchMessages() async { if (idConversation <= 0) return; try { @@ -144,15 +184,24 @@ class _ChatScreenState extends State { final jsonResponse = jsonDecode(response.body); if (jsonResponse.containsKey('messages')) { final List messagesList = jsonResponse['messages']; + final decryptedMessages = + await Future.wait(messagesList.map((msg) async { + final isMe = msg['expediteur'].toString() == expediteur; + + final encrypted = msg['messages'].toString(); + final cle = msg['key']?.toString() ?? ''; + final texte = await _dechiffrerMessage(encrypted, cle); + return { + 'sender': msg['expediteur'].toString(), + 'text': texte, + 'encrypted': msg['messages'].toString(), + 'timestamp': msg['sent_at'].toString(), + 'key': msg['key']?.toString() ?? '', + 'type': msg['type'] ?? 'text' + }; + })); setState(() { - messages = messagesList.map((msg) { - bool isMe = msg['expediteur'].toString() == expediteur; - return { - 'sender': msg['expediteur'].toString(), - 'text': msg['messages'].toString(), - 'timestamp': msg['sent_at'].toString(), - }; - }).toList(); + messages = decryptedMessages; _isInitialLoading = false; }); _scrollToBottom(); @@ -163,6 +212,31 @@ class _ChatScreenState extends State { } } + Future _supprimerMessage(Map message) async { + try { + final uri = Uri.parse( + 'https://nexuschat.derickexm.be/messages/messages/delete_message/'); + final response = await http.post( + uri, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'expediteur': expediteur, + 'id_conversation': idConversation, + 'message': message['encrypted'], + 'key': message['key'], + }), + ); + if (response.statusCode == 200) { + print("✅ Message supprimé"); + _fetchMessages(); // refresh + } else { + print("❌ Erreur suppression: ${response.body}"); + } + } catch (e) { + print("❌ Erreur _supprimerMessage: $e"); + } + } + Future _loadExpediteur() async { SharedPreferences prefs = await SharedPreferences.getInstance(); String? expediteurEmail = @@ -178,6 +252,7 @@ class _ChatScreenState extends State { setState(() { expediteur = jsonResponse['username']; }); + print("📦 Chargement expediteur : $expediteur"); } } } catch (e) { @@ -194,21 +269,41 @@ class _ChatScreenState extends State { } Future sendMessage(String message) async { + print("🧪 Appel à sendMessage()..."); + print("🔍 expediteur: $expediteur"); if (expediteur == null || message.trim().isEmpty) return; final now = DateTime.now(); + final cryptoData = await _chiffrerMessage(message.trim()); + print("Résultat chiffrement : $cryptoData"); + final encryptedMessage = cryptoData['encrypted_message'] ?? ''; + final key = cryptoData['key'] ?? ''; + // Ajout du texte en clair + final plainText = _controller.text.trim(); + if (key == null || key.isEmpty) { + print('❌ Clé de chiffrement manquante. Message non envoyé.'); + return; + } + setState(() { - messages.add({ - 'sender': expediteur!, - 'text': message.trim(), - 'timestamp': now.toIso8601String(), - }); + messages = List>.from(messages) + ..add({ + 'sender': expediteur ?? '', + 'text': plainText, + 'encrypted': encryptedMessage, + 'timestamp': now.toIso8601String(), + 'key': key, + 'type': 'text' + }); }); _controller.clear(); _updateButtonState(); _scrollToBottom(); + print("✉️ Envoi du message chiffré : $encryptedMessage"); + print("🔑 Clé : $key"); + try { final response = await http.post( Uri.parse('https://nexuschat.derickexm.be/messages/send_message/'), @@ -216,9 +311,12 @@ class _ChatScreenState extends State { body: jsonEncode({ 'expediteur': expediteur, 'destinataire': destinataire, - 'message': message.trim(), - 'sent_at': now.toIso8601String(), + 'message': encryptedMessage, + // Correction : horodatage en heure locale (Belgique) + 'timestamp': DateTime.now().toIso8601String(), 'id_conversation': idConversation, + // Correction : forcer 'key' non vide + 'key': key.isNotEmpty ? key : 'test' }), ); if (response.statusCode == 200) { @@ -239,6 +337,66 @@ class _ChatScreenState extends State { } } + Future _sendGif(String gifUrl) async { + if (expediteur == null || gifUrl.isEmpty) return; + print('📤 Préparation à l’envoi du GIF :'); + print(' ↪️ URL : $gifUrl'); + + final nowUtcIso = DateTime.now().toIso8601String(); + // Désactivation du chiffrement pour les GIFs + final encryptedMessage = gifUrl; + final key = 'test'; + print(' 🔐 Encrypted : $encryptedMessage'); + print(' 🔑 Key : $key'); + print(' 💬 ID conversation : $idConversation'); + setState(() { + messages = List>.from(messages) + ..add({ + 'sender': expediteur ?? '', + 'text': gifUrl, + 'encrypted': encryptedMessage, + 'timestamp': nowUtcIso, + 'key': key, + 'type': 'gif' + }); + }); + _scrollToBottom(); + + final body = jsonEncode({ + 'expediteur': expediteur, + 'destinataire': destinataire, + 'message': encryptedMessage, + 'timestamp': nowUtcIso, + 'id_conversation': idConversation, + 'key': key, + 'type': 'gif' + }); + print("📦 Corps envoyé à l’API :"); + print(" expediteur : ${expediteur}"); + print(" destinataire : ${destinataire}"); + print(" message : $encryptedMessage"); + print(" key : $key"); + print(" timestamp : $nowUtcIso"); + print(" id_conversation: $idConversation"); + print(" type : gif"); + print("🔒 Longueur message : ${encryptedMessage.length}"); + try { + final response = await http.post( + Uri.parse('https://nexuschat.derickexm.be/messages/send_message/'), + headers: {'Content-Type': 'application/json'}, + body: body, + ); + + if (response.statusCode != 200) { + print('Erreur envoi GIF : ${response.body}'); + } else { + print('✅ GIF envoyé avec succès.'); + } + } catch (e) { + print('Erreur réseau envoi GIF : $e'); + } + } + void _scrollToBottom() { WidgetsBinding.instance.addPostFrameCallback((_) { if (_scrollController.hasClients) { @@ -255,8 +413,20 @@ class _ChatScreenState extends State { print('Sélectionner une photo'); } - void _selectGif() { - print('Sélectionner un GIF'); + Future _selectGif() async { + GiphyLocale? fr; + fr ??= GiphyLocale.fromContext(context); + + final config = GiphyUIConfig( + apiKey: 'qG62ngUKbr66l2jVPcDGulJW1RbZy5xI', + ); + final result = + await showGiphyPicker(context, config, locale: GiphyLocale.fr); + + if (result != null) { + print("GIF sélectionné : ${result.url}"); + _sendGif(result.url); + } } @override @@ -308,19 +478,64 @@ class _ChatScreenState extends State { color: Colors.grey[700], ), ), - Container( - margin: const EdgeInsets.only(top: 2), - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: isMe ? Colors.orange : Colors.grey[300], - borderRadius: BorderRadius.circular(10), - ), - child: Text( - message['text'] ?? '', - style: TextStyle( - color: isMe ? Colors.white : Colors.black, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: GestureDetector( + onLongPress: isMe + ? () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text( + "Supprimer le message ?"), + actions: [ + TextButton( + child: Text("Annuler"), + onPressed: () => + Navigator.of(context) + .pop(), + ), + TextButton( + child: Text("Supprimer"), + onPressed: () { + Navigator.of(context) + .pop(); + _supprimerMessage( + message); + }, + ), + ], + ); + }, + ); + } + : null, + child: Container( + margin: const EdgeInsets.only(top: 2), + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: isMe + ? Colors.orange + : Colors.grey[300], + borderRadius: BorderRadius.circular(10), + ), + child: message['type'] == 'gif' + ? Image.network(message['text'] ?? '') + : Text( + message['text'] ?? '', + style: TextStyle( + color: isMe + ? Colors.white + : Colors.black, + ), + ), + ), + ), ), - ), + ], ), if (formattedTime.isNotEmpty) Padding( @@ -339,51 +554,80 @@ class _ChatScreenState extends State { ), Padding( padding: const EdgeInsets.all(8.0), - child: Row( + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: TextField( - controller: _controller, - focusNode: _focusNode, - style: TextStyle(fontSize: 16), - cursorColor: Colors.orange, - decoration: InputDecoration( - hintText: 'Entrez votre message...', - border: OutlineInputBorder(), - ), - minLines: 1, - maxLines: 5, - keyboardType: TextInputType.multiline, - textInputAction: TextInputAction.newline, - onChanged: (text) => _updateButtonState(), - onEditingComplete: () {}, - inputFormatters: [ - _EnterKeyFormatter( - onEnter: () { - if (_controller.text.trim().isNotEmpty) { - sendMessage(_controller.text); - _controller - .clear(); // 👈 Ajout explicite du clear ici - } - }, + Row( + children: [ + Expanded( + child: TextField( + controller: _controller, + focusNode: _focusNode, + style: TextStyle(fontSize: 16), + cursorColor: Colors.orange, + decoration: InputDecoration( + hintText: 'Entrez votre message...', + border: OutlineInputBorder(), + ), + minLines: 1, + maxLines: 5, + keyboardType: TextInputType.multiline, + textInputAction: TextInputAction.newline, + onChanged: (text) => _updateButtonState(), + onEditingComplete: () {}, + inputFormatters: [ + _EnterKeyFormatter( + onEnter: () { + if (_controller.text.trim().isNotEmpty) { + sendMessage(_controller.text); + _controller + .clear(); // 👈 Ajout explicite du clear ici + } + }, + ), + ], ), - ], + ), + SizedBox(width: 8), + Container( + decoration: BoxDecoration( + color: Colors.orange.shade100, // plus doux + borderRadius: BorderRadius.circular(12), + ), + child: IconButton( + icon: Icon(Icons.gif_box, + color: Colors.deepOrange, size: 28), + onPressed: _selectGif, + tooltip: 'GIF', + ), + ), + SizedBox(width: 5), + Container( + decoration: BoxDecoration( + color: Colors.orange, + shape: BoxShape.circle, + ), + child: IconButton( + icon: Icon(Icons.send, color: Colors.black), + onPressed: _isButtonEnabled + ? () { + sendMessage(_controller.text); + _controller.clear(); + _updateButtonState(); + } + : null, + ), + ), + SizedBox(width: 8), + ], + ), + Padding( + padding: const EdgeInsets.only(bottom: 4, top: 2), + child: Text( + "🔒 Messages chiffrés de bout en bout", + style: TextStyle(fontSize: 12, color: Colors.grey), ), ), - SizedBox(width: 8), - Container( - decoration: BoxDecoration( - color: Colors.orange, - shape: BoxShape.circle, - ), - child: IconButton( - icon: Icon(Icons.send, color: Colors.black), - onPressed: _isButtonEnabled - ? () => sendMessage(_controller.text) - : null, - ), - ), - SizedBox(width: 8), ], ), ), diff --git a/nexuschat/lib/contacts.dart b/nexuschat/lib/contacts.dart index cb3e472..9544b85 100644 --- a/nexuschat/lib/contacts.dart +++ b/nexuschat/lib/contacts.dart @@ -14,10 +14,12 @@ class Contacts extends StatefulWidget { class _ContactsState extends State with SingleTickerProviderStateMixin { List _contacts = []; + List _filteredContacts = []; List _demandes = []; List _users = []; List _filteredUsers = []; TextEditingController _searchController = TextEditingController(); + TextEditingController _contactSearchController = TextEditingController(); String? _userEmail; String? currentUser; @@ -28,6 +30,7 @@ class _ContactsState extends State super.initState(); _tabController = TabController(length: 3, vsync: this); _initUser(); + _contactSearchController.addListener(_filterContacts); } Future _initUser() async { @@ -66,7 +69,10 @@ class _ContactsState extends State ); if (response.statusCode == 200) { final data = json.decode(response.body); - setState(() => _contacts = data); + setState(() { + _contacts = data; + _filteredContacts = data; + }); } else { print("Erreur chargement contacts: ${response.statusCode}"); } @@ -119,6 +125,15 @@ class _ContactsState extends State }); } + void _filterContacts() { + final query = _contactSearchController.text.toLowerCase(); + setState(() { + _filteredContacts = _contacts + .where((contact) => contact['contacts'].toLowerCase().contains(query)) + .toList(); + }); + } + Future _envoyerDemandeContact(String destinataire) async { if (destinataire == currentUser) { ScaffoldMessenger.of(context).showSnackBar( @@ -202,6 +217,47 @@ class _ContactsState extends State } } + Future _supprimerContact(String destinataire) async { + final confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Confirmer la suppression"), + content: Text( + "Voulez-vous vraiment supprimer $destinataire de vos contacts ?"), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text("Annuler"), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text("Supprimer"), + ), + ], + ), + ); + + if (confirm != true) return; + + try { + final response = await http.post( + Uri.parse('https://nexuschat.derickexm.be/contacts/supprimer_contact'), + headers: {"Content-Type": "application/json"}, + body: jsonEncode({"owner": currentUser, "contact": destinataire}), + ); + if (response.statusCode == 200) { + await _loadContacts(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Contact $destinataire supprimé")), + ); + print("Status: ${response.statusCode}"); + print("Body: ${response.body}"); + } + } catch (e) { + print("Erreur : $e"); + } + } + Future _getEtatRelation(String target) async { final response = await http.get( Uri.parse( @@ -234,27 +290,53 @@ class _ContactsState extends State children: [ _contacts.isEmpty ? Center(child: Text("Aucun contact")) - : ListView.builder( - itemCount: _contacts.length, - itemBuilder: (context, index) { - final user = _contacts[index]['contacts']; - return Card( - child: ListTile( - title: Text(user), - leading: Icon(Icons.person), - trailing: ElevatedButton( - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - ChatScreen(usernameExpediteur: user), - ), - ), - child: Text("Chat"), + : Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _contactSearchController, + decoration: InputDecoration( + labelText: "Rechercher dans mes contacts...", + prefixIcon: Icon(Icons.search), + border: OutlineInputBorder(), ), ), - ); - }, + ), + Expanded( + child: ListView.builder( + itemCount: _filteredContacts.length, + itemBuilder: (context, index) { + final user = _filteredContacts[index]['contacts']; + return Card( + child: ListTile( + title: Text(user), + leading: Icon(Icons.person), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatScreen( + usernameExpediteur: user), + ), + ), + child: Text("Chat"), + ), + IconButton( + icon: Icon(Icons.delete), + onPressed: () => _supprimerContact(user), + ), + ], + ), + ), + ); + }, + ), + ), + ], ), _demandes.isEmpty ? Center(child: Text("Aucune demande")) diff --git a/nexuschat/lib/inscription.dart b/nexuschat/lib/inscription.dart index 82c909e..288910a 100644 --- a/nexuschat/lib/inscription.dart +++ b/nexuschat/lib/inscription.dart @@ -42,6 +42,11 @@ class Inscription extends StatelessWidget { Future _API_inscription(BuildContext context) async { const String apiUrl = "https://nexuschat.derickexm.be/users/create_user"; + if (username.text.isEmpty || email.text.isEmpty || passwd.text.isEmpty) { + _showSnackBar(context, "Veuillez remplir tous les champs."); + return; + } + try { final response = await http.post( Uri.parse(apiUrl), diff --git a/nexuschat/lib/listechat.dart b/nexuschat/lib/listechat.dart index 55007a9..975dbdd 100644 --- a/nexuschat/lib/listechat.dart +++ b/nexuschat/lib/listechat.dart @@ -271,6 +271,12 @@ class Listechatstate extends State { style: const TextStyle( fontWeight: FontWeight.bold), ), + // trailing: IconButton( + // icon: Icon(Icons.delete), + // color: Colors.red, + // onPressed: () => + // _supprimerConversation(destinataire), + // ), // // subtitle: Column( // crossAxisAlignment: CrossAxisAlignment.start, diff --git a/nexuschat/lib/login.dart b/nexuschat/lib/login.dart index 424c991..c7c4d39 100644 --- a/nexuschat/lib/login.dart +++ b/nexuschat/lib/login.dart @@ -78,7 +78,6 @@ class Login extends StatelessWidget { if (response.statusCode == 200) { print("Connexion réussie"); - // Stocker l'email de l'utilisateur final prefs = await SharedPreferences.getInstance(); await prefs.setString('user_email', email); @@ -99,8 +98,7 @@ class Login extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(16.0), child: Container( - width: - 400, // Définition d'une largeur fixe pour un meilleur affichage + width: 400, padding: const EdgeInsets.all(16.0), decoration: BoxDecoration( border: Border.all(color: Colors.black, width: 2), @@ -159,6 +157,13 @@ class Login extends StatelessWidget { child: ElevatedButton( onPressed: () { FocusManager.instance.primaryFocus?.unfocus(); + + if (email.text.isEmpty || passwd.text.isEmpty) { + _showErrorDialog( + context, "Veuillez remplir tous les champs."); + return; + } + print("Email saisi : ${email.text}"); print("Mot de passe : ${passwd.text}"); checkCredentials(email.text, passwd.text); diff --git a/nexuschat/lib/menu.dart b/nexuschat/lib/menu.dart index 1d7a74c..01a3148 100644 --- a/nexuschat/lib/menu.dart +++ b/nexuschat/lib/menu.dart @@ -93,28 +93,6 @@ class _MenuState extends State { padding: const EdgeInsets.fromLTRB(15, 10, 10, 10), child: Column( children: [ - if (showEmailWarning) - Container( - padding: const EdgeInsets.all(10), - margin: const EdgeInsets.only(bottom: 10), - decoration: BoxDecoration( - color: Colors.amber[200], - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: const [ - Icon(Icons.warning_amber_rounded, color: Colors.black), - SizedBox(width: 10), - Expanded( - child: Text( - " Les emails de vérification sont momentanément indisponibles. Veuillez nous en excuser !", - style: TextStyle( - fontWeight: FontWeight.w600, color: Colors.red), - ), - ), - ], - ), - ), Expanded( child: Center( child: _widgetOptions.elementAt(_selectedIndex), diff --git a/nexuschat/pubspec.lock b/nexuschat/pubspec.lock index f79392c..567a6e4 100644 --- a/nexuschat/pubspec.lock +++ b/nexuschat/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -41,6 +49,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" + source: hosted + version: "0.3.5" clock: dependency: transitive description: @@ -110,14 +134,27 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_lints: - dependency: "direct dev" + flutter_giphy_picker: + dependency: "direct main" description: - name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + name: flutter_giphy_picker + sha256: "249841f086ab5b7200a2316eb2a0a773a813f696d822a856e7803f17df759e35" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "1.0.11" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c + url: "https://pub.dev" + source: hosted + version: "0.11.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -126,6 +163,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.26" + flutter_staggered_grid_view: + dependency: transitive + description: + name: flutter_staggered_grid_view + sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" + url: "https://pub.dev" + source: hosted + version: "0.7.0" flutter_test: dependency: "direct dev" description: flutter @@ -136,14 +181,22 @@ packages: description: flutter source: sdk version: "0.0.0" + focus_detector_v2: + dependency: transitive + description: + name: focus_detector_v2 + sha256: d4abc4c755ba894238ab92f42f6eee7ade78aa285199e112f45926c7053f90c6 + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" http: dependency: "direct main" description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" url: "https://pub.dev" source: hosted - version: "0.13.6" + version: "1.4.0" http_parser: dependency: transitive description: @@ -168,6 +221,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" leak_tracker: dependency: transitive description: @@ -192,14 +253,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.dev" - source: hosted - version: "5.1.1" matcher: dependency: transitive description: @@ -469,6 +522,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" vm_service: dependency: transitive description: @@ -509,6 +570,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: dart: ">=3.6.0 <4.0.0" flutter: ">=3.27.0" diff --git a/nexuschat/pubspec.yaml b/nexuschat/pubspec.yaml index 34db463..5131720 100644 --- a/nexuschat/pubspec.yaml +++ b/nexuschat/pubspec.yaml @@ -30,11 +30,14 @@ environment: dependencies: flutter: sdk: flutter + # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 - http: ^0.13.6 + + flutter_giphy_picker: ^1.0.5 + http: ^1.4.0 adaptive_theme: ^3.6.0 url_launcher: ^6.3.0 intl: ^0.19.0 @@ -47,13 +50,10 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + flutter_launcher_icons: ^0.11.0 + - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^5.0.0 +flutter_lints: ^1.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -97,3 +97,8 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/to/font-from-package + +flutter_icons: + android: true + ios: true + image_path: "assets/logo.png" diff --git a/nexuschat/web/index.html b/nexuschat/web/index.html index 3fcc17e..8bd405a 100644 --- a/nexuschat/web/index.html +++ b/nexuschat/web/index.html @@ -19,7 +19,7 @@ - + @@ -30,7 +30,7 @@ - nexuschat + Nexuschat