refactor actions and mutations, each in its own file.

This commit is contained in:
fiatjaf 2020-11-17 23:12:18 -03:00
parent 83b95e1b13
commit f689d9535b
3 changed files with 215 additions and 221 deletions

127
web-client/src/actions.js Normal file
View File

@ -0,0 +1,127 @@
// vuex store actions
import {verifySignature, publishEvent} from './helpers'
import {db} from './globals'
export default {
async receivedEvent(store, {event, context}) {
if (!verifySignature(event)) {
console.log('received event with invalid signature', event)
return
}
switch (event.kind) {
case 0: // setMetadata
break
case 1: // textNote
store.commit('receivedTextNote', {event, context})
break
case 2: // recommendServer
let host = event.content
try {
new URL(host)
} catch (err) {
// ignore invalid URLs
return
}
// ignore if we already know this
// this prevents infinite loops and overwriting of our settings
if (await db.relays.get(host)) {
return
}
if (context === 'requested') {
// someone we're just browsing
await db.relays.put({
host,
policy: '',
recommender: event.pubkey
})
} else {
// someone we're following
await db.relays.put({
host,
policy: 'r',
recommender: event.pubkey
})
}
store.commit('loadedRelays', await db.relays.toArray())
break
}
},
async addRelay(store, relay) {
await db.relays.put(relay)
store.commit('loadedRelays', await db.relays.toArray())
},
async updateRelay(store, {key, host, policy}) {
let relay = {host, policy}
await db.relays.update(key, relay)
store.commit('loadedRelays', await db.relays.toArray())
},
async browseProfile(store, pubkey) {
await store.state.haveEventSource
for (let i = 0; i < store.getters.readServers.length; i++) {
let host = store.getters.readServers[i]
window.fetch(host + '/request_user?session=' + store.state.session, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({pubkey})
})
}
},
async browseNote(store, id) {
await store.state.haveEventSource
for (let i = 0; i < store.getters.readServers.length; i++) {
let host = store.getters.readServers[i]
window.fetch(host + '/request_note?session=' + store.state.session, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({id})
})
}
},
async publishMetadata(store, meta) {
let evt = await publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 0,
content: JSON.stringify(meta)
},
store.state.key,
store.getters.writeServers
)
db.cachedmetadata.put({pubkey: evt.pubkey, time: evt.created_at, meta})
},
async publishNote(store, text) {
let event = await publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 1,
content: text.trim()
},
store.state.key,
store.getters.writeServers
)
db.mynotes.put(event)
store.commit('receivedTextNote', {event, context: 'happening'})
},
async recommendRelay(store, host) {
publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 2,
content: host
},
store.state.key,
store.getters.writeServers
)
}
}

View File

@ -0,0 +1,73 @@
// vuex store mutations
import {pubkeyFromPrivate} from './helpers'
import {db} from './globals'
export default {
setInit(state, {relays, key, following, home, metadata}) {
state.relays = relays
state.key = key
state.following = following.concat(
// always be following thyself
pubkeyFromPrivate(state.key)
)
state.home = home
state.metadata = metadata
},
gotEventSource(state, session) {
state.haveEventSource.resolve()
state.session = session
},
loadedRelays(state, relays) {
state.relays = relays
},
follow(state, key) {
state.following.push(key)
db.following.put({pubkey: key})
},
unfollow(state, key) {
state.following.splice(state.following.indexOf(key), 1)
db.following.delete(key)
},
receivedSetMetadata(state, {event: evt, context}) {
let meta = JSON.parse(evt.content)
let storeable = {
pubkey: evt.pubkey,
time: evt.created_at,
meta
}
if (context === 'requested') {
// just someone we're viewing
if (!state.metadata.has(evt.pubkey)) {
state.metadata.set(evt.pubkey, meta)
}
} else if (context === 'happening') {
// an update from someone we follow that happened just now
state.metadata.set(evt.pubkey, meta)
db.cachedmetadata.put(storeable)
} else if (context === 'history') {
// someone we follow, but an old update
db.cachedmetadata.get(evt.pubkey).then(data => {
if (data.time < storeable.time) {
db.cachedmetadata.put(storeable)
}
})
}
},
receivedTextNote(state, {event: evt, context}) {
if (context === 'requested') {
state.browsing.set(evt.id, evt)
state.browsing.set('from:' + evt.pubkey, evt)
if (evt.ref && evt.ref.length) {
state.browsing.set('rel:' + evt.ref, evt)
}
} else {
state.home.set(evt.id + ':' + evt.created_at, evt)
}
},
updatePublishStatus(state, {id, time, host, status}) {
if (!(id in state.publishStatus)) state.publishStatus[id] = {}
state.publishStatus[id][host] = {time, status}
}
}

