From 61dcdbf99293de8c8b813ccec2833b190d3f97b2 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 7 Apr 2021 22:42:34 +0300
Subject: migrate to v-slot

---
 src/components/chat_message/chat_message.vue | 32 +++++++++++++++-------------
 1 file changed, 17 insertions(+), 15 deletions(-)

(limited to 'src/components/chat_message/chat_message.vue')

diff --git a/src/components/chat_message/chat_message.vue b/src/components/chat_message/chat_message.vue
index 0777f880..0f3fc97d 100644
--- a/src/components/chat_message/chat_message.vue
+++ b/src/components/chat_message/chat_message.vue
@@ -50,7 +50,7 @@
                 @show="menuOpened = true"
                 @close="menuOpened = false"
               >
-                <div slot="content">
+                <template v-slot:content>
                   <div class="dropdown-menu">
                     <button
                       class="button-default dropdown-item dropdown-item-icon"
@@ -59,26 +59,28 @@
                       <FAIcon icon="times" /> {{ $t("chats.delete") }}
                     </button>
                   </div>
-                </div>
-                <button
-                  slot="trigger"
-                  class="button-default menu-icon"
-                  :title="$t('chats.more')"
-                >
-                  <FAIcon icon="ellipsis-h" />
-                </button>
+                </template>
+                <template v-slot:trigger>
+                  <button
+                    class="button-default menu-icon"
+                    :title="$t('chats.more')"
+                  >
+                    <FAIcon icon="ellipsis-h" />
+                  </button>
+                </template>
               </Popover>
             </div>
             <StatusContent
               :status="messageForStatusContent"
               :full-content="true"
             >
-              <span
-                slot="footer"
-                class="created-at"
-              >
-                {{ createdAt }}
-              </span>
+              <template v-slot:footer>
+                <span
+                  class="created-at"
+                >
+                  {{ createdAt }}
+                </span>
+              </template>
             </StatusContent>
           </div>
         </div>
-- 
cgit v1.2.3-70-g09d2


From 8e9f5d7580d5a248e280b110218aa23052827789 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 7 Jun 2021 19:50:26 +0300
Subject: renamed StatusText to StatusBody for clarity, fixed chats

---
 src/components/chat_list_item/chat_list_item.js    |   9 +-
 src/components/chat_list_item/chat_list_item.scss  |   9 +-
 src/components/chat_list_item/chat_list_item.vue   |   3 +-
 src/components/chat_message/chat_message.js        |   2 +
 src/components/chat_message/chat_message.scss      |   6 +-
 src/components/chat_message/chat_message.vue       |   1 +
 .../settings_modal/tabs/theme_tab/theme_tab.js     |   2 +-
 src/components/status/status.vue                   |  10 +-
 src/components/status_body/status_body.js          | 147 +++++++++++++++++++++
 src/components/status_body/status_body.scss        | 112 ++++++++++++++++
 src/components/status_body/status_body.vue         |  95 +++++++++++++
 src/components/status_content/status_content.js    |   4 +-
 src/components/status_content/status_content.vue   | 102 +-------------
 src/components/status_text/status_text.js          | 147 ---------------------
 src/components/status_text/status_text.vue         |  95 -------------
 .../entity_normalizer/entity_normalizer.service.js |   2 +
 .../mini_html_converter.service.js                 |   2 +-
 yarn.lock                                          |  81 ++++++++++--
 18 files changed, 460 insertions(+), 369 deletions(-)
 create mode 100644 src/components/status_body/status_body.js
 create mode 100644 src/components/status_body/status_body.scss
 create mode 100644 src/components/status_body/status_body.vue
 delete mode 100644 src/components/status_text/status_text.js
 delete mode 100644 src/components/status_text/status_text.vue

(limited to 'src/components/chat_message/chat_message.vue')

diff --git a/src/components/chat_list_item/chat_list_item.js b/src/components/chat_list_item/chat_list_item.js
index bee1ad53..e01b9bd4 100644
--- a/src/components/chat_list_item/chat_list_item.js
+++ b/src/components/chat_list_item/chat_list_item.js
@@ -1,5 +1,5 @@
 import { mapState } from 'vuex'
