Implement follow/unfollow

This commit is contained in:
styppo 2023-01-12 18:56:56 +00:00
parent 90a2abc7a3
commit a9f3f79dbf
No known key found for this signature in database
GPG Key ID: 3AAA685C50724C28
8 changed files with 58 additions and 16 deletions

View File

@ -141,8 +141,7 @@ export default {
try { try {
const event = this.buildEvent() const event = this.buildEvent()
await this.app.signEvent(event) await this.app.signEvent(event)
//this.nostr.sendEvent(event) this.nostr.publish(event)
console.log('Publishing', event)
this.reset() this.reset()
this.$emit('publish', event) this.$emit('publish', event)

View File

@ -1,11 +1,10 @@
<template> <template>
<div v-if="app.isSignedIn" class="following"> <div v-if="app.isSignedIn && contacts?.length" class="following">
<div class="following-wrapper"> <div class="following-wrapper">
<div class="following-header"> <div class="following-header">
<h3>Following</h3> <h3>Following</h3>
</div> </div>
<div <div
v-if="contacts?.length"
class="following-body" class="following-body"
> >
<UserCard <UserCard

View File

@ -47,7 +47,7 @@ export default {
}) })
}) })
await useAppStore().signEvent(event) await useAppStore().signEvent(event)
useNostrStore().sendEvent(event) useNostrStore().publish(event)
this.$emit('complete', { this.$emit('complete', {
pubkey: account.pubkey, pubkey: account.pubkey,

View File

@ -3,6 +3,7 @@
v-if="app.isSignedIn" v-if="app.isSignedIn"
class="btn btn-sm" class="btn btn-sm"
:class="{'btn-primary': !isFollowing}" :class="{'btn-primary': !isFollowing}"
@click="toggleFollow"
> >
{{ isFollowing ? 'Unfollow' : 'Follow' }} {{ isFollowing ? 'Unfollow' : 'Follow' }}
</button> </button>
@ -11,6 +12,7 @@
<script> <script>
import {useNostrStore} from 'src/nostr/NostrStore' import {useNostrStore} from 'src/nostr/NostrStore'
import {useAppStore} from 'stores/App' import {useAppStore} from 'stores/App'
import Event, {EventKind, TagType} from 'src/nostr/model/Event'
export default { export default {
name: 'FollowButton', name: 'FollowButton',
@ -27,12 +29,53 @@ export default {
} }
}, },
computed: { computed: {
contacts() {
return this.nostr.getContacts(this.app.myPubkey)
},
isFollowing() { isFollowing() {
// TODO improve // TODO improve
const contacts = this.nostr.getContacts(this.app.myPubkey) return this.contacts?.length && this.contacts.find(contact => contact.pubkey === this.pubkey)
return contacts?.length && contacts.find(contact => contact.pubkey === this.pubkey) },
} },
} methods: {
// TODO Move this logic somewhere else
buildEvent(contacts) {
return Event.fresh({
pubkey: this.app.myPubkey,
kind: EventKind.CONTACT,
tags: this.buildTags(contacts),
content: '',
})
},
buildTags(contacts) {
const tags = []
for (const contact of contacts) {
tags.push([TagType.PUBKEY, contact.pubkey])
}
return tags
},
async updateContacts(contacts) {
const event = this.buildEvent(contacts)
await this.app.signEvent(event)
this.nostr.publish(event)
},
toggleFollow() {
return this.isFollowing
? this.unfollow()
: this.follow()
},
async follow() {
const contacts = [].concat(this.contacts || []) // Clone array
contacts.push({pubkey: this.pubkey})
await this.updateContacts(contacts)
},
async unfollow() {
const contacts = [].concat(this.contacts || []) // Clone array
const idx = contacts.findIndex(contact => contact.pubkey === this.pubkey)
contacts.splice(idx, 1)
await this.updateContacts(contacts)
},
},
} }
</script> </script>

View File

@ -57,7 +57,7 @@ export default class FetchQueue extends Observable {
if (!filteredIds.length) return if (!filteredIds.length) return
console.log(`Fetching ${ids.length}/${Object.keys(this.queue).length} ${this.subId}s`, ids) console.log(`Fetching ${filteredIds.length}/${Object.keys(this.queue).length} ${this.subId}s`, ids)
this.fetching = true this.fetching = true
this.retryInterval = setInterval(this.fetch.bind(this), this.retryDelay) this.retryInterval = setInterval(this.fetch.bind(this), this.retryDelay)

View File

@ -69,6 +69,7 @@ export const useNostrStore = defineStore('nostr', {
this.contactQueue = contactQueue(this.client, 'queue') this.contactQueue = contactQueue(this.client, 'queue')
this.contactQueue.on('event', this.addEvent.bind(this)) this.contactQueue.on('event', this.addEvent.bind(this))
}, },
addEvent(event, relay = null) { addEvent(event, relay = null) {
// console.log(`[EVENT] from ${relay}`, event) // console.log(`[EVENT] from ${relay}`, event)
@ -119,7 +120,7 @@ export const useNostrStore = defineStore('nostr', {
return !!this.seenBy[id] return !!this.seenBy[id]
}, },
sendEvent(event) { publish(event) {
this.addEvent(event) this.addEvent(event)
return this.client.publish(event) return this.client.publish(event)
}, },

View File

@ -61,7 +61,7 @@ export default class Event {
this.pubkey = opts.pubkey this.pubkey = opts.pubkey
this.created_at = opts.createdAt || opts.created_at this.created_at = opts.createdAt || opts.created_at
this.kind = opts.kind this.kind = opts.kind
this.tags = Event.parseTags(opts.tags || []) this.tags = opts.tags || []
this.content = opts.content this.content = opts.content
this.sig = opts.sig this.sig = opts.sig
} }
@ -99,11 +99,11 @@ export default class Event {
} }
pubkeyTags() { pubkeyTags() {
return this.tags.filter(tag => tag.type === TagType.PUBKEY) return Event.parseTags(this.tags).filter(tag => tag.type === TagType.PUBKEY)
} }
eventTags() { eventTags() {
return this.tags.filter(tag => tag.type === TagType.EVENT) return Event.parseTags(this.tags).filter(tag => tag.type === TagType.EVENT)
} }
pubkeyRefs() { pubkeyRefs() {

View File

@ -1,4 +1,4 @@
import {EventKind, EventRefs, TagType} from 'src/nostr/model/Event' import Event, {EventKind, EventRefs, TagType} from 'src/nostr/model/Event'
import {isEmoji} from 'src/utils/utils' import {isEmoji} from 'src/utils/utils'
export default class Note { export default class Note {
@ -21,7 +21,7 @@ export default class Note {
author: event.pubkey, author: event.pubkey,
createdAt: event.createdAt, createdAt: event.createdAt,
content, content,
tags: event.tags, tags: Event.parseTags(event.tags),
}) })
} }