@@ -17,7 +17,8 @@ class ChatViewScreen extends StatefulWidget {
1717 super .key,
1818 required this .chatId,
1919 required this .displayName,
20- this .embedded = false , required this .chatView,
20+ this .embedded = false ,
21+ required this .chatView,
2122 });
2223
2324 @override
@@ -55,86 +56,160 @@ class _ChatViewScreenState extends State<ChatViewScreen> {
5556 super .dispose ();
5657 }
5758
58- Future <void > _loadMessages () async {
59- try {
60- setState (() => _loading = true );
61- final all = await messageService.getAllMessagesForChat (widget.chatId);
62- // 🕒 tri croissant (vieux → récents)
63- DateTime normalize (DateTime d) {
64- final s = d.toIso8601String ();
65- print ("normalizing date string: $s " );
66- // Si la date n'a pas de "Z" ni d'offset, on la traite comme locale et on force en UTC
67- if (! s.endsWith ('Z' ) && ! s.contains ('+' )) {
68- print ("manque zone info, normalizing to UTC for $s " );
69- final res = DateTime .utc (
70- d.year,
71- d.month,
72- d.day,
73- d.hour,
74- d.minute,
75- d.second,
76- d.millisecond,
77- d.microsecond,
78- ).toUtc ();
79- print ("normalized date: ${res .toIso8601String ()}" );
80- return res;
81- }
82- return d.toUtc ();
83- }
84- for (final msg in all) {
85- msg.createdAt = normalize (msg.createdAt);
86- }
87- all.sort ((a, b) => a.createdAt.compareTo (b.createdAt));
88- for (final msg in all) {
89- print ('Message from ${msg .fromUserId }: ${msg .ciphertext } at ${msg .createdAt }' );
90- }
59+ Future <void > _loadMessages () async {
60+ try {
61+ setState (() => _loading = true );
62+ final all = await messageService.getAllMessagesForChat (widget.chatId);
63+ // 🕒 tri croissant (vieux → récents)
64+ DateTime normalize (DateTime d) {
65+ final s = d.toIso8601String ();
66+ print ("normalizing date string: $s " );
67+ // Si la date n'a pas de "Z" ni d'offset, on la traite comme locale et on force en UTC
68+ if (! s.endsWith ('Z' ) && ! s.contains ('+' )) {
69+ print ("manque zone info, normalizing to UTC for $s " );
70+ final res = DateTime .utc (
71+ d.year,
72+ d.month,
73+ d.day,
74+ d.hour,
75+ d.minute,
76+ d.second,
77+ d.millisecond,
78+ d.microsecond,
79+ ).toUtc ();
80+ print ("normalized date: ${res .toIso8601String ()}" );
81+ return res;
82+ }
83+ return d.toUtc ();
84+ }
9185
92- setState (( ) {
93- _messages = all ;
94- _loading = false ;
95- } );
96- } catch (e ) {
97- debugPrint ( "Error loading messages: $ e " );
98- setState (() => _loading = false );
99- }
100- }
86+ for ( final msg in all ) {
87+ msg.createdAt = normalize (msg.createdAt) ;
88+ }
89+ all. sort ((a, b) => a.createdAt. compareTo (b.createdAt) );
90+ for ( final msg in all ) {
91+ print (
92+ 'Message from ${ msg . fromUserId }: ${ msg . ciphertext } at ${ msg . createdAt }' ,
93+ );
94+ }
10195
102- Future <void > _sendMessage () async {
103- final text = _controller.text.trim ();
104- if (text.isEmpty || _currentUserId == null ) return ;
96+ setState (() {
97+ _messages = all;
98+ _loading = false ;
99+ });
100+ } catch (e) {
101+ debugPrint ("Error loading messages: $e " );
102+ setState (() => _loading = false );
103+ }
104+ }
105105
106- try {
107- final keyProvider = KeyProvider ();
106+ Future <void > _sendMessage () async {
107+ final text = _controller.text.trim ();
108+ if (text.isEmpty || _currentUserId == null ) return ;
108109
109- // 1️⃣ Identifier le destinataire
110- final recipientUserId = widget.chatView.partnerUserId ! ;
110+ try {
111+ final keyProvider = KeyProvider () ;
111112
112- // 2️⃣ Récupérer les devices actifs du destinataire
113- final devices = await keyProvider.getUserDevicesKeys (recipientUserId);
114- if (devices.isEmpty) {
115- debugPrint ('No devices for recipient' );
116- return ;
117- }
113+ // 1️⃣ Identifier le destinataire
114+ final recipientUserId = widget.chatView.partnerUserId! ;
118115
119- // 5️⃣ Envoi du message
120- await messageService.sendMessage (
121- chatId: widget.chatId,
122- plaintext: text,
123- recipientUserId: recipientUserId,
124- recipientDeviceIds: devices.map ((d) => d.deviceId).toList (),
125- );
116+ // 2️⃣ Récupérer les devices actifs du destinataire
117+ final devices = await keyProvider.getUserDevicesKeys (recipientUserId);
118+ if (devices.isEmpty) {
119+ debugPrint ('No devices for recipient' );
120+ return ;
121+ }
126122
127- // 6️⃣ Reset input et refresh UI
128- _controller.clear ();
129- await _loadMessages ();
123+ // 5️⃣ Envoi du message
124+ await messageService.sendMessage (
125+ chatId: widget.chatId,
126+ plaintext: text,
127+ recipientUserId: recipientUserId,
128+ recipientDeviceIds: devices.map ((d) => d.deviceId).toList (),
129+ );
130130
131- } catch (e) {
132- debugPrint ("❌ Error sending message: $e " );
131+ // 6️⃣ Reset input et refresh UI
132+ _controller.clear ();
133+ await _loadMessages ();
134+ } catch (e) {
135+ debugPrint ("❌ Error sending message: $e " );
136+ }
133137 }
134- }
135138
136139 @override
137140 Widget build (BuildContext context) {
141+ Widget _infoRow (String title, String value) {
142+ return Padding (
143+ padding: const EdgeInsets .symmetric (vertical: 4 ),
144+ child: Row (
145+ mainAxisAlignment: MainAxisAlignment .spaceBetween,
146+ children: [
147+ Text (
148+ title,
149+ style: const TextStyle (color: Colors .grey, fontSize: 13 ),
150+ ),
151+ Flexible (
152+ child: Text (
153+ value,
154+ textAlign: TextAlign .right,
155+ style: const TextStyle (color: Colors .white, fontSize: 13 ),
156+ ),
157+ ),
158+ ],
159+ ),
160+ );
161+ }
162+
163+ void _showMessageInfo (BuildContext context, MessageView msg) {
164+ showModalBottomSheet (
165+ context: context,
166+ backgroundColor: const Color (0xFF1C1C1C ),
167+ shape: const RoundedRectangleBorder (
168+ borderRadius: BorderRadius .vertical (top: Radius .circular (16 )),
169+ ),
170+ builder: (context) {
171+ return Padding (
172+ padding: const EdgeInsets .all (16 ),
173+ child: Column (
174+ mainAxisSize: MainAxisSize .min,
175+ crossAxisAlignment: CrossAxisAlignment .start,
176+ children: [
177+ const Text (
178+ "🔒 Message Encryption Info" ,
179+ style: TextStyle (
180+ fontSize: 16 ,
181+ fontWeight: FontWeight .bold,
182+ color: Colors .greenAccent,
183+ ),
184+ ),
185+ const SizedBox (height: 12 ),
186+ _infoRow ("Message ID" , msg.id ?? "unknown" ),
187+ _infoRow ("From" , msg.fromUserId ?? "unknown" ),
188+ _infoRow ("Created at" , msg.createdAt.toIso8601String ()),
189+ const Divider (color: Colors .grey),
190+ const SizedBox (height: 6 ),
191+ _infoRow ("Algorithm" , "AES-256-GCM" ),
192+ _infoRow ("Key Exchange" , "X3DH + Double Ratchet" ),
193+ _infoRow ("Ciphertext Length" , "${msg .ciphertext .length } bytes" ),
194+ _infoRow ("Session ID" , widget.chatId),
195+ const SizedBox (height: 12 ),
196+ Center (
197+ child: TextButton .icon (
198+ onPressed: () => Navigator .pop (context),
199+ icon: const Icon (Icons .close, color: Colors .grey),
200+ label: const Text (
201+ "Close" ,
202+ style: TextStyle (color: Colors .grey),
203+ ),
204+ ),
205+ ),
206+ ],
207+ ),
208+ );
209+ },
210+ );
211+ }
212+
138213 final isDesktop = MediaQuery .of (context).size.width > 800 ;
139214
140215 final chatBody = Column (
@@ -153,28 +228,43 @@ Future<void> _sendMessage() async {
153228 Expanded (
154229 child: _loading
155230 ? const Center (
156- child:
157- CircularProgressIndicator (color : Colors .greenAccent) )
231+ child: CircularProgressIndicator (color : Colors .greenAccent),
232+ )
158233 : _messages.isEmpty
159- ? const Center (
160- child: Text ("No messages yet 💬" ,
161- style: TextStyle (color: Colors .grey)),
162- )
163- : ListView .builder (
164- reverse: false ,
165- padding: const EdgeInsets .all (12 ),
166- itemCount: _messages.length,
167- itemBuilder: (context, index) {
168- final msg = _messages[index];
169- final isMe = msg.fromUserId == _currentUserId;
170- return Align (
171- alignment: isMe
172- ? Alignment .centerRight
173- : Alignment .centerLeft,
174- child: Container (
175- margin: const EdgeInsets .symmetric (vertical: 4 ),
234+ ? const Center (
235+ child: Text (
236+ "No messages yet 💬" ,
237+ style: TextStyle (color: Colors .grey),
238+ ),
239+ )
240+ : ListView .builder (
241+ reverse: false ,
242+ padding: const EdgeInsets .all (12 ),
243+ itemCount: _messages.length,
244+ itemBuilder: (context, index) {
245+ final msg = _messages[index];
246+ final isMe = msg.fromUserId == _currentUserId;
247+
248+ return Align (
249+ alignment: isMe
250+ ? Alignment .centerRight
251+ : Alignment .centerLeft,
252+ child: Row (
253+ mainAxisSize: MainAxisSize .min,
254+ crossAxisAlignment: CrossAxisAlignment .end,
255+ textDirection: isMe
256+ ? TextDirection .rtl
257+ : TextDirection .ltr, // 🔁 pour aligner correctement
258+ children: [
259+ Container (
260+ margin: const EdgeInsets .symmetric (
261+ vertical: 4 ,
262+ horizontal: 4 ,
263+ ),
176264 padding: const EdgeInsets .symmetric (
177- horizontal: 14 , vertical: 10 ),
265+ horizontal: 14 ,
266+ vertical: 10 ,
267+ ),
178268 decoration: BoxDecoration (
179269 color: isMe
180270 ? Colors .greenAccent
@@ -188,17 +278,29 @@ Future<void> _sendMessage() async {
188278 ),
189279 ),
190280 ),
191- );
192- },
193- ),
281+ IconButton (
282+ icon: Icon (
283+ Icons .info_outline,
284+ color: isMe
285+ ? Colors .greenAccent
286+ : Colors .grey[400 ],
287+ size: 18 ,
288+ ),
289+ onPressed: () => _showMessageInfo (context, msg),
290+ ),
291+ ],
292+ ),
293+ );
294+ },
295+ ),
194296 ),
195297 Container (
196- padding:
197- const EdgeInsets .symmetric (horizontal: 16 , vertical: 10 ),
298+ padding: const EdgeInsets .symmetric (horizontal: 16 , vertical: 10 ),
198299 decoration: const BoxDecoration (
199300 color: Color (0xFF1C1C1C ),
200301 border: Border (
201- top: BorderSide (color: Color (0xFF2F2F2F ), width: 0.5 )),
302+ top: BorderSide (color: Color (0xFF2F2F2F ), width: 0.5 ),
303+ ),
202304 ),
203305 child: Row (
204306 children: [
@@ -224,15 +326,12 @@ Future<void> _sendMessage() async {
224326 );
225327
226328 if (widget.embedded) {
227- return Container (
228- color: const Color (0xFF101010 ),
229- child: chatBody,
230- );
329+ return Container (color: const Color (0xFF101010 ), child: chatBody);
231330 }
232331
233332 return Scaffold (
234333 backgroundColor: const Color (0xFF101010 ),
235334 body: SafeArea (child: chatBody),
236335 );
237336 }
238- }
337+ }
0 commit comments