feat: unify mobile queue start and continue action (Closes #1450)
CI / lint (pull_request) Successful in 3m55s
CI / build-release (pull_request) Successful in 7s
CI / browser-journey (pull_request) Successful in 7m18s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-27 01:12:38 +00:00
1 parent c2b7ce67d8
commit 9381ff9d84
7 files changed
+112 -17

No files matched your search

-1
View File
@@ -1533,7 +1533,6 @@ textarea { resize: vertical; min-height: 120px; }
.mobile-start-day { display:grid; gap:12px; max-width:100%; overflow-wrap:anywhere; margin-top:12px; padding:14px; border:1px solid #31577f; border-radius:14px; background:linear-gradient(135deg,#173b64,#102641); }
.mobile-start-day h3, .mobile-start-day p { margin:0; }
.mobile-start-day p + p { margin-top:4px; }
.mobile-start-day-action { width:100%; min-height:48px; text-align:center; }
.mobile-start-day-finish { min-height:44px; width:100%; background:transparent; }
.mobile-queue-list { display:grid; gap:8px; margin-top:12px; }
.mobile-queue-list button { display:flex; align-items:center; justify-content:space-between; gap:12px; min-height:56px; width:100%; padding:10px 14px; text-align:left; }
+12 -5
View File
@@ -179,6 +179,11 @@
firstAction: name => qs('#my-work-list .my-work-card-main, #my-work-list .draft-resume, #my-work-list .draft-continue, #my-work-list .draft-edit'),
announce: announceWork,
getCounts: () => queueCounts,
getPreparation: () => {
const briefing = mobileStartDay.briefing();
return {...briefing, active:mobileStartDay.state().active};
},
openPreparation: () => mobileStartDay.startNext(),
openFindWork: () => qs('#find-work').click(),
rows: Object.fromEntries(
Array.from(document.querySelectorAll('[data-mobile-queue]')).map(button => [button.dataset.mobileQueue, button])
@@ -190,7 +195,6 @@
activeSection: qs('#mobile-queue-active-list').parentElement,
});
renderMobileQueuePresentation = () => mobileQueueLauncher.renderPresentation();
renderMobileQueuePresentation();
qs('#mobile-queue-next-action').addEventListener('click', () => mobileQueueLauncher.continueWork());
function openMobileStartDay() {
followingQueue.load().catch(() => {});
@@ -199,7 +203,7 @@
qs('#mobile-queue-heading').textContent = state.active ? 'Resume Prepare Today' : 'Prepare Today';
const sheet = qs('#mobile-queue-sheet');
if (!sheet.open) qs('#mobile-queue-sheet').showModal();
qs('#mobile-start-day-action').focus();
qs('#mobile-queue-next-action').focus();
}
const mobileFirstTask = createMobileFirstTask({
getLogin: () => confirmedOwnerLogin,
@@ -238,17 +242,20 @@
qs('#mobile-queue-heading').textContent = 'Prepare Today · ' + current.label;
const sheet = qs('#mobile-queue-sheet');
if (!sheet.open) sheet.showModal();
qs('#mobile-start-day-action').focus();
qs('#mobile-queue-next-action').focus();
},
elements: {
summary: qs('#mobile-start-day-summary'),
phases: qs('#mobile-start-day-phases'),
action: qs('#mobile-start-day-action'),
finish: qs('#finish-mobile-start-day'),
},
});
mobileStartDay.start();
qs('#finish-mobile-start-day').addEventListener('click', () => mobileStartDay.finish());
renderMobileQueuePresentation();
qs('#finish-mobile-start-day').addEventListener('click', () => {
mobileStartDay.finish();
renderMobileQueuePresentation();
});
function showMobileQueueCompletion(completedName, cleared = true, phase = '') {
if (cleared && phase && mobileStartDay.completePhase(phase)) return;
mobileStartDay.render();
+1 -2
View File
@@ -2177,11 +2177,10 @@
<p id="mobile-start-day-summary" class="small" aria-live="polite">Reviewing urgent queues…</p>
<p id="mobile-start-day-phases" class="small muted">Checking Agenda, Attention, Updates, Filed, and Following</p>
</div>
<button class="mobile-start-day-action" id="mobile-start-day-action" type="button">Prepare Today</button>
<button class="mobile-start-day-finish" id="finish-mobile-start-day" type="button" hidden>Finish for now</button>
</section>
<section class="mobile-queue-next" aria-labelledby="mobile-queue-next-heading">
<p class="small muted" id="mobile-queue-next-heading">Next up</p>
<p class="small muted" id="mobile-queue-next-heading">Start / Continue</p>
<button id="mobile-queue-next-action" type="button">Find Work</button>
</section>
<section class="mobile-queue-group" aria-labelledby="mobile-queue-active-heading" hidden>
+18 -4
View File
@@ -34,6 +34,15 @@
return {name, count, label: label + ' (' + count + ')'};
}
function adaptiveRecommendation() {
const preparation = options.getPreparation ? options.getPreparation() : null;
if (preparation && (preparation.active || Number(preparation.total) > 0)) {
const prefix = preparation.active ? 'Resume preparation · ' : 'Start day · ';
return {name: 'prepare', count: Math.max(0, Number(preparation.total) || 0), label: prefix + preparation.label};
}
return recommend();
}
function presentation() {
const counts = options.getCounts ? options.getCounts() : {};
const active = activeQueueNames
@@ -45,7 +54,7 @@
}
});
return {
nextUp: recommend(),
nextUp: adaptiveRecommendation(),
active,
planning: ['today', 'tomorrow', 'week'],
all: allQueues.slice(),
@@ -60,7 +69,8 @@
if (options.nextAction) {
options.nextAction.textContent = view.nextUp.label;
options.nextAction.dataset.queue = view.nextUp.name;
options.nextAction.setAttribute('aria-label', 'Next up: ' + view.nextUp.label);
const prefix = view.nextUp.name === 'prepare' ? 'Start or continue: ' : 'Next up: ';
options.nextAction.setAttribute('aria-label', prefix + view.nextUp.label);
}
active.forEach(item => {
const row = options.rows?.[item.name];
@@ -103,7 +113,11 @@
}
function continueWork() {
const next = recommend();
const next = adaptiveRecommendation();
if (next.name === 'prepare') {
options.openPreparation();
return 'prepare';
}
if (next.name === 'find') {
options.openFindWork();
return 'find';
@@ -111,5 +125,5 @@
return open(next.name);
}
return { open, recommend, presentation, renderPresentation, continueWork };
return { open, recommend, adaptiveRecommendation, presentation, renderPresentation, continueWork };
});
+4 -2
View File
@@ -185,14 +185,16 @@
options.elements.phases.textContent = current.phases.length ?
current.phases.map(phase => phase.label + ' ' + phase.count).join(' · ') :
'All urgent queues reviewed';
options.elements.action.textContent = checkpoint() ? 'Resume preparation · ' + current.label : current.label;
if (options.elements.action) {
options.elements.action.textContent = checkpoint() ? 'Resume preparation · ' + current.label : current.label;
}
if (options.elements.finish) options.elements.finish.hidden = !checkpoint();
return current;
}
function start() {
render();
if (options.elements) options.elements.action.addEventListener('click', startNext);
if (options.elements?.action) options.elements.action.addEventListener('click', startNext);
}
return {briefing, completePhase, finish, reconcile, render, start, startNext, state};