💄 Better paste & drag 'n drop handling

This commit is contained in:
LittleSheep 2024-06-30 17:43:36 +08:00
parent 8c7de68e7a
commit 9d54b04f77
3 changed files with 62 additions and 45 deletions

View File

@ -31,16 +31,23 @@ Future<String> calculateFileSha256(File file) async {
return await calculateBytesSha256(bytes); return await calculateBytesSha256(bytes);
} }
Future<double> calculateDataAspectRatio(Uint8List data) async {
if (PlatformInfo.isWeb) {
return 1;
}
final decoder = await Isolate.run(() => img.findDecoderForData(data));
if (decoder == null) return 1;
final image = await Isolate.run(() => decoder.decode(data));
if (image == null) return 1;
return image.width / image.height;
}
Future<double> calculateFileAspectRatio(File file) async { Future<double> calculateFileAspectRatio(File file) async {
if (PlatformInfo.isWeb) { if (PlatformInfo.isWeb) {
return 1; return 1;
} }
final bytes = await Isolate.run(() => file.readAsBytesSync()); final bytes = await Isolate.run(() => file.readAsBytesSync());
final decoder = await Isolate.run(() => img.findDecoderForData(bytes)); return await calculateDataAspectRatio(bytes);
if (decoder == null) return 1;
final image = await Isolate.run(() => decoder.decode(bytes));
if (image == null) return 1;
return image.width / image.height;
} }
class AttachmentProvider extends GetConnect { class AttachmentProvider extends GetConnect {

View File

@ -82,17 +82,25 @@ class AccountHeadingWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.baseline, crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic, textBaseline: TextBaseline.alphabetic,
children: [ children: [
Text( Flexible(
nick, child: Text(
style: const TextStyle( nick,
fontSize: 17, maxLines: 1,
fontWeight: FontWeight.bold, overflow: TextOverflow.ellipsis,
), style: const TextStyle(
).paddingOnly(right: 4), fontSize: 17,
Text( fontWeight: FontWeight.bold,
'@$name', ),
style: const TextStyle( ).paddingOnly(right: 4),
fontSize: 15, ),
Flexible(
child: Text(
'@$name',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 15,
),
), ),
), ),
], ],

View File

@ -158,30 +158,44 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
final clipboard = SystemClipboard.instance; final clipboard = SystemClipboard.instance;
if (clipboard == null) return; if (clipboard == null) return;
final reader = await clipboard.read(); final reader = await clipboard.read();
for (final format in Formats.standardFormats.whereType<FileFormat>()) { handleNativeReader(reader);
if (reader.canProvide(format)) {
reader.getFile(format, (file) async {
final data = await file.readAll();
await uploadAttachment(
data,
file.fileName ?? 'unknown',
await calculateBytesSha256(data),
);
});
}
}
} }
void handlePasteFile(ClipboardReadEvent event) async { void handlePasteEvent(ClipboardReadEvent event) async {
final reader = await event.getClipboardReader(); final reader = await event.getClipboardReader();
for (final format in Formats.standardFormats.whereType<FileFormat>()) { handleNativeReader(reader);
}
void handleNativeReader(DataReader reader) async {
var read = false;
for (final format in Formats.standardFormats
.whereType<FileFormat>()
.where((x) => ![Formats.tiff].contains(x))) {
if (read) break;
if (reader.canProvide(format)) { if (reader.canProvide(format)) {
reader.getFile(format, (file) async { reader.getFile(format, (file) async {
if (read) return;
final data = await file.readAll(); final data = await file.readAll();
read = true;
// Calculate ratio if available
double? ratio;
if ([
Formats.png,
Formats.jpeg,
Formats.gif,
Formats.ico,
Formats.webp
].contains(format)) {
ratio = await calculateDataAspectRatio(data);
}
await uploadAttachment( await uploadAttachment(
data, data,
file.fileName ?? 'unknown', file.fileName ?? 'unknown',
await calculateBytesSha256(data), await calculateBytesSha256(data),
ratio: ratio,
); );
}); });
} }
@ -262,13 +276,13 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
void initState() { void initState() {
super.initState(); super.initState();
revertMetadataList(); revertMetadataList();
ClipboardEvents.instance?.registerPasteEventListener(handlePasteFile); ClipboardEvents.instance?.registerPasteEventListener(handlePasteEvent);
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
ClipboardEvents.instance?.unregisterPasteEventListener(handlePasteFile); ClipboardEvents.instance?.unregisterPasteEventListener(handlePasteEvent);
} }
@override @override
@ -291,19 +305,7 @@ class _AttachmentPublishPopupState extends State<AttachmentPublishPopup> {
onPerformDrop: (event) async { onPerformDrop: (event) async {
for (final item in event.session.items) { for (final item in event.session.items) {
final reader = item.dataReader!; final reader = item.dataReader!;
for (final format handleNativeReader(reader);
in Formats.standardFormats.whereType<FileFormat>()) {
if (reader.canProvide(format)) {
reader.getFile(format, (file) async {
final data = await file.readAll();
await uploadAttachment(
data,
file.fileName ?? 'unknown',
await calculateBytesSha256(data),
);
});
}
}
} }
}, },
child: Column( child: Column(