Move poll state handling to its own module

This commit is contained in:
Shpuld Shpludson 2019-06-20 13:02:04 +00:00
parent eca533aab6
commit e5e9bb27f3
6 changed files with 96 additions and 34 deletions

View File

@ -3,26 +3,33 @@ import { forEach, map } from 'lodash'
export default { export default {
name: 'Poll', name: 'Poll',
props: ['poll', 'statusId'], props: ['pollId'],
components: { Timeago }, components: { Timeago },
data () { data () {
return { return {
loading: false, loading: false,
choices: [], choices: []
refreshInterval: null
} }
}, },
created () { mounted () {
this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000) this.$store.dispatch('trackPoll', this.pollId)
// Initialize choices to booleans and set its length to match options
this.choices = this.poll.options.map(_ => false)
}, },
destroyed () { destroyed () {
clearTimeout(this.refreshInterval) this.$store.dispatch('untrackPoll', this.pollId)
}, },
computed: { computed: {
poll () {
const storePoll = this.$store.state.polls.pollsObject[this.pollId]
return storePoll || {}
},
options () {
return (this.poll && this.poll.options) || []
},
expiresAt () {
return (this.poll && this.poll.expires_at) || 0
},
expired () { expired () {
return Date.now() > Date.parse(this.poll.expires_at) return Date.now() > Date.parse(this.expiresAt)
}, },
loggedIn () { loggedIn () {
return this.$store.state.users.currentUser return this.$store.state.users.currentUser
@ -33,9 +40,6 @@ export default {
totalVotesCount () { totalVotesCount () {
return this.poll.votes_count return this.poll.votes_count
}, },
expiresAt () {
return Date.parse(this.poll.expires_at).toLocaleString()
},
containerClass () { containerClass () {
return { return {
loading: this.loading loading: this.loading
@ -55,11 +59,6 @@ export default {
} }
}, },
methods: { methods: {
refreshPoll () {
if (this.expired) return
this.fetchPoll()
this.refreshInterval = setTimeout(this.refreshPoll, 30 * 1000)
},
percentageForOption (count) { percentageForOption (count) {
return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100) return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
}, },

View File

@ -2,7 +2,7 @@
<div class="poll" v-bind:class="containerClass"> <div class="poll" v-bind:class="containerClass">
<div <div
class="poll-option" class="poll-option"
v-for="(option, index) in poll.options" v-for="(option, index) in options"
:key="index" :key="index"
> >
<div v-if="showResults" :title="resultTitle(option)" class="option-result"> <div v-if="showResults" :title="resultTitle(option)" class="option-result">
@ -50,7 +50,7 @@
{{totalVotesCount}} {{ $t("polls.votes") }}&nbsp;·&nbsp; {{totalVotesCount}} {{ $t("polls.votes") }}&nbsp;·&nbsp;
</div> </div>
<i18n :path="expired ? 'polls.expired' : 'polls.expires_in'"> <i18n :path="expired ? 'polls.expired' : 'polls.expires_in'">
<Timeago :time="this.poll.expires_at" :auto-update="60" :now-threshold="0" /> <Timeago :time="this.expiresAt" :auto-update="60" :now-threshold="0" />
</i18n> </i18n>
</div> </div>
</div> </div>

View File

@ -124,7 +124,7 @@
</div> </div>
<div v-if="status.poll && status.poll.options"> <div v-if="status.poll && status.poll.options">
<poll :poll="status.poll" :status-id="status.id" /> <poll :poll-id="status.poll.id" />
</div> </div>
<div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body"> <div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">

View File

@ -14,6 +14,7 @@ import authFlowModule from './modules/auth_flow.js'
import mediaViewerModule from './modules/media_viewer.js' import mediaViewerModule from './modules/media_viewer.js'
import oauthTokensModule from './modules/oauth_tokens.js' import oauthTokensModule from './modules/oauth_tokens.js'
import reportsModule from './modules/reports.js' import reportsModule from './modules/reports.js'
import pollsModule from './modules/polls.js'
import VueI18n from 'vue-i18n' import VueI18n from 'vue-i18n'
@ -72,7 +73,8 @@ const persistedStateOptions = {
authFlow: authFlowModule, authFlow: authFlowModule,
mediaViewer: mediaViewerModule, mediaViewer: mediaViewerModule,
oauthTokens: oauthTokensModule, oauthTokens: oauthTokensModule,
reports: reportsModule reports: reportsModule,
polls: pollsModule
}, },
plugins: [persistedState, pushNotifications], plugins: [persistedState, pushNotifications],
strict: false // Socket modifies itself, let's ignore this for now. strict: false // Socket modifies itself, let's ignore this for now.

73
src/modules/polls.js Normal file
View File

@ -0,0 +1,73 @@
import { each, merge } from 'lodash'
import { set } from 'vue'
const polls = {
state: {
// Contains key = id, value = number of trackers for this poll
trackedPolls: {},
pollsObject: {}
},
mutations: {
addNewStatuses (state, { statuses }) {
each(statuses, status => {
if (status.poll) {
set(state.pollsObject, status.poll.id, status.poll)
}
})
},
mergePoll (state, poll) {
state.pollsObject[poll.id] = merge(state.pollsObject[poll.id], poll)
},
trackPoll (state, pollId) {
const currentValue = state.trackedPolls[pollId]
if (currentValue) {
set(state.trackedPolls, pollId, currentValue + 1)
} else {
set(state.trackedPolls, pollId, 1)
}
},
untrackPoll (state, pollId) {
const currentValue = state.trackedPolls[pollId]
if (currentValue) {
set(state.trackedPolls, pollId, currentValue - 1)
} else {
set(state.trackedPolls, pollId, 0)
}
}
},
actions: {
updatePoll ({ rootState, commit }, pollId) {
return rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
commit('mergePoll', poll)
return poll
})
},
updateTrackedPoll ({ rootState, dispatch, commit }, pollId) {
rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
setTimeout(() => {
if (rootState.polls.trackedPolls[pollId]) {
dispatch('updateTrackedPoll', pollId)
}
}, 30 * 1000)
commit('mergePoll', poll)
})
},
trackPoll ({ rootState, commit, dispatch }, pollId) {
if (!rootState.polls.trackedPolls[pollId]) {
setTimeout(() => dispatch('updateTrackedPoll', pollId), 30 * 1000)
}
commit('trackPoll', pollId)
},
untrackPoll ({ commit }, pollId) {
commit('untrackPoll', pollId)
},
votePoll ({ rootState, commit }, { id, pollId, choices }) {
return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
commit('mergePoll', poll)
return poll
})
}
}
}
export default polls

View File

@ -582,18 +582,6 @@ const statuses = {
]).then(([favoritedByUsers, rebloggedByUsers]) => ]).then(([favoritedByUsers, rebloggedByUsers]) =>
commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers }) commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers })
) )
},
votePoll ({ rootState, commit }, { id, pollId, choices }) {
return rootState.api.backendInteractor.vote(pollId, choices).then(poll => {
commit('updateStatusWithPoll', { id, poll })
return poll
})
},
refreshPoll ({ rootState, commit }, { id, pollId }) {
return rootState.api.backendInteractor.fetchPoll(pollId).then(poll => {
commit('updateStatusWithPoll', { id, poll })
return poll
})
} }
}, },
mutations mutations