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';
|
import '../../matrix.dart';
|
||||||
|
|
||||||
class MatrixFile {
|
class MatrixFile {
|
||||||
Uint8List bytes;
|
final Uint8List bytes;
|
||||||
String name;
|
final String name;
|
||||||
String mimeType;
|
final String mimeType;
|
||||||
|
|
||||||
/// Encrypts this file and returns the
|
/// Encrypts this file and returns the
|
||||||
/// encryption information as an [EncryptedFile].
|
/// encryption information as an [EncryptedFile].
|
||||||
|
|
@ -66,14 +66,36 @@ class MatrixFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MatrixImageFile extends MatrixFile {
|
class MatrixImageFile extends MatrixFile {
|
||||||
Image? _image;
|
|
||||||
|
|
||||||
MatrixImageFile({
|
MatrixImageFile({
|
||||||
required Uint8List bytes,
|
required Uint8List bytes,
|
||||||
required String name,
|
required String name,
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
|
this.blurhash,
|
||||||
}) : super(bytes: bytes, name: name, mimeType: mimeType);
|
}) : 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
|
/// builds a [MatrixImageFile] and shrinks it in order to reduce traffic
|
||||||
///
|
///
|
||||||
/// in case shrinking does not work (e.g. for unsupported MIME types), the
|
/// in case shrinking does not work (e.g. for unsupported MIME types), the
|
||||||
|
|
@ -85,11 +107,11 @@ class MatrixImageFile extends MatrixFile {
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
Future<T> Function<T, U>(FutureOr<T> Function(U arg) function, U arg)?
|
||||||
compute}) async {
|
compute}) async {
|
||||||
Image? image;
|
|
||||||
final arguments = _ResizeArguments(
|
final arguments = _ResizeArguments(
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
maxDimension: maxDimension,
|
maxDimension: maxDimension,
|
||||||
fileName: name,
|
fileName: name,
|
||||||
|
calcBlurhash: true,
|
||||||
);
|
);
|
||||||
final resizedData = compute != null
|
final resizedData = compute != null
|
||||||
? await compute(_resize, arguments)
|
? await compute(_resize, arguments)
|
||||||
|
|
@ -98,48 +120,26 @@ class MatrixImageFile extends MatrixFile {
|
||||||
if (resizedData == null) {
|
if (resizedData == null) {
|
||||||
return MatrixImageFile(bytes: bytes, name: name, mimeType: mimeType);
|
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(
|
final thumbnailFile = MatrixImageFile(
|
||||||
bytes: Uint8List.fromList(encoded),
|
bytes: resizedData.bytes,
|
||||||
name: name,
|
name: name,
|
||||||
mimeType: mimeType,
|
mimeType: mimeType,
|
||||||
|
width: resizedData.width,
|
||||||
|
height: resizedData.height,
|
||||||
|
blurhash: resizedData.blurhash,
|
||||||
);
|
);
|
||||||
// preserving the previously generated image
|
|
||||||
thumbnailFile._image = image;
|
|
||||||
return thumbnailFile;
|
return thumbnailFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns the width of the image
|
/// returns the width of the image
|
||||||
int? get width {
|
final int? width;
|
||||||
_image ??= decodeImage(bytes);
|
|
||||||
return _image?.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// returns the height of the image
|
/// returns the height of the image
|
||||||
int? get height {
|
final int? height;
|
||||||
_image ??= decodeImage(bytes);
|
|
||||||
return _image?.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// generates the blur hash for the image
|
/// generates the blur hash for the image
|
||||||
String? get blurhash {
|
final String? blurhash;
|
||||||
_image ??= decodeImage(bytes)!;
|
|
||||||
if (_image != null) {
|
|
||||||
final blur = BlurHash.encode(_image!, numCompX: 4, numCompY: 3);
|
|
||||||
return blur.hash;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get msgType => 'm.image';
|
String get msgType => 'm.image';
|
||||||
|
|
@ -171,7 +171,23 @@ class MatrixImageFile extends MatrixFile {
|
||||||
return thumbnailFile;
|
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 image = decodeImage(arguments.bytes);
|
||||||
|
|
||||||
final resized = copyResize(image!,
|
final resized = copyResize(image!,
|
||||||
|
|
@ -180,26 +196,54 @@ class MatrixImageFile extends MatrixFile {
|
||||||
|
|
||||||
final encoded = encodeNamedImage(resized, arguments.fileName);
|
final encoded = encodeNamedImage(resized, arguments.fileName);
|
||||||
if (encoded == null) return null;
|
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 {
|
class _ResizeArguments {
|
||||||
final Uint8List bytes;
|
final Uint8List bytes;
|
||||||
final int maxDimension;
|
final int maxDimension;
|
||||||
final String fileName;
|
final String fileName;
|
||||||
|
final bool calcBlurhash;
|
||||||
|
|
||||||
const _ResizeArguments({
|
const _ResizeArguments({
|
||||||
required this.bytes,
|
required this.bytes,
|
||||||
required this.maxDimension,
|
required this.maxDimension,
|
||||||
required this.fileName,
|
required this.fileName,
|
||||||
|
required this.calcBlurhash,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MatrixVideoFile extends MatrixFile {
|
class MatrixVideoFile extends MatrixFile {
|
||||||
int? width;
|
final int? width;
|
||||||
int? height;
|
final int? height;
|
||||||
int? duration;
|
final int? duration;
|
||||||
|
|
||||||
MatrixVideoFile(
|
MatrixVideoFile(
|
||||||
{required Uint8List bytes,
|
{required Uint8List bytes,
|
||||||
|
|
@ -221,7 +265,7 @@ class MatrixVideoFile extends MatrixFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MatrixAudioFile extends MatrixFile {
|
class MatrixAudioFile extends MatrixFile {
|
||||||
int? duration;
|
final int? duration;
|
||||||
|
|
||||||
MatrixAudioFile(
|
MatrixAudioFile(
|
||||||
{required Uint8List bytes,
|
{required Uint8List bytes,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ void main() {
|
||||||
'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';
|
'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';
|
||||||
final data = base64Decode(base64Image);
|
final data = base64Decode(base64Image);
|
||||||
|
|
||||||
final image = MatrixImageFile(
|
final image = await MatrixImageFile.create(
|
||||||
bytes: data,
|
bytes: data,
|
||||||
name: 'bomb.png',
|
name: 'bomb.png',
|
||||||
mimeType: 'image/png',
|
mimeType: 'image/png',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue