Skip to content

Commit 94a8450

Browse files
CubeRomanMagellanMagellan
authored andcommitted
SK-477: Message reply functionality (#78)
* add PopupMessageMenu * add ReplyMessageWidget * add repliedMessageId * add sender to MessageModel * add scrollTo * add Autoscroll * add focus menu * fix attachment in reply * add showScrollFAB * add draft reply --------- Co-authored-by: Magellan <magellan@connectycube.com>
1 parent bcac6fc commit 94a8450

40 files changed

Lines changed: 1493 additions & 404 deletions

lib/objectbox-model.json

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
},
9393
{
9494
"id": "11:6168919874786736956",
95-
"lastPropertyId": "9:1875750503242122079",
95+
"lastPropertyId": "14:1893283248997063821",
9696
"name": "MessageModel",
9797
"properties": [
9898
{
@@ -142,6 +142,37 @@
142142
"id": "9:1875750503242122079",
143143
"name": "dbExtension",
144144
"type": 9
145+
},
146+
{
147+
"id": "10:6395861719839579723",
148+
"name": "repliedMessageId",
149+
"type": 9
150+
},
151+
{
152+
"id": "11:8502424052705749036",
153+
"name": "replyMessageBindId",
154+
"type": 11,
155+
"flags": 520,
156+
"indexId": "39:2280023974172957156",
157+
"relationTarget": "MessageModel"
158+
},
159+
{
160+
"id": "12:6401592278627748216",
161+
"name": "senderBindId",
162+
"type": 11,
163+
"flags": 520,
164+
"indexId": "40:5803255922961343502",
165+
"relationTarget": "UserModel"
166+
},
167+
{
168+
"id": "13:5213655976270008005",
169+
"name": "isOwn",
170+
"type": 1
171+
},
172+
{
173+
"id": "14:1893283248997063821",
174+
"name": "isTempReplied",
175+
"type": 1
145176
}
146177
],
147178
"relations": [
@@ -330,7 +361,7 @@
330361
}
331362
],
332363
"lastEntityId": "13:9106374520578572502",
333-
"lastIndexId": "38:1718185030575189588",
364+
"lastIndexId": "40:5803255922961343502",
334365
"lastRelationId": "5:7785256265115248397",
335366
"lastSequenceId": "0:0",
336367
"modelVersion": 5,

lib/objectbox.g.dart

