Different behavior on Mac vs. iPhone/iPad

I’m using the action “Process Journal Items” from the Quick Journaling action group.

I made some modifications in order for it to support TickTick. When run from the Mac, it processes all the lines that are considered actions and uses the callback to add them to TickTick.

However, on the IOS devices it only processes the first one?

I suspect the issue is with my sendToTicktick function, but I’m confused why it would work on the Mac and not the IOS devices.

const lines = draft.content.split("\n");
const dayoneURL = "dayone2://post"
const fantasticalURL = "fantastical2://x-callback-url/parse";
const goodtaskURL = "goodtask3://x-callback-url/add";
const omnifocusURL = "omnifocus://x-callback-url/add";
const thingsURL = "things:///add";
const todoistURL = "todoist://addtask";

// EZ - These constants are added for my purposes
const tags = draft.tags;
const title = draft.displayTitle;
const uuid = draft.uuid;
const ticktickURL = "ticktick://x-callback-url/v1/add_task?";

var dayOneLines = [];

// Actions for sending journal entries to various apps

function collectForDayOne(entry) {
    dayOneLines.push(entry);
}

function sendToFantastical(entry) {
    var cb = CallbackURL.create();
    cb.baseURL = fantasticalURL;
    cb.addParameter("sentence", entry);
    cb.open();
}

function sendToGoodTask(entry) {
    var cb = CallbackURL.create();
    cb.baseURL = goodtaskURL;
    cb.addParameter("title", entry);
    cb.open();
}

function sendToOmniFocus(entry) {
    var cb = CallbackURL.create();
    cb.baseURL = omnifocusURL;
    cb.addParameter("name", entry);
    cb.open();
}

function sendToReminders(entry) {
    var list = ReminderList.findOrCreate("Journal");
    var reminder = list.createReminder();
    reminder.title = entry;
    reminder.update();
}

function sendToThings(entry) {
    var cb = CallbackURL.create();
    cb.baseURL = thingsURL;
    cb.addParameter("title", entry);
    cb.open();
}

function sendToTodoist(entry) {
    var cb = CallbackURL.create();
    cb.baseURL = todoistURL;
    cb.addParameter("content", entry);
    cb.open();
}

// EZ - This function is meant to take only task list items and send them to TickTick via a callback URL
function sendToTicktick(entry) {
	var cb = CallbackURL.create();

	// EZ - Search for "- [x]" and replace it with a "X". I don't see that you can actually send TickTick a completed item.  Hopefully that will change or I find a way.
	if (entry.startsWith("[x]"||"[x] ") ) {
		cb.addParameter("title", entry.replace(/\[x\]\s+/, 'X - ') );
	}

	// EZ - Search for "- [ ]" and clear it out. We don't need a checkbox in TickTick
	else if (entry.startsWith("[ ]"||"[ ] ") ) {
		cb.addParameter("title", entry.replace(/\[ \]\s+/, '') );
	}

    cb.baseURL = ticktickURL;
    cb.addParameter("tags", tags);
    cb.addParameter("content", "Generated from: " + "[" + title + "](drafts://x-callback-url/open?uuid=" + uuid + ")");
    cb.waitForResponse = false;
    cb.open();
}

// Resolve actions defined in the settings file to the actual
// functions to call.

var actionMap = {
    "Day One": collectForDayOne,
    "Fantastical": sendToFantastical,
    "GoodTask": sendToGoodTask,
    "OmniFocus": sendToOmniFocus,
    "Reminders": sendToReminders,
    "Things": sendToThings,
    "Todoist": sendToTodoist,
    "TickTick": sendToTicktick,
}

var actions = {}
for (var key in lineProcessors) {
    var actionName = lineProcessors[key];
    actions[key] = actionMap[actionName];
}

// Process all the lines.

for (var line of lines) {
    line = line.trim();
    if (line.length == 0) { continue; }

    first = line[0];
    rest = line.substr(1).trim();
    if (rest.length == 0) { continue; }

    action = actions[first];
    if (action === undefined) { continue; }

    action(rest);
}

// Some actions are processed in a batch after all their entries
// are collected. This is where that happens.

if (dayOneLines.length) {
    var body = dayOneLines.join("\n\n");
    var cb = CallbackURL.create();
    cb.baseURL = dayoneURL;
    cb.addParameter("entry", body);
    cb.waitForResponse = false;
    cb.open();
}

Try setting waitForResponse to true. If you are processing a series of URLs, you need to wait for each one to finish before processing the next or you can create race conditions, or it will just fail. This is less of a problem on Mac, but can also be unpredictable depending on the behavior of the target app.

Thanks, when I turn that on it takes a great deal of time to process each line. This happens on both the IOS devices and the Mac.

That is the nature of URL schemes. They were not designed to be used in this way.

I really appreciate the response but I guess I don’t understand why it would function for the Mac and not the IOS devices.

With that turned on, they all exhibit the same behavior. Works on the Mac but not the IOS devices. Although, I admit it works REALLY slow on the Mac.

They all use the same network, I even verified they are using the same DNS servers. My network game is tight :wink:

Callback URLs do not use the network. They are not http URLs, they are custom URLs registered to open applications. The reason they exist is to allow deep links to specific content in an application, not to execute commands.

Using them as commands with callbacks was an innovation created because there was no other way to do such things on iOS, not because they were a good solution. It will be slow because it requires the other app to launch, load up, process the URL, and open a URL to return to the originating app, which is a lot of overhead.

If any of the services you are trying to integrate with provide direct web-based APIs, or Shortcuts integration, those routes will be faster and better.

(Note that none of this is problematic in the common use cases of opening one URL command, but if you start to try to stack a bunch of them in one action, it’s not great.)

1 Like

Thanks for taking the time to explain that to me. We learn something new every day.

I guess, in this case, I have an action I can only run from my Mac.

App boundary crossing is bound to be expensive / slow. But each crossing pair can be written off over more than one item if you can batch them up.

Does TickTick allow you to send a batch over from Drafts? That would almost certainly be quicker.