diff --git a/packages/desktop_drop/lib/src/channel.dart b/packages/desktop_drop/lib/src/channel.dart index bc3b0aa4..f1bca675 100644 --- a/packages/desktop_drop/lib/src/channel.dart +++ b/packages/desktop_drop/lib/src/channel.dart @@ -37,22 +37,18 @@ class DesktopDrop { }); } - Future startAccessingSecurityScopedResource( - {required Uint8List bookmark}) async { + Future startAccessingSecurityScopedResource({required Uint8List bookmark}) async { Map resultMap = Map(); resultMap["apple-bookmark"] = bookmark; - final bool? result = await _channel.invokeMethod( - "startAccessingSecurityScopedResource", resultMap); + final bool? result = await _channel.invokeMethod("startAccessingSecurityScopedResource", resultMap); if (result == null) return false; return result; } - Future stopAccessingSecurityScopedResource( - {required Uint8List bookmark}) async { + Future stopAccessingSecurityScopedResource({required Uint8List bookmark}) async { Map resultMap = Map(); resultMap["apple-bookmark"] = bookmark; - final bool result = await _channel.invokeMethod( - "stopAccessingSecurityScopedResource", resultMap); + final bool result = await _channel.invokeMethod("stopAccessingSecurityScopedResource", resultMap); return result; } @@ -108,8 +104,7 @@ class DesktopDrop { case "performOperation_linux": // gtk notify 'exit' before 'performOperation'. final text = (call.arguments as List)[0] as String; - final offset = ((call.arguments as List)[1] as List) - .cast(); + final offset = ((call.arguments as List)[1] as List).cast(); final paths = const LineSplitter().convert(text).map((e) { try { return Uri.tryParse(e)?.toFilePath() ?? ''; @@ -124,11 +119,7 @@ class DesktopDrop { )); break; case "performOperation_web": - final results = (call.arguments as List) - .cast() - .map((e) => WebDropItem.fromJson(e.cast())) - .map((e) => e.toDropItem()) - .toList(); + final results = (call.arguments as List).cast().map((e) => WebDropItem.fromJson(e.cast())).map((e) => e.toDropItem()).toList(); _notifyEvent( DropDoneEvent(location: _offset ?? Offset.zero, files: results), ); @@ -154,4 +145,12 @@ class DesktopDrop { assert(_listeners.contains(listener)); _listeners.remove(listener); } + + void enableDragDropVisualFeedback() { + _channel.invokeMethod('enable', {}); + } + + void disableDragDropVisualFeedback() { + _channel.invokeMethod('disable', {}); + } } diff --git a/packages/desktop_drop/macos/Classes/DesktopDropPlugin.swift b/packages/desktop_drop/macos/Classes/DesktopDropPlugin.swift index 0cb33cd9..55b1ddbc 100644 --- a/packages/desktop_drop/macos/Classes/DesktopDropPlugin.swift +++ b/packages/desktop_drop/macos/Classes/DesktopDropPlugin.swift @@ -35,9 +35,22 @@ public class DesktopDropPlugin: NSObject, FlutterPlugin { d.registerForDraggedTypes(NSFilePromiseReceiver.readableDraggedTypes.map { NSPasteboard.PasteboardType($0) }) d.registerForDraggedTypes([NSPasteboard.PasteboardType.fileURL]) - vc.view.addSubview(d) + // If the DropTarget be added from here, drag-and-drop visual feedback will be implemented immediately. + // This will causes the cursor to change to `+` shape and appear as if files can be dropped, even though the flutter code does not include a DropTarget widget. + // vc.view.addSubview(d) registrar.addMethodCallDelegate(instance, channel: channel) + + // Instead, it should be added only when needed and removed otherwise. + // `channel.setMethodCallHandler` should be implemented after `registrar.addMethodCallDelegate` + channel.setMethodCallHandler { call, result in + if call.method == "enable"{ + vc.view.addSubview(d) + }else if (call.method == "disable"){ + d.removeFromSuperview() + } + result(nil) + } } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult){