akkoma-fe/src/modules/statuses.js

216 lines
5.8 KiB
JavaScript
Raw Normal View History

import { map, slice, sortBy, toInteger, each, find, flatten, maxBy, last, merge, max } from 'lodash'
2016-10-28 13:59:49 +00:00
import moment from 'moment'
2016-10-30 15:12:35 +00:00
import apiService from '../services/api/api.service.js'
2016-11-15 09:35:16 +00:00
// import parse from '../services/status_parser/status_parser.js'
2016-10-26 17:03:55 +00:00
export const defaultState = {
2016-10-26 17:03:55 +00:00
allStatuses: [],
maxId: 0,
timelines: {
public: {
statuses: [],
faves: [],
visibleStatuses: [],
newStatusCount: 0,
maxId: 0,
2016-11-06 16:44:05 +00:00
minVisibleId: 0,
loading: false
2016-10-26 17:03:55 +00:00
},
publicAndExternal: {
statuses: [],
faves: [],
visibleStatuses: [],
newStatusCount: 0,
maxId: 0,
2016-11-06 16:44:05 +00:00
minVisibleId: 0,
loading: false
2016-10-26 17:03:55 +00:00
},
friends: {
statuses: [],
faves: [],
visibleStatuses: [],
newStatusCount: 0,
maxId: 0,
2016-11-06 16:44:05 +00:00
minVisibleId: 0,
loading: false
2016-10-26 17:03:55 +00:00
}
}
}
2016-11-15 09:35:16 +00:00
export const prepareStatus = (status) => {
// Parse nsfw tags
if (status.nsfw === undefined) {
const nsfwRegex = /#nsfw/i
status.nsfw = !!status.text.match(nsfwRegex)
}
// Set created_at_parsed to initial value
status.created_at_parsed = status.created_at
return status
}
2016-10-28 13:59:49 +00:00
const updateTimestampsInStatuses = (statuses) => {
2016-10-28 23:38:41 +00:00
return map(statuses, (statusoid) => {
const status = statusoid.retweeted_status || statusoid
2016-10-28 13:59:49 +00:00
// Parse date
status.created_at_parsed = moment(status.created_at).fromNow()
return status
})
}
const statusType = (status) => {
if (status.is_post_verb) {
return 'status'
}
2016-11-13 21:09:27 +00:00
if (status.retweeted_status) {
return 'retweet'
}
2016-11-13 21:09:27 +00:00
if (typeof status.uri === 'string' && status.uri.match(/fave/)) {
return 'favorite'
}
2016-11-13 21:40:33 +00:00
return 'unknown'
}
2016-11-13 21:54:49 +00:00
2016-11-15 09:35:16 +00:00
export const findMaxId = (...args) => {
return (maxBy(flatten(args), 'id') || {}).id
2016-11-13 21:40:33 +00:00
}
const mergeOrAdd = (arr, item) => {
const oldItem = find(arr, {id: item.id})
if (oldItem) {
// We already have this, so only merge the new info.
merge(oldItem, item)
return oldItem
} else {
// This is a new item, prepare it
prepareStatus(item)
arr.push(item)
return item
}
}
export const mutations = {
addNewStatuses (state, { statuses, showImmediately = false, timeline }) {
const allStatuses = state.allStatuses
2016-11-13 21:09:27 +00:00
const timelineObject = state.timelines[timeline]
// Set the maxId to the new id if it's larger.
const updateMaxId = ({id}) => {
timelineObject.maxId = max([id, timelineObject.maxId])
}
const addStatus = (status, showImmediately, addToTimeline = true) => {
// Remember the current amount of statuses
// We need that to calculate new status count.
const prevLength = timelineObject.statuses.length
2016-11-15 09:35:16 +00:00
updateMaxId(status)
2016-11-15 09:35:16 +00:00
status = mergeOrAdd(allStatuses, status)
// Some statuses should only be added to the global status repository.
if (addToTimeline) {
mergeOrAdd(timelineObject.statuses, status)
}
if (showImmediately) {
// Add it directly to the visibleStatuses, don't change
// newStatusCount
mergeOrAdd(timelineObject.visibleStatuses, status)
} else {
// Just change newStatuscount
timelineObject.newStatusCount += (timelineObject.statuses.length - prevLength)
}
return status
}
2016-11-18 15:05:04 +00:00
const favoriteStatus = (favorite) => {
const status = find(allStatuses, { id: toInteger(favorite.in_reply_to_status_id) })
if (status) {
status.fave_num += 1
}
return status
}
const processors = {
'status': (status) => {
addStatus(status, showImmediately)
},
'retweet': (status) => {
// RetweetedStatuses are never shown immediately
const retweetedStatus = addStatus(status.retweeted_status, false, false)
const retweet = addStatus(status, showImmediately)
retweet.retweeted_status = retweetedStatus
},
'favorite': (status) => {
updateMaxId(status)
favoriteStatus(status)
}
}
each(statuses, (status) => {
const type = statusType(status)
processors[type](status)
})
// Keep the visible statuses sorted
timelineObject.visibleStatuses = sortBy(timelineObject.visibleStatuses, ({id}) => -id)
timelineObject.statuses = sortBy(timelineObject.statuses, ({id}) => -id)
timelineObject.minVisibleId = (last(timelineObject.statuses) || {}).id
},
showNewStatuses (state, { timeline }) {
const oldTimeline = (state.timelines[timeline])
oldTimeline.newStatusCount = 0
oldTimeline.visibleStatuses = slice(oldTimeline.statuses, 0, 50)
},
updateTimestamps (state) {
updateTimestampsInStatuses(state.allStatuses)
},
setFavorited (state, { status, value }) {
const newStatus = find(state.allStatuses, status)
newStatus.favorited = value
},
2016-11-13 16:09:16 +00:00
setRetweeted (state, { status, value }) {
const newStatus = find(state.allStatuses, status)
newStatus.repeated = value
},
setLoading (state, { timeline, value }) {
state.timelines[timeline].loading = value
},
setNsfw (state, { id, nsfw }) {
2016-11-07 17:47:38 +00:00
const newStatus = find(state.allStatuses, { id })
newStatus.nsfw = nsfw
}
}
2016-10-26 17:03:55 +00:00
const statuses = {
state: defaultState,
2016-10-30 15:12:35 +00:00
actions: {
favorite ({ rootState, commit }, status) {
// Optimistic favoriting...
commit('setFavorited', { status, value: true })
apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
},
unfavorite ({ rootState, commit }, status) {
// Optimistic favoriting...
commit('setFavorited', { status, value: false })
apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
2016-11-13 16:09:16 +00:00
},
retweet ({ rootState, commit }, status) {
// Optimistic retweeting...
commit('setRetweeted', { status, value: true })
apiService.retweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
2016-10-30 15:12:35 +00:00
}
},
mutations
2016-10-26 17:03:55 +00:00
}
export default statuses