feat: switch from pedantic to lints
This commit is contained in:
parent
543875e8cf
commit
6555f36d6d
|
|
@ -4,6 +4,7 @@
|
|||
*.pyc
|
||||
*.swp
|
||||
*.swo
|
||||
*.swn
|
||||
*.dylib
|
||||
.DS_Store
|
||||
.atom/
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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!}');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>{
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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'};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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'/((?:[#!@+][^:]*:)?[^/?]*)(?:\?.*$)?')
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
///
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ String roomAliasFromRoomName(String roomName) {
|
|||
}
|
||||
|
||||
String genCallID() {
|
||||
return '${DateTime.now().millisecondsSinceEpoch}' + randomAlphaNumeric(16);
|
||||
return '${DateTime.now().millisecondsSinceEpoch}${randomAlphaNumeric(16)}';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
44
pubspec.yaml
44
pubspec.yaml
|
|
@ -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
|
|
@ -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',
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -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?');
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue