feat: Pass through a custom image

resize function to the client

This allows the use of the
native imaging package in a more
easy way.
This commit is contained in:
Christian Pauly 2022-03-30 10:35:17 +02:00
parent a915cdacc8
commit 445252b3a5
3 changed files with 27 additions and 11 deletions

View File

@ -104,6 +104,9 @@ class Client extends MatrixApi {
final Duration sendTimelineEventTimeout; final Duration sendTimelineEventTimeout;
MatrixImageFileResizedResponse? Function(MatrixImageFileResizeArguments)?
customImageResizer;
/// Create a client /// Create a client
/// [clientName] = unique identifier of this client /// [clientName] = unique identifier of this client
/// [databaseBuilder]: A function that creates the database instance, that will be used. /// [databaseBuilder]: A function that creates the database instance, that will be used.
@ -141,6 +144,8 @@ class Client extends MatrixApi {
/// code in background. /// code in background.
/// Set [timelineEventTimeout] to the preferred time the Client should retry /// Set [timelineEventTimeout] to the preferred time the Client should retry
/// sending events on connection problems or to `Duration.zero` to disable it. /// sending events on connection problems or to `Duration.zero` to disable it.
/// Set [customImageResizer] to your own implementation for a more advanced
/// and faster image resizing experience.
Client( Client(
this.clientName, { this.clientName, {
this.databaseBuilder, this.databaseBuilder,
@ -164,6 +169,7 @@ class Client extends MatrixApi {
Level? logLevel, Level? logLevel,
Filter? syncFilter, Filter? syncFilter,
this.sendTimelineEventTimeout = const Duration(minutes: 1), this.sendTimelineEventTimeout = const Duration(minutes: 1),
this.customImageResizer,
@deprecated bool? debug, @deprecated bool? debug,
}) : syncFilter = syncFilter ?? }) : syncFilter = syncFilter ??
Filter( Filter(

View File

@ -743,13 +743,16 @@ class Room {
.unsigned![fileSendingStatusKey] = .unsigned![fileSendingStatusKey] =
FileSendingStatus.generatingThumbnail.name; FileSendingStatus.generatingThumbnail.name;
await _handleFakeSync(syncUpdate); await _handleFakeSync(syncUpdate);
thumbnail ??= thumbnail ??= await file.generateThumbnail(
await file.generateThumbnail(compute: client.runInBackground); compute: client.runInBackground,
customImageResizer: client.customImageResizer,
);
if (shrinkImageMaxDimension != null) { if (shrinkImageMaxDimension != null) {
file = await MatrixImageFile.shrink( file = await MatrixImageFile.shrink(
bytes: file.bytes, bytes: file.bytes,
name: file.name, name: file.name,
maxDimension: shrinkImageMaxDimension, maxDimension: shrinkImageMaxDimension,
customImageResizer: client.customImageResizer,
); );
} }
} }

View File

@ -105,14 +105,17 @@ class MatrixImageFile extends MatrixFile {
required String name, required String name,
int maxDimension = 1600, int maxDimension = 1600,
String? mimeType, String? mimeType,
MatrixImageFileResizedResponse? Function(MatrixImageFileResizeArguments)?
customImageResizer,
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 {
final arguments = _ResizeArguments( final arguments = MatrixImageFileResizeArguments(
bytes: bytes, bytes: bytes,
maxDimension: maxDimension, maxDimension: maxDimension,
fileName: name, fileName: name,
calcBlurhash: true, calcBlurhash: true,
); );
customImageResizer ??= _resize;
final resizedData = compute != null final resizedData = compute != null
? await compute(_resize, arguments) ? await compute(_resize, arguments)
: _resize(arguments); : _resize(arguments);
@ -154,6 +157,8 @@ class MatrixImageFile extends MatrixFile {
/// computes a thumbnail for the image /// computes a thumbnail for the image
Future<MatrixImageFile?> generateThumbnail( Future<MatrixImageFile?> generateThumbnail(
{int dimension = Client.defaultThumbnailSize, {int dimension = Client.defaultThumbnailSize,
MatrixImageFileResizedResponse? Function(MatrixImageFileResizeArguments)?
customImageResizer,
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 {
final thumbnailFile = await shrink( final thumbnailFile = await shrink(
@ -162,6 +167,7 @@ class MatrixImageFile extends MatrixFile {
mimeType: mimeType, mimeType: mimeType,
compute: compute, compute: compute,
maxDimension: dimension, maxDimension: dimension,
customImageResizer: customImageResizer,
); );
// the thumbnail should rather return null than the unshrinked image // the thumbnail should rather return null than the unshrinked image
if ((thumbnailFile.width ?? 0) > dimension || if ((thumbnailFile.width ?? 0) > dimension ||
@ -171,11 +177,11 @@ class MatrixImageFile extends MatrixFile {
return thumbnailFile; return thumbnailFile;
} }
static _ResizedResponse? _calcMetadata(Uint8List bytes) { static MatrixImageFileResizedResponse? _calcMetadata(Uint8List bytes) {
final image = decodeImage(bytes); final image = decodeImage(bytes);
if (image == null) return null; if (image == null) return null;
return _ResizedResponse( return MatrixImageFileResizedResponse(
bytes: bytes, bytes: bytes,
width: image.width, width: image.width,
height: image.height, height: image.height,
@ -187,7 +193,8 @@ class MatrixImageFile extends MatrixFile {
); );
} }
static _ResizedResponse? _resize(_ResizeArguments arguments) { static MatrixImageFileResizedResponse? _resize(
MatrixImageFileResizeArguments arguments) {
final image = decodeImage(arguments.bytes); final image = decodeImage(arguments.bytes);
final resized = copyResize(image!, final resized = copyResize(image!,
@ -197,7 +204,7 @@ 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;
final bytes = Uint8List.fromList(encoded); final bytes = Uint8List.fromList(encoded);
return _ResizedResponse( return MatrixImageFileResizedResponse(
bytes: bytes, bytes: bytes,
width: resized.width, width: resized.width,
height: resized.height, height: resized.height,
@ -212,13 +219,13 @@ class MatrixImageFile extends MatrixFile {
} }
} }
class _ResizedResponse { class MatrixImageFileResizedResponse {
final Uint8List bytes; final Uint8List bytes;
final int width; final int width;
final int height; final int height;
final String? blurhash; final String? blurhash;
const _ResizedResponse({ const MatrixImageFileResizedResponse({
required this.bytes, required this.bytes,
required this.width, required this.width,
required this.height, required this.height,
@ -226,13 +233,13 @@ class _ResizedResponse {
}); });
} }
class _ResizeArguments { class MatrixImageFileResizeArguments {
final Uint8List bytes; final Uint8List bytes;
final int maxDimension; final int maxDimension;
final String fileName; final String fileName;
final bool calcBlurhash; final bool calcBlurhash;
const _ResizeArguments({ const MatrixImageFileResizeArguments({
required this.bytes, required this.bytes,
required this.maxDimension, required this.maxDimension,
required this.fileName, required this.fileName,