2020-11-18 21:19:02 +00:00
< template >
< div >
< div v-if = "loaded && page == 'read'" class="container messages-page p-0 p-md-2 mt-n4" style="min-height: 60vh;" >
< div class = "col-12 col-md-8 offset-md-2 p-0 px-md-2" >
< div class = "card shadow-none border mt-4" >
< div class = "card-header bg-white d-flex justify-content-between align-items-center" >
< span >
< a href = "/account/direct" class = "text-muted" >
< i class = "fas fa-chevron-left fa-lg" > < / i >
< / a >
< / span >
< span >
< div class = "media" >
2021-07-11 08:57:14 +00:00
< img class = "mr-3 rounded-circle img-thumbnail" :src = "thread.avatar" width = "40" onerror = "this.onerror=null;this.src='/storage/avatars/default.jpg';" >
2020-11-18 21:19:02 +00:00
< div class = "media-body" >
< p class = "mb-0" >
< span class = "font-weight-bold" > { { thread . name } } < / span >
< / p >
< p class = "mb-0" >
< a v-if = "!thread.isLocal" :href="'/'+thread.username" class="text-decoration-none text-muted" > {{ thread.username }} < / a >
< a v -else :href = "'/'+thread.username" class = "text-decoration-none text-muted" > & commat ; { { thread . username } } < / a >
< / p >
< / div >
< / div >
< / span >
< span > < a href = "#" class = "text-muted" @click.prevent ="showOptions()" > < i class = "fas fa-cog fa-lg" > < / i > < / a > < / span >
< / div >
< ul class = "list-group list-group-flush dm-wrapper" style = "height:60vh;overflow-y: scroll;" >
< li class = "list-group-item border-0" >
< p class = "text-center small text-muted" >
Conversation with < span class = "font-weight-bold" > { { thread . username } } < / span >
< / p >
< hr >
< / li >
< li v-if = "showLoadMore && thread.messages && thread.messages.length > 5" class="list-group-item border-0 mt-n4" >
< p class = "text-center small text-muted" >
< button v-if = "!loadingMessages" class="btn btn-primary font-weight-bold rounded-pill btn-sm px-3" @click="loadOlderMessages()" > Load Older Messages < / button >
< button v -else class = "btn btn-primary font-weight-bold rounded-pill btn-sm px-3" disabled > Loading ... < / button >
< / p >
< / li >
< li v-for = "(convo, index) in thread.messages" class="list-group-item border-0 chat-msg cursor-pointer" @click="openCtxMenu(convo, index)" >
< div v-if = "!convo.isAuthor" class="media d-inline-flex mb-0" >
2021-07-11 08:57:14 +00:00
< img v-if = "!hideAvatars" class="mr-3 mt-2 rounded-circle img-thumbnail" :src="thread.avatar" alt="avatar" width="32" onerror="this.onerror=null;this.src='/storage/avatars/default.jpg';" >
2020-11-18 21:19:02 +00:00
< div class = "media-body" >
< p v-if = "convo.type == 'photo'" class="pill-to p-0 shadow" >
2021-07-11 08:57:14 +00:00
< img :src = "convo.media" width = "140" style = "border-radius:20px;" onerror = "this.onerror=null;this.src='/storage/no-preview.png';" >
2020-11-18 21:19:02 +00:00
< / p >
< div v -else -if = " convo.type = = ' link ' " class = "media d-inline-flex mb-0 cursor-pointer" >
< div class = "media-body" >
< div class = "card mb-2 rounded border shadow" style = "width:240px;" :title = "convo.text" >
< div class = "card-body p-0" >
< div class = "media d-flex align-items-center" >
< div v-if = "convo.meta.local" class="bg-primary mr-3 border-right p-3" >
< i class = "fas fa-link text-white fa-2x" > < / i >
< / div >
< div v -else class = "bg-light mr-3 border-right p-3" >
< i class = "fas fa-link text-lighter fa-2x" > < / i >
< / div >
< div class = "media-body text-muted small text-truncate pr-2 font-weight-bold" >
{ { convo . meta . local ? convo . text . substr ( 8 ) : convo . meta . domain } }
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< p v -else -if = " convo.type = = ' video ' " class = "pill-to p-0 shadow" >
<!-- < video :src = "convo.media" width = "140px" style = "border-radius:20px;" > < / video > -- >
< span class = "d-block bg-primary d-flex align-items-center justify-content-center" style = "width:200px;height: 110px;border-radius: 20px;" >
< div class = "text-center" >
< p class = "mb-1" >
< i class = "fas fa-play fa-2x text-white" > < / i >
< / p >
< p class = "mb-0 small font-weight-bold text-white" >
Play
< / p >
< / div >
< / span >
< / p >
< p v -else -if = " convo.type = = ' emoji ' " class = "p-0 emoji-msg" >
{ { convo . text } }
< / p >
< p v -else : class = "[largerText ? 'pill-to shadow larger-text text-break':'pill-to shadow text-break']" >
{ { convo . text } }
< / p >
< p v-if = "!hideTimestamps" class="small text-muted font-weight-bold ml-2 d-flex align-items-center justify-content-start" data-timestamp="timestamp"> <span v-if="convo.hidden" class="mr-2 small" title="Filtered Message" data-toggle="tooltip" data-placement="bottom"><i class="fas fa-lock" > < / i > < / span > {{ convo.timeAgo }} < / p >
2020-11-19 09:15:07 +00:00
< p v-else > & nbsp ; < / p >
2020-11-18 21:19:02 +00:00
< / div >
< / div >
< div v -else class = "media d-inline-flex float-right mb-0" >
< div class = "media-body" >
< p v-if = "convo.type == 'photo'" class="pill-from p-0 shadow" >
2021-07-11 08:57:14 +00:00
< img :src = "convo.media" width = "140" style = "border-radius:20px;" onerror = "this.onerror=null;this.src='/storage/no-preview.png';" >
2020-11-18 21:19:02 +00:00
< / p >
< div v -else -if = " convo.type = = ' link ' " class = "media d-inline-flex float-right mb-0 cursor-pointer" >
< div class = "media-body" >
< div class = "card mb-2 rounded border shadow" style = "width:240px;" :title = "convo.text" >
< div class = "card-body p-0" >
< div class = "media d-flex align-items-center" >
< div v-if = "convo.meta.local" class="bg-primary mr-3 border-right p-3" >
< i class = "fas fa-link text-white fa-2x" > < / i >
< / div >
< div v -else class = "bg-light mr-3 border-right p-3" >
< i class = "fas fa-link text-lighter fa-2x" > < / i >
< / div >
< div class = "media-body text-muted small text-truncate pr-2 font-weight-bold" >
{ { convo . meta . local ? convo . text . substr ( 8 ) : convo . meta . domain } }
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< p v -else -if = " convo.type = = ' video ' " class = "pill-from p-0 shadow" >
<!-- < video :src = "convo.media" width = "140px" style = "border-radius:20px;" > < / video > -- >
< span class = "rounded-pill bg-primary d-flex align-items-center justify-content-center" style = "width:200px;height: 110px" >
< div class = "text-center" >
< p class = "mb-1" >
< i class = "fas fa-play fa-2x text-white" > < / i >
< / p >
< p class = "mb-0 small font-weight-bold" >
Play
< / p >
< / div >
< / span >
< / p >
< p v -else -if = " convo.type = = ' emoji ' " class = "p-0 emoji-msg" >
{ { convo . text } }
< / p >
< p v -else : class = "[largerText ? 'pill-from shadow larger-text text-break':'pill-from shadow text-break']" >
{ { convo . text } }
< / p >
< p v-if = "!hideTimestamps" class="small text-muted font-weight-bold text-right mr-2"> <span v-if="convo.hidden" class="mr-2 small" title="Filtered Message" data-toggle="tooltip" data-placement="bottom"><i class="fas fa-lock" > < / i > < / span > {{ convo.timeAgo }}
< / p >
2020-11-19 09:15:07 +00:00
< p v-else > & nbsp ; < / p >
2020-11-18 21:19:02 +00:00
< / div >
2021-07-11 08:57:14 +00:00
< img v-if = "!hideAvatars" class="ml-3 mt-2 rounded-circle img-thumbnail" :src="profile.avatar" alt="avatar" width="32" onerror="this.onerror=null;this.src='/storage/avatars/default.jpg';" >
2020-11-18 21:19:02 +00:00
< / div >
< / li >
< / ul >
< div class = "card-footer bg-white p-0" >
< form class = "border-0 rounded-0 align-middle" method = "post" action = "#" >
< textarea class = "form-control border-0 rounded-0 no-focus" name = "comment" placeholder = "Reply ..." autocomplete = "off" autocorrect = "off" style = "height:86px;line-height: 18px;max-height:80px;resize: none; padding-right:115.22px;" v-model ="replyText" :disabled ="blocked" > < / textarea >
< input type = "button" value = "Send" : class = "[replyText.length ? 'd-inline-block btn btn-sm btn-primary rounded-pill font-weight-bold reply-btn text-decoration-none text-uppercase' : 'd-inline-block btn btn-sm btn-primary rounded-pill font-weight-bold reply-btn text-decoration-none text-uppercase disabled']" : disabled = "replyText.length == 0" @click.prevent ="sendMessage" / >
< / form >
< / div >
< div class = "card-footer p-0" >
< p class = "d-flex justify-content-between align-items-center mb-0 px-3 py-1 small" >
<!-- < span class = "font-weight-bold" style = "color: #D69E2E" >
< i class = "fas fa-circle mr-1" > < / i >
Typing ...
< / span > -- >
< span >
<!-- < span class = "btn btn-primary btn-sm font-weight-bold py-0 px-3 rounded-pill" @click ="uploadMedia" >
< i class = "fas fa-share mr-1" > < / i >
Share
< / span > -- >
< span class = "btn btn-primary btn-sm font-weight-bold py-0 px-3 rounded-pill" @click ="uploadMedia" >
< i class = "fas fa-upload mr-1" > < / i >
Add Photo / Video
< / span >
< / span >
< input type = "file" id = "uploadMedia" class = "d-none" name = "uploadMedia" accept = "image/jpeg,image/png,image/gif,video/mp4" >
< span class = "text-muted font-weight-bold" > { { replyText . length } } / 600 < / span >
< / p >
< / div >
< / div >
< / div >
< / div >
< div v-if = "loaded && page == 'options'" class="container messages-page p-0 p-md-2 mt-n4" style="min-height: 60vh;" >
< div class = "col-12 col-md-8 offset-md-2 p-0 px-md-2" >
< div class = "card shadow-none border mt-4" >
< div class = "card-header bg-white d-flex justify-content-between align-items-center" >
< span >
< a href = "#" class = "text-muted" @click.prevent ="page='read'" >
< i class = "fas fa-chevron-left fa-lg" > < / i >
< / a >
< / span >
< span >
< p class = "mb-0 lead font-weight-bold py-2" > Message Settings < / p >
< / span >
< span class = "text-lighter" data -toggle = " tooltip " data -placement = " bottom " title = "Have a nice day!" > < i class = "far fa-smile fa-lg" > < / i > < / span >
< / div >
< ul class = "list-group list-group-flush dm-wrapper" style = "height: 698px;" >
< div class = "list-group-item media border-bottom" >
< div class = "d-inline-block custom-control custom-switch ml-3" >
< input type = "checkbox" class = "custom-control-input" id = "customSwitch0" v-model = "hideAvatars" >
< label class = "custom-control-label" for = "customSwitch0" > < / label >
< / div >
< div class = "d-inline-block ml-3 font-weight-bold" >
Hide Avatars
< / div >
< / div >
< div class = "list-group-item media border-bottom" >
< div class = "d-inline-block custom-control custom-switch ml-3" >
< input type = "checkbox" class = "custom-control-input" id = "customSwitch1" v-model = "hideTimestamps" >
< label class = "custom-control-label" for = "customSwitch1" > < / label >
< / div >
< div class = "d-inline-block ml-3 font-weight-bold" >
Hide Timestamps
< / div >
< / div >
< div class = "list-group-item media border-bottom" >
< div class = "d-inline-block custom-control custom-switch ml-3" >
< input type = "checkbox" class = "custom-control-input" id = "customSwitch2" v-model = "largerText" >
< label class = "custom-control-label" for = "customSwitch2" > < / label >
< / div >
< div class = "d-inline-block ml-3 font-weight-bold" >
Larger Text
< / div >
< / div >
<!-- < div class = "list-group-item media border-bottom" >
< div class = "d-inline-block custom-control custom-switch ml-3" >
< input type = "checkbox" class = "custom-control-input" id = "customSwitch3" v-model = "autoRefresh" >
< label class = "custom-control-label" for = "customSwitch3" > < / label >
< / div >
< div class = "d-inline-block ml-3 font-weight-bold" >
Auto Refresh
< / div >
< / div > -- >
< div class = "list-group-item media border-bottom d-flex align-items-center" >
< div class = "d-inline-block custom-control custom-switch ml-3" >
< input type = "checkbox" class = "custom-control-input" id = "customSwitch4" v-model = "mutedNotifications" >
< label class = "custom-control-label" for = "customSwitch4" > < / label >
< / div >
< div class = "d-inline-block ml-3 font-weight-bold" >
Mute Notifications
< p class = "small mb-0" > You will not receive any direct message notifications from < strong > { { thread . username } } < / strong > . < / p >
< / div >
< / div >
< / ul >
< / div >
< / div >
< / div >
< b-modal ref = "ctxModal"
id = "ctx-modal"
hide - header
hide - footer
centered
rounded
size = "sm"
body - class = "list-group-flush p-0 rounded" >
< div class = "list-group text-center" >
< div v-if = "ctxContext && ctxContext.type == 'photo'" class="list-group-item rounded cursor-pointer font-weight-bold text-dark" @click="viewOriginal()" > View Original < / div >
< div v-if = "ctxContext && ctxContext.type == 'video'" class="list-group-item rounded cursor-pointer font-weight-bold text-dark" @click="viewOriginal()" > Play < / div >
< div v-if = "ctxContext && ctxContext.type == 'link'" class="list-group-item rounded cursor-pointer" @click="clickLink()" >
< p class = "mb-0" style = "font-size:12px;" >
Navigate to
< / p >
< p class = "mb-0 font-weight-bold text-dark" >
{ { this . ctxContext . meta . domain } }
< / p >
< / div >
< div v-if = "ctxContext && (ctxContext.type == 'text' || ctxContext.type == 'emoji' || ctxContext.type == 'link')" class="list-group-item rounded cursor-pointer text-dark" @click="copyText()" > Copy < / div >
< div v-if = "ctxContext && !ctxContext.isAuthor" class="list-group-item rounded cursor-pointer text-muted" @click="reportMessage()" > Report < / div >
< div v-if = "ctxContext && ctxContext.isAuthor" class="list-group-item rounded cursor-pointer text-muted" @click="deleteMessage()" > Delete < / div >
< div class = "list-group-item rounded cursor-pointer text-lighter" @click ="closeCtxMenu()" > Cancel < / div >
< / div >
< / b-modal >
< / div >
< / template >
< style type = "text/css" scoped >
. reply - btn {
position : absolute ;
bottom : 54 px ;
right : 20 px ;
width : 90 px ;
text - align : center ;
border - radius : 0 3 px 3 px 0 ;
}
. media - body . bg - primary {
background : linear - gradient ( 135 deg , # 2 EA2F4 0 % , # 0 B93F6 100 % ) ! important ;
}
. pill - to {
background : # EDF2F7 ;
font - weight : 500 ;
border - radius : 20 px ! important ;
padding - left : 1 rem ;
padding - right : 1 rem ;
padding - top : 0.5 rem ;
padding - bottom : 0.5 rem ;
margin - right : 3 rem ;
margin - bottom : 0.25 rem ;
}
. pill - from {
color : white ! important ;
text - align : right ! important ;
/*background: #53d769;*/
background : linear - gradient ( 135 deg , # 2 EA2F4 0 % , # 0 B93F6 100 % ) ! important ;
font - weight : 500 ;
border - radius : 20 px ! important ;
padding - left : 1 rem ;
padding - right : 1 rem ;
padding - top : 0.5 rem ;
padding - bottom : 0.5 rem ;
margin - left : 3 rem ;
margin - bottom : 0.25 rem ;
}
. chat - msg : hover {
background : # f7fbfd ;
}
. no - focus : focus {
outline : none ! important ;
outline - width : 0 ! important ;
box - shadow : none ;
- moz - box - shadow : none ;
- webkit - box - shadow : none ;
}
. emoji - msg {
font - size : 4 rem ! important ;
line - height : 30 px ! important ;
margin - top : 10 px ! important ;
}
. larger - text {
font - size : 22 px ;
}
< / style >
< script type = "text/javascript" >
export default {
props : [ 'accountId' ] ,
data ( ) {
return {
config : window . App . config ,
hideAvatars : true ,
hideTimestamps : false ,
largerText : false ,
autoRefresh : false ,
mutedNotifications : false ,
blocked : false ,
loaded : false ,
profile : { } ,
page : 'read' ,
pages : [ 'browse' , 'add' , 'read' ] ,
threads : [ ] ,
thread : false ,
threadIndex : false ,
replyText : '' ,
composeUsername : '' ,
ctxContext : null ,
ctxIndex : null ,
uploading : false ,
uploadProgress : null ,
min _id : null ,
max _id : null ,
loadingMessages : false ,
showLoadMore : true ,
}
} ,
mounted ( ) {
this . fetchProfile ( ) ;
let self = this ;
2020-11-18 21:31:59 +00:00
axios . get ( '/api/direct/thread' , {
2020-11-18 21:19:02 +00:00
params : {
pid : self . accountId
}
} )
. then ( res => {
self . loaded = true ;
let d = res . data ;
d . messages . reverse ( ) ;
this . thread = d ;
this . threads = [ d ] ;
this . threadIndex = 0 ;
let mids = d . messages . map ( m => m . id ) ;
this . max _id = Math . max ( ... mids ) ;
this . min _id = Math . min ( ... mids ) ;
this . mutedNotifications = d . muted ;
this . markAsRead ( ) ;
//this.messagePoll();
setTimeout ( function ( ) {
let objDiv = document . querySelector ( '.dm-wrapper' ) ;
objDiv . scrollTop = objDiv . scrollHeight ;
} , 300 ) ;
} ) ;
2020-11-19 02:51:08 +00:00
let options = localStorage . getItem ( 'px_dm_options' ) ;
if ( options ) {
options = JSON . parse ( options ) ;
this . hideAvatars = options . hideAvatars ;
this . hideTimestamps = options . hideTimestamps ;
this . largerText = options . largerText ;
}
2020-11-18 21:19:02 +00:00
} ,
watch : {
mutedNotifications : function ( v ) {
if ( v ) {
2020-11-18 21:31:59 +00:00
axios . post ( '/api/direct/mute' , {
2020-11-18 21:19:02 +00:00
id : this . accountId
} ) . then ( res => {
} ) ;
} else {
2020-11-18 21:31:59 +00:00
axios . post ( '/api/direct/unmute' , {
2020-11-18 21:19:02 +00:00
id : this . accountId
} ) . then ( res => {
} ) ;
}
this . mutedNotifications = v ;
} ,
2020-11-19 02:51:08 +00:00
hideAvatars : function ( v ) {
this . hideAvatars = v ;
this . updateOptions ( ) ;
} ,
hideTimestamps : function ( v ) {
this . hideTimestamps = v ;
this . updateOptions ( ) ;
} ,
largerText : function ( v ) {
this . largerText = v ;
this . updateOptions ( ) ;
} ,
2020-11-18 21:19:02 +00:00
} ,
updated ( ) {
$ ( '[data-toggle="tooltip"]' ) . tooltip ( ) ;
} ,
methods : {
fetchProfile ( ) {
axios . get ( '/api/pixelfed/v1/accounts/verify_credentials' ) . then ( res => {
this . profile = res . data ;
window . _sharedData . curUser = res . data ;
2020-12-03 04:45:50 +00:00
window . App . util . navatar ( ) ;
2020-11-18 21:19:02 +00:00
} ) ;
} ,
sendMessage ( ) {
let self = this ;
let rt = this . replyText ;
2020-11-18 21:31:59 +00:00
axios . post ( '/api/direct/create' , {
2020-11-18 21:19:02 +00:00
'to_id' : this . threads [ this . threadIndex ] . id ,
'message' : rt ,
'type' : self . isEmoji ( rt ) && rt . length < 10 ? 'emoji' : 'text'
} ) . then ( res => {
let msg = res . data ;
self . threads [ self . threadIndex ] . messages . push ( msg ) ;
let mids = self . threads [ self . threadIndex ] . messages . map ( m => m . id ) ;
this . max _id = Math . max ( ... mids )
this . min _id = Math . min ( ... mids )
setTimeout ( function ( ) {
var objDiv = document . querySelector ( '.dm-wrapper' ) ;
objDiv . scrollTop = objDiv . scrollHeight ;
} , 300 ) ;
} ) . catch ( err => {
if ( err . response . status == 403 ) {
self . blocked = true ;
swal ( 'Profile Unavailable' , 'You cannot message this profile at this time.' , 'error' ) ;
}
} )
this . replyText = '' ;
} ,
openCtxMenu ( r , i ) {
this . ctxIndex = i ;
this . ctxContext = r ;
this . $refs . ctxModal . show ( ) ;
} ,
closeCtxMenu ( ) {
this . $refs . ctxModal . hide ( ) ;
} ,
truncate ( t ) {
return _ . truncate ( t ) ;
} ,
deleteMessage ( ) {
let self = this ;
let c = window . confirm ( 'Are you sure you want to delete this message?' ) ;
if ( c ) {
axios . delete ( '/api/direct/message' , {
params : {
2020-11-19 06:07:00 +00:00
id : self . ctxContext . reportId
2020-11-18 21:19:02 +00:00
}
} ) . then ( res => {
self . threads [ self . threadIndex ] . messages . splice ( self . ctxIndex , 1 ) ;
self . closeCtxMenu ( ) ;
} ) ;
} else {
self . closeCtxMenu ( ) ;
}
} ,
reportMessage ( ) {
this . closeCtxMenu ( ) ;
2020-11-19 02:51:08 +00:00
let url = '/i/report?type=post&id=' + this . ctxContext . reportId ;
2020-11-18 21:19:02 +00:00
window . location . href = url ;
return ;
} ,
uploadMedia ( event ) {
let self = this ;
$ ( document ) . on ( 'change' , '#uploadMedia' , function ( e ) {
self . handleUpload ( ) ;
} ) ;
let el = $ ( event . target ) ;
el . attr ( 'disabled' , '' ) ;
$ ( '#uploadMedia' ) . click ( ) ;
el . blur ( ) ;
el . removeAttr ( 'disabled' ) ;
} ,
handleUpload ( ) {
let self = this ;
self . uploading = true ;
let io = document . querySelector ( '#uploadMedia' ) ;
if ( ! io . files . length ) {
this . uploading = false ;
}
Array . prototype . forEach . call ( io . files , function ( io , i ) {
let type = io . type ;
let acceptedMimes = self . config . uploader . media _types . split ( ',' ) ;
let validated = $ . inArray ( type , acceptedMimes ) ;
if ( validated == - 1 ) {
swal ( 'Invalid File Type' , 'The file you are trying to add is not a valid mime type. Please upload a ' + self . config . uploader . media _types + ' only.' , 'error' ) ;
self . uploading = false ;
return ;
}
let form = new FormData ( ) ;
form . append ( 'file' , io ) ;
form . append ( 'to_id' , self . threads [ self . threadIndex ] . id ) ;
let xhrConfig = {
onUploadProgress : function ( e ) {
let progress = Math . round ( ( e . loaded * 100 ) / e . total ) ;
self . uploadProgress = progress ;
}
} ;
axios . post ( '/api/direct/media' , form , xhrConfig )
. then ( function ( e ) {
self . uploadProgress = 100 ;
self . uploading = false ;
let msg = {
2020-11-19 06:07:00 +00:00
id : e . data . id ,
2020-11-18 21:19:02 +00:00
type : e . data . type ,
2020-11-19 06:07:00 +00:00
reportId : e . data . reportId ,
2020-11-18 21:19:02 +00:00
isAuthor : true ,
text : null ,
media : e . data . url ,
timeAgo : '1s' ,
seen : null
} ;
self . threads [ self . threadIndex ] . messages . push ( msg ) ;
setTimeout ( function ( ) {
var objDiv = document . querySelector ( '.dm-wrapper' ) ;
objDiv . scrollTop = objDiv . scrollHeight ;
} , 300 ) ;
} ) . catch ( function ( e ) {
switch ( e . response . status ) {
case 451 :
self . uploading = false ;
io . value = null ;
swal ( 'Banned Content' , 'This content has been banned and cannot be uploaded.' , 'error' ) ;
break ;
default :
self . uploading = false ;
io . value = null ;
swal ( 'Oops, something went wrong!' , 'An unexpected error occurred.' , 'error' ) ;
break ;
}
} ) ;
io . value = null ;
self . uploadProgress = 0 ;
} ) ;
} ,
viewOriginal ( ) {
let url = this . ctxContext . media ;
window . location . href = url ;
return ;
} ,
isEmoji ( text ) {
const onlyEmojis = text . replace ( new RegExp ( '[\u0000-\u1eeff]' , 'g' ) , '' )
const visibleChars = text . replace ( new RegExp ( '[\n\r\s]+|( )+' , 'g' ) , '' )
return onlyEmojis . length === visibleChars . length
} ,
copyText ( ) {
window . App . util . clipboard ( this . ctxContext . text ) ;
this . closeCtxMenu ( ) ;
return ;
} ,
clickLink ( ) {
let url = this . ctxContext . text ;
if ( this . ctxContext . meta . local != true ) {
url = '/i/redirect?url=' + encodeURI ( this . ctxContext . text ) ;
}
window . location . href = url ;
} ,
markAsRead ( ) {
return ;
axios . post ( '/api/direct/read' , {
pid : this . accountId ,
sid : this . max _id
} ) . then ( res => {
} ) . catch ( err => {
} ) ;
} ,
loadOlderMessages ( ) {
let self = this ;
this . loadingMessages = true ;
2020-11-18 21:31:59 +00:00
axios . get ( '/api/direct/thread' , {
2020-11-18 21:19:02 +00:00
params : {
pid : this . accountId ,
max _id : this . min _id ,
}
} ) . then ( res => {
let d = res . data ;
if ( ! d . messages . length ) {
this . showLoadMore = false ;
this . loadingMessages = false ;
return ;
}
let cids = this . thread . messages . map ( m => m . id ) ;
let m = d . messages . filter ( m => {
return cids . indexOf ( m . id ) == - 1 ;
} ) . reverse ( ) ;
let mids = m . map ( m => m . id ) ;
let min _id = Math . min ( ... mids ) ;
if ( min _id == this . min _id ) {
this . showLoadMore = false ;
this . loadingMessages = false ;
return ;
}
this . min _id = min _id ;
this . thread . messages . unshift ( ... m ) ;
setTimeout ( function ( ) {
self . loadingMessages = false ;
} , 500 ) ;
} ) . catch ( err => {
this . loadingMessages = false ;
} )
} ,
messagePoll ( ) {
let self = this ;
setInterval ( function ( ) {
2020-11-18 21:31:59 +00:00
axios . get ( '/api/direct/thread' , {
2020-11-18 21:19:02 +00:00
params : {
pid : self . accountId ,
min _id : self . thread . messages [ self . thread . messages . length - 1 ] . id
}
} ) . then ( res => {
} ) ;
} , 5000 ) ;
} ,
showOptions ( ) {
this . page = 'options' ;
2020-11-19 02:51:08 +00:00
} ,
updateOptions ( ) {
let options = {
v : 1 ,
hideAvatars : this . hideAvatars ,
hideTimestamps : this . hideTimestamps ,
largerText : this . largerText
}
window . localStorage . setItem ( 'px_dm_options' , JSON . stringify ( options ) ) ;
2020-11-18 21:19:02 +00:00
}
}
}
2021-07-11 08:57:14 +00:00
< / script >