View File

@ -2,19 +2,16 @@ import {createStore, createLogger} from 'vuex'
import {SortedMap} from 'insort'
import LRU from 'quick-lru'
import {
pubkeyFromPrivate,
makeRandom32,
verifySignature,
publishEvent
} from './helpers'
import {pubkeyFromPrivate, makeRandom32} from './helpers'
import {db} from './globals'
import actions from './actions'
import mutations from './mutations'
export default createStore({
plugins: (process.env.NODE_ENV !== 'production'
? [createLogger()]
: []
).concat([init, listener, relayLoader, publishStatusLoader]),
).concat([init, listener, publishStatusLoader]),
state() {
let relays = [
{
@ -53,176 +50,8 @@ export default createStore({
.filter(({policy}) => policy.indexOf('r') !== -1)
.map(({host}) => host)
},
mutations: {
setInit(state, {relays, key, following, home, metadata}) {
state.relays = relays
state.key = key
state.following = following.concat(
// always be following thyself
pubkeyFromPrivate(state.key)
)
state.home = home
state.metadata = metadata
},
gotEventSource(state, session) {
state.haveEventSource.resolve()
state.session = session
},
addRelay(state, relay) {
db.relays.put(relay)
},
updateRelay(state, {key, host, policy}) {
let relay = {host, policy}
db.relays.update(key, relay)
},
deleteRelay(state, host) {
db.relays.delete(host)
},
loadedRelays(state, relays) {
state.relays = relays
},
follow(state, key) {
state.following.push(key)
db.following.put({pubkey: key})
},
unfollow(state, key) {
state.following.splice(state.following.indexOf(key), 1)
db.following.delete(key)
},
receivedEvent(state, {event: evt, context}) {
if (!verifySignature(evt)) {
console.log('received event with invalid signature', evt)
return
}
switch (evt.kind) {
case 0: // setMetadata
let meta = JSON.parse(evt.content)
let storeable = {
pubkey: evt.pubkey,
time: evt.created_at,
meta
}
if (context === 'requested') {
// just someone we're viewing
if (!state.metadata.has(evt.pubkey)) {
state.metadata.set(evt.pubkey, meta)
}
} else if (context === 'happening') {
// an update from someone we follow that happened just now
state.metadata.set(evt.pubkey, meta)
db.cachedmetadata.put(storeable)
} else if (context === 'history') {
// someone we follow, but an old update
db.cachedmetadata.get(evt.pubkey).then(data => {
if (data.time < storeable.time) {
db.cachedmetadata.put(storeable)
}
})
}
break
case 1: // textNote
if (context === 'requested') {
state.browsing.set(evt.id, evt)
state.browsing.set('from:' + evt.pubkey, evt)
if (evt.ref && evt.ref.length) {
state.browsing.set('rel:' + evt.ref, evt)
}
} else {
state.home.set(evt.id + ':' + evt.created_at, evt)
}
break
case 2: // recommendServer
let host = evt.content
if (context === 'requested') {
// someone we're just browsing
db.relays.put({
host,
policy: '',
recommender: evt.pubkey
})
} else {
// someone we're following
db.relays.put({
host,
policy: 'r',
recommender: evt.pubkey
})
}
break
}
},
updatePublishStatus(state, {id, time, host, status}) {
if (!(id in state.publishStatus)) state.publishStatus[id] = {}
state.publishStatus[id][host] = {time, status}
}
},
actions: {
async browseProfile(store, pubkey) {
await store.state.haveEventSource
for (let i = 0; i < store.getters.readServers.length; i++) {
let host = store.getters.readServers[i]
window.fetch(host + '/request_user?session=' + store.state.session, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({pubkey})
})
}
},
async browseNote(store, id) {
await store.state.haveEventSource
for (let i = 0; i < store.getters.readServers.length; i++) {
let host = store.getters.readServers[i]
window.fetch(host + '/request_note?session=' + store.state.session, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({id})
})
}
},
async publishMetadata(store, meta) {
let evt = await publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 0,
content: JSON.stringify(meta)
},
store.state.key,
store.getters.writeServers
)
db.cachedmetadata.put({pubkey: evt.pubkey, time: evt.created_at, meta})
},
async publishNote(store, text) {
let evt = await publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 1,
content: text.trim()
},
store.state.key,
store.getters.writeServers
)
db.mynotes.put(evt)
store.commit('receivedEvent', {event: evt, context: 'happening'})
},
recommendRelay(store, host) {
publishEvent(
{
pubkey: store.getters.pubKeyHex,
created_at: Math.round(new Date().getTime() / 1000),
kind: 2,
content: host
},
store.state.key,
store.getters.writeServers
)
}
}
mutations,
actions
})
async function init(store) {
@ -274,19 +103,6 @@ async function init(store) {
})
}
function relayLoader(store) {
db.relays.hook('creating', loadRelays)
db.relays.hook('updating', loadRelays)
db.relays.hook('deleting', loadRelays)
function loadRelays() {
setTimeout(async () => {
let relays = await db.relays.toArray()
store.commit('loadedRelays', relays)
}, 1)
}
}
function publishStatusLoader(store) {
db.publishlog.hook('creating', (_, {id, time, host, status}) => {
store.commit('updatePublishStatus', {id, time, host, status})
@ -296,29 +112,14 @@ function publishStatusLoader(store) {
function listener(store) {
var ess = new Map()
db.relays.hook('creating', host => {
listenToRelay(host)
})
db.relays.hook('updating', (mod, _, obj) => {
if (obj.policy.indexOf('r') !== -1) {
stopListeningToRelay(obj.host)
}
if (!mod.policy || mod.policy.indexOf('r') !== -1) {
listenToRelay(mod.host || obj.host)
}
})
db.relays.hook('deleting', host => {
stopListeningToRelay(host)
})
db.following.hook('creating', () => {
restartListeners()
})
store.subscribe(mutation => {
if (mutation.type === 'setInit') restartListeners()
switch (mutation.type) {
case 'setInit':
case 'loadedRelays':
case 'follow':
case 'unfollow':
restartListeners()
}
})
function restartListeners() {
@ -329,13 +130,6 @@ function listener(store) {
store.getters.readServers.forEach(listenToRelay)
}
function stopListeningToRelay(host) {
let es = ess.get(host)
if (!es) return
es.close()
ess.delete(host)
}
function listenToRelay(host) {
if (store.state.following.length === 0) return
@ -349,7 +143,7 @@ function listener(store) {
ess.set(host, es)
es.onerror = err => {
console.log(`${host}/listen_updates error: ${err}`)
console.log(`${host}/listen_updates error`, err)
es.close()
ess.delete(host)
}
@ -361,7 +155,7 @@ function listener(store) {
})
;['history', 'happening', 'requested'].forEach(context => {
es.addEventListener(context, e => {
store.commit('receivedEvent', {
store.dispatch('receivedEvent', {
event: JSON.parse(e.data),
context
})