do the impossible, fix the unfixable

This commit is contained in:
Henry Jameson 2021-06-14 10:30:08 +03:00
parent 636dbdaba8
commit c21b1cf898
8 changed files with 118 additions and 41 deletions

View file

@ -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)
if (!firstMentionReplaced && !this.hideMentions) {
firstMentionReplaced = true
return <MentionsLine mentions={ firstMentions } />
} else {
return '' 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

View file

@ -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}`
} }

View file

@ -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,

View file

@ -38,28 +38,17 @@
> >
{{ $t("general.show_more") }} {{ $t("general.show_more") }}
</button> </button>
<span
v-if="!hideSubjectStatus && !(singleLine && status.summary_raw_html)"
class="rich-content-wrapper"
>
<MentionsLine
v-if="!hideMentions && firstMentions && firstMentions.length > 0"
:mentions="firstMentions"
/>
<RichContent <RichContent
v-if="!hideSubjectStatus && !(singleLine && status.summary_raw_html)"
:class="{ '-single-line': singleLine }" :class="{ '-single-line': singleLine }"
class="text media-body" class="text media-body"
:html="status.raw_html" :html="status.raw_html"
:emoji="status.emojis" :emoji="status.emojis"
:handle-links="true" :handle-links="true"
:hide-mentions="hideMentions"
:greentext="mergedConfig.greentext" :greentext="mergedConfig.greentext"
@parseReady="setHeadTailLinks" @parseReady="$emit('parseReady', $event)"
/> />
<MentionsLine
v-if="!hideMentions && lastMentions.length > 1 && firstMentions.length <= 1"
:mentions="lastMentions"
/>
</span>
<button <button
v-if="hideSubjectStatus" v-if="hideSubjectStatus"

View file

@ -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)

View file

@ -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" />

View file

@ -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: [],

View file

@ -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', () => {