feat: make Following a changed-first inbox (Closes #1297)
This commit is contained in:
1 parent
bbf397454d
commit
32e2a228b9
8 files changed
+325
-21
No files matched your search
@@ -1092,6 +1092,8 @@ textarea { resize: vertical; min-height: 120px; }
|
||||
.following-list { display:grid; gap:8px; min-width:0; max-height:70dvh; overflow:auto; }
|
||||
.following-card { box-sizing:border-box; display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%; min-width:0; min-height:52px; padding:10px 12px; text-align:left; }
|
||||
.following-card span:first-child { min-width:0; display:grid; gap:3px; }
|
||||
.following-card em { color:var(--accent); font-size:.75rem; font-style:normal; font-weight:700; text-transform:uppercase; letter-spacing:.04em; }
|
||||
.following-card.has-unseen-change { border-color:var(--accent); }
|
||||
.following-card strong, .following-card small { overflow-wrap:anywhere; }
|
||||
.markdown-content { min-width:0; max-width:100%; overflow-wrap:anywhere; white-space:normal; }
|
||||
.markdown-content > :first-child { margin-top:0; }
|
||||
|
||||
+28
-8
@@ -14,9 +14,12 @@
|
||||
|
||||
function publish(status, error) {
|
||||
const state = {status, revision:snapshot.revision, items:[...snapshot.items]};
|
||||
state.degraded = snapshot.degraded === true;
|
||||
state.refreshFailures = Number(snapshot.refreshFailures) || 0;
|
||||
if (error) state.error = error;
|
||||
options.render?.(state);
|
||||
if (status === 'ready') options.onCount?.(snapshot.items.length);
|
||||
if (status === 'ready') options.onCount?.(
|
||||
snapshot.items.filter(item => item.has_unseen_change === true).length);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -29,6 +32,8 @@
|
||||
snapshot = {
|
||||
revision:Number(result?.revision) || 0,
|
||||
items:Array.isArray(result?.items) ? result.items.slice(0, 50) : [],
|
||||
degraded:result?.degraded === true,
|
||||
refreshFailures:Number(result?.refresh_failures) || 0,
|
||||
};
|
||||
publish('ready');
|
||||
return snapshot;
|
||||
@@ -38,10 +43,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function open(index) {
|
||||
async function open(index) {
|
||||
const item = snapshot.items[Number(index)];
|
||||
if (!item) return false;
|
||||
Promise.resolve(options.onOpen?.({...item, kind:'issue'})).catch(() => {});
|
||||
await options.onOpen?.({...item, kind:'issue'});
|
||||
if (item.has_unseen_change === true && typeof options.onAcknowledge === 'function') {
|
||||
await options.onAcknowledge(item);
|
||||
item.has_unseen_change = false;
|
||||
publish('ready');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,17 +77,19 @@
|
||||
query('#retry-following').hidden = state.status !== 'error';
|
||||
if (state.status === 'loading') return void (status.textContent = 'Loading watched issues…');
|
||||
if (state.status === 'error') return void (status.textContent = state.error?.message || 'Following is temporarily unavailable.');
|
||||
status.textContent = state.items.length
|
||||
status.textContent = (state.degraded ? 'Some watched issues could not be refreshed. Showing last known details. ' : '') + (state.items.length
|
||||
? state.items.length + (state.items.length === 1 ? ' watched issue.' : ' watched issues.')
|
||||
: 'No watched issues yet. Watch one from Search to keep it here.';
|
||||
: 'No watched issues yet. Watch one from Search to keep it here.');
|
||||
list.innerHTML = state.items.map((item, index) =>
|
||||
'<button class="following-card" type="button" data-following-index="' + index + '"><span><strong>' +
|
||||
'<button class="following-card' + (item.has_unseen_change ? ' has-unseen-change' : '') +
|
||||
'" type="button" data-following-index="' + index + '"><span>' +
|
||||
(item.has_unseen_change ? '<em>New activity</em>' : '') + '<strong>' +
|
||||
escapeHtml(item.title) + '</strong><small>' + escapeHtml(item.repository + ' #' + item.number +
|
||||
' · ' + item.state + ' · ' + formatTime(item.updated_at)) +
|
||||
'</small></span><span aria-hidden="true">›</span></button>').join('');
|
||||
list.querySelectorAll('[data-following-index]').forEach(button => button.addEventListener('click', () => {
|
||||
query('#following-sheet').close();
|
||||
feature.open(Number(button.dataset.followingIndex));
|
||||
feature.open(Number(button.dataset.followingIndex)).catch(() => {});
|
||||
}));
|
||||
}
|
||||
feature = createFollowing({
|
||||
@@ -86,9 +98,17 @@
|
||||
const value = query('[data-mobile-queue-count="following"]');
|
||||
value.textContent = count;
|
||||
value.closest('button').setAttribute('aria-label', 'Following, ' + count +
|
||||
(count === 1 ? ' watched issue' : ' watched issues'));
|
||||
(count === 1 ? ' unseen change' : ' unseen changes'));
|
||||
},
|
||||
onOpen,
|
||||
onAcknowledge:item => {
|
||||
const [owner, repo] = item.repository.split('/');
|
||||
return fetchJson('api/v1/following/' + encodeURIComponent(owner) + '/' +
|
||||
encodeURIComponent(repo) + '/issues/' + item.number + '/seen', {
|
||||
method:'PUT', headers:{'Content-Type':'application/json', Accept:'application/json'},
|
||||
body:JSON.stringify({updated_at:item.updated_at}),
|
||||
});
|
||||
},
|
||||
});
|
||||
query('#close-following').addEventListener('click', () => query('#following-sheet').close());
|
||||
query('#retry-following').addEventListener('click', () => feature.load().catch(() => {}));
|
||||
|
||||
Reference in new issue
Block a user