124 lines
4.4 KiB
JavaScript
124 lines
4.4 KiB
JavaScript
(function (root, factory) {
|
|
if (typeof module === 'object' && module.exports) module.exports = factory;
|
|
else root.createMobileQueuePriority = factory;
|
|
})(typeof self !== 'undefined' ? self : this, function createMobileQueuePriority(options = {}) {
|
|
const DEFAULT_ORDER = [
|
|
'attention', 'today', 'update', 'agenda', 'following', 'authored', 'filed', 'later', 'draft',
|
|
];
|
|
const storage = options.storage;
|
|
const getLogin = options.getLogin || (() => '');
|
|
const prefix = 'stackchain-mobile-queue-priority-v1:';
|
|
const labels = options.labels || {};
|
|
const documentRef = options.document || (typeof document !== 'undefined' ? document : null);
|
|
|
|
function key() {
|
|
const login = String(getLogin() || '').trim().toLowerCase();
|
|
return login ? prefix + encodeURIComponent(login) : '';
|
|
}
|
|
|
|
function valid(order) {
|
|
return Array.isArray(order) && order.length === DEFAULT_ORDER.length &&
|
|
new Set(order).size === DEFAULT_ORDER.length &&
|
|
order.every((name, index) => DEFAULT_ORDER.includes(name) && typeof name === 'string');
|
|
}
|
|
|
|
function getOrder() {
|
|
const accountKey = key();
|
|
if (!accountKey || !storage) return DEFAULT_ORDER.slice();
|
|
try {
|
|
const saved = JSON.parse(storage.getItem(accountKey) || 'null');
|
|
return valid(saved) ? saved.slice() : DEFAULT_ORDER.slice();
|
|
} catch (_error) {
|
|
return DEFAULT_ORDER.slice();
|
|
}
|
|
}
|
|
|
|
function save(order) {
|
|
const accountKey = key();
|
|
if (!accountKey || !storage || !valid(order)) return false;
|
|
try {
|
|
storage.setItem(accountKey, JSON.stringify(order));
|
|
options.onChange?.(order.slice());
|
|
return true;
|
|
} catch (_error) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function move(name, delta) {
|
|
const order = getOrder();
|
|
const index = order.indexOf(name);
|
|
const next = index + (Number(delta) < 0 ? -1 : 1);
|
|
if (index < 0 || next < 0 || next >= order.length) return order;
|
|
[order[index], order[next]] = [order[next], order[index]];
|
|
save(order);
|
|
return order.slice();
|
|
}
|
|
|
|
function reset() {
|
|
const accountKey = key();
|
|
if (accountKey && storage) {
|
|
try { storage.removeItem(accountKey); } catch (_error) {}
|
|
}
|
|
const order = DEFAULT_ORDER.slice();
|
|
options.onChange?.(order.slice());
|
|
return order;
|
|
}
|
|
|
|
function displayName(name) {
|
|
return labels[name] || name.charAt(0).toUpperCase() + name.slice(1);
|
|
}
|
|
|
|
function render() {
|
|
if (!options.list || !documentRef) return getOrder();
|
|
const order = getOrder();
|
|
const signedIn = Boolean(key());
|
|
const rows = order.map((name, index) => {
|
|
const row = documentRef.createElement('div');
|
|
row.setAttribute('data-queue-priority', name);
|
|
row.setAttribute('class', 'mobile-queue-priority-row');
|
|
const label = documentRef.createElement('span');
|
|
label.textContent = displayName(name);
|
|
const controls = documentRef.createElement('span');
|
|
controls.setAttribute('class', 'mobile-queue-priority-controls');
|
|
const earlier = documentRef.createElement('button');
|
|
earlier.textContent = 'Earlier';
|
|
earlier.setAttribute('type', 'button');
|
|
earlier.setAttribute('aria-label', 'Move ' + displayName(name) + ' earlier');
|
|
earlier.disabled = !signedIn || index === 0;
|
|
earlier.addEventListener('click', () => {
|
|
move(name, -1);
|
|
if (options.status) options.status.textContent = displayName(name) + ' moved earlier.';
|
|
render();
|
|
});
|
|
const later = documentRef.createElement('button');
|
|
later.textContent = 'Later';
|
|
later.setAttribute('type', 'button');
|
|
later.setAttribute('aria-label', 'Move ' + displayName(name) + ' later');
|
|
later.disabled = !signedIn || index === order.length - 1;
|
|
later.addEventListener('click', () => {
|
|
move(name, 1);
|
|
if (options.status) options.status.textContent = displayName(name) + ' moved later.';
|
|
render();
|
|
});
|
|
controls.append(earlier, later);
|
|
row.append(label, controls);
|
|
return row;
|
|
});
|
|
options.list.replaceChildren(...rows);
|
|
if (options.resetButton) options.resetButton.disabled = !signedIn;
|
|
return order;
|
|
}
|
|
|
|
function start() {
|
|
options.resetButton?.addEventListener('click', () => {
|
|
reset();
|
|
if (options.status) options.status.textContent = 'Routine order reset.';
|
|
render();
|
|
});
|
|
return render();
|
|
}
|
|
|
|
return {getOrder, move, reset, render, start, defaultOrder: () => DEFAULT_ORDER.slice()};
|
|
});
|