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}`;
}
}