feat: search by host

dev
gravel 9 months ago
parent f29d183e9c
commit 16f625199a
No known key found for this signature in database
GPG Key ID: CA95FFF4E0123903

@ -68,57 +68,105 @@ export class RoomInfo {
}));
}
/**
* @param {string} identifier
* @returns {string[]}
*/
static getRoomStaff(identifier) {
const room = _RoomInfo.getRoom(identifier);
const { admins = [], moderators = [] } = room;
return [...new Set([...admins, ...moderators])];
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomPublicKey(identifier) {
const server = _RoomInfo.getRoomServer(identifier);
return server.pubkey;
}
/**
* @param {string} identifier
* @returns {Date}
*/
static getRoomCreationDate(identifier) {
const room = _RoomInfo.getRoom(identifier);
return new Date(room.created * 1000);
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomToken(identifier) {
return identifier.split("+")[0];
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomServerId(identifier) {
return identifier.split("+")[1];
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomLanguageFlag(identifier) {
return _RoomInfo.getRoom(identifier).language_flag;
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomName(identifier) {
return _RoomInfo.getRoom(identifier).name;
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomDescription(identifier) {
return _RoomInfo.getRoom(identifier).description;
}
/**
* @param {string} identifier
* @returns {number}
*/
static getRoomUserCount(identifier) {
return _RoomInfo.getRoom(identifier).active_users;
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomPreviewLink(identifier) {
const server = _RoomInfo.getRoomServer(identifier);
return `${server.base_url}/r/${RoomInfo.getRoomToken(identifier)}`;
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomJoinLink(identifier) {
const server = _RoomInfo.getRoomServer(identifier);
const token = RoomInfo.getRoomToken(identifier);
return `${server.base_url}/${token}?public_key=${server.pubkey}`;
}
/**
* @param {string} identifier
* @returns {string}
*/
static getRoomHostname(identifier) {
return _RoomInfo.getRoomServer(identifier)?.base_url;
}
@ -158,6 +206,7 @@ export const dom = {
preview_link: RoomInfo.getRoomPreviewLink(identifier),
join_link: RoomInfo.getRoomJoinLink(identifier),
identifier,
server_id: identifier.split("+")[1],
hostname: RoomInfo.getRoomHostname(identifier),
public_key: RoomInfo.getRoomPublicKey(identifier),
staff: RoomInfo.getRoomStaff(identifier),

@ -107,12 +107,12 @@ function reactToURLParameters() {
const hash = decodeURIComponent(rawHash.slice(1));
if (hash.startsWith("q=")) {
useSearchTerm(decodeURIComponent(hash.slice(2)), true);
useSearchTerm(decodeURIComponent(hash.slice(2)), { fillSearchBarWithTerm: true });
return;
}
if (!hash.includes("+") && !document.querySelector(`#${hash}`)) {
useSearchTerm(`#${hash}`, true);
useSearchTerm(`#${hash}`, { fillSearchBarWithTerm: true });
return;
}
@ -544,15 +544,17 @@ function setLastChecked(last_checked) {
timestamp_element.innerText = `${time_passed_in_minutes} minutes ago`;
}
// TODO: Move info into dynamic modal.
function addServerIconInteractions() {
const rows = dom.tbl_communities_content_rows();
for (const row of rows) {
const { hostname, public_key } = dom.row_info(row);
const { hostname } = dom.row_info(row);
const serverIcon = row.querySelector('.td_server_icon');
if (!serverIcon) continue;
serverIcon.addEventListener('click', () => {
alert(`Host: ${hostname}\n\nPublic key:\n${public_key}`);
useSearchTerm(`#host:${hostname.split("//")[1]}`, {
fillSearchBarWithTerm: true,
scrollSearchBarIntoView: true
});
});
}
}
@ -604,7 +606,7 @@ function addSearchInteractions() {
})
dom.btn_clear_search()?.addEventListener('click', function () {
useSearchTerm("", true);
useSearchTerm("", { fillSearchBarWithTerm: true });
dom.search_bar()?.focus();
})
@ -613,7 +615,7 @@ function addSearchInteractions() {
const currentSearchTerm = searchBar.value;
const randomSearches = [
"#new",
"#we're here",
"#we're-here",
"language",
"Australia",
"#chat",
@ -621,11 +623,11 @@ function addSearchInteractions() {
"#privacy",
"#android",
"#crypto",
"lang:en",
"lang:zh",
"#lang:en",
"#lang:zh",
].filter(term => term != currentSearchTerm);
const randomSearch = randomSearches[~~(Math.random() * randomSearches.length)];
useSearchTerm(randomSearch, true);
useSearchTerm(randomSearch, { fillSearchBarWithTerm: true });
})
dom.btn_share_search()?.addEventListener('click', function() {
@ -644,7 +646,10 @@ function addSearchInteractions() {
tag.setAttribute('tabindex', "0");
tag.addEventListener('click', function(event) {
event.stopPropagation();
useSearchTerm("#" + this.innerText.replace(/ /g,"-"), true);
useSearchTerm("#" + this.innerText.replace(/ /g,"-"), {
fillSearchBarWithTerm: true,
scrollSearchBarIntoView: true
});
});
}
}
@ -800,12 +805,18 @@ function initializeSearch() {
}
let lastSearchTerm = null;
/**
*
* @param {string} rawTerm
* @param {{fillSearchBarWithTerm?: boolean, scrollSearchBarIntoView?: boolean}} [opts]
*/
async function useSearchTerm(rawTerm, fillSearchBarWithTerm = false) {
async function useSearchTerm(rawTerm, opts) {
if (rawTerm === lastSearchTerm) return;
const {fillSearchBarWithTerm, scrollSearchBarIntoView} = {
fillSearchBarWithTerm: false,
scrollSearchBarIntoView: false,
...opts
};
lastSearchTerm = rawTerm;
const searchBar = dom.search_bar();
@ -819,9 +830,12 @@ async function useSearchTerm(rawTerm, fillSearchBarWithTerm = false) {
dom.search_bar()?.classList.remove(CLASSES.SEARCH.NO_RESULTS);
} else {
location.hash = `q=${rawTerm}`;
const term = rawTerm.toLowerCase().replace(/lang:(\S+)|#$/g, "").trim();
const termTags = Array.from(rawTerm.matchAll(/#[^#\s]+/g)).map(match => match[0].slice(1).toLowerCase());
const term = rawTerm.toLowerCase().replace(/#[^#\s]+/g, "").trim();
const termTags = Array.from(rawTerm.matchAll(/#[^#\s]+/g))
.map(match => match[0].slice(1).toLowerCase())
.filter(tag => !tag.includes(":"));
const termLanguage = rawTerm.match(/lang:(\S+)/)?.[1];
const termHost = rawTerm.match(/host:(\S+)/)?.[1];
/**
* @param {{row: HTMLTableRowElement, identifier: string}} rowCache
*/
@ -834,10 +848,13 @@ async function useSearchTerm(rawTerm, fillSearchBarWithTerm = false) {
}
const rowName = RoomInfo.getRoomName(identifier).toLowerCase();
const rowDesc = RoomInfo.getRoomDescription(identifier).toLowerCase();
if (rowName.includes(term) || rowDesc.includes(term)) {
return true;
if (!rowName.includes(term) && !rowDesc.includes(term)) {
return false;
}
let hostname = RoomInfo.getRoomHostname(identifier).split("//")[1];
if (termHost && !hostname.startsWith(termHost)) return false;
const rowTags = RoomInfo.getRoomTags(identifier).map(({text}) => text.replace(/\s+/g, "-"));
console.log(rowTags, termTags);
for (const termTag of termTags) {
for (const rowTag of rowTags) {
if (rowTag.startsWith(termTag)) {
@ -845,7 +862,7 @@ async function useSearchTerm(rawTerm, fillSearchBarWithTerm = false) {
}
}
}
return false;
return termTags.length == 0;
}
const newRowMatches = communityFullRowCache.map(async (rowCache) => ({ rowCache, doesMatch: await rowMatches(rowCache) }));
const newRows = (await Promise.all(newRowMatches)).filter((row) => row.doesMatch).map(({rowCache}) => rowCache.row);
@ -862,6 +879,10 @@ async function useSearchTerm(rawTerm, fillSearchBarWithTerm = false) {
searchBar.value = rawTerm;
}
if (scrollSearchBarIntoView) {
searchBar.scrollIntoView({ behavior: 'smooth' });
}
sortTable();
}

@ -107,7 +107,7 @@
</a>
</td>
<td class="td_server_icon"
title="Host: <?=$hostname?>"
title="Host: <?=$hostname?>. Click to filter"
>
<?php if (empty($server_icon)): ?>
<div class="td_server_icon-circle" style="background-color: <?=$icon_color?>">

Loading…
Cancel
Save