2022-08-16 20:29:57 -04:00
import * as tfrpc from '/static/tfrpc.js' ;
2022-06-19 18:08:15 -04:00
import * as tfshared from './tf-shared.js' ;
2022-07-27 21:20:09 -04:00
import * as tf from './tf.js' ;
2022-08-16 20:29:57 -04:00
import * as emojis from './emojis.js' ;
2022-06-19 18:08:15 -04:00
2022-02-26 21:30:11 -05:00
Vue . component ( 'tf-message' , {
props : [ 'message' , 'messages' , 'votes' ] ,
data : function ( ) { return { showRaw : false } } ,
computed : {
content _json : function ( ) {
try {
return JSON . parse ( this . message . content ) ;
} catch {
return undefined ;
}
} ,
content _raw : function ( ) {
try {
return JSON . stringify ( JSON . parse ( this . message . content ) , null , 2 ) ;
} catch {
return this . message . content ;
}
} ,
timestamp _relative : function ( ) {
var units = [
{ value : 1 , name : 'milliseconds' } ,
{ value : 1000 , name : 'seconds' } ,
{ value : 1000 * 60 , name : 'minutes' } ,
{ value : 1000 * 60 * 60 , name : 'hours' } ,
{ value : 1000 * 60 * 60 * 24 , name : 'days' } ,
{ value : 1000 * 60 * 60 * 24 * 7 , name : 'weeks' } ,
{ value : 1000 * 60 * 60 * 24 * 30 , name : 'months' } ,
{ value : 1000 * 60 * 60 * 24 * 365 , name : 'years' } ,
] ;
var v = new Date ( ) . valueOf ( ) - this . message . timestamp ;
var result = null ;
for ( let unit of units ) {
if ( v >= unit . value ) {
result = Math . round ( v / unit . value ) + ' ' + unit . name + ' ago' ;
}
}
return result ;
} ,
} ,
methods : {
2022-06-19 18:08:15 -04:00
markdown : tfshared . markdown ,
2022-02-26 21:30:11 -05:00
set _reply : function ( ) {
2022-07-27 21:20:09 -04:00
tf . g _data . reply _root = this . content _json . root || this . message . id ;
tf . g _data . reply _branch = this . message . id ;
2022-02-26 21:30:11 -05:00
} ,
2022-08-16 20:29:57 -04:00
vote : function ( emoji ) {
let reaction = emoji . emoji ;
2022-02-26 21:30:11 -05:00
var message = this . message . id ;
if ( confirm ( 'Are you sure you want to react with ' + reaction + ' to ' + message + '?' ) ) {
2022-08-16 20:29:57 -04:00
tfrpc . rpc . appendMessage ( {
type : 'vote' ,
vote : {
link : message ,
value : 1 ,
expression : reaction ,
2022-02-26 21:30:11 -05:00
} ,
2022-08-16 20:29:57 -04:00
} ) . catch ( function ( error ) {
alert ( error ? . message ) ;
} ) ;
2022-02-26 21:30:11 -05:00
}
} ,
2022-08-16 20:29:57 -04:00
show _emoji _picker : function ( event ) {
let self = this ;
emojis . picker ( x => self . vote ( x ) , event . srcElement ) ;
} ,
2022-02-26 21:30:11 -05:00
show _message : function ( ) {
2022-08-03 19:26:41 -04:00
window . parent . postMessage ( {
action : 'setHash' ,
2022-08-13 15:39:29 -04:00
hash : this . message . id ,
2022-08-03 19:26:41 -04:00
} , '*' ) ;
2022-02-26 21:30:11 -05:00
} ,
expand _image : function ( event ) {
var div = document . createElement ( 'div' ) ;
div . style . left = 0 ;
div . style . top = 0 ;
div . style . width = '100%' ;
div . style . height = '100%' ;
div . style . position = 'fixed' ;
div . style . background = '#000' ;
div . style . zIndex = 100 ;
div . style . display = 'grid' ;
var img = document . createElement ( 'img' ) ;
img . src = event . srcElement . src ;
img . style . maxWidth = '100%' ;
img . style . maxHeight = '100%' ;
img . style . display = 'block' ;
img . style . margin = 'auto' ;
img . style . objectFit = 'contain' ;
img . style . width = '100%' ;
div . appendChild ( img ) ;
2022-08-13 15:39:29 -04:00
function image _close ( event ) {
document . body . removeChild ( div ) ;
window . removeEventListener ( 'keydown' , image _close ) ;
}
div . onclick = image _close ;
window . addEventListener ( 'keydown' , image _close ) ;
2022-02-26 21:30:11 -05:00
document . body . appendChild ( div ) ;
} ,
} ,
template : ` <md-app class="md-elevation-8" style="margin: 1em" v-if="!content_json || ['pub', 'vote'].indexOf(content_json.type) == -1">
< md - app - toolbar >
< h3 >
< md - button class = "md-icon-button md-dense" @ click = "show_message" >
< md - icon > percent < / m d - i c o n >
< / m d - b u t t o n >
< tf - user : id = "message.author" v - if = "message.author" > < / t f - u s e r >
< / h 3 >
< template v - if = "message.author" >
< div style = "font-size: x-small" >
{ { timestamp _relative } }
< md - tooltip style = "height: auto" >
< div > { { new Date ( message . timestamp ) } } < / d i v >
< div > { { message . id } } < / d i v >
< / m d - t o o l t i p >
< / d i v >
< div class = "md-toolbar-section-end" >
< md - menu >
< md - switch v - model = "showRaw" > < / m d - s w i t c h >
< md - tooltip > Show Raw Message < / m d - t o o l t i p >
< / m d - m e n u >
< / d i v >
< / t e m p l a t e >
< template v - else >
< h3 > Missing < / h 3 >
< / t e m p l a t e >
< / m d - a p p - t o o l b a r >
< md - app - content >
< template v - if = "message.author" >
< div v - if = "showRaw" >
< h1 > { { message . id } } < / h 1 >
< pre style = "word-wrap: break-all; white-space: pre-wrap" > { { content _raw } } < / p r e >
< / d i v >
< div v - else >
< div v - if = "content_json && content_json.type == 'post'" >
< div v - html = "this.markdown(content_json.text)" > < / d i v >
< span v - for = "mention in content_json.mentions" v - if = "mention.link && typeof(mention.link) == 'string' && mention.link.startsWith('&')" >
< a v - if = "mention.type == 'application/tildefriends'" : href = "'/' + mention.link + '/'" target = "_top" > { { mention . name } } < / a >
2022-06-19 17:05:34 -04:00
< div v - else - if = "mention.name && mention.name.startsWith('audio:')" >
< audio controls style = "height: 32px" >
< source : src = "'/' + mention.link + '/view'" > < / s o u r c e >
< / a u d i o >
< / d i v >
2022-02-26 21:30:11 -05:00
< img v - else class = "md-elevation-4" style = "margin: 4px; max-width: 320px; max-height: 240px" : src = "'/' + mention.link + '/view'" v - on : click = "expand_image" > < / i m g >
< / s p a n >
< / d i v >
< div v - else - if = "content_json && content_json.type == 'tildefriends-app'" >
< div v - html = "this.markdown(content_json.text)" > < / d i v >
< md - button target = "_top" : href = "'/' + message.id + '/'" > { { content _json . name || 'tildefriends-app' } } < / m d - b u t t o n >
< / d i v >
< div v - else - if = "content_json && content_json.type == 'contact'" > < tf - user : id = "message.author" > < /tf-user> {{content_json.following ? '==>' : '=/ = & gt ; ' } } < tf - user : id = "content_json.contact" > < / t f - u s e r > < / d i v >
< div v - else > { { message . content } } < / d i v >
< / d i v >
< / t e m p l a t e >
< template v - else >
{ { message . id } }
< / t e m p l a t e >
< tf - message v - for = "sub_message in (message.children || [])" v - bind : message = "sub_message" v - bind : messages = "messages" v - bind : votes = "votes" v - bind : key = "sub_message.id" > < / t f - m e s s a g e >
< md - chip md - clickable v - for = "v in Object.keys(votes[message.id] || {})" v - bind : key = "v" @ click = "vote" >
{ { v + ( votes [ message . id ] [ v ] . length > 1 ? ' (' + votes [ message . id ] [ v ] . length + ')' : '' ) } }
2022-05-25 20:03:46 -04:00
< md - tooltip style = "height: auto; background-color: #000; border: 1px solid #fff" >
2022-04-14 19:47:41 -04:00
< tf - user v - for = "vote in votes[message.id][v]" : id = "vote.author" : key = "vote.author" > < / t f - u s e r >
2022-02-26 21:30:11 -05:00
< / m d - t o o l t i p >
< / m d - c h i p >
< md - card - actions v - if = "message.author" >
< md - button class = "md-icon-button" @ click = "set_reply" >
< md - icon > reply < / m d - i c o n >
< / m d - b u t t o n >
< md - menu >
2022-08-16 20:29:57 -04:00
< md - button class = "md-icon-button" @ click = "show_emoji_picker" >
2022-02-26 21:30:11 -05:00
< md - icon > thumb _up < / m d - i c o n >
< / m d - b u t t o n >
< / m d - m e n u >
< / m d - c a r d - a c t i o n s >
< / m d - a p p - c o n t e n t >
< / m d - a p p > ` ,
} ) ;