Merge branch 'mxcontent-refactor-uri-extension' into 'master'

[MxContent] Switch to Uri Extension

See merge request famedly/famedlysdk!265
This commit is contained in:
Christian Pauly 2020-04-24 09:43:30 +00:00
commit 96d2a2a0b4
13 changed files with 42 additions and 59 deletions

View file

@ -30,7 +30,7 @@ export 'package:famedlysdk/src/utils/device_keys_list.dart';
export 'package:famedlysdk/src/utils/matrix_exception.dart'; export 'package:famedlysdk/src/utils/matrix_exception.dart';
export 'package:famedlysdk/src/utils/matrix_file.dart'; export 'package:famedlysdk/src/utils/matrix_file.dart';
export 'package:famedlysdk/src/utils/matrix_id_string_extension.dart'; export 'package:famedlysdk/src/utils/matrix_id_string_extension.dart';
export 'package:famedlysdk/src/utils/mx_content.dart'; export 'package:famedlysdk/src/utils/uri_extension.dart';
export 'package:famedlysdk/src/utils/open_id_credentials.dart'; export 'package:famedlysdk/src/utils/open_id_credentials.dart';
export 'package:famedlysdk/src/utils/profile.dart'; export 'package:famedlysdk/src/utils/profile.dart';
export 'package:famedlysdk/src/utils/public_rooms_response.dart'; export 'package:famedlysdk/src/utils/public_rooms_response.dart';

View file

@ -459,10 +459,10 @@ class Event {
throw ('Encryption is not enabled in your Client.'); throw ('Encryption is not enabled in your Client.');
} }
var mxContent = getThumbnail var mxContent = getThumbnail
? MxContent(isEncrypted ? Uri.parse(isEncrypted
? content['info']['thumbnail_file']['url'] ? content['info']['thumbnail_file']['url']
: content['info']['thumbnail_url']) : content['info']['thumbnail_url'])
: MxContent(isEncrypted ? content['file']['url'] : content['url']); : Uri.parse(isEncrypted ? content['file']['url'] : content['url']);
Uint8List uint8list; Uint8List uint8list;
@ -475,7 +475,7 @@ class Event {
infoMap['size'] <= ExtendedStoreAPI.MAX_FILE_SIZE; infoMap['size'] <= ExtendedStoreAPI.MAX_FILE_SIZE;
if (storeable) { if (storeable) {
uint8list = await room.client.store.getFile(mxContent.mxc); uint8list = await room.client.store.getFile(mxContent.toString());
} }
// Download the file // Download the file
@ -483,7 +483,7 @@ class Event {
uint8list = uint8list =
(await http.get(mxContent.getDownloadLink(room.client))).bodyBytes; (await http.get(mxContent.getDownloadLink(room.client))).bodyBytes;
if (storeable) { if (storeable) {
await room.client.store.storeFile(uint8list, mxContent.mxc); await room.client.store.storeFile(uint8list, mxContent.toString());
} }
} }

View file