-import StatusContent from '../status_content/status_content.vue'
+import StatusBody from '../status_content/status_content.vue'
 import fileType from 'src/services/file_type/file_type.service'
 import UserAvatar from '../user_avatar/user_avatar.vue'
 import AvatarList from '../avatar_list/avatar_list.vue'
@@ -16,7 +16,7 @@ const ChatListItem = {
     AvatarList,
     Timeago,
     ChatTitle,
-    StatusContent
+    StatusBody
   },
   computed: {
     ...mapState({
@@ -38,12 +38,15 @@ const ChatListItem = {
     },
     messageForStatusContent () {
       const message = this.chat.lastMessage
+      const messageEmojis = message ? message.emojis : []
       const isYou = message && message.account_id === this.currentUser.id
-      const content = message ? (this.attachmentInfo || message.content) : ''
+      const content = message ? (this.attachmentInfo || message.content_raw) : ''
       const messagePreview = isYou ? `<i>${this.$t('chats.you')}</i> ${content}` : content
       return {
         summary: '',
+        emojis: messageEmojis,
         statusnet_html: messagePreview,
+        raw_html: messagePreview,
         text: messagePreview,
         attachments: []
       }
diff --git a/src/components/chat_list_item/chat_list_item.scss b/src/components/chat_list_item/chat_list_item.scss
index 9e97b28e..57332bed 100644
--- a/src/components/chat_list_item/chat_list_item.scss
+++ b/src/components/chat_list_item/chat_list_item.scss
@@ -77,18 +77,15 @@
     border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
   }
 
-  .StatusContent {
-    img.emoji {
-      width: 1.4em;
-      height: 1.4em;
-    }
+  .chat-preview-body {
+    --emoji-size: 1.4em;
   }
 
   .time-wrapper {
     line-height: 1.4em;
   }
 
-  .single-line {
+  .chat-preview-body {
     padding-right: 1em;
   }
 }
diff --git a/src/components/chat_list_item/chat_list_item.vue b/src/components/chat_list_item/chat_list_item.vue
index cd3f436e..c7c0e878 100644
--- a/src/components/chat_list_item/chat_list_item.vue
+++ b/src/components/chat_list_item/chat_list_item.vue
@@ -29,7 +29,8 @@
         </div>
       </div>
       <div class="chat-preview">
-        <StatusContent
+        <StatusBody
+          class="chat-preview-body"
           :status="messageForStatusContent"
           :single-line="true"
         />
diff --git a/src/components/chat_message/chat_message.js b/src/components/chat_message/chat_message.js
index bb380f87..d126d453 100644
--- a/src/components/chat_message/chat_message.js
+++ b/src/components/chat_message/chat_message.js
@@ -57,6 +57,8 @@ const ChatMessage = {
     messageForStatusContent () {
       return {
         summary: '',
+        emojis: this.message.emojis,
+        raw_html: this.message.content_raw,
         statusnet_html: this.message.content,
         text: this.message.content,
         attachments: this.message.attachments
diff --git a/src/components/chat_message/chat_message.scss b/src/components/chat_message/chat_message.scss
index e4351d3b..220355ea 100644
--- a/src/components/chat_message/chat_message.scss
+++ b/src/components/chat_message/chat_message.scss
@@ -89,8 +89,9 @@
   }
 
   .without-attachment {
-    .status-content {
-      &::after {
+    .message-content {
+      // TODO figure out how to do it properly
+      .text::after {
         margin-right: 5.4em;
         content: " ";
         display: inline-block;
@@ -162,6 +163,7 @@
   .visible {
     opacity: 1;
   }
+
 }
 
 .chat-message-date-separator {
diff --git a/src/components/chat_message/chat_message.vue b/src/components/chat_message/chat_message.vue
index 0f3fc97d..d62b831d 100644
--- a/src/components/chat_message/chat_message.vue
+++ b/src/components/chat_message/chat_message.vue
@@ -71,6 +71,7 @@
               </Popover>
             </div>
             <StatusContent
+              class="message-content"
               :status="messageForStatusContent"
               :full-content="true"
             >
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index 1388f74b..63416e93 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -474,7 +474,7 @@ export default {
           this.loadThemeFromLocalStorage(false, true)
           break
         case 'file':
-          console.err('Forcing snapshout from file is not supported yet')
+          console.error('Forcing snapshout from file is not supported yet')
           break
       }
       this.dismissWarning()
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index cc5fb79f..a4247cd4 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -89,7 +89,10 @@
               v-if="retweeterHtml"
               :to="retweeterProfileLink"
             >
-              <RichContent :html="retweeterHtml" :emoji="retweeterUser.emoji"/>
+              <RichContent
+                :html="retweeterHtml"
+                :emoji="retweeterUser.emoji"
+              />
             </router-link>
             <router-link
               v-else
@@ -146,7 +149,10 @@
                   class="status-username"
                   :title="status.user.name"
                 >
-                  <RichContent :html="status.user.name" :emoji="status.user.emoji" />
+                  <RichContent
+                    :html="status.user.name"
+                    :emoji="status.user.emoji"
+                  />
                 </h4>
                 <h4
                   v-else
diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js
new file mode 100644
index 00000000..232afccb
--- /dev/null
+++ b/src/components/status_body/status_body.js
@@ -0,0 +1,147 @@
+import fileType from 'src/services/file_type/file_type.service'
+import RichContent from 'src/components/rich_content/rich_content.jsx'
+import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
+import { extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
+import { mapGetters } from 'vuex'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faFile,
+  faMusic,
+  faImage,
+  faLink,
+  faPollH
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faFile,
+  faMusic,
+  faImage,
+  faLink,
+  faPollH
+)
+
+const StatusContent = {
+  name: 'StatusContent',
+  props: [
+    'status',
+    'focused',
+    'noHeading',
+    'fullContent',
+    'singleLine'
+  ],
+  data () {
+    return {
+      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
+    }
+  },
+  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 () {
+      const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
+      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)
+    },
+    postBodyHtml () {
+      const html = this.status.raw_html
+
+      if (this.mergedConfig.greentext) {
+        try {
+          if (html.includes('&gt;')) {
+            // This checks if post has '>' at the beginning, excluding mentions so that @mention >impying works
+            return processHtml(html, (string) => {
+              if (string.includes('&gt;') &&
+                  string
+                    .replace(/<[^>]+?>/gi, '') // remove all tags
+                    .replace(/@\w+/gi, '') // remove mentions (even failed ones)
+                    .trim()
+                    .startsWith('&gt;')) {
+                return `<span class='greentext'>${string}</span>`
+              } else {
+                return string
+              }
+            })
+          } else {
+            return html
+          }
+        } catch (e) {
+          console.error('Failed to process status html', e)
+          return html
+        }
+      } else {
+        return html
+      }
+    },
+    attachmentTypes () {
+      return this.status.attachments.map(file => fileType.fileType(file.mimetype))
+    },
+    ...mapGetters(['mergedConfig'])
+  },
+  components: {
+    RichContent
+  },
+  mounted () {
+    this.status.attentions && this.status.attentions.forEach(attn => {
+      const { id } = attn
+      this.$store.dispatch('fetchUserIfMissing', id)
+    })
+  },
+  methods: {
+    linkClicked (event) {
+      const target = event.target.closest('.status-content a')
+      if (target) {
+        if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) {
+          // Extract tag name from dataset or link url
+          const tag = target.dataset.tag || extractTagFromUrl(target.href)
+          if (tag) {
+            const link = this.generateTagLink(tag)
+            this.$router.push(link)
+            return
+          }
+        }
+        window.open(target.href, '_blank')
+      }
+    },
+    toggleShowMore () {
+      if (this.mightHideBecauseTall) {
+        this.showingTall = !this.showingTall
+      } else if (this.mightHideBecauseSubject) {
+        this.expandingSubject = !this.expandingSubject
+      }
+    },
+    generateTagLink (tag) {
+      return `/tag/${tag}`
+    }
+  }
+}
+
+export default StatusContent
diff --git a/src/components/status_body/status_body.scss b/src/components/status_body/status_body.scss
new file mode 100644
index 00000000..6282919c
--- /dev/null
+++ b/src/components/status_body/status_body.scss
@@ -0,0 +1,112 @@
+@import '../../_variables.scss';
+
+.StatusBody {
+  .emoji {
+    --_still_image-label-scale: 0.5;
+  }
+
+  .summary {
+    display: block;
+    font-style: italic;
+    padding-bottom: 0.5em;
+  }
+
+  .text {
+    &.-single-line {
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      height: 1.4em;
+    }
+  }
+
+  .summary-wrapper {
+    margin-bottom: 0.5em;
+    border-style: solid;
+    border-width: 0 0 1px 0;
+    border-color: var(--border, $fallback--border);
+    flex-grow: 0;
+
+    &.-tall {
+      position: relative;
+
+      .summary {
+        max-height: 2em;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+      }
+    }
+  }
+
+  .text-wrapper {
+    display: flex;
+    flex-direction: column;
+    flex-wrap: nowrap;
+
+    &.-tall-status {
+      position: relative;
+      height: 220px;
+      overflow-x: hidden;
+      overflow-y: hidden;
+      z-index: 1;
+
+      .text {
+        min-height: 0;
+        mask:
+          linear-gradient(to top, white, transparent) bottom/100% 70px no-repeat,
+          linear-gradient(to top, white, white);
+
+        /* Autoprefixed seem to ignore this one, and also syntax is different */
+        -webkit-mask-composite: xor;
+        mask-composite: exclude;
+      }
+    }
+  }
+
+  & .tall-status-hider,
+  & .tall-subject-hider,
+  & .status-unhider,
+  & .cw-status-hider {
+    display: inline-block;
+    word-break: break-all;
+    width: 100%;
+    text-align: center;
+  }
+
+  .tall-status-hider {
+    position: absolute;
+    height: 70px;
+    margin-top: 150px;
+    line-height: 110px;
+    z-index: 2;
+  }
+
+  .tall-subject-hider {
+    // position: absolute;
+    padding-bottom: 0.5em;
+  }
+
+  & .status-unhider,
+  & .cw-status-hider {
+    word-break: break-all;
+
+    svg {
+      color: inherit;
+    }
+  }
+
+  .greentext {
+    color: $fallback--cGreen;
+    color: var(--postGreentext, $fallback--cGreen);
+  }
+
+  /* Not sure if this is necessary */
+  video {
+    max-width: 100%;
+    max-height: 400px;
+    vertical-align: middle;
+    object-fit: contain;
+  }
+
+}
diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue
new file mode 100644
index 00000000..6f982f2e
--- /dev/null
+++ b/src/components/status_body/status_body.vue
@@ -0,0 +1,95 @@
+<template>
+  <div class="StatusBody">
+    <div class="body">
+      <div
+        v-if="status.summary_html"
+        class="summary-wrapper"
+        :class="{ '-tall': (longSubject && !showingLongSubject) }"
+      >
+        <RichContent
+          class="media-body summary"
+          :html="status.summary_raw_html"
+          :emoji="status.emojis"
+          @click.prevent="linkClicked"
+        />
+        <button
+          v-if="longSubject && showingLongSubject"
+          class="button-unstyled -link tall-subject-hider"
+          @click.prevent="showingLongSubject=false"
+        >
+          {{ $t("status.hide_full_subject") }}
+        </button>
+        <button
+          v-else-if="longSubject"
+          class="button-unstyled -link tall-subject-hider"
+          @click.prevent="showingLongSubject=true"
+        >
+          {{ $t("status.show_full_subject") }}
+        </button>
+      </div>
+      <div
+        :class="{'-tall-status': hideTallStatus}"
+        class="text-wrapper"
+      >
+        <button
+          v-if="hideTallStatus"
+          class="button-unstyled -link tall-status-hider"
+          :class="{ '-focused': focused }"
+          @click.prevent="toggleShowMore"
+        >
+          {{ $t("general.show_more") }}
+        </button>
+        <RichContent
+          v-if="!hideSubjectStatus && !(singleLine && status.summary_html)"
+          :class="{ '-single-line': singleLine }"
+          class="text media-body"
+          :html="postBodyHtml"
+          :emoji="status.emojis"
+          :handle-links="true"
+          @click.prevent="linkClicked"
+        />
+        <button
+          v-if="hideSubjectStatus"
+          class="button-unstyled -link cw-status-hider"
+          @click.prevent="toggleShowMore"
+        >
+          {{ $t("status.show_content") }}
+          <FAIcon
+            v-if="attachmentTypes.includes('image')"
+            icon="image"
+          />
+          <FAIcon
+            v-if="attachmentTypes.includes('video')"
+            icon="video"
+          />
+          <FAIcon
+            v-if="attachmentTypes.includes('audio')"
+            icon="music"
+          />
+          <FAIcon
+            v-if="attachmentTypes.includes('unknown')"
+            icon="file"
+          />
+          <FAIcon
+            v-if="status.poll && status.poll.options"
+            icon="poll-h"
+          />
+          <FAIcon
+            v-if="status.card"
+            icon="link"
+          />
+        </button>
+        <button
+          v-if="showingMore && !fullContent"
+          class="button-unstyled -link status-unhider"
+          @click.prevent="toggleShowMore"
+        >
+          {{ tallStatus ? $t("general.show_less") : $t("status.hide_content") }}
+        </button>
+      </div>
+    </div>
+    <slot v-if="!hideSubjectStatus" />
+  </div>
+</template>
+<script src="./status_body.js" ></script>
+<style lang="scss" src="./status_body.scss" />
diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js
index 67323b8a..1b80ee09 100644
--- a/src/components/status_content/status_content.js
+++ b/src/components/status_content/status_content.js
@@ -1,7 +1,7 @@
 import Attachment from '../attachment/attachment.vue'
 import Poll from '../poll/poll.vue'
 import Gallery from '../gallery/gallery.vue'
-import StatusText from 'src/components/status_text/status_text.vue'
+import StatusBody from 'src/components/status_body/status_body.vue'
 import LinkPreview from '../link-preview/link-preview.vue'
 import fileType from 'src/services/file_type/file_type.service'
 import { mapGetters, mapState } from 'vuex'
@@ -88,7 +88,7 @@ const StatusContent = {
     Poll,
     Gallery,
     LinkPreview,
-    StatusText
+    StatusBody
   },
   methods: {
     setMedia () {
diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue
index 7389244a..0551f275 100644
--- a/src/components/status_content/status_content.vue
+++ b/src/components/status_content/status_content.vue
@@ -1,7 +1,7 @@
 <template>
   <div class="StatusContent">
     <slot name="header" />
-    <StatusText :status="status">
+    <StatusBody :status="status" :single-line="singleLine">
       <div v-if="status.poll && status.poll.options">
         <poll :base-poll="status.poll" />
       </div>
@@ -40,7 +40,7 @@
           :nsfw="nsfwClickthrough"
         />
       </div>
-    </StatusText>
+    </StatusBody>
     <slot name="footer" />
   </div>
 </template>
@@ -54,103 +54,5 @@ $status-margin: 0.75em;
 .StatusContent {
   flex: 1;
   min-width: 0;
-
-  .status-content-wrapper {
-    display: flex;
-    flex-direction: column;
-    flex-wrap: nowrap;
-  }
-
-  .tall-status {
-    position: relative;
-    height: 220px;
-    overflow-x: hidden;
-    overflow-y: hidden;
-    z-index: 1;
-    .status-content {
-      min-height: 0;
-      mask: linear-gradient(to top, white, transparent) bottom/100% 70px no-repeat,
-            linear-gradient(to top, white, white);
-      /* Autoprefixed seem to ignore this one, and also syntax is different */
-      -webkit-mask-composite: xor;
-      mask-composite: exclude;
-    }
-  }
-
-  .tall-status-hider {
-    display: inline-block;
-    word-break: break-all;
-    position: absolute;
-    height: 70px;
-    margin-top: 150px;
-    width: 100%;
-    text-align: center;
-    line-height: 110px;
-    z-index: 2;
-  }
-
-  .status-unhider, .cw-status-hider {
-    width: 100%;
-    text-align: center;
-    display: inline-block;
-    word-break: break-all;
-
-    svg {
-      color: inherit;
-    }
-  }
-
-  video {
-    max-width: 100%;
-    max-height: 400px;
-    vertical-align: middle;
-    object-fit: contain;
-  }
-
-  .summary-wrapper {
-    margin-bottom: 0.5em;
-    border-style: solid;
-    border-width: 0 0 1px 0;
-    border-color: var(--border, $fallback--border);
-    flex-grow: 0;
-  }
-
-  .summary {
-    font-style: italic;
-    padding-bottom: 0.5em;
-  }
-
-  .tall-subject {
-    position: relative;
-    .summary {
-      max-height: 2em;
-      overflow: hidden;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-    }
-  }
-
-  .tall-subject-hider {
-    display: inline-block;
-    word-break: break-all;
-    // position: absolute;
-    width: 100%;
-    text-align: center;
-    padding-bottom: 0.5em;
-  }
-
-  .status-content {
-    &.single-line {
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      overflow: hidden;
-      height: 1.4em;
-    }
-  }
-}
-
-.greentext {
-  color: $fallback--cGreen;
-  color: var(--postGreentext, $fallback--cGreen);
 }
 </style>
diff --git a/src/components/status_text/status_text.js b/src/components/status_text/status_text.js
deleted file mode 100644
index e0b11edc..00000000
--- a/src/components/status_text/status_text.js
+++ /dev/null
@@ -1,147 +0,0 @@
-import fileType from 'src/services/file_type/file_type.service'
-import RichContent from 'src/components/rich_content/rich_content.jsx'
-import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
-import { extractTagFromUrl } from 'src/services/matcher/matcher.service.js'
-import { mapGetters } from 'vuex'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faFile,
-  faMusic,
-  faImage,
-  faLink,
-  faPollH
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faFile,
-  faMusic,
-  faImage,
-  faLink,
-  faPollH
-)
-
-const StatusContent = {
-  name: 'StatusContent',
-  props: [
-    'status',
-    'focused',
-    'noHeading',
-    'fullContent',
-    'singleLine'
-  ],
-  data () {
-    return {
-      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
-    }
-  },
-  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 () {
-      const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
-      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)
-    },
-    postBodyHtml () {
-      const html = this.status.raw_html
-
-      if (this.mergedConfig.greentext) {
-        try {
-          if (html.includes('&gt;')) {
-            // This checks if post has '>' at the beginning, excluding mentions so that @mention >impying works
-            return processHtml(html, (string) => {
-              if (string.includes('&gt;') &&
-                  string
-                    .replace(/<[^>]+?>/gi, '') // remove all tags
-                    .replace(/@\w+/gi, '') // remove mentions (even failed ones)
-                    .trim()
-                    .startsWith('&gt;')) {
-                return `<span class='greentext'>${string}</span>`
-              } else {
-                return string
-              }
-            })
-          } else {
-            return html
-          }
-        } catch (e) {
-          console.err('Failed to process status html', e)
-          return html
-        }
-      } else {
-        return html
-      }
-    },
-    attachmentTypes () {
-      return this.status.attachments.map(file => fileType.fileType(file.mimetype))
-    },
-    ...mapGetters(['mergedConfig']),
-  },
-  components: {
-    RichContent
-  },
-  mounted () {
-    this.status.attentions.forEach(attn => {
-      const { id } = attn
-      this.$store.dispatch('fetchUserIfMissing', id)
-    })
-  },
-  methods: {
-    linkClicked (event) {
-      const target = event.target.closest('.status-content a')
-      if (target) {
-        if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) {
-          // Extract tag name from dataset or link url
-          const tag = target.dataset.tag || extractTagFromUrl(target.href)
-          if (tag) {
-            const link = this.generateTagLink(tag)
-            this.$router.push(link)
-            return
-          }
-        }
-        window.open(target.href, '_blank')
-      }
-    },
-    toggleShowMore () {
-      if (this.mightHideBecauseTall) {
-        this.showingTall = !this.showingTall
-      } else if (this.mightHideBecauseSubject) {
-        this.expandingSubject = !this.expandingSubject
-      }
-    },
-    generateTagLink (tag) {
-      return `/tag/${tag}`
-    }
-  }
-}
-
-export default StatusContent
diff --git a/src/components/status_text/status_text.vue b/src/components/status_text/status_text.vue
deleted file mode 100644
index bf723e15..00000000
--- a/src/components/status_text/status_text.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-<template>
-  <div class="StatusText">
-    <div
-      v-if="status.summary_html"
-      class="summary-wrapper"
-      :class="{ 'tall-subject': (longSubject && !showingLongSubject) }"
-    >
-      <RichContent
-        class="media-body summary"
-        :html="status.summary_raw_html"
-        :emoji="status.emojis"
-        @click.prevent="linkClicked"
-      />
-      <button
-        v-if="longSubject && showingLongSubject"
-        class="button-unstyled -link tall-subject-hider"
-        @click.prevent="showingLongSubject=false"
-        >
-        {{ $t("status.hide_full_subject") }}
-      </button>
-      <button
-        v-else-if="longSubject"
-        class="button-unstyled -link tall-subject-hider"
-        :class="{ 'tall-subject-hider_focused': focused }"
-        @click.prevent="showingLongSubject=true"
-      >
-        {{ $t("status.show_full_subject") }}
-      </button>
-    </div>
-    <div
-      :class="{'tall-status': hideTallStatus}"
-      class="status-content-wrapper"
-      >
-      <button
-        v-if="hideTallStatus"
-        class="button-unstyled -link tall-status-hider"
-        :class="{ 'tall-status-hider_focused': focused }"
-        @click.prevent="toggleShowMore"
-      >
-        {{ $t("general.show_more") }}
-      </button>
-      <RichContent
-        v-if="!hideSubjectStatus"
-        :class="{ 'single-line': singleLine }"
-        class="status-content media-body"
-        :html="postBodyHtml"
-        :emoji="status.emojis"
-        :handleLinks="true"
-        @click.prevent="linkClicked"
-        />
-      <button
-        v-if="hideSubjectStatus"
-        class="button-unstyled -link cw-status-hider"
-        @click.prevent="toggleShowMore"
-        >
-        {{ $t("status.show_content") }}
-        <FAIcon
-          v-if="attachmentTypes.includes('image')"
-          icon="image"
-          />
-        <FAIcon
-          v-if="attachmentTypes.includes('video')"
-          icon="video"
-          />
-        <FAIcon
-          v-if="attachmentTypes.includes('audio')"
-          icon="music"
-          />
-        <FAIcon
-          v-if="attachmentTypes.includes('unknown')"
-          icon="file"
-          />
-        <FAIcon
-          v-if="status.poll && status.poll.options"
-          icon="poll-h"
-          />
-        <FAIcon
-          v-if="status.card"
-          icon="link"
-          />
-      </button>
-      <button
-        v-if="showingMore && !fullContent"
-        class="button-unstyled -link status-unhider"
-        @click.prevent="toggleShowMore"
-        >
-        {{ tallStatus ? $t("general.show_less") : $t("status.hide_content") }}
-      </button>
-    </div>
-    <div v-if="!hideSubjectStatus">
-      <slot/>
-    </div>
-  </div>
-</template>
-<script src="./status_text.js" ></script>
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index 8dc22823..13162dcf 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -448,6 +448,8 @@ export const parseChatMessage = (message) => {
   output.id = message.id
   output.created_at = new Date(message.created_at)
   output.chat_id = message.chat_id
+  output.emojis = message.emojis
+  output.content_raw = message.content
   if (message.content) {
     output.content = addEmojis(message.content, message.emojis)
   } else {
diff --git a/src/services/mini_html_converter/mini_html_converter.service.js b/src/services/mini_html_converter/mini_html_converter.service.js
index 01f8adf8..900752cd 100644
--- a/src/services/mini_html_converter/mini_html_converter.service.js
+++ b/src/services/mini_html_converter/mini_html_converter.service.js
@@ -1,6 +1,6 @@
 /**
  * This is a not-so-tiny purpose-built HTML parser/processor. It was made for use
- * with StatusText component for purpose of replacing tags with vue components
+ * with StatusBody component for purpose of replacing tags with vue components
  *
  * known issue: doesn't handle CDATA so nested CDATA might not work well
  *
diff --git a/yarn.lock b/yarn.lock
index 23cc895b..9329cc3a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1011,23 +1011,86 @@
   resolved "https://registry.yarnpkg.com/@ungap/event-target/-/event-target-0.1.0.tgz#88d527d40de86c4b0c99a060ca241d755999915b"
   integrity sha512-W2oyj0Fe1w/XhPZjkI3oUcDUAmu5P4qsdT2/2S8aMhtAWM/CE/jYWtji0pKNPDfxLI75fa5gWSEmnynKMNP/oA==
 
-"@vue/babel-helper-vue-jsx-merge-props@^1.0.0":
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz#048fe579958da408fb7a8b2a3ec050b50a661040"
-  integrity sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw==
+"@vue/babel-helper-vue-jsx-merge-props@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz#31624a7a505fb14da1d58023725a4c5f270e6a81"
+  integrity sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==
 
-"@vue/babel-plugin-transform-vue-jsx@^1.1.2":
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.1.2.tgz#c0a3e6efc022e75e4247b448a8fc6b86f03e91c0"
-  integrity sha512-YfdaoSMvD1nj7+DsrwfTvTnhDXI7bsuh+Y5qWwvQXlD24uLgnsoww3qbiZvWf/EoviZMrvqkqN4CBw0W3BWUTQ==
+"@vue/babel-plugin-transform-vue-jsx@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz#646046c652c2f0242727f34519d917b064041ed7"
+  integrity sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==
   dependencies:
     "@babel/helper-module-imports" "^7.0.0"
     "@babel/plugin-syntax-jsx" "^7.2.0"
-    "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
+    "@vue/babel-helper-vue-jsx-merge-props" "^1.2.1"
     html-tags "^2.0.0"
     lodash.kebabcase "^4.1.1"
     svg-tags "^1.0.0"
 
+"@vue/babel-preset-jsx@^1.2.4":
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz#92fea79db6f13b01e80d3a0099e2924bdcbe4e87"
+  integrity sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==
+  dependencies:
+    "@vue/babel-helper-vue-jsx-merge-props" "^1.2.1"
+    "@vue/babel-plugin-transform-vue-jsx" "^1.2.1"
+    "@vue/babel-sugar-composition-api-inject-h" "^1.2.1"
+    "@vue/babel-sugar-composition-api-render-instance" "^1.2.4"
+    "@vue/babel-sugar-functional-vue" "^1.2.2"
+    "@vue/babel-sugar-inject-h" "^1.2.2"
+    "@vue/babel-sugar-v-model" "^1.2.3"
+    "@vue/babel-sugar-v-on" "^1.2.3"
+
+"@vue/babel-sugar-composition-api-inject-h@^1.2.1":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz#05d6e0c432710e37582b2be9a6049b689b6f03eb"
+  integrity sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@vue/babel-sugar-composition-api-render-instance@^1.2.4":
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz#e4cbc6997c344fac271785ad7a29325c51d68d19"
+  integrity sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@vue/babel-sugar-functional-vue@^1.2.2":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz#267a9ac8d787c96edbf03ce3f392c49da9bd2658"
+  integrity sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@vue/babel-sugar-inject-h@^1.2.2":
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz#d738d3c893367ec8491dcbb669b000919293e3aa"
+  integrity sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@vue/babel-sugar-v-model@^1.2.3":
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz#fa1f29ba51ebf0aa1a6c35fa66d539bc459a18f2"
+  integrity sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+    "@vue/babel-helper-vue-jsx-merge-props" "^1.2.1"
+    "@vue/babel-plugin-transform-vue-jsx" "^1.2.1"
+    camelcase "^5.0.0"
+    html-tags "^2.0.0"
+    svg-tags "^1.0.0"
+
+"@vue/babel-sugar-v-on@^1.2.3":
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz#342367178586a69f392f04bfba32021d02913ada"
+  integrity sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==
+  dependencies:
+    "@babel/plugin-syntax-jsx" "^7.2.0"
+    "@vue/babel-plugin-transform-vue-jsx" "^1.2.1"
+    camelcase "^5.0.0"
+
 "@vue/test-utils@^1.0.0-beta.26":
   version "1.0.0-beta.28"
   resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.28.tgz#767c43413df8cde86128735e58923803e444b9a5"
-- 
cgit v1.2.3-70-g09d2

