From 71eaf25045c91a60d276168d63432da851e7eeef Mon Sep 17 00:00:00 2001 From: Jonathan Staab Date: Thu, 2 Mar 2023 15:56:21 -0600 Subject: [PATCH] Fix a few bugs, add zaps to alerts --- ROADMAP.md | 1 - src/agent/sync.ts | 10 ++++++---- src/app/alerts.ts | 30 +++++++++++++++++++++++------- src/util/misc.ts | 10 ++++++++++ src/util/nostr.ts | 2 +- src/views/alerts/Alert.svelte | 2 ++ src/views/alerts/Alerts.svelte | 9 ++++++++- src/views/notes/NoteDetail.svelte | 4 +++- 8 files changed, 53 insertions(+), 15 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index d2973093..e9ce8f18 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,5 @@ # Current -- [ ] Add zaps to notifications - [ ] Try adding boxes/separation on feeds based on user feedback - [ ] Strip zero width spaces from compose - [ ] Fix iOS/safari/firefox diff --git a/src/agent/sync.ts b/src/agent/sync.ts index a551e867..83de1558 100644 --- a/src/agent/sync.ts +++ b/src/agent/sync.ts @@ -3,7 +3,7 @@ import {nip05} from 'nostr-tools' import {getParams} from 'js-lnurl' import {noop, createMap, ensurePlural, chunk, switcherFn} from 'hurdak/lib/hurdak' import {log} from 'src/util/logger' -import {hexToBech32, now, sleep, tryJson, timedelta, shuffle, hash} from 'src/util/misc' +import {hexToBech32, tryFetch, now, sleep, tryJson, timedelta, shuffle, hash} from 'src/util/misc' import {Tags, roomAttrs, personKinds, isRelay, isShareableRelay, normalizeRelayUrl} from 'src/util/nostr' import database from 'src/agent/database' @@ -321,10 +321,12 @@ const verifyZapper = async (pubkey, address) => { } const url = `https://${domain}/.well-known/lnurlp/${name}` - const res = await fetch(url) + const res = await tryFetch(() => fetch(url)) - zapper = await res.json() - lnurl = hexToBech32('lnurl', url) + if (res) { + zapper = await res.json() + lnurl = hexToBech32('lnurl', url) + } } if (zapper?.allowsNostr && zapper?.nostrPubkey) { diff --git a/src/app/alerts.ts b/src/app/alerts.ts index 4a97354f..50177c79 100644 --- a/src/app/alerts.ts +++ b/src/app/alerts.ts @@ -1,3 +1,4 @@ +import type {DisplayEvent} from 'src/util/types' import {max, find, pluck, propEq, partition, uniq} from 'ramda' import {derived} from 'svelte/store' import {createMap} from 'hurdak/lib/hurdak' @@ -9,6 +10,13 @@ import network from 'src/agent/network' let listener +type AlertEvent = DisplayEvent & { + zappedBy?: Array + likedBy: Array + repliesFrom: Array + isMention: boolean +} + // State const seenAlertIds = synced('app/alerts/seenAlertIds', []) @@ -52,8 +60,8 @@ const processAlerts = async (pubkey, events) => { const parents = createMap('id', await network.loadParents(events)) - const asAlert = e => - asDisplayEvent({...e, repliesFrom: [], likedBy: [], isMention: false}) + const asAlert = (e): AlertEvent => + ({repliesFrom: [], likedBy: [], zappedBy: [], isMention: false, ...asDisplayEvent(e)}) const isPubkeyChild = e => { const parentId = findReplyId(e) @@ -61,19 +69,27 @@ const processAlerts = async (pubkey, events) => { return parents[parentId]?.pubkey === pubkey } - const [likes, notes] = partition(propEq('kind', 7), events) - const [replies, mentions] = partition(isPubkeyChild, notes) + const [replies, mentions] = partition(isPubkeyChild, events.filter(propEq('kind', 1))) + const likes = events.filter(propEq('kind', 7)) + const zaps = events.filter(propEq('kind', 9735)) + + zaps.filter(isPubkeyChild).forEach(e => { + const parent = parents[findReplyId(e)] + const note = asAlert(database.alerts.get(parent.id) || parent) + + database.alerts.put({...note, zappedBy: uniq(note.zappedBy.concat(e.pubkey))}) + }) likes.filter(isPubkeyChild).forEach(e => { const parent = parents[findReplyId(e)] - const note = database.alerts.get(parent.id) || asAlert(parent) + const note = asAlert(database.alerts.get(parent.id) || parent) database.alerts.put({...note, likedBy: uniq(note.likedBy.concat(e.pubkey))}) }) replies.forEach(e => { const parent = parents[findReplyId(e)] - const note = database.alerts.get(parent.id) || asAlert(parent) + const note = asAlert(database.alerts.get(parent.id) || parent) database.alerts.put({...note, repliesFrom: uniq(note.repliesFrom.concat(e.pubkey))}) }) @@ -150,7 +166,7 @@ const listen = async pubkey => { filter: [ {kinds: personKinds, authors: [pubkey], since}, {kinds: [4], authors: [pubkey], since}, - {kinds: [1, 7, 4], '#p': [pubkey], since}, + {kinds: [1, 7, 4, 9735], '#p': [pubkey], since}, {kinds: [42], '#e': roomIds, since}, ], onChunk: async events => { diff --git a/src/util/misc.ts b/src/util/misc.ts index f0f4e608..55a51dde 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -271,6 +271,16 @@ export const tryJson = f => { } } +export const tryFetch = async f => { + try { + return await f() + } catch (e) { + if (!e.toString().includes('fetch')) { + warn(e) + } + } +} + export const union = (...sets) => new Set(sets.flatMap(s => Array.from(s))) diff --git a/src/util/nostr.ts b/src/util/nostr.ts index 023c743e..37875863 100644 --- a/src/util/nostr.ts +++ b/src/util/nostr.ts @@ -83,7 +83,7 @@ export const displayPerson = p => { export const isLike = content => ['', '+', '🤙', '👍', '❤️'].includes(content) export const isAlert = (e, pubkey) => { - if (![1, 7].includes(e.kind)) { + if (![1, 7, 9735].includes(e.kind)) { return false } diff --git a/src/views/alerts/Alert.svelte b/src/views/alerts/Alert.svelte index 0ff8d070..fe6fe806 100644 --- a/src/views/alerts/Alert.svelte +++ b/src/views/alerts/Alert.svelte @@ -13,11 +13,13 @@ const pubkeys = switcher(type, { replies: note.repliesFrom, likes: note.likedBy, + zaps: note.zappedBy, }) const actionText = switcher(type, { replies: 'replied to your note', likes: 'liked your note', + zaps: 'zapped your note', }) let isOpen = false diff --git a/src/views/alerts/Alerts.svelte b/src/views/alerts/Alerts.svelte index 4da48837..45a922df 100644 --- a/src/views/alerts/Alerts.svelte +++ b/src/views/alerts/Alerts.svelte @@ -23,7 +23,12 @@ // Filter out alerts for which we failed to find the required context. The bug // is really upstream of this, but it's an easy fix const events = user.mute(database.alerts.all()) - .filter(e => e.replies.length > 0 || e.likedBy.length > 0 || e.isMention) + .filter(e => ( + e.replies.length > 0 + || e.likedBy.length > 0 + || e.zappedBy?.length > 0 + || e.isMention + )) notes = sortBy(e => -e.created_at, events).slice(0, limit) }) @@ -36,6 +41,8 @@
{#if note.replies.length > 0} + {:else if note.zappedBy?.length > 0} + {:else if note.likedBy.length > 0} {:else} diff --git a/src/views/notes/NoteDetail.svelte b/src/views/notes/NoteDetail.svelte index f3ac2504..1ade3994 100644 --- a/src/views/notes/NoteDetail.svelte +++ b/src/views/notes/NoteDetail.svelte @@ -56,7 +56,9 @@
{:else if note.pubkey}
- + + +
{/if}