♻️ Improved image analyzer in attachments
This commit is contained in:
parent
5a7432e330
commit
0573ee456e
@ -31,23 +31,27 @@ Future<String> calculateFileSha256(File file) async {
|
|||||||
return await calculateBytesSha256(bytes);
|
return await calculateBytesSha256(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<double> calculateDataAspectRatio(Uint8List data) async {
|
Future<Map<String, dynamic>> calculateImageData(Uint8List data) async {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
return 1;
|
return {};
|
||||||
}
|
}
|
||||||
final decoder = await Isolate.run(() => img.findDecoderForData(data));
|
final decoder = await Isolate.run(() => img.findDecoderForData(data));
|
||||||
if (decoder == null) return 1;
|
if (decoder == null) return {};
|
||||||
final image = await Isolate.run(() => decoder.decode(data));
|
final image = await Isolate.run(() => decoder.decode(data));
|
||||||
if (image == null) return 1;
|
if (image == null) return {};
|
||||||
return image.width / image.height;
|
return {
|
||||||
|
'width': image.width,
|
||||||
|
'height': image.height,
|
||||||
|
'ratio': image.width / image.height
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<double> calculateFileAspectRatio(File file) async {
|
Future<Map<String, dynamic>> calculateImageMetaFromFile(File file) async {
|
||||||
if (PlatformInfo.isWeb) {
|
if (PlatformInfo.isWeb) {
|
||||||
return 1;
|
return {};
|
||||||
}
|
}
|
||||||
final bytes = await Isolate.run(() => file.readAsBytesSync());
|
final bytes = await Isolate.run(() => file.readAsBytesSync());
|
||||||
return await calculateDataAspectRatio(bytes);
|
return await calculateImageData(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentProvider extends GetConnect {
|
class AttachmentProvider extends GetConnect {
|
||||||
@ -75,8 +79,12 @@ class AttachmentProvider extends GetConnect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Response> createAttachment(
|
Future<Response> createAttachment(
|
||||||
Uint8List data, String path, String hash, String usage,
|
Uint8List data,
|
||||||
{double? ratio}) async {
|
String path,
|
||||||
|
String hash,
|
||||||
|
String usage,
|
||||||
|
Map<String, dynamic>? metadata,
|
||||||
|
) async {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (!await auth.isAuthorized) throw Exception('unauthorized');
|
if (!await auth.isAuthorized) throw Exception('unauthorized');
|
||||||
|
|
||||||
@ -104,9 +112,7 @@ class AttachmentProvider extends GetConnect {
|
|||||||
'hash': hash,
|
'hash': hash,
|
||||||
'usage': usage,
|
'usage': usage,
|
||||||
if (mimetypeOverride != null) 'mimetype': mimetypeOverride,
|
if (mimetypeOverride != null) 'mimetype': mimetypeOverride,
|
||||||
'metadata': jsonEncode({
|
'metadata': jsonEncode(metadata),
|
||||||
if (ratio != null) 'ratio': ratio,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
final resp = await client.post('/attachments', payload);
|
final resp = await client.post('/attachments', payload);
|
||||||
if (resp.statusCode != 200) {
|
if (resp.statusCode != 200) {
|
||||||
|
@ -87,12 +87,14 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
try {
|
try {
|
||||||
final file = File(image.path);
|
final file = File(image.path);
|
||||||
final hash = await calculateFileSha256(file);
|
final hash = await calculateFileSha256(file);
|
||||||
|
final meta = await calculateImageMetaFromFile(file);
|
||||||
|
|
||||||
attachResp = await provider.createAttachment(
|
attachResp = await provider.createAttachment(
|
||||||
await file.readAsBytes(),
|
await file.readAsBytes(),
|
||||||
file.path,
|
file.path,
|
||||||
hash,
|
hash,
|
||||||
'p.$position',
|
'p.$position',
|
||||||
ratio: await calculateFileAspectRatio(file),
|
{...meta},
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
|
@ -54,13 +54,14 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
for (final media in medias) {
|
for (final media in medias) {
|
||||||
final file = File(media.path);
|
final file = File(media.path);
|
||||||
final hash = await calculateFileSha256(file);
|
final hash = await calculateFileSha256(file);
|
||||||
|
final meta = await calculateImageMetaFromFile(file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await uploadAttachment(
|
await uploadAttachment(
|
||||||
await file.readAsBytes(),
|
await file.readAsBytes(),
|
||||||
file.path,
|
file.path,
|
||||||
hash,
|
hash,
|
||||||
ratio: await calculateFileAspectRatio(file),
|
{...meta},
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
@ -81,11 +82,11 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
|
|
||||||
final file = File(media.path);
|
final file = File(media.path);
|
||||||
final hash = await calculateFileSha256(file);
|
final hash = await calculateFileSha256(file);
|
||||||
const ratio = 16 / 9;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await uploadAttachment(await file.readAsBytes(), file.path, hash,
|
await uploadAttachment(await file.readAsBytes(), file.path, hash, {
|
||||||
ratio: ratio);
|
'ratio': 16 / 9,
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
}
|
}
|
||||||
@ -97,8 +98,9 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (!await auth.isAuthorized) return;
|
if (!await auth.isAuthorized) return;
|
||||||
|
|
||||||
FilePickerResult? result =
|
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||||
await FilePicker.platform.pickFiles(allowMultiple: true);
|
allowMultiple: true,
|
||||||
|
);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
@ -108,7 +110,7 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
for (final file in files) {
|
for (final file in files) {
|
||||||
final hash = await calculateFileSha256(file);
|
final hash = await calculateFileSha256(file);
|
||||||
try {
|
try {
|
||||||
await uploadAttachment(await file.readAsBytes(), file.path, hash);
|
await uploadAttachment(await file.readAsBytes(), file.path, hash, null);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
}
|
}
|
||||||
@ -131,23 +133,20 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
double? ratio;
|
Map<String, dynamic> metadata;
|
||||||
final file = File(media.path);
|
final file = File(media.path);
|
||||||
final hash = await calculateFileSha256(file);
|
final hash = await calculateFileSha256(file);
|
||||||
|
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
ratio = 16 / 9;
|
metadata = {'ratio': 16 / 9};
|
||||||
} else {
|
} else {
|
||||||
ratio = await calculateFileAspectRatio(file);
|
metadata = await calculateImageMetaFromFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await uploadAttachment(
|
await uploadAttachment(await file.readAsBytes(), file.path, hash, {
|
||||||
await file.readAsBytes(),
|
...metadata,
|
||||||
file.path,
|
});
|
||||||
hash,
|
|
||||||
ratio: ratio,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
}
|
}
|
||||||
@ -162,14 +161,14 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
final hash = await calculateBytesSha256(data);
|
final hash = await calculateBytesSha256(data);
|
||||||
final ratio = await calculateDataAspectRatio(data);
|
final meta = await calculateImageData(data);
|
||||||
uploadAttachment(data, 'pasted image', hash, ratio: ratio);
|
uploadAttachment(data, 'Pasted Image', hash, {...meta});
|
||||||
|
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> uploadAttachment(Uint8List data, String path, String hash,
|
Future<void> uploadAttachment(Uint8List data, String path, String hash,
|
||||||
{double? ratio}) async {
|
Map<String, dynamic>? metadata) async {
|
||||||
final AttachmentProvider provider = Get.find();
|
final AttachmentProvider provider = Get.find();
|
||||||
try {
|
try {
|
||||||
context.showSnackbar((PlatformInfo.isWeb
|
context.showSnackbar((PlatformInfo.isWeb
|
||||||
@ -181,7 +180,7 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
path,
|
path,
|
||||||
hash,
|
hash,
|
||||||
widget.usage,
|
widget.usage,
|
||||||
ratio: ratio,
|
metadata,
|
||||||
);
|
);
|
||||||
var result = Attachment.fromJson(resp.body);
|
var result = Attachment.fromJson(resp.body);
|
||||||
setState(() => _attachments.add(result));
|
setState(() => _attachments.add(result));
|
||||||
@ -281,11 +280,14 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
for (final file in detail.files) {
|
for (final file in detail.files) {
|
||||||
final data = await file.readAsBytes();
|
final data = await file.readAsBytes();
|
||||||
final hash = await calculateBytesSha256(data);
|
final hash = await calculateBytesSha256(data);
|
||||||
double? ratio;
|
|
||||||
|
Map<String, dynamic> meta = {};
|
||||||
|
|
||||||
if (file.mimeType?.split('/').firstOrNull == 'image') {
|
if (file.mimeType?.split('/').firstOrNull == 'image') {
|
||||||
ratio = await calculateDataAspectRatio(data);
|
meta = await calculateImageData(data);
|
||||||
}
|
}
|
||||||
uploadAttachment(data, file.path, hash, ratio: ratio);
|
|
||||||
|
uploadAttachment(data, file.path, hash, {...meta});
|
||||||
}
|
}
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
},
|
},
|
||||||
@ -347,9 +349,8 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontFamily: 'monospace'
|
fontFamily: 'monospace'),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${fileType[0].toUpperCase()}${fileType.substring(1)} · ${formatBytes(element.size)}',
|
'${fileType[0].toUpperCase()}${fileType.substring(1)} · ${formatBytes(element.size)}',
|
||||||
@ -506,7 +507,7 @@ class _AttachmentEditorDialogState extends State<AttachmentEditorDialog> {
|
|||||||
_isMature = widget.item.isMature;
|
_isMature = widget.item.isMature;
|
||||||
_altController.text = widget.item.alt;
|
_altController.text = widget.item.alt;
|
||||||
|
|
||||||
if (['image', 'video'].contains(widget.item.mimetype.split('/').first)) {
|
if (['image', 'video'].contains(widget.item.mimetype.split('/').firstOrNull)) {
|
||||||
_ratioController.text =
|
_ratioController.text =
|
||||||
widget.item.metadata?['ratio']?.toString() ?? 1.toString();
|
widget.item.metadata?['ratio']?.toString() ?? 1.toString();
|
||||||
_hasAspectRatio = true;
|
_hasAspectRatio = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user