Event `task:stateChange` isn't fired for "external" tasks
On a page make some tasks:
- [ ] task 1 #shopping
- [ ] task 2 #shopping
- [ ] task 3 #shopping
On a different page, fetch those tasks:
External tasks below:
`` `template
{{#each {task where tags = "shopping"}}}
- [{{state}}] [[{{ref}}]] {{name}}
{{/each}}
`` `
When completing the task on the different page, a related "task:stateChange" event is not fired.
But then even is triggered when you actually complete those tasks on that other page, right? What is your use case for having the event also be triggered on pages where these tasks are merely queried?
But then even is triggered when you actually complete those tasks on that other page, right? What is your use case for having the event also be triggered on pages where these tasks are merely queried?
But they aren't merely queried. The tasks can be completed from within the query.
The event doesn't seem to fire at all when checking off a task from within a query.
I realize it may be difficult to do what I want to do, but on my daily note page I have a query showing all tasks due that day, and I want to be able to mark it complete and have the event append ✅ {{today}} to the source task.
Ah, when you toggle the box in the query. Ok right. I think I can make that happen.
Possibly unrelated, but the remote toggle example on https://silverbullet.md/Plugs/Tasks (under "Rendering") doesn't work for me either.
@argus-core right, yeah that's a bit misleading there. It doesn't work because silverbullet.md is running in read-only mode. I should remove that example probably.
Hi, as an additional input, I find that task:stateChange also doesn't fire if the state is non defaults. I have following script which works to update the task when completed and blank, but not when it is a new state. I think it is easily reproducible on other instance so long you define an addition state change.
My script snippet is as following ( not complete, just showing the approach) :
const appendDate = async (from, emoji) => {
const now = Temporal.Now.plainDateISO().toString();
await syscall("editor.dispatch", {
changes: { from, insert: ` ${emoji} ${now}` },
});
}
const checkbox = /^\[([^\]]+)]\s+/
const stateChanges = {
// Completed
"x": async ({ to, text }) => {
await appendDate(to, "✅");
},
// Cancelled
"-": async ({ to, text }) => {
await appendDate(to, "🛑");
},
" ": async ({ from, text, to }) => {
const finalDatesRegex = /\s*(✅|❌)\s*\d{4}-\d{2}-\d{2}/g;
const insert = text.replace(finalDatesRegex, "").trim();
if (insert === text) return;
const [current] = checkbox.exec(text) || [""];
const offset = current.length;
await syscall("editor.dispatch", {
changes: {
from: from + offset,
to,
insert: insert.slice(offset),
},
});
},
}
// Add or remove finalization date when changing a task
silverbullet.registerEventListener(
{ name: "task:stateChange" },
({ data }) => stateChanges[data.newState]?.(data)
)
Ok, so I looked into this and there's a bit of a design problem. Currently task:stateChange event assumes that the task change happened on the current page (open in the editor) so it passes in a "from" and "to" assuming the same page, which you can use to dispatch CodeMirror changes to. This would not work when triggered from a query, which may (very likely) update a task on some other page not open in the editor, and so wouldn't be able to change it with dispatch.
Although not great, what I can do is add an additional event, e.g. task:stateChangeExternal or similar that specifies the page, the from (or pos), as well as the newState — then your code would have to figure out what to do with that. If you want to make changes you'd have to fetch the page content, manipulate it and write it back which is a bit of work, but can be done. Would that help?
Of course an additional event would help. I just wonder whether it is better to have a meta event of stateChange combining both events ( don't know if this is possible) and move the current stateChange to something like stateChangeInternal so we have better intuition with the name? Otherwise a detail documentation section should be added explaining the difference and nuance, which I could help with.