Merge branch 'matrixfile-refactor-all' into 'master'
MatrixFile refactoring for thumbnails See merge request famedly/famedlysdk!371
This commit is contained in:
commit
0ac7aec071
|
@ -449,7 +449,7 @@ class Client {
|
|||
|
||||
/// Uploads a new user avatar for this user.
|
||||
Future<void> setAvatar(MatrixFile file) async {
|
||||
final uploadResp = await api.upload(file.bytes, file.path);
|
||||
final uploadResp = await api.upload(file.bytes, file.name);
|
||||
await api.setAvatarUrl(userID, Uri.parse(uploadResp));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -424,7 +424,7 @@ class Event extends MatrixEvent {
|
|||
encryptedFile.sha256 = fileMap['hashes']['sha256'];
|
||||
uint8list = await decryptFile(encryptedFile);
|
||||
}
|
||||
return MatrixFile(bytes: uint8list, path: '/$body');
|
||||
return MatrixFile(bytes: uint8list, name: body);
|
||||
}
|
||||
|
||||
/// Returns a localized String representation of this event. For a
|
||||
|
|
|
@ -25,9 +25,7 @@ import 'package:famedlysdk/src/event.dart';
|
|||
import 'package:famedlysdk/src/utils/event_update.dart';
|
||||
import 'package:famedlysdk/src/utils/room_update.dart';
|
||||
import 'package:famedlysdk/src/utils/matrix_file.dart';
|
||||
import 'package:image/image.dart';
|
||||
import 'package:matrix_file_e2ee/matrix_file_e2ee.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:html_unescape/html_unescape.dart';
|
||||
|
||||
import './user.dart';
|
||||
|
@ -504,79 +502,53 @@ class Room {
|
|||
return sendEvent(event, txid: txid, inReplyTo: inReplyTo);
|
||||
}
|
||||
|
||||
/// Sends a [file] to this room after uploading it. The [msgType] is optional
|
||||
/// and will be detected by the mimetype of the file. Returns the mxc uri of
|
||||
/// Sends a [file] to this room after uploading it. Returns the mxc uri of
|
||||
/// the uploaded file. If [waitUntilSent] is true, the future will wait until
|
||||
/// the message event has received the server. Otherwise the future will only
|
||||
/// wait until the file has been uploaded.
|
||||
Future<String> sendFileEvent(
|
||||
MatrixFile file, {
|
||||
String msgType,
|
||||
String txid,
|
||||
Event inReplyTo,
|
||||
Map<String, dynamic> info,
|
||||
bool waitUntilSent = false,
|
||||
MatrixFile thumbnail,
|
||||
MatrixImageFile thumbnail,
|
||||
}) async {
|
||||
Image fileImage;
|
||||
Image thumbnailImage;
|
||||
EncryptedFile encryptedThumbnail;
|
||||
String thumbnailUploadResp;
|
||||
|
||||
var fileName = file.path.split('/').last;
|
||||
final mimeType = lookupMimeType(file.path, headerBytes: file.bytes) ?? '';
|
||||
if (msgType == null) {
|
||||
final metaType = (mimeType).split('/')[0];
|
||||
switch (metaType) {
|
||||
case 'image':
|
||||
case 'audio':
|
||||
case 'video':
|
||||
msgType = 'm.$metaType';
|
||||
break;
|
||||
default:
|
||||
msgType = 'm.file';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (msgType == 'm.image') {
|
||||
fileImage = decodeImage(file.bytes.toList());
|
||||
if (thumbnail != null) {
|
||||
thumbnailImage = decodeImage(thumbnail.bytes.toList());
|
||||
}
|
||||
}
|
||||
|
||||
final sendEncrypted = encrypted && client.fileEncryptionEnabled;
|
||||
MatrixFile uploadFile = file; // ignore: omit_local_variable_types
|
||||
MatrixFile uploadThumbnail = thumbnail; // ignore: omit_local_variable_types
|
||||
EncryptedFile encryptedFile;
|
||||
if (sendEncrypted) {
|
||||
EncryptedFile encryptedThumbnail;
|
||||
if (encrypted && client.fileEncryptionEnabled) {
|
||||
encryptedFile = await file.encrypt();
|
||||
uploadFile = encryptedFile.toMatrixFile();
|
||||
|
||||
if (thumbnail != null) {
|
||||
encryptedThumbnail = await thumbnail.encrypt();
|
||||
uploadThumbnail = encryptedThumbnail.toMatrixFile();
|
||||
}
|
||||
}
|
||||
final uploadResp = await client.api.upload(
|
||||
file.bytes,
|
||||
file.path,
|
||||
contentType: sendEncrypted ? 'application/octet-stream' : null,
|
||||
uploadFile.bytes,
|
||||
uploadFile.name,
|
||||
contentType: uploadFile.mimeType,
|
||||
);
|
||||
if (thumbnail != null) {
|
||||
thumbnailUploadResp = await client.api.upload(
|
||||
thumbnail.bytes,
|
||||
thumbnail.path,
|
||||
contentType: sendEncrypted ? 'application/octet-stream' : null,
|
||||
);
|
||||
}
|
||||
final thumbnailUploadResp = uploadThumbnail != null
|
||||
? await client.api.upload(
|
||||
uploadThumbnail.bytes,
|
||||
uploadThumbnail.name,
|
||||
contentType: uploadThumbnail.mimeType,
|
||||
)
|
||||
: null;
|
||||
|
||||
// Send event
|
||||
var content = <String, dynamic>{
|
||||
'msgtype': msgType,
|
||||
'body': fileName,
|
||||
'filename': fileName,
|
||||
if (!sendEncrypted) 'url': uploadResp,
|
||||
if (sendEncrypted)
|
||||
'msgtype': file.msgType,
|
||||
'body': file.name,
|
||||
'filename': file.name,
|
||||
if (encryptedFile == null) 'url': uploadResp,
|
||||
if (encryptedFile != null)
|
||||
'file': {
|
||||
'url': uploadResp,
|
||||
'mimetype': mimeType,
|
||||
'mimetype': file.mimeType,
|
||||
'v': 'v2',
|
||||
'key': {
|
||||
'alg': 'A256CTR',
|
||||
|
@ -588,37 +560,27 @@ class Room {
|
|||
'iv': encryptedFile.iv,
|
||||
'hashes': {'sha256': encryptedFile.sha256}
|
||||
},
|
||||
'info': info ??
|
||||
{
|
||||
'mimetype': mimeType,
|
||||
'size': file.size,
|
||||
if (fileImage != null) 'h': fileImage.height,
|
||||
if (fileImage != null) 'w': fileImage.width,
|
||||
if (thumbnailUploadResp != null && !sendEncrypted)
|
||||
'thumbnail_url': thumbnailUploadResp,
|
||||
if (thumbnailUploadResp != null && sendEncrypted)
|
||||
'thumbnail_file': {
|
||||
'url': thumbnailUploadResp,
|
||||
'mimetype': mimeType,
|
||||
'v': 'v2',
|
||||
'key': {
|
||||
'alg': 'A256CTR',
|
||||
'ext': true,
|
||||
'k': encryptedThumbnail.k,
|
||||
'key_ops': ['encrypt', 'decrypt'],
|
||||
'kty': 'oct'
|
||||
},
|
||||
'iv': encryptedThumbnail.iv,
|
||||
'hashes': {'sha256': encryptedThumbnail.sha256}
|
||||
},
|
||||
if (thumbnailImage != null)
|
||||
'thumbnail_info': {
|
||||
'h': thumbnailImage.height,
|
||||
'mimetype': mimeType,
|
||||
'size': thumbnail.size,
|
||||
'w': thumbnailImage.width,
|
||||
}
|
||||
}
|
||||
'info': {
|
||||
...file.info,
|
||||
if (thumbnail != null && encryptedThumbnail == null)
|
||||
'thumbnail_url': thumbnailUploadResp,
|
||||
if (thumbnail != null && encryptedThumbnail != null)
|
||||
'thumbnail_file': {
|
||||
'url': thumbnailUploadResp,
|
||||
'mimetype': thumbnail.mimeType,
|
||||
'v': 'v2',
|
||||
'key': {
|
||||
'alg': 'A256CTR',
|
||||
'ext': true,
|
||||
'k': encryptedThumbnail.k,
|
||||
'key_ops': ['encrypt', 'decrypt'],
|
||||
'kty': 'oct'
|
||||
},
|
||||
'iv': encryptedThumbnail.iv,
|
||||
'hashes': {'sha256': encryptedThumbnail.sha256}
|
||||
},
|
||||
if (thumbnail != null) 'thumbnail_info': thumbnail.info,
|
||||
}
|
||||
};
|
||||
final sendResponse = sendEvent(
|
||||
content,
|
||||
|
@ -631,79 +593,6 @@ class Room {
|
|||
return uploadResp;
|
||||
}
|
||||
|
||||
/// Sends an audio file to this room and returns the mxc uri.
|
||||
Future<String> sendAudioEvent(MatrixFile file,
|
||||
{String txid, Event inReplyTo}) async {
|
||||
return await sendFileEvent(file,
|
||||
msgType: 'm.audio', txid: txid, inReplyTo: inReplyTo);
|
||||
}
|
||||
|
||||
/// Sends an image to this room and returns the mxc uri.
|
||||
Future<String> sendImageEvent(MatrixFile file,
|
||||
{String txid, int width, int height, Event inReplyTo}) async {
|
||||
return await sendFileEvent(file,
|
||||
msgType: 'm.image',
|
||||
txid: txid,
|
||||
inReplyTo: inReplyTo,
|
||||
info: {
|
||||
'size': file.size,
|
||||
'mimetype': lookupMimeType(file.path, headerBytes: file.bytes),
|
||||
'w': width,
|
||||
'h': height,
|
||||
});
|
||||
}
|
||||
|
||||
/// Sends an video to this room and returns the mxc uri.
|
||||
Future<String> sendVideoEvent(MatrixFile file,
|
||||
{String txid,
|
||||
int videoWidth,
|
||||
int videoHeight,
|
||||
int duration,
|
||||
MatrixFile thumbnail,
|
||||
int thumbnailWidth,
|
||||
int thumbnailHeight,
|
||||
Event inReplyTo}) async {
|
||||
var info = <String, dynamic>{
|
||||
'size': file.size,
|
||||
'mimetype': lookupMimeType(file.path, headerBytes: file.bytes),
|
||||
};
|
||||
if (videoWidth != null) {
|
||||
info['w'] = videoWidth;
|
||||
}
|
||||
if (thumbnailHeight != null) {
|
||||
info['h'] = thumbnailHeight;
|
||||
}
|
||||
if (duration != null) {
|
||||
info['duration'] = duration;
|
||||
}
|
||||
if (thumbnail != null && !(encrypted && client.encryptionEnabled)) {
|
||||
final thumbnailUploadResp = await client.api.upload(
|
||||
thumbnail.bytes,
|
||||
thumbnail.path,
|
||||
);
|
||||
info['thumbnail_url'] = thumbnailUploadResp;
|
||||
info['thumbnail_info'] = {
|
||||
'size': thumbnail.size,
|
||||
'mimetype':
|
||||
lookupMimeType(thumbnail.path, headerBytes: thumbnail.bytes),
|
||||
};
|
||||
if (thumbnailWidth != null) {
|
||||
info['thumbnail_info']['w'] = thumbnailWidth;
|
||||
}
|
||||
if (thumbnailHeight != null) {
|
||||
info['thumbnail_info']['h'] = thumbnailHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return await sendFileEvent(
|
||||
file,
|
||||
msgType: 'm.video',
|
||||
txid: txid,
|
||||
inReplyTo: inReplyTo,
|
||||
info: info,
|
||||
);
|
||||
}
|
||||
|
||||
/// Sends an event to this room with this json as a content. Returns the
|
||||
/// event ID generated from the server.
|
||||
Future<String> sendEvent(Map<String, dynamic> content,
|
||||
|
@ -1236,7 +1125,7 @@ class Room {
|
|||
/// Uploads a new user avatar for this room. Returns the event ID of the new
|
||||
/// m.room.avatar event.
|
||||
Future<String> setAvatar(MatrixFile file) async {
|
||||
final uploadResp = await client.api.upload(file.bytes, file.path);
|
||||
final uploadResp = await client.api.upload(file.bytes, file.name);
|
||||
return await client.api.sendState(
|
||||
id,
|
||||
EventTypes.RoomAvatar,
|
||||
|
|
|
@ -2,20 +2,100 @@
|
|||
|
||||
import 'dart:typed_data';
|
||||
import 'package:matrix_file_e2ee/matrix_file_e2ee.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
class MatrixFile {
|
||||
Uint8List bytes;
|
||||
String path;
|
||||
String name;
|
||||
String mimeType;
|
||||
|
||||
/// Encrypts this file, changes the [bytes] and returns the
|
||||
/// Encrypts this file and returns the
|
||||
/// encryption information as an [EncryptedFile].
|
||||
Future<EncryptedFile> encrypt() async {
|
||||
var encryptFile2 = encryptFile(bytes);
|
||||
final encryptedFile = await encryptFile2;
|
||||
bytes = encryptedFile.data;
|
||||
return encryptedFile;
|
||||
return await encryptFile(bytes);
|
||||
}
|
||||
|
||||
MatrixFile({this.bytes, this.name, this.mimeType}) {
|
||||
mimeType ??= lookupMimeType(name, headerBytes: bytes);
|
||||
name = name.split('/').last.toLowerCase();
|
||||
}
|
||||
|
||||
MatrixFile({this.bytes, String path}) : path = path.toLowerCase();
|
||||
int get size => bytes.length;
|
||||
|
||||
String get msgType => 'm.file';
|
||||
|
||||
Map<String, dynamic> get info => ({
|
||||
'mimetype': mimeType,
|
||||
'size': size,
|
||||
});
|
||||
}
|
||||
|
||||
class MatrixImageFile extends MatrixFile {
|
||||
int width;
|
||||
int height;
|
||||
String blurhash;
|
||||
|
||||
MatrixImageFile(
|
||||
{Uint8List bytes,
|
||||
String name,
|
||||
String mimeType,
|
||||
this.width,
|
||||
this.height,
|
||||
this.blurhash})
|
||||
: super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
@override
|
||||
String get msgType => 'm.image';
|
||||
@override
|
||||
Map<String, dynamic> get info => ({
|
||||
...super.info,
|
||||
if (width != null) 'w': width,
|
||||
if (height != null) 'h': height,
|
||||
if (blurhash != null) 'xyz.amorgan.blurhash': blurhash,
|
||||
});
|
||||
}
|
||||
|
||||
class MatrixVideoFile extends MatrixFile {
|
||||
int width;
|
||||
int height;
|
||||
int duration;
|
||||
|
||||
MatrixVideoFile(
|
||||
{Uint8List bytes,
|
||||
String name,
|
||||
String mimeType,
|
||||
this.width,
|
||||
this.height,
|
||||
this.duration})
|
||||
: super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
@override
|
||||
String get msgType => 'm.video';
|
||||
@override
|
||||
Map<String, dynamic> get info => ({
|
||||
...super.info,
|
||||
if (width != null) 'w': width,
|
||||
if (height != null) 'h': height,
|
||||
if (duration != null) 'duration': duration,
|
||||
});
|
||||
}
|
||||
|
||||
class MatrixAudioFile extends MatrixFile {
|
||||
int duration;
|
||||
|
||||
MatrixAudioFile(
|
||||
{Uint8List bytes, String name, String mimeType, this.duration})
|
||||
: super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
@override
|
||||
String get msgType => 'm.audio';
|
||||
@override
|
||||
Map<String, dynamic> get info => ({
|
||||
...super.info,
|
||||
if (duration != null) 'duration': duration,
|
||||
});
|
||||
}
|
||||
|
||||
extension ToMatrixFile on EncryptedFile {
|
||||
MatrixFile toMatrixFile() {
|
||||
return MatrixFile(
|
||||
bytes: data, name: 'crypt', mimeType: 'application/octet-stream');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,13 +274,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.12"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -11,7 +11,6 @@ dependencies:
|
|||
http: ^0.12.1
|
||||
mime: ^0.9.6
|
||||
canonical_json: ^1.0.0
|
||||
image: ^2.1.4
|
||||
markdown: ^2.1.3
|
||||
html_unescape: ^1.0.1+3
|
||||
moor: ^3.0.2
|
||||
|
|
|
@ -343,8 +343,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('setAvatar', () async {
|
||||
final testFile =
|
||||
MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg');
|
||||
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
|
||||
await matrix.setAvatar(testFile);
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ void main() {
|
|||
test('Decrypt', () async {
|
||||
final text = 'hello world';
|
||||
final file = MatrixFile(
|
||||
path: '/path/to/file.txt',
|
||||
name: 'file.txt',
|
||||
bytes: Uint8List.fromList(text.codeUnits),
|
||||
);
|
||||
var olmEnabled = true;
|
||||
|
|
|
@ -333,8 +333,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('setAvatar', () async {
|
||||
final testFile =
|
||||
MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg');
|
||||
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
|
||||
final dynamic resp = await room.setAvatar(testFile);
|
||||
expect(resp, 'YUwRidLecu:example.com');
|
||||
});
|
||||
|
@ -361,10 +360,8 @@ void main() {
|
|||
});*/
|
||||
|
||||
test('sendFileEvent', () async {
|
||||
final testFile =
|
||||
MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg');
|
||||
final dynamic resp = await room.sendFileEvent(testFile,
|
||||
msgType: 'm.file', txid: 'testtxid');
|
||||
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
|
||||
final dynamic resp = await room.sendFileEvent(testFile, txid: 'testtxid');
|
||||
expect(resp, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw');
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue