fix: recover Today blocker planning after reload (Closes #1068)
This commit is contained in:
1 parent
1bd87fc33e
commit
3c8e2e2720
5 files changed
+174
-5
No files matched your search
@@ -291,6 +291,7 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.today-progress-blocker { display:grid; gap:8px; margin-top:14px; padding:12px; border:1px solid #875f2a; border-radius:12px; background:#21180d; }
|
||||
.today-progress-blocker input, .today-progress-blocker button { box-sizing:border-box; width:100%; min-height:44px; }
|
||||
.today-progress-blocker p { margin:0; }
|
||||
.today-progress-blocker .today-progress-blocker-recovery { padding:8px; border-radius:8px; background:#3a270d; color:#fde68a; font-weight:700; }
|
||||
.today-progress-actions { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:12px; }
|
||||
.today-progress-actions button { width:100%; }
|
||||
.today-progress-panel .voice-conversation { margin-top:10px; }
|
||||
|
||||
@@ -1603,6 +1603,7 @@
|
||||
<p class="small muted">Save privately on this device, or post to the exact Gitea item. Today keeps running either way.</p>
|
||||
<section class="today-progress-blocker" aria-labelledby="today-progress-blocker-title">
|
||||
<strong id="today-progress-blocker-title">Blocked?</strong>
|
||||
<p id="today-progress-blocker-recovery" class="today-progress-blocker-recovery small" role="status" hidden></p>
|
||||
<label for="today-blocker-return-at">Return this item to Later at</label>
|
||||
<input id="today-blocker-return-at" type="datetime-local" />
|
||||
<button id="post-today-blocker" type="button">Post blocker & move on</button>
|
||||
|
||||
@@ -154,7 +154,16 @@ maxLength = 2000, maxItems = 20 }) {
|
||||
write(drafts);
|
||||
}
|
||||
} else {
|
||||
until = record.blocker_until;
|
||||
const replacementUntil = String(until || '').trim();
|
||||
until = replacementUntil || record.blocker_until;
|
||||
if (replacementUntil && replacementUntil !== record.blocker_until) {
|
||||
const drafts = read();
|
||||
if (drafts[target.identity]?.operation_id === record.operation_id) {
|
||||
drafts[target.identity] = { ...drafts[target.identity], blocker_until:replacementUntil };
|
||||
write(drafts);
|
||||
record = drafts[target.identity];
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (typeof completeEvidence === 'function') await completeEvidence();
|
||||
@@ -176,7 +185,13 @@ maxLength = 2000, maxItems = 20 }) {
|
||||
return admission;
|
||||
}
|
||||
|
||||
return { load, save, discard:identity => save(identity, ''), post, postBlocker };
|
||||
function blockerRecovery(identity) {
|
||||
if (!validIdentity(identity)) return null;
|
||||
const record = read()[identity];
|
||||
return record?.blocker_pending === true ? { pending:true, until:String(record.blocker_until || '') } : null;
|
||||
}
|
||||
|
||||
return { load, save, discard:identity => save(identity, ''), post, postBlocker, blockerRecovery };
|
||||
}
|
||||
|
||||
function createTodayProgressActivity({ fetchJson, createPager, getActions, onActions, surfaceStatus, paint = () => {}, setStatus = () => {} }) {
|
||||
@@ -299,8 +314,31 @@ function createTodayProgressView({ progress, currentTarget, qs, photos, voice, a
|
||||
const body = qs('#today-progress-body');
|
||||
const status = qs('#today-progress-status');
|
||||
const launcher = qs('[data-mobile-today-update]');
|
||||
const blockerButton = qs('#post-today-blocker');
|
||||
const blockerReturn = qs('#today-blocker-return-at');
|
||||
const blockerRecovery = qs('#today-progress-blocker-recovery');
|
||||
const saveButton = qs('#save-today-progress');
|
||||
const postButton = qs('#post-today-progress');
|
||||
let openedTarget = null;
|
||||
|
||||
const localDateTime = value => {
|
||||
const date = new Date(value || '');
|
||||
if (!Number.isFinite(date.getTime())) return '';
|
||||
return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, 16);
|
||||
};
|
||||
const showBlockerRecovery = recovery => {
|
||||
const pending = recovery?.pending === true;
|
||||
body.disabled = pending;
|
||||
saveButton.disabled = pending;
|
||||
postButton.disabled = pending;
|
||||
if (blockerButton) blockerButton.textContent = pending ? 'Finish moving on' : 'Post blocker & move on';
|
||||
if (blockerReturn) blockerReturn.value = pending ? localDateTime(recovery.until) : '';
|
||||
if (blockerRecovery) {
|
||||
blockerRecovery.hidden = !pending;
|
||||
blockerRecovery.textContent = pending ? 'Blocker queued—finish moving on. The posted update cannot be changed.' : '';
|
||||
}
|
||||
};
|
||||
|
||||
const update = () => {
|
||||
const target = currentTarget();
|
||||
launcher.hidden = !target;
|
||||
@@ -334,6 +372,7 @@ function createTodayProgressView({ progress, currentTarget, qs, photos, voice, a
|
||||
openedTarget = target;
|
||||
qs('#today-progress-target').textContent = target.label + (target.title ? ' · ' + target.title : '');
|
||||
body.value = progress.load(target.identity);
|
||||
showBlockerRecovery(progress.blockerRecovery?.(target.identity));
|
||||
status.textContent = 'Restoring saved photo evidence…';
|
||||
sheet.showModal();
|
||||
try {
|
||||
@@ -357,14 +396,13 @@ function createTodayProgressView({ progress, currentTarget, qs, photos, voice, a
|
||||
announce('Progress update saved privately to this Today item.');
|
||||
close();
|
||||
});
|
||||
const blockerButton = qs('#post-today-blocker');
|
||||
blockerButton?.addEventListener('click', async () => {
|
||||
const target = currentTarget();
|
||||
if (!target || target.identity !== openedTarget?.identity) {
|
||||
status.textContent = 'The active Today item changed. Close and open its update again.';
|
||||
return;
|
||||
}
|
||||
const returnInput = qs('#today-blocker-return-at');
|
||||
const returnInput = blockerReturn;
|
||||
const wakeAt = new Date(returnInput?.value || '');
|
||||
if (!body.value.trim()) {
|
||||
status.textContent = 'Describe what is blocking this Today item.';
|
||||
|
||||
Reference in new issue
Block a user