No tag assigned by iOS lockscreen action

I have created an action that does what it is supposed to do. When I launch it from within Drafts it assigns a tag after success, as it is set to do.

The same action when launched by its lockscreen widget again does what it is supposed to do—with the exception of assigning the tag.

Is this a bug, a known limitation, or did I do something wrong? It’s not a real problem since most of the action contains of a script and I could add a line to add the tag.

But I’m curious if it is a mistake on my side I could fix. One thing that comes to my mind: I started using the action from within Drafts and that way, naturally, the editor with a draft is active already. So the action has no creation of a draft at the beginning. When launched by a lockscreen widget on the other hand there is no active draft yet. Although there is one after the action is finished and only after that the tag is supposed to get assigned.

You are basically on the right track with your thought pattern.

Sort of covered in the guide, but probably not with enough detail.

All actions are run on a draft, with that draft in context. It becomes the draft global variable for scripts, is the draft used to evaluate template tags for steps, etc. “After success” items are applied to that draft in context as well.

When you run an action from the action list or action bar, the draft in context is the one currently loaded in the editor.

When you run an action from a widget (or from a URL, or similar), a new, blank draft is created and used as the draft in context. After success items are applied to that draft - but, depending on what your action does, that draft may never be saved if it remains blank at the end of the action.

If you shared what your action does exactly, I could help clarify the steps needed to make it work the way you would like from the widget.

I love to share the action. I anyway planned to add it to the repository but in my opinion it needs a bit of polishing yet.

The purpose of my action: I am reading books, real paper ones, and I quote them in digital atomic notes. Each of the notes needs a proper reference. Usually I read one book at a time. I use Bookends as a reference manager. One of its reference formats looks like this: {Jelinek, 2022, #255414} (author, year, unique ID).

My action contains of three steps:

  1. A Template Tag named theReference (in the above reference format).
  2. A Template Tag named theReferenceLanguage (in en-US format or empty for the iOS default language).
  3. The script.

When launched the action prompts to enter the page number of the excerpt from the book and three options to get the excerpt into the draft: Dictate, Scan, and Write. After dictating or scanning the excerpt gets copied into the draft plus—in case of writing: just—the reference in the format:

…[^ref]

[^ref]: {Jelinek, 2022, #255414@17}

And after success the tag “excerpt” gets assigned. Or should get, in case of the lockscreen widget.

This action assumes the draft you want to manipulate is already loaded in the editor, correct? It does not seem to establish any context by loading a draft or anything…you feel comfortable that is a save assumption when running from the widget?

If that is true, I would say your best bet is to create a separate action that queues this action to run on the draft in the editor. So, a stub action with just this script:

let d = editor.draft
let a = Action.find("Bookends-Referenz")
app.queueAction(a, d)

When you run that from the widget, it will open Drafts and run the action as if it was run from the list.

Thank you.

In general as this is about atomic notes the action should stand at the beginning of the creation of such a note. But my script respects both the cursor position and deselects just in case the note already has content which might get overwritten when selected.

Is this stub action the only solution or could it be handled from within my original action? Like make the action start with the condition If Drafts is not opened/If no draft is open Then open/create?

The reason I’m asking: This additional stub action will work fine for me. But when I upload my action to the Drafts action repository it might be scaring off others that a second action is necessary.

Up to you want makes sense. I don’t know enough about how this would be used, and how the target draft is determined. If it’s a static draft, where you are always appending to the same one, it would probably be safest to add a little code at the begin to ensure that the right draft is loaded in the editor.

No, the normal use of this action is one per draft. Otherwise it would not make sense at all to use a static footnote anchor name. One excerpt, one reference. Maybe sometimes plus a commentary by me, which of course does not have or need another reference.

If that’s the case, then I would ensure you create a new draft at the beginning of the script, and load it in the editor, like:

editor.load(new Draft())

You don’t need to worry about any existing selections or anything that way either.

Thanks again, but I’d like the action to be a bit more flexible.

While one reference per draft and therefore one use of the action per draft is set, the action should allow that a draft is loaded when the action gets launched. It should allow it, although it would be the exception in my workflow. But like I said, I’d like to share it with others.

So is there a condition to find out if Drafts runs already / a draft is loaded? And I mean a draft, not a specific one.

There should always be a draft. If you are looking to determine if it is a new draft, maybe you just need to check if the draft has content or a tag, or perhaps when it was created relative to now?

Not if the action is started from the lockscreen. That was my question: Is a stub action like the one above @agiletortoise necessary or can the action itself find out, if Drafts is running/a draft is in Draft’s editor.

I thought “the draft in context” meant that draft was implicitly loaded into the editor. If that is not the case, does that then mean the editor object in Drafts’ JavaScript would be undefined or null in such a scenario … In which case that could be the identifier.

There is always a draft object. And there is always an editor object. There is no guarantee that the draft in the draft global variable is the same as the draft loaded in the editor.

@suavito’s action, as written, is using editor functions to manipulate the text in the editor, and relies on the “after success” options on the action to assign tags.

By using the stub action I suggested to queue to action to run on a specific draft, you are ensuring the “after success” options are applied to that draft.

If you do not want the stub action, and you want the action to work from the widget, you can just not rely on the after success options and explicit change values on the draft that is loaded in the editor.

Something like:

editor.draft.addTag("my-tag")
editor.draft.update()

Thanks Greg.

I think that matches with my original understanding :+1:t2:

Alright then, stub action it is.

But I’m doing something wrong.

This is my stub code to get a new draft when launching from a widget but not from within Drafts:

editor.load(new Draft())
let a = Action.find("Bookends Single Reference")
app.queueAction(a, draft)

The tagging (not by code but by the After Success setting) does not work as expected: It does not tag the current draft but the one before in the drafts list (if existing).

draft refers to the draft currently in context for the action running, so you are queuing the action to run on the same draft the stub action is running on. You would want something like:

let d = new Draft()
d.update() // save it so you it will still exist
editor.load(d)
let a = Action.find("Bookends Single Reference")
app.queueAction(a, d)

Or, if you want it to just use the one that is already in the editor:

let d = editor.draft
let a = Action.find("Bookends Single Reference")
app.queueAction(a, d)

Thank you for your extremely fast reply, now it works. I use the first code block for a new draft.

I had played around with the earlier code snippets and with what I read in the script reference but I missed the .update part.

One thing: While testing before getting your code I set both the stub action and the actual action to assign a tag. The Bookends Single Reference now sets the tag to the right draft, but the stub action still tags the draft before the loaded one. I will remove this as I don’t need two tags, but just out of curiosity—why does that happen?

The stub action an action, like any other. If it has an after success option configured, it will apply those changes to the draft that it is running against…which, when running from the action list, is the one loaded in the editor.

Okay.

After I had put my stub action into the newly created Widget Launchers action group I had to move it up in the action list because only the first three action groups were available when setting the launch screen widget. Is that intended or a limitation by the OS?

You can search in the widget selection list to get any item.