tzickel / launcher-plugin-specification

0 stars 1 forks source link

Future-proofing #5

Open skurfer opened 6 years ago

skurfer commented 6 years ago

At a minimum, to save some backward-incompatible changes down the road, I would make these changes:

First, change the data on each entry object from a string to a dictionary:

{
    type1: data1,
    type2: data2
}

The type can be a UTI, MIME type, or something completely made up, as long as it’s consistent.

Second, get rid of EntrySelect. Maybe I’m missing something, but it seems far too limited. That might allow you to open a file or launch an application, but what about moving/renaming/deleting a file? What about quitting or hiding an application?

To replace EntrySelect, in addition to asking the plug-in for a list of entries, the launcher should be able to ask the plug-in for a list of actions or commands. Each action should include a list of types it supports.

Those types don’t necessarily have to come from the same plug-in. For example, you might write a plug-in that does something useful with files, but doesn’t provide files (or anything else) when asked for its entries.

tzickel commented 6 years ago

The way I see this (if it's not understood from the specification, maybe I need to clarify it), is that entries can have subentries so the main entry can be a file entry (which has an execute / open operation on it), and it subentries can be other operations on it (in your example).

The EntrySelect point is exactly to know what to do (without the launcher knowing anything about this). Every entry and subentries can have it's unique id, so when the launcher shows the user "Delete file..." subentry for a given entry, it has an id, that when the user selects it, the launcher notifies the id to the plugin via EntrySelect, and the plugin knows the user wants to delete the file and does it.

This is generic enough so that anything can be coded for any situation. And the added benefit is for example (in this case) if the plugin knows the user does not have permissions to write or execute a file, it can decide not to send them for this specific entry to the launcher at all.

There are 2 others issues I see here (the first i tried to address in the specification):

  1. What happens if you don't have an id or "selectable" is false in the entry, in this case i expect the launcher (unless it wants to do something fancy) to try to execute / open / quick preview the data.
  2. How to have extended abilities between plugins, this I am leaving for future versions of the specifications.
skurfer commented 6 years ago

The way I see this (if it's not understood from the specification, maybe I need to clarify it), is that entries can have subentries so the main entry can be a file entry (which has an execute / open operation on it), and it subentries can be other operations on it (in your example).

OK, that was not obvious. When I think of subentries for a folder, I think of the folder’s contents. For an application, I think of its recent documents or something like that.

So for a file, you’d have the main entry and several subentries, all with the same icon, name, description, etc. but they would each refer to a different command? I suppose the launcher could pull it all apart and present it a different way, but it seems redundant. And the only way to differentiate the command is by embedding it in the identifier somehow?

And the added benefit is for example (in this case) if the plugin knows the user does not have permissions to write or execute a file, it can decide not to send them for this specific entry to the launcher at all.

OK, that corresponds to something we do currently, but it would happen when the entries are created, not when they’re displayed in the interface. I’d have to think through a few use cases to see if that will be sufficient.

How to have extended abilities between plugins, this I am leaving for future versions of the specifications.

Yeah, that’s fair. My point is to just structure things in such a way that when this does get added, it doesn’t break everything. So if you intend for data to only have one key and one value at first, go ahead and make it a dictionary so it can accommodate multiple key/value pairs one day.

tzickel commented 6 years ago

OK, that was not obvious.

I agree that it is hard to convey the abstract of this concept (especially when you come in with something you already do differently), maybe I should have an examples document near the specification one (or put it inside).

When I think of subentries for a folder, I think of the folder’s contents. For an application, I think of its recent documents or something like that.

Exactly, the plugin decides the meaning and what to do with this.

several subentries, all with the same icon, name, description, etc. but they would each refer to a different command?

No need, let's say you have an entry with a filename (with id / text / icon / description / ...), the subentries can have only an id field which just has to be unique (doesn't need to encode anything in it, it can be a UUID for example), and a text of "Delete file..." (no need for icon which can be inherited, description is not needed because of the text which explains what it is). Since the plugin created the id, it will know what to do when the launcher tells it to select it (in this case delete the file). The launcher knows it's a subentry so it can decide what parts to inherit for GUI purposes (depends on it's layout).

this does get added, it doesn’t break everything. So if you intend for data to only have one key and one value at first, go ahead and make it a dictionary so it can accommodate multiple key/value pairs one day.

I still think that even then the solution would be to transform the entry (modify it, and if needed add / change the subentries) instead of making data a dictionary.


I wrote a limit that subentries are non-recursive (this is good for performance reasons as well as GUI ones), so there is a question if you want to implement something like you said "folder where you can enter it and see it's files", I don't think a file explorer should be implemented but we should not limit the case if it can be done easily (or maybe other use case).

My thought about this is to add an API command from the plugin which is called "SetText" where the plugin upon an EntrySelect can decide to change the launcher text field to something else (let's say in this case to the folder name), and thus it would then receive a new request, and it could show it's files for example.

This is something I thought about leaving for future versions of the specification.

skurfer commented 6 years ago

Since the plugin created the id, it will know what to do when the launcher tells it to select it (in this case delete the file).

Well, OK but that requires the plug-in to maintain quite a bit of state so it will know what to do when something comes back to it.

I still think that even then the solution would be to transform the entry (modify it, and if needed add / change the subentries) instead of making data a dictionary.

So let’s say there are 4 plug-ins that provide things that could reasonably be represented as text, like file paths from one, URLs from another, etc. Pasting text is a pretty reasonable thing to do. Are you saying all 4 plug-ins would need to provide their own implementation of “paste” for the text representation of the items they provide?

I don't think a file explorer should be implemented

That should be up to the plug-ins, and the spec shouldn’t impose limits that would prevent it. 😄