This commit is contained in:
exmKrd
2025-04-22 18:42:24 +02:00
parent 91db846958
commit e727ac641c
11 changed files with 584 additions and 115 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,7 +1,6 @@
// ✅ chat.dart (corrigé sans ChatApp)
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@@ -17,6 +16,9 @@ class ChatScreen extends StatefulWidget {
class _ChatScreenState extends State<ChatScreen> { class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _controller = TextEditingController(); final TextEditingController _controller = TextEditingController();
final ScrollController _scrollController = ScrollController();
final FocusNode _focusNode = FocusNode();
List<Map<String, String>> messages = []; List<Map<String, String>> messages = [];
String? expediteur; String? expediteur;
late String destinataire; late String destinataire;
@@ -45,6 +47,8 @@ class _ChatScreenState extends State<ChatScreen> {
_pollingTimer.cancel(); _pollingTimer.cancel();
_controller.removeListener(_updateButtonState); _controller.removeListener(_updateButtonState);
_controller.dispose(); _controller.dispose();
_focusNode.dispose();
_scrollController.dispose();
super.dispose(); super.dispose();
} }
@@ -144,12 +148,14 @@ class _ChatScreenState extends State<ChatScreen> {
messages = messagesList.map((msg) { messages = messagesList.map((msg) {
bool isMe = msg['expediteur'].toString() == expediteur; bool isMe = msg['expediteur'].toString() == expediteur;
return { return {
'sender': isMe ? 'me' : 'bot', 'sender': msg['expediteur'].toString(),
'text': msg['messages'].toString(), 'text': msg['messages'].toString(),
'timestamp': msg['sent_at'].toString(),
}; };
}).toList(); }).toList();
_isInitialLoading = false; _isInitialLoading = false;
}); });
_scrollToBottom();
} }
} }
} catch (e) { } catch (e) {
@@ -183,16 +189,26 @@ class _ChatScreenState extends State<ChatScreen> {
void _updateButtonState() { void _updateButtonState() {
setState(() { setState(() {
_isButtonEnabled = _controller.text.isNotEmpty; _isButtonEnabled = _controller.text.trim().isNotEmpty;
}); });
} }
Future<void> sendMessage(String message) async { Future<void> sendMessage(String message) async {
if (expediteur == null || message.trim().isEmpty) return;
final now = DateTime.now();
setState(() { setState(() {
messages.add({'sender': 'me', 'text': message}); messages.add({
'sender': expediteur!,
'text': message.trim(),
'timestamp': now.toIso8601String(),
});
}); });
_controller.clear(); _controller.clear();
_updateButtonState(); _updateButtonState();
_scrollToBottom();
try { try {
final response = await http.post( final response = await http.post(
Uri.parse('https://nexuschat.derickexm.be/messages/send_message/'), Uri.parse('https://nexuschat.derickexm.be/messages/send_message/'),
@@ -200,8 +216,8 @@ class _ChatScreenState extends State<ChatScreen> {
body: jsonEncode({ body: jsonEncode({
'expediteur': expediteur, 'expediteur': expediteur,
'destinataire': destinataire, 'destinataire': destinataire,
'message': message, 'message': message.trim(),
'timestamp': DateTime.now().toIso8601String(), 'sent_at': now.toIso8601String(),
'id_conversation': idConversation, 'id_conversation': idConversation,
}), }),
); );
@@ -209,8 +225,13 @@ class _ChatScreenState extends State<ChatScreen> {
final jsonResponse = jsonDecode(response.body); final jsonResponse = jsonDecode(response.body);
if (jsonResponse.containsKey('reply')) { if (jsonResponse.containsKey('reply')) {
setState(() { setState(() {
messages.add({'sender': 'bot', 'text': jsonResponse['reply']}); messages.add({
'sender': destinataire,
'text': jsonResponse['reply'],
'timestamp': DateTime.now().toIso8601String(),
}); });
});
_scrollToBottom();
} }
} }
} catch (e) { } catch (e) {
@@ -218,6 +239,26 @@ class _ChatScreenState extends State<ChatScreen> {
} }
} }
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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@@ -236,28 +277,62 @@ class _ChatScreenState extends State<ChatScreen> {
children: [ children: [
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
controller: _scrollController,
itemCount: messages.length, itemCount: messages.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final message = messages[index]; final message = messages[index];
final isMe = message['sender'] == 'me'; final isMe = message['sender'] == expediteur;
return Align(
// 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: alignment:
isMe ? Alignment.centerRight : Alignment.centerLeft, isMe ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
margin: const EdgeInsets.symmetric( margin: const EdgeInsets.symmetric(
vertical: 5, horizontal: 10), 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), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isMe ? Colors.orange : Colors.grey[300], color: isMe ? Colors.orange : Colors.grey[300],
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: Text( child: Text(
message['text']!, message['text'] ?? '',
style: TextStyle( style: TextStyle(
color: isMe ? Colors.white : Colors.black, 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<ChatScreen> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _controller, controller: _controller,
decoration: const InputDecoration( focusNode: _focusNode,
hintText: 'Écrire un message...', style: TextStyle(fontSize: 16),
cursorColor: Colors.orange,
decoration: InputDecoration(
hintText: 'Entrez votre message...',
border: OutlineInputBorder(), 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( SizedBox(width: 8),
icon: const Icon(Icons.send), Container(
decoration: BoxDecoration(
color: Colors.orange,
shape: BoxShape.circle,
),
child: IconButton(
icon: Icon(Icons.send, color: Colors.black),
onPressed: _isButtonEnabled onPressed: _isButtonEnabled
? () => sendMessage(_controller.text) ? () => sendMessage(_controller.text)
: null, : null,
color: _isButtonEnabled ? Colors.orange : Colors.grey,
), ),
),
SizedBox(width: 8),
], ],
), ),
), ),
@@ -290,3 +392,25 @@ class _ChatScreenState extends State<ChatScreen> {
); );
} }
} }
// ✅ 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;
}
}

View File

@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import 'package:nexuschat/listechat.dart';
import 'package:nexuschat/login.dart'; import 'package:nexuschat/login.dart';
class Inscription extends StatelessWidget { class Inscription extends StatelessWidget {
@@ -13,33 +12,33 @@ class Inscription extends StatelessWidget {
final TextEditingController username = TextEditingController(); final TextEditingController username = TextEditingController();
Future<void> sendVerificationEmail(BuildContext context, String email) async { Future<void> 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 { try {
final response = await http.post( final response = await http.post(
url, url,
headers: {'Content-Type': 'application/json'}, headers: {'Accept': 'application/json'},
body: jsonEncode({
"email": email,
}),
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context, "Email de vérification envoyé avec succès!");
SnackBar(content: Text("Email de vérification envoyé avec succès!")),
);
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context,
SnackBar( "Impossible d'envoyer l'email de vérification. (${response.statusCode})");
content: Text("Impossible d'envoyer l'email de vérification.")), print("Réponse serveur : ${response.body}");
);
} }
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context, "Erreur de connexion à l'API.");
SnackBar(content: Text("Erreur de connexion à l'API: $e")), print("Erreur d'envoi email : $e");
);
} }
} }
void _showSnackBar(BuildContext context, String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}
Future<void> _API_inscription(BuildContext context) async { Future<void> _API_inscription(BuildContext context) async {
const String apiUrl = "https://nexuschat.derickexm.be/users/create_user"; const String apiUrl = "https://nexuschat.derickexm.be/users/create_user";
@@ -56,29 +55,20 @@ class Inscription extends StatelessWidget {
if (response.statusCode == 200) { if (response.statusCode == 200) {
print("Inscription réussie !"); print("Inscription réussie !");
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context, "Inscription réussie !");
const SnackBar(content: Text("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( Navigator.pushReplacement(
context, context,
MaterialPageRoute(builder: (context) => Login()), MaterialPageRoute(builder: (context) => Login()),
); );
} else { } else {
print("Erreur : ${response.body}"); print("Erreur : ${response.body}");
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context, "Erreur lors de l'inscription");
const SnackBar(content: Text("Erreur lors de l'inscription")),
);
} }
} catch (e) { } catch (e) {
print("Erreur réseau : $e"); print("Erreur réseau : $e");
ScaffoldMessenger.of(context).showSnackBar( _showSnackBar(context, "Problème de connexion au serveur");
const SnackBar(content: Text("Problème de connexion au serveur")),
);
} }
} }
@@ -106,8 +96,6 @@ class Inscription extends StatelessWidget {
const Text("S'inscrire sur NexusChat", const Text("S'inscrire sur NexusChat",
style: TextStyle(fontSize: 24)), style: TextStyle(fontSize: 24)),
const SizedBox(height: 20), const SizedBox(height: 20),
// Champ Nom d'utilisateur
SizedBox( SizedBox(
width: 400, width: 400,
child: TextField( child: TextField(
@@ -121,8 +109,6 @@ class Inscription extends StatelessWidget {
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
// Champ Email
SizedBox( SizedBox(
width: 400, width: 400,
child: TextField( child: TextField(
@@ -136,8 +122,6 @@ class Inscription extends StatelessWidget {
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
// Champ Mot de passe
SizedBox( SizedBox(
width: 400, width: 400,
child: TextField( child: TextField(
@@ -151,15 +135,11 @@ class Inscription extends StatelessWidget {
), ),
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
// Bouton S'inscrire
ElevatedButton( ElevatedButton(
onPressed: () => _API_inscription(context), onPressed: () => _API_inscription(context),
child: const Text("S'inscrire"), child: const Text("S'inscrire"),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
// Bouton Déjà inscrit ?
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
Navigator.push(context, Navigator.push(context,

View File

@@ -99,17 +99,15 @@ class Listechatstate extends State<Listechat> {
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = json.decode(response.body); final data = json.decode(response.body);
if (data is Map<String, dynamic> && data.containsKey("conversations")) { if (data is Map<String, dynamic>) {
if (data.containsKey("conversations")) {
return List<Map<String, dynamic>>.from(data["conversations"]); return List<Map<String, dynamic>>.from(data["conversations"]);
} else { } else if (data.containsKey("exists") && data["exists"] == false) {
setState(() {
errorMessage = "Format de réponse inattendu";
});
return []; return [];
} }
} else { }
setState(() { setState(() {
errorMessage = "Erreur serveur: ${response.statusCode}"; errorMessage = "Format de réponse inattendu";
}); });
return []; return [];
} }
@@ -120,6 +118,9 @@ class Listechatstate extends State<Listechat> {
}); });
return []; return [];
} }
// ✅ Ce return évite l'erreur "body might complete normally"
return [];
} }
Future<void> _refreshConversations() async { Future<void> _refreshConversations() async {
@@ -146,6 +147,7 @@ class Listechatstate extends State<Listechat> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: false,
title: const Text("Mes Conversations"), title: const Text("Mes Conversations"),
actions: [ actions: [
IconButton( IconButton(
@@ -200,9 +202,21 @@ class Listechatstate extends State<Listechat> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Text("Aucune conversation trouvée"), const Icon(Icons.chat_bubble_outline,
size: 80, color: Colors.grey),
const SizedBox(height: 20), const SizedBox(height: 20),
ElevatedButton( const Text(
"Aucune conversation pour linstant",
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: () { onPressed: () {
Navigator.push( Navigator.push(
context, context,
@@ -211,7 +225,8 @@ class Listechatstate extends State<Listechat> {
), ),
); );
}, },
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<Listechat> {
? "conversation_${expediteur}_$rawId" ? "conversation_${expediteur}_$rawId"
: "conversation_${expediteur}_${destinataire}_$index"; : "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( return Hero(
tag: uniqueTag, tag: uniqueTag,
child: Card( child: Card(
@@ -263,19 +271,20 @@ class Listechatstate extends State<Listechat> {
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
subtitle: Column( //
crossAxisAlignment: CrossAxisAlignment.start, // subtitle: Column(
children: [ // crossAxisAlignment: CrossAxisAlignment.start,
Text(truncatedMessage), // children: [
Text( // Text(truncatedMessage),
formattedDate, // Text(
style: TextStyle( // formattedDate,
fontSize: 12, // style: TextStyle(
color: Colors.grey[600], // fontSize: 12,
), // color: Colors.grey[600],
), // ),
], // ),
), // ],
// ),
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,

View File

@@ -36,6 +36,27 @@ class Login extends StatelessWidget {
); );
} }
Future<void> 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<void> checkCredentials(String email, String password) async { Future<void> checkCredentials(String email, String password) async {
final url = final url =
Uri.parse('https://nexuschat.derickexm.be/users/check_credentials'); Uri.parse('https://nexuschat.derickexm.be/users/check_credentials');
@@ -63,6 +84,7 @@ class Login extends StatelessWidget {
Navigator.pushReplacement( Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => Menu())); context, MaterialPageRoute(builder: (context) => Menu()));
await sendAttemptLogin(email);
} else { } else {
_showErrorDialog( _showErrorDialog(
context, "Nom d'utilisateur ou mot de passe incorrect"); context, "Nom d'utilisateur ou mot de passe incorrect");

View File

@@ -14,12 +14,14 @@ class _MenuState extends State<Menu> {
int _selectedIndex = 0; int _selectedIndex = 0;
String? _userDisplayName; String? _userDisplayName;
String? _profilePictureURL; String? _profilePictureURL;
bool showEmailWarning = true;
static late List<Widget> _widgetOptions; static late List<Widget> _widgetOptions;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_widgetOptions = <Widget>[ _widgetOptions = <Widget>[
Listechat(), Listechat(),
Setting(), Setting(),
@@ -91,6 +93,28 @@ class _MenuState extends State<Menu> {
padding: const EdgeInsets.fromLTRB(15, 10, 10, 10), padding: const EdgeInsets.fromLTRB(15, 10, 10, 10),
child: Column( child: Column(
children: [ 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( Expanded(
child: Center( child: Center(
child: _widgetOptions.elementAt(_selectedIndex), child: _widgetOptions.elementAt(_selectedIndex),

View File

@@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:nexuschat/login.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
late SharedPreferences prefs; late SharedPreferences prefs;
@@ -109,6 +110,7 @@ class _ProfilState extends State<Profil> {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
setState(() { setState(() {
_username = data['username']; _username = data['username'];
prefs.setString('username', _username!);
}); });
} else { } else {
_showSnackBar("Impossible de récupérer le nom d'utilisateur."); _showSnackBar("Impossible de récupérer le nom d'utilisateur.");
@@ -124,6 +126,167 @@ class _ProfilState extends State<Profil> {
); );
} }
Future<void> _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<void> _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<void> sendVerificationEmail(BuildContext context, String email) async { Future<void> sendVerificationEmail(BuildContext context, String email) async {
final url = Uri.parse( final url = Uri.parse(
'https://nexuschat.derickexm.be/email/send_email?email=$_userEmail'); 'https://nexuschat.derickexm.be/email/send_email?email=$_userEmail');
@@ -227,6 +390,7 @@ class _ProfilState extends State<Profil> {
), ),
), ),
const SizedBox(height: 15), const SizedBox(height: 15),
if (!_isEmailVerified)
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
if (_userEmail != null) { if (_userEmail != null) {
@@ -290,6 +454,24 @@ class _ProfilState extends State<Profil> {
}, },
child: const Text('Changer nom d\'utilisateur'), 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)),
),
], ],
), ),
), ),

View File

@@ -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

View File

@@ -27,6 +27,8 @@
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 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 */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -60,11 +62,13 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference 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 = "<group>"; };
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; }; 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 = "<group>"; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
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 = "<group>"; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@@ -76,8 +80,14 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; }; 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
B8BA568225B7722CCF96E8D8 /* Pods_RunnerTests.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -92,6 +103,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
C2185F62C3CD9FF30DDE5155 /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -125,6 +137,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */, 331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */, 33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */, D73912EC22F37F3D000D13A0 /* Frameworks */,
9866A980C9448EA5D225CC03 /* Pods */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -172,9 +185,25 @@
path = Runner; path = Runner;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
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 = "<group>";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = { D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0C83475F4656F24A643903FD /* Pods_Runner.framework */,
715EBAFB738B4F4A7653918C /* Pods_RunnerTests.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -186,6 +215,7 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = ( buildPhases = (
239B5D276F88E359251E43FD /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */, 331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */, 331C80D3294CF70F00263BE5 /* Resources */,
@@ -204,11 +234,13 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
0735B088592D17EFE1C39F67 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */, 33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */, 33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */, 33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */, 3399D490228B24CF009A79C7 /* ShellScript */,
976689EE1C53CE19E6E6C9A5 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@@ -291,6 +323,50 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase 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 */ = { 3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1; alwaysOutOfDate = 1;
@@ -329,6 +405,23 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; 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 */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@@ -380,6 +473,7 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = { 331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 9DC09B5245FF3C3E541B7D09 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
@@ -394,6 +488,7 @@
}; };
331C80DC294CF71000263BE5 /* Release */ = { 331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = B92B3CB62787A38FD35339CD /* Pods-RunnerTests.release.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
@@ -408,6 +503,7 @@
}; };
331C80DD294CF71000263BE5 /* Profile */ = { 331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = DE1B5073B319B2490AAEB036 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;

View File

@@ -4,4 +4,7 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

View File

@@ -25,10 +25,10 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="nexuschat"> <meta name="apple-mobile-web-app-title" content="nexuschat">
<link rel="apple-touch-icon" href="assets/logo.png"> <link rel="apple-touch-icon" href="assets/assets/logo.png">
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="assets/logo.png" /> <link rel="icon" type="image/png" href="assets/assets/logo.png" />
<title>nexuschat</title> <title>nexuschat</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">