Merge branch 'krille/matrix-file-improvements' into 'main'
refactor: Make MatrixFile final and move all image calculation into isolate Closes famedly/fluffychat#863 See merge request famedly/company/frontend/famedlysdk!972
This commit is contained in:
commit
93b11dd8ca
|
|
@ -28,9 +28,9 @@ import 'package:mime/mime.dart';
|
|||
import '../../matrix.dart';
|
||||
|
||||
class MatrixFile {
|
||||
Uint8List bytes;
|
||||
String name;
|
||||
String mimeType;
|
||||
final Uint8List bytes;
|
||||
final String name;
|
||||
final String mimeType;
|
||||
|
||||
/// Encrypts this file and returns the
|
||||
/// encryption information as an [EncryptedFile].
|
||||
|
|
@ -66,14 +66,36 @@ class MatrixFile {
|
|||
}
|
||||
|
||||
class MatrixImageFile extends MatrixFile {
|
||||
Image? _image;
|
||||
|
||||
MatrixImageFile({
|
||||
required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
this.width,
|
||||
this.height,
|
||||
this.blurhash,
|
||||
}) : super(bytes: bytes, name: name, mimeType: mimeType);
|
||||
|
||||
/// Creates a new image file and calculates the width, height and blurhash.
|
||||
static Future<MatrixImageFile> create(
|
||||
{required Uint8List bytes,
|
||||
required String name,
|
||||
String? mimeType,
|
||||
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
||||
compute}) async {
|
||||
final metaData = compute != null
|
||||
? await compute(_calcMetadata, bytes)
|
||||
: _calcMetadata(bytes);
|
||||
|
||||
return MatrixImageFile(
|
||||
bytes: metaData?.bytes ?? bytes,
|
||||
name: name,
|
||||
mimeType: mimeType,
|
||||
width: metaData?.width,
|
||||
height: metaData?.height,
|
||||
blurhash: metaData?.blurhash,
|
||||
);
|
||||
}
|
||||
|
||||
/// builds a [MatrixImageFile] and shrinks it in order to reduce traffic
|
||||
///
|
||||
/// in case shrinking does not work (e.g. for unsupported MIME types), the
|
||||
|
|
@ -85,11 +107,11 @@ class MatrixImageFile extends MatrixFile {
|
|||
String? mimeType,
|
||||
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
||||
compute}) async {
|
||||
Image? image;
|
||||
final arguments = _ResizeArguments(
|
||||
bytes: bytes,
|
||||
maxDimension: maxDimension,
|
||||
fileName: name,
|
||||
calcBlurhash: true,
|
||||
);
|
||||
final resizedData = compute != null
|
||||
? await compute(_resize, arguments)
|
||||
|
|
@ -98,48 +120,26 @@ class MatrixImageFile extends MatrixFile {
|
|||
if (resizedData == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
image = decodeImage(resizedData);
|
||||
|
||||
if (image == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
|
||||
final encoded = encodeNamedImage(image, name);
|
||||
if (encoded == null) {
|
||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
||||
}
|
||||
|
||||
final thumbnailFile = MatrixImageFile(
|
||||
bytes: Uint8List.fromList(encoded),
|
||||
bytes: resizedData.bytes,
|
||||
name: name,
|
||||
mimeType: mimeType,
|
||||
width: resizedData.width,
|
||||
height: resizedData.height,
|
||||
blurhash: resizedData.blurhash,
|
||||
);
|
||||
// preserving the previously generated image
|
||||
thumbnailFile._image = image;
|
||||
return thumbnailFile;
|
||||
}
|
||||
|
||||
/// returns the width of the image
|
||||
int? get width {
|
||||
_image ??= decodeImage(bytes);
|
||||
return _image?.width;
|
||||
}
|
||||
final int? width;
|
||||
|
||||
/// returns the height of the image
|
||||
int? get height {
|
||||
_image ??= decodeImage(bytes);
|
||||
return _image?.height;
|
||||
}
|
||||
final int? height;
|
||||
|
||||
/// generates the blur hash for the image
|
||||
String? get blurhash {
|
||||
_image ??= decodeImage(bytes)!;
|
||||
if (_image != null) {
|
||||
final blur = BlurHash.encode(_image!, numCompX: 4, numCompY: 3);
|
||||
return blur.hash;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final String? blurhash;
|
||||
|
||||
@override
|
||||
String get msgType => 'm.image';
|
||||
|
|
@ -171,7 +171,23 @@ class MatrixImageFile extends MatrixFile {
|
|||
return thumbnailFile;
|
||||
}
|
||||
|
||||
static Uint8List? _resize(_ResizeArguments arguments) {
|
||||
static _ResizedResponse? _calcMetadata(Uint8List bytes) {
|
||||
final image = decodeImage(bytes);
|
||||
if (image == null) return null;
|
||||
|
||||
return _ResizedResponse(
|
||||
bytes: bytes,
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
blurhash: BlurHash.encode(
|
||||
image,
|
||||
numCompX: 4,
|
||||
numCompY: 3,
|
||||
).hash,
|
||||
);
|
||||
}
|
||||
|
||||
static _ResizedResponse? _resize(_ResizeArguments arguments) {
|
||||
final image = decodeImage(arguments.bytes);
|
||||
|
||||
final resized = copyResize(image!,
|
||||
|
|
@ -180,26 +196,54 @@ class MatrixImageFile extends MatrixFile {
|
|||
|
||||
final encoded = encodeNamedImage(resized, arguments.fileName);
|
||||
if (encoded == null) return null;
|
||||
return Uint8List.fromList(encoded);
|
||||
final bytes = Uint8List.fromList(encoded);
|
||||
return _ResizedResponse(
|
||||
bytes: bytes,
|
||||
width: resized.width,
|
||||
height: resized.height,
|
||||
blurhash: arguments.calcBlurhash
|
||||
? BlurHash.encode(
|
||||
resized,
|
||||
numCompX: 4,
|
||||
numCompY: 3,
|
||||
).hash
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ResizedResponse {
|
||||
final Uint8List bytes;
|
||||
final int width;
|
||||
final int height;
|
||||
final String? blurhash;
|
||||
|
||||
const _ResizedResponse({
|
||||
required this.bytes,
|
||||
required this.width,
|
||||
required this.height,
|
||||
this.blurhash,
|
||||
});
|
||||
}
|
||||
|
||||
class _ResizeArguments {
|
||||
final Uint8List bytes;
|
||||
final int maxDimension;
|
||||
final String fileName;
|
||||
final bool calcBlurhash;
|
||||
|
||||
const _ResizeArguments({
|
||||
required this.bytes,
|
||||
required this.maxDimension,
|
||||
required this.fileName,
|
||||
required this.calcBlurhash,
|
||||
});
|
||||
}
|
||||
|
||||
class MatrixVideoFile extends MatrixFile {
|
||||
int? width;
|
||||
int? height;
|
||||
int? duration;
|
||||
final int? width;
|
||||
final int? height;
|
||||
final int? duration;
|
||||
|
||||
MatrixVideoFile(
|
||||
{required Uint8List bytes,
|
||||
|
|
@ -221,7 +265,7 @@ class MatrixVideoFile extends MatrixFile {
|
|||
}
|
||||
|
||||
class MatrixAudioFile extends MatrixFile {
|
||||
int? duration;
|
||||
final int? duration;
|
||||
|
||||
MatrixAudioFile(
|
||||
{required Uint8List bytes,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ void main() {
|
|||
'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';
|
||||
final data = base64Decode(base64Image);
|
||||
|
||||
final image = MatrixImageFile(
|
||||
final image = await MatrixImageFile.create(
|
||||
bytes: data,
|
||||
name: 'bomb.png',
|
||||
mimeType: 'image/png',
|
||||
|
|
|
|||
Loading…
Reference in New Issue