From e727ac641ce77d566432c3a229efc660e15b0000 Mon Sep 17 00:00:00 2001 From: exmKrd Date: Tue, 22 Apr 2025 18:42:24 +0200 Subject: [PATCH] update --- .DS_Store | Bin 10244 -> 10244 bytes nexuschat/lib/chat.dart | 186 +++++++++++++--- nexuschat/lib/inscription.dart | 58 ++--- nexuschat/lib/listechat.dart | 73 ++++--- nexuschat/lib/login.dart | 22 ++ nexuschat/lib/menu.dart | 24 +++ nexuschat/lib/profil.dart | 202 +++++++++++++++++- nexuschat/macos/Podfile.lock | 29 +++ .../macos/Runner.xcodeproj/project.pbxproj | 98 ++++++++- .../contents.xcworkspacedata | 3 + nexuschat/web/index.html | 4 +- 11 files changed, 584 insertions(+), 115 deletions(-) create mode 100644 nexuschat/macos/Podfile.lock diff --git a/.DS_Store b/.DS_Store index 163a16c5ac5b8561ed265fb5fd7509e242b8d7bb..689bda06fa729cb59a0b8bee618a43fce7312339 100644 GIT binary patch delta 135 zcmZn(XbIS$DiF_YEX}~cz`~%%kj{|FP?DSP;*yk;p9B=+n1Ag-ywvq$j;Qh}c;yQ+ v41<&Na|?ia7#PGiFiegU6x%#YfR&NOo@0F~n731KDI2qWOT*?wiN*W?j6wf diff --git a/nexuschat/lib/chat.dart b/nexuschat/lib/chat.dart index cee7f04..cbae078 100644 --- a/nexuschat/lib/chat.dart +++ b/nexuschat/lib/chat.dart @@ -1,7 +1,6 @@ -// ✅ chat.dart (corrigé sans ChatApp) - import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; @@ -17,6 +16,9 @@ class ChatScreen extends StatefulWidget { class _ChatScreenState extends State { final TextEditingController _controller = TextEditingController(); + final ScrollController _scrollController = ScrollController(); + final FocusNode _focusNode = FocusNode(); + List> messages = []; String? expediteur; late String destinataire; @@ -45,6 +47,8 @@ class _ChatScreenState extends State { _pollingTimer.cancel(); _controller.removeListener(_updateButtonState); _controller.dispose(); + _focusNode.dispose(); + _scrollController.dispose(); super.dispose(); } @@ -144,12 +148,14 @@ class _ChatScreenState extends State { messages = messagesList.map((msg) { bool isMe = msg['expediteur'].toString() == expediteur; return { - 'sender': isMe ? 'me' : 'bot', + 'sender': msg['expediteur'].toString(), 'text': msg['messages'].toString(), + 'timestamp': msg['sent_at'].toString(), }; }).toList(); _isInitialLoading = false; }); + _scrollToBottom(); } } } catch (e) { @@ -183,16 +189,26 @@ class _ChatScreenState extends State { void _updateButtonState() { setState(() { - _isButtonEnabled = _controller.text.isNotEmpty; + _isButtonEnabled = _controller.text.trim().isNotEmpty; }); } Future sendMessage(String message) async { + if (expediteur == null || message.trim().isEmpty) return; + + final now = DateTime.now(); + setState(() { - messages.add({'sender': 'me', 'text': message}); + messages.add({ + 'sender': expediteur!, + 'text': message.trim(), + 'timestamp': now.toIso8601String(), + }); }); _controller.clear(); _updateButtonState(); + _scrollToBottom(); + try { final response = await http.post( Uri.parse('https://nexuschat.derickexm.be/messages/send_message/'), @@ -200,8 +216,8 @@ class _ChatScreenState extends State { body: jsonEncode({ 'expediteur': expediteur, 'destinataire': destinataire, - 'message': message, - 'timestamp': DateTime.now().toIso8601String(), + 'message': message.trim(), + 'sent_at': now.toIso8601String(), 'id_conversation': idConversation, }), ); @@ -209,8 +225,13 @@ class _ChatScreenState extends State { final jsonResponse = jsonDecode(response.body); if (jsonResponse.containsKey('reply')) { setState(() { - messages.add({'sender': 'bot', 'text': jsonResponse['reply']}); + messages.add({ + 'sender': destinataire, + 'text': jsonResponse['reply'], + 'timestamp': DateTime.now().toIso8601String(), + }); }); + _scrollToBottom(); } } } catch (e) { @@ -218,6 +239,26 @@ class _ChatScreenState extends State { } } + void _scrollToBottom() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + } + }); + } + + void _selectPhoto() { + print('Sélectionner une photo'); + } + + void _selectGif() { + print('Sélectionner un GIF'); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -236,27 +277,61 @@ class _ChatScreenState extends State { children: [ Expanded( child: ListView.builder( + controller: _scrollController, itemCount: messages.length, itemBuilder: (context, index) { final message = messages[index]; - final isMe = message['sender'] == 'me'; - return Align( + final isMe = message['sender'] == expediteur; + + // Formatage de l'heure + final time = + DateTime.tryParse(message['timestamp'] ?? ''); + final formattedTime = time != null + ? "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}" + : ''; + + return Container( alignment: isMe ? Alignment.centerRight : Alignment.centerLeft, - child: Container( - margin: const EdgeInsets.symmetric( - vertical: 5, horizontal: 10), - 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, + margin: const EdgeInsets.symmetric( + vertical: 4, horizontal: 8), + child: Column( + crossAxisAlignment: isMe + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + Text( + message['sender'] ?? '', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, + 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, + ), + ), + ), + if (formattedTime.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 2), + child: Text( + formattedTime, + style: TextStyle( + fontSize: 10, color: Colors.grey[600]), + ), + ), + ], ), ); }, @@ -269,19 +344,46 @@ class _ChatScreenState extends State { Expanded( child: TextField( controller: _controller, - decoration: const InputDecoration( - hintText: 'Écrire un message...', + 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 + } + }, + ), + ], ), ), - IconButton( - icon: const Icon(Icons.send), - onPressed: _isButtonEnabled - ? () => sendMessage(_controller.text) - : null, - color: _isButtonEnabled ? Colors.orange : 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), ], ), ), @@ -290,3 +392,25 @@ class _ChatScreenState extends State { ); } } + +// ✅ Formatter : Enter = envoi / Shift+Enter = saut de ligne +class _EnterKeyFormatter extends TextInputFormatter { + final VoidCallback onEnter; + + _EnterKeyFormatter({required this.onEnter}); + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { + if (newValue.text.length > oldValue.text.length && + newValue.text.endsWith('\n') && + !RawKeyboard.instance.keysPressed + .contains(LogicalKeyboardKey.shiftLeft) && + !RawKeyboard.instance.keysPressed + .contains(LogicalKeyboardKey.shiftRight)) { + onEnter(); + return const TextEditingValue(text: ''); // vide le champ après envoi + } + return newValue; + } +} diff --git a/nexuschat/lib/inscription.dart b/nexuschat/lib/inscription.dart index 80a89e2..82c909e 100644 --- a/nexuschat/lib/inscription.dart +++ b/nexuschat/lib/inscription.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; -import 'package:nexuschat/listechat.dart'; import 'package:nexuschat/login.dart'; class Inscription extends StatelessWidget { @@ -13,33 +12,33 @@ class Inscription extends StatelessWidget { final TextEditingController username = TextEditingController(); Future sendVerificationEmail(BuildContext context, String email) async { - final url = Uri.parse('https://nexuschat.derickexm.be/email/send_email/'); + final url = Uri.parse( + 'https://nexuschat.derickexm.be/email/send_email?email=$email'); try { final response = await http.post( url, - headers: {'Content-Type': 'application/json'}, - body: jsonEncode({ - "email": email, - }), + headers: {'Accept': 'application/json'}, ); if (response.statusCode == 200) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Email de vérification envoyé avec succès!")), - ); + _showSnackBar(context, "Email de vérification envoyé avec succès!"); } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text("Impossible d'envoyer l'email de vérification.")), - ); + _showSnackBar(context, + "Impossible d'envoyer l'email de vérification. (${response.statusCode})"); + print("Réponse serveur : ${response.body}"); } } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Erreur de connexion à l'API: $e")), - ); + _showSnackBar(context, "Erreur de connexion à l'API."); + print("Erreur d'envoi email : $e"); } } + void _showSnackBar(BuildContext context, String message) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message)), + ); + } + Future _API_inscription(BuildContext context) async { const String apiUrl = "https://nexuschat.derickexm.be/users/create_user"; @@ -56,29 +55,20 @@ class Inscription extends StatelessWidget { if (response.statusCode == 200) { print("Inscription réussie !"); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Inscription réussie !")), - ); + _showSnackBar(context, "Inscription réussie !"); + sendVerificationEmail(context, email.text); - // Appel de la fonction pour envoyer l'email de confirmation - await sendVerificationEmail(context, email.text); - - // Redirection vers la page de login Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Login()), ); } else { print("Erreur : ${response.body}"); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Erreur lors de l'inscription")), - ); + _showSnackBar(context, "Erreur lors de l'inscription"); } } catch (e) { print("Erreur réseau : $e"); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Problème de connexion au serveur")), - ); + _showSnackBar(context, "Problème de connexion au serveur"); } } @@ -106,8 +96,6 @@ class Inscription extends StatelessWidget { const Text("S'inscrire sur NexusChat", style: TextStyle(fontSize: 24)), const SizedBox(height: 20), - - // Champ Nom d'utilisateur SizedBox( width: 400, child: TextField( @@ -121,8 +109,6 @@ class Inscription extends StatelessWidget { ), ), const SizedBox(height: 20), - - // Champ Email SizedBox( width: 400, child: TextField( @@ -136,8 +122,6 @@ class Inscription extends StatelessWidget { ), ), const SizedBox(height: 20), - - // Champ Mot de passe SizedBox( width: 400, child: TextField( @@ -151,15 +135,11 @@ class Inscription extends StatelessWidget { ), ), const SizedBox(height: 30), - - // Bouton S'inscrire ElevatedButton( onPressed: () => _API_inscription(context), child: const Text("S'inscrire"), ), const SizedBox(height: 20), - - // Bouton Déjà inscrit ? ElevatedButton( onPressed: () { Navigator.push(context, diff --git a/nexuschat/lib/listechat.dart b/nexuschat/lib/listechat.dart index d3e5d32..55007a9 100644 --- a/nexuschat/lib/listechat.dart +++ b/nexuschat/lib/listechat.dart @@ -99,17 +99,15 @@ class Listechatstate extends State { if (response.statusCode == 200) { final data = json.decode(response.body); - if (data is Map && data.containsKey("conversations")) { - return List>.from(data["conversations"]); - } else { - setState(() { - errorMessage = "Format de réponse inattendu"; - }); - return []; + if (data is Map) { + if (data.containsKey("conversations")) { + return List>.from(data["conversations"]); + } else if (data.containsKey("exists") && data["exists"] == false) { + return []; + } } - } else { setState(() { - errorMessage = "Erreur serveur: ${response.statusCode}"; + errorMessage = "Format de réponse inattendu"; }); return []; } @@ -120,6 +118,9 @@ class Listechatstate extends State { }); return []; } + + // ✅ Ce return évite l'erreur "body might complete normally" + return []; } Future _refreshConversations() async { @@ -146,6 +147,7 @@ class Listechatstate extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( + automaticallyImplyLeading: false, title: const Text("Mes Conversations"), actions: [ IconButton( @@ -200,9 +202,21 @@ class Listechatstate extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text("Aucune conversation trouvée"), + const Icon(Icons.chat_bubble_outline, + size: 80, color: Colors.grey), const SizedBox(height: 20), - ElevatedButton( + const Text( + "Aucune conversation pour l’instant", + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 10), + const Text( + "Commencez une discussion avec vos contacts.", + style: TextStyle(color: Colors.grey), + ), + const SizedBox(height: 20), + ElevatedButton.icon( onPressed: () { Navigator.push( context, @@ -211,7 +225,8 @@ class Listechatstate extends State { ), ); }, - child: const Text("Démarrer une conversation"), + icon: const Icon(Icons.add_comment), + label: const Text("Démarrer une conversation"), ), ], ), @@ -234,13 +249,6 @@ class Listechatstate extends State { ? "conversation_${expediteur}_$rawId" : "conversation_${expediteur}_${destinataire}_$index"; - final lastMessage = - conv["last_message"] ?? "Aucun message"; - final timestamp = conv["created_at"] ?? "Inconnu"; - final formattedDate = formatTimestamp(timestamp); - final truncatedMessage = - truncateMessage(lastMessage, 40); - return Hero( tag: uniqueTag, child: Card( @@ -263,19 +271,20 @@ class Listechatstate extends State { style: const TextStyle( fontWeight: FontWeight.bold), ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(truncatedMessage), - Text( - formattedDate, - style: TextStyle( - fontSize: 12, - color: Colors.grey[600], - ), - ), - ], - ), + // + // subtitle: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text(truncatedMessage), + // Text( + // formattedDate, + // style: TextStyle( + // fontSize: 12, + // color: Colors.grey[600], + // ), + // ), + // ], + // ), onTap: () { Navigator.push( context, diff --git a/nexuschat/lib/login.dart b/nexuschat/lib/login.dart index 7e4ef8e..424c991 100644 --- a/nexuschat/lib/login.dart +++ b/nexuschat/lib/login.dart @@ -36,6 +36,27 @@ class Login extends StatelessWidget { ); } + Future sendAttemptLogin(String email) async { + final url = Uri.parse( + 'https://nexuschat.derickexm.be/email/send_login_attempt_email/?email=$email'); + + try { + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + ); + + if (response.statusCode != 200) { + print( + "Erreur lors de l'envoi de l'alerte de tentative de connexion : ${response.body}"); + } else { + print("Alerte de tentative de connexion envoyée à $email"); + } + } catch (e) { + print("Erreur de connexion lors de l'envoi de l'alerte : $e"); + } + } + Future checkCredentials(String email, String password) async { final url = Uri.parse('https://nexuschat.derickexm.be/users/check_credentials'); @@ -63,6 +84,7 @@ class Login extends StatelessWidget { Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => Menu())); + await sendAttemptLogin(email); } else { _showErrorDialog( context, "Nom d'utilisateur ou mot de passe incorrect"); diff --git a/nexuschat/lib/menu.dart b/nexuschat/lib/menu.dart index fd7c9e1..1d7a74c 100644 --- a/nexuschat/lib/menu.dart +++ b/nexuschat/lib/menu.dart @@ -14,12 +14,14 @@ class _MenuState extends State { int _selectedIndex = 0; String? _userDisplayName; String? _profilePictureURL; + bool showEmailWarning = true; static late List _widgetOptions; @override void initState() { super.initState(); + _widgetOptions = [ Listechat(), Setting(), @@ -91,6 +93,28 @@ 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/lib/profil.dart b/nexuschat/lib/profil.dart index ad55c12..06dab70 100644 --- a/nexuschat/lib/profil.dart +++ b/nexuschat/lib/profil.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; +import 'package:nexuschat/login.dart'; import 'package:shared_preferences/shared_preferences.dart'; late SharedPreferences prefs; @@ -109,6 +110,7 @@ class _ProfilState extends State { final data = jsonDecode(response.body); setState(() { _username = data['username']; + prefs.setString('username', _username!); }); } else { _showSnackBar("Impossible de récupérer le nom d'utilisateur."); @@ -124,6 +126,167 @@ class _ProfilState extends State { ); } + Future _ChangePassword() async { + final email = prefs.getString("user_email"); + + if (email == null) { + _showSnackBar("Email utilisateur introuvable."); + return; + } + + final oldPasswordController = TextEditingController(); + final newPasswordController = TextEditingController(); + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Changer le mot de passe'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: oldPasswordController, + obscureText: true, + decoration: const InputDecoration( + labelText: 'Ancien mot de passe', + ), + ), + const SizedBox(height: 10), + TextField( + controller: newPasswordController, + obscureText: true, + decoration: const InputDecoration( + labelText: 'Nouveau mot de passe', + ), + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Annuler'), + ), + TextButton( + onPressed: () async { + final oldPassword = oldPasswordController.text.trim(); + final newPassword = newPasswordController.text.trim(); + + if (oldPassword.isEmpty || newPassword.isEmpty) { + _showSnackBar("Les deux champs sont requis."); + return; + } + + final url = Uri.parse( + 'https://nexuschat.derickexm.be/users/change_password'); + + try { + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + "email": email, + "old_password": oldPassword, + "new_password": newPassword, + }), + ); + + if (response.statusCode == 200) { + _showSnackBar("Mot de passe mis à jour !"); + Navigator.of(context).pop(); // Fermer le popup + } else { + final responseData = jsonDecode(response.body); + _showSnackBar(responseData["error"] ?? "Erreur inconnue."); + } + } catch (e) { + _showSnackBar("Erreur lors de la connexion à l'API."); + } + }, + child: const Text('Confirmer'), + ), + ], + ); + }, + ); + } + + Future _deleteAccount() async { + final username = prefs.getString('username'); + final email = prefs.getString('user_email'); + final passwordController = TextEditingController(); + + if (username == null || email == null) { + _showSnackBar("Impossible de récupérer les infos du compte."); + return; + } + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Confirmation'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Pour supprimer votre compte, entrez votre mot de passe :"), + const SizedBox(height: 10), + TextField( + controller: passwordController, + obscureText: true, + decoration: const InputDecoration(labelText: "Mot de passe"), + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text("Annuler"), + ), + TextButton( + onPressed: () async { + final password = passwordController.text.trim(); + if (password.isEmpty) { + _showSnackBar("Le mot de passe est requis."); + return; + } + + final url = Uri.parse( + 'https://nexuschat.derickexm.be/users/delete_user'); + try { + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + "username": username, + "email": email, + "password": password, + }), + ); + + if (response.statusCode == 200) { + _showSnackBar("Compte supprimé avec succès."); + await prefs.clear(); + + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const Login()), + ); + } else { + _showSnackBar("Échec de la suppression du compte."); + } + } catch (e) { + _showSnackBar("Erreur de connexion à l'API."); + } + }, + child: const Text("Supprimer"), + ), + ], + ); + }, + ); + } + Future sendVerificationEmail(BuildContext context, String email) async { final url = Uri.parse( 'https://nexuschat.derickexm.be/email/send_email?email=$_userEmail'); @@ -227,16 +390,17 @@ class _ProfilState extends State { ), ), const SizedBox(height: 15), - ElevatedButton( - onPressed: () { - if (_userEmail != null) { - sendVerificationEmail(context, _userEmail!); - } else { - _showSnackBar("Aucun email trouvé pour l'utilisateur."); - } - }, - child: const Text("Envoyer l'email de vérification"), - ), + if (!_isEmailVerified) + ElevatedButton( + onPressed: () { + if (_userEmail != null) { + sendVerificationEmail(context, _userEmail!); + } else { + _showSnackBar("Aucun email trouvé pour l'utilisateur."); + } + }, + child: const Text("Envoyer l'email de vérification"), + ), const SizedBox(height: 20), const Text("Statut", style: @@ -290,6 +454,24 @@ class _ProfilState extends State { }, child: const Text('Changer nom d\'utilisateur'), ), + SizedBox( + height: 10, + ), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: Colors.red), + onPressed: _ChangePassword, + child: const Text("Changer le mot de passe", + style: TextStyle(color: Colors.white)), + ), + SizedBox( + height: 10, + ), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: Colors.red), + onPressed: _deleteAccount, + child: const Text("Supprimer le compte", + style: TextStyle(color: Colors.white)), + ), ], ), ), diff --git a/nexuschat/macos/Podfile.lock b/nexuschat/macos/Podfile.lock new file mode 100644 index 0000000..c54852e --- /dev/null +++ b/nexuschat/macos/Podfile.lock @@ -0,0 +1,29 @@ +PODS: + - FlutterMacOS (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - url_launcher_macos (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 + url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 + +PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 + +COCOAPODS: 1.16.2 diff --git a/nexuschat/macos/Runner.xcodeproj/project.pbxproj b/nexuschat/macos/Runner.xcodeproj/project.pbxproj index ab67831..5f334bb 100644 --- a/nexuschat/macos/Runner.xcodeproj/project.pbxproj +++ b/nexuschat/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + B8BA568225B7722CCF96E8D8 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 715EBAFB738B4F4A7653918C /* Pods_RunnerTests.framework */; }; + C2185F62C3CD9FF30DDE5155 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C83475F4656F24A643903FD /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 070AC6A69E7291C1C4854DFA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 0C83475F4656F24A643903FD /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* nexuschat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "nexuschat.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* nexuschat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = nexuschat.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -76,8 +80,14 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 715EBAFB738B4F4A7653918C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 9DC09B5245FF3C3E541B7D09 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + B92B3CB62787A38FD35339CD /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + CF42FF394810944FE028C7BC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + DE1B5073B319B2490AAEB036 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + E34584EA242300AA26F1BA1B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B8BA568225B7722CCF96E8D8 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C2185F62C3CD9FF30DDE5155 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 9866A980C9448EA5D225CC03 /* Pods */, ); sourceTree = ""; }; @@ -172,9 +185,25 @@ path = Runner; sourceTree = ""; }; + 9866A980C9448EA5D225CC03 /* Pods */ = { + isa = PBXGroup; + children = ( + 070AC6A69E7291C1C4854DFA /* Pods-Runner.debug.xcconfig */, + CF42FF394810944FE028C7BC /* Pods-Runner.release.xcconfig */, + E34584EA242300AA26F1BA1B /* Pods-Runner.profile.xcconfig */, + 9DC09B5245FF3C3E541B7D09 /* Pods-RunnerTests.debug.xcconfig */, + B92B3CB62787A38FD35339CD /* Pods-RunnerTests.release.xcconfig */, + DE1B5073B319B2490AAEB036 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 0C83475F4656F24A643903FD /* Pods_Runner.framework */, + 715EBAFB738B4F4A7653918C /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 239B5D276F88E359251E43FD /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 0735B088592D17EFE1C39F67 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 976689EE1C53CE19E6E6C9A5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,50 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0735B088592D17EFE1C39F67 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 239B5D276F88E359251E43FD /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +405,23 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 976689EE1C53CE19E6E6C9A5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9DC09B5245FF3C3E541B7D09 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = B92B3CB62787A38FD35339CD /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DE1B5073B319B2490AAEB036 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/nexuschat/macos/Runner.xcworkspace/contents.xcworkspacedata b/nexuschat/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/nexuschat/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/nexuschat/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/nexuschat/web/index.html b/nexuschat/web/index.html index 08840d2..3fcc17e 100644 --- a/nexuschat/web/index.html +++ b/nexuschat/web/index.html @@ -25,10 +25,10 @@ - + - + nexuschat