forked from AkkomaGang/akkoma-fe
do the impossible, fix the unfixable
This commit is contained in:
parent
636dbdaba8
commit
c21b1cf898
8 changed files with 118 additions and 41 deletions
|
@ -5,6 +5,7 @@ import { convertHtmlToTree } from 'src/services/html_converter/html_tree_convert
|
||||||
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
||||||
import StillImage from 'src/components/still-image/still-image.vue'
|
import StillImage from 'src/components/still-image/still-image.vue'
|
||||||
import MentionLink from 'src/components/mention_link/mention_link.vue'
|
import MentionLink from 'src/components/mention_link/mention_link.vue'
|
||||||
|
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
||||||
|
|
||||||
import './rich_content.scss'
|
import './rich_content.scss'
|
||||||
|
|
||||||
|
@ -51,6 +52,11 @@ export default Vue.component('RichContent', {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
hideMentions: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// NEVER EVER TOUCH DATA INSIDE RENDER
|
// NEVER EVER TOUCH DATA INSIDE RENDER
|
||||||
|
@ -64,6 +70,7 @@ export default Vue.component('RichContent', {
|
||||||
// unique index for vue "tag" property
|
// unique index for vue "tag" property
|
||||||
let mentionIndex = 0
|
let mentionIndex = 0
|
||||||
let tagsIndex = 0
|
let tagsIndex = 0
|
||||||
|
let firstMentionReplaced = false
|
||||||
|
|
||||||
const renderImage = (tag) => {
|
const renderImage = (tag) => {
|
||||||
return <StillImage
|
return <StillImage
|
||||||
|
@ -90,7 +97,12 @@ export default Vue.component('RichContent', {
|
||||||
writtenMentions.push(linkData)
|
writtenMentions.push(linkData)
|
||||||
if (!encounteredText) {
|
if (!encounteredText) {
|
||||||
firstMentions.push(linkData)
|
firstMentions.push(linkData)
|
||||||
return ''
|
if (!firstMentionReplaced && !this.hideMentions) {
|
||||||
|
firstMentionReplaced = true
|
||||||
|
return <MentionsLine mentions={ firstMentions } />
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return <MentionLink
|
return <MentionLink
|
||||||
url={attrs.href}
|
url={attrs.href}
|
||||||
|
@ -143,7 +155,7 @@ export default Vue.component('RichContent', {
|
||||||
if (firstMentions.length > 1 && lastMentions.length > 1) {
|
if (firstMentions.length > 1 && lastMentions.length > 1) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return !this.hideMentions ? <MentionsLine mentions={lastMentions} /> : ''
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import fileType from 'src/services/file_type/file_type.service'
|
import fileType from 'src/services/file_type/file_type.service'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
|
@ -36,9 +35,6 @@ const StatusContent = {
|
||||||
showingLongSubject: false,
|
showingLongSubject: false,
|
||||||
// not as computed because it sets the initial state which will be changed later
|
// not as computed because it sets the initial state which will be changed later
|
||||||
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject,
|
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject,
|
||||||
headTailLinks: null,
|
|
||||||
firstMentions: [],
|
|
||||||
lastMentions: []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -81,8 +77,7 @@ const StatusContent = {
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
RichContent,
|
RichContent
|
||||||
MentionsLine
|
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.status.attentions && this.status.attentions.forEach(attn => {
|
this.status.attentions && this.status.attentions.forEach(attn => {
|
||||||
|
@ -98,11 +93,6 @@ const StatusContent = {
|
||||||
this.expandingSubject = !this.expandingSubject
|
this.expandingSubject = !this.expandingSubject
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setHeadTailLinks (headTailLinks) {
|
|
||||||
set(this, 'headTailLinks', headTailLinks)
|
|
||||||
set(this, 'firstMentions', headTailLinks.firstMentions)
|
|
||||||
set(this, 'lastMentions', headTailLinks.lastMentions)
|
|
||||||
},
|
|
||||||
generateTagLink (tag) {
|
generateTagLink (tag) {
|
||||||
return `/tag/${tag}`
|
return `/tag/${tag}`
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
.rich-content-wrapper {
|
.media-body {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
mask:
|
mask:
|
||||||
linear-gradient(to top, white, transparent) bottom/100% 70px no-repeat,
|
linear-gradient(to top, white, transparent) bottom/100% 70px no-repeat,
|
||||||
|
|
|
@ -38,28 +38,17 @@
|
||||||
>
|
>
|
||||||
{{ $t("general.show_more") }}
|
{{ $t("general.show_more") }}
|
||||||
</button>
|
</button>
|
||||||
<span
|
<RichContent
|
||||||
v-if="!hideSubjectStatus && !(singleLine && status.summary_raw_html)"
|
v-if="!hideSubjectStatus && !(singleLine && status.summary_raw_html)"
|
||||||
class="rich-content-wrapper"
|
:class="{ '-single-line': singleLine }"
|
||||||
>
|
class="text media-body"
|
||||||
<MentionsLine
|
:html="status.raw_html"
|
||||||
v-if="!hideMentions && firstMentions && firstMentions.length > 0"
|
:emoji="status.emojis"
|
||||||
:mentions="firstMentions"
|
:handle-links="true"
|
||||||
/>
|
:hide-mentions="hideMentions"
|
||||||
<RichContent
|
:greentext="mergedConfig.greentext"
|
||||||
:class="{ '-single-line': singleLine }"
|
@parseReady="$emit('parseReady', $event)"
|
||||||
class="text media-body"
|
/>
|
||||||
:html="status.raw_html"
|
|
||||||
:emoji="status.emojis"
|
|
||||||
:handle-links="true"
|
|
||||||
:greentext="mergedConfig.greentext"
|
|
||||||
@parseReady="setHeadTailLinks"
|
|
||||||
/>
|
|
||||||
<MentionsLine
|
|
||||||
v-if="!hideMentions && lastMentions.length > 1 && firstMentions.length <= 1"
|
|
||||||
:mentions="lastMentions"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="hideSubjectStatus"
|
v-if="hideSubjectStatus"
|
||||||
|
|
|
@ -92,9 +92,6 @@ const StatusContent = {
|
||||||
StatusBody
|
StatusBody
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setHeadTailLinks (headTailLinks) {
|
|
||||||
this.$emit('parseReady', headTailLinks)
|
|
||||||
},
|
|
||||||
setMedia () {
|
setMedia () {
|
||||||
const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
|
const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
|
||||||
return () => this.$store.dispatch('setMedia', attachments)
|
return () => this.$store.dispatch('setMedia', attachments)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
:status="status"
|
:status="status"
|
||||||
:single-line="singleLine"
|
:single-line="singleLine"
|
||||||
:hide-mentions="hideMentions"
|
:hide-mentions="hideMentions"
|
||||||
@parseReady="setHeadTailLinks"
|
@parseReady="$emit('parseReady', $event)"
|
||||||
>
|
>
|
||||||
<div v-if="status.poll && status.poll.options">
|
<div v-if="status.poll && status.poll.options">
|
||||||
<poll :base-poll="status.poll" />
|
<poll :base-poll="status.poll" />
|
||||||
|
|
|
@ -16,6 +16,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -38,6 +39,34 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
|
handleLinks: true,
|
||||||
|
greentext: true,
|
||||||
|
emoji: [],
|
||||||
|
html
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('replaces first mention with mentionsline if hideMentions=false', () => {
|
||||||
|
const html = p(
|
||||||
|
makeMention('John'),
|
||||||
|
' how are you doing thoday?'
|
||||||
|
)
|
||||||
|
const expected = p(
|
||||||
|
'<span class="h-card">',
|
||||||
|
'<mentionsline-stub mentions="',
|
||||||
|
'[object Object]',
|
||||||
|
'"></mentionsline-stub>',
|
||||||
|
'</span>',
|
||||||
|
'how are you doing thoday?'
|
||||||
|
)
|
||||||
|
const wrapper = shallowMount(RichContent, {
|
||||||
|
localVue,
|
||||||
|
propsData: {
|
||||||
|
hideMentions: false,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -68,6 +97,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -78,6 +108,44 @@ describe('RichContent', () => {
|
||||||
expect(wrapper.html()).to.eql(compwrap(expected))
|
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('replaces mentions at the end of the hellpost if hideMentions=false (<p>)', () => {
|
||||||
|
const html = [
|
||||||
|
p('How are you doing today, fine gentlemen?'),
|
||||||
|
p(
|
||||||
|
makeMention('John'),
|
||||||
|
makeMention('Josh'),
|
||||||
|
makeMention('Jeremy')
|
||||||
|
)
|
||||||
|
].join('')
|
||||||
|
const expected = [
|
||||||
|
p(
|
||||||
|
'How are you doing today, fine gentlemen?'
|
||||||
|
),
|
||||||
|
// TODO fix this extra line somehow?
|
||||||
|
p(
|
||||||
|
'<mentionsline-stub mentions="',
|
||||||
|
'[object Object],',
|
||||||
|
'[object Object],',
|
||||||
|
'[object Object]',
|
||||||
|
'"></mentionsline-stub>'
|
||||||
|
)
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
const wrapper = shallowMount(RichContent, {
|
||||||
|
localVue,
|
||||||
|
propsData: {
|
||||||
|
hideMentions: false,
|
||||||
|
handleLinks: true,
|
||||||
|
greentext: true,
|
||||||
|
emoji: [],
|
||||||
|
html
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
it('removes mentions from the end of the hellpost (<br>)', () => {
|
it('removes mentions from the end of the hellpost (<br>)', () => {
|
||||||
const html = [
|
const html = [
|
||||||
'How are you doing today, fine gentlemen?',
|
'How are you doing today, fine gentlemen?',
|
||||||
|
@ -96,6 +164,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -124,6 +193,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -165,6 +235,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -199,6 +270,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -240,6 +312,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -267,6 +340,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: false,
|
handleLinks: false,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -290,6 +364,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: false,
|
handleLinks: false,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -309,6 +384,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: false,
|
handleLinks: false,
|
||||||
greentext: false,
|
greentext: false,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -329,6 +405,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: false,
|
handleLinks: false,
|
||||||
greentext: false,
|
greentext: false,
|
||||||
emoji: [{ url: 'about:blank', shortcode: 'spurdo' }],
|
emoji: [{ url: 'about:blank', shortcode: 'spurdo' }],
|
||||||
|
@ -345,6 +422,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: false,
|
handleLinks: false,
|
||||||
greentext: false,
|
greentext: false,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -407,6 +485,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -425,10 +504,18 @@ describe('RichContent', () => {
|
||||||
makeMention('bar'),
|
makeMention('bar'),
|
||||||
makeMention('baz')
|
makeMention('baz')
|
||||||
].join('<br>')
|
].join('<br>')
|
||||||
|
const expected = [
|
||||||
|
'Bruh',
|
||||||
|
'Bruh',
|
||||||
|
stubMention('foo'),
|
||||||
|
stubMention('bar'),
|
||||||
|
stubMention('baz')
|
||||||
|
].join('<br>')
|
||||||
|
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -436,7 +523,7 @@ describe('RichContent', () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(wrapper.html()).to.eql(compwrap(html))
|
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Don\'t remove last mentions if there are more than one first mention - remove first instead', () => {
|
it('Don\'t remove last mentions if there are more than one first mention - remove first instead', () => {
|
||||||
|
@ -471,6 +558,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
@ -506,6 +594,7 @@ describe('RichContent', () => {
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
localVue,
|
localVue,
|
||||||
propsData: {
|
propsData: {
|
||||||
|
hideMentions: true,
|
||||||
handleLinks: true,
|
handleLinks: true,
|
||||||
greentext: true,
|
greentext: true,
|
||||||
emoji: [],
|
emoji: [],
|
||||||
|
|
|
@ -11,7 +11,7 @@ const mapOnlyText = (processor) => (input) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe.only('html_line_converter', () => {
|
describe('html_line_converter', () => {
|
||||||
describe('with processor that keeps original line should not make any changes to HTML when', () => {
|
describe('with processor that keeps original line should not make any changes to HTML when', () => {
|
||||||
const processorKeep = (line) => line
|
const processorKeep = (line) => line
|
||||||
it('fed with regular HTML with newlines', () => {
|
it('fed with regular HTML with newlines', () => {
|
||||||
|
|
Loading…
Reference in a new issue