2017-12-20 18:27:21 +00:00
< 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
2018-10-17 17:57:57 +00:00
h3 . leader (
: class = 'userLevelStyle(msg)' ,
@ click = "showMemberModal(msg.uuid)" ,
v - b - tooltip . hover . top = "tierTitle" ,
v - if = "msg.user"
)
| { { msg . user } }
2018-10-22 21:29:47 +00:00
. svg - icon ( v - html = "tierIcon" )
2018-10-19 21:20:13 +00:00
p . time
2018-10-17 23:28:58 +00:00
span . mr - 1 ( v - if = "msg.username" ) @ { { msg . username } }
span . mr - 1 ( v - if = "msg.username" ) •
2018-10-19 21:20:13 +00:00
span ( v - b - tooltip = "" , : title = "msg.timestamp | date" ) { { msg . timestamp | timeAgo } }
2018-10-17 17:57:57 +00:00
. text ( v - html = 'atHighlight(parseMarkdown(msg.text))' )
hr
. d - flex ( v - if = 'msg.id' )
. action . d - flex . align - items - center ( v - if = '!inbox' , @ click = 'copyAsTodo(msg)' )
. svg - icon ( v - html = "icons.copy" )
div { { $t ( 'copyAsTodo' ) } }
. action . d - flex . align - items - center ( v - if = '!inbox && user.flags.communityGuidelinesAccepted && msg.uuid !== "system"' , @ click = 'report(msg)' )
. svg - icon ( v - html = "icons.report" )
div { { $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
. action . d - flex . align - items - center ( v - if = 'msg.uuid === user._id || inbox || user.contributor.admin' , @ click = 'remove()' )
. svg - icon ( v - html = "icons.delete" )
| { { $t ( 'delete' ) } }
2018-11-03 18:16:32 +00:00
. ml - auto . d - flex ( v - b - tooltip = "{title: likeTooltip(msg.likes[user._id])}" , v - if = '!inbox' )
2018-10-17 23:28:58 +00:00
. action . d - flex . align - items - center . mr - 0 ( @ click = 'like()' , v - if = 'likeCount > 0' , : class = '{active: msg.likes[user._id]}' )
2018-11-03 18:16:32 +00:00
. svg - icon ( v - html = "icons.liked" , : title = '$t("liked")' )
2018-10-17 23:28:58 +00:00
| + { { likeCount } }
. action . d - flex . align - items - center . mr - 0 ( @ click = 'like()' , v - if = 'likeCount === 0' , : class = '{active: msg.likes[user._id]}' )
2018-11-03 18:16:32 +00:00
. svg - icon ( v - html = "icons.like" , : title = '$t("like")' )
2018-08-19 02:08:32 +00:00
span ( v - if = '!msg.likes[user._id]' ) { { $t ( 'like' ) } }
2017-12-20 18:27:21 +00:00
< / template >
2018-10-17 17:57:57 +00:00
< style lang = "scss" >
. at - highlight {
background - color : rgba ( 213 , 200 , 255 , 0.32 ) ;
padding : 0.1 rem ;
}
2018-11-15 21:58:07 +00:00
. at - text {
color : # 6133 b4 ;
}
2018-10-17 17:57:57 +00:00
< / style >
2017-12-20 18:27:21 +00:00
< style lang = "scss" scoped >
2018-10-17 23:28:58 +00:00
@ import '~client/assets/scss/colors.scss' ;
2017-12-20 18:27:21 +00:00
@ import '~client/assets/scss/tiers.scss' ;
. mentioned - icon {
width : 16 px ;
height : 16 px ;
border - radius : 50 % ;
background - color : # bda8ff ;
box - shadow : 0 1 px 1 px 0 rgba ( 26 , 24 , 29 , 0.12 ) ;
position : absolute ;
right : - .5 em ;
top : - .5 em ;
}
2018-01-11 18:04:07 +00:00
. message - hidden {
2017-12-20 18:27:21 +00:00
margin - left : 1.5 em ;
margin - top : 1 em ;
color : red ;
}
2018-10-17 17:57:57 +00:00
hr {
margin - bottom : 0.5 rem ;
margin - top : 0.5 rem ;
}
2017-12-20 18:27:21 +00:00
. card - body {
2018-10-19 21:20:13 +00:00
padding : 0.75 rem 1.25 rem 0.75 rem 1.25 rem ;
2018-10-17 17:57:57 +00:00
2017-12-20 18:27:21 +00:00
. leader {
margin - bottom : 0 ;
}
h3 { // this is the user name
cursor : pointer ;
display : inline - block ;
2018-10-17 23:28:58 +00:00
font - size : 16 px ;
2017-12-20 18:27:21 +00:00
. svg - icon {
width : 10 px ;
display : inline - block ;
margin - left : .5 em ;
}
}
. time {
font - size : 12 px ;
color : # 878190 ;
2018-10-17 17:57:57 +00:00
margin - bottom : 0.5 rem ;
2017-12-20 18:27:21 +00:00
}
. text {
font - size : 14 px ;
color : # 4 e4a57 ;
text - align : left ! important ;
2018-10-22 21:29:47 +00:00
min - height : 0 rem ;
margin - bottom : - 0.5 rem ;
2017-12-20 18:27:21 +00:00
}
}
. action {
display : inline - block ;
color : # 878190 ;
margin - right : 1 em ;
2018-10-17 17:57:57 +00:00
font - size : 12 px ;
2017-12-20 18:27:21 +00:00
2018-10-17 23:28:58 +00:00
: hover {
cursor : pointer ;
}
2017-12-20 18:27:21 +00:00
2018-10-17 23:28:58 +00:00
. svg - icon {
color : # A5A1AC ;
margin - right : .2 em ;
width : 16 px ;
}
2017-12-20 18:27:21 +00:00
}
2018-10-17 23:28:58 +00:00
. active {
color : $purple - 300 ;
2017-12-20 18:27:21 +00:00
2018-10-17 23:28:58 +00:00
. svg - icon {
color : $purple - 400 ;
}
2017-12-20 18:27:21 +00:00
}
< / style >
< script >
import axios from 'axios' ;
import moment from 'moment' ;
import cloneDeep from 'lodash/cloneDeep' ;
import escapeRegExp from 'lodash/escapeRegExp' ;
2018-11-13 20:14:02 +00:00
import max from 'lodash/max' ;
2017-12-20 18:27:21 +00:00
2018-10-17 17:57:57 +00:00
import habiticaMarkdown from 'habitica-markdown' ;
2017-12-20 18:27:21 +00:00
import { mapState } from 'client/libs/store' ;
import styleHelper from 'client/mixins/styleHelper' ;
2018-08-30 19:52:37 +00:00
import achievementsLib from '../../../common/script/libs/achievements' ;
2017-12-20 18:27:21 +00:00
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 {
icons : Object . freeze ( {
like : likeIcon ,
copy : copyIcon ,
report : reportIcon ,
delete : deleteIcon ,
liked : likedIcon ,
tier1 ,
tier2 ,
tier3 ,
tier4 ,
tier5 ,
tier6 ,
tier7 ,
tier8 ,
tier9 ,
tierNPC ,
} ) ,
} ;
} ,
filters : {
timeAgo ( value ) {
return moment ( value ) . fromNow ( ) ;
} ,
date ( value ) {
2018-07-21 13:09:36 +00:00
// @TODO: Vue doesn't support this so we cant user preference
2017-12-20 18:27:21 +00:00
return moment ( value ) . toDate ( ) ;
} ,
} ,
computed : {
... mapState ( { user : 'user.data' } ) ,
isUserMentioned ( ) {
const message = this . msg ;
2018-11-13 20:14:02 +00:00
const user = this . user ;
2017-12-20 18:27:21 +00:00
if ( message . hasOwnProperty ( 'highlight' ) ) return message . highlight ;
message . highlight = false ;
2018-11-13 20:14:02 +00:00
const messageText = message . text . toLowerCase ( ) ;
const displayName = user . profile . name ;
const username = user . auth . local && user . auth . local . username ;
const mentioned = max ( [ messageText . indexOf ( username . toLowerCase ( ) ) , messageText . indexOf ( displayName . toLowerCase ( ) ) ] ) ;
2017-12-20 18:27:21 +00:00
if ( mentioned === - 1 ) return message . highlight ;
2018-11-13 20:14:02 +00:00
const escapedDisplayName = escapeRegExp ( displayName ) ;
const escapedUsername = escapeRegExp ( username ) ;
2018-11-14 22:31:35 +00:00
const pattern = ` @( ${ escapedUsername } | ${ escapedDisplayName } )( \\ b) ` ;
2018-11-13 20:14:02 +00:00
const precedingChar = messageText . substring ( mentioned - 1 , mentioned ) ;
if ( mentioned === 0 || precedingChar . trim ( ) === '' || precedingChar === '@' ) {
2017-12-20 18:27:21 +00:00
let regex = new RegExp ( pattern , 'i' ) ;
2018-11-13 20:14:02 +00:00
message . highlight = regex . test ( messageText ) ;
2017-12-20 18:27:21 +00:00
}
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 ;
} ,
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 } ` ] ;
} ,
2018-08-30 19:52:37 +00:00
tierTitle ( ) {
const message = this . msg ;
return achievementsLib . getContribText ( message . contributor , message . backer ) || '' ;
} ,
2017-12-20 18:27:21 +00:00
} ,
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 ] ;
}
2018-03-31 11:20:41 +00:00
this . $emit ( 'message-liked' , message ) ;
2018-11-03 18:16:32 +00:00
this . $root . $emit ( 'bv::hide::tooltip' ) ;
} ,
likeTooltip ( likedStatus ) {
if ( ! likedStatus ) return this . $t ( 'like' ) ;
2017-12-20 18:27:21 +00:00
} ,
copyAsTodo ( message ) {
2018-02-05 16:43:00 +00:00
this . $root . $emit ( 'habitica::copy-as-todo' , message ) ;
2017-12-20 18:27:21 +00:00
} ,
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 ) {
2018-08-30 19:50:03 +00:00
await axios . delete ( ` /api/v4/inbox/messages/ ${ message . id } ` ) ;
2017-12-20 18:27:21 +00:00
return ;
}
await this . $store . dispatch ( 'chat:deleteChat' , {
groupId : this . groupId ,
chatId : message . id ,
} ) ;
} ,
showMemberModal ( memberId ) {
this . $emit ( 'show-member-modal' , memberId ) ;
} ,
2018-10-17 17:57:57 +00:00
atHighlight ( text ) {
2018-11-15 21:58:07 +00:00
const userRegex = new RegExp ( ` @( ${ this . user . auth . local . username } | ${ this . user . profile . name } )(?: \\ b) ` , 'gi' ) ;
const atRegex = new RegExp ( /(?!\b)@[\w-]+/g ) ;
if ( userRegex . test ( text ) ) {
text = text . replace ( userRegex , match => {
return ` <span class="at-highlight at-text"> ${ match } </span> ` ;
} ) ;
}
if ( atRegex . test ( text ) ) {
text = text . replace ( atRegex , match => {
return ` <span class="at-text"> ${ match } </span> ` ;
} ) ;
}
return text ;
2018-10-17 17:57:57 +00:00
} ,
parseMarkdown ( text ) {
return habiticaMarkdown . render ( text ) ;
} ,
2017-12-20 18:27:21 +00:00
} ,
} ;
< / script >