327 lines
9.8 KiB
JavaScript
327 lines
9.8 KiB
JavaScript
import Vue from 'vue'
|
|
import Vuex from 'vuex'
|
|
import Micropub from 'micropub-helper';
|
|
import EventSource from 'eventsource'
|
|
import _ from "lodash"
|
|
|
|
Vue.use(Vuex)
|
|
|
|
export default new Vuex.Store({
|
|
state() {
|
|
let newState = {
|
|
channels: [],
|
|
timeline: {items: [], paging: {}},
|
|
channel: {},
|
|
logged_in: false,
|
|
micropubEndpoint: '',
|
|
microsubEndpoint: '/microsub',
|
|
channelCreatorIsOpen: false,
|
|
searchPopupIsOpen: false,
|
|
searchItems: [],
|
|
eventSource: null,
|
|
globalTimeline: {items: []},
|
|
debug: false,
|
|
debugItem: {},
|
|
debugVisible: false
|
|
};
|
|
let loginData = JSON.parse(window.localStorage.getItem('login_data'))
|
|
if (loginData) {
|
|
newState = {...newState, ...loginData}
|
|
newState.logged_in = loginData.access_token && loginData.access_token.length > 0
|
|
}
|
|
let endpoints = JSON.parse(window.localStorage.getItem('endpoints'))
|
|
if (endpoints) {
|
|
newState = {...newState, ...endpoints}
|
|
}
|
|
return newState
|
|
},
|
|
|
|
mutations: {
|
|
newChannels(state, channels) {
|
|
state.channels = channels
|
|
},
|
|
newTimeline(state, {channel, timeline}) {
|
|
// find the channel matching the selected uid
|
|
channel = _.find(state.channels, item => item.uid === channel.uid)
|
|
state.channel = channel
|
|
state.timeline = timeline
|
|
},
|
|
newAccessToken(state, {me, access_token, scope}) {
|
|
state.logged_in = true
|
|
state.scope = scope
|
|
state.me = me
|
|
state.access_token = access_token
|
|
},
|
|
clearTimeline(state, {channel}) {
|
|
state.channel = channel
|
|
state.timeline = {
|
|
items: [],
|
|
paging: {}
|
|
}
|
|
},
|
|
setChannelCreatorState(state, open) {
|
|
state.channelCreatorIsOpen = open
|
|
},
|
|
setSearchPopupState(state, open) {
|
|
state.searchPopupIsOpen = open
|
|
state.searchItems = []
|
|
},
|
|
newEndpoints(state, endpoints) {
|
|
state.micropubEndpoint = endpoints.micropubEndpoint
|
|
state.microsubEndpoint = endpoints.microsubEndpoint
|
|
},
|
|
createEventSource(state, url) {
|
|
if (state.eventSource !== null) {
|
|
state.eventSource.close()
|
|
}
|
|
state.eventSource = new EventSource(state.microsubEndpoint + url, {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
}
|
|
})
|
|
state.eventSource.addEventListener('open', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
})
|
|
state.eventSource.addEventListener('ping', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
})
|
|
state.eventSource.addEventListener('message', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
})
|
|
state.eventSource.addEventListener('error', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
if (evt.message === "network error") {
|
|
state.eventSource.close()
|
|
}
|
|
})
|
|
state.eventSource.addEventListener('new item', evt => {
|
|
try {
|
|
let newItemMsg = JSON.parse(evt.data)
|
|
if (state.channel.uid === newItemMsg.channel) {
|
|
state.timeline.items = [newItemMsg.item, ...state.timeline.items]
|
|
}
|
|
state.globalTimeline.items = _.takeRight([...state.globalTimeline.items, newItemMsg.item], 10)
|
|
} catch (e) {
|
|
// eslint-disable-next-line
|
|
console.log(e)
|
|
}
|
|
})
|
|
state.eventSource.addEventListener('new item in channel', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
let msg = JSON.parse(evt.data)
|
|
let channel = _.find(state.channels, item => item.uid === msg.uid)
|
|
if (channel) {
|
|
channel.unread = msg.unread
|
|
}
|
|
})
|
|
|
|
state.eventSource.addEventListener('new channel', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
let msg = JSON.parse(evt.data)
|
|
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
|
if (!channel) {
|
|
state.channels.push(msg.channel)
|
|
}
|
|
})
|
|
|
|
state.eventSource.addEventListener('update channel', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
let msg = JSON.parse(evt.data)
|
|
let channel = _.find(state.channels, it => it.uid === msg.channel.uid)
|
|
if (channel) {
|
|
channel.name = msg.channel.name
|
|
}
|
|
})
|
|
|
|
state.eventSource.addEventListener('delete channel', evt => {
|
|
// eslint-disable-next-line
|
|
console.log(evt)
|
|
let msg = JSON.parse(evt.data)
|
|
state.channels = _.remove(state.channels, it => it.uid === msg.uid)
|
|
})
|
|
},
|
|
newSearchResults(state, items) {
|
|
state.searchItems = items
|
|
},
|
|
openDebugPopup(state, item) {
|
|
state.debugItem = item
|
|
state.debugVisible = true
|
|
},
|
|
closeDebugPopup(state) {
|
|
state.debugVisible = false
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
fetchChannels({commit}) {
|
|
fetch(this.state.microsubEndpoint + '?action=channels', {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(response => {
|
|
commit('newChannels', response.channels)
|
|
})
|
|
},
|
|
switchChannel({commit}, channel) {
|
|
commit('clearTimeline', {channel: channel})
|
|
},
|
|
fetchTimeline({commit}, channel) {
|
|
let url = this.state.microsubEndpoint + '?action=timeline&channel=' + channel.uid
|
|
if (channel.after) {
|
|
url += '&after=' + channel.after;
|
|
}
|
|
if (channel.before) {
|
|
url += '&before=' + channel.before;
|
|
}
|
|
fetch(url, {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(response => {
|
|
commit('newTimeline', {channel: channel, timeline: response})
|
|
})
|
|
},
|
|
saveEndpoints({commit}, endpoints) {
|
|
window.localStorage.setItem('endpoints', JSON.stringify(endpoints))
|
|
commit('newEndpoints', endpoints)
|
|
},
|
|
tokenResponse({commit}, response) {
|
|
window.localStorage.setItem('login_data', JSON.stringify(response))
|
|
commit('newAccessToken', response)
|
|
},
|
|
isLoggedIn({commit}, response) {
|
|
// eslint-disable-next-line
|
|
console.log(response)
|
|
commit('newAccessToken', response)
|
|
},
|
|
markRead(x, {channel, entry}) {
|
|
let entries = '';
|
|
if (Array.isArray(entry)) {
|
|
entries = _(entry).map(uid => '&entry[]=' + encodeURIComponent(uid)).join("")
|
|
} else {
|
|
entries = '&entry=' + encodeURIComponent(entry)
|
|
}
|
|
let url = this.state.microsubEndpoint + '?action=timeline&method=mark_read&channel=' + encodeURIComponent(channel) + entries;
|
|
return fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
}
|
|
})
|
|
},
|
|
configQuery (_, key) {
|
|
let micropub = new Micropub({
|
|
token: this.state.access_token,
|
|
micropubEndpoint: this.state.micropubEndpoint
|
|
})
|
|
return micropub.query(key)
|
|
},
|
|
fetchSyndicationTargets() {
|
|
return this.dispatch('configQuery', 'syndicate-to')
|
|
},
|
|
fetchDestinations() {
|
|
return this.dispatch('configQuery', 'destination')
|
|
},
|
|
micropubPost(_, mf2post) {
|
|
let micropub = new Micropub({
|
|
token: this.state.access_token,
|
|
micropubEndpoint: this.state.micropubEndpoint
|
|
})
|
|
return micropub.create(mf2post)
|
|
},
|
|
micropubLikeOf(_, url) {
|
|
this.dispatch('micropubPost', {
|
|
'type': ['h-entry'],
|
|
'properties': {
|
|
'like-of': [url]
|
|
}
|
|
})
|
|
},
|
|
openChannelCreator({commit}) {
|
|
commit('setChannelCreatorState', true)
|
|
},
|
|
closeChannelCreator({commit}) {
|
|
commit('setChannelCreatorState', false)
|
|
},
|
|
openSearch({commit}) {
|
|
commit('setSearchPopupState', true)
|
|
},
|
|
closeSearch({commit}) {
|
|
commit('setSearchPopupState', false)
|
|
},
|
|
startQuery({state, commit}, query) {
|
|
let channel = 'global'
|
|
if (state.channel !== null && state.channel.uid !== null && state.channel.uid !== 'home') {
|
|
channel = state.channel.uid
|
|
}
|
|
return fetch(this.state.microsubEndpoint + '?action=search&channel='+channel+'&query='+query, {
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
},
|
|
method: 'POST'
|
|
})
|
|
.then(response => response.json())
|
|
.then(response => {
|
|
if (response.items) {
|
|
commit('newSearchResults', response.items)
|
|
return { error: false }
|
|
} else {
|
|
commit('newSearchResults', [])
|
|
return { error: response.error }
|
|
}
|
|
})
|
|
},
|
|
createChannel(x, name) {
|
|
let url = this.state.microsubEndpoint + '?action=channels&name=' + encodeURIComponent(name)
|
|
return fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': 'Bearer ' + this.state.access_token
|
|
}
|
|
}).then(() => {
|
|
this.dispatch('fetchChannels')
|
|
})
|
|
},
|
|
bottomReached() {
|
|
// eslint-disable-next-line
|
|
console.log('bottomReached')
|
|
|
|
let items = this.state.timeline.items
|
|
// eslint-disable-next-line
|
|
console.log(items)
|
|
let uids = _(items).reject('_is_read').map('_id').value()
|
|
// eslint-disable-next-line
|
|
console.log(uids)
|
|
|
|
items.forEach((item) => {
|
|
if (item && !item._is_read) {
|
|
item._is_read = true
|
|
}
|
|
})
|
|
if (uids.length > 0) {
|
|
return this.dispatch('markRead', {channel: this.state.channel.uid, 'entry': uids})
|
|
}
|
|
},
|
|
startEventListening({commit}, url) {
|
|
commit('createEventSource', url)
|
|
},
|
|
openDebug({commit}, item) {
|
|
return commit('openDebugPopup', item)
|
|
},
|
|
closeDebug({commit}) {
|
|
return commit('closeDebugPopup')
|
|
},
|
|
}
|
|
})
|