Skip to content

Commit 65ca4db

Browse files
committed
feat: Implement ChatView model and integrate chat service for conversation management
1 parent a4dcfa9 commit 65ca4db

7 files changed

Lines changed: 174 additions & 180 deletions

File tree

lib/models/chat_view.dart

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'package:intl/intl.dart';
2+
3+
class ChatView {
4+
final String id;
5+
final String chatType;
6+
final String? partnerUserId;
7+
final String? partnerUsername;
8+
final String? name; // for group chats
9+
final String? lastMessageId;
10+
final String? lastMessagePreview;
11+
final DateTime updatedAt;
12+
final String displayName;
13+
14+
ChatView({
15+
required this.id,
16+
required this.chatType,
17+
this.partnerUserId,
18+
this.partnerUsername,
19+
this.name,
20+
this.lastMessageId,
21+
this.lastMessagePreview,
22+
required this.updatedAt,
23+
this.displayName = '',
24+
});
25+
26+
factory ChatView.fromJson(Map<String, dynamic> json) {
27+
return ChatView(
28+
id: json['id'] ?? '',
29+
chatType: json['chat_type'] ?? 'direct',
30+
partnerUserId: json['partner_user_id'],
31+
partnerUsername: json['partner_username'],
32+
name: json['name'],
33+
lastMessageId: json['last_message_id'],
34+
lastMessagePreview: json['last_message_preview'],
35+
updatedAt: DateTime.parse(json['updated_at']),
36+
displayName: json['name'] ?? json['partner_username'] ?? '',
37+
);
38+
}
39+
40+
Map<String, dynamic> toJson() {
41+
return {
42+
'id': id,
43+
'chat_type': chatType,
44+
'partner_user_id': partnerUserId,
45+
'partner_username': partnerUsername,
46+
'name': name,
47+
'last_message_id': lastMessageId,
48+
'last_message_preview': lastMessagePreview,
49+
'updated_at': updatedAt.toIso8601String(),
50+
};
51+
}
52+
53+
/// Optional helper: format the last update nicely for UI
54+
String get formattedDate {
55+
return DateFormat('dd/MM HH:mm').format(updatedAt);
56+
}
57+
58+
/// Optional helper: title shown in chat list
59+
String get displayTitle {
60+
if (chatType == 'group') return name ?? 'Group chat';
61+
return partnerUsername ?? 'Unknown';
62+
}
63+
64+
String get previewText {
65+
return lastMessagePreview ?? 'Secure session established 🔒';
66+
}
67+
}

lib/models/session.dart

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,28 @@
11
import 'dart:convert';
2-
import 'dart:typed_data';
32

43
class Session {
54
final String id;
65
final String chatId;
76
final String senderDeviceId;
87
final String receiverDeviceId;
9-
final Uint8List rootKey;
10-
final Uint8List? sendChainKey;
11-
final Uint8List? recvChainKey;
12-
final int sendCounter;
13-
final int recvCounter;
14-
final Uint8List ratchetPub;
15-
final Uint8List? ratchetPriv;
16-
final Uint8List? lastRemotePub;
178
final DateTime createdAt;
189
final DateTime updatedAt;
1910

2011
Session({
21-
this.id = '',
22-
this.chatId = '',
12+
this.id = '',
13+
this.chatId = '',
2314
required this.senderDeviceId,
2415
required this.receiverDeviceId,
25-
required this.rootKey,
26-
this.sendChainKey,
27-
this.recvChainKey,
28-
this.sendCounter = 0,
29-
this.recvCounter = 0,
30-
required this.ratchetPub,
31-
this.ratchetPriv,
32-
this.lastRemotePub,
3316
required this.createdAt,
3417
required this.updatedAt,
3518
});
36-
3719

3820
factory Session.fromJson(Map<String, dynamic> json) {
3921
return Session(
40-
id: json['id'],
41-
chatId: json['chat_id'],
22+
id: json['id'] ?? '',
23+
chatId: json['chat_id'] ?? '',
4224
senderDeviceId: json['sender_device_id'],
4325
receiverDeviceId: json['receiver_device_id'],
44-
rootKey: base64Decode(json['root_key']),
45-
sendChainKey: json['send_chain_key'] != null
46-
? base64Decode(json['send_chain_key'])
47-
: null,
48-
recvChainKey: json['recv_chain_key'] != null
49-
? base64Decode(json['recv_chain_key'])
50-
: null,
51-
sendCounter: json['send_counter'] ?? 0,
52-
recvCounter: json['recv_counter'] ?? 0,
53-
ratchetPub: base64Decode(json['ratchet_pub']),
54-
ratchetPriv: json['ratchet_priv'] != null
55-
? base64Decode(json['ratchet_priv'])
56-
: null,
57-
lastRemotePub: json['last_remote_pub'] != null
58-
? base64Decode(json['last_remote_pub'])
59-
: null,
6026
createdAt: DateTime.parse(json['created_at']),
6127
updatedAt: DateTime.parse(json['updated_at']),
6228
);
@@ -68,30 +34,17 @@ class Session {
6834
'chat_id': chatId,
6935
'sender_device_id': senderDeviceId,
7036
'receiver_device_id': receiverDeviceId,
71-
'root_key': base64Encode(rootKey),
72-
if (sendChainKey != null)
73-
'send_chain_key': base64Encode(sendChainKey!),
74-
if (recvChainKey != null)
75-
'recv_chain_key': base64Encode(recvChainKey!),
76-
'send_counter': sendCounter,
77-
'recv_counter': recvCounter,
78-
'ratchet_pub': base64Encode(ratchetPub),
79-
if (ratchetPriv != null)
80-
'ratchet_priv': base64Encode(ratchetPriv!),
81-
if (lastRemotePub != null)
82-
'last_remote_pub': base64Encode(lastRemotePub!),
8337
'created_at': createdAt.toIso8601String(),
8438
'updated_at': updatedAt.toIso8601String(),
8539
};
8640
}
41+
42+
/// This JSON is used when confirming a pending session with the node.
43+
/// Only non-sensitive metadata is uploaded — the actual ratchet keys remain client-side.
8744
Map<String, dynamic> toConfirmJson() {
88-
return {
89-
"sender_device_id": senderDeviceId,
90-
"receiver_device_id": receiverDeviceId,
91-
"root_key": base64Encode(rootKey),
92-
"ratchet_pub": base64Encode(ratchetPub),
93-
if (lastRemotePub != null)
94-
"last_remote_pub": base64Encode(lastRemotePub!),
95-
};
96-
}
45+
return {
46+
'sender_device_id': senderDeviceId,
47+
'receiver_device_id': receiverDeviceId,
48+
};
49+
}
9750
}

0 commit comments

Comments
 (0)