Merge branch 'main' into karthi/fix-hangup-timeout
This commit is contained in:
commit
579b8aa944
|
|
@ -1205,8 +1205,7 @@ const knownHashes = ['sha256'];
|
|||
const knownHashesAuthentificationCodes = ['hkdf-hmac-sha256'];
|
||||
|
||||
class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
||||
_KeyVerificationMethodSas({required KeyVerification request})
|
||||
: super(request: request);
|
||||
_KeyVerificationMethodSas({required super.request});
|
||||
|
||||
@override
|
||||
// ignore: overridden_fields
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ class Client extends MatrixApi {
|
|||
|
||||
bool enableDehydratedDevices = false;
|
||||
|
||||
/// Wether read receipts are sent as public receipts by default or just as private receipts.
|
||||
/// Whether read receipts are sent as public receipts by default or just as private receipts.
|
||||
bool receiptsPublicByDefault = true;
|
||||
|
||||
/// Whether this client supports end-to-end encryption using olm.
|
||||
|
|
@ -940,60 +940,76 @@ class Client extends MatrixApi {
|
|||
final leave = syncResp.rooms?.leave;
|
||||
if (leave != null) {
|
||||
for (final entry in leave.entries) {
|
||||
final id = entry.key;
|
||||
final room = entry.value;
|
||||
final leftRoom = Room(
|
||||
id: id,
|
||||
membership: Membership.leave,
|
||||
client: this,
|
||||
roomAccountData:
|
||||
room.accountData?.asMap().map((k, v) => MapEntry(v.type, v)) ??
|
||||
<String, BasicRoomEvent>{},
|
||||
);
|
||||
|
||||
final timeline = Timeline(
|
||||
room: leftRoom,
|
||||
chunk: TimelineChunk(
|
||||
events: room.timeline?.events?.reversed
|
||||
.toList() // we display the event in the other sence
|
||||
.map((e) => Event.fromMatrixEvent(e, leftRoom))
|
||||
.toList() ??
|
||||
[]));
|
||||
|
||||
leftRoom.prev_batch = room.timeline?.prevBatch;
|
||||
room.state?.forEach((event) {
|
||||
leftRoom.setState(Event.fromMatrixEvent(
|
||||
event,
|
||||
leftRoom,
|
||||
));
|
||||
});
|
||||
|
||||
room.timeline?.events?.forEach((event) {
|
||||
leftRoom.setState(Event.fromMatrixEvent(
|
||||
event,
|
||||
leftRoom,
|
||||
));
|
||||
});
|
||||
|
||||
for (var i = 0; i < timeline.events.length; i++) {
|
||||
// Try to decrypt encrypted events but don't update the database.
|
||||
if (leftRoom.encrypted && leftRoom.client.encryptionEnabled) {
|
||||
if (timeline.events[i].type == EventTypes.Encrypted) {
|
||||
timeline.events[i] =
|
||||
await leftRoom.client.encryption!.decryptRoomEvent(
|
||||
leftRoom.id,
|
||||
timeline.events[i],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_archivedRooms.add(ArchivedRoom(room: leftRoom, timeline: timeline));
|
||||
await _storeArchivedRoom(entry.key, entry.value);
|
||||
}
|
||||
}
|
||||
return _archivedRooms;
|
||||
}
|
||||
|
||||
/// [_storeArchivedRoom]
|
||||
/// @leftRoom we can pass a room which was left so that we don't loose states
|
||||
Future<void> _storeArchivedRoom(
|
||||
String id,
|
||||
LeftRoomUpdate update, {
|
||||
Room? leftRoom,
|
||||
}) async {
|
||||
final roomUpdate = update;
|
||||
final archivedRoom = leftRoom ??
|
||||
Room(
|
||||
id: id,
|
||||
membership: Membership.leave,
|
||||
client: this,
|
||||
roomAccountData: roomUpdate.accountData
|
||||
?.asMap()
|
||||
.map((k, v) => MapEntry(v.type, v)) ??
|
||||
<String, BasicRoomEvent>{},
|
||||
);
|
||||
// Set membership of room to leave, in the case we got a left room passed, otherwise
|
||||
// the left room would have still membership join, which would be wrong for the setState later
|
||||
archivedRoom.membership = Membership.leave;
|
||||
final timeline = Timeline(
|
||||
room: archivedRoom,
|
||||
chunk: TimelineChunk(
|
||||
events: roomUpdate.timeline?.events?.reversed
|
||||
.toList() // we display the event in the other sence
|
||||
.map((e) => Event.fromMatrixEvent(e, archivedRoom))
|
||||
.toList() ??
|
||||
[]));
|
||||
|
||||
archivedRoom.prev_batch = update.timeline?.prevBatch;
|
||||
update.state?.forEach((event) {
|
||||
archivedRoom.setState(Event.fromMatrixEvent(
|
||||
event,
|
||||
archivedRoom,
|
||||
));
|
||||
});
|
||||
|
||||
update.timeline?.events?.forEach((event) {
|
||||
archivedRoom.setState(Event.fromMatrixEvent(
|
||||
event,
|
||||
archivedRoom,
|
||||
));
|
||||
});
|
||||
|
||||
for (var i = 0; i < timeline.events.length; i++) {
|
||||
// Try to decrypt encrypted events but don't update the database.
|
||||
if (archivedRoom.encrypted && archivedRoom.client.encryptionEnabled) {
|
||||
if (timeline.events[i].type == EventTypes.Encrypted) {
|
||||
await archivedRoom.client.encryption!
|
||||
.decryptRoomEvent(
|
||||
archivedRoom.id,
|
||||
timeline.events[i],
|
||||
)
|
||||
.then(
|
||||
(decrypted) => timeline.events[i] = decrypted,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_archivedRooms.add(ArchivedRoom(room: archivedRoom, timeline: timeline));
|
||||
}
|
||||
|
||||
/// Uploads a file and automatically caches it in the database, if it is small enough
|
||||
/// and returns the mxc url.
|
||||
@override
|
||||
|
|
@ -1892,7 +1908,7 @@ class Client extends MatrixApi {
|
|||
final syncRoomUpdate = entry.value;
|
||||
|
||||
await database?.storeRoomUpdate(id, syncRoomUpdate, this);
|
||||
final room = _updateRoomsByRoomUpdate(id, syncRoomUpdate);
|
||||
final room = await _updateRoomsByRoomUpdate(id, syncRoomUpdate);
|
||||
|
||||
final timelineUpdateType = direction != null
|
||||
? (direction == Direction.b
|
||||
|
|
@ -2132,7 +2148,8 @@ class Client extends MatrixApi {
|
|||
}
|
||||
}
|
||||
|
||||
Room _updateRoomsByRoomUpdate(String roomId, SyncRoomUpdate chatUpdate) {
|
||||
Future<Room> _updateRoomsByRoomUpdate(
|
||||
String roomId, SyncRoomUpdate chatUpdate) async {
|
||||
// Update the chat list item.
|
||||
// Search the room in the rooms
|
||||
final roomIndex = rooms.indexWhere((r) => r.id == roomId);
|
||||
|
|
@ -2175,8 +2192,13 @@ class Client extends MatrixApi {
|
|||
room.stopStaleCallsChecker(room.id);
|
||||
|
||||
rooms.removeAt(roomIndex);
|
||||
|
||||
// in order to keep the archive in sync, add left room to archive
|
||||
if (chatUpdate is LeftRoomUpdate) {
|
||||
await _storeArchivedRoom(room.id, chatUpdate, leftRoom: room);
|
||||
}
|
||||
}
|
||||
// Update notification, highlight count and/or additional informations
|
||||
// Update notification, highlight count and/or additional information
|
||||
else if (found &&
|
||||
chatUpdate is JoinedRoomUpdate &&
|
||||
(rooms[roomIndex].membership != membership ||
|
||||
|
|
@ -2206,7 +2228,7 @@ class Client extends MatrixApi {
|
|||
requestHistoryOnLimitedTimeline) {
|
||||
Logs().v(
|
||||
'Limited timeline for ${rooms[roomIndex].id} request history now');
|
||||
runInRoot(rooms[roomIndex].requestHistory);
|
||||
unawaited(runInRoot(rooms[roomIndex].requestHistory));
|
||||
}
|
||||
}
|
||||
return room;
|
||||
|
|
|
|||
|
|
@ -79,10 +79,10 @@ class Event extends MatrixEvent {
|
|||
|
||||
Event({
|
||||
this.status = defaultStatus,
|
||||
required Map<String, dynamic> content,
|
||||
required String type,
|
||||
required Map<String, dynamic> super.content,
|
||||
required super.type,
|
||||
required String eventId,
|
||||
required String senderId,
|
||||
required super.senderId,
|
||||
required DateTime originServerTs,
|
||||
Map<String, dynamic>? unsigned,
|
||||
Map<String, dynamic>? prevContent,
|
||||
|
|
@ -91,10 +91,7 @@ class Event extends MatrixEvent {
|
|||
MatrixEvent? originalSource,
|
||||
}) : _originalSource = originalSource,
|
||||
super(
|
||||
content: content,
|
||||
type: type,
|
||||
eventId: eventId,
|
||||
senderId: senderId,
|
||||
originServerTs: originServerTs,
|
||||
roomId: room.id,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,12 @@ class Room {
|
|||
Future<void> forget() async {
|
||||
await client.database?.forgetRoom(id);
|
||||
await client.forgetRoom(id);
|
||||
// Update archived rooms, otherwise an archived room may still be in the
|
||||
// list after a forget room call
|
||||
final roomIndex = client.archivedRooms.indexWhere((r) => r.room.id == id);
|
||||
if (roomIndex != -1) {
|
||||
client.archivedRooms.removeAt(roomIndex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1375,7 +1381,7 @@ class Room {
|
|||
);
|
||||
|
||||
final events = [
|
||||
if (resp.eventsAfter != null) ...resp.eventsAfter!.reversed.toList(),
|
||||
if (resp.eventsAfter != null) ...resp.eventsAfter!.reversed,
|
||||
if (resp.event != null) resp.event!,
|
||||
if (resp.eventsBefore != null) ...resp.eventsBefore!
|
||||
].map((e) => Event.fromMatrixEvent(e, this)).toList();
|
||||
|
|
|
|||
|
|
@ -43,25 +43,17 @@ class User extends Event {
|
|||
}
|
||||
|
||||
User.fromState({
|
||||
Map<String, dynamic>? prevContent,
|
||||
required String stateKey,
|
||||
Map<String, dynamic> content = const {},
|
||||
super.prevContent,
|
||||
required String super.stateKey,
|
||||
super.content = const {},
|
||||
required String typeKey,
|
||||
required String eventId,
|
||||
required String senderId,
|
||||
required DateTime originServerTs,
|
||||
dynamic unsigned,
|
||||
required Room room,
|
||||
required super.eventId,
|
||||
required super.senderId,
|
||||
required super.originServerTs,
|
||||
super.unsigned,
|
||||
required super.room,
|
||||
}) : super(
|
||||
stateKey: stateKey,
|
||||
prevContent: prevContent,
|
||||
content: content,
|
||||
type: typeKey,
|
||||
eventId: eventId,
|
||||
senderId: senderId,
|
||||
originServerTs: originServerTs,
|
||||
unsigned: unsigned,
|
||||
room: room,
|
||||
);
|
||||
|
||||
/// The full qualified Matrix ID in the format @username:server.abc.
|
||||
|
|
|
|||
|
|
@ -135,7 +135,8 @@ class SimpleSignableKey extends MatrixSignableKey {
|
|||
@override
|
||||
String? identifier;
|
||||
|
||||
SimpleSignableKey.fromJson(Map<String, dynamic> json) : super.fromJson(json);
|
||||
SimpleSignableKey.fromJson(Map<String, dynamic> super.json)
|
||||
: super.fromJson();
|
||||
}
|
||||
|
||||
abstract class SignableKey extends MatrixSignableKey {
|
||||
|
|
@ -166,8 +167,8 @@ abstract class SignableKey extends MatrixSignableKey {
|
|||
bool get crossVerified => hasValidSignatureChain();
|
||||
bool get signed => hasValidSignatureChain(verifiedOnly: false);
|
||||
|
||||
SignableKey.fromJson(Map<String, dynamic> json, this.client)
|
||||
: super.fromJson(json) {
|
||||
SignableKey.fromJson(Map<String, dynamic> super.json, this.client)
|
||||
: super.fromJson() {
|
||||
_verified = false;
|
||||
_blocked = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ abstract class TimeoutHttpClient extends http.BaseClient {
|
|||
}
|
||||
|
||||
class FixedTimeoutHttpClient extends TimeoutHttpClient {
|
||||
FixedTimeoutHttpClient(http.Client inner, this.timeout) : super(inner);
|
||||
FixedTimeoutHttpClient(super.inner, this.timeout);
|
||||
@override
|
||||
Duration timeout;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
/// Workaround until [File] in dart:io and dart:html is unified
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
|
@ -91,15 +92,14 @@ class MatrixFile {
|
|||
|
||||
class MatrixImageFile extends MatrixFile {
|
||||
MatrixImageFile({
|
||||
required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
required super.bytes,
|
||||
required super.name,
|
||||
super.mimeType,
|
||||
int? width,
|
||||
int? height,
|
||||
this.blurhash,
|
||||
}) : _width = width,
|
||||
_height = height,
|
||||
super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
_height = height;
|
||||
|
||||
/// Creates a new image file and calculates the width, height and blurhash.
|
||||
static Future<MatrixImageFile> create({
|
||||
|
|
@ -355,13 +355,12 @@ class MatrixVideoFile extends MatrixFile {
|
|||
final int? duration;
|
||||
|
||||
MatrixVideoFile(
|
||||
{required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
{required super.bytes,
|
||||
required super.name,
|
||||
super.mimeType,
|
||||
this.width,
|
||||
this.height,
|
||||
this.duration})
|
||||
: super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
this.duration});
|
||||
|
||||
@override
|
||||
String get msgType => 'm.video';
|
||||
|
|
@ -379,11 +378,10 @@ class MatrixAudioFile extends MatrixFile {
|
|||
final int? duration;
|
||||
|
||||
MatrixAudioFile(
|
||||
{required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
this.duration})
|
||||
: super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
{required super.bytes,
|
||||
required super.name,
|
||||
super.mimeType,
|
||||
this.duration});
|
||||
|
||||
@override
|
||||
String get msgType => 'm.audio';
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@ class ToDeviceEvent extends BasicEventWithSender {
|
|||
|
||||
ToDeviceEvent({
|
||||
required String sender,
|
||||
required String type,
|
||||
required Map<String, dynamic> content,
|
||||
required super.type,
|
||||
required Map<String, dynamic> super.content,
|
||||
this.encryptedContent,
|
||||
}) : super(senderId: sender, type: type, content: content);
|
||||
}) : super(senderId: sender);
|
||||
|
||||
factory ToDeviceEvent.fromJson(Map<String, dynamic> json) {
|
||||
final event = BasicEventWithSender.fromJson(json);
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ dependencies:
|
|||
|
||||
dev_dependencies:
|
||||
coverage: ">=0.15.0 <2.0.0"
|
||||
file: ^6.1.1
|
||||
file: ">=6.1.1 <8.0.0"
|
||||
import_sorter: ^4.6.0
|
||||
lints: ^2.0.0
|
||||
lints: ^3.0.0
|
||||
test: ^1.15.7
|
||||
#flutter_test: {sdk: flutter}
|
||||
#dependency_overrides:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Uint8List secureRandomBytes(int len) {
|
|||
}
|
||||
|
||||
class MockSSSS extends SSSS {
|
||||
MockSSSS(Encryption encryption) : super(encryption);
|
||||
MockSSSS(super.encryption);
|
||||
|
||||
bool requestedSecrets = false;
|
||||
@override
|
||||
|
|
|
|||
Loading…
Reference in New Issue