OS level drag and drop
In this lesson we will start with just the native side of things.
Before we start we should talk a bit about drag-and-drop. Maybe you have implemented this in your web apps before. There are many libraries out there and the browser abstracts some of the work for you, but we are going to have to deal with the native APIs directly, and they work a bit differently.
We are going to register a list of supported types. This list is not only limited to files - we can register listeners for strings, files, specific image types and so on. So, here we will encounter the first difference: when you drag and drop a file from the computer file system, we will get not a blob but rather a URL, and it is then up to us to do something with this URL. We will create a copy in our app sandboxed document folder.
Another important difference happens when you drag an element out of another program, for example, dragging an image out of your browser. Here we will not get a URL or a file blob, but a promise object. We need to handle this promise and tell macOS where to download it.
There are many types you can register the app to listen for, so we need to be able to handle each case (more or less).
Registering our app for drop events#
We will start by registering our status bar button to be a droppable element. In
AppDelegate add/change the following lines:
We first start by creating an array of valid types for dropping into our app (they have the
NSPasteboard.PasteboardType type). For now we will register the
string types. On the next line we create a type for the type of
Promises you get when dragging complex objects (we mentioned dragging images from a browser). We finally put all of them into a single array.
Then when we create our status bar button, we call the
registerForDraggedTypes function with our array of types.
Creating extensions for native classes#
lib directory, create the following files:
We are going to extend the native URL object to make it a bit easier to distinguish passed URLs. One useful thing is to know if the URL is an image (so we can display it) or if it is a localFile so we can copy it to our app's internal directory.
We are also going to extend the
FileManager class. The
extractWhereFrom method does spelunking in the internal metadata of a file to extract where it was copied from. This could be the local disk or maybe a website, can be useful to display to the user where this file came from.