update
This commit is contained in:
@@ -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<ChatScreen> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
List<Map<String, String>> messages = [];
|
||||
String? expediteur;
|
||||
late String destinataire;
|
||||
@@ -45,6 +47,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
_pollingTimer.cancel();
|
||||
_controller.removeListener(_updateButtonState);
|
||||
_controller.dispose();
|
||||
_focusNode.dispose();
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -144,12 +148,14 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
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<ChatScreen> {
|
||||
|
||||
void _updateButtonState() {
|
||||
setState(() {
|
||||
_isButtonEnabled = _controller.text.isNotEmpty;
|
||||
_isButtonEnabled = _controller.text.trim().isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> 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<ChatScreen> {
|
||||
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<ChatScreen> {
|
||||
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<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
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -236,27 +277,61 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
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<ChatScreen> {
|
||||
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<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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<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 {
|
||||
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<void> _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,
|
||||
|
||||
@@ -99,17 +99,15 @@ class Listechatstate extends State<Listechat> {
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
if (data is Map<String, dynamic> && data.containsKey("conversations")) {
|
||||
return List<Map<String, dynamic>>.from(data["conversations"]);
|
||||
} else {
|
||||
setState(() {
|
||||
errorMessage = "Format de réponse inattendu";
|
||||
});
|
||||
return [];
|
||||
if (data is Map<String, dynamic>) {
|
||||
if (data.containsKey("conversations")) {
|
||||
return List<Map<String, dynamic>>.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<Listechat> {
|
||||
});
|
||||
return [];
|
||||
}
|
||||
|
||||
// ✅ Ce return évite l'erreur "body might complete normally"
|
||||
return [];
|
||||
}
|
||||
|
||||
Future<void> _refreshConversations() async {
|
||||
@@ -146,6 +147,7 @@ class Listechatstate extends State<Listechat> {
|
||||
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<Listechat> {
|
||||
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<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}_${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<Listechat> {
|
||||
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,
|
||||
|
||||
@@ -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 {
|
||||
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");
|
||||
|
||||
@@ -14,12 +14,14 @@ class _MenuState extends State<Menu> {
|
||||
int _selectedIndex = 0;
|
||||
String? _userDisplayName;
|
||||
String? _profilePictureURL;
|
||||
bool showEmailWarning = true;
|
||||
|
||||
static late List<Widget> _widgetOptions;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_widgetOptions = <Widget>[
|
||||
Listechat(),
|
||||
Setting(),
|
||||
@@ -91,6 +93,28 @@ class _MenuState extends State<Menu> {
|
||||
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),
|
||||
|
||||
@@ -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<Profil> {
|
||||
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<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 {
|
||||
final url = Uri.parse(
|
||||
'https://nexuschat.derickexm.be/email/send_email?email=$_userEmail');
|
||||
@@ -227,16 +390,17 @@ class _ProfilState extends State<Profil> {
|
||||
),
|
||||
),
|
||||
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<Profil> {
|
||||
},
|
||||
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)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
29
nexuschat/macos/Podfile.lock
Normal file
29
nexuschat/macos/Podfile.lock
Normal 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
|
||||
@@ -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 = "<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; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -76,8 +80,14 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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 */
|
||||
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
@@ -172,9 +185,25 @@
|
||||
path = Runner;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0C83475F4656F24A643903FD /* Pods_Runner.framework */,
|
||||
715EBAFB738B4F4A7653918C /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -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;
|
||||
|
||||
@@ -4,4 +4,7 @@
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
<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-title" content="nexuschat">
|
||||
<link rel="apple-touch-icon" href="assets/logo.png">
|
||||
<link rel="apple-touch-icon" href="assets/assets/logo.png">
|
||||
|
||||
<!-- 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>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
Reference in New Issue
Block a user