mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Refactored duplicate card section (#9730)
* Refactored duplicate card section * Updated to new computed methods
This commit is contained in:
276
website/client/components/chat/chatCard.vue
Normal file
276
website/client/components/chat/chatCard.vue
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<template lang="pug">
|
||||||
|
div
|
||||||
|
.mentioned-icon(v-if='isUserMentioned')
|
||||||
|
.message-hidden(v-if='msg.flagCount === 1 && user.contributor.admin') Message flagged once, not hidden
|
||||||
|
.message-hidden(v-if='msg.flagCount > 1 && user.contributor.admin') Message hidden
|
||||||
|
.card-body
|
||||||
|
h3.leader(
|
||||||
|
:class='userLevelStyle(msg)',
|
||||||
|
@click="showMemberModal(msg.uuid)",
|
||||||
|
v-b-tooltip.hover.top="('contributor' in msg) ? msg.contributor.text : ''",
|
||||||
|
)
|
||||||
|
| {{msg.user}}
|
||||||
|
.svg-icon(v-html="tierIcon", v-if='showShowTierStyle')
|
||||||
|
p.time {{msg.timestamp | timeAgo}}
|
||||||
|
.text(v-markdown='msg.text')
|
||||||
|
hr
|
||||||
|
.action(@click='like()', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
||||||
|
.svg-icon(v-html="icons.like")
|
||||||
|
span(v-if='!msg.likes[user._id]') {{ $t('like') }}
|
||||||
|
span(v-if='msg.likes[user._id]') {{ $t('liked') }}
|
||||||
|
// @TODO make copyAsTodo work in Tavern, guilds, party (inbox can be done later)
|
||||||
|
span.action(v-if='!inbox', @click='copyAsTodo(msg)')
|
||||||
|
.svg-icon(v-html="icons.copy")
|
||||||
|
| {{$t('copyAsTodo')}}
|
||||||
|
// @TODO make copyAsTodo work in the inbox
|
||||||
|
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)')
|
||||||
|
.svg-icon(v-html="icons.report")
|
||||||
|
| {{$t('report')}}
|
||||||
|
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
|
||||||
|
span.action(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove()')
|
||||||
|
.svg-icon(v-html="icons.delete")
|
||||||
|
| {{$t('delete')}}
|
||||||
|
span.action.float-right.liked(v-if='likeCount > 0')
|
||||||
|
.svg-icon(v-html="icons.liked")
|
||||||
|
| + {{ likeCount }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~client/assets/scss/tiers.scss';
|
||||||
|
|
||||||
|
.mentioned-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #bda8ff;
|
||||||
|
box-shadow: 0 1px 1px 0 rgba(26, 24, 29, 0.12);
|
||||||
|
position: absolute;
|
||||||
|
right: -.5em;
|
||||||
|
top: -.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-hidden {
|
||||||
|
margin-left: 1.5em;
|
||||||
|
margin-top: 1em;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
.leader {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 { // this is the user name
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
.svg-icon {
|
||||||
|
width: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #878190;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #4e4a57;
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
display: inline-block;
|
||||||
|
color: #878190;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.liked:hover {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action .svg-icon {
|
||||||
|
margin-right: .2em;
|
||||||
|
width: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
color: #A5A1AC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action.active, .active .svg-icon {
|
||||||
|
color: #46a7d9
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
|
import moment from 'moment';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import escapeRegExp from 'lodash/escapeRegExp';
|
||||||
|
|
||||||
|
import markdownDirective from 'client/directives/markdown';
|
||||||
|
import { mapState } from 'client/libs/store';
|
||||||
|
import styleHelper from 'client/mixins/styleHelper';
|
||||||
|
|
||||||
|
import deleteIcon from 'assets/svg/delete.svg';
|
||||||
|
import copyIcon from 'assets/svg/copy.svg';
|
||||||
|
import likeIcon from 'assets/svg/like.svg';
|
||||||
|
import likedIcon from 'assets/svg/liked.svg';
|
||||||
|
import reportIcon from 'assets/svg/report.svg';
|
||||||
|
import tier1 from 'assets/svg/tier-1.svg';
|
||||||
|
import tier2 from 'assets/svg/tier-2.svg';
|
||||||
|
import tier3 from 'assets/svg/tier-3.svg';
|
||||||
|
import tier4 from 'assets/svg/tier-4.svg';
|
||||||
|
import tier5 from 'assets/svg/tier-5.svg';
|
||||||
|
import tier6 from 'assets/svg/tier-6.svg';
|
||||||
|
import tier7 from 'assets/svg/tier-7.svg';
|
||||||
|
import tier8 from 'assets/svg/tier-mod.svg';
|
||||||
|
import tier9 from 'assets/svg/tier-staff.svg';
|
||||||
|
import tierNPC from 'assets/svg/tier-npc.svg';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['msg', 'inbox', 'groupId'],
|
||||||
|
mixins: [styleHelper],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
copyingMessage: {},
|
||||||
|
icons: Object.freeze({
|
||||||
|
like: likeIcon,
|
||||||
|
copy: copyIcon,
|
||||||
|
report: reportIcon,
|
||||||
|
delete: deleteIcon,
|
||||||
|
liked: likedIcon,
|
||||||
|
tier1,
|
||||||
|
tier2,
|
||||||
|
tier3,
|
||||||
|
tier4,
|
||||||
|
tier5,
|
||||||
|
tier6,
|
||||||
|
tier7,
|
||||||
|
tier8,
|
||||||
|
tier9,
|
||||||
|
tierNPC,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
directives: {
|
||||||
|
markdown: markdownDirective,
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
timeAgo (value) {
|
||||||
|
return moment(value).fromNow();
|
||||||
|
},
|
||||||
|
date (value) {
|
||||||
|
// @TODO: Add user preference
|
||||||
|
return moment(value).toDate();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({user: 'user.data'}),
|
||||||
|
isUserMentioned () {
|
||||||
|
const message = this.msg;
|
||||||
|
let user = this.user;
|
||||||
|
|
||||||
|
if (message.hasOwnProperty('highlight')) return message.highlight;
|
||||||
|
|
||||||
|
message.highlight = false;
|
||||||
|
let messagetext = message.text.toLowerCase();
|
||||||
|
let username = user.profile.name;
|
||||||
|
let mentioned = messagetext.indexOf(username.toLowerCase());
|
||||||
|
let escapedUsername = escapeRegExp(username);
|
||||||
|
let pattern = `@${escapedUsername}([^\w]|$){1}`;
|
||||||
|
|
||||||
|
if (mentioned === -1) return message.highlight;
|
||||||
|
|
||||||
|
let preceedingchar = messagetext.substring(mentioned - 1, mentioned);
|
||||||
|
if (mentioned === 0 || preceedingchar.trim() === '' || preceedingchar === '@') {
|
||||||
|
let regex = new RegExp(pattern, 'i');
|
||||||
|
message.highlight = regex.test(messagetext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message.highlight;
|
||||||
|
},
|
||||||
|
likeCount () {
|
||||||
|
const message = this.msg;
|
||||||
|
if (!message.likes) return 0;
|
||||||
|
|
||||||
|
let likeCount = 0;
|
||||||
|
for (let key in message.likes) {
|
||||||
|
let like = message.likes[key];
|
||||||
|
if (like) likeCount += 1;
|
||||||
|
}
|
||||||
|
return likeCount;
|
||||||
|
},
|
||||||
|
showShowTierStyle () {
|
||||||
|
const message = this.msg;
|
||||||
|
const isContributor = Boolean(message.contributor && message.contributor.level);
|
||||||
|
const isNPC = Boolean(message.backer && message.backer.npc);
|
||||||
|
return isContributor || isNPC;
|
||||||
|
},
|
||||||
|
tierIcon () {
|
||||||
|
const message = this.msg;
|
||||||
|
const isNPC = Boolean(message.backer && message.backer.npc);
|
||||||
|
if (isNPC) {
|
||||||
|
return this.icons.tierNPC;
|
||||||
|
}
|
||||||
|
return this.icons[`tier${message.contributor.level}`];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async like () {
|
||||||
|
let message = cloneDeep(this.msg);
|
||||||
|
|
||||||
|
await this.$store.dispatch('chat:like', {
|
||||||
|
groupId: this.groupId,
|
||||||
|
chatId: message.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!message.likes[this.user._id]) {
|
||||||
|
message.likes[this.user._id] = true;
|
||||||
|
} else {
|
||||||
|
message.likes[this.user._id] = !message.likes[this.user._id];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('messaged-liked', message);
|
||||||
|
},
|
||||||
|
copyAsTodo (message) {
|
||||||
|
// @TODO: Move to Habitica Event
|
||||||
|
this.copyingMessage = message;
|
||||||
|
this.$root.$emit('bv::show::modal', 'copyAsTodo');
|
||||||
|
},
|
||||||
|
async report () {
|
||||||
|
this.$root.$emit('habitica::report-chat', {
|
||||||
|
message: this.msg,
|
||||||
|
groupId: this.groupId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async remove () {
|
||||||
|
if (!confirm(this.$t('areYouSureDeleteMessage'))) return;
|
||||||
|
|
||||||
|
const message = this.msg;
|
||||||
|
this.$emit('message-removed', message);
|
||||||
|
|
||||||
|
if (this.inbox) {
|
||||||
|
axios.delete(`/api/v3/user/messages/${message.id}`);
|
||||||
|
this.$delete(this.user.inbox.messages, message.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.$store.dispatch('chat:deleteChat', {
|
||||||
|
groupId: this.groupId,
|
||||||
|
chatId: message.id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showMemberModal (memberId) {
|
||||||
|
this.$emit('show-member-modal', memberId);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -2,9 +2,8 @@
|
|||||||
.container
|
.container
|
||||||
.row
|
.row
|
||||||
.col-12
|
.col-12
|
||||||
copy-as-todo-modal(:copying-message='copyingMessage', :group-name='groupName', :group-id='groupId')
|
copy-as-todo-modal(:group-name='groupName', :group-id='groupId')
|
||||||
report-flag-modal
|
report-flag-modal
|
||||||
|
|
||||||
div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)')
|
div(v-for="(msg, index) in messages", v-if='chat && canViewFlag(msg)')
|
||||||
// @TODO: is there a different way to do these conditionals? This creates an infinite loop
|
// @TODO: is there a different way to do these conditionals? This creates an infinite loop
|
||||||
//.hr(v-if='displayDivider(msg)')
|
//.hr(v-if='displayDivider(msg)')
|
||||||
@@ -19,78 +18,22 @@
|
|||||||
@click.native="showMemberModal(msg.uuid)",
|
@click.native="showMemberModal(msg.uuid)",
|
||||||
)
|
)
|
||||||
.card(:class='inbox ? "col-8" : "col-10"')
|
.card(:class='inbox ? "col-8" : "col-10"')
|
||||||
.mentioned-icon(v-if='isUserMentioned(msg)')
|
chat-card(
|
||||||
.message-hidden(v-if='msg.flagCount === 1 && user.contributor.admin') Message flagged once, not hidden
|
:msg='msg',
|
||||||
.message-hidden(v-if='msg.flagCount > 1 && user.contributor.admin') Message hidden
|
:inbox='inbox',
|
||||||
.card-body
|
:groupId='groupId',
|
||||||
h3.leader(
|
@messaged-liked='messageLiked',
|
||||||
:class='userLevelStyle(msg)',
|
@message-removed='messageRemoved',
|
||||||
@click="showMemberModal(msg.uuid)",
|
@show-member-modal='showMemberModal')
|
||||||
v-b-tooltip.hover.top="('contributor' in msg) ? msg.contributor.text : ''",
|
|
||||||
)
|
|
||||||
| {{msg.user}}
|
|
||||||
.svg-icon(v-html="getTierIcon(msg)", v-if='showShowTierStyle(msg)')
|
|
||||||
p.time {{msg.timestamp | timeAgo}}
|
|
||||||
.text(v-markdown='msg.text')
|
|
||||||
hr
|
|
||||||
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
|
||||||
.svg-icon(v-html="icons.like")
|
|
||||||
span(v-if='!msg.likes[user._id]') {{ $t('like') }}
|
|
||||||
span(v-if='msg.likes[user._id]') {{ $t('liked') }}
|
|
||||||
// @TODO make copyAsTodo work in Tavern, guilds, party (inbox can be done later)
|
|
||||||
span.action(v-if='!inbox', @click='copyAsTodo(msg)')
|
|
||||||
.svg-icon(v-html="icons.copy")
|
|
||||||
| {{$t('copyAsTodo')}}
|
|
||||||
// @TODO make copyAsTodo work in the inbox
|
|
||||||
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"', @click='report(msg)')
|
|
||||||
.svg-icon(v-html="icons.report")
|
|
||||||
| {{$t('report')}}
|
|
||||||
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
|
|
||||||
span.action(v-if='msg.uuid === user._id || inbox || user.contributor.admin', @click='remove(msg, index)')
|
|
||||||
.svg-icon(v-html="icons.delete")
|
|
||||||
| {{$t('delete')}}
|
|
||||||
span.action.float-right.liked(v-if='likeCount(msg) > 0')
|
|
||||||
.svg-icon(v-html="icons.liked")
|
|
||||||
| + {{ likeCount(msg) }}
|
|
||||||
// @TODO can we avoid duplicating all this code? Cannot we just push everything
|
|
||||||
// to the right if the user is the author?
|
|
||||||
// Maybe we just create two sub components instead
|
|
||||||
.row(v-if='user._id === msg.uuid')
|
.row(v-if='user._id === msg.uuid')
|
||||||
.card(:class='inbox ? "col-8" : "col-10"')
|
.card(:class='inbox ? "col-8" : "col-10"')
|
||||||
.mentioned-icon(v-if='isUserMentioned(msg)')
|
chat-card(
|
||||||
.message-hidden(v-if='msg.flagCount === 1 && user.contributor.admin') Message flagged once, not hidden
|
:msg='msg',
|
||||||
.message-hidden(v-if='msg.flagCount > 1 && user.contributor.admin') Message hidden
|
:inbox='inbox',
|
||||||
.card-body
|
:groupId='groupId',
|
||||||
h3.leader(
|
@messaged-liked='messageLiked',
|
||||||
:class='userLevelStyle(msg)',
|
@message-removed='messageRemoved',
|
||||||
@click="showMemberModal(msg.uuid)",
|
@show-member-modal='showMemberModal')
|
||||||
v-b-tooltip.hover.top="('contributor' in msg) ? msg.contributor.text : ''",
|
|
||||||
)
|
|
||||||
| {{msg.user}}
|
|
||||||
.svg-icon(v-html="getTierIcon(msg)", v-if='showShowTierStyle(msg)')
|
|
||||||
p.time {{msg.timestamp | timeAgo}}
|
|
||||||
.text(v-markdown='msg.text')
|
|
||||||
hr
|
|
||||||
.action(@click='like(msg, index)', v-if='msg.likes', :class='{active: msg.likes[user._id]}')
|
|
||||||
.svg-icon(v-html="icons.like")
|
|
||||||
span(v-if='!msg.likes[user._id]') {{ $t('like') }}
|
|
||||||
span(v-if='msg.likes[user._id]') {{ $t('liked') }}
|
|
||||||
// @TODO make copyAsTodo work in Tavern, guilds, party (inbox can be done later)
|
|
||||||
span.action(v-if='!inbox', @click='copyAsTodo(msg)')
|
|
||||||
.svg-icon(v-html="icons.copy")
|
|
||||||
| {{$t('copyAsTodo')}}
|
|
||||||
// @TODO make copyAsTodo work in the inbox
|
|
||||||
span.action(v-if='user.flags.communityGuidelinesAccepted', @click='report(msg)')
|
|
||||||
span.action(v-if='!inbox && user.flags.communityGuidelinesAccepted', @click='report(msg)')
|
|
||||||
.svg-icon(v-html="icons.report")
|
|
||||||
| {{$t('report')}}
|
|
||||||
// @TODO make flagging/reporting work in the inbox. NOTE: it must work even if the communityGuidelines are not accepted and it MUST work for messages that you have SENT as well as received. -- Alys
|
|
||||||
span.action(v-if='msg.uuid === user._id', @click='remove(msg, index)')
|
|
||||||
.svg-icon(v-html="icons.delete")
|
|
||||||
| {{$t('delete')}}
|
|
||||||
span.action.float-right.liked(v-if='likeCount(msg) > 0')
|
|
||||||
.svg-icon(v-html="icons.liked")
|
|
||||||
| + {{ likeCount(msg) }}
|
|
||||||
div(:class='inbox ? "col-4" : "col-2"')
|
div(:class='inbox ? "col-4" : "col-2"')
|
||||||
avatar(
|
avatar(
|
||||||
v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected',
|
v-if='cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected',
|
||||||
@@ -103,38 +46,6 @@
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '~client/assets/scss/colors.scss';
|
@import '~client/assets/scss/colors.scss';
|
||||||
@import '~client/assets/scss/tiers.scss';
|
|
||||||
|
|
||||||
.leader {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #878190;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mentioned-icon {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #bda8ff;
|
|
||||||
box-shadow: 0 1px 1px 0 rgba(26, 24, 29, 0.12);
|
|
||||||
position: absolute;
|
|
||||||
right: -.5em;
|
|
||||||
top: -.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 { // this is the user name
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
.svg-icon {
|
|
||||||
width: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hr {
|
.hr {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -161,86 +72,28 @@
|
|||||||
.card {
|
.card {
|
||||||
margin-bottom: .5em;
|
margin-bottom: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #4e4a57;
|
|
||||||
text-align: left !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
|
||||||
display: inline-block;
|
|
||||||
color: #878190;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.liked:hover {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action .svg-icon {
|
|
||||||
margin-right: .2em;
|
|
||||||
width: 16px;
|
|
||||||
display: inline-block;
|
|
||||||
color: #A5A1AC;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action.active, .active .svg-icon {
|
|
||||||
color: #46a7d9
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-hidden {
|
|
||||||
margin-left: 1.5em;
|
|
||||||
margin-top: 1em;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import axios from 'axios';
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import escapeRegExp from 'lodash/escapeRegExp';
|
import findIndex from 'lodash/findIndex';
|
||||||
import markdownDirective from 'client/directives/markdown';
|
|
||||||
import Avatar from '../avatar';
|
|
||||||
import styleHelper from 'client/mixins/styleHelper';
|
|
||||||
|
|
||||||
|
import Avatar from '../avatar';
|
||||||
import copyAsTodoModal from './copyAsTodoModal';
|
import copyAsTodoModal from './copyAsTodoModal';
|
||||||
import reportFlagModal from './reportFlagModal';
|
import reportFlagModal from './reportFlagModal';
|
||||||
|
import chatCard from './chatCard';
|
||||||
import deleteIcon from 'assets/svg/delete.svg';
|
|
||||||
import copyIcon from 'assets/svg/copy.svg';
|
|
||||||
import likeIcon from 'assets/svg/like.svg';
|
|
||||||
import likedIcon from 'assets/svg/liked.svg';
|
|
||||||
import reportIcon from 'assets/svg/report.svg';
|
|
||||||
import tier1 from 'assets/svg/tier-1.svg';
|
|
||||||
import tier2 from 'assets/svg/tier-2.svg';
|
|
||||||
import tier3 from 'assets/svg/tier-3.svg';
|
|
||||||
import tier4 from 'assets/svg/tier-4.svg';
|
|
||||||
import tier5 from 'assets/svg/tier-5.svg';
|
|
||||||
import tier6 from 'assets/svg/tier-6.svg';
|
|
||||||
import tier7 from 'assets/svg/tier-7.svg';
|
|
||||||
import tier8 from 'assets/svg/tier-mod.svg';
|
|
||||||
import tier9 from 'assets/svg/tier-staff.svg';
|
|
||||||
import tierNPC from 'assets/svg/tier-npc.svg';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['chat', 'groupId', 'groupName', 'inbox'],
|
props: ['chat', 'groupId', 'groupName', 'inbox'],
|
||||||
mixins: [styleHelper],
|
|
||||||
components: {
|
components: {
|
||||||
copyAsTodoModal,
|
copyAsTodoModal,
|
||||||
reportFlagModal,
|
reportFlagModal,
|
||||||
|
chatCard,
|
||||||
Avatar,
|
Avatar,
|
||||||
},
|
},
|
||||||
directives: {
|
|
||||||
markdown: markdownDirective,
|
|
||||||
},
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.loadProfileCache();
|
this.loadProfileCache();
|
||||||
},
|
},
|
||||||
@@ -252,24 +105,6 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
icons: Object.freeze({
|
|
||||||
like: likeIcon,
|
|
||||||
copy: copyIcon,
|
|
||||||
report: reportIcon,
|
|
||||||
delete: deleteIcon,
|
|
||||||
liked: likedIcon,
|
|
||||||
tier1,
|
|
||||||
tier2,
|
|
||||||
tier3,
|
|
||||||
tier4,
|
|
||||||
tier5,
|
|
||||||
tier6,
|
|
||||||
tier7,
|
|
||||||
tier8,
|
|
||||||
tier9,
|
|
||||||
tierNPC,
|
|
||||||
}),
|
|
||||||
copyingMessage: {},
|
|
||||||
currentDayDividerDisplay: moment().day(),
|
currentDayDividerDisplay: moment().day(),
|
||||||
cachedProfileData: {},
|
cachedProfileData: {},
|
||||||
currentProfileLoadedCount: 0,
|
currentProfileLoadedCount: 0,
|
||||||
@@ -277,15 +112,6 @@ export default {
|
|||||||
loading: false,
|
loading: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
filters: {
|
|
||||||
timeAgo (value) {
|
|
||||||
return moment(value).fromNow();
|
|
||||||
},
|
|
||||||
date (value) {
|
|
||||||
// @TODO: Add user preference
|
|
||||||
return moment(value).toDate();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({user: 'user.data'}),
|
||||||
// @TODO: We need a different lazy load mechnism.
|
// @TODO: We need a different lazy load mechnism.
|
||||||
@@ -304,28 +130,6 @@ export default {
|
|||||||
handleScroll () {
|
handleScroll () {
|
||||||
this.loadProfileCache(window.scrollY / 1000);
|
this.loadProfileCache(window.scrollY / 1000);
|
||||||
},
|
},
|
||||||
isUserMentioned (message) {
|
|
||||||
let user = this.user;
|
|
||||||
|
|
||||||
if (message.hasOwnProperty('highlight')) return message.highlight;
|
|
||||||
|
|
||||||
message.highlight = false;
|
|
||||||
let messagetext = message.text.toLowerCase();
|
|
||||||
let username = user.profile.name;
|
|
||||||
let mentioned = messagetext.indexOf(username.toLowerCase());
|
|
||||||
let escapedUsername = escapeRegExp(username);
|
|
||||||
let pattern = `@${escapedUsername}([^\w]|$){1}`;
|
|
||||||
|
|
||||||
if (mentioned === -1) return message.highlight;
|
|
||||||
|
|
||||||
let preceedingchar = messagetext.substring(mentioned - 1, mentioned);
|
|
||||||
if (mentioned === 0 || preceedingchar.trim() === '' || preceedingchar === '@') {
|
|
||||||
let regex = new RegExp(pattern, 'i');
|
|
||||||
message.highlight = regex.test(messagetext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return message.highlight;
|
|
||||||
},
|
|
||||||
canViewFlag (message) {
|
canViewFlag (message) {
|
||||||
if (message.uuid === this.user._id) return true;
|
if (message.uuid === this.user._id) return true;
|
||||||
if (!message.flagCount || message.flagCount < 2) return true;
|
if (!message.flagCount || message.flagCount < 2) return true;
|
||||||
@@ -381,58 +185,6 @@ export default {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
likeCount (message) {
|
|
||||||
if (!message.likes) return 0;
|
|
||||||
|
|
||||||
let likeCount = 0;
|
|
||||||
for (let key in message.likes) {
|
|
||||||
let like = message.likes[key];
|
|
||||||
if (like) likeCount += 1;
|
|
||||||
}
|
|
||||||
return likeCount;
|
|
||||||
},
|
|
||||||
async like (messageToLike, index) {
|
|
||||||
let message = cloneDeep(messageToLike);
|
|
||||||
|
|
||||||
await this.$store.dispatch('chat:like', {
|
|
||||||
groupId: this.groupId,
|
|
||||||
chatId: message.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!message.likes[this.user._id]) {
|
|
||||||
message.likes[this.user._id] = true;
|
|
||||||
} else {
|
|
||||||
message.likes[this.user._id] = !message.likes[this.user._id];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chat.splice(index, 1, message);
|
|
||||||
},
|
|
||||||
copyAsTodo (message) {
|
|
||||||
this.copyingMessage = message;
|
|
||||||
this.$root.$emit('bv::show::modal', 'copyAsTodo');
|
|
||||||
},
|
|
||||||
async report (message) {
|
|
||||||
this.$store.state.flagChatOptions.message = message;
|
|
||||||
this.$store.state.flagChatOptions.groupId = this.groupId;
|
|
||||||
|
|
||||||
this.$root.$emit('bv::show::modal', 'report-flag');
|
|
||||||
},
|
|
||||||
async remove (message, index) {
|
|
||||||
if (!confirm(this.$t('areYouSureDeleteMessage'))) return;
|
|
||||||
|
|
||||||
this.chat.splice(index, 1);
|
|
||||||
|
|
||||||
if (this.inbox) {
|
|
||||||
axios.delete(`/api/v3/user/messages/${message.id}`);
|
|
||||||
this.$delete(this.user.inbox.messages, message.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.$store.dispatch('chat:deleteChat', {
|
|
||||||
groupId: this.groupId,
|
|
||||||
chatId: message.id,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showMemberModal (memberId) {
|
showMemberModal (memberId) {
|
||||||
const profile = this.cachedProfileData[memberId];
|
const profile = this.cachedProfileData[memberId];
|
||||||
|
|
||||||
@@ -444,17 +196,17 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showShowTierStyle (message) {
|
messageLiked (message) {
|
||||||
const isContributor = Boolean(message.contributor && message.contributor.level);
|
const chatIndex = findIndex(this.chat, chatMessage => {
|
||||||
const isNPC = Boolean(message.backer && message.backer.npc);
|
return chatMessage.id === message.id;
|
||||||
return isContributor || isNPC;
|
});
|
||||||
|
this.chat.splice(chatIndex, 1, message);
|
||||||
},
|
},
|
||||||
getTierIcon (message) {
|
messageRemoved (message) {
|
||||||
const isNPC = Boolean(message.backer && message.backer.npc);
|
const chatIndex = findIndex(this.chat, chatMessage => {
|
||||||
if (isNPC) {
|
return chatMessage.id === message.id;
|
||||||
return this.icons.tierNPC;
|
});
|
||||||
}
|
this.chat.splice(chatIndex, 1);
|
||||||
return this.icons[`tier${message.contributor.level}`];
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,12 +33,6 @@ export default {
|
|||||||
name: `<span class='text-danger'>${reportMessage}</span>`,
|
name: `<span class='text-danger'>${reportMessage}</span>`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
abuseObject () {
|
|
||||||
return this.$store.state.flagChatOptions.message;
|
|
||||||
},
|
|
||||||
groupId () {
|
|
||||||
return this.$store.state.flagChatOptions.groupId;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
let abuseFlagModalBody = {
|
let abuseFlagModalBody = {
|
||||||
@@ -49,8 +43,21 @@ export default {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
abuseFlagModalBody,
|
abuseFlagModalBody,
|
||||||
|
abuseObject: '',
|
||||||
|
groupId: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
created () {
|
||||||
|
this.$root.$on('habitica::report-chat', data => {
|
||||||
|
if (!data.message || !data.groupId) return;
|
||||||
|
this.abuseObject = data.message;
|
||||||
|
this.groupId = data.groupId;
|
||||||
|
this.$root.$emit('bv::show::modal', 'report-flag');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
this.$root.$off('habitica::report-chat');
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
close () {
|
close () {
|
||||||
this.$root.$emit('bv::hide::modal', 'report-flag');
|
this.$root.$emit('bv::hide::modal', 'report-flag');
|
||||||
|
|||||||
@@ -91,10 +91,6 @@ export default function () {
|
|||||||
startingPage: '',
|
startingPage: '',
|
||||||
subPage: '',
|
subPage: '',
|
||||||
},
|
},
|
||||||
flagChatOptions: {
|
|
||||||
message: {},
|
|
||||||
groupId: '',
|
|
||||||
},
|
|
||||||
challengeOptions: {
|
challengeOptions: {
|
||||||
cloning: false,
|
cloning: false,
|
||||||
tasksToClone: {},
|
tasksToClone: {},
|
||||||
|
|||||||
Reference in New Issue
Block a user