From 2cfff1b8b9c642e9284483d6658312d9a3763417 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Aug 2021 02:49:37 +0300
Subject: remove new options for style and separate line, now groups all
 chained mentions on a mentionsline regardless of placement. fixes spacing

---
 src/components/rich_content/rich_content.jsx | 128 ++++++---------------------
 1 file changed, 29 insertions(+), 99 deletions(-)

(limited to 'src/components/rich_content/rich_content.jsx')

diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index cd73f2e5..4b7d4d37 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -56,25 +56,21 @@ export default Vue.component('RichContent', {
       required: false,
       type: Boolean,
       default: false
-    },
-    hideMentions: {
-      required: false,
-      type: Boolean,
-      default: false
     }
   },
   // NEVER EVER TOUCH DATA INSIDE RENDER
   render (h) {
     // Pre-process HTML
-    const { newHtml: html, lastMentions } = preProcessPerLine(this.html, this.greentext, this.handleLinks)
-    const firstMentions = [] // Mentions that appear in the beginning of post body
+    const { newHtml: html } = preProcessPerLine(this.html, this.greentext, this.handleLinks)
+    let currentMentions = null // Current chain of mentions, we group all mentions together
+    // to collapse too many mentions in a row
+
     const lastTags = [] // Tags that appear at the end of post body
     const writtenMentions = [] // All mentions that appear in post body
     const writtenTags = [] // All tags that appear in post body
     // unique index for vue "tag" property
     let mentionIndex = 0
     let tagsIndex = 0
-    let firstMentionReplaced = false
 
     const renderImage = (tag) => {
       return <StillImage
@@ -98,41 +94,32 @@ export default Vue.component('RichContent', {
     const renderMention = (attrs, children) => {
       const linkData = getLinkData(attrs, children, mentionIndex++)
       linkData.notifying = this.attentions.some(a => a.statusnet_profile_url === linkData.url)
-      if (!linkData.notifying) {
-        encounteredText = true
-      }
       writtenMentions.push(linkData)
-      if (!encounteredText) {
-        firstMentions.push(linkData)
-        if (!firstMentionReplaced && !this.hideMentions) {
-          firstMentionReplaced = true
-          return <MentionsLine mentions={ firstMentions } />
-        } else {
-          return ''
-        }
+      if (currentMentions === null) {
+        currentMentions = []
+      }
+      currentMentions.push(linkData)
+      if (currentMentions.length === 1) {
+        return <MentionsLine mentions={ currentMentions } />
       } else {
-        return <MentionLink
-          url={attrs.href}
-          content={flattenDeep(children).join('')}
-        />
+        return ''
       }
     }
 
-    // We stop treating mentions as "first" ones when we encounter
-    // non-whitespace text
-    let encounteredText = false
     // Processor to use with html_tree_converter
     const processItem = (item, index, array, what) => {
       // Handle text nodes - just add emoji
       if (typeof item === 'string') {
         const emptyText = item.trim() === ''
-        if (emptyText) {
-          return encounteredText ? item : item.trim()
+        if (item.includes('\n')) {
+          currentMentions = null
         }
-        if (!encounteredText) {
-          item = item.trimStart()
-          encounteredText = true
+        if (emptyText) {
+          // don't include spaces when processing mentions - we'll include them
+          // in MentionsLine
+          return currentMentions !== null ? item.trim() : item
         }
+        currentMentions = null
         if (item.includes(':')) {
           item = ['', processTextForEmoji(
             item,
@@ -156,28 +143,25 @@ export default Vue.component('RichContent', {
         const Tag = getTagName(opener)
         const attrs = getAttrs(opener)
         switch (Tag) {
-          case 'span': // Replace last mentions class with mentionsline
-            if (attrs['class'] && attrs['class'].includes('lastMentions')) {
-              if (firstMentions.length > 1 && lastMentions.length > 1) {
-                break
-              } else {
-                return !this.hideMentions ? <MentionsLine mentions={lastMentions} /> : ''
-              }
-            } else {
-              break
-            }
+          case 'br':
+            currentMentions = null
+            break
           case 'img': // replace images with StillImage
             return renderImage(opener)
           case 'a': // replace mentions with MentionLink
             if (!this.handleLinks) break
             if (attrs['class'] && attrs['class'].includes('mention')) {
               // Handling mentions here
-              return renderMention(attrs, children, encounteredText)
+              return renderMention(attrs, children)
             } else {
               // Everything else will be handled in reverse pass
-              encounteredText = true
+              currentMentions = null
               return item // We'll handle it later
             }
+          case 'span':
+            if (attrs['class'].includes('h-card')) {
+              return ['', children.map(processItem), '']
+            }
         }
 
         if (children !== undefined) {
@@ -246,8 +230,6 @@ export default Vue.component('RichContent', {
     </span>
 
     const event = {
-      firstMentions,
-      lastMentions,
       lastTags,
       writtenMentions,
       writtenTags
@@ -284,15 +266,12 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
   const lastMentions = []
   const greentextHandle = new Set(['p', 'div'])
 
-  let nonEmptyIndex = -1
   const lines = convertHtmlToLines(html)
-  const linesNum = lines.filter(c => c.text).length
   const newHtml = lines.reverse().map((item, index, array) => {
     // Going over each line in reverse to detect last mentions,
     // keeping non-text stuff as-is
     if (!item.text) return item
     const string = item.text
-    nonEmptyIndex += 1
 
     // Greentext stuff
     if (
@@ -316,42 +295,19 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
     // Converting that line part into tree
     const tree = convertHtmlToTree(string)
 
-    // If line has loose text, i.e. text outside a mention or a tag
-    // we won't touch mentions.
-    let hasLooseText = false
-    let mentionsNum = 0
     const process = (item) => {
       if (Array.isArray(item)) {
         const [opener, children, closer] = item
         const tag = getTagName(opener)
-        // If we have a link we probably have mentions
-        if (tag === 'a') {
-          if (!handleLinks) return [opener, children, closer]
-          const attrs = getAttrs(opener)
-          if (attrs['class'] && attrs['class'].includes('mention')) {
-            // Got mentions
-            mentionsNum++
-            return [opener, children, closer]
-          } else {
-            // Not a mention? Means we have loose text or whatever
-            hasLooseText = true
-            return [opener, children, closer]
-          }
-        } else if (tag === 'span' || tag === 'p') {
+        if (tag === 'span' || tag === 'p') {
           // For span and p we need to go deeper
           return [opener, [...children].map(process), closer]
         } else {
-          // Everything else equals to a loose text
-          hasLooseText = true
           return [opener, children, closer]
         }
       }
 
       if (typeof item === 'string') {
-        if (item.trim() !== '') {
-          // only meaningful strings are loose text
-          hasLooseText = true
-        }
         return item
       }
     }
@@ -359,33 +315,7 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
     // We now processed our tree, now we need to mark line as lastMentions
     const result = [...tree].map(process)
 
-    if (
-      handleLinks && // Do we handle links at all?
-        mentionsNum > 1 && // Does it have more than one mention?
-        !hasLooseText && // Don't do anything if it has something besides mentions
-        nonEmptyIndex === 0 && // Only check last (first since list is reversed) line
-        nonEmptyIndex !== linesNum - 1 // Don't do anything if there's only one line
-    ) {
-      let mentionIndex = 0
-      const process = (item) => {
-        if (Array.isArray(item)) {
-          const [opener, children] = item
-          const tag = getTagName(opener)
-          if (tag === 'a') {
-            const attrs = getAttrs(opener)
-            lastMentions.push(getLinkData(attrs, children, mentionIndex++))
-          } else if (children) {
-            children.forEach(process)
-          }
-        }
-      }
-      result.forEach(process)
-      // we DO need mentions here so that we conditionally remove them if don't
-      // have first mentions
-      return ['<span class="lastMentions">', flattenDeep(result).join(''), '</span>'].join('')
-    } else {
-      return flattenDeep(result).join('')
-    }
+    return flattenDeep(result).join('')
   }).reverse().join('')
 
   return { newHtml, lastMentions }
-- 
cgit v1.2.3-70-g09d2


From add5921b8b3579b153bef6ee2b1916227016d200 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 12 Aug 2021 19:37:04 +0300
Subject: fix tests, add performance test (skipped, doesn't assert anything),
 tweak max mentions count

---
 src/components/mention_link/mention_link.js     |   2 +-
 src/components/mentions_line/mentions_line.js   |   2 +-
 src/components/rich_content/rich_content.jsx    |   2 +-
 test/unit/specs/components/rich_content.spec.js | 126 +++++++++++++-----------
 4 files changed, 72 insertions(+), 60 deletions(-)

(limited to 'src/components/rich_content/rich_content.jsx')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index a60a8040..4d27fe6d 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -41,7 +41,7 @@ const MentionLink = {
   },
   computed: {
     user () {
-      return this.url && this.$store.getters.findUserByUrl(this.url)
+      return this.url && this.$store && this.$store.getters.findUserByUrl(this.url)
     },
     isYou () {
       // FIXME why user !== currentUser???
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index 33e25391..83eeea4c 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -15,7 +15,7 @@ const MentionsLine = {
   },
   computed: {
     limit () {
-      return 2
+      return 5
     },
     mentionsComputed () {
       return this.mentions.slice(0, this.limit)
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index 4b7d4d37..32b737ec 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -159,7 +159,7 @@ export default Vue.component('RichContent', {
               return item // We'll handle it later
             }
           case 'span':
-            if (attrs['class'].includes('h-card')) {
+            if (this.handleLinks && attrs['class'] && attrs['class'].includes('h-card')) {
               return ['', children.map(processItem), '']
             }
         }
diff --git a/test/unit/specs/components/rich_content.spec.js b/test/unit/specs/components/rich_content.spec.js
index dfc229c0..b29edeab 100644
--- a/test/unit/specs/components/rich_content.spec.js
+++ b/test/unit/specs/components/rich_content.spec.js
@@ -56,7 +56,7 @@ describe('RichContent', () => {
     expect(wrapper.html()).to.eql(compwrap(expected))
   })
 
-  it('replaces first mention with mentionsline', () => {
+  it('replaces mention with mentionsline', () => {
     const html = p(
       makeMention('John'),
       ' how are you doing today?'
@@ -234,7 +234,7 @@ describe('RichContent', () => {
     ].join('\n')
     const expected = [
       '<span class="greentext">&gt;quote</span>',
-      mentionsLine(1)
+      mentionsLine(1),
       '<span class="greentext">&gt;quote</span>',
       '<span class="greentext">&gt;quote</span>'
     ].join('\n')
@@ -267,7 +267,7 @@ describe('RichContent', () => {
     const expected = [
       'Bruh',
       'Bruh',
-      mentionsLine(3)
+      mentionsLine(3),
       'Bruh'
     ].join('<br>')
 
@@ -322,53 +322,6 @@ describe('RichContent', () => {
   })
 
   it('rich contents of a mention are handled properly', () => {
-    const html = [
-      p(
-        'Testing'
-      ),
-      p(
-        '<a href="lol" class="mention">',
-        '<span>',
-        'https://</span>',
-        '<span>',
-        'lol.tld/</span>',
-        '<span>',
-        '</span>',
-        '</a>'
-      )
-    ].join('')
-    const expected = [
-      p(
-        'Testing'
-      ),
-      p(
-        '<mentionlink-stub url="lol" content="',
-        '<span>',
-        'https://</span>',
-        '<span>',
-        'lol.tld/</span>',
-        '<span>',
-        '</span>',
-        '">',
-        '</mentionlink-stub>'
-      )
-    ].join('')
-
-    const wrapper = shallowMount(RichContent, {
-      localVue,
-      propsData: {
-        attentions,
-        handleLinks: true,
-        greentext: true,
-        emoji: [],
-        html
-      }
-    })
-
-    expect(wrapper.html()).to.eql(compwrap(expected))
-  })
-
-  it('rich contents of a mention in beginning are handled properly', () => {
     attentions.push({ statusnet_profile_url: 'lol' })
     const html = [
       p(
@@ -388,16 +341,19 @@ describe('RichContent', () => {
     const expected = [
       p(
         '<span class="MentionsLine">',
-        '<mentionlink-stub content="',
+        '<span class="MentionLink mention-link">',
+        '<a href="lol" target="_blank" class="original">',
         '<span>',
         'https://</span>',
         '<span>',
         'lol.tld/</span>',
         '<span>',
         '</span>',
-        '" url="lol" class="mention-link">',
-        '</mentionlink-stub>',
-        '<!---->', // v-if placeholder
+        '</a>',
+        ' ',
+        '<!---->', // v-if placeholder, mentionlink's "new" (i.e. rich) display
+        '</span>',
+        '<!---->', // v-if placeholder, mentionsline's extra mentions and stuff
         '</span>'
       ),
       p(
@@ -407,9 +363,6 @@ describe('RichContent', () => {
 
     const wrapper = mount(RichContent, {
       localVue,
-      stubs: {
-        MentionLink: true
-      },
       propsData: {
         attentions,
         handleLinks: true,
@@ -465,4 +418,63 @@ describe('RichContent', () => {
 
     expect(wrapper.html()).to.eql(compwrap(expected))
   })
+
+  it.skip('[INFORMATIVE] Performance testing, 10 000 simple posts', () => {
+    const amount = 20
+
+    const onePost = p(
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      makeMention('Lain'),
+      ' i just landed in l a where are you'
+    )
+
+    const TestComponent = {
+      template: `
+      <div v-if="!vhtml">
+        ${new Array(amount).fill(`<RichContent html="${onePost}" :greentext="true" :handleLinks="handeLinks" :emoji="[]" :attentions="attentions"/>`)}
+      </div>
+      <div v-else="vhtml">
+        ${new Array(amount).fill(`<div v-html="${onePost}"/>`)}
+      </div>
+      `,
+      props: ['handleLinks', 'attentions', 'vhtml']
+    }
+    console.log(1)
+
+    const ptest = (handleLinks, vhtml) => {
+      const t0 = performance.now()
+
+      const wrapper = mount(TestComponent, {
+        localVue,
+        propsData: {
+          attentions,
+          handleLinks,
+          vhtml
+        }
+      })
+
+      const t1 = performance.now()
+
+      wrapper.destroy()
+
+      const t2 = performance.now()
+
+      return `Mount: ${t1 - t0}ms, destroy: ${t2 - t1}ms, avg ${(t1 - t0) / amount}ms - ${(t2 - t1) / amount}ms per item`
+    }
+
+    console.log(`${amount} items with links handling:`)
+    console.log(ptest(true))
+    console.log(`${amount} items without links handling:`)
+    console.log(ptest(false))
+    console.log(`${amount} items plain v-html:`)
+    console.log(ptest(false, true))
+  })
 })
-- 
cgit v1.2.3-70-g09d2


From 530ac4442b498c90c73533d2a03ae5b7d6875900 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sun, 15 Aug 2021 02:41:53 +0300
Subject: removed useless code, review change, fixed bug with tall statuses

---
 src/components/mention_link/mention_link.js   |  2 +-
 src/components/mentions_line/mentions_line.js |  9 ++--
 src/components/rich_content/rich_content.jsx  | 69 +++++++++++----------------
 src/components/status_body/status_body.js     | 16 +++++--
 4 files changed, 45 insertions(+), 51 deletions(-)

(limited to 'src/components/rich_content/rich_content.jsx')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 4d27fe6d..65c62baa 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -45,7 +45,7 @@ const MentionLink = {
     },
     isYou () {
       // FIXME why user !== currentUser???
-      return this.user && this.user.screen_name === this.currentUser.screen_name
+      return this.user && this.user.id === this.currentUser.id
     },
     userName () {
       return this.user && this.userNameFullUi.split('@')[0]
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index 83eeea4c..a4a0c724 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -1,6 +1,8 @@
 import MentionLink from 'src/components/mention_link/mention_link.vue'
 import { mapGetters } from 'vuex'
 
+export const MENTIONS_LIMIT = 5
+
 const MentionsLine = {
   name: 'MentionsLine',
   props: {
@@ -14,14 +16,11 @@ const MentionsLine = {
     MentionLink
   },
   computed: {
-    limit () {
-      return 5
-    },
     mentionsComputed () {
-      return this.mentions.slice(0, this.limit)
+      return this.mentions.slice(0, MENTIONS_LIMIT)
     },
     extraMentions () {
-      return this.mentions.slice(this.limit)
+      return this.mentions.slice(MENTIONS_LIMIT)
     },
     manyMentions () {
       return this.extraMentions.length > 0
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx
index 32b737ec..1353541f 100644
--- a/src/components/rich_content/rich_content.jsx
+++ b/src/components/rich_content/rich_content.jsx
@@ -4,8 +4,7 @@ import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_con
 import { convertHtmlToTree } from 'src/services/html_converter/html_tree_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 MentionLink from 'src/components/mention_link/mention_link.vue'
-import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
+import MentionsLine, { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.vue'
 
 import './rich_content.scss'
 
@@ -13,12 +12,11 @@ import './rich_content.scss'
  * RichContent, The Über-powered component for rendering Post HTML.
  *
  * This takes post HTML and does multiple things to it:
- * - Converts mention links to <MentionLink>-s
- * - Removes mentions from beginning and end (hellthread style only)
+ * - Groups all mentions into <MentionsLine>, this affects all mentions regardles
+ *   of where they are (beginning/middle/end), even single mentions are converted
+ *   to a <MentionsLine> containing single <MentionLink>.
  * - Replaces emoji shortcodes with <StillImage>'d images.
  *
- * Stuff like removing mentions from beginning and end is done so that they could
- * be either replaced by collapsible <MentionsLine>  or moved to separate place.
  * There are two problems with this component's architecture:
  * 1. Parsing HTML and rendering are inseparable. Attempts to separate the two
  *    proven to be a massive overcomplication due to amount of things done here.
@@ -61,12 +59,13 @@ export default Vue.component('RichContent', {
   // NEVER EVER TOUCH DATA INSIDE RENDER
   render (h) {
     // Pre-process HTML
-    const { newHtml: html } = preProcessPerLine(this.html, this.greentext, this.handleLinks)
+    const { newHtml: html } = preProcessPerLine(this.html, this.greentext)
     let currentMentions = null // Current chain of mentions, we group all mentions together
-    // to collapse too many mentions in a row
 
     const lastTags = [] // Tags that appear at the end of post body
     const writtenMentions = [] // All mentions that appear in post body
+    const invisibleMentions = [] // All mentions that go beyond the limiter (see MentionsLine)
+    // to collapse too many mentions in a row
     const writtenTags = [] // All tags that appear in post body
     // unique index for vue "tag" property
     let mentionIndex = 0
@@ -99,6 +98,9 @@ export default Vue.component('RichContent', {
         currentMentions = []
       }
       currentMentions.push(linkData)
+      if (currentMentions.length > MENTIONS_LIMIT) {
+        invisibleMentions.push(linkData)
+      }
       if (currentMentions.length === 1) {
         return <MentionsLine mentions={ currentMentions } />
       } else {
@@ -232,7 +234,8 @@ export default Vue.component('RichContent', {
     const event = {
       lastTags,
       writtenMentions,
-      writtenTags
+      writtenTags,
+      invisibleMentions
     }
 
     // DO NOT MOVE TO UPDATE. BAD IDEA.
@@ -243,27 +246,32 @@ export default Vue.component('RichContent', {
 })
 
 const getLinkData = (attrs, children, index) => {
+  const stripTags = (item) => {
+    if (typeof item === 'string') {
+      return item
+    } else {
+      return item[1].map(stripTags).join('')
+    }
+  }
+  const textContent = children.map(stripTags).join('')
   return {
     index,
     url: attrs.href,
     hashtag: attrs['data-tag'],
-    content: flattenDeep(children).join('')
+    content: flattenDeep(children).join(''),
+    textContent
   }
 }
 
 /** Pre-processing HTML
  *
- * Currently this does two things:
+ * Currently this does one thing:
  * - add green/cyantexting
- * - wrap and mark last line containing only mentions as ".lastMentionsLine" for
- *   more compact hellthreads.
  *
  * @param {String} html - raw HTML to process
  * @param {Boolean} greentext - whether to enable greentexting or not
- * @param {Boolean} handleLinks - whether to handle links or not
  */
-export const preProcessPerLine = (html, greentext, handleLinks) => {
-  const lastMentions = []
+export const preProcessPerLine = (html, greentext) => {
   const greentextHandle = new Set(['p', 'div'])
 
   const lines = convertHtmlToLines(html)
@@ -277,7 +285,7 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
     if (
       // Only if greentext is engaged
       greentext &&
-        // Only handle p's and divs. Don't want to affect blocquotes, code etc
+        // Only handle p's and divs. Don't want to affect blockquotes, code etc
         item.level.every(l => greentextHandle.has(l)) &&
         // Only if line begins with '>' or '<'
         (string.includes('&gt;') || string.includes('&lt;'))
@@ -292,31 +300,8 @@ export const preProcessPerLine = (html, greentext, handleLinks) => {
       }
     }
 
-    // Converting that line part into tree
-    const tree = convertHtmlToTree(string)
-
-    const process = (item) => {
-      if (Array.isArray(item)) {
-        const [opener, children, closer] = item
-        const tag = getTagName(opener)
-        if (tag === 'span' || tag === 'p') {
-          // For span and p we need to go deeper
-          return [opener, [...children].map(process), closer]
-        } else {
-          return [opener, children, closer]
-        }
-      }
-
-      if (typeof item === 'string') {
-        return item
-      }
-    }
-
-    // We now processed our tree, now we need to mark line as lastMentions
-    const result = [...tree].map(process)
-
-    return flattenDeep(result).join('')
+    return string
   }).reverse().join('')
 
-  return { newHtml, lastMentions }
+  return { newHtml }
 }
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
index 8757154d..b941765c 100644
--- a/src/components/status_body/status_body.js
+++ b/src/components/status_body/status_body.js
@@ -32,7 +32,8 @@ const StatusContent = {
       showingTall: this.fullContent || (this.inConversation && this.focused),
       showingLongSubject: false,
       // 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,
+      postLength: this.status.text.length
     }
   },
   computed: {
@@ -47,7 +48,7 @@ const StatusContent = {
     // Using max-height + overflow: auto for status components resulted in false positives
     // very often with japanese characters, and it was very annoying.
     tallStatus () {
-      const lengthScore = this.status.raw_html.split(/<p|<br/).length + this.status.text.length / 80
+      const lengthScore = this.status.raw_html.split(/<p|<br/).length + this.postLength / 80
       return lengthScore > 20
     },
     longSubject () {
@@ -86,7 +87,7 @@ const StatusContent = {
   methods: {
     onParseReady (event) {
       this.$emit('parseReady', event)
-      const { writtenMentions } = event
+      const { writtenMentions, invisibleMentions } = event
       writtenMentions
         .filter(mention => !mention.notifying)
         .forEach(mention => {
@@ -97,6 +98,15 @@ const StatusContent = {
           const host = url.replace(/^https?:\/\//, '').replace(/\/.+?$/, '')
           this.$store.dispatch('fetchUserIfMissing', `${handle}@${host}`)
         })
+      /* This is a bit of a hack to make current tall status detector work
+       * 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)
     },
     toggleShowMore () {
       if (this.mightHideBecauseTall) {
-- 
cgit v1.2.3-70-g09d2

