From f55514eef0fba7bf283d384646c1623c536dc913 Mon Sep 17 00:00:00 2001 From: Crizant Lai Date: Thu, 15 Feb 2024 11:30:57 +0800 Subject: [PATCH] feat: handle drop files from web --- .DS_Store | Bin 0 -> 6148 bytes packages/desktop_drop/example/pubspec.lock | 6 +-- .../desktop_drop/lib/desktop_drop_web.dart | 36 ++++++++++++++++-- .../desktop_drop/lib/src/web_drop_item.dart | 4 +- packages/desktop_drop/pubspec.yaml | 3 +- 5 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..510230b521fedb692317cf09f272cc67907ac1d1 GIT binary patch literal 6148 zcmeHK&uiN-6n;w6#-(H6HR)~}45CT50 ze@w6YOZM+<-;>nRke1!THuT`>dwM@C^hrn-5sA(u*(0hGkq2e0_-LLGjvWjn{;$N;Zhjo#BS9Z`=St)Ge!;cd}|?)=gMi?_m%BD$a}w3jrX z!mRg0{@tJQ<7qLBGoAk<9%gAVZZ?04%35`OqvqATP47$iO-;jbG@cZlX!MDDr%Gk< zy&c78>0sKgzdTa;I7;)uNEf8Z04bl((>zhrj+*32p=(1E@O;nj*SBZ0*8aPO+-tVx z4LLh_(`?B7*4z2q_qJZ|9-j2Cvg=%Z*E1!7U9IJX#e2AgvBbkoILb4XUn0hJKAnKk zHg)L(aEGobS!7DQLe^tu(RJb&a11yGR>FWi-Mr0}jOGS$3^)ekWj|JVrftx z9cc6u09b`v3vB*raozv` literal 0 HcmV?d00001 diff --git a/packages/desktop_drop/example/pubspec.lock b/packages/desktop_drop/example/pubspec.lock index c09f4e10..27ed279c 100644 --- a/packages/desktop_drop/example/pubspec.lock +++ b/packages/desktop_drop/example/pubspec.lock @@ -208,10 +208,10 @@ packages: dependency: transitive description: name: web - sha256: "14f1f70c51119012600c5f1f60ca68efda5a9b6077748163c6af2893ec5df8fc" + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.2.1-beta" + version: "0.3.0" sdks: - dart: ">=3.2.0-157.0.dev <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=1.20.0" diff --git a/packages/desktop_drop/lib/desktop_drop_web.dart b/packages/desktop_drop/lib/desktop_drop_web.dart index 03a529ef..448bba09 100644 --- a/packages/desktop_drop/lib/desktop_drop_web.dart +++ b/packages/desktop_drop/lib/desktop_drop_web.dart @@ -1,10 +1,12 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:html' as html; import 'dart:js_util' as js_util; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:mime/mime.dart'; import 'src/web_drop_item.dart'; @@ -47,7 +49,8 @@ class DesktopDropWeb { final children = await Future.wait( entries.map((e) => _entryToWebDropItem(e)), ) - ..removeWhere((element) => element.name == '.DS_Store' && element.type == ''); + ..removeWhere( + (element) => element.name == '.DS_Store' && element.type == ''); return WebDropItem( uri: html.Url.createObjectUrlFromBlob(html.Blob([], 'directory')), name: entry.name ?? '', @@ -80,6 +83,11 @@ class DesktopDropWeb { ); } + String _getMimeType(String text) { + final pattern = RegExp(r'^data:([^;]+);'); + return pattern.firstMatch(text)?.group(1) ?? 'text/plain'; + } + void _registerEvents() { html.window.onDrop.listen((event) { event.preventDefault(); @@ -87,12 +95,32 @@ class DesktopDropWeb { final items = event.dataTransfer.items; Future.wait(List.generate(items?.length ?? 0, (index) { final item = items![index]; - final entry = item.getAsEntry(); - return _entryToWebDropItem(entry); + if (item.kind == 'file') { + final entry = item.getAsEntry(); + return _entryToWebDropItem(entry); + } + if (item.kind == 'string' && item.type == 'text/uri-list') { + final data = event.dataTransfer.getData(item.type!); + final mime = _getMimeType(data); + return Future.value( + WebDropItem( + uri: data, + name: 'file.${extensionFromMime(mime)}', + type: mime, + data: base64Decode(data.split(';base64,')[1]), + size: 0, + relativePath: '', + lastModified: DateTime.now(), + children: [], + ), + ); + } + // other types such as text/html + return Future.value(null); })).then((webItems) { channel.invokeMethod( "performOperation_web", - webItems.map((e) => e.toJson()).toList(), + webItems.whereType().map((e) => e.toJson()).toList(), ); }).catchError((e, s) { debugPrint('desktop_drop_web: $e $s'); diff --git a/packages/desktop_drop/lib/src/web_drop_item.dart b/packages/desktop_drop/lib/src/web_drop_item.dart index 1a8a758d..f12aedab 100644 --- a/packages/desktop_drop/lib/src/web_drop_item.dart +++ b/packages/desktop_drop/lib/src/web_drop_item.dart @@ -31,7 +31,9 @@ class WebDropItem { .cast() .map((e) => WebDropItem.fromJson(e.cast())) .toList(), - data: json['data'] != null ? Uint8List.fromList(json['data']) : null, + data: json['data'] != null + ? Uint8List.fromList((json['data'] as List).cast()) + : null, name: json['name'], type: json['type'], size: json['size'], diff --git a/packages/desktop_drop/pubspec.yaml b/packages/desktop_drop/pubspec.yaml index da850a04..5fcbddba 100644 --- a/packages/desktop_drop/pubspec.yaml +++ b/packages/desktop_drop/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: flutter_web_plugins: sdk: flutter cross_file: ^0.3.3+4 + mime: ^1.0.5 dev_dependencies: flutter_test: @@ -33,4 +34,4 @@ flutter: pluginClass: DesktopDropPlugin web: pluginClass: DesktopDropWeb - fileName: desktop_drop_web.dart \ No newline at end of file + fileName: desktop_drop_web.dart