feat: watch assigned work from mobile detail (Closes #1309)
This commit is contained in:
1 parent
4e3f67df3d
commit
35a88bb398
7 files changed
+296
-3
No files matched your search
@@ -955,6 +955,8 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.filed-claim-actions button { min-width:0; min-height:44px; }
|
||||
.issue-sheet-actions { position:sticky; bottom:0; z-index:3; display:grid; gap:8px; margin-top:14px; padding:10px 4px; padding-bottom:calc(10px + env(safe-area-inset-bottom)); background:rgba(11,21,38,.98); border-top:1px solid #2a496e; }
|
||||
.issue-sheet-actions button, .issue-sheet-actions a { min-height:44px; display:flex; align-items:center; justify-content:center; }
|
||||
.issue-sheet-actions #watch-issue-detail, .pull-sheet-actions #watch-pull-detail { min-width:0; min-height:44px; }
|
||||
.detail-watch-status:not(:empty) { margin-top:8px; overflow-wrap:anywhere; }
|
||||
.issue-sheet-actions a { border:1px solid #60a5fa; border-radius:10px; font-weight:700; }
|
||||
.issue-handoff, .pull-ownership { margin-top:14px; padding:12px; border:1px solid #2a496e; border-radius:12px; }
|
||||
.issue-handoff > div, .pull-ownership > div { display:grid; gap:8px; margin-top:10px; }
|
||||
|
||||
@@ -122,6 +122,18 @@
|
||||
},
|
||||
onReviewComplete:() => mobileStartDay.completePhase('following'),
|
||||
});
|
||||
function bindDetailWatch(kind, button, status) {
|
||||
const feature=createDetailWatch({fetchJson:fetchReviewJson,refreshFollowing:()=>followingQueue.load(),onState:(state,watching,error)=>{
|
||||
button.disabled=['loading','watching','unwatching'].includes(state);
|
||||
button.textContent=watching?'Stop watching':'Watch '+(kind==='pull'?'pull request':'issue');
|
||||
status.textContent=state==='ready'?(watching?'Watching · available in Following.':''):
|
||||
searchPreviewWatchStatus({status:state==='error'?'watch-error':state,error,detail:{kind}});
|
||||
}});
|
||||
button.addEventListener('click',()=>feature.toggle().catch(()=>{}));
|
||||
return feature;
|
||||
}
|
||||
const issueDetailWatch = bindDetailWatch('issue',qs('#watch-issue-detail'),qs('#issue-watch-status'));
|
||||
const pullDetailWatch = bindDetailWatch('pull',qs('#watch-pull-detail'),qs('#pull-watch-status'));
|
||||
const mobileDeliveryRecovery = createMobileDeliveryRecovery({
|
||||
getItems: () => draftInbox.partition(lastDrafts).deliveries,
|
||||
getIndex: item => lastDrafts.indexOf(item),
|
||||
@@ -4275,6 +4287,15 @@
|
||||
issueConversation = null;
|
||||
issueTrigger = trigger;
|
||||
qs('#issue-sheet').classList.add('open');
|
||||
if (offlineDetail) {
|
||||
qs('#watch-issue-detail').hidden = true;
|
||||
qs('#issue-watch-status').textContent = 'Reconnect to change watch status.';
|
||||
} else {
|
||||
qs('#watch-issue-detail').hidden = item.state !== 'open';
|
||||
void issueDetailWatch.open(item).catch(error => {
|
||||
if (selectedIssue === item) qs('#issue-watch-status').textContent = error.message + ' Retry.';
|
||||
});
|
||||
}
|
||||
qs('#issue-sheet-key').textContent = item.key || '';
|
||||
qs('#issue-sheet-title').textContent = item.title || 'Assigned issue';
|
||||
qs('#issue-sheet-status').textContent = 'Loading issue…';
|
||||
@@ -4597,6 +4618,15 @@
|
||||
pullConversation = null;
|
||||
pullReviewState = null;
|
||||
qs('#pull-sheet').classList.add('open');
|
||||
if (offlineDetail) {
|
||||
qs('#watch-pull-detail').hidden = true;
|
||||
qs('#pull-watch-status').textContent = 'Reconnect to change watch status.';
|
||||
} else {
|
||||
qs('#watch-pull-detail').hidden = item.state !== 'open';
|
||||
void pullDetailWatch.open(item).catch(error => {
|
||||
if (selectedPull === item) qs('#pull-watch-status').textContent = error.message + ' Retry.';
|
||||
});
|
||||
}
|
||||
qs('#pull-sheet-key').textContent = item.key || '';
|
||||
qs('#pull-sheet-title').textContent = item.title || 'Assigned pull request';
|
||||
qs('#pull-sheet-status').textContent = 'Loading pull request…';
|
||||
|
||||
@@ -1181,11 +1181,13 @@
|
||||
</section>
|
||||
<div class="issue-sheet-actions">
|
||||
<button class="share-work-route" type="button">Share</button>
|
||||
<button id="watch-issue-detail" type="button">Watch issue</button>
|
||||
<button id="release-issue" type="button">Release assignment</button>
|
||||
<button id="close-issue" type="button">Close issue</button>
|
||||
<a id="open-issue-gitea" href="#" target="_blank" rel="noopener noreferrer">Open in Gitea</a>
|
||||
<details class="detail-defer"><summary>Defer</summary><div class="detail-defer-options"><button type="button" data-detail-defer-preset="today" disabled data-planning-disabled>Later today</button><button type="button" data-detail-defer-preset="tomorrow" disabled data-planning-disabled>Tomorrow</button><button type="button" data-detail-defer-custom disabled data-planning-disabled>Choose date & time</button><button type="button" data-detail-defer-cancel>Cancel</button></div></details>
|
||||
</div>
|
||||
<div id="issue-watch-status" class="detail-watch-status small" aria-live="polite"></div>
|
||||
<nav class="work-session-nav" aria-label="Work session" hidden>
|
||||
<span class="small" aria-live="polite" data-work-session-progress></span>
|
||||
<button type="button" data-work-session-previous>Previous</button>
|
||||
@@ -1719,10 +1721,12 @@
|
||||
</details>
|
||||
<div class="pull-sheet-actions">
|
||||
<button class="share-work-route" type="button">Share</button>
|
||||
<button id="watch-pull-detail" type="button">Watch pull request</button>
|
||||
<button id="release-pull" type="button">Release assignment</button>
|
||||
<a id="open-pull-gitea" href="#" target="_blank" rel="noopener noreferrer">Open in Gitea</a>
|
||||
<details class="detail-defer"><summary>Defer</summary><div class="detail-defer-options"><button type="button" data-detail-defer-preset="today" disabled data-planning-disabled>Later today</button><button type="button" data-detail-defer-preset="tomorrow" disabled data-planning-disabled>Tomorrow</button><button type="button" data-detail-defer-custom disabled data-planning-disabled>Choose date & time</button><button type="button" data-detail-defer-cancel>Cancel</button></div></details>
|
||||
</div>
|
||||
<div id="pull-watch-status" class="detail-watch-status small" aria-live="polite"></div>
|
||||
<nav class="work-session-nav" aria-label="Work session" hidden>
|
||||
<span class="small" aria-live="polite" data-work-session-progress></span>
|
||||
<button type="button" data-work-session-previous>Previous</button>
|
||||
|
||||
@@ -53,6 +53,33 @@
|
||||
})});
|
||||
return options;
|
||||
};
|
||||
root.createDetailWatch = ({fetchJson,refreshFollowing,onState}) => {
|
||||
const api=root.searchPreviewSubscriptionOptions(fetchJson);
|
||||
let item,watching=false,mutation;
|
||||
return {
|
||||
async open(next) {
|
||||
item=next; onState('loading',watching);
|
||||
const result=await api.load(next).catch(error=>{
|
||||
if(item===next)onState('error',watching,error);throw error;
|
||||
});
|
||||
if (item !== next) return;
|
||||
watching=result.watching === true; onState('ready',watching);
|
||||
},
|
||||
toggle() {
|
||||
if (mutation) return mutation;
|
||||
const next=!watching;
|
||||
onState(next?'watching':'unwatching',watching);
|
||||
mutation=api.watch(item,next).then(async result => {
|
||||
if (result?.watching !== next || result?.following_synced !== true)
|
||||
throw new Error(result?.error || 'Unconfirmed.');
|
||||
watching=next; await refreshFollowing();
|
||||
onState(watching?'watched':'unwatched',watching);
|
||||
}).catch(error => {onState('error',watching,error);throw error;})
|
||||
.finally(()=>{mutation=null;});
|
||||
return mutation;
|
||||
},
|
||||
};
|
||||
};
|
||||
root.searchPreviewWatchStatus = state => ({
|
||||
watching:'Starting watch…', unwatching:'Stopping watch…',
|
||||
watched:'Watching · available in Following. Future activity will appear in Updates.',
|
||||
|
||||
Reference in new issue
Block a user