feat: switch from pedantic to lints

This commit is contained in:
Nicolas Werner 2022-08-15 14:15:51 +00:00
parent 543875e8cf
commit 6555f36d6d
61 changed files with 367 additions and 365 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
*.pyc
*.swp
*.swo
*.swn
*.dylib
.DS_Store
.atom/

View File

@ -1,12 +1,21 @@
include: package:pedantic/analysis_options.yaml
include: package:lints/recommended.yaml
linter:
rules:
- camel_case_types
- avoid_print
- constant_identifier_names
- prefer_final_locals
- prefer_final_in_for_each
camel_case_types: true
avoid_print: true
constant_identifier_names: true
prefer_final_locals: true
prefer_final_in_for_each: true
sort_pub_dependencies: true
always_use_package_imports: true
always_declare_return_types: true
prefer_single_quotes: true
sort_child_properties_last: true
unawaited_futures: true
unsafe_html: true
avoid_function_literals_in_foreach_calls: false
non_constant_identifier_names: false # seems to wrongly diagnose static const variables
analyzer:
errors:

View File

@ -20,10 +20,10 @@ import 'dart:typed_data';
import 'package:olm/olm.dart' as olm;
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/ssss.dart';
import 'package:matrix/encryption/utils/base64_unpadded.dart';
import '../matrix.dart';
import 'encryption.dart';
import 'ssss.dart';
import 'package:matrix/matrix.dart';
class CrossSigning {
final Encryption encryption;
@ -131,14 +131,14 @@ class CrossSigning {
throw Exception('[sign] keys are not in cache but sign was called');
}
final addSignature =
(SignableKey key, SignableKey signedWith, String signature) {
void addSignature(
SignableKey key, SignableKey signedWith, String signature) {
final signedKey = key.cloneForSigning();
((signedKey.signatures ??=
<String, Map<String, String>>{})[signedWith.userId] ??=
<String, String>{})['ed25519:${signedWith.identifier}'] = signature;
signedKeys.add(signedKey);
};
}
for (final key in keys) {
if (key.userId == client.userID) {

View File

@ -21,14 +21,14 @@ import 'dart:convert';
import 'package:olm/olm.dart' as olm;
import '../matrix.dart';
import '../src/utils/run_in_root.dart';
import 'cross_signing.dart';
import 'key_manager.dart';
import 'key_verification_manager.dart';
import 'olm_manager.dart';
import 'ssss.dart';
import 'utils/bootstrap.dart';
import 'package:matrix/encryption/cross_signing.dart';
import 'package:matrix/encryption/key_manager.dart';
import 'package:matrix/encryption/key_verification_manager.dart';
import 'package:matrix/encryption/olm_manager.dart';
import 'package:matrix/encryption/ssss.dart';
import 'package:matrix/encryption/utils/bootstrap.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/run_in_root.dart';
class Encryption {
final Client client;
@ -206,10 +206,9 @@ class Encryption {
canRequestSession = false;
// we can't have the key be an int, else json-serializing will fail, thus we need it to be a string
final messageIndexKey = 'key-' + decryptResult.message_index.toString();
final messageIndexValue = event.eventId +
'|' +
event.originServerTs.millisecondsSinceEpoch.toString();
final messageIndexKey = 'key-${decryptResult.message_index}';
final messageIndexValue =
'${event.eventId}|${event.originServerTs.millisecondsSinceEpoch}';
final haveIndex =
inboundGroupSession.indexes.containsKey(messageIndexKey);
if (haveIndex &&

View File

@ -22,13 +22,13 @@ import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:olm/olm.dart' as olm;
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/utils/base64_unpadded.dart';
import 'package:matrix/encryption/utils/outbound_group_session.dart';
import 'package:matrix/encryption/utils/session_key.dart';
import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
import '../matrix.dart';
import '../src/utils/run_in_root.dart';
import './encryption.dart';
import './utils/outbound_group_session.dart';
import './utils/session_key.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/run_in_root.dart';
const megolmKey = EventTypes.MegolmBackup;
@ -445,13 +445,17 @@ class KeyManager {
if (sess != null) {
return sess;
}
_pendingNewOutboundGroupSessions[roomId] =
final newSess = _pendingNewOutboundGroupSessions[roomId] =
_createOutboundGroupSession(roomId);
try {
await _pendingNewOutboundGroupSessions[roomId];
await newSess;
} finally {
return _pendingNewOutboundGroupSessions.remove(roomId)!;
_pendingNewOutboundGroupSessions
.removeWhere((_, value) => value == newSess);
}
return newSess;
}
/// Prepares an outbound group session for a given room ID. That is, load it from
@ -794,7 +798,7 @@ class KeyManager {
/// Handle an incoming to_device event that is related to key sharing
Future<void> handleToDeviceEvent(ToDeviceEvent event) async {
if (event.type == EventTypes.RoomKeyRequest) {
if (!(event.content['request_id'] is String)) {
if (event.content['request_id'] is! String) {
return; // invalid event
}
if (event.content['action'] == 'request') {
@ -899,7 +903,7 @@ class KeyManager {
return; // someone we didn't send our request to replied....better ignore this
}
// we add the sender key to the forwarded key chain
if (!(event.content['forwarding_curve25519_key_chain'] is List)) {
if (event.content['forwarding_curve25519_key_chain'] is! List) {
event.content['forwarding_curve25519_key_chain'] = <String>[];
}
event.content['forwarding_curve25519_key_chain']

View File

@ -16,9 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../matrix.dart';
import 'encryption.dart';
import 'utils/key_verification.dart';
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/utils/key_verification.dart';
import 'package:matrix/matrix.dart';
class KeyVerificationManager {
final Encryption encryption;

View File

@ -23,11 +23,11 @@ import 'package:canonical_json/canonical_json.dart';
import 'package:collection/collection.dart';
import 'package:olm/olm.dart' as olm;
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/utils/json_signature_check_extension.dart';
import 'package:matrix/encryption/utils/olm_session.dart';
import 'package:matrix/matrix.dart';
import '../encryption/utils/json_signature_check_extension.dart';
import '../src/utils/run_in_root.dart';
import 'encryption.dart';
import 'utils/olm_session.dart';
import 'package:matrix/src/utils/run_in_root.dart';
class OlmManager {
final Encryption encryption;
@ -119,8 +119,8 @@ class OlmManager {
bool updateDatabase = true,
bool? unusedFallbackKey = false,
}) async {
final _olmAccount = this._olmAccount;
if (_olmAccount == null) {
final olmAccount = _olmAccount;
if (olmAccount == null) {
return true;
}
@ -136,22 +136,22 @@ class OlmManager {
// check if we have OTKs that still need uploading. If we do, we don't try to generate new ones,
// instead we try to upload the old ones first
final oldOTKsNeedingUpload = json
.decode(_olmAccount.one_time_keys())['curve25519']
.decode(olmAccount.one_time_keys())['curve25519']
.entries
.length as int;
// generate one-time keys
// we generate 2/3rds of max, so that other keys people may still have can
// still be used
final oneTimeKeysCount =
(_olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
(olmAccount.max_number_of_one_time_keys() * 2 / 3).floor() -
oldKeyCount -
oldOTKsNeedingUpload;
if (oneTimeKeysCount > 0) {
_olmAccount.generate_one_time_keys(oneTimeKeysCount);
olmAccount.generate_one_time_keys(oneTimeKeysCount);
}
uploadedOneTimeKeysCount = oneTimeKeysCount + oldOTKsNeedingUpload;
final Map<String, dynamic> oneTimeKeys =
json.decode(_olmAccount.one_time_keys());
json.decode(olmAccount.one_time_keys());
// now sign all the one-time keys
for (final entry in oneTimeKeys['curve25519'].entries) {
@ -166,8 +166,8 @@ class OlmManager {
final signedFallbackKeys = <String, dynamic>{};
if (encryption.isMinOlmVersion(3, 2, 0) && unusedFallbackKey == false) {
// we don't have an unused fallback key uploaded....so let's change that!
_olmAccount.generate_fallback_key();
final fallbackKey = json.decode(_olmAccount.fallback_key());
olmAccount.generate_fallback_key();
final fallbackKey = json.decode(olmAccount.fallback_key());
// now sign all the fallback keys
for (final entry in fallbackKey['curve25519'].entries) {
final key = entry.key;
@ -194,7 +194,7 @@ class OlmManager {
};
if (uploadDeviceKeys) {
final Map<String, dynamic> keys =
json.decode(_olmAccount.identity_keys());
json.decode(olmAccount.identity_keys());
for (final entry in keys.entries) {
final algorithm = entry.key;
final value = entry.value;
@ -228,7 +228,7 @@ class OlmManager {
}
// mark the OTKs as published and save that to datbase
_olmAccount.mark_keys_as_published();
olmAccount.mark_keys_as_published();
if (updateDatabase) {
await client.database?.updateClientKeys(pickledOlmAccount!);
}
@ -324,7 +324,8 @@ class OlmManager {
final device = client.userDeviceKeys[event.sender]?.deviceKeys.values
.firstWhereOrNull((d) => d.curve25519Key == senderKey);
final existingSessions = olmSessions[senderKey];
final updateSessionUsage = ([OlmSession? session]) => runInRoot(() async {
Future<void> updateSessionUsage([OlmSession? session]) =>
runInRoot(() async {
if (session != null) {
session.lastReceived = DateTime.now();
await storeOlmSession(session);
@ -480,10 +481,11 @@ class OlmManager {
return event;
}
final senderKey = event.parsedRoomEncryptedContent.senderKey;
final loadFromDb = () async {
Future<bool> loadFromDb() async {
final sessions = await getOlmSessions(senderKey);
return sessions.isNotEmpty;
};
}
if (!_olmSessions.containsKey(senderKey)) {
await loadFromDb();
}

View File

@ -25,12 +25,12 @@ import 'package:base58check/base58.dart';
import 'package:collection/collection.dart';
import 'package:crypto/crypto.dart';
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/utils/base64_unpadded.dart';
import '../matrix.dart';
import '../src/utils/crypto/crypto.dart' as uc;
import '../src/utils/run_in_root.dart';
import 'encryption.dart';
import 'utils/ssss_cache.dart';
import 'package:matrix/encryption/utils/ssss_cache.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/crypto/crypto.dart' as uc;
import 'package:matrix/src/utils/run_in_root.dart';
const cacheTypes = <String>{
EventTypes.CrossSigningSelfSigning,
@ -286,7 +286,7 @@ class SSSS {
if (keys == null) {
return null;
}
final isValid = (dbEntry) =>
bool isValid(dbEntry) =>
keys.contains(dbEntry.keyId) &&
dbEntry.ciphertext != null &&
client.accountData[type]?.content['encrypted'][dbEntry.keyId]
@ -311,10 +311,10 @@ class SSSS {
if (secretInfo == null) {
throw Exception('Not found');
}
if (!(secretInfo.content['encrypted'] is Map)) {
if (secretInfo.content['encrypted'] is! Map) {
throw Exception('Content is not encrypted');
}
if (!(secretInfo.content['encrypted'][keyId] is Map)) {
if (secretInfo.content['encrypted'][keyId] is! Map) {
throw Exception('Wrong / unknown key');
}
final enc = secretInfo.content['encrypted'][keyId];
@ -338,7 +338,7 @@ class SSSS {
Map<String, dynamic>? content;
if (add && client.accountData[type] != null) {
content = client.accountData[type]!.content.copy();
if (!(content['encrypted'] is Map)) {
if (content['encrypted'] is! Map) {
content['encrypted'] = <String, dynamic>{};
}
}
@ -526,7 +526,7 @@ class SSSS {
return; // someone replied whom we didn't send the share request to
}
final secret = event.content['secret'];
if (!(event.content['secret'] is String)) {
if (event.content['secret'] is! String) {
Logs().i('[SSSS] Secret wasn\'t a string');
return; // the secret wasn't a string....wut?
}

View File

@ -22,11 +22,11 @@ import 'dart:typed_data';
import 'package:canonical_json/canonical_json.dart';
import 'package:olm/olm.dart' as olm;
import '../../matrix.dart';
import '../encryption.dart';
import '../key_manager.dart';
import '../ssss.dart';
import 'base64_unpadded.dart';
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/encryption/key_manager.dart';
import 'package:matrix/encryption/ssss.dart';
import 'package:matrix/encryption/utils/base64_unpadded.dart';
import 'package:matrix/matrix.dart';
enum BootstrapState {
/// Is loading.
@ -104,7 +104,7 @@ class Bootstrap {
for (final entry in client.accountData.entries) {
final type = entry.key;
final event = entry.value;
if (!(event.content['encrypted'] is Map)) {
if (event.content['encrypted'] is! Map) {
continue;
}
final validKeys = <String>{};
@ -112,13 +112,13 @@ class Bootstrap {
for (final keyEntry in event.content['encrypted'].entries) {
final key = keyEntry.key;
final value = keyEntry.value;
if (!(value is Map)) {
if (value is! Map) {
// we don't add the key to invalidKeys as this was not a proper secret anyways!
continue;
}
if (!(value['iv'] is String) ||
!(value['ciphertext'] is String) ||
!(value['mac'] is String)) {
if (value['iv'] is! String ||
value['ciphertext'] is! String ||
value['mac'] is! String) {
invalidKeys.add(key);
continue;
}
@ -163,11 +163,12 @@ class Bootstrap {
(k, v) => v.isEmpty); // we don't care about the failed secrets here
final keys = <String>{};
final defaultKeyId = encryption.ssss.defaultKeyId;
final removeKey = (String key) {
int removeKey(String key) {
final sizeBefore = secrets.length;
secrets.removeWhere((k, v) => v.contains(key));
return sizeBefore - secrets.length;
};
}
// first we want to try the default key id
if (defaultKeyId != null) {
if (removeKey(defaultKeyId) > 0) {
@ -264,14 +265,15 @@ class Bootstrap {
if (oldSsssKeys != null) {
// alright, we have to re-encrypt old secrets with the new key
final secrets = analyzeSecrets();
final removeKey = (String key) {
Set<String> removeKey(String key) {
final s = secrets.entries
.where((e) => e.value.contains(key))
.map((e) => e.key)
.toSet();
secrets.removeWhere((k, v) => v.contains(key));
return s;
};
}
secretMap = <String, String>{};
for (final entry in oldSsssKeys!.entries) {
final key = entry.value;
@ -400,7 +402,7 @@ class Bootstrap {
master.free();
}
}
final _sign = (Map<String, dynamic> object) {
String? sign(Map<String, dynamic> object) {
final keyObj = olm.PkSigning();
try {
keyObj.init_with_seed(masterSigningKey);
@ -409,7 +411,8 @@ class Bootstrap {
} finally {
keyObj.free();
}
};
}
if (setupSelfSigningKey) {
final selfSigning = olm.PkSigning();
try {
@ -422,7 +425,7 @@ class Bootstrap {
'ed25519:$selfSigningPub': selfSigningPub,
},
};
final signature = _sign(json);
final signature = sign(json);
json['signatures'] = <String, dynamic>{
userID: <String, dynamic>{
'ed25519:$masterPub': signature,
@ -447,7 +450,7 @@ class Bootstrap {
'ed25519:$userSigningPub': userSigningPub,
},
};
final signature = _sign(json);
final signature = sign(json);
json['signatures'] = <String, dynamic>{
userID: <String, dynamic>{
'ed25519:$masterPub': signature,

View File

@ -19,14 +19,14 @@
import 'package:canonical_json/canonical_json.dart';
import 'package:olm/olm.dart' as olm;
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
extension JsonSignatureCheckExtension on Map<String, dynamic> {
/// Checks the signature of a signed json object.
bool checkJsonSignature(String key, String userId, String deviceId) {
final signatures = this['signatures'];
if (signatures == null ||
!(signatures is Map<String, dynamic>) ||
signatures is! Map<String, dynamic> ||
!signatures.containsKey(userId)) return false;
remove('unsigned');
remove('signatures');

View File

@ -22,8 +22,8 @@ import 'dart:typed_data';
import 'package:canonical_json/canonical_json.dart';
import 'package:olm/olm.dart' as olm;
import '../../matrix.dart';
import '../encryption.dart';
import 'package:matrix/encryption/encryption.dart';
import 'package:matrix/matrix.dart';
/*
+-------------+ +-----------+
@ -112,7 +112,7 @@ class KeyVerification {
String? get deviceId => _deviceId;
String? _deviceId;
bool startedVerification = false;
_KeyVerificationMethod? method;
_KeyVerificationMethod? _method;
List<String> possibleMethods = [];
Map<String, dynamic>? startPayload;
String? _nextAction;
@ -140,7 +140,7 @@ class KeyVerification {
void dispose() {
Logs().i('[Key Verification] disposing object...');
method?.dispose();
_method?.dispose();
}
static String? getTransactionId(Map<String, dynamic> payload) {
@ -194,7 +194,7 @@ class KeyVerification {
await Future.delayed(Duration(milliseconds: 50));
}
_handlePayloadLock = true;
Logs().i('[Key Verification] Received type $type: ' + payload.toString());
Logs().i('[Key Verification] Received type $type: $payload');
try {
var thisLastStep = lastStep;
switch (type) {
@ -272,17 +272,17 @@ class KeyVerification {
// as such, we better set it *before* we send our start
lastStep = type;
// TODO: Pick method?
final method = this.method =
_makeVerificationMethod(possibleMethods.first, this);
final method =
_method = _makeVerificationMethod(possibleMethods.first, this);
await method.sendStart();
setState(KeyVerificationState.waitingAccept);
break;
case EventTypes.KeyVerificationStart:
_deviceId ??= payload['from_device'];
transactionId ??= eventId ?? payload['transaction_id'];
if (method != null) {
if (_method != null) {
// the other side sent us a start, even though we already sent one
if (payload['method'] == method!.type) {
if (payload['method'] == _method!.type) {
// same method. Determine priority
final ourEntry = '${client.userID}|${client.deviceID}';
final entries = [ourEntry, '$userId|$deviceId'];
@ -295,7 +295,7 @@ class KeyVerification {
startedVerification = false; // it is now as if they started
thisLastStep = lastStep =
EventTypes.KeyVerificationRequest; // we fake the last step
method!.dispose(); // in case anything got created already
_method!.dispose(); // in case anything got created already
}
} else {
// methods don't match up, let's cancel this
@ -321,7 +321,7 @@ class KeyVerification {
}
}
method = _makeVerificationMethod(payload['method'], this);
_method = _makeVerificationMethod(payload['method'], this);
if (lastStep == null) {
// validate the start time
if (room != null) {
@ -330,7 +330,7 @@ class KeyVerification {
return;
}
// validate the specific payload
if (!method!.validateStart(payload)) {
if (!_method!.validateStart(payload)) {
await cancel('m.unknown_method');
return;
}
@ -338,7 +338,7 @@ class KeyVerification {
setState(KeyVerificationState.askAccept);
} else {
Logs().i('handling start in method.....');
await method!.handlePayload(type, payload);
await _method!.handlePayload(type, payload);
}
break;
case EventTypes.KeyVerificationDone:
@ -351,7 +351,7 @@ class KeyVerification {
setState(KeyVerificationState.error);
break;
default:
final method = this.method;
final method = _method;
if (method != null) {
await method.handlePayload(type, payload);
} else {
@ -382,7 +382,7 @@ class KeyVerification {
String? recoveryKey,
String? keyOrPassphrase,
bool skip = false}) async {
final next = () async {
Future<void> next() async {
if (_nextAction == 'request') {
await sendStart();
} else if (_nextAction == 'done') {
@ -390,7 +390,8 @@ class KeyVerification {
unawaited(encryption.crossSigning.sign(_verifiedDevices));
setState(KeyVerificationState.done);
}
};
}
if (skip) {
await next();
return;
@ -420,7 +421,7 @@ class KeyVerification {
});
} else {
// we need to send an accept event
await method!
await _method!
.handlePayload(EventTypes.KeyVerificationStart, startPayload!);
}
}
@ -440,20 +441,20 @@ class KeyVerification {
}
Future<void> acceptSas() async {
if (method is _KeyVerificationMethodSas) {
await (method as _KeyVerificationMethodSas).acceptSas();
if (_method is _KeyVerificationMethodSas) {
await (_method as _KeyVerificationMethodSas).acceptSas();
}
}
Future<void> rejectSas() async {
if (method is _KeyVerificationMethodSas) {
await (method as _KeyVerificationMethodSas).rejectSas();
if (_method is _KeyVerificationMethodSas) {
await (_method as _KeyVerificationMethodSas).rejectSas();
}
}
List<int> get sasNumbers {
if (method is _KeyVerificationMethodSas) {
return _bytesToInt((method as _KeyVerificationMethodSas).makeSas(5), 13)
if (_method is _KeyVerificationMethodSas) {
return _bytesToInt((_method as _KeyVerificationMethodSas).makeSas(5), 13)
.map((n) => n + 1000)
.toList();
}
@ -461,16 +462,16 @@ class KeyVerification {
}
List<String> get sasTypes {
if (method is _KeyVerificationMethodSas) {
return (method as _KeyVerificationMethodSas).authenticationTypes ?? [];
if (_method is _KeyVerificationMethodSas) {
return (_method as _KeyVerificationMethodSas).authenticationTypes ?? [];
}
return [];
}
List<KeyVerificationEmoji> get sasEmojis {
if (method is _KeyVerificationMethodSas) {
if (_method is _KeyVerificationMethodSas) {
final numbers =
_bytesToInt((method as _KeyVerificationMethodSas).makeSas(6), 6);
_bytesToInt((_method as _KeyVerificationMethodSas).makeSas(6), 6);
return numbers.map((n) => KeyVerificationEmoji(n)).toList().sublist(0, 7);
}
return [];
@ -605,7 +606,7 @@ class KeyVerification {
Future<void> send(String type, Map<String, dynamic> payload) async {
makePayload(payload);
Logs().i('[Key Verification] Sending type $type: ' + payload.toString());
Logs().i('[Key Verification] Sending type $type: $payload');
if (room != null) {
Logs().i('[Key Verification] Sending to $userId in room ${room!.id}...');
if ({EventTypes.KeyVerificationRequest}.contains(type)) {
@ -680,6 +681,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
: super(request: request);
@override
// ignore: overridden_fields
final _type = 'm.sas.v1';
String? keyAgreementProtocol;
@ -897,19 +899,13 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
'${client.userID}|${client.deviceID}|${sas!.get_pubkey()}|';
final theirInfo =
'${request.userId}|${request.deviceId}|$theirPublicKey|';
sasInfo = 'MATRIX_KEY_VERIFICATION_SAS|' +
(request.startedVerification
? ourInfo + theirInfo
: theirInfo + ourInfo) +
request.transactionId!;
sasInfo =
'MATRIX_KEY_VERIFICATION_SAS|${request.startedVerification ? ourInfo + theirInfo : theirInfo + ourInfo}${request.transactionId!}';
} else if (keyAgreementProtocol == 'curve25519') {
final ourInfo = client.userID! + client.deviceID!;
final theirInfo = request.userId + request.deviceId!;
sasInfo = 'MATRIX_KEY_VERIFICATION_SAS' +
(request.startedVerification
? ourInfo + theirInfo
: theirInfo + ourInfo) +
request.transactionId!;
sasInfo =
'MATRIX_KEY_VERIFICATION_SAS${request.startedVerification ? ourInfo + theirInfo : theirInfo + ourInfo}${request.transactionId!}';
} else {
throw Exception('Unknown key agreement protocol');
}
@ -917,12 +913,8 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
}
Future<void> _sendMac() async {
final baseInfo = 'MATRIX_KEY_VERIFICATION_MAC' +
client.userID! +
client.deviceID! +
request.userId +
request.deviceId! +
request.transactionId!;
final baseInfo =
'MATRIX_KEY_VERIFICATION_MAC${client.userID!}${client.deviceID!}${request.userId}${request.deviceId!}${request.transactionId!}';
final mac = <String, String>{};
final keyList = <String>[];
@ -944,7 +936,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
}
keyList.sort();
final keys = _calculateMac(keyList.join(','), baseInfo + 'KEY_IDS');
final keys = _calculateMac(keyList.join(','), '${baseInfo}KEY_IDS');
await request.send('m.key.verification.mac', {
'mac': mac,
'keys': keys,
@ -953,17 +945,13 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
Future<void> _processMac() async {
final payload = macPayload!;
final baseInfo = 'MATRIX_KEY_VERIFICATION_MAC' +
request.userId +
request.deviceId! +
client.userID! +
client.deviceID! +
request.transactionId!;
final baseInfo =
'MATRIX_KEY_VERIFICATION_MAC${request.userId}${request.deviceId!}${client.userID!}${client.deviceID!}${request.transactionId!}';
final keyList = payload['mac'].keys.toList();
keyList.sort();
if (payload['keys'] !=
_calculateMac(keyList.join(','), baseInfo + 'KEY_IDS')) {
_calculateMac(keyList.join(','), '${baseInfo}KEY_IDS')) {
await request.cancel('m.key_mismatch');
return;
}
@ -981,7 +969,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
await request.verifyKeys(mac, (String mac, SignableKey key) async {
return mac ==
_calculateMac(
key.ed25519Key!, baseInfo + 'ed25519:' + key.identifier!);
key.ed25519Key!, '${baseInfo}ed25519:${key.identifier!}');
});
}

View File

@ -18,7 +18,7 @@
import 'package:olm/olm.dart' as olm;
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
class OlmSession {
String identityKey;
@ -38,9 +38,8 @@ class OlmSession {
required this.lastReceived,
});
OlmSession.fromJson(Map<String, dynamic> dbEntry, String key)
: key = key,
identityKey = dbEntry['identity_key'] ?? '' {
OlmSession.fromJson(Map<String, dynamic> dbEntry, this.key)
: identityKey = dbEntry['identity_key'] ?? '' {
session = olm.Session();
try {
session!.unpickle(key, dbEntry['pickle']);

View File

@ -20,7 +20,7 @@ import 'dart:convert';
import 'package:olm/olm.dart' as olm;
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
class OutboundGroupSession {
/// The devices is a map from user id to device id to if the device is blocked.
@ -41,8 +41,7 @@ class OutboundGroupSession {
required this.outboundGroupSession,
required this.key});
OutboundGroupSession.fromJson(Map<String, dynamic> dbEntry, String key)
: key = key {
OutboundGroupSession.fromJson(Map<String, dynamic> dbEntry, this.key) {
try {
for (final entry in json.decode(dbEntry['device_ids']).entries) {
devices[entry.key] = Map<String, bool>.from(entry.value);
@ -50,8 +49,7 @@ class OutboundGroupSession {
} catch (e) {
// devices is bad (old data), so just not use this session
Logs().i(
'[OutboundGroupSession] Session in database is old, not using it. ' +
e.toString());
'[OutboundGroupSession] Session in database is old, not using it. $e');
return;
}
outboundGroupSession = olm.OutboundGroupSession();

View File

@ -20,7 +20,7 @@ import 'package:matrix_api_lite/src/utils/filter_map_extension.dart';
import 'package:olm/olm.dart' as olm;
import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
class SessionKey {
/// The raw json content of the key
@ -74,9 +74,8 @@ class SessionKey {
: indexes = indexes ?? <String, String>{},
allowedAtIndex = allowedAtIndex ?? <String, Map<String, int>>{};
SessionKey.fromDb(StoredInboundGroupSession dbEntry, String key)
: key = key,
content = Event.getMapFromPayload(dbEntry.content),
SessionKey.fromDb(StoredInboundGroupSession dbEntry, this.key)
: content = Event.getMapFromPayload(dbEntry.content),
indexes = Event.getMapFromPayload(dbEntry.indexes)
.catchMap((k, v) => MapEntry<String, String>(k, v)),
allowedAtIndex = Event.getMapFromPayload(dbEntry.allowedAtIndex)

View File

@ -19,7 +19,7 @@ extension MatrixWidgets on Room {
Future<String> addWidget(MatrixWidget widget) {
final user = client.userID;
final widgetId =
widget.name!.toLowerCase().replaceAll(RegExp(r'\W'), '_') + '_' + user!;
'${widget.name!.toLowerCase().replaceAll(RegExp(r'\W'), '_')}_${user!}';
final json = widget.toJson();
json['creatorUserId'] = user;

View File

@ -27,15 +27,15 @@ import 'package:mime/mime.dart';
import 'package:olm/olm.dart' as olm;
import 'package:random_string/random_string.dart';
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/models/timeline_chunk.dart';
import 'package:matrix/src/utils/cached_stream_controller.dart';
import 'package:matrix/src/utils/compute_callback.dart';
import 'package:matrix/src/utils/multilock.dart';
import 'package:matrix/src/utils/run_benchmarked.dart';
import 'package:matrix/src/utils/run_in_root.dart';
import 'package:matrix/src/utils/sync_update_item_count.dart';
import '../encryption.dart';
import '../matrix.dart';
import 'models/timeline_chunk.dart';
import 'utils/compute_callback.dart';
import 'utils/multilock.dart';
import 'utils/run_benchmarked.dart';
typedef RoomSorter = int Function(Room a, Room b);
@ -940,28 +940,30 @@ class Client extends MatrixApi {
try {
// stopping sync loop and subscriptions while keeping DB open
await dispose(closeDatabase: false);
} finally {
_database ??= await databaseBuilder!.call(this);
final success = await database!.importDump(export);
if (success) {
// closing including DB
await dispose();
try {
bearerToken = null;
await init(
waitForFirstSync: false,
waitUntilLoadCompletedLoaded: false,
);
} catch (e) {
return false;
}
}
return success;
} catch (_) {
// Client was probably not initialized yet.
}
_database ??= await databaseBuilder!.call(this);
final success = await database!.importDump(export);
if (success) {
// closing including DB
await dispose();
try {
bearerToken = null;
await init(
waitForFirstSync: false,
waitUntilLoadCompletedLoaded: false,
);
} catch (e) {
return false;
}
}
return success;
}
/// Uploads a new user avatar for this user. Leave file null to remove the
@ -1336,13 +1338,13 @@ class Client extends MatrixApi {
String? olmAccount;
String? accessToken;
String? _userID;
String? userID;
final account = await this.database?.getClient(clientName);
if (account != null) {
_id = account['client_id'];
homeserver = Uri.parse(account['homeserver_url']);
accessToken = this.accessToken = account['token'];
_userID = this._userID = account['user_id'];
userID = _userID = account['user_id'];
_deviceID = account['device_id'];
_deviceName = account['device_name'];
syncFilterId = account['sync_filter_id'];
@ -1352,20 +1354,20 @@ class Client extends MatrixApi {
if (newToken != null) {
accessToken = this.accessToken = newToken;
homeserver = newHomeserver;
_userID = this._userID = newUserID;
userID = _userID = newUserID;
_deviceID = newDeviceID;
_deviceName = newDeviceName;
olmAccount = newOlmAccount;
} else {
accessToken = this.accessToken = newToken ?? accessToken;
homeserver = newHomeserver ?? homeserver;
_userID = this._userID = newUserID ?? _userID;
userID = _userID = newUserID ?? userID;
_deviceID = newDeviceID ?? _deviceID;
_deviceName = newDeviceName ?? _deviceName;
olmAccount = newOlmAccount ?? olmAccount;
}
if (accessToken == null || homeserver == null || _userID == null) {
if (accessToken == null || homeserver == null || userID == null) {
if (legacyDatabaseBuilder != null) {
await _migrateFromLegacyDatabase();
if (isLogged()) return;
@ -1397,7 +1399,7 @@ class Client extends MatrixApi {
await database.updateClient(
homeserver.toString(),
accessToken,
_userID,
userID,
_deviceID,
_deviceName,
prevBatch,
@ -1408,7 +1410,7 @@ class Client extends MatrixApi {
clientName,
homeserver.toString(),
accessToken,
_userID,
userID,
_deviceID,
_deviceName,
prevBatch,
@ -1434,7 +1436,7 @@ class Client extends MatrixApi {
_initLock = false;
onLoginStateChanged.add(LoginState.loggedIn);
Logs().i(
'Successfully connected as ${userID?.localpart} with ${homeserver.toString()}',
'Successfully connected as ${userID.localpart} with ${homeserver.toString()}',
);
final syncFuture = _sync();
@ -1508,13 +1510,13 @@ class Client extends MatrixApi {
}
Future<void> _sync() {
final _currentSync = this._currentSync ??= _innerSync().whenComplete(() {
this._currentSync = null;
final currentSync = _currentSync ??= _innerSync().whenComplete(() {
_currentSync = null;
if (_backgroundSync && isLogged() && !_disposed) {
_sync();
}
});
return _currentSync;
return currentSync;
}
/// Presence that is set on sync.
@ -1533,13 +1535,13 @@ class Client extends MatrixApi {
Future<void> _innerSync() async {
await _retryDelay;
_retryDelay = Future.delayed(Duration(seconds: syncErrorTimeoutSec));
if (!isLogged() || _disposed || _aborted) return null;
if (!isLogged() || _disposed || _aborted) return;
try {
if (_initLock) {
Logs().d('Running sync while init isn\'t done yet, dropping request');
return;
}
var syncError;
dynamic syncError;
await _checkSyncFilter();
final syncRequest = sync(
filter: syncFilterId,

View File

@ -22,8 +22,8 @@ import 'package:matrix/encryption/utils/olm_session.dart';
import 'package:matrix/encryption/utils/outbound_group_session.dart';
import 'package:matrix/encryption/utils/ssss_cache.dart';
import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/queued_to_device_event.dart';
import '../../matrix.dart';
abstract class DatabaseApi {
int get maxFileSize => 1 * 1024 * 1024;
@ -154,7 +154,7 @@ abstract class DatabaseApi {
);
Future storeOlmSession(
String identitiyKey,
String identityKey,
String sessionId,
String pickle,
int lastReceived,

View File

@ -448,9 +448,9 @@ class FluffyBoxDatabase extends DatabaseApi {
@override
Future<List<OlmSession>> getOlmSessionsForDevices(
List<String> identityKey, String userId) async {
List<String> identityKeys, String userId) async {
final sessions = await Future.wait(
identityKey.map((identityKey) => getOlmSessions(identityKey, userId)));
identityKeys.map((identityKey) => getOlmSessions(identityKey, userId)));
return <OlmSession>[for (final sublist in sessions) ...sublist];
}
@ -1433,10 +1433,9 @@ class FluffyBoxDatabase extends DatabaseApi {
Future<void> addSeenDeviceId(
String userId,
String deviceId,
String publicKeysHash,
String publicKeys,
) =>
_seenDeviceIdsBox.put(
TupleKey(userId, deviceId).toString(), publicKeysHash);
_seenDeviceIdsBox.put(TupleKey(userId, deviceId).toString(), publicKeys);
@override
Future<void> addSeenPublicKey(

View File

@ -474,9 +474,9 @@ class HiveCollectionsDatabase extends DatabaseApi {
@override
Future<List<OlmSession>> getOlmSessionsForDevices(
List<String> identityKey, String userId) async {
List<String> identityKeys, String userId) async {
final sessions = await Future.wait(
identityKey.map((identityKey) => getOlmSessions(identityKey, userId)));
identityKeys.map((identityKey) => getOlmSessions(identityKey, userId)));
return <OlmSession>[for (final sublist in sessions) ...sublist];
}
@ -1459,10 +1459,9 @@ class HiveCollectionsDatabase extends DatabaseApi {
Future<void> addSeenDeviceId(
String userId,
String deviceId,
String publicKeysHash,
String publicKeys,
) =>
_seenDeviceIdsBox.put(
TupleKey(userId, deviceId).toString(), publicKeysHash);
_seenDeviceIdsBox.put(TupleKey(userId, deviceId).toString(), publicKeys);
@override
Future<void> addSeenPublicKey(
@ -1611,6 +1610,9 @@ class TupleKey {
@override
bool operator ==(other) => parts.toString() == other.toString();
@override
int get hashCode => Object.hashAll(parts);
}
dynamic _castValue(dynamic value) {

View File

@ -505,9 +505,9 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
@override
Future<List<OlmSession>> getOlmSessionsForDevices(
List<String> identityKey, String userId) async {
List<String> identityKeys, String userId) async {
final sessions = await Future.wait(
identityKey.map((identityKey) => getOlmSessions(identityKey, userId)));
identityKeys.map((identityKey) => getOlmSessions(identityKey, userId)));
return <OlmSession>[for (final sublist in sessions) ...sublist];
}
@ -1380,10 +1380,9 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
Future<void> addSeenDeviceId(
String userId,
String deviceId,
String publicKeysHash,
String publicKeys,
) =>
_seenDeviceIdsBox.put(
MultiKey(userId, deviceId).toString(), publicKeysHash);
_seenDeviceIdsBox.put(MultiKey(userId, deviceId).toString(), publicKeys);
@override
Future<void> addSeenPublicKey(
@ -1461,6 +1460,9 @@ class MultiKey {
@override
bool operator ==(other) => parts.toString() == other.toString();
@override
int get hashCode => Object.hashAll(parts);
}
extension HiveKeyExtension on String {

View File

@ -23,11 +23,11 @@ import 'package:collection/collection.dart';
import 'package:html/parser.dart';
import 'package:http/http.dart' as http;
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/event_localizations.dart';
import 'package:matrix/src/utils/file_send_request_credentials.dart';
import '../matrix.dart';
import 'utils/event_localizations.dart';
import 'utils/html_to_text.dart';
import 'utils/markdown.dart';
import 'package:matrix/src/utils/html_to_text.dart';
import 'package:matrix/src/utils/markdown.dart';
abstract class RelationshipTypes {
static const String reply = 'm.in_reply_to';
@ -296,7 +296,7 @@ class Event extends MatrixEvent {
if (redacted) return 'Redacted';
if (text != '') return text;
if (formattedText != '') return formattedText;
return '$type';
return type;
}
/// Use this to get a plain-text representation of the event, stripping things
@ -870,7 +870,7 @@ class Event extends MatrixEvent {
bool get onlyEmotes {
if (isRichMessage) {
final formattedTextStripped = formattedText.replaceAll(
RegExp('<mx-reply>.*<\/mx-reply>',
RegExp('<mx-reply>.*</mx-reply>',
caseSensitive: false, multiLine: false, dotAll: true),
'');
return _onlyEmojiEmoteRegex.hasMatch(formattedTextStripped);
@ -886,7 +886,7 @@ class Event extends MatrixEvent {
int get numberEmotes {
if (isRichMessage) {
final formattedTextStripped = formattedText.replaceAll(
RegExp('<mx-reply>.*<\/mx-reply>',
RegExp('<mx-reply>.*</mx-reply>',
caseSensitive: false, multiLine: false, dotAll: true),
'');
return _countEmojiEmoteRegex.allMatches(formattedTextStripped).length;

View File

@ -1,4 +1,4 @@
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
class TimelineChunk {
String prevBatch; // pos of the first event of the database timeline chunk

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../matrix.dart';
import 'package:matrix/matrix.dart';
class CachedPresence {
PresenceType presence;
@ -45,9 +45,7 @@ class CachedPresence {
: this(event.presence, event.lastActiveAgo, event.statusMsg,
event.currentlyActive, userid);
CachedPresence.neverSeen(String userid)
: presence = PresenceType.offline,
userid = userid;
CachedPresence.neverSeen(this.userid) : presence = PresenceType.offline;
Presence toPresence() {
final content = <String, dynamic>{

View File

@ -23,14 +23,14 @@ import 'dart:typed_data';
import 'package:collection/collection.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/models/timeline_chunk.dart';
import 'package:matrix/src/utils/cached_stream_controller.dart';
import 'package:matrix/src/utils/crypto/crypto.dart';
import 'package:matrix/src/utils/file_send_request_credentials.dart';
import 'package:matrix/src/utils/markdown.dart';
import 'package:matrix/src/utils/marked_unread.dart';
import 'package:matrix/src/utils/space_child.dart';
import '../matrix.dart';
import 'utils/markdown.dart';
import 'utils/marked_unread.dart';
enum PushRuleState { notify, mentionsOnly, dontNotify }
@ -907,7 +907,7 @@ class Room {
}
inPrefix = false;
temp += temp.isEmpty ? l : ('\n' + l);
temp += temp.isEmpty ? l : ('\n$l');
}
return temp;
@ -936,7 +936,7 @@ class Room {
if (inReplyTo != null) {
var replyText =
'<${inReplyTo.senderId}> ' + _stripBodyFallback(inReplyTo.body);
'<${inReplyTo.senderId}> ${_stripBodyFallback(inReplyTo.body)}';
replyText = replyText.split('\n').map((line) => '> $line').join('\n');
content['format'] = 'org.matrix.custom.html';
// be sure that we strip any previous reply fallbacks
@ -971,10 +971,10 @@ class Room {
'rel_type': RelationshipTypes.edit,
};
if (content['body'] is String) {
content['body'] = '* ' + content['body'];
content['body'] = '* ${content['body']}';
}
if (content['formatted_body'] is String) {
content['formatted_body'] = '* ' + content['formatted_body'];
content['formatted_body'] = '* ${content['formatted_body']}';
}
}
final sentDate = DateTime.now();
@ -1113,7 +1113,7 @@ class Room {
/// power level event, there might something broken and this returns null.
Future<String> setPower(String userID, int power) async {
var powerMap = getState(EventTypes.RoomPowerLevels)?.content;
if (!(powerMap is Map<String, dynamic>)) {
if (powerMap is! Map<String, dynamic>) {
powerMap = <String, dynamic>{};
}
(powerMap['users'] ??= {})[userID] = power;
@ -1155,7 +1155,7 @@ class Room {
if (onHistoryReceived != null) onHistoryReceived();
this.prev_batch = resp.end;
final loadFn = () async {
Future<void> loadFn() async {
if (!((resp.chunk.isNotEmpty) && resp.end != null)) return;
await client.handleSync(
@ -1196,7 +1196,7 @@ class Room {
: null),
),
direction: Direction.b);
};
}
if (client.database != null) {
await client.database?.transaction(() async {
@ -1331,7 +1331,7 @@ class Room {
String? eventContextId}) async {
await postLoad();
var events;
List<Event> events;
if (!isArchived) {
events = await client.database?.getEventList(
@ -1762,7 +1762,7 @@ class Room {
PushRuleState get pushRuleState {
final globalPushRules =
client.accountData['m.push_rules']?.content['global'];
if (!(globalPushRules is Map)) {
if (globalPushRules is! Map) {
return PushRuleState.notify;
}
@ -1794,7 +1794,7 @@ class Room {
/// Sends a request to the homeserver to set the [PushRuleState] for this room.
/// Returns ErrorResponse if something goes wrong.
Future<void> setPushRuleState(PushRuleState newState) async {
if (newState == pushRuleState) return null;
if (newState == pushRuleState) return;
dynamic resp;
switch (newState) {
// All push notifications should be sent to the user
@ -2076,6 +2076,9 @@ class Room {
@override
bool operator ==(dynamic other) => (other is Room && other.id == id);
@override
int get hashCode => Object.hashAll([id]);
}
enum EncryptionHealthState {

View File

@ -19,10 +19,10 @@
import 'dart:async';
import 'dart:convert';
import 'package:collection/src/iterable_extensions.dart';
import 'package:collection/collection.dart';
import '../matrix.dart';
import 'models/timeline_chunk.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/models/timeline_chunk.dart';
/// Represents the timeline of a room. The callback [onUpdate] will be triggered
/// automatically. The initial
@ -305,7 +305,7 @@ class Timeline {
void _sessionKeyReceived(String sessionId) async {
var decryptAtLeastOneEvent = false;
final decryptFn = () async {
Future<void> decryptFn() async {
final encryption = room.client.encryption;
if (!room.client.encryptionEnabled || encryption == null) {
return;
@ -322,7 +322,8 @@ class Timeline {
}
}
}
};
}
if (room.client.database != null) {
await room.client.database?.transaction(decryptFn);
} else {

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../matrix.dart';
import 'package:matrix/matrix.dart';
/// Represents a Matrix User which may be a participant in a Matrix Room.
class User extends Event {
@ -80,7 +80,7 @@ class User extends Event {
/// ban
Membership get membership => Membership.values.firstWhere((e) {
if (content['membership'] != null) {
return e.toString() == 'Membership.' + content['membership'];
return e.toString() == 'Membership.${content['membership']}';
}
return false;
}, orElse: () => Membership.join);
@ -197,6 +197,9 @@ class User extends Event {
other.room == room &&
other.membership == membership);
@override
int get hashCode => Object.hash(id, room, membership);
/// Get the mention text to use in a plain text body to mention this specific user
/// in this specific room
String get mention {
@ -210,11 +213,8 @@ class User extends Event {
return id;
}
final identifier = '@' +
// if we have non-word characters we need to surround with []
(RegExp(r'^\w+$').hasMatch(displayName)
? displayName
: '[$displayName]');
final identifier =
'@${RegExp(r'^\w+$').hasMatch(displayName) ? displayName : '[$displayName]'}';
// get all the users with the same display name
final allUsersWithSameDisplayname = room.getParticipants();
@ -243,11 +243,8 @@ class User extends Event {
{'[', ']', ':'}.any(displayName.contains)) {
return {};
}
final identifier = '@' +
// if we have non-word characters we need to surround with []
(RegExp(r'^\w+$').hasMatch(displayName)
? displayName
: '[$displayName]');
final identifier =
'@${RegExp(r'^\w+$').hasMatch(displayName) ? displayName : '[$displayName]'}';
final hash = _hash(id);
return {identifier, '$identifier#$hash'};

View File

@ -18,7 +18,7 @@
import 'dart:async';
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
extension CommandsClientExtension on Client {
/// Add a command to the command handler. `command` is its name, and `callback` is the

View File

@ -20,7 +20,7 @@ import 'dart:convert';
import 'dart:typed_data';
import 'package:matrix/encryption/utils/base64_unpadded.dart';
import 'crypto.dart';
import 'package:matrix/src/utils/crypto/crypto.dart';
class EncryptedFile {
EncryptedFile({

View File

@ -3,8 +3,8 @@
import 'dart:typed_data';
import 'subtle.dart' as subtle;
import 'subtle.dart';
import 'package:matrix/src/utils/crypto/subtle.dart' as subtle;
import 'package:matrix/src/utils/crypto/subtle.dart';
abstract class Hash {
Hash._(this.name);

View File

@ -4,7 +4,7 @@ import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'ffi.dart';
import 'package:matrix/src/utils/crypto/ffi.dart';
abstract class Hash {
Hash._(this.ptr);

View File

@ -22,8 +22,8 @@ import 'package:canonical_json/canonical_json.dart';
import 'package:collection/collection.dart' show IterableExtension;
import 'package:olm/olm.dart' as olm;
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
import '../../encryption.dart';
enum UserVerifiedStatus { verified, unknown, unknownDevice }
@ -349,6 +349,9 @@ abstract class SignableKey extends MatrixSignableKey {
bool operator ==(dynamic other) => (other is SignableKey &&
other.userId == userId &&
other.identifier == identifier);
@override
int get hashCode => Object.hash(userId, identifier);
}
class CrossSigningKey extends SignableKey {

View File

@ -18,8 +18,8 @@
import 'package:collection/collection.dart';
import '../../encryption.dart';
import '../../matrix.dart';
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
abstract class EventLocalizations {
// As we need to create the localized body off of a different set of parameters, we
@ -54,16 +54,16 @@ abstract class EventLocalizations {
String errorText;
switch (event.body) {
case DecryptException.channelCorrupted:
errorText = i18n.channelCorruptedDecryptError + '.';
errorText = '${i18n.channelCorruptedDecryptError}.';
break;
case DecryptException.notEnabled:
errorText = i18n.encryptionNotEnabled + '.';
errorText = '${i18n.encryptionNotEnabled}.';
break;
case DecryptException.unknownAlgorithm:
errorText = i18n.unknownEncryptionAlgorithm + '.';
errorText = '${i18n.unknownEncryptionAlgorithm}.';
break;
case DecryptException.unknownSession:
errorText = i18n.noPermission + '.';
errorText = '${i18n.noPermission}.';
break;
default:
errorText = body;
@ -240,7 +240,7 @@ abstract class EventLocalizations {
var localizedBody = i18n.activatedEndToEndEncryption(
event.senderFromMemoryOrFallback.calcDisplayname());
if (event.room.client.encryptionEnabled == false) {
localizedBody += '. ' + i18n.needPantalaimonWarning;
localizedBody += '. ${i18n.needPantalaimonWarning}';
}
return localizedBody;
},

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
enum EventUpdateType {
timeline,

View File

@ -32,7 +32,7 @@ class HtmlToText {
// miss-matching tags, and this way we actually correctly identify what we want to strip and, well,
// strip it.
final renderHtml = html.replaceAll(
RegExp('<mx-reply>.*<\/mx-reply>',
RegExp('<mx-reply>.*</mx-reply>',
caseSensitive: false, multiLine: false, dotAll: true),
'');
@ -84,7 +84,7 @@ class HtmlToText {
static String _parseBlockquoteContent(_ConvertOpts opts, Element node) {
final msg = _walkChildNodes(opts, node);
return msg.split('\n').map((s) => '> $s').join('\n') + '\n';
return '${msg.split('\n').map((s) => '> $s').join('\n')}\n';
}
static String _parseSpanContent(_ConvertOpts opts, Element node) {
@ -109,10 +109,7 @@ class HtmlToText {
return entries
.map((s) =>
(' ' * opts.listDepth) +
bulletPoint +
' ' +
s.replaceAll('\n', '\n' + (' ' * opts.listDepth) + ' '))
'${' ' * opts.listDepth}$bulletPoint ${s.replaceAll('\n', '\n${' ' * opts.listDepth} ')}')
.join('\n');
}
@ -128,9 +125,7 @@ class HtmlToText {
return entries
.mapIndexed((index, s) =>
(' ' * opts.listDepth) +
'${start + index}. ' +
s.replaceAll('\n', '\n' + (' ' * opts.listDepth) + ' '))
'${' ' * opts.listDepth}${start + index}. ${s.replaceAll('\n', '\n${' ' * opts.listDepth} ')}')
.join('\n');
}

View File

@ -20,7 +20,7 @@ import 'dart:async';
import 'package:http/http.dart' as http;
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
/// Stream.timeout fails if no progress is made in timeLimit.
/// In contrast, streamTotalTimeout fails if the stream isn't completed
@ -68,10 +68,6 @@ class FixedTimeoutHttpClient extends TimeoutHttpClient {
FixedTimeoutHttpClient(http.Client inner, this.timeout) : super(inner);
@override
Duration timeout;
@override
Future<http.StreamedResponse> send(http.BaseRequest request) =>
super.send(request);
}
class VariableTimeoutHttpClient extends TimeoutHttpClient {

View File

@ -19,14 +19,15 @@
import 'package:matrix_api_lite/matrix_api_lite.dart';
import 'package:slugify/slugify.dart';
import '../room.dart';
import 'package:matrix/src/room.dart';
extension ImagePackRoomExtension on Room {
/// Get all the active image packs for the specified [usage], mapped by their slug
Map<String, ImagePackContent> getImagePacks([ImagePackUsage? usage]) {
final allMxcs = <Uri>{}; // used for easy deduplication
final packs = <String, ImagePackContent>{};
final addImagePack = (BasicEvent? event, {Room? room, String? slug}) {
void addImagePack(BasicEvent? event, {Room? room, String? slug}) {
if (event == null) return;
final imagePack = event.parsedImagePackContent;
final finalSlug = slugify(slug ?? 'pack');
@ -53,7 +54,8 @@ extension ImagePackRoomExtension on Room {
.images[entry.key] = image;
allMxcs.add(image.url);
}
};
}
// first we add the user image pack
addImagePack(client.accountData['im.ponies.user_emotes'], slug: 'user');
// next we add all the external image packs

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:matrix_api_lite/src/utils/try_get_map_extension.dart';
import 'package:matrix_api_lite/matrix_api_lite.dart';
mixin EventType {
static const String markedUnread = 'com.famedly.marked_unread';

View File

@ -25,8 +25,8 @@ import 'package:blurhash_dart/blurhash_dart.dart';
import 'package:image/image.dart';
import 'package:mime/mime.dart';
import '../../matrix.dart';
import 'compute_callback.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/compute_callback.dart';
class MatrixFile {
final Uint8List bytes;

View File

@ -81,14 +81,8 @@ extension MatrixIdExtension on String {
}
return uri.replace(pathSegments: identifiers);
} else if (toLowerCase().startsWith(matrixToPrefix)) {
return Uri.tryParse('//' +
substring(matrixToPrefix.length - 1)
.replaceAllMapped(
RegExp(r'(?<=/)[#!@+][^:]*:|(\?.*$)'),
(m) => m[0]!.replaceAllMapped(
RegExp(m.group(1) != null ? '' : '[/?]'),
(m) => Uri.encodeComponent(m.group(0)!)))
.replaceAll('#', '%23'));
return Uri.tryParse(
'//${substring(matrixToPrefix.length - 1).replaceAllMapped(RegExp(r'(?<=/)[#!@+][^:]*:|(\?.*$)'), (m) => m[0]!.replaceAllMapped(RegExp(m.group(1) != null ? '' : '[/?]'), (m) => Uri.encodeComponent(m.group(0)!))).replaceAll('#', '%23')}');
} else {
return Uri(
pathSegments: RegExp(r'/((?:[#!@+][^:]*:)?[^/?]*)(?:\?.*$)?')

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../room.dart';
import 'package:matrix/src/room.dart';
abstract class MatrixLocalizations {
const MatrixLocalizations();

View File

@ -3,7 +3,7 @@ import 'dart:typed_data';
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
import 'compute_callback.dart';
import 'package:matrix/src/utils/compute_callback.dart';
/// provides native implementations for demanding arithmetic operations
/// in order to prevent the UI from blocking

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../user.dart';
import 'package:matrix/src/user.dart';
/// Represents a receipt.
/// This [user] has read an event at the given [time].
@ -30,4 +30,7 @@ class Receipt {
bool operator ==(dynamic other) => (other is Receipt &&
other.user == user &&
other.time.microsecondsSinceEpoch == time.microsecondsSinceEpoch);
@override
int get hashCode => Object.hash(user, time);
}

View File

@ -18,7 +18,7 @@
import 'dart:async';
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
Future<T?> runInRoot<T>(FutureOr<T> Function() fn) async {
return await Zone.root.run(() async {

View File

@ -18,7 +18,7 @@
import 'package:matrix_api_lite/matrix_api_lite.dart';
import '../event.dart';
import 'package:matrix/src/event.dart';
class SpaceChild {
final String? roomId;

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
/// This extension adds easy-to-use filters for the sync update, meant to be used on the `client.onSync` stream, e.g.
/// `client.onSync.stream.where((s) => s.hasRoomUpdate)`. Multiple filters can easily be

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
class ToDeviceEvent extends BasicEventWithSender {
Map<String, dynamic>? encryptedContent;

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import '../../matrix.dart';
import 'package:matrix/matrix.dart';
enum UiaRequestState {
/// The request is done

View File

@ -18,7 +18,7 @@
import 'dart:core';
import '../client.dart';
import 'package:matrix/src/client.dart';
extension MxcUriExtension on Uri {
/// Returns a download Link to this content.

View File

@ -11,7 +11,7 @@ import 'package:js/js_util.dart';
import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart' hide Event;
import 'native_implementations_web_worker.dart';
import 'package:matrix/src/utils/web_worker/native_implementations_web_worker.dart';
///
///

View File

@ -21,8 +21,8 @@ import 'dart:core';
import 'package:webrtc_interface/webrtc_interface.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/cached_stream_controller.dart';
import '../../matrix.dart';
/// https://github.com/matrix-org/matrix-doc/pull/2746
/// version 1
@ -997,7 +997,7 @@ class CallSession {
}
Future<void> onRejectReceived(String? reason) async {
Logs().v('[VOIP] Reject received for call ID ' + callId);
Logs().v('[VOIP] Reject received for call ID $callId');
// No need to check party_id for reject because if we'd received either
// an answer or reject, we wouldn't be in state InviteSent
final shouldTerminate = (state == CallState.kFledgling &&

View File

@ -28,5 +28,5 @@ String roomAliasFromRoomName(String roomName) {
}
String genCallID() {
return '${DateTime.now().millisecondsSinceEpoch}' + randomAlphaNumeric(16);
return '${DateTime.now().millisecondsSinceEpoch}${randomAlphaNumeric(16)}';
}

View File

@ -4,8 +4,8 @@ import 'dart:core';
import 'package:sdp_transform/sdp_transform.dart' as sdp_transform;
import 'package:webrtc_interface/webrtc_interface.dart';
import 'package:matrix/matrix.dart';
import 'package:matrix/src/utils/cached_stream_controller.dart';
import '../../matrix.dart';
/// Delegate WebRTC basic functionality.
abstract class WebRTCDelegate {
@ -317,7 +317,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('Reject received for call ID ' + callId);
Logs().d('Reject received for call ID $callId');
final call = calls[callId];
if (call != null) {
@ -339,7 +339,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('onCallReplaces received for call ID ' + callId);
Logs().d('onCallReplaces received for call ID $callId');
final call = calls[callId];
if (call != null) {
if (call.room.id != roomId) {
@ -358,7 +358,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('SelectAnswer received for call ID ' + callId);
Logs().d('SelectAnswer received for call ID $callId');
final call = calls[callId];
final String selectedPartyId = content['selected_party_id'];
@ -379,7 +379,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('SDP Stream metadata received for call ID ' + callId);
Logs().d('SDP Stream metadata received for call ID $callId');
final call = calls[callId];
if (call != null) {
if (call.room.id != roomId) {
@ -404,7 +404,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('Asserted identity received for call ID ' + callId);
Logs().d('Asserted identity received for call ID $callId');
final call = calls[callId];
if (call != null) {
if (call.room.id != roomId) {
@ -429,7 +429,7 @@ class VoIP {
return;
}
final String callId = content['call_id'];
Logs().d('Negotiate received for call ID ' + callId);
Logs().d('Negotiate received for call ID $callId');
final call = calls[callId];
if (call != null) {
if (call.room.id != roomId) {

View File

@ -9,33 +9,33 @@ environment:
dependencies:
async: ^2.8.0
blurhash_dart: ^1.1.0
http: ^0.13.0
mime: ^1.0.0
canonical_json: ^1.1.0
markdown: ^4.0.0
html_unescape: ^2.0.0
random_string: ^2.3.1
crypto: ^3.0.0
base58check: ^2.0.0
olm: ^2.0.0
matrix_api_lite: ^1.1.0
hive: ^2.2.1
image: ^3.1.1
ffi: ^1.0.0
js: ^0.6.3
slugify: ^2.0.0
html: ^0.15.0
blurhash_dart: ^1.1.0
canonical_json: ^1.1.0
collection: ^1.15.0
webrtc_interface: ^1.0.1
sdp_transform: ^0.3.2
crypto: ^3.0.0
ffi: ^1.0.0
fluffybox: ^0.4.3
hive: ^2.2.1
html: ^0.15.0
html_unescape: ^2.0.0
http: ^0.13.0
image: ^3.1.1
js: ^0.6.3
markdown: ^4.0.0
matrix_api_lite: ^1.1.0
mime: ^1.0.0
olm: ^2.0.0
random_string: ^2.3.1
sdp_transform: ^0.3.2
slugify: ^2.0.0
webrtc_interface: ^1.0.1
dev_dependencies:
import_sorter: ^4.6.0
dart_code_metrics: ^4.10.1
pedantic: ^1.11.0
test: ^1.15.7
coverage: ">=0.15.0 <2.0.0"
dart_code_metrics: ^4.10.1
file: ^6.1.1
import_sorter: ^4.6.0
lints: ^2.0.0
test: ^1.15.7
#flutter_test: {sdk: flutter}

File diff suppressed because one or more lines are too long

View File

@ -31,15 +31,15 @@ void main() {
late Room room;
var olmEnabled = true;
final getLastMessagePayload =
([String type = 'm.room.message', String? stateKey]) {
Map<String, dynamic> getLastMessagePayload(
[String type = 'm.room.message', String? stateKey]) {
final state = stateKey != null;
return json.decode(FakeMatrixApi.calledEndpoints.entries
.firstWhere((e) => e.key.startsWith(
'/client/v3/rooms/${Uri.encodeComponent(room.id)}/${state ? 'state' : 'send'}/${Uri.encodeComponent(type)}${state && stateKey?.isNotEmpty == true ? '/' + Uri.encodeComponent(stateKey!) : ''}'))
'/client/v3/rooms/${Uri.encodeComponent(room.id)}/${state ? 'state' : 'send'}/${Uri.encodeComponent(type)}${state && stateKey?.isNotEmpty == true ? '/${Uri.encodeComponent(stateKey!)}' : ''}'))
.value
.first);
};
}
test('setupClient', () async {
try {
@ -57,7 +57,7 @@ void main() {
stateKey: '',
eventId: '\$fakeeventid',
originServerTs: DateTime.now(),
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
));
room.setState(Event(
type: 'm.room.member',
@ -66,7 +66,7 @@ void main() {
stateKey: client.userID,
eventId: '\$fakeeventid',
originServerTs: DateTime.now(),
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
));
});

View File

@ -128,7 +128,7 @@ void main() {
var decoded = SSSS.decodeRecoveryKey(encoded);
expect(key, decoded);
decoded = SSSS.decodeRecoveryKey(encoded + ' \n\t');
decoded = SSSS.decodeRecoveryKey('$encoded \n\t');
expect(key, decoded);
final handle = client.encryption!.ssss.open();

View File

@ -1043,7 +1043,7 @@ void main() {
'# Title\nsome text and [link](https://example.com)\nokay and this is **important**',
'format': 'org.matrix.custom.html',
'formatted_body':
'<h1>Title</h1>\n<p>some text and <a href=\"https://example.com\">link</a><br>okay and this is <strong>important</strong></p>\n',
'<h1>Title</h1>\n<p>some text and <a href="https://example.com">link</a><br>okay and this is <strong>important</strong></p>\n',
'msgtype': 'm.text'
},
'event_id': '\$143273582443PhrSn:example.org',
@ -1253,12 +1253,13 @@ void main() {
test('attachments', () async {
final FILE_BUFF = Uint8List.fromList([0]);
final THUMBNAIL_BUFF = Uint8List.fromList([2]);
final downloadCallback = (Uri uri) async {
Future<Uint8List> downloadCallback(Uri uri) async {
return {
'/_matrix/media/v3/download/example.org/file': FILE_BUFF,
'/_matrix/media/v3/download/example.org/thumb': THUMBNAIL_BUFF,
}[uri.path]!;
};
}
await client.checkHomeserver(Uri.parse('https://fakeserver.notexisting'),
checkWellKnown: false);
final room = Room(id: '!localpart:server.abc', client: client);
@ -1344,12 +1345,13 @@ void main() {
Uint8List.fromList([0x55, 0xD7, 0xEB, 0x72, 0x05, 0x13]);
final THUMB_BUFF_DEC =
Uint8List.fromList([0x74, 0x68, 0x75, 0x6D, 0x62, 0x0A]);
final downloadCallback = (Uri uri) async {
Future<Uint8List> downloadCallback(Uri uri) async {
return {
'/_matrix/media/v3/download/example.com/file': FILE_BUFF_ENC,
'/_matrix/media/v3/download/example.com/thumb': THUMB_BUFF_ENC,
}[uri.path]!;
};
}
final room = Room(id: '!localpart:server.abc', client: await getClient());
var event = Event.fromJson({
'type': EventTypes.Message,
@ -1440,12 +1442,13 @@ void main() {
test('downloadAndDecryptAttachment store', () async {
final FILE_BUFF = Uint8List.fromList([0]);
var serverHits = 0;
final downloadCallback = (Uri uri) async {
Future<Uint8List> downloadCallback(Uri uri) async {
serverHits++;
return {
'/_matrix/media/v3/download/example.org/newfile': FILE_BUFF,
}[uri.path]!;
};
}
await client.checkHomeserver(Uri.parse('https://fakeserver.notexisting'),
checkWellKnown: false);
final room = Room(id: '!localpart:server.abc', client: await getClient());
@ -1606,7 +1609,7 @@ void main() {
''',
'format': 'org.matrix.custom.html',
'formatted_body':
'\<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>😒😒</blockquote></mx-reply>❤❤❤'
'<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>😒😒</blockquote></mx-reply>❤❤❤'
},
'event_id': '\$edit2',
'sender': '@alice:example.org',
@ -1622,7 +1625,7 @@ void main() {
''',
'format': 'org.matrix.custom.html',
'formatted_body':
'\<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>A 😒</blockquote></mx-reply>❤❤'
'<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>A 😒</blockquote></mx-reply>❤❤'
},
'event_id': '\$edit2',
'sender': '@alice:example.org',
@ -1638,7 +1641,7 @@ void main() {
A''',
'format': 'org.matrix.custom.html',
'formatted_body':
'\<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>😒😒😒</blockquote></mx-reply>❤A❤'
'<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>😒😒😒</blockquote></mx-reply>❤A❤'
},
'event_id': '\$edit2',
'sender': '@alice:example.org',
@ -1654,7 +1657,7 @@ void main() {
A''',
'format': 'org.matrix.custom.html',
'formatted_body':
'\<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>A😒</blockquote></mx-reply>❤A❤'
'<mx-reply><blockquote><a href="https://fakeserver.notexisting/\$jEsUZKDJdhlrceRyVU">In reply to</a> <a href="https://fakeserver.notexisting/@alice:example.org">@alice:example.org</a><br>A😒</blockquote></mx-reply>❤A❤'
},
'event_id': '\$edit2',
'sender': '@alice:example.org',

View File

@ -92,7 +92,7 @@ class FakeMatrixApi extends BaseClient {
var action = request.url.path;
if (request.url.path.contains('/_matrix')) {
action =
request.url.path.split('/_matrix').last + '?' + request.url.query;
'${request.url.path.split('/_matrix').last}?${request.url.query}';
}
// ignore: avoid_print

View File

@ -45,7 +45,7 @@ void main() {
content: {'membership': 'join'},
room: room,
stateKey: client.userID,
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid2:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -63,7 +63,7 @@ void main() {
content: {'membership': 'join'},
room: room,
stateKey: client.userID,
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid4:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -81,7 +81,7 @@ void main() {
},
room: room,
stateKey: '',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid5:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -110,7 +110,7 @@ void main() {
},
room: room,
stateKey: '',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid6:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -135,7 +135,7 @@ void main() {
},
room: room,
stateKey: '',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid7:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -158,7 +158,7 @@ void main() {
},
room: room,
stateKey: 'fox',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid8:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -201,7 +201,7 @@ void main() {
},
room: room2,
stateKey: '',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid9:fakeServer.notExisting',
originServerTs: DateTime.now(),
));
@ -234,7 +234,7 @@ void main() {
},
room: room2,
stateKey: 'fox',
senderId: '\@fakeuser:fakeServer.notExisting',
senderId: '@fakeuser:fakeServer.notExisting',
eventId: '\$fakeid10:fakeServer.notExisting',
originServerTs: DateTime.now(),
));

View File

@ -40,7 +40,7 @@ void main() {
'@[Fast Fox]#123': '@fastfox:example.org',
'@[">]': '@blah:example.org',
};
final getMention = (mention) => mentionMap[mention];
String? getMention(mention) => mentionMap[mention];
test('simple markdown', () {
expect(markdown('hey *there* how are **you** doing?'),
'hey <em>there</em> how are <strong>you</strong> doing?');

View File

@ -139,7 +139,7 @@ void main() {
group('Sync Filters', () {
Logs().level = Level.error;
test('room update', () {
final testFn = (SyncUpdate s) => s.hasRoomUpdate;
bool testFn(SyncUpdate s) => s.hasRoomUpdate;
final expected = {
'empty': false,
'presence': false,
@ -153,7 +153,7 @@ void main() {
});
test('presence update', () {
final testFn = (SyncUpdate s) => s.hasPresenceUpdate;
bool testFn(SyncUpdate s) => s.hasPresenceUpdate;
final expected = {
'empty': false,
'presence': true,