implement some changes
This commit is contained in:
parent
6b5ecb21d4
commit
56f34ecb59
|
|
@ -2776,13 +2776,13 @@ class Client extends MatrixApi {
|
||||||
final List<ReceiptEventContent> receipts = [];
|
final List<ReceiptEventContent> receipts = [];
|
||||||
|
|
||||||
for (final event in events) {
|
for (final event in events) {
|
||||||
|
|
||||||
room.setEphemeral(event);
|
room.setEphemeral(event);
|
||||||
|
|
||||||
// Receipt events are deltas between two states. We will create a
|
// Receipt events are deltas between two states. We will create a
|
||||||
// fake room account data event for this and store the difference
|
// fake room account data event for this and store the difference
|
||||||
// there.
|
// there.
|
||||||
if (event.type != 'm.receipt') continue;
|
if (event.type != 'm.receipt') continue;
|
||||||
|
|
||||||
receipts.add(ReceiptEventContent.fromJson(event.content));
|
receipts.add(ReceiptEventContent.fromJson(event.content));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2797,6 +2797,7 @@ class Client extends MatrixApi {
|
||||||
type: LatestReceiptState.eventType,
|
type: LatestReceiptState.eventType,
|
||||||
content: receiptStateContent.toJson(),
|
content: receiptStateContent.toJson(),
|
||||||
);
|
);
|
||||||
|
|
||||||
await database.storeRoomAccountData(room.id, event);
|
await database.storeRoomAccountData(room.id, event);
|
||||||
room.roomAccountData[event.type] = event;
|
room.roomAccountData[event.type] = event;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ abstract class DatabaseApi {
|
||||||
Event threadRootEvent,
|
Event threadRootEvent,
|
||||||
Event? lastEvent,
|
Event? lastEvent,
|
||||||
bool currentUserParticipated,
|
bool currentUserParticipated,
|
||||||
|
int? notificationCount,
|
||||||
|
int? highlightCount,
|
||||||
int count,
|
int count,
|
||||||
Client client,
|
Client client,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1401,6 +1401,8 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
|
||||||
Event threadRootEvent,
|
Event threadRootEvent,
|
||||||
Event? lastEvent,
|
Event? lastEvent,
|
||||||
bool currentUserParticipated,
|
bool currentUserParticipated,
|
||||||
|
int? notificationCount,
|
||||||
|
int? highlightCount,
|
||||||
int count,
|
int count,
|
||||||
Client client,
|
Client client,
|
||||||
) async {
|
) async {
|
||||||
|
|
@ -1415,6 +1417,8 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
|
||||||
client: client,
|
client: client,
|
||||||
currentUserParticipated: currentUserParticipated,
|
currentUserParticipated: currentUserParticipated,
|
||||||
count: count,
|
count: count,
|
||||||
|
notificationCount: notificationCount ?? 0,
|
||||||
|
highlightCount: highlightCount ?? 0,
|
||||||
).toJson(),
|
).toJson(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import 'package:html_unescape/html_unescape.dart';
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:matrix/src/models/timeline_chunk.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/cached_stream_controller.dart';
|
||||||
import 'package:matrix/src/utils/file_send_request_credentials.dart';
|
import 'package:matrix/src/utils/file_send_request_credentials.dart';
|
||||||
import 'package:matrix/src/utils/markdown.dart';
|
import 'package:matrix/src/utils/markdown.dart';
|
||||||
|
|
@ -148,17 +147,18 @@ class Room {
|
||||||
|
|
||||||
for (final threadEvent in response.chunk) {
|
for (final threadEvent in response.chunk) {
|
||||||
final event = Event.fromMatrixEvent(threadEvent, this);
|
final event = Event.fromMatrixEvent(threadEvent, this);
|
||||||
|
final thread = Thread.fromJson(threadEvent.toJson(), client);
|
||||||
// Store thread in database
|
// Store thread in database
|
||||||
await client.database.storeThread(
|
await client.database.storeThread(
|
||||||
id,
|
id,
|
||||||
event,
|
event,
|
||||||
event, // lastEvent
|
thread.lastEvent, // lastEvent
|
||||||
false, // currentUserParticipated
|
thread.currentUserParticipated ?? false, // currentUserParticipated
|
||||||
1, // count
|
0, 0,
|
||||||
|
thread.count ?? 1, // count
|
||||||
client,
|
client,
|
||||||
);
|
);
|
||||||
threads[event.eventId] =
|
threads[event.eventId] = thread;
|
||||||
(await client.database.getThread(id, event.eventId, client))!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.nextBatch == null) {
|
if (response.nextBatch == null) {
|
||||||
|
|
@ -180,12 +180,14 @@ class Room {
|
||||||
// Update thread metadata in database
|
// Update thread metadata in database
|
||||||
final root = await getEventById(event.relationshipEventId!);
|
final root = await getEventById(event.relationshipEventId!);
|
||||||
if (root == null) return;
|
if (root == null) return;
|
||||||
|
final thread = await client.database.getThread(id, event.relationshipEventId!, client);
|
||||||
await client.database.storeThread(
|
await client.database.storeThread(
|
||||||
id,
|
id,
|
||||||
root,
|
root,
|
||||||
event, // update last event
|
event, // update last event
|
||||||
event.senderId == client.userID, // currentUserParticipated
|
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,
|
client,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -243,14 +245,17 @@ class Room {
|
||||||
|
|
||||||
Future<Thread> getThread(Event rootEvent) async {
|
Future<Thread> getThread(Event rootEvent) async {
|
||||||
final threads = await getThreads();
|
final threads = await getThreads();
|
||||||
if (threads.containsKey(rootEvent.eventId))
|
if (threads.containsKey(rootEvent.eventId)) {
|
||||||
return threads[rootEvent.eventId]!;
|
return threads[rootEvent.eventId]!;
|
||||||
|
}
|
||||||
return Thread(
|
return Thread(
|
||||||
room: this,
|
room: this,
|
||||||
rootEvent: rootEvent,
|
rootEvent: rootEvent,
|
||||||
client: client,
|
client: client,
|
||||||
currentUserParticipated: false,
|
currentUserParticipated: false,
|
||||||
count: 0,
|
count: 0,
|
||||||
|
highlightCount: 0,
|
||||||
|
notificationCount: 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1523,7 +1528,6 @@ class Room {
|
||||||
direction = Direction.b,
|
direction = Direction.b,
|
||||||
StateFilter? filter,
|
StateFilter? filter,
|
||||||
}) async {
|
}) async {
|
||||||
|
|
||||||
unawaited(_loadThreadsFromServer());
|
unawaited(_loadThreadsFromServer());
|
||||||
|
|
||||||
final prev_batch = this.prev_batch;
|
final prev_batch = this.prev_batch;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:matrix/matrix_api_lite/generated/internal.dart';
|
|
||||||
import 'package:matrix/src/models/timeline_chunk.dart';
|
import 'package:matrix/src/models/timeline_chunk.dart';
|
||||||
|
|
||||||
class Thread {
|
class Thread {
|
||||||
|
|
@ -11,16 +12,28 @@ class Thread {
|
||||||
int? count;
|
int? count;
|
||||||
final Client client;
|
final Client client;
|
||||||
|
|
||||||
|
/// The count of unread notifications.
|
||||||
|
int notificationCount = 0;
|
||||||
|
|
||||||
|
/// The count of highlighted notifications.
|
||||||
|
int highlightCount = 0;
|
||||||
|
|
||||||
Thread({
|
Thread({
|
||||||
required this.room,
|
required this.room,
|
||||||
required this.rootEvent,
|
required this.rootEvent,
|
||||||
required this.client,
|
required this.client,
|
||||||
required this.currentUserParticipated,
|
required this.currentUserParticipated,
|
||||||
required this.count,
|
required this.count,
|
||||||
|
required this.notificationCount,
|
||||||
|
required this.highlightCount,
|
||||||
this.prev_batch,
|
this.prev_batch,
|
||||||
this.lastEvent,
|
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() => {
|
Map<String, dynamic> toJson() => {
|
||||||
...rootEvent.toJson(),
|
...rootEvent.toJson(),
|
||||||
'unsigned': {
|
'unsigned': {
|
||||||
|
|
@ -66,10 +79,20 @@ class Thread {
|
||||||
count: json['unsigned']?['m.relations']?['m.thread']?['count'],
|
count: json['unsigned']?['m.relations']?['m.thread']?['count'],
|
||||||
currentUserParticipated: json['unsigned']?['m.relations']?['m.thread']
|
currentUserParticipated: json['unsigned']?['m.relations']?['m.thread']
|
||||||
?['current_user_participated'],
|
?['current_user_participated'],
|
||||||
|
highlightCount: 0,
|
||||||
|
notificationCount: 0,
|
||||||
);
|
);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Event?> refreshLastEvent({
|
||||||
|
timeout = const Duration(seconds: 30),
|
||||||
|
}) async {
|
||||||
|
final lastEvent = _refreshingLastEvent ??= _refreshLastEvent();
|
||||||
|
_refreshingLastEvent = null;
|
||||||
|
return lastEvent;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Event?>? _refreshingLastEvent;
|
Future<Event?>? _refreshingLastEvent;
|
||||||
|
|
||||||
Future<Event?> _refreshLastEvent({
|
Future<Event?> _refreshLastEvent({
|
||||||
|
|
@ -121,8 +144,27 @@ class Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get hasNewMessages {
|
bool get hasNewMessages {
|
||||||
// TODO: Implement this
|
final lastEvent = this.lastEvent;
|
||||||
return false;
|
|
||||||
|
// 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 {
|
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({
|
Future<int> requestHistory({
|
||||||
int historyCount = Room.defaultHistoryCount,
|
int historyCount = Room.defaultHistoryCount,
|
||||||
void Function()? onHistoryReceived,
|
void Function()? onHistoryReceived,
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ class ThreadTimeline extends Timeline {
|
||||||
addAggregatedEvent(event);
|
addAggregatedEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unawaited(thread.setLastEvent(events[events.length - 1]));
|
||||||
|
|
||||||
// Handle redaction events
|
// Handle redaction events
|
||||||
if (event.type == EventTypes.Redaction) {
|
if (event.type == EventTypes.Redaction) {
|
||||||
final index = _findEvent(event_id: event.redacts);
|
final index = _findEvent(event_id: event.redacts);
|
||||||
|
|
@ -428,14 +430,15 @@ class ThreadTimeline extends Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<(List<Event>, String?)> startSearch(
|
Stream<(List<Event>, String?)> startSearch({
|
||||||
{String? searchTerm,
|
String? searchTerm,
|
||||||
int requestHistoryCount = 100,
|
int requestHistoryCount = 100,
|
||||||
int maxHistoryRequests = 10,
|
int maxHistoryRequests = 10,
|
||||||
String? prevBatch,
|
String? prevBatch,
|
||||||
String? sinceEventId,
|
String? sinceEventId,
|
||||||
int? limit,
|
int? limit,
|
||||||
bool Function(Event p1)? searchFunc}) {
|
bool Function(Event p1)? searchFunc,
|
||||||
|
}) {
|
||||||
// TODO: implement startSearch
|
// TODO: implement startSearch
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
@ -466,10 +469,10 @@ class ThreadTimeline extends Timeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void requestKeys({
|
Future<void> requestKeys({
|
||||||
bool tryOnlineBackup = true,
|
bool tryOnlineBackup = true,
|
||||||
bool onlineKeyBackupOnly = true,
|
bool onlineKeyBackupOnly = true,
|
||||||
}) {
|
}) async {
|
||||||
for (final event in events) {
|
for (final event in events) {
|
||||||
if (event.type == EventTypes.Encrypted &&
|
if (event.type == EventTypes.Encrypted &&
|
||||||
event.messageType == MessageTypes.BadEncrypted &&
|
event.messageType == MessageTypes.BadEncrypted &&
|
||||||
|
|
@ -477,7 +480,7 @@ class ThreadTimeline extends Timeline {
|
||||||
final sessionId = event.content.tryGet<String>('session_id');
|
final sessionId = event.content.tryGet<String>('session_id');
|
||||||
final senderKey = event.content.tryGet<String>('sender_key');
|
final senderKey = event.content.tryGet<String>('sender_key');
|
||||||
if (sessionId != null && senderKey != null) {
|
if (sessionId != null && senderKey != null) {
|
||||||
thread.room.requestSessionKey(sessionId, senderKey);
|
await thread.room.requestSessionKey(sessionId, senderKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue