You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.5 KiB
Dart
104 lines
2.5 KiB
Dart
import 'dart:math' show min;
|
|
import 'dart:typed_data';
|
|
import 'dart:ui';
|
|
|
|
import 'package:matrix/matrix.dart';
|
|
|
|
extension ClientDownloadContentExtension on Client {
|
|
Future<Uint8List> downloadMxcCached(
|
|
Uri mxc, {
|
|
num? width,
|
|
num? height,
|
|
bool isThumbnail = false,
|
|
bool? animated,
|
|
ThumbnailMethod? thumbnailMethod,
|
|
bool rounded = false,
|
|
}) async {
|
|
// To stay compatible with previous storeKeys:
|
|
final cacheKey = isThumbnail
|
|
// ignore: deprecated_member_use
|
|
? mxc.getThumbnail(
|
|
this,
|
|
width: width,
|
|
height: height,
|
|
animated: animated,
|
|
method: thumbnailMethod!,
|
|
)
|
|
: mxc;
|
|
|
|
final cachedData = await database.getFile(cacheKey);
|
|
if (cachedData != null) return cachedData;
|
|
|
|
final httpUri = isThumbnail
|
|
? await mxc.getThumbnailUri(
|
|
this,
|
|
width: width,
|
|
height: height,
|
|
animated: animated,
|
|
method: thumbnailMethod,
|
|
)
|
|
: await mxc.getDownloadUri(this);
|
|
|
|
final response = await httpClient.get(
|
|
httpUri,
|
|
headers:
|
|
accessToken == null ? null : {'authorization': 'Bearer $accessToken'},
|
|
);
|
|
if (response.statusCode != 200) {
|
|
throw Exception();
|
|
}
|
|
var imageData = response.bodyBytes;
|
|
|
|
if (rounded) {
|
|
imageData = await _convertToCircularImage(
|
|
imageData,
|
|
min(width ?? 64, height ?? 64).round(),
|
|
);
|
|
}
|
|
|
|
await database.storeFile(cacheKey, imageData, 0);
|
|
|
|
return imageData;
|
|
}
|
|
}
|
|
|
|
Future<Uint8List> _convertToCircularImage(
|
|
Uint8List imageBytes,
|
|
int size,
|
|
) async {
|
|
final codec = await instantiateImageCodec(imageBytes);
|
|
final frame = await codec.getNextFrame();
|
|
final originalImage = frame.image;
|
|
|
|
final recorder = PictureRecorder();
|
|
final canvas = Canvas(recorder);
|
|
|
|
final paint = Paint();
|
|
final rect = Rect.fromLTWH(0, 0, size.toDouble(), size.toDouble());
|
|
|
|
final clipPath = Path()
|
|
..addOval(
|
|
Rect.fromCircle(center: Offset(size / 2, size / 2), radius: size / 2),
|
|
);
|
|
|
|
canvas.clipPath(clipPath);
|
|
|
|
canvas.drawImageRect(
|
|
originalImage,
|
|
Rect.fromLTWH(
|
|
0,
|
|
0,
|
|
originalImage.width.toDouble(),
|
|
originalImage.height.toDouble(),
|
|
),
|
|
rect,
|
|
paint,
|
|
);
|
|
|
|
final picture = recorder.endRecording();
|
|
final circularImage = await picture.toImage(size, size);
|
|
|
|
final byteData = await circularImage.toByteData(format: ImageByteFormat.png);
|
|
return byteData!.buffer.asUint8List();
|
|
}
|