@ -21,8 +21,6 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:famedlysdk/famedlysdk.dart';
enum PresenceType { online, offline, unavailable } enum PresenceType { online, offline, unavailable }
/// Informs the client of a user's presence state change. /// Informs the client of a user's presence state change.
@ -34,7 +32,7 @@ class Presence {
final String displayname; final String displayname;
/// The current avatar URL for this user, if any. /// The current avatar URL for this user, if any.
final MxContent avatarUrl; final Uri avatarUrl;
final bool currentlyActive; final bool currentlyActive;
final int lastActiveAgo; final int lastActiveAgo;
final PresenceType presence; final PresenceType presence;
@ -44,7 +42,9 @@ class Presence {
Presence.fromJson(Map<String, dynamic> json) Presence.fromJson(Map<String, dynamic> json)
: sender = json['sender'], : sender = json['sender'],
displayname = json['content']['displayname'], displayname = json['content']['displayname'],
avatarUrl = MxContent(json['content']['avatar_url'] ?? ''), avatarUrl = json['content']['avatar_url'] != null
? Uri.parse(json['content']['avatar_url'])
: null,
currentlyActive = json['content']['currently_active'], currentlyActive = json['content']['currently_active'],
lastActiveAgo = json['content']['last_active_ago'], lastActiveAgo = json['content']['last_active_ago'],
time = DateTime.fromMillisecondsSinceEpoch( time = DateTime.fromMillisecondsSinceEpoch(

View file

@ -32,7 +32,6 @@ import 'package:famedlysdk/src/sync/event_update.dart';
import 'package:famedlysdk/src/sync/room_update.dart'; import 'package:famedlysdk/src/sync/room_update.dart';
import 'package:famedlysdk/src/utils/matrix_exception.dart'; import 'package:famedlysdk/src/utils/matrix_exception.dart';
import 'package:famedlysdk/src/utils/matrix_file.dart'; import 'package:famedlysdk/src/utils/matrix_file.dart';
import 'package:famedlysdk/src/utils/mx_content.dart';
import 'package:famedlysdk/src/utils/session_key.dart'; import 'package:famedlysdk/src/utils/session_key.dart';
import 'package:image/image.dart'; import 'package:image/image.dart';
import 'package:matrix_file_e2ee/matrix_file_e2ee.dart'; import 'package:matrix_file_e2ee/matrix_file_e2ee.dart';
@ -286,9 +285,10 @@ class Room {
: ''; : '';
/// The avatar of the room if set by a participant. /// The avatar of the room if set by a participant.
MxContent get avatar { Uri get avatar {
if (states['m.room.avatar'] != null) { if (states['m.room.avatar'] != null &&
return MxContent(states['m.room.avatar'].content['url']); states['m.room.avatar'].content['url'] != null) {
return Uri.parse(states['m.room.avatar'].content['url']);
} }
if (mHeroes != null && mHeroes.length == 1 && states[mHeroes[0]] != null) { if (mHeroes != null && mHeroes.length == 1 && states[mHeroes[0]] != null) {
return states[mHeroes[0]].asUser.avatarUrl; return states[mHeroes[0]].asUser.avatarUrl;
@ -297,7 +297,7 @@ class Room {
getState('m.room.member', client.userID) != null) { getState('m.room.member', client.userID) != null) {
return getState('m.room.member', client.userID).sender.avatarUrl; return getState('m.room.member', client.userID).sender.avatarUrl;
} }
return MxContent(''); return null;
} }
/// The address in the format: #roomname:homeserver.org. /// The address in the format: #roomname:homeserver.org.

View file

@ -146,7 +146,7 @@ class Timeline {
?.getUser(matrixID: eventUpdate.content['sender'], room: room); ?.getUser(matrixID: eventUpdate.content['sender'], room: room);
if (senderUser != null) { if (senderUser != null) {
eventUpdate.content['displayname'] = senderUser.displayName; eventUpdate.content['displayname'] = senderUser.displayName;
eventUpdate.content['avatar_url'] = senderUser.avatarUrl.mxc; eventUpdate.content['avatar_url'] = senderUser.avatarUrl.toString();
} }
newEvent = Event.fromJson(eventUpdate.content, room); newEvent = Event.fromJson(eventUpdate.content, room);

View file

@ -24,7 +24,6 @@
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/src/room.dart'; import 'package:famedlysdk/src/room.dart';
import 'package:famedlysdk/src/event.dart'; import 'package:famedlysdk/src/event.dart';
import 'package:famedlysdk/src/utils/mx_content.dart';
enum Membership { join, invite, leave, ban } enum Membership { join, invite, leave, ban }
@ -96,9 +95,9 @@ class User extends Event {
}, orElse: () => Membership.join); }, orElse: () => Membership.join);
/// The avatar if the user has one. /// The avatar if the user has one.
MxContent get avatarUrl => content != null && content['avatar_url'] is String Uri get avatarUrl => content != null && content['avatar_url'] is String
? MxContent(content['avatar_url']) ? Uri.parse(content['avatar_url'])
: MxContent(''); : null;
/// Returns the displayname or the local part of the Matrix ID if the user /// Returns the displayname or the local part of the Matrix ID if the user
/// has no displayname. If [formatLocalpart] is true, then the localpart will /// has no displayname. If [formatLocalpart] is true, then the localpart will

View file

@ -1,9 +1,7 @@
import 'package:famedlysdk/src/utils/mx_content.dart';
/// Represents a user profile returned by a /profile request. /// Represents a user profile returned by a /profile request.
class Profile { class Profile {
/// The user's avatar URL if they have set one, otherwise null. /// The user's avatar URL if they have set one, otherwise null.
final MxContent avatarUrl; final Uri avatarUrl;
/// The user's display name if they have set one, otherwise null. /// The user's display name if they have set one, otherwise null.
final String displayname; final String displayname;
@ -12,11 +10,11 @@ class Profile {
final Map<String, dynamic> content; final Map<String, dynamic> content;
Profile.fromJson(Map<String, dynamic> json) Profile.fromJson(Map<String, dynamic> json)
: avatarUrl = MxContent(json['avatar_url']), : avatarUrl = Uri.parse(json['avatar_url']),
displayname = json['displayname'], displayname = json['displayname'],
content = json; content = json;
@override @override
bool operator ==(dynamic other) => bool operator ==(dynamic other) =>
avatarUrl.mxc == other.avatarUrl.mxc && displayname == other.displayname; avatarUrl == other.avatarUrl && displayname == other.displayname;
} }

View file

@ -24,32 +24,25 @@
import 'package:famedlysdk/src/client.dart'; import 'package:famedlysdk/src/client.dart';
import 'dart:core'; import 'dart:core';
/// A file in Matrix presented by a mxc:// uri scheme. extension MxcUriExtension on Uri {
class MxContent {
final String _mxc;
/// Insert a mxc:// uri here.
MxContent(String mxcUrl) : _mxc = mxcUrl ?? '';
/// Returns the mxc uri.
String get mxc => _mxc;
/// Returns a download Link to this content. /// Returns a download Link to this content.
String getDownloadLink(Client matrix) => matrix.homeserver != null String getDownloadLink(Client matrix) => isScheme('mxc')
? "${matrix.homeserver}/_matrix/media/r0/download/${_mxc.replaceFirst("mxc://", "")}" ? matrix.homeserver != null
: ''; ? '${matrix.homeserver}/_matrix/media/r0/download/$host$path'
: ''
: toString();
/// Returns a scaled thumbnail link to this content with the given [width] and /// Returns a scaled thumbnail link to this content with the given [width] and
/// [height]. [method] can be [ThumbnailMethod.crop] or /// [height]. [method] can be [ThumbnailMethod.crop] or
/// [ThumbnailMethod.scale] and defaults to [ThumbnailMethod.scale]. /// [ThumbnailMethod.scale] and defaults to [ThumbnailMethod.scale].
String getThumbnail(Client matrix, String getThumbnail(Client matrix,
{num width, num height, ThumbnailMethod method}) { {num width, num height, ThumbnailMethod method = ThumbnailMethod.crop}) {
var methodStr = 'crop'; if (!isScheme('mxc')) return toString();
if (method == ThumbnailMethod.scale) methodStr = 'scale'; final methodStr = method.toString().split('.').last;
width = width.round(); width = width.round();
height = height.round(); height = height.round();
return matrix.homeserver != null return matrix.homeserver != null
? "${matrix.homeserver}/_matrix/media/r0/thumbnail/${_mxc.replaceFirst("mxc://", "")}?width=$width&height=$height&method=$methodStr" ? '${matrix.homeserver}/_matrix/media/r0/thumbnail/$host$path?width=$width&height=$height&method=$methodStr'
: ''; : '';
} }
} }

View file

@ -470,9 +470,9 @@ void main() {
test('getProfileFromUserId', () async { test('getProfileFromUserId', () async {
final profile = await matrix.getProfileFromUserId('@getme:example.com'); final profile = await matrix.getProfileFromUserId('@getme:example.com');
expect(profile.avatarUrl.mxc, 'mxc://test'); expect(profile.avatarUrl.toString(), 'mxc://test');
expect(profile.displayname, 'You got me'); expect(profile.displayname, 'You got me');
expect(profile.content['avatar_url'], profile.avatarUrl.mxc); expect(profile.content['avatar_url'], profile.avatarUrl.toString());
expect(profile.content['displayname'], profile.displayname); expect(profile.content['displayname'], profile.displayname);
}); });

View file

@ -23,7 +23,7 @@
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:famedlysdk/src/client.dart'; import 'package:famedlysdk/src/client.dart';
import 'package:famedlysdk/src/utils/mx_content.dart'; import 'package:famedlysdk/src/utils/uri_extension.dart';
import 'fake_matrix_api.dart'; import 'fake_matrix_api.dart';
@ -35,7 +35,8 @@ void main() {
client.httpClient = FakeMatrixApi(); client.httpClient = FakeMatrixApi();
await client.checkServer('https://fakeserver.notexisting'); await client.checkServer('https://fakeserver.notexisting');
final mxc = 'mxc://exampleserver.abc/abcdefghijklmn'; final mxc = 'mxc://exampleserver.abc/abcdefghijklmn';
final content = MxContent(mxc); final content = Uri.parse(mxc);
expect(content.isScheme('mxc'), true);
expect(content.getDownloadLink(client), expect(content.getDownloadLink(client),
'${client.homeserver}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn'); '${client.homeserver}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn');
@ -46,13 +47,5 @@ void main() {
width: 50, height: 50, method: ThumbnailMethod.scale), width: 50, height: 50, method: ThumbnailMethod.scale),
'${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale'); '${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale');
}); });
test('Not crashing if null', () async {
var client = Client('testclient');
client.httpClient = FakeMatrixApi();
await client.checkServer('https://fakeserver.notexisting');
final content = MxContent(null);
expect(content.getDownloadLink(client),
'${client.homeserver}/_matrix/media/r0/download/');
});
}); });
} }

