185 lines
5.5 KiB
JavaScript
185 lines
5.5 KiB
JavaScript
|
|
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
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|