1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5export function getSortedItems(items) {
6 return [...items].sort((a, b) => {
7 const aVetoed = Object.values(a.votes).includes('veto');
8 const bVetoed = Object.values(b.votes).includes('veto');
9 if (aVetoed && !bVetoed) return 1;
10 if (!aVetoed && bVetoed) return -1;
11 const aScore = Object.values(a.votes).reduce((sum, v) =>
12 sum + (v === 'up' ? 1 : v === 'down' ? -1 : 0), 0);
13 const bScore = Object.values(b.votes).reduce((sum, v) =>
14 sum + (v === 'up' ? 1 : v === 'down' ? -1 : 0), 0);
15 return bScore - aScore;
16 });
17}
18
19export function escapeHtml(text) {
20 const div = document.createElement('div');
21 div.textContent = text;
22 return div.innerHTML;
23}
24
25export function updateConnectionStatus(status) {
26 const statusDot = document.querySelector('.status-dot');
27 const statusText = document.querySelector('.status-text');
28
29 statusDot.className = 'status-dot ' + status;
30
31 const statusLabels = {
32 connecting: 'Connecting...',
33 connected: 'Connected',
34 disconnected: 'Disconnected'
35 };
36
37 statusText.textContent = statusLabels[status] || status;
38}
39
40function formatTimeSince(timestamp) {
41 const seconds = Math.floor((Date.now() - timestamp) / 1000);
42
43 if (seconds < 5) return 'just now';
44 if (seconds < 60) return `${seconds}s ago`;
45
46 const minutes = Math.floor(seconds / 60);
47 if (minutes < 60) return `${minutes}m ago`;
48
49 const hours = Math.floor(minutes / 60);
50 if (hours < 24) return `${hours}h ago`;
51
52 const days = Math.floor(hours / 24);
53 return `${days}d ago`;
54}
55
56export function updateLastSync(lastSyncTime) {
57 const lastSyncEl = document.querySelector('.last-sync');
58 if (!lastSyncTime) {
59 lastSyncEl.textContent = '';
60 return;
61 }
62
63 lastSyncEl.textContent = '• ' + formatTimeSince(lastSyncTime);
64}
65
66export function setUIEnabled(enabled, listScreen, listContainer) {
67 const inputs = listScreen.querySelectorAll('input, textarea, button');
68 inputs.forEach(input => {
69 // Don't disable the leave button
70 if (input.id === 'leave-btn') return;
71 input.disabled = !enabled;
72 });
73
74 if (enabled) {
75 listContainer.classList.remove('disabled');
76 } else {
77 listContainer.classList.add('disabled');
78 }
79}