View file

@ -30,7 +30,7 @@ void main() {
test('fromJson', () async { test('fromJson', () async {
var rawPresence = <String, dynamic>{ var rawPresence = <String, dynamic>{
'content': { 'content': {
'avatar_url': 'mxc://localhost:wefuiwegh8742w', 'avatar_url': 'mxc://example.org/wefuiwegh8742w',
'currently_active': false, 'currently_active': false,
'last_active_ago': 2478593, 'last_active_ago': 2478593,
'presence': 'online', 'presence': 'online',
@ -41,7 +41,7 @@ void main() {
}; };
var presence = Presence.fromJson(rawPresence); var presence = Presence.fromJson(rawPresence);
expect(presence.sender, '@example:localhost'); expect(presence.sender, '@example:localhost');
expect(presence.avatarUrl.mxc, 'mxc://localhost:wefuiwegh8742w'); expect(presence.avatarUrl.toString(), 'mxc://example.org/wefuiwegh8742w');
expect(presence.currentlyActive, false); expect(presence.currentlyActive, false);
expect(presence.lastActiveAgo, 2478593); expect(presence.lastActiveAgo, 2478593);
expect(presence.presence, PresenceType.online); expect(presence.presence, PresenceType.online);

View file

@ -145,7 +145,7 @@ void main() {
stateKey: ''); stateKey: '');
expect(room.topic, 'testtopic'); expect(room.topic, 'testtopic');
expect(room.avatar.mxc, ''); expect(room.avatar, null);
room.states['m.room.avatar'] = Event( room.states['m.room.avatar'] = Event(
senderId: '@test:example.com', senderId: '@test:example.com',
typeKey: 'm.room.avatar', typeKey: 'm.room.avatar',
@ -154,7 +154,7 @@ void main() {
eventId: '123', eventId: '123',
content: {'url': 'mxc://testurl'}, content: {'url': 'mxc://testurl'},
stateKey: ''); stateKey: '');
expect(room.avatar.mxc, 'mxc://testurl'); expect(room.avatar.toString(), 'mxc://testurl');
room.states['m.room.message'] = Event( room.states['m.room.message'] = Event(
senderId: '@test:example.com', senderId: '@test:example.com',
typeKey: 'm.room.message', typeKey: 'm.room.message',
@ -180,7 +180,7 @@ void main() {
expect(user.id, '@alice:example.org'); expect(user.id, '@alice:example.org');
expect(user.displayName, 'Alice Margatroid'); expect(user.displayName, 'Alice Margatroid');
expect(user.membership, Membership.join); expect(user.membership, Membership.join);
expect(user.avatarUrl.mxc, 'mxc://example.org/SEsfnsuifSDFSSEF'); expect(user.avatarUrl.toString(), 'mxc://example.org/SEsfnsuifSDFSSEF');
expect(user.room.id, '!localpart:server.abc'); expect(user.room.id, '!localpart:server.abc');
}); });

View file

@ -54,7 +54,7 @@ void main() {
expect(user.id, id); expect(user.id, id);
expect(user.membership, membership); expect(user.membership, membership);
expect(user.displayName, displayName); expect(user.displayName, displayName);
expect(user.avatarUrl.mxc, avatarUrl); expect(user.avatarUrl.toString(), avatarUrl);
expect(user.calcDisplayname(), displayName); expect(user.calcDisplayname(), displayName);
}); });