implement some changes

This commit is contained in:
OfficialDakari 2025-10-26 15:01:18 +05:00
parent 6b5ecb21d4
commit 56f34ecb59
6 changed files with 96 additions and 24 deletions

View File

@ -2776,13 +2776,13 @@ class Client extends MatrixApi {
final List<ReceiptEventContent> receipts = [];
for (final event in events) {
room.setEphemeral(event);
// Receipt events are deltas between two states. We will create a
// fake room account data event for this and store the difference
// there.
if (event.type != 'm.receipt') continue;
receipts.add(ReceiptEventContent.fromJson(event.content));
}
@ -2797,6 +2797,7 @@ class Client extends MatrixApi {
type: LatestReceiptState.eventType,
content: receiptStateContent.toJson(),
);
await database.storeRoomAccountData(room.id, event);
room.roomAccountData[event.type] = event;
}

View File

@ -68,6 +68,8 @@ abstract class DatabaseApi {
Event threadRootEvent,
Event? lastEvent,
bool currentUserParticipated,
int? notificationCount,
int? highlightCount,
int count,
Client client,
);

View File

@ -1401,6 +1401,8 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
Event threadRootEvent,
Event? lastEvent,
bool currentUserParticipated,
int? notificationCount,
int? highlightCount,
int count,
Client client,
) async {
@ -1415,6 +1417,8 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
client: client,
currentUserParticipated: currentUserParticipated,
count: count,
notificationCount: notificationCount ?? 0,
highlightCount: highlightCount ?? 0,
).toJson(),
);
}

View File

@ -26,7 +26,6 @@ import 'package:html_unescape/html_unescape.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/models/timeline_chunk.dart';
import 'package:matrix/src/room_timeline.dart';
import 'package:matrix/src/utils/cached_stream_controller.dart';
import 'package:matrix/src/utils/file_send_request_credentials.dart';
import 'package:matrix/src/utils/markdown.dart';
@ -148,17 +147,18 @@ class Room {
for (final threadEvent in response.chunk) {
final event = Event.fromMatrixEvent(threadEvent, this);
final thread = Thread.fromJson(threadEvent.toJson(), client);
// Store thread in database
await client.database.storeThread(
id,
event,
event, // lastEvent
false, // currentUserParticipated
1, // count
thread.lastEvent, // lastEvent
thread.currentUserParticipated ?? false, // currentUserParticipated
0, 0,
thread.count ?? 1, // count
client,
);
threads[event.eventId] =
(await client.database.getThread(id, event.eventId, client))!;
threads[event.eventId] = thread;
}
if (response.nextBatch == null) {
@ -180,12 +180,14 @@ class Room {
// Update thread metadata in database
final root = await getEventById(event.relationshipEventId!);
if (root == null) return;
final thread = await client.database.getThread(id, event.relationshipEventId!, client);
await client.database.storeThread(
id,
root,
event, // update last event
event.senderId == client.userID, // currentUserParticipated
1, // increment count - should be calculated properly
(thread?.count ?? 0) + 1, // increment count - should be calculated properly
0, 0,
client,
);
}
@ -243,14 +245,17 @@ class Room {
Future<Thread> getThread(Event rootEvent) async {
final threads = await getThreads();
if (threads.containsKey(rootEvent.eventId))
if (threads.containsKey(rootEvent.eventId)) {
return threads[rootEvent.eventId]!;
}
return Thread(
room: this,
rootEvent: rootEvent,
client: client,
currentUserParticipated: false,
count: 0,
highlightCount: 0,
notificationCount: 0,
);
}
@ -1523,7 +1528,6 @@ class Room {
direction = Direction.b,
StateFilter? filter,
}) async {
unawaited(_loadThreadsFromServer());
final prev_batch = this.prev_batch;

View File

@ -1,5 +1,6 @@
import 'dart:async';
import 'package:matrix/matrix.dart';
import 'package:matrix/matrix_api_lite/generated/internal.dart';
import 'package:matrix/src/models/timeline_chunk.dart';
class Thread {
@ -11,16 +12,28 @@ class Thread {
int? count;
final Client client;
/// The count of unread notifications.
int notificationCount = 0;
/// The count of highlighted notifications.
int highlightCount = 0;
Thread({
required this.room,
required this.rootEvent,
required this.client,
required this.currentUserParticipated,
required this.count,
required this.notificationCount,
required this.highlightCount,
this.prev_batch,
this.lastEvent,
});
/// Returns true if this room is unread. To check if there are new messages
/// in muted rooms, use [hasNewMessages].
bool get isUnread => notificationCount > 0;
Map<String, dynamic> toJson() => {
...rootEvent.toJson(),
'unsigned': {
@ -66,10 +79,20 @@ class Thread {
count: json['unsigned']?['m.relations']?['m.thread']?['count'],
currentUserParticipated: json['unsigned']?['m.relations']?['m.thread']
?['current_user_participated'],
highlightCount: 0,
notificationCount: 0,
);
return thread;
}
Future<Event?> refreshLastEvent({
timeout = const Duration(seconds: 30),
}) async {
final lastEvent = _refreshingLastEvent ??= _refreshLastEvent();
_refreshingLastEvent = null;
return lastEvent;
}
Future<Event?>? _refreshingLastEvent;
Future<Event?> _refreshLastEvent({
@ -121,8 +144,27 @@ class Thread {
}
bool get hasNewMessages {
// TODO: Implement this
return false;
final lastEvent = this.lastEvent;
// There is no known event or the last event is only a state fallback event,
// we assume there is no new messages.
if (lastEvent == null ||
!client.roomPreviewLastEvents.contains(lastEvent.type)) {
return false;
}
// Read marker is on the last event so no new messages.
if (lastEvent.receipts
.any((receipt) => receipt.user.senderId == client.userID!)) {
return false;
}
// If the last event is sent, we mark the room as read.
if (lastEvent.senderId == client.userID) return false;
// Get the timestamp of read marker and compare
final readAtMilliseconds = room.receiptState.byThread[rootEvent.eventId]?.latestOwnReceipt?.ts ?? 0;
return readAtMilliseconds < lastEvent.originServerTs.millisecondsSinceEpoch;
}
Future<TimelineChunk?> getEventContext(String eventId) async {
@ -327,6 +369,22 @@ class Thread {
);
}
Future<void> setLastEvent(Event event) async {
lastEvent = event;
final thread = await client.database.getThread(room.id, rootEvent.eventId, client);
Logs().v('Set lastEvent to ${room.id}:${rootEvent.eventId} (${event.senderId})');
await client.database.storeThread(
room.id,
rootEvent,
lastEvent,
currentUserParticipated ?? false,
notificationCount,
highlightCount,
(thread?.count ?? 0) + 1,
client,
);
}
Future<int> requestHistory({
int historyCount = Room.defaultHistoryCount,
void Function()? onHistoryReceived,

View File

@ -119,6 +119,8 @@ class ThreadTimeline extends Timeline {
addAggregatedEvent(event);
}
unawaited(thread.setLastEvent(events[events.length - 1]));
// Handle redaction events
if (event.type == EventTypes.Redaction) {
final index = _findEvent(event_id: event.redacts);
@ -428,14 +430,15 @@ class ThreadTimeline extends Timeline {
}
@override
Stream<(List<Event>, String?)> startSearch(
{String? searchTerm,
int requestHistoryCount = 100,
int maxHistoryRequests = 10,
String? prevBatch,
String? sinceEventId,
int? limit,
bool Function(Event p1)? searchFunc}) {
Stream<(List<Event>, String?)> startSearch({
String? searchTerm,
int requestHistoryCount = 100,
int maxHistoryRequests = 10,
String? prevBatch,
String? sinceEventId,
int? limit,
bool Function(Event p1)? searchFunc,
}) {
// TODO: implement startSearch
throw UnimplementedError();
}
@ -466,10 +469,10 @@ class ThreadTimeline extends Timeline {
}
@override
void requestKeys({
Future<void> requestKeys({
bool tryOnlineBackup = true,
bool onlineKeyBackupOnly = true,
}) {
}) async {
for (final event in events) {
if (event.type == EventTypes.Encrypted &&
event.messageType == MessageTypes.BadEncrypted &&
@ -477,7 +480,7 @@ class ThreadTimeline extends Timeline {
final sessionId = event.content.tryGet<String>('session_id');
final senderKey = event.content.tryGet<String>('sender_key');
if (sessionId != null && senderKey != null) {
thread.room.requestSessionKey(sessionId, senderKey);
await thread.room.requestSessionKey(sessionId, senderKey);
}
}
}