Lines changed: 86 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/api/chats/messages_api.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Future<(bool, Message?)> sendMessage({
2121
'id': message.id,
2222
'cid': message.cid,
2323
if (message.body?.isNotEmpty ?? false) 'body': message.body,
24+
if (message.repliedMessageId?.isNotEmpty ?? false)
25+
'replied_message_id': message.repliedMessageId,
2426
if (message.extension != null) 'x': message.extension,
2527
if (message.attachments != null) 'attachments': message.attachments,
2628
};

lib/src/api/conversations/models/message.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Message extends Equatable {
66
final String? id; //_id
77
final String? from; //from
88
final String? cid; //cid
9+
final String? repliedMessageId; //replied_message_id
910
final String? rawStatus; //status
1011
final String? body; //body
1112
final List<Attachment>? attachments; //attachments
@@ -17,6 +18,7 @@ class Message extends Equatable {
1718
this.id,
1819
this.from,
1920
this.cid,
21+
this.repliedMessageId,
2022
this.rawStatus,
2123
this.body,
2224
this.attachments,
@@ -29,6 +31,7 @@ class Message extends Equatable {
2931
: id = json['_id'],
3032
from = json['from'],
3133
cid = json['cid'],
34+
repliedMessageId = json['replied_message_id'],
3235
rawStatus = json['status'],
3336
body = json['body'],
3437
attachments = json['attachments'] == null
@@ -53,6 +56,7 @@ class Message extends Equatable {
5356
String? id,
5457
String? from,
5558
String? cid,
59+
String? repliedMessageId,
5660
String? rawStatus,
5761
String? body,
5862
List<Attachment>? attachments,
@@ -64,6 +68,7 @@ class Message extends Equatable {
6468
id: id ?? this.id,
6569
from: from ?? this.from,
6670
cid: cid ?? this.cid,
71+
repliedMessageId: repliedMessageId ?? this.repliedMessageId,
6772
rawStatus: rawStatus ?? this.rawStatus,
6873
body: body ?? this.body,
6974
attachments: attachments ?? this.attachments,

lib/src/db/db_service.dart

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,19 @@ class DatabaseService {
275275
/// ///////////////////////////
276276
277277
Future<List<MessageModel>> getAllMessagesLocal(
278-
String cid, DateTime? ltDate) async {
278+
String cid, DateTime? ltDate, int? limit) async {
279279
final query = store!
280280
.box<MessageModel>()
281281
.query(MessageModel_.cid
282282
.equals(cid)
283283
.and(MessageModel_.createdAt.lessThanDate(ltDate ?? DateTime.now()))
284+
.and(MessageModel_.isTempReplied.isNull())
284285
.and(MessageModel_.rawStatus
285286
.notEquals(ChatMessageStatus.draft.name) //hide draft messages
286287
.or(MessageModel_.rawStatus.isNull())))
287288
.order(MessageModel_.createdAt, flags: Order.descending)
288-
.build();
289+
.build()
290+
..limit = limit ?? 0;
289291
final results = await query.findAsync();
290292
query.close();
291293
return results;
@@ -295,20 +297,32 @@ class DatabaseService {
295297
[int violationId = 0]) async {
296298
final query = store!
297299
.box<MessageModel>()
298-
.query(MessageModel_.id
299-
.oneOf(items.map((element) => element.id!).toList()))
300+
.query(
301+
MessageModel_.id.oneOf(items.map((element) => element.id).toList()))
300302
.build();
301303

302304
final messagesInDb = await query.findAsync();
303305
query.close();
304306

305307
var messagesInDbMap = {for (var v in messagesInDb) v.id: v};
306-
for (var message in items) {
308+
309+
Map<String, MessageModel> messagesMap = {};
310+
311+
for (var message in items.reversed) {
307312
final messageInDb = messagesInDbMap[message.id];
308313
if (messageInDb != null) {
309314
assignMessage(message, messageInDb);
310315
}
316+
messagesMap[message.id] = message;
317+
318+
if (message.repliedMessageId != null && message.replyMessage == null) {
319+
var replyMessage = messagesMap[message.repliedMessageId];
320+
if (replyMessage != null) {
321+
message.replyMessage = replyMessage;
322+
}
323+
}
311324
}
325+
312326
try {
313327
await store!.box<MessageModel>().putManyAsync(items, mode: PutMode.put);
314328
} on UniqueViolationException catch (e) {
@@ -379,14 +393,27 @@ class DatabaseService {
379393
if (msgInDb != null) {
380394
assignMessage(item, msgInDb);
381395
}
396+
// TODO delete after check replyMessage functionality
397+
// if (item.replyMessage != null && item.replyMessage!.bid == null) {
398+
// final query = store!
399+
// .box<MessageModel>()
400+
// .query(MessageModel_.id.equals(item.replyMessage!.id))
401+
// .build();
402+
// final replyMsgInDb = await query.findFirstAsync();
403+
// query.close();
404+
// print('updateMessageLocal replyMsgInDb= $replyMsgInDb');
405+
// item.replyMessage = replyMsgInDb?.replyMessage;
406+
// }
382407
}
408+
383409
return await store!
384410
.box<MessageModel>()
385411
.putAndGetAsync(item, mode: PutMode.put);
386412
}
387413

388414
Future<void> assignMessage(MessageModel msg, MessageModel msgInDb) async {
389415
msg.bid = msgInDb.bid;
416+
msg.replyMessage = msgInDb.replyMessage;
390417
if (msg.attachments.isNotEmpty) {
391418
msg.attachments.clear();
392419
}

lib/src/db/local/message_local_datasource.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ class MessageLocalDatasource {
66
final DatabaseService _databaseService = DatabaseService.instance;
77

88
Future<List<MessageModel>> getAllMessagesLocal(String cid,
9-
{DateTime? ltDate}) async {
9+
{DateTime? ltDate, int? limit}) async {
1010
print('getAllMessagesLocal');
1111
try {
12-
return await _databaseService.getAllMessagesLocal(cid, ltDate);
12+
return await _databaseService.getAllMessagesLocal(cid, ltDate, limit);
1313
} catch (e) {
1414
print('getAllMessagesLocal e ${e.toString()}');
1515
throw DatabaseException(e.toString());

0 commit comments

Comments
 (0)