import util from "../../plugins/utils"; export default { data() { return { pollQuestion: "", pollAnswers: [], pollResponseRelations: null, pollEndRelations: null, pollEndTs: null, pollIsDisclosed: true, } }, mounted() { this.$matrix.on("Room.timeline", this.pollMixinOnEvent); this.pollQuestion = (this.event && this.event.getContent()["org.matrix.msc3381.poll.start"]["question"]["body"]) || ""; this.updateAnswers(); }, destroyed() { this.$matrix.off("Room.timeline", this.pollMixinOnEvent); }, beforeDestroy() { if (this.pollResponseRelations) { this.pollResponseRelations.off('Relations.add', this.onAddRelation); this.pollResponseRelations = null; } if (this.pollEndRelations) { this.pollEndRelations.off('Relations.add', this.onAddRelation); this.pollEndRelations = null; } }, methods: { updateAnswers() { let answers = (this.event && this.event.getContent()["org.matrix.msc3381.poll.start"]["answers"]) || []; var answerMap = {}; var answerArray = []; answers.forEach(a => { let text = a["org.matrix.msc1767.text"]; let answer = {id: a.id, text: text, numVotes: 0, percentage: 0} answerMap[a.id] = answer; answerArray.push(answer); }); // Kind of poll this.pollIsDisclosed = (this.event && this.event.getContent()["org.matrix.msc3381.poll.start"]["kind"] != "org.matrix.msc3381.poll.undisclosed") || false; // Look for poll end this.pollEndRelations = this.timelineSet.getRelationsForEvent( this.event.getId(), 'm.reference', 'org.matrix.msc3381.poll.end' ); if (this.pollEndRelations) { const endMessages = this.pollEndRelations.getRelations() || []; if (endMessages.length > 0) { this.pollEndTs = endMessages[endMessages.length - 1].getTs(); } } // Process votes this.pollResponseRelations = this.timelineSet.getRelationsForEvent( this.event.getId(), 'm.reference', 'org.matrix.msc3381.poll.response' ); var userVotes = {}; if (this.pollResponseRelations) { const votes = this.pollResponseRelations.getRelations() || []; for (const vote of votes) { //const emoji = r.getRelation().key; if (this.pollEndTs && vote.getTs() > this.pollEndTs) { continue; // Invalid vote, after poll was closed. } const sender = vote.getSender(); const answersFromThisUser = vote.getContent()["org.matrix.msc3381.poll.response"]["answers"] || []; if (answersFromThisUser.length == 0) { delete userVotes[sender]; } else { userVotes[sender] = answersFromThisUser; } } } var totalVotes = 0; for (const [user, answersFromThisUser] of Object.entries(userVotes)) { for (const a of answersFromThisUser) { if (answerMap[a]) { answerMap[a].numVotes += 1; totalVotes += 1; if (user == this.$matrix.currentUserId) { answerMap[a].hasMyVote = true; } } } } // Update percentage answerArray.forEach(a => { a.percentage = parseInt(((100 * a.numVotes) / totalVotes).toFixed(0)); }); this.pollAnswers = answerArray; }, pollAnswer(id) { if (this.pollIsClosed) { return; } util .sendPollAnswer( this.$matrix.matrixClient, this.room.roomId, [id], this.event ) .catch((err) => { console.log("Failed to send:", err); }); }, pollClose() { util .closePoll( this.$matrix.matrixClient, this.room.roomId, this.event ) .catch((err) => { console.log("Failed to send:", err); }); }, onAddRelation(ignoredevent) { this.updateAnswers(); }, pollMixinOnEvent(event) { if (event.getRoomId() !== this.room.roomId) { return; // Not for this room } if ( event.getType().startsWith("org.matrix.msc3381.poll.")) { this.updateAnswers(); } }, }, computed: { pollIsClosed() { return this.pollEndTs != null && this.pollEndTs !== undefined; }, userCanClosePoll() { return this.room && this.room.currentState && this.room.currentState.maySendRedactionForEvent(this.event, this.$matrix.currentUserId); }, userHasVoted() { return this.pollAnswers.some(a => a.hasMyVote); }, pollIsAdmin() { // Admins can view results of not-yet-closed undisclosed polls. const me = this.room && this.room.getMember(this.$matrix.currentUserId); let isAdmin = me && this.room.currentState && this.room.currentState.hasSufficientPowerLevelFor("redact", me.powerLevel); return isAdmin; } }, watch: { pollResponseRelations: { handler(newValue, oldValue) { if (oldValue) { oldValue.off('Relations.add', this.onAddRelation); } if (newValue) { newValue.on('Relations.add', this.onAddRelation); } this.updateAnswers(); }, immediate: true }, pollEndRelations: { handler(newValue, oldValue) { if (oldValue) { oldValue.off('Relations.add', this.onAddRelation); } if (newValue) { newValue.on('Relations.add', this.onAddRelation); } this.updateAnswers(); }, immediate: true } } }