2021-06-07 15:41:55 +00:00
import fileType from 'src/services/file_type/file_type.service'
2021-06-11 10:38:08 +00:00
import RichContent from 'src/components/rich_content/rich_content.jsx'
2021-06-07 15:41:55 +00:00
import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faFile ,
faMusic ,
faImage ,
faLink ,
faPollH
} from '@fortawesome/free-solid-svg-icons'
2022-08-30 14:43:57 +00:00
import Select from 'src/components/select/select.vue'
2021-06-07 15:41:55 +00:00
library . add (
faFile ,
faMusic ,
faImage ,
faLink ,
faPollH
)
const StatusContent = {
name : 'StatusContent' ,
props : [
2021-06-13 23:52:41 +00:00
'compact' ,
2021-06-07 15:41:55 +00:00
'status' ,
'focused' ,
'noHeading' ,
'fullContent' ,
2021-09-09 04:03:10 +00:00
'singleLine' ,
'showingTall' ,
'expandingSubject' ,
'showingLongSubject' ,
'toggleShowingTall' ,
'toggleExpandingSubject' ,
'toggleShowingLongSubject'
2021-06-07 15:41:55 +00:00
] ,
data ( ) {
2022-06-14 14:57:02 +00:00
const { renderMisskeyMarkdown } = this . $store . getters . mergedConfig
2021-06-07 15:41:55 +00:00
return {
2021-08-14 23:55:45 +00:00
postLength : this . status . text . length ,
2022-06-14 14:57:02 +00:00
parseReadyDone : false ,
2022-08-30 14:43:57 +00:00
renderMisskeyMarkdown ,
translateFrom : null
2021-06-07 15:41:55 +00:00
}
} ,
computed : {
localCollapseSubjectDefault ( ) {
return this . mergedConfig . collapseMessageWithSubject
} ,
// This is a bit hacky, but we want to approximate post height before rendering
// so we count newlines (masto uses <p> for paragraphs, GS uses <br> between them)
// as well as approximate line count by counting characters and approximating ~80
// per line.
//
// Using max-height + overflow: auto for status components resulted in false positives
// very often with japanese characters, and it was very annoying.
tallStatus ( ) {
2021-08-15 15:21:25 +00:00
if ( this . singleLine || this . compact ) return false
2021-08-14 23:41:53 +00:00
const lengthScore = this . status . raw _html . split ( /<p|<br/ ) . length + this . postLength / 80
2021-06-07 15:41:55 +00:00
return lengthScore > 20
} ,
longSubject ( ) {
return this . status . summary . length > 240
} ,
// When a status has a subject and is also tall, we should only have one show more/less button. If the default is to collapse statuses with subjects, we just treat it like a status with a subject; otherwise, we just treat it like a tall status.
mightHideBecauseSubject ( ) {
return ! ! this . status . summary && this . localCollapseSubjectDefault
} ,
mightHideBecauseTall ( ) {
return this . tallStatus && ! ( this . status . summary && this . localCollapseSubjectDefault )
} ,
hideSubjectStatus ( ) {
return this . mightHideBecauseSubject && ! this . expandingSubject
} ,
hideTallStatus ( ) {
return this . mightHideBecauseTall && ! this . showingTall
} ,
showingMore ( ) {
return ( this . mightHideBecauseTall && this . showingTall ) || ( this . mightHideBecauseSubject && this . expandingSubject )
} ,
attachmentTypes ( ) {
return this . status . attachments . map ( file => fileType . fileType ( file . mimetype ) )
} ,
2022-08-30 14:43:57 +00:00
translationLanguages ( ) {
2022-10-06 15:59:16 +00:00
return ( this . $store . state . instance . supportedTranslationLanguages . source || [ ] ) . map ( lang => ( { key : lang . code , value : lang . code , label : lang . name } ) )
2022-08-30 14:43:57 +00:00
} ,
2021-06-07 16:50:26 +00:00
... mapGetters ( [ 'mergedConfig' ] )
2021-06-07 15:41:55 +00:00
} ,
components : {
2022-08-30 14:43:57 +00:00
RichContent ,
Select
2021-06-07 15:41:55 +00:00
} ,
mounted ( ) {
2021-06-07 16:50:26 +00:00
this . status . attentions && this . status . attentions . forEach ( attn => {
2021-06-07 15:41:55 +00:00
const { id } = attn
this . $store . dispatch ( 'fetchUserIfMissing' , id )
} )
} ,
methods : {
2021-06-22 17:16:26 +00:00
onParseReady ( event ) {
2021-08-14 23:55:45 +00:00
if ( this . parseReadyDone ) return
this . parseReadyDone = true
2021-06-22 17:16:26 +00:00
this . $emit ( 'parseReady' , event )
2021-08-14 23:41:53 +00:00
const { writtenMentions , invisibleMentions } = event
2021-06-22 17:16:26 +00:00
writtenMentions
. filter ( mention => ! mention . notifying )
. forEach ( mention => {
const { content , url } = mention
const cleanedString = content . replace ( /<[^>]+?>/gi , '' ) // remove all tags
if ( ! cleanedString . startsWith ( '@' ) ) return
const handle = cleanedString . slice ( 1 )
const host = url . replace ( /^https?:\/\// , '' ) . replace ( /\/.+?$/ , '' )
this . $store . dispatch ( 'fetchUserIfMissing' , ` ${ handle } @ ${ host } ` )
} )
2021-08-14 23:41:53 +00:00
/ * T h i s i s a b i t o f a h a c k t o m a k e c u r r e n t t a l l s t a t u s d e t e c t o r w o r k
* with rich mentions . Invisible mentions are detected at RichContent level
* and also we generate plaintext version of mentions by stripping tags
* so here we subtract from post length by each mention that became invisible
* via MentionsLine
* /
this . postLength = invisibleMentions . reduce ( ( acc , mention ) => {
return acc - mention . textContent . length - 1
} , this . postLength )
2021-06-22 17:16:26 +00:00
} ,
2021-06-07 15:41:55 +00:00
toggleShowMore ( ) {
if ( this . mightHideBecauseTall ) {
2021-09-09 04:03:10 +00:00
this . toggleShowingTall ( )
2021-06-07 15:41:55 +00:00
} else if ( this . mightHideBecauseSubject ) {
2021-09-09 04:03:10 +00:00
this . toggleExpandingSubject ( )
2021-06-07 15:41:55 +00:00
}
} ,
generateTagLink ( tag ) {
return ` /tag/ ${ tag } `
2022-08-30 14:43:57 +00:00
} ,
translateStatus ( ) {
const translateTo = this . $store . getters . mergedConfig . translationLanguage || this . $store . state . instance . interfaceLanguage
this . $store . dispatch ( 'translateStatus' , { id : this . status . id , language : translateTo , from : this . translateFrom } )
2021-06-07 15:41:55 +00:00
}
}
}
export default StatusContent