1import { renderClaimHandle, showDashboard } from './dashboard';2import { renderSignedOut } from './home';3import { showProfile } from './profile';4import { bindServiceDialogs, showServiceRoute } from './services';5import { api, element, escapeHtml, type Me, setPageTitle } from './shared';6import { clearTheme, watchLogoContrast } from './theme';78const main = element('main');9let me: Me | null = null;1011function startSignIn() {12 const returnTo = `${location.pathname}${location.search}`;13 location.assign(`/auth/start?return_to=${encodeURIComponent(returnTo)}`);14}1516function renderSession() {17 const session = element('session');18 if (!me) {19 session.innerHTML = '<li><a href="#" id="signin" role="button" class="outline">Sign in</a></li>';20 element('signin').addEventListener('click', (event) => {21 event.preventDefault();22 startSignIn();23 });24 return;25 }26 session.innerHTML = me.handle27 ? `<li><a href="/@${escapeHtml(me.handle)}">@${escapeHtml(me.handle)}</a></li>`28 : '<li><small>no handle yet</small></li>';29}3031function showSignedOutHome() {32 me = null;33 history.replaceState({}, '', '/');34 clearTheme();35 renderSession();36 renderSignedOut();37}3839async function route() {40 const path = location.pathname;41 setPageTitle();42 try {43 me = await api<Me | null>('/api/me');44 } catch {45 me = null;46 }47 renderSession();4849 const handleMatch = path.match(/^\/@([^/]+)$/);50 if (handleMatch) {51 showProfile(decodeURIComponent(handleMatch[1] ?? ''));52 return;53 }5455 const serviceMatch = path.match(/^\/s\/(res_[a-z2-7]+)$/);56 if (serviceMatch) {57 showServiceRoute(serviceMatch[1] ?? '', me !== null);58 return;59 }6061 if (!me) {62 renderSignedOut();63 return;64 }65 if (!me.handle) {66 renderClaimHandle();67 return;68 }69 await showDashboard(me.handle, showSignedOutHome);70}7172bindServiceDialogs(main);73watchLogoContrast();74main.removeAttribute('aria-busy');75await route();