feat: start deferred work directly (#457)
CI / lint (pull_request) Successful in 52s
CI / build-release (pull_request) Successful in 6s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-10 06:00:35 +00:00
1 parent f8c5c2b058
commit a610708e36
7 files changed
+316 -4

No files matched your search

+25 -2
View File
@@ -915,6 +915,19 @@
refresh: refreshMyWorkView,
warm: warmTodayOffline,
});
const laterAndStart = createLaterAndStart({
todayWork,
todaySync,
laterWork,
refresh: refreshMyWorkView,
warm: warmTodayOffline,
start: item => {
qs('[data-work-filter="today"]').click();
qs('#my-work-action-status').textContent = 'Checking Today readiness…';
return todayReadiness.run('start', workSession.items(), item);
},
announce: message => { qs('#my-work-action-status').textContent = message; },
});
const selectedSessionItem = kind => ({
issue: selectedIssue,
@@ -1688,14 +1701,15 @@
'<a class="read-update" href="' + escAttr(createWorkRoute.serialize({ kind:'update', notification_id:item.notification_id })) + '" data-update-index="' + index + '">Read update</a>' : '';
const planningDisabled = planningOwnerLogin ? '' : ' disabled data-planning-disabled';
const laterActions = selectedWorkFilter === 'later' ?
'<div class="later-actions"><button type="button" data-later-restore data-work-index="' + index + '">Bring back now</button></div>' :
'<div class="later-actions" aria-label="Deferred work actions"><button type="button" data-later-start data-work-index="' + index + '"' + planningDisabled + '>Start now</button><button type="button" data-later-restore data-work-index="' + index + '">Bring back now</button></div>' :
'<div class="later-actions" aria-label="Defer this work"><button type="button" data-later-preset="today" data-work-index="' + index + '"' + planningDisabled + '>Later today</button><button type="button" data-later-preset="tomorrow" data-work-index="' + index + '"' + planningDisabled + '>Tomorrow</button><button type="button" data-later-custom data-work-index="' + index + '"' + planningDisabled + '>Choose date &amp; time</button></div>';
const alreadyToday = todayWork.contains(item);
const todayPosition = todayWork.position(item);
const todayActions = selectedWorkFilter === 'today' ?
'<div class="today-actions" aria-label="Reorder Today"><button type="button" data-today-move="up" data-work-index="' + index + '"' + (todayPosition.can_up ? '' : ' disabled') + '>Move up</button><button type="button" data-today-move="down" data-work-index="' + index + '"' + (todayPosition.can_down ? '' : ' disabled') + '>Move down</button><button type="button" data-today-remove data-work-index="' + index + '">Remove from Today</button></div>' :
'<div class="today-actions"><button type="button" data-today-add data-work-index="' + index + '"' + (alreadyToday ? ' disabled' : planningDisabled) + '>' + (alreadyToday ? 'Added to Today' : 'Add to Today') + '</button></div>';
const planningActions = '<details class="card-planning" data-card-planning><summary aria-expanded="false">Plan or defer</summary><div class="card-planning-actions">' + todayActions + laterActions + '</div></details>';
const planningActions = selectedWorkFilter === 'later' ? laterActions :
'<details class="card-planning" data-card-planning><summary aria-expanded="false">Plan or defer</summary><div class="card-planning-actions">' + todayActions + laterActions + '</div></details>';
if (item.is_review) {
return '<article class="my-work-card"><a class="my-work-card-main review-trigger" href="' + escAttr(routeHref) + '" data-review-index="' + index + '">' + contents + '</a>' + readUpdate + markRead + planningActions + '</article>';
}
@@ -1777,6 +1791,15 @@
refreshMyWorkView();
});
});
document.querySelectorAll('[data-later-start]').forEach(button => {
button.addEventListener('click', async () => {
const item = lastMyWork[Number(button.dataset.workIndex)];
if (!item) return;
button.disabled = true;
await laterAndStart.start(item);
if (button.isConnected) button.disabled = false;
});
});
document.querySelectorAll('[data-today-add]').forEach(button => {
button.addEventListener('click', () => {
if (!planningOwnerLogin) {
+1
View File
@@ -652,6 +652,7 @@
<script src="static/update-ownership.js"></script>
<script src="static/later-work.js"></script>
<script src="static/later-sync.js"></script>
<script src="static/later-and-start.js"></script>
<script src="static/detail-defer.js"></script>
<script src="static/later-picker.js"></script>
<script src="static/pick-work.js"></script>
+51
View File
@@ -0,0 +1,51 @@
function createLaterAndStart({ todayWork, todaySync, laterWork, refresh, warm, start, announce }) {
const pending = new Map();
async function run(item, identity) {
const added = todayWork.add(item);
if (added === 'full') {
announce('Today is limited to 5 items. Remove one, then try Start now again.');
return 'full';
}
if (added !== 'added' && added !== 'exists') {
announce('Could not save Today on this device. The item remains in Later; try again.');
return added;
}
if (added === 'added' && !todaySync.enqueue('add', identity)) {
todayWork.remove(item);
announce('Today sync is unavailable. The item remains in Later; try again.');
return 'sync-unavailable';
}
if (!laterWork.restore(item)) {
if (added === 'added') {
todayWork.remove(item);
todaySync.enqueue('remove', identity);
todaySync.flush();
}
announce('Could not remove this item from Later. Nothing was started; try again.');
return 'later-unavailable';
}
refresh();
if (added === 'added') todaySync.flush();
warm();
const outcome = await start(item);
if (outcome === 'gated') {
announce('Moved to Today. Choose how to handle its blocker before starting.');
return 'gated';
}
announce(added === 'exists' ? 'Opened the existing Today item.' : 'Moved to Today and opened.');
return 'started';
}
function startDeferred(item) {
const identity = todayWork.identity(item);
if (pending.has(identity)) return pending.get(identity);
const operation = run(item, identity).finally(() => pending.delete(identity));
pending.set(identity, operation);
return operation;
}
return { start: startDeferred };
}
if (typeof module !== 'undefined' && module.exports) module.exports = createLaterAndStart;
+1
View File
@@ -37,6 +37,7 @@ const SHELL = [
BASE + 'static/update-ownership.js',
BASE + 'static/later-work.js',
BASE + 'static/later-sync.js',
BASE + 'static/later-and-start.js',
BASE + 'static/detail-defer.js',
BASE + 'static/later-picker.js',
BASE + 'static/pick-work.js',