| |
| 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, ''); |
| |
| |
| $('.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(); |
| |
| |
| 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(); |