chore: strict casts

This commit is contained in:
Nicolas Werner 2022-08-20 17:26:16 +02:00
parent 6a225e3b8c
commit a525bb120a
29 changed files with 174 additions and 169 deletions

View File

@ -11,7 +11,7 @@ linter:
analyzer: analyzer:
language: language:
strict-casts: false strict-casts: true
strict-inference: true strict-inference: true
strict-raw-types: true strict-raw-types: true
errors: errors:

View File

@ -31,12 +31,12 @@ import 'package:matrix_api_lite/matrix_api_lite.dart';
Map<String, dynamic> decodeJson(dynamic data) { Map<String, dynamic> decodeJson(dynamic data) {
if (data is String) { if (data is String) {
return json.decode(data); return json.decode(data) as Map<String, dynamic>;
} }
if (data is Map && data.isEmpty) { if (data is Map && data.isEmpty) {
return <String, dynamic>{}; return <String, dynamic>{};
} }
return data; return data as Map<String, dynamic>;
} }
T? tryCast<T>(dynamic object) => object is T ? object : null; T? tryCast<T>(dynamic object) => object is T ? object : null;

View File

@ -47,7 +47,10 @@ class MatrixApi extends Api {
@override @override
Never unexpectedResponse(http.BaseResponse response, Uint8List body) { Never unexpectedResponse(http.BaseResponse response, Uint8List body) {
if (response.statusCode >= 400 && response.statusCode < 500) { if (response.statusCode >= 400 && response.statusCode < 500) {
throw MatrixException.fromJson(json.decode(utf8.decode(body))); final resp = json.decode(utf8.decode(body));
if (resp is Map<String, dynamic>) {
throw MatrixException.fromJson(resp);
}
} }
super.unexpectedResponse(response, body); super.unexpectedResponse(response, body);
} }
@ -164,7 +167,7 @@ class MatrixApi extends Api {
}, },
}, },
); );
return Map<String, int>.from(response['one_time_key_counts']); return Map<String, int>.from(response['one_time_key_counts'] as Map);
} }
/// This endpoint allows the creation, modification and deletion of pushers /// This endpoint allows the creation, modification and deletion of pushers

View File

