diff options
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/messages.js | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 9336f7c..f563435 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -25,6 +25,7 @@ import { import { makeDMRumor, unwrapDM, wrapDM } from '../dm.js'; import { saveInbox } from '../dm-inbox.js'; import { makeSearcher, resultRows, fallbackAvatar } from '../recipient-search.js'; +import { getNetwork } from '../api.js'; import { hexToBytes, bytesToHex } from '@noble/hashes/utils'; import { t } from '../i18n.js'; @@ -607,6 +608,18 @@ export function messagesFeature(ctx) { const urlInvite = typeof location !== 'undefined' ? parseInviteLink(location.href) : null; if (urlInvite) { try { history.replaceState(null, '', '/'); } catch {} } + // coinos.io/<username> parity: a claimed name (or a raw npub / hex key) as + // the whole URL path deep-links to that profile. Real files never reach the + // app — the server tries them first — and gift/invite links carry their own + // multi-segment paths, which this single-segment shape can't match. The + // path is consumed immediately so a reload lands on the wallet as usual. + const urlProfile = (() => { + if (typeof location === 'undefined' || urlInvite) return null; + const m = location.pathname.match(/^\/([A-Za-z0-9._-]{1,64})\/?$/); + return m ? m[1] : null; + })(); + if (urlProfile) { try { history.replaceState(null, '', '/'); } catch {} } + // ---- push notifications ------------------------------------------------- // The nwcpush notifier watches relays for what it can see without keys: // kind-1059 wraps p-tagged at us (DMs, direct invites), zap receipts @@ -2380,6 +2393,22 @@ export function messagesFeature(ctx) { loadLinkInvite(urlInvite); setTimeout(() => { ui.chatOpen = true; ui.msgView = 'home'; render(); }, 0); } + if (urlProfile) { + (async () => { + let pk = parseNostrPubkey(urlProfile); + if (!pk && /^[a-z0-9._-]{1,30}$/i.test(urlProfile)) { + // same registrar + domain rule the names feature uses + const domain = getNetwork() === 'mutinynet' ? 'staging.coinos.io' : 'coinos.io'; + const name = urlProfile.toLowerCase(); + try { + const j = await fetch(`https://names.coinos.io/.well-known/nostr.json?name=${encodeURIComponent(name)}&domain=${domain}`) + .then((r) => r.json()); + pk = (j.names || {})[name] || null; + } catch {} + } + if (pk && /^[0-9a-f]{64}$/.test(pk)) openProfile(pk); + })(); + } window.addEventListener('resize', onViewportResize); window.visualViewport?.addEventListener('resize', onViewportResize); allUnsubs.push(() => { |
