Back to OScope
Code
84 lines (78 loc) · 4.11 KB
// OScope: page entry. Header, search, routes.
import { $, h, usd, sol as fsol, short } from './util.js';
import { icon } from './icons.js';
import { live, net } from './net.js';
import { paper } from './paper.js';
import './trackers.js';
import { route, mount, go } from './router.js';
import { avatar } from './parts.js';
import { openSettings } from './settings.js';
import { pulseView } from './pulse.js';
import { liveView } from './live.js';
import { coinView } from './coin.js';
import { portfolioView } from './portfolio.js';
import { trackersView, walletView } from './trackerview.js';
route(/^\/$/, pulseView, 'pulse');
route(/^\/live$/, liveView, 'live');
route(/^\/coin\/([1-9A-HJ-NP-Za-km-z]{32,44})$/, coinView, '');
route(/^\/portfolio$/, portfolioView, 'portfolio');
route(/^\/trackers$/, trackersView, 'trackers');
route(/^\/wallet\/([1-9A-HJ-NP-Za-km-z]{32,44})$/, walletView, '');
// ---------- header ----------
$('.search-ic').innerHTML = icon('search', 15);
$('.wallet-ic').innerHTML = icon('wallet', 15);
$('#settings-btn').innerHTML = icon('gear', 17);
$('#settings-btn').addEventListener('click', openSettings);
function status() {
const f = $('#feed');
const ok = live.open && live.feed && (live.lag == null || live.lag < 15000);
f.className = 'feed ' + (ok ? 'ok' : live.open ? 'bad' : '');
$('#feed-txt').textContent = !live.open ? 'Connecting' : !live.feed ? 'Stream down' : live.lag > 15000 ? 'Stream quiet' : 'Live';
$('#solpx span').textContent = live.sol ? '$' + live.sol.toFixed(2) : '–';
}
live.on('status', status);
status();
function wallet() { $('#wallet-sol').textContent = fsol(paper.s.sol) + ' SOL'; }
paper.on('change', wallet);
wallet();
// ---------- search ----------
const q = $('#q'), res = $('#search-res');
let timer = 0, items = [], sel = -1, seq = 0;
async function search() {
const text = q.value.trim();
if (!text) { res.classList.remove('open'); return; }
const my = ++seq;
let list = [];
try { list = await net.get('/api/search?q=' + encodeURIComponent(text)); } catch {}
if (my !== seq) return;
items = list;
sel = list.length ? 0 : -1;
const isAddr = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(text);
res.replaceChildren(...(list.length ? list.map((r, i) => h('a.sr' + (i === sel ? '.sel' : ''), { href: `/coin/${r.m}`, 'data-link': '', onmousedown: e => e.preventDefault(), onclick: () => close() },
avatar(r, 36),
h('div', { style: { minWidth: 0 } }, h('b', null, r.n || r.s), ' ', h('span.mut', null, r.s), h('div.mut', null, short(r.m, 5))),
h('div', { style: { textAlign: 'right' } }, h('b', null, usd(r.mc * live.sol)), h('div.mut', null, r.mig ? 'Migrated' : r.pr.toFixed(0) + '% curve')))) :
isAddr ? [h('a.sr', { href: `/coin/${text}`, 'data-link': '', onclick: () => close() }, h('div'), h('div', null, h('b', null, 'Open this coin'), h('div.mut', null, short(text, 6))), h('span')),
h('a.sr', { href: `/wallet/${text}`, 'data-link': '', onclick: () => close() }, h('div'), h('div', null, h('b', null, 'Open as a wallet'), h('div.mut', null, short(text, 6))), h('span'))]
: [h('div.sr-empty', null, 'No coin by that name in the last hours')]));
res.classList.add('open');
}
function close() { res.classList.remove('open'); q.value = ''; q.blur(); }
q.addEventListener('input', () => { clearTimeout(timer); timer = setTimeout(search, 120); });
q.addEventListener('focus', () => { if (q.value.trim()) search(); });
q.addEventListener('blur', () => setTimeout(() => res.classList.remove('open'), 120));
q.addEventListener('keydown', e => {
const links = [...res.querySelectorAll('a.sr')];
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
e.preventDefault();
sel = Math.max(0, Math.min(links.length - 1, sel + (e.key === 'ArrowDown' ? 1 : -1)));
links.forEach((a, i) => a.classList.toggle('sel', i === sel));
} else if (e.key === 'Enter') {
const a = links[Math.max(0, sel)];
if (a) { go(a.getAttribute('href')); close(); }
} else if (e.key === 'Escape') close();
});
document.addEventListener('keydown', e => {
if (e.key === '/' && !/^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement?.tagName)) { e.preventDefault(); q.focus(); }
});
mount();