mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Fix alerts
This commit is contained in:
parent
efac30809a
commit
9bdb707d27
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
npm run lint
|
npm run qa:lint
|
||||||
npm run check
|
npm run qa:check
|
||||||
|
|
||||||
|
13
README.md
13
README.md
@ -55,7 +55,6 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
- Put user detail in a modal?
|
- Put user detail in a modal?
|
||||||
- ReplaceState for settings modals?
|
- ReplaceState for settings modals?
|
||||||
- [ ] Mentions are sorta weird, usually mention self
|
- [ ] Mentions are sorta weird, usually mention self
|
||||||
- [ ] Alerts are not showing likes, just generally screwy. Maybe because I threadify before adding to the db?
|
|
||||||
- [ ] Change network tab to list relays the user is connected to
|
- [ ] Change network tab to list relays the user is connected to
|
||||||
- [ ] Sync mentions box and in-reply mentions
|
- [ ] Sync mentions box and in-reply mentions
|
||||||
- [ ] Add petnames for channels
|
- [ ] Add petnames for channels
|
||||||
@ -63,11 +62,17 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.2.10
|
||||||
|
|
||||||
|
- [x] Fixed likes not showing up in alerts
|
||||||
|
- [x] Raised threshold for pool to 2 so we don't have such a small amount of results
|
||||||
|
- [x] Wait for profile info on login, navigate to network by default
|
||||||
|
|
||||||
## 0.2.9
|
## 0.2.9
|
||||||
|
|
||||||
- [x] Fix a bug in pool.subscribe which was causing requests to wait for all connections
|
- [x] Fixed a bug in pool.subscribe which was causing requests to wait for all connections
|
||||||
- [x] Add typescript with pre-commit hook
|
- [x] Added typescript with pre-commit hook
|
||||||
- [x] Fix layout for chat, person pages
|
- [x] Fixed layout for chat, person pages
|
||||||
- [x] Parse relays for kind 3
|
- [x] Parse relays for kind 3
|
||||||
|
|
||||||
## 0.2.8
|
## 0.2.8
|
||||||
|
BIN
package-lock.json
generated
BIN
package-lock.json
generated
Binary file not shown.
@ -7,8 +7,10 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint src/*/** --quiet",
|
"qa:lint": "eslint src/*/** --quiet",
|
||||||
"check": "svelte-check --tsconfig ./tsconfig.json --threshold error"
|
"qa:check": "svelte-check --tsconfig ./tsconfig.json --threshold error",
|
||||||
|
"qa:all": "run-p qa:lint qa:check",
|
||||||
|
"watch": "find src -type f | entr -r npm run qa:all"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.1.0",
|
"@sveltejs/vite-plugin-svelte": "^1.1.0",
|
||||||
@ -36,6 +38,7 @@
|
|||||||
"hurdak": "github:ConsignCloud/hurdak",
|
"hurdak": "github:ConsignCloud/hurdak",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"nostr-tools": "^1.2.1",
|
"nostr-tools": "^1.2.1",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
"ramda": "^0.28.0",
|
"ramda": "^0.28.0",
|
||||||
"svelte-check": "^3.0.3",
|
"svelte-check": "^3.0.3",
|
||||||
"svelte-link-preview": "^0.3.3",
|
"svelte-link-preview": "^0.3.3",
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
import {displayPerson, isLike} from 'src/util/nostr'
|
import {displayPerson, isLike} from 'src/util/nostr'
|
||||||
import {timedelta, now} from 'src/util/misc'
|
import {timedelta, now} from 'src/util/misc'
|
||||||
import {keys, user, pool, getRelays} from 'src/agent'
|
import {keys, user, pool, getRelays} from 'src/agent'
|
||||||
import {modal, toast, settings, logUsage, alerts, messages} from "src/app"
|
import {modal, toast, settings, logUsage, alerts, messages, loadAppData} from "src/app"
|
||||||
import {routes} from "src/app/ui"
|
import {routes} from "src/app/ui"
|
||||||
import Anchor from 'src/partials/Anchor.svelte'
|
import Anchor from 'src/partials/Anchor.svelte'
|
||||||
|
import Content from 'src/partials/Content.svelte'
|
||||||
import Spinner from 'src/partials/Spinner.svelte'
|
import Spinner from 'src/partials/Spinner.svelte'
|
||||||
import Modal from 'src/partials/Modal.svelte'
|
import Modal from 'src/partials/Modal.svelte'
|
||||||
import SignUp from "src/views/SignUp.svelte"
|
import SignUp from "src/views/SignUp.svelte"
|
||||||
@ -74,9 +75,7 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if ($user) {
|
if ($user) {
|
||||||
alerts.load(getRelays(), $user.pubkey)
|
loadAppData($user.pubkey)
|
||||||
alerts.listen(getRelays(), $user.pubkey)
|
|
||||||
messages.listen(getRelays(), $user.pubkey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
@ -301,6 +300,13 @@
|
|||||||
<PubKeyLogin />
|
<PubKeyLogin />
|
||||||
{:else if $modal.type === 'person/settings'}
|
{:else if $modal.type === 'person/settings'}
|
||||||
<PersonSettings />
|
<PersonSettings />
|
||||||
|
{:else if $modal.type === 'message'}
|
||||||
|
<Content size="lg">
|
||||||
|
<div class="text-center">{$modal.message}</div>
|
||||||
|
{#if $modal.spinner}
|
||||||
|
<Spinner delay={0} />
|
||||||
|
{/if}
|
||||||
|
</Content>
|
||||||
{/if}
|
{/if}
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -192,17 +192,15 @@ const request = (relays, filters, {threshold = 2} = {}): Promise<Record<string,
|
|||||||
const eose = []
|
const eose = []
|
||||||
|
|
||||||
const attemptToComplete = () => {
|
const attemptToComplete = () => {
|
||||||
const done = (
|
const allEose = eose.length === relays.length
|
||||||
eose.length === relays.length
|
const atThreshold = eose.filter(url => relaysWithEvents.has(url)).length >= threshold
|
||||||
|| eose.filter(url => relaysWithEvents.has(url)).length >= threshold
|
const hardTimeout = Date.now() - now >= 5000
|
||||||
|| (
|
const softTimeout = (
|
||||||
Date.now() - now >= 1000
|
Date.now() - now >= 1000
|
||||||
&& eose.length > relays.length - Math.round(relays.length / 10)
|
&& eose.length > relays.length - Math.round(relays.length / 10)
|
||||||
)
|
)
|
||||||
|| Date.now() - now >= 5000
|
|
||||||
)
|
|
||||||
|
|
||||||
if (done) {
|
if (allEose || atThreshold || hardTimeout || softTimeout) {
|
||||||
agg.unsub()
|
agg.unsub()
|
||||||
resolve(events)
|
resolve(events)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {synced, batch, now} from 'src/util/misc'
|
import {groupBy, pluck, partition, propEq} from 'ramda'
|
||||||
import {isAlert} from 'src/util/nostr'
|
import {synced, timedelta, batch, now} from 'src/util/misc'
|
||||||
import {load as _load, listen as _listen, getMuffle, db} from 'src/agent'
|
import {isAlert, findReplyId} from 'src/util/nostr'
|
||||||
|
import {load as _load, listen as _listen, db} from 'src/agent'
|
||||||
import loaders from 'src/app/loaders'
|
import loaders from 'src/app/loaders'
|
||||||
import {threadify} from 'src/app'
|
import {annotate} from 'src/app'
|
||||||
|
|
||||||
let listener
|
let listener
|
||||||
|
|
||||||
@ -14,21 +15,29 @@ const onChunk = async (relays, pubkey, events) => {
|
|||||||
events = events.filter(e => isAlert(e, pubkey))
|
events = events.filter(e => isAlert(e, pubkey))
|
||||||
|
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
const context = await loaders.loadContext(relays, events, {threshold: 2})
|
const context = await loaders.loadContext(relays, events)
|
||||||
const notes = threadify(events, context, {muffle: getMuffle()})
|
const [likes, notes] = partition(propEq('kind', 7), events)
|
||||||
|
const annotatedNotes = notes.map(n => annotate(n, context))
|
||||||
|
const likesByParent = groupBy(findReplyId, likes)
|
||||||
|
const likedNotes = context
|
||||||
|
.filter(e => likesByParent[e.id])
|
||||||
|
.map(e => annotate({...e, likedBy: pluck('pubkey', likesByParent[e.id])}, context))
|
||||||
|
|
||||||
await db.table('alerts').bulkPut(notes)
|
await db.table('alerts').bulkPut(annotatedNotes.concat(likedNotes))
|
||||||
|
|
||||||
mostRecentAlert.update($t => events.reduce((t, e) => Math.max(t, e.created_at), $t))
|
mostRecentAlert.update($t => events.reduce((t, e) => Math.max(t, e.created_at), $t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const load = async (relays, pubkey) => {
|
const load = async (relays, pubkey) => {
|
||||||
const since = get(mostRecentAlert)
|
// Include an offset so we don't miss alerts on one relay but not another
|
||||||
|
const since = get(mostRecentAlert) - timedelta(30, 'days')
|
||||||
|
|
||||||
|
// Crank the threshold up since we can afford for this to be slow
|
||||||
const events = await _load(
|
const events = await _load(
|
||||||
relays,
|
relays,
|
||||||
{kinds: [1, 7], '#p': [pubkey], since, limit: 100},
|
{kinds: [1, 7], '#p': [pubkey], since, limit: 1000},
|
||||||
{threshold: 2}
|
{threshold: 10}
|
||||||
)
|
)
|
||||||
|
|
||||||
onChunk(relays, pubkey, events)
|
onChunk(relays, pubkey, events)
|
||||||
|
@ -14,6 +14,15 @@ import loaders from 'src/app/loaders'
|
|||||||
|
|
||||||
export {toast, modal, settings, alerts, messages, logUsage}
|
export {toast, modal, settings, alerts, messages, logUsage}
|
||||||
|
|
||||||
|
export const loadAppData = pubkey => {
|
||||||
|
return Promise.all([
|
||||||
|
loaders.loadNetwork(getRelays(), pubkey),
|
||||||
|
alerts.load(getRelays(), pubkey),
|
||||||
|
alerts.listen(getRelays(), pubkey),
|
||||||
|
messages.listen(getRelays(), pubkey),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: string}, usingExtension = false) => {
|
export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: string}, usingExtension = false) => {
|
||||||
if (privkey) {
|
if (privkey) {
|
||||||
keys.setPrivateKey(privkey)
|
keys.setPrivateKey(privkey)
|
||||||
@ -21,16 +30,18 @@ export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: strin
|
|||||||
keys.setPublicKey(pubkey)
|
keys.setPublicKey(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modal.set({type: 'message', message: "Loading your profile data...", spinner: true})
|
||||||
|
|
||||||
// Load network and start listening, but don't wait for it
|
// Load network and start listening, but don't wait for it
|
||||||
loaders.loadNetwork(getRelays(), pubkey),
|
loadAppData(pubkey)
|
||||||
alerts.load(getRelays(), pubkey),
|
|
||||||
alerts.listen(getRelays(), pubkey),
|
// Load our user so we can populate network and show profile info
|
||||||
messages.listen(getRelays(), pubkey)
|
await loaders.loadPeople(getRelays(), [pubkey])
|
||||||
|
|
||||||
// Not ideal, but the network tab depends on the user's social network being
|
// Not ideal, but the network tab depends on the user's social network being
|
||||||
// loaded, so put them on global when they first log in so we're not slowing
|
// loaded, so put them on global when they first log in so we're not slowing
|
||||||
// down users' first run experience too much
|
// down users' first run experience too much
|
||||||
navigate('/notes/global')
|
navigate('/notes/network')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addRelay = async relay => {
|
export const addRelay = async relay => {
|
||||||
@ -46,12 +57,8 @@ export const addRelay = async relay => {
|
|||||||
// Publish to the new set of relays
|
// Publish to the new set of relays
|
||||||
await cmd.setRelays(relays, relays)
|
await cmd.setRelays(relays, relays)
|
||||||
|
|
||||||
await Promise.all([
|
// Reload alerts, messages, etc
|
||||||
loaders.loadNetwork(relays, person.pubkey),
|
await loadAppData(person.pubkey)
|
||||||
alerts.load(relays, person.pubkey),
|
|
||||||
alerts.listen(relays, person.pubkey),
|
|
||||||
messages.listen(getRelays(), person.pubkey)
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +133,7 @@ export const annotate = (note, context) => {
|
|||||||
|
|
||||||
export const threadify = (events, context, {muffle = [], showReplies = true} = {}) => {
|
export const threadify = (events, context, {muffle = [], showReplies = true} = {}) => {
|
||||||
const contextById = createMap('id', events.concat(context))
|
const contextById = createMap('id', events.concat(context))
|
||||||
|
|
||||||
// Show parents when possible. For reactions, if there's no parent,
|
// Show parents when possible. For reactions, if there's no parent,
|
||||||
// throw it away. Sort by created date descending
|
// throw it away. Sort by created date descending
|
||||||
const notes = sortBy(
|
const notes = sortBy(
|
||||||
|
@ -2,8 +2,7 @@ import {uniqBy, prop, uniq, flatten, pluck, identity} from 'ramda'
|
|||||||
import {ensurePlural, createMap, chunk} from 'hurdak/lib/hurdak'
|
import {ensurePlural, createMap, chunk} from 'hurdak/lib/hurdak'
|
||||||
import {findReply, personKinds, Tags} from 'src/util/nostr'
|
import {findReply, personKinds, Tags} from 'src/util/nostr'
|
||||||
import {now, timedelta} from 'src/util/misc'
|
import {now, timedelta} from 'src/util/misc'
|
||||||
import {load, getPerson} from 'src/agent'
|
import {load, getPerson, getFollows} from 'src/agent'
|
||||||
import defaults from 'src/agent/defaults'
|
|
||||||
|
|
||||||
const getStalePubkeys = pubkeys => {
|
const getStalePubkeys = pubkeys => {
|
||||||
// If we're not reloading, only get pubkeys we don't already know about
|
// If we're not reloading, only get pubkeys we don't already know about
|
||||||
@ -28,17 +27,7 @@ const loadPeople = (relays, pubkeys, {kinds = personKinds, force = false, ...opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loadNetwork = async (relays, pubkey) => {
|
const loadNetwork = async (relays, pubkey) => {
|
||||||
// Get this user's profile to start with. This may update what relays
|
const tags = Tags.wrap(getFollows(pubkey))
|
||||||
// are available, so don't assign relays to a variable here.
|
|
||||||
const events = pubkey ? await loadPeople(relays, [pubkey], {force: true}) : []
|
|
||||||
let petnames = Tags.from(events.filter(e => e.kind === 3)).type("p").all()
|
|
||||||
|
|
||||||
// Default to some cool guys we know
|
|
||||||
if (petnames.length === 0) {
|
|
||||||
petnames = defaults.petnames
|
|
||||||
}
|
|
||||||
|
|
||||||
const tags = Tags.wrap(petnames)
|
|
||||||
|
|
||||||
// Use nip-2 recommended relays to load our user's second-order follows
|
// Use nip-2 recommended relays to load our user's second-order follows
|
||||||
await loadPeople(tags.relays(), tags.values().all())
|
await loadPeople(tags.relays(), tags.values().all())
|
||||||
|
@ -178,7 +178,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if suggestions.length > 0}
|
{#if suggestions.length > 0}
|
||||||
<div class="rounded border border-solid border-medium mt-2" in:fly={{y: 20}}>
|
<div class="rounded border border-solid border-medium mt-2 flex flex-col" in:fly={{y: 20}}>
|
||||||
{#each suggestions as person, i (person.pubkey)}
|
{#each suggestions as person, i (person.pubkey)}
|
||||||
<button
|
<button
|
||||||
class="py-2 px-4 cursor-pointer"
|
class="py-2 px-4 cursor-pointer"
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {uniqBy, prop} from 'ramda'
|
import {uniq} from 'ramda'
|
||||||
import {ellipsize, quantify} from 'hurdak/lib/hurdak'
|
import {ellipsize, quantify} from 'hurdak/lib/hurdak'
|
||||||
import Badge from "src/partials/Badge.svelte"
|
import Badge from "src/partials/Badge.svelte"
|
||||||
import {formatTimestamp} from 'src/util/misc'
|
import {formatTimestamp} from 'src/util/misc'
|
||||||
import {killEvent} from 'src/util/html'
|
import {killEvent} from 'src/util/html'
|
||||||
|
import {getPerson} from 'src/agent'
|
||||||
import {modal} from 'src/app'
|
import {modal} from 'src/app'
|
||||||
|
|
||||||
export let note
|
export let note
|
||||||
@ -26,11 +27,11 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="py-2 px-3 flex flex-col gap-2 text-white cursor-pointer transition-all
|
class="py-2 px-3 flex flex-col gap-2 text-white cursor-pointer transition-all
|
||||||
border border-solid border-black hover:border-medium hover:bg-dark"
|
border border-solid border-black hover:border-medium hover:bg-dark text-left"
|
||||||
on:click={() => modal.set({type: 'note/detail', note})}>
|
on:click={() => modal.set({type: 'note/detail', note})}>
|
||||||
<div class="flex gap-2 items-center justify-between relative">
|
<div class="flex gap-2 items-center justify-between relative">
|
||||||
<button class="cursor-pointer" on:click={openPopover}>
|
<button class="cursor-pointer" on:click={openPopover}>
|
||||||
{quantify(note.people.length, 'person', 'people')} liked your note.
|
{quantify(note.likedBy.length, 'person', 'people')} liked your note.
|
||||||
</button>
|
</button>
|
||||||
{#if isOpen}
|
{#if isOpen}
|
||||||
<button in:fly={{y: 20}} class="fixed inset-0 z-10" on:click={closePopover} />
|
<button in:fly={{y: 20}} class="fixed inset-0 z-10" on:click={closePopover} />
|
||||||
@ -39,8 +40,8 @@
|
|||||||
in:fly={{y: 20}}
|
in:fly={{y: 20}}
|
||||||
class="absolute top-0 mt-8 py-2 px-4 rounded border border-solid border-medium
|
class="absolute top-0 mt-8 py-2 px-4 rounded border border-solid border-medium
|
||||||
bg-dark grid grid-cols-3 gap-y-2 gap-x-4 z-20">
|
bg-dark grid grid-cols-3 gap-y-2 gap-x-4 z-20">
|
||||||
{#each uniqBy(prop('pubkey'), note.people) as person (person.pubkey)}
|
{#each uniq(note.likedBy) as pubkey}
|
||||||
<Badge {person} />
|
<Badge person={getPerson(pubkey)} />
|
||||||
{/each}
|
{/each}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import {fade} from 'svelte/transition'
|
import {fade} from 'svelte/transition'
|
||||||
import {Circle2} from 'svelte-loading-spinners'
|
import {Circle2} from 'svelte-loading-spinners'
|
||||||
|
|
||||||
|
export let delay = 1000
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="py-20 flex flex-col gap-4 items-center justify-center" in:fade={{delay: 1000}}>
|
<div class="py-20 flex flex-col gap-4 items-center justify-center" in:fade={{delay}}>
|
||||||
<slot />
|
<slot />
|
||||||
<Circle2 colorOuter="#CCC5B9" colorInner="#403D39" colorCenter="#EB5E28" />
|
<Circle2 colorOuter="#CCC5B9" colorInner="#403D39" colorCenter="#EB5E28" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
import {onMount} from 'svelte'
|
import {onMount} from 'svelte'
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {now, createScroller} from 'src/util/misc'
|
import {now, createScroller} from 'src/util/misc'
|
||||||
import {user, db} from 'src/agent'
|
import {db} from 'src/agent'
|
||||||
import {alerts} from 'src/app'
|
import {alerts} from 'src/app'
|
||||||
import Note from 'src/partials/Note.svelte'
|
import Note from 'src/partials/Note.svelte'
|
||||||
import Content from 'src/partials/Content.svelte'
|
import Content from 'src/partials/Content.svelte'
|
||||||
import Like from 'src/partials/Like.svelte'
|
import Like from 'src/partials/Like.svelte'
|
||||||
|
|
||||||
let limit = 0
|
let limit = 0
|
||||||
let annotatedNotes = []
|
let notes = []
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
alerts.lastCheckedAlerts.set(now())
|
alerts.lastCheckedAlerts.set(now())
|
||||||
@ -19,37 +19,24 @@
|
|||||||
limit += 10
|
limit += 10
|
||||||
|
|
||||||
const events = await db.table('alerts').toArray()
|
const events = await db.table('alerts').toArray()
|
||||||
const notes = events.filter(e => e.kind === 1)
|
|
||||||
const likes = events.filter(e => e.kind === 7)
|
|
||||||
|
|
||||||
// Combine likes of a single note. Remove grandchild likes
|
notes = sortBy(e => -e.created_at, events).slice(0, limit)
|
||||||
const likesById = {}
|
|
||||||
for (const like of likes.filter(e => e.parent?.pubkey === $user.pubkey)) {
|
|
||||||
if (!likesById[like.parent.id]) {
|
|
||||||
likesById[like.parent.id] = {...like.parent, people: []}
|
|
||||||
}
|
|
||||||
|
|
||||||
likesById[like.parent.id].people.push(like.person)
|
|
||||||
}
|
|
||||||
|
|
||||||
annotatedNotes = sortBy(
|
|
||||||
e => -e.created_at,
|
|
||||||
notes
|
|
||||||
.filter(e => e && e.pubkey !== $user.pubkey)
|
|
||||||
.concat(Object.values(likesById))
|
|
||||||
).slice(0, limit)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Content>
|
<Content>
|
||||||
{#each annotatedNotes as e (e.id)}
|
{#each notes as e (e.id)}
|
||||||
<div in:fly={{y: 20}}>
|
<div in:fly={{y: 20}}>
|
||||||
{#if e.people}
|
{#if e.likedBy}
|
||||||
<Like note={e} />
|
<Like note={e} />
|
||||||
{:else}
|
{:else}
|
||||||
<Note note={e} />
|
<Note note={e} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<Content size="lg" class="text-center">
|
||||||
|
No alerts found - check back later!
|
||||||
|
</Content>
|
||||||
{/each}
|
{/each}
|
||||||
</Content>
|
</Content>
|
||||||
|
Loading…
Reference in New Issue
Block a user