@ -30,8 +30,8 @@ class AuthenticationData {
AuthenticationData({this.type, this.session}); AuthenticationData({this.type, this.session});
AuthenticationData.fromJson(Map<String, dynamic> json) AuthenticationData.fromJson(Map<String, dynamic> json)
: type = json['type'], : type = json['type'] as String?,
session = json['session']; session = json['session'] as String?;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -32,7 +32,7 @@ class AuthenticationIdentifier {
AuthenticationIdentifier({required this.type}); AuthenticationIdentifier({required this.type});
AuthenticationIdentifier.fromJson(Map<String, dynamic> json) AuthenticationIdentifier.fromJson(Map<String, dynamic> json)
: type = json['type']; : type = json['type'] as String;
factory AuthenticationIdentifier.subFromJson(Map<String, dynamic> json) { factory AuthenticationIdentifier.subFromJson(Map<String, dynamic> json) {
switch (json['type']) { switch (json['type']) {

View File

@ -41,8 +41,9 @@ class AuthenticationPassword extends AuthenticationData {
); );
AuthenticationPassword.fromJson(Map<String, dynamic> json) AuthenticationPassword.fromJson(Map<String, dynamic> json)
: password = json['password'], : password = json['password'] as String,
identifier = AuthenticationIdentifier.subFromJson(json['identifier']), identifier = AuthenticationIdentifier.subFromJson(
json['identifier'] as Map<String, dynamic>),
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -32,8 +32,8 @@ class AuthenticationPhoneIdentifier extends AuthenticationIdentifier {
: super(type: AuthenticationIdentifierTypes.phone); : super(type: AuthenticationIdentifierTypes.phone);
AuthenticationPhoneIdentifier.fromJson(Map<String, dynamic> json) AuthenticationPhoneIdentifier.fromJson(Map<String, dynamic> json)
: country = json['country'], : country = json['country'] as String,
phone = json['phone'], phone = json['phone'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -34,7 +34,7 @@ class AuthenticationRecaptcha extends AuthenticationData {
); );
AuthenticationRecaptcha.fromJson(Map<String, dynamic> json) AuthenticationRecaptcha.fromJson(Map<String, dynamic> json)
: response = json['response'], : response = json['response'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -33,8 +33,8 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier {
: super(type: AuthenticationIdentifierTypes.thirdParty); : super(type: AuthenticationIdentifierTypes.thirdParty);
AuthenticationThirdPartyIdentifier.fromJson(Map<String, dynamic> json) AuthenticationThirdPartyIdentifier.fromJson(Map<String, dynamic> json)
: medium = json['medium'], : medium = json['medium'] as String,
address = json['address'], address = json['address'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -66,10 +66,10 @@ class ThreepidCreds {
this.idAccessToken}); this.idAccessToken});
ThreepidCreds.fromJson(Map<String, dynamic> json) ThreepidCreds.fromJson(Map<String, dynamic> json)
: sid = json['sid'], : sid = json['sid'] as String,
clientSecret = json['client_secret'], clientSecret = json['client_secret'] as String,
idServer = json['id_server'], idServer = json['id_server'] as String?,
idAccessToken = json['id_access_token']; idAccessToken = json['id_access_token'] as String?;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -37,8 +37,8 @@ class AuthenticationToken extends AuthenticationData {
); );
AuthenticationToken.fromJson(Map<String, dynamic> json) AuthenticationToken.fromJson(Map<String, dynamic> json)
: token = json['token'], : token = json['token'] as String,
txnId = json['txn_id'], txnId = json['txn_id'] as String?,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -31,7 +31,7 @@ class AuthenticationUserIdentifier extends AuthenticationIdentifier {
: super(type: AuthenticationIdentifierTypes.userId); : super(type: AuthenticationIdentifierTypes.userId);
AuthenticationUserIdentifier.fromJson(Map<String, dynamic> json) AuthenticationUserIdentifier.fromJson(Map<String, dynamic> json)
: user = json['user'], : user = json['user'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -33,7 +33,7 @@ class BasicEvent {
}); });
BasicEvent.fromJson(Map<String, dynamic> json) BasicEvent.fromJson(Map<String, dynamic> json)
: type = json['type'], : type = json['type'] as String,
content = (json['content'] as Map<String, dynamic>).copy(); content = (json['content'] as Map<String, dynamic>).copy();
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {

View File

@ -33,7 +33,7 @@ class BasicEventWithSender extends BasicEvent {
: super(type: type, content: content); : super(type: type, content: content);
BasicEventWithSender.fromJson(Map<String, dynamic> json) BasicEventWithSender.fromJson(Map<String, dynamic> json)
: senderId = json['sender'], : senderId = json['sender'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -36,7 +36,7 @@ class BasicRoomEvent extends BasicEvent {
); );
BasicRoomEvent.fromJson(Map<String, dynamic> json) BasicRoomEvent.fromJson(Map<String, dynamic> json)
: roomId = json['room_id'], : roomId = json['room_id'] as String?,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -39,8 +39,8 @@ class ChildrenState extends StrippedStateEvent {
stateKey: stateKey); stateKey: stateKey);
ChildrenState.fromJson(Map<String, dynamic> json) ChildrenState.fromJson(Map<String, dynamic> json)
: originServerTs = : originServerTs = DateTime.fromMillisecondsSinceEpoch(
DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), json['origin_server_ts'] as int),
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -78,15 +78,19 @@ class ImagePackContent {
(e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))), (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))),
pack = ImagePackPackContent.fromJson( pack = ImagePackPackContent.fromJson(
json.tryGetMap<String, dynamic>('pack') ?? {}), json.tryGetMap<String, dynamic>('pack') ?? {}),
images = json.tryGetMap<String, dynamic>('images')?.catchMap( images = json.tryGetMap<String, dynamic>('images')?.catchMap((k, v) =>
(k, v) => MapEntry(k, ImagePackImageContent.fromJson(v))) ?? MapEntry(
k,
ImagePackImageContent.fromJson(
v as Map<String, dynamic>))) ??
// the "emoticons" key needs a small migration on the key, ":string:" --> "string" // the "emoticons" key needs a small migration on the key, ":string:" --> "string"
json.tryGetMap<String, dynamic>('emoticons')?.catchMap((k, v) => json.tryGetMap<String, dynamic>('emoticons')?.catchMap((k, v) =>
MapEntry( MapEntry(
k.startsWith(':') && k.endsWith(':') k.startsWith(':') && k.endsWith(':')
? k.substring(1, k.length - 1) ? k.substring(1, k.length - 1)
: k, : k,
ImagePackImageContent.fromJson(v))) ?? ImagePackImageContent.fromJson(
v as Map<String, dynamic>))) ??
// the "short" key was still just a map from shortcode to mxc uri // the "short" key was still just a map from shortcode to mxc uri
json.tryGetMap<String, String>('short')?.catchMap((k, v) => json.tryGetMap<String, String>('short')?.catchMap((k, v) =>
MapEntry( MapEntry(
@ -118,7 +122,7 @@ class ImagePackImageContent {
ImagePackImageContent.fromJson(Map<String, dynamic> json) ImagePackImageContent.fromJson(Map<String, dynamic> json)
: _json = Map.fromEntries(json.entries : _json = Map.fromEntries(json.entries
.where((e) => !['url', 'body', 'info'].contains(e.key))), .where((e) => !['url', 'body', 'info'].contains(e.key))),
url = Uri.parse(json['url']), url = Uri.parse(json['url'] as String),
body = json.tryGet('body'), body = json.tryGet('body'),
info = json.tryGetMap<String, dynamic>('info'), info = json.tryGetMap<String, dynamic>('info'),
usage = imagePackUsageFromJson(json.tryGetList<String>('usage')); usage = imagePackUsageFromJson(json.tryGetList<String>('usage'));

View File

@ -49,7 +49,8 @@ class RoomEncryptedContent {
// filter out invalid/incomplete CiphertextInfos // filter out invalid/incomplete CiphertextInfos
ciphertextOlm = json ciphertextOlm = json
.tryGet<Map<String, dynamic>>('ciphertext', TryGet.silent) .tryGet<Map<String, dynamic>>('ciphertext', TryGet.silent)
?.catchMap((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); ?.catchMap((k, v) => MapEntry(
k, CiphertextInfo.fromJson(v as Map<String, dynamic>)));
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -81,8 +82,8 @@ class CiphertextInfo {
int type; int type;
CiphertextInfo.fromJson(Map<String, dynamic> json) CiphertextInfo.fromJson(Map<String, dynamic> json)
: body = json['body'], : body = json['body'] as String,
type = json['type']; type = json['type'] as int;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -50,13 +50,13 @@ class MatrixEvent extends StrippedStateEvent {
stateKey: stateKey); stateKey: stateKey);
MatrixEvent.fromJson(Map<String, dynamic> json) MatrixEvent.fromJson(Map<String, dynamic> json)
: eventId = json['event_id'], : eventId = json['event_id'] as String,
roomId = json['room_id'], roomId = json['room_id'] as String?,
originServerTs = originServerTs = DateTime.fromMillisecondsSinceEpoch(
DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), json['origin_server_ts'] as int),
unsigned = (json['unsigned'] as Map<String, dynamic>?)?.copy(), unsigned = (json['unsigned'] as Map<String, dynamic>?)?.copy(),
prevContent = (json['prev_content'] as Map<String, dynamic>?)?.copy(), prevContent = (json['prev_content'] as Map<String, dynamic>?)?.copy(),
redacts = json['redacts'], redacts = json['redacts'] as String?,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -65,12 +65,12 @@ class MatrixException implements Exception {
/// The unique identifier for this error. /// The unique identifier for this error.
String get errcode => String get errcode =>
raw['errcode'] ?? raw['errcode'] as String? ??
(requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN'); (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN');
/// A human readable error description. /// A human readable error description.
String get errorMessage => String get errorMessage =>
raw['error'] ?? raw['error'] as String? ??
(requireAdditionalAuthentication (requireAdditionalAuthentication
? 'Require additional authentication' ? 'Require additional authentication'
: 'Unknown error'); : 'Unknown error');
@ -79,7 +79,7 @@ class MatrixException implements Exception {
http.Response? response; http.Response? response;
MatrixException(http.Response this.response) MatrixException(http.Response this.response)
: raw = json.decode(response.body); : raw = json.decode(response.body) as Map<String, dynamic>;
MatrixException.fromJson(Map<String, dynamic> content) : raw = content; MatrixException.fromJson(Map<String, dynamic> content) : raw = content;
@ -91,11 +91,11 @@ class MatrixException implements Exception {
(e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}',
orElse: () => MatrixError.M_UNKNOWN); orElse: () => MatrixError.M_UNKNOWN);
int? get retryAfterMs => raw['retry_after_ms']; int? get retryAfterMs => raw['retry_after_ms'] as int?;
/// This is a session identifier that the client must pass back to the homeserver, if one is provided, /// This is a session identifier that the client must pass back to the homeserver, if one is provided,
/// in subsequent attempts to authenticate in the same API call. /// in subsequent attempts to authenticate in the same API call.
String? get session => raw['session']; String? get session => raw['session'] as String?;
/// Returns true if the server requires additional authentication. /// Returns true if the server requires additional authentication.
bool get requireAdditionalAuthentication => response != null bool get requireAdditionalAuthentication => response != null
@ -119,11 +119,12 @@ class MatrixException implements Exception {
/// This section contains any information that the client will need to know in order to use a given type /// This section contains any information that the client will need to know in order to use a given type
/// of authentication. For each authentication type presented, that type may be present as a key in this /// of authentication. For each authentication type presented, that type may be present as a key in this
/// dictionary. For example, the public part of an OAuth client ID could be given here. /// dictionary. For example, the public part of an OAuth client ID could be given here.
Map<String, dynamic>? get authenticationParams => raw['params']; Map<String, dynamic>? get authenticationParams =>
raw['params'] as Map<String, dynamic>?;
/// Returns the list of already completed authentication flows from previous requests. /// Returns the list of already completed authentication flows from previous requests.
List<String> get completedAuthenticationFlows => List<String> get completedAuthenticationFlows =>
List<String>.from(raw['completed'] ?? []); List<String>.from(raw['completed'] as List<String>? ?? []);
} }
/// For each endpoint, a server offers one or more 'flows' that the client can use /// For each endpoint, a server offers one or more 'flows' that the client can use

View File

@ -21,7 +21,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import '../utils/map_copy_extension.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart';
abstract class MatrixSignableKey { abstract class MatrixSignableKey {
String userId; String userId;
@ -39,14 +39,11 @@ abstract class MatrixSignableKey {
MatrixSignableKey.fromJson(Map<String, dynamic> json) MatrixSignableKey.fromJson(Map<String, dynamic> json)
: _json = json, : _json = json,
userId = json['user_id'], userId = json['user_id'] as String,
keys = Map<String, String>.from(json['keys']), keys = Map<String, String>.from(json['keys'] as Map<String, dynamic>),
// we need to manually copy to ensure that our map is Map<String, Map<String, String>> // we need to manually copy to ensure that our map is Map<String, Map<String, String>>
signatures = json['signatures'] is Map signatures = json.tryGetMap<String, Map<String, String>>('signatures'),
? Map<String, Map<String, String>>.from((json['signatures'] as Map) unsigned = json.tryGetMap<String, dynamic>('unsigned');
.map((k, v) => MapEntry(k, Map<String, String>.from(v))))
: null,
unsigned = (json['unsigned'] as Map<String, dynamic>?)?.copy();
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = _json ?? <String, dynamic>{}; final data = _json ?? <String, dynamic>{};
@ -81,7 +78,7 @@ class MatrixCrossSigningKey extends MatrixSignableKey {
@override @override
MatrixCrossSigningKey.fromJson(Map<String, dynamic> json) MatrixCrossSigningKey.fromJson(Map<String, dynamic> json)
: usage = List<String>.from(json['usage']), : usage = json.tryGetList<String>('usage') ?? [],
super.fromJson(json); super.fromJson(json);
@override @override
@ -97,7 +94,7 @@ class MatrixDeviceKeys extends MatrixSignableKey {
List<String> algorithms; List<String> algorithms;
String? get deviceDisplayName => String? get deviceDisplayName =>
unsigned != null ? unsigned!['device_display_name'] : null; unsigned?.tryGet<String>('device_display_name');
MatrixDeviceKeys( MatrixDeviceKeys(
String userId, String userId,
@ -113,8 +110,8 @@ class MatrixDeviceKeys extends MatrixSignableKey {
@override @override
MatrixDeviceKeys.fromJson(Map<String, dynamic> json) MatrixDeviceKeys.fromJson(Map<String, dynamic> json)
: algorithms = (json['algorithms'] as List).cast<String>(), : algorithms = json.tryGetList<String>('algorithms') ?? [],
deviceId = json['device_id'], deviceId = json['device_id'] as String,
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -28,6 +28,7 @@ class Presence extends BasicEventWithSender {
PresenceContent presence; PresenceContent presence;
Presence.fromJson(Map<String, dynamic> json) Presence.fromJson(Map<String, dynamic> json)
: presence = PresenceContent.fromJson(json['content']), : presence =
PresenceContent.fromJson(json['content'] as Map<String, dynamic>),
super.fromJson(json); super.fromJson(json);
} }

View File

@ -21,7 +21,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import '../generated/model.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart';
class PresenceContent { class PresenceContent {
PresenceType presence; PresenceType presence;
@ -32,9 +32,9 @@ class PresenceContent {
PresenceContent.fromJson(Map<String, dynamic> json) PresenceContent.fromJson(Map<String, dynamic> json)
: presence = PresenceType.values.firstWhere( : presence = PresenceType.values.firstWhere(
(p) => p.toString().split('.').last == json['presence']), (p) => p.toString().split('.').last == json['presence']),
lastActiveAgo = json['last_active_ago'], lastActiveAgo = json.tryGet<int>('last_active_ago'),
statusMsg = json['status_msg'], statusMsg = json.tryGet<String>('status_msg'),
currentlyActive = json['currently_active']; currentlyActive = json.tryGet<bool>('currently_active');
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -21,6 +21,8 @@
* SOFTWARE. * SOFTWARE.
*/ */
import 'package:matrix_api_lite/matrix_api_lite.dart';
class RoomKeysSingleKey { class RoomKeysSingleKey {
int firstMessageIndex; int firstMessageIndex;
int forwardedCount; int forwardedCount;
@ -34,10 +36,10 @@ class RoomKeysSingleKey {
required this.sessionData}); required this.sessionData});
RoomKeysSingleKey.fromJson(Map<String, dynamic> json) RoomKeysSingleKey.fromJson(Map<String, dynamic> json)
: firstMessageIndex = json['first_message_index'], : firstMessageIndex = json['first_message_index'] as int,
forwardedCount = json['forwarded_count'], forwardedCount = json['forwarded_count'] as int,
isVerified = json['is_verified'], isVerified = json['is_verified'] as bool,
sessionData = json['session_data']; sessionData = json['session_data'] as Map<String, dynamic>;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -55,8 +57,8 @@ class RoomKeysRoom {
RoomKeysRoom({required this.sessions}); RoomKeysRoom({required this.sessions});
RoomKeysRoom.fromJson(Map<String, dynamic> json) RoomKeysRoom.fromJson(Map<String, dynamic> json)
: sessions = (json['sessions'] as Map) : sessions = (json['sessions'] as Map<String, dynamic>).map((k, v) =>
.map((k, v) => MapEntry(k, RoomKeysSingleKey.fromJson(v))); MapEntry(k, RoomKeysSingleKey.fromJson(v as Map<String, dynamic>)));
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -70,8 +72,9 @@ class RoomKeysUpdateResponse {
int count; int count;
RoomKeysUpdateResponse.fromJson(Map<String, dynamic> json) RoomKeysUpdateResponse.fromJson(Map<String, dynamic> json)
: etag = json['etag'], // synapse replies an int but docs say string? : etag = json.tryGet<String>('etag') ??
count = json['count']; '', // synapse replies an int but docs say string?
count = json.tryGet<int>('count') ?? 0;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -28,10 +28,10 @@ class RoomSummary {
RoomSummary.fromJson(Map<String, dynamic> json) RoomSummary.fromJson(Map<String, dynamic> json)
: mHeroes = json['m.heroes'] != null : mHeroes = json['m.heroes'] != null
? List<String>.from(json['m.heroes']) ? List<String>.from(json['m.heroes'] as List)
: null, : null,
mJoinedMemberCount = json['m.joined_member_count'], mJoinedMemberCount = json['m.joined_member_count'] as int?,
mInvitedMemberCount = json['m.invited_member_count']; mInvitedMemberCount = json['m.invited_member_count'] as int?;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -21,7 +21,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import 'basic_event_with_sender.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart';
class StrippedStateEvent extends BasicEventWithSender { class StrippedStateEvent extends BasicEventWithSender {
String? stateKey; String? stateKey;
@ -34,7 +34,7 @@ class StrippedStateEvent extends BasicEventWithSender {
: super(type: type, content: content, senderId: senderId); : super(type: type, content: content, senderId: senderId);
StrippedStateEvent.fromJson(Map<String, dynamic> json) StrippedStateEvent.fromJson(Map<String, dynamic> json)
: stateKey = json['state_key'], : stateKey = json.tryGet<String>('state_key'),
super.fromJson(json); super.fromJson(json);
@override @override

View File

@ -21,13 +21,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import 'basic_event.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart';
import 'basic_event_with_sender.dart';
import 'basic_room_event.dart';
import 'matrix_event.dart';
import 'presence.dart';
import 'room_summary.dart';
import 'stripped_state_event.dart';
class SyncUpdate { class SyncUpdate {
String nextBatch; String nextBatch;
@ -51,32 +45,34 @@ class SyncUpdate {
}); });
SyncUpdate.fromJson(Map<String, dynamic> json) SyncUpdate.fromJson(Map<String, dynamic> json)
: nextBatch = json['next_batch'], : nextBatch = json['next_batch'] as String,
rooms = rooms = (() {
json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null, final temp = json.tryGetMap<String, dynamic>('rooms');
presence = ((json['presence'] as Map?)?['events'] as List?) return temp != null ? RoomsUpdate.fromJson(temp) : null;
?.map((i) => Presence.fromJson(i)) }()),
presence = json
.tryGetMap<String, List<dynamic>>('presence')?['events']
?.map((i) => Presence.fromJson(i as Map<String, dynamic>))
.toList(), .toList(),
accountData = ((json['account_data'] as Map?)?['events'] as List?) accountData = json
?.map((i) => BasicEvent.fromJson(i)) .tryGetMap<String, List<dynamic>>('account_data')?['events']
?.map((i) => BasicEvent.fromJson(i as Map<String, dynamic>))
.toList(), .toList(),
toDevice = ((json['to_device'] as Map?)?['events'] as List?) toDevice = json
?.map((i) => BasicEventWithSender.fromJson(i)) .tryGetMap<String, List<dynamic>>('to_device')?['events']
?.map(
(i) => BasicEventWithSender.fromJson(i as Map<String, dynamic>))
.toList(), .toList(),
deviceLists = json['device_lists'] != null deviceLists = (() {
? DeviceListsUpdate.fromJson(json['device_lists']) final temp = json.tryGetMap<String, dynamic>('device_lists');
: null, return temp != null ? DeviceListsUpdate.fromJson(temp) : null;
deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null }()),
? Map<String, int>.from(json['device_one_time_keys_count']) deviceOneTimeKeysCount =
: null, json.tryGetMap<String, int>('device_one_time_keys_count'),
deviceUnusedFallbackKeyTypes = (json[ deviceUnusedFallbackKeyTypes =
'device_unused_fallback_key_types'] ?? json.tryGetList<String>('device_unused_fallback_key_types') ??
json[ json.tryGetList<String>(
'org.matrix.msc2732.device_unused_fallback_key_types']) != 'org.matrix.msc2732.device_unused_fallback_key_types');
null
? List<String>.from(json['device_unused_fallback_key_types'] ??
json['org.matrix.msc2732.device_unused_fallback_key_types'])
: null;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -126,18 +122,12 @@ class RoomsUpdate {
}); });
RoomsUpdate.fromJson(Map<String, dynamic> json) { RoomsUpdate.fromJson(Map<String, dynamic> json) {
join = json['join'] != null join = json.tryGetMap<String, dynamic>('join')?.catchMap((k, v) =>
? (json['join'] as Map) MapEntry(k, JoinedRoomUpdate.fromJson(v as Map<String, dynamic>)));
.map((k, v) => MapEntry(k, JoinedRoomUpdate.fromJson(v))) invite = json.tryGetMap<String, dynamic>('invite')?.catchMap((k, v) =>
: null; MapEntry(k, InvitedRoomUpdate.fromJson(v as Map<String, dynamic>)));
invite = json['invite'] != null leave = json.tryGetMap<String, dynamic>('leave')?.catchMap((k, v) =>
? (json['invite'] as Map) MapEntry(k, LeftRoomUpdate.fromJson(v as Map<String, dynamic>)));
.map((k, v) => MapEntry(k, InvitedRoomUpdate.fromJson(v)))
: null;
leave = json['leave'] != null
? (json['leave'] as Map)
.map((k, v) => MapEntry(k, LeftRoomUpdate.fromJson(v)))
: null;
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -175,24 +165,22 @@ class JoinedRoomUpdate extends SyncRoomUpdate {
}); });
JoinedRoomUpdate.fromJson(Map<String, dynamic> json) JoinedRoomUpdate.fromJson(Map<String, dynamic> json)
: summary = json['summary'] != null : summary = json.tryGetFromJson('summary', RoomSummary.fromJson),
? RoomSummary.fromJson(json['summary']) state = json
: null, .tryGetMap<String, List<dynamic>>('state')?['events']
state = ((json['state'] as Map?)?['events'] as List?) ?.map((i) => MatrixEvent.fromJson(i as Map<String, dynamic>))
?.map((i) => MatrixEvent.fromJson(i))
.toList(), .toList(),
timeline = json['timeline'] != null timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson),
? TimelineUpdate.fromJson(json['timeline']) ephemeral = json
: null, .tryGetMap<String, List<dynamic>>('ephemeral')?['events']
ephemeral = ((json['ephemeral'] as Map?)?['events'] as List?) ?.map((i) => BasicRoomEvent.fromJson(i as Map<String, dynamic>))
?.map((i) => BasicRoomEvent.fromJson(i))
.toList(), .toList(),
accountData = ((json['account_data'] as Map?)?['events'] as List?) accountData = json
?.map((i) => BasicRoomEvent.fromJson(i)) .tryGetMap<String, List<dynamic>>('account_data')?['events']
?.map((i) => BasicRoomEvent.fromJson(i as Map<String, dynamic>))
.toList(), .toList(),
unreadNotifications = json['unread_notifications'] != null unreadNotifications = json.tryGetFromJson(
? UnreadNotificationCounts.fromJson(json['unread_notifications']) 'unread_notifications', UnreadNotificationCounts.fromJson);
: null;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -230,8 +218,9 @@ class InvitedRoomUpdate extends SyncRoomUpdate {
InvitedRoomUpdate({this.inviteState}); InvitedRoomUpdate({this.inviteState});
InvitedRoomUpdate.fromJson(Map<String, dynamic> json) InvitedRoomUpdate.fromJson(Map<String, dynamic> json)
: inviteState = ((json['invite_state'] as Map?)?['events'] as List?) : inviteState = json
?.map((i) => StrippedStateEvent.fromJson(i)) .tryGetMap<String, List<dynamic>>('invite_state')?['events']
?.map((i) => StrippedStateEvent.fromJson(i as Map<String, dynamic>))
.toList(); .toList();
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -257,14 +246,14 @@ class LeftRoomUpdate extends SyncRoomUpdate {
}); });
LeftRoomUpdate.fromJson(Map<String, dynamic> json) LeftRoomUpdate.fromJson(Map<String, dynamic> json)
: state = ((json['state'] as Map?)?['events'] as List?) : state = json
?.map((i) => MatrixEvent.fromJson(i)) .tryGetMap<String, List<dynamic>>('state')?['events']
?.map((i) => MatrixEvent.fromJson(i as Map<String, dynamic>))
.toList(), .toList(),
timeline = json['timeline'] != null timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson),
? TimelineUpdate.fromJson(json['timeline']) accountData = json
: null, .tryGetMap<String, List<dynamic>>('account_data')?['events']
accountData = ((json['account_data'] as Map?)?['events'] as List?) ?.map((i) => BasicRoomEvent.fromJson(i as Map<String, dynamic>))
?.map((i) => BasicRoomEvent.fromJson(i))
.toList(); .toList();
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -297,13 +286,13 @@ class TimelineUpdate {
this.prevBatch, this.prevBatch,
}); });
TimelineUpdate.fromJson(Map<String, dynamic> json) { TimelineUpdate.fromJson(Map<String, dynamic> json)
events = json['events'] != null : events = json
? (json['events'] as List).map((i) => MatrixEvent.fromJson(i)).toList() .tryGetList<Map<String, dynamic>>('events')
: null; ?.map((v) => MatrixEvent.fromJson(v))
limited = json['limited']; .toList(),
prevBatch = json['prev_batch']; limited = json.tryGet<bool>('limited'),
} prevBatch = json.tryGet<String>('prev_batch');
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -329,10 +318,9 @@ class UnreadNotificationCounts {
this.highlightCount, this.highlightCount,
}); });
UnreadNotificationCounts.fromJson(Map<String, dynamic> json) { UnreadNotificationCounts.fromJson(Map<String, dynamic> json)
highlightCount = json['highlight_count']; : highlightCount = json.tryGet<int>('highlight_count'),
notificationCount = json['notification_count']; notificationCount = json.tryGet<int>('notification_count');
}
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};
@ -355,10 +343,9 @@ class DeviceListsUpdate {
this.left, this.left,
}); });
DeviceListsUpdate.fromJson(Map<String, dynamic> json) { DeviceListsUpdate.fromJson(Map<String, dynamic> json)
changed = List<String>.from(json['changed'] ?? []); : changed = json.tryGetList<String>('changed') ?? [],
left = List<String>.from(json['left'] ?? []); left = json.tryGetList<String>('left') ?? [];
}
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final data = <String, dynamic>{}; final data = <String, dynamic>{};

View File

@ -100,6 +100,13 @@ extension TryGetMapExtension on Map<String, dynamic> {
return null; return null;
} }
} }
A? tryGetFromJson<A>(String key, A Function(Map<String, dynamic>) fromJson,
[TryGet log = TryGet.optional]) {
final value = tryGetMap<String, dynamic>(key, log);
return value != null ? fromJson(value) : null;
}
} }
extension on StackTrace { extension on StackTrace {

View File

@ -43,7 +43,7 @@ void main() {
'type': 'm.room.encryption', 'type': 'm.room.encryption',
'unsigned': {'age': 1234} 'unsigned': {'age': 1234}
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(), expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(),
json['content']); json['content']);
}); });
@ -63,7 +63,7 @@ void main() {
'type': 'm.room.encrypted', 'type': 'm.room.encrypted',
'unsigned': {'age': 1234} 'unsigned': {'age': 1234}
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(),
json['content']); json['content']);
json = <String, dynamic>{ json = <String, dynamic>{
@ -84,7 +84,7 @@ void main() {
'type': 'm.room.encrypted', 'type': 'm.room.encrypted',
'unsigned': {'age': 1234} 'unsigned': {'age': 1234}
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(),
json['content']); json['content']);
}); });
@ -98,7 +98,7 @@ void main() {
}, },
'type': 'm.room_key' 'type': 'm.room_key'
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(), expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(),
json['content']); json['content']);
}); });
@ -111,7 +111,7 @@ void main() {
}, },
'type': 'm.room_key_request' 'type': 'm.room_key_request'
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(),
json['content']); json['content']);
json = <String, dynamic>{ json = <String, dynamic>{
@ -128,7 +128,7 @@ void main() {
}, },
'type': 'm.room_key_request' 'type': 'm.room_key_request'
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(),
json['content']); json['content']);
}); });
@ -148,7 +148,7 @@ void main() {
}, },
'type': 'm.forwarded_room_key' 'type': 'm.forwarded_room_key'
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(), expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(),
json['content']); json['content']);
}); });
@ -164,7 +164,7 @@ void main() {
'recipient_keys': {'ed25519': '<our_ed25519_key>'}, 'recipient_keys': {'ed25519': '<our_ed25519_key>'},
'keys': {'ed25519': '<sender_ed25519_key>'} 'keys': {'ed25519': '<sender_ed25519_key>'}
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>?;
expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); expect(OlmPlaintextPayload.fromJson(json!).toJson(), json);
}); });
test('Image Pack Content', () { test('Image Pack Content', () {
@ -190,7 +190,7 @@ void main() {
'org.custom': 'blah', 'org.custom': 'blah',
}, },
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>;
expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(), expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(),
json['content']); json['content']);
@ -205,7 +205,7 @@ void main() {
}, },
}, },
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>;
expect( expect(
BasicEvent.fromJson(json) BasicEvent.fromJson(json)
.parsedImagePackContent .parsedImagePackContent
@ -223,7 +223,7 @@ void main() {
}, },
}, },
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>;
expect( expect(
BasicEvent.fromJson(json) BasicEvent.fromJson(json)
.parsedImagePackContent .parsedImagePackContent
@ -242,7 +242,7 @@ void main() {
}, },
}, },
}; };
json = jsonDecode(jsonEncode(json)); json = jsonDecode(jsonEncode(json)) as Map<String, dynamic>;
expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'], expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'],
null); null);
}); });