diff --git a/directory/index.html b/directory/index.html index e2db972ffd..f3b8825ba1 100644 --- a/directory/index.html +++ b/directory/index.html @@ -895,7 +895,7 @@ window.addEventListener('scroll',changeHeaderBg);
diff --git a/js/directory.js b/js/directory.js index 313bdeedec..72c93d35fb 100644 --- a/js/directory.js +++ b/js/directory.js @@ -5,12 +5,14 @@ const directoryDataURL = 'https://directory.simplex.chat/data/'; let allEntries = []; -let sortedEntries = []; - let filteredEntries = []; let currentSortMode = ''; +let currentSearch = ''; + +let currentPage = 1; + async function initDirectory() { const listing = await fetchJSON(directoryDataURL + 'listing.json') const liveBtn = document.querySelector('#top-pagination .live'); @@ -18,24 +20,29 @@ async function initDirectory() { const topBtn = document.querySelector('#top-pagination .top'); const searchInput = document.getElementById('search'); allEntries = listing.entries - renderSortedEntries('top', byMemberCountDesc, topBtn) - window.addEventListener('hashchange', renderDirectoryPage); - searchInput.addEventListener('input', (e) => renderFilteredEntries(e.target.value)); + renderEntries('top', bySortPriority, topBtn) + searchInput.addEventListener('input', (e) => renderEntries('top', bySortPriority, topBtn, e.target.value.trim())); + liveBtn.addEventListener('click', () => renderEntries('live', byActiveAtDesc, liveBtn, '')); + newBtn.addEventListener('click', () => renderEntries('new', byCreatedAtDesc, newBtn, '')); + topBtn.addEventListener('click', () => renderEntries('top', bySortPriority, topBtn, '')); - liveBtn.addEventListener('click', () => renderSortedEntries('live', byActiveAtDesc, liveBtn)); - newBtn.addEventListener('click', () => renderSortedEntries('new', byCreatedAtDesc, newBtn)); - topBtn.addEventListener('click', () => renderSortedEntries('top', byMemberCountDesc, topBtn)); - - function renderSortedEntries(mode, comparator, btn) { - if (currentSortMode === mode) return; + function renderEntries(mode, comparator, btn, search) { + if (currentSortMode === mode && search == currentSearch) return; currentSortMode = mode; if (location.hash) location.hash = ''; liveBtn.classList.remove('active'); newBtn.classList.remove('active'); topBtn.classList.remove('active'); - btn.classList.add('active'); - sortedEntries = allEntries.slice().sort(comparator); - renderFilteredEntries(searchInput.value); + if (search == '') { + currentSearch = ''; + currentPage = 1; + searchInput.value = ''; + btn.classList.add('active'); + } else { + currentSearch = search; + } + filteredEntries = filterEntries(mode, search ?? '').sort(comparator); + renderDirectoryPage(); } } @@ -44,18 +51,20 @@ function renderDirectoryPage() { displayEntries(currentEntries); } -function renderFilteredEntries(s) { - const query = s.toLowerCase().trim(); - if (query === '') { - filteredEntries = sortedEntries.slice(); - } else { - filteredEntries = sortedEntries.filter(entry => - (entry.displayName || '').toLowerCase().includes(query) - || includesQuery(entry.shortDescr, query) - || includesQuery(entry.welcomeMessage, query) - ); - } - renderDirectoryPage(); +function filterEntries(mode, s) { + if (s === '' && mode == 'top') return allEntries.slice(); + const query = s.toLowerCase(); + return allEntries.filter(entry => + ( mode === 'top' + || (mode === 'new' && entry.createdAt) + || (mode === 'live' && entry.activeAt) + ) && + ( query === '' + || (entry.displayName || '').toLowerCase().includes(query) + || includesQuery(entry.shortDescr, query) + || includesQuery(entry.welcomeMessage, query) + ) + ); } function includesQuery(field, query) { @@ -91,18 +100,18 @@ async function fetchJSON(url) { } } -function byMemberCountDesc(entry1, entry2) { - return entryMemberCount(entry2) - entryMemberCount(entry1); +function bySortPriority(entry1, entry2) { + return entrySortPriority(entry2) - entrySortPriority(entry1); } function byActiveAtDesc(entry1, entry2) { return (roundedTs(entry2.activeAt) - roundedTs(entry1.activeAt)) * 10 - + Math.sign(byMemberCountDesc(entry1, entry2)); + + Math.sign(bySortPriority(entry1, entry2)); } function byCreatedAtDesc(entry1, entry2) { return (roundedTs(entry2.createdAt) - roundedTs(entry1.createdAt)) * 10 - + Math.sign(byMemberCountDesc(entry1, entry2)); + + Math.sign(bySortPriority(entry1, entry2)); } function roundedTs(s) { @@ -114,6 +123,14 @@ function roundedTs(s) { } } +const simplexUsersGroup = 'SimpleX users group'; + +function entrySortPriority(entry) { + return entry.displayName === simplexUsersGroup + ? Number.MAX_VALUE + : entryMemberCount(entry) +} + function entryMemberCount(entry) { return entry.entryType.type == 'group' ? (entry.entryType.summary?.currentMembers ?? 0) @@ -204,7 +221,7 @@ function displayEntries(entries) { console.log(e); imgElement.href = groupLinkUri; } - if (!isCurrentSite(imgElement.href)) imgElement.target = "_blank"; + imgElement.target = "_blank"; imgElement.title = `Join ${displayName}`; entryDiv.appendChild(imgElement); @@ -223,13 +240,13 @@ function displayEntries(entries) { } function goToPage(p) { - location.hash = p.toString(); + currentPage = p; + renderDirectoryPage(); } function addPagination(entries) { const entriesPerPage = 10; const totalPages = Math.ceil(entries.length / entriesPerPage); - let currentPage = parseInt(location.hash.slice(1)) || 1; if (currentPage < 1) currentPage = 1; if (currentPage > totalPages) currentPage = totalPages; @@ -376,7 +393,7 @@ function platformSimplexUri(uri) { if (remainingParams) newFragment += '?' + remainingParams; return `https://${host}:/${linkType}#${newFragment}`; } else { - return `https://simplex.chat/${fragment}`; + return `https://simplex.chat/${linkType}#${fragment}`; } }