(function (root, factory) { if (typeof module === 'object' && module.exports) module.exports = factory; else root.createProgressiveMobileDock = factory; })(typeof self !== 'undefined' ? self : this, function createProgressiveMobileDock(options) { const document = options.document; const myWork = options.myWork; const work = document.querySelector('[data-mobile-task="work"]'); const queues = document.querySelector('[data-mobile-task="queues"]'); const sheet = document.querySelector('#mobile-queue-sheet'); const close = document.querySelector('#close-mobile-queues'); const next = document.querySelector('#mobile-queue-next-action'); const rows = Object.fromEntries(Array.from(document.querySelectorAll('[data-mobile-queue]')) .map(row => [row.dataset.mobileQueue, row])); const countElements = Object.fromEntries(Array.from(document.querySelectorAll('[data-mobile-queue-count]')) .map(element => [element.dataset.mobileQueueCount, element])); const originalDescriptions = Object.fromEntries(Object.entries(rows) .map(([name, row]) => [name, row.querySelector?.('small')?.textContent || ''])); const originalCounts = Object.fromEntries(Object.entries(countElements) .map(([name, element]) => [name, element.textContent])); const supported = new Set(['all', 'attention', 'filed', 'authored', 'issue', 'pull', 'review', 'update']); const listeners = []; let started = false; let lastTask = null; let unsubscribe = null; function listen(element, name, listener) { if (!element) return; element.addEventListener(name, listener); listeners.push([element, name, listener]); } function render() { const counts = myWork?.counts?.() || {}; Object.entries(rows).forEach(([name, row]) => { const count = Math.max(0, Number(counts[name]) || 0); const countElement = countElements[name]; if (supported.has(name)) { row.removeAttribute('data-unavailable'); row.removeAttribute('data-progressive-loading'); if (countElement) countElement.textContent = String(count); return; } row.setAttribute('data-unavailable', 'true'); row.setAttribute('data-progressive-loading', 'true'); const description = row.querySelector?.('small'); if (description) description.textContent = 'Still loading'; if (countElement) countElement.textContent = '…'; }); const actionable = ['attention', 'filed', 'authored', 'review', 'update'] .find(name => Number(counts[name]) > 0); if (next) { if (actionable) { next.textContent = 'Open ' + (actionable === 'authored' ? 'My PRs' : actionable[0].toUpperCase() + actionable.slice(1)) + ' (' + counts[actionable] + ')'; next.dataset.queue = actionable; next.removeAttribute('data-unavailable'); } else { next.textContent = Number(counts.all) > 0 ? 'Open assigned work (' + counts.all + ')' : 'Assigned work is still loading'; next.dataset.queue = 'all'; if (!Number(counts.all)) next.setAttribute('data-unavailable', 'true'); } } } function openSheet() { lastTask = 'queues'; render(); if (sheet && !sheet.open) sheet.showModal(); } function openQueue(name) { if (!supported.has(name)) return false; lastTask = 'work'; if (sheet?.open) sheet.close(); myWork?.selectQueue?.(name, {openFirst:true}); return true; } function start() { if (started) return false; started = true; listen(work, 'click', () => { lastTask = 'work'; myWork?.openFirst?.(); }); listen(queues, 'click', openSheet); listen(close, 'click', () => sheet?.open && sheet.close()); Object.entries(rows).forEach(([name, row]) => listen(row, 'click', () => openQueue(name))); listen(next, 'click', () => openQueue(next.dataset.queue || 'all')); unsubscribe = myWork?.subscribe?.(render) || null; render(); return true; } function handoff() { return {queueSheetOpen:Boolean(sheet?.open), lastTask}; } function stop() { listeners.splice(0).forEach(([element, name, listener]) => element.removeEventListener(name, listener)); unsubscribe?.(); unsubscribe = null; Object.entries(rows).forEach(([name, row]) => { row.removeAttribute('data-unavailable'); row.removeAttribute('data-progressive-loading'); const description = row.querySelector?.('small'); if (description) description.textContent = originalDescriptions[name]; if (countElements[name]) countElements[name].textContent = originalCounts[name]; }); started = false; } return {start, stop, handoff, render, openQueue}; }); if (typeof window !== 'undefined' && typeof document !== 'undefined') { window.stackchainProgressiveMobileDock = createProgressiveMobileDock({ document, myWork:window.stackchainProgressiveMyWork, }); window.stackchainProgressiveMobileDock.start(); }