Browse Source

Merge branch 'fix-mentions-new-bugs' into 'develop'

Fix newfound bugs with rich mentions + user suggestions

See merge request pleroma/pleroma-fe!1430
HJ 2 years ago
parent
commit
58d0f9678b

+ 7 - 0
src/components/chat_message/chat_message.scss

@@ -1,6 +1,7 @@
 @import '../../_variables.scss';
 
 .chat-message-wrapper {
+
   &.hovered-message-chain {
     .animated.Avatar {
       canvas {
@@ -40,6 +41,12 @@
   .chat-message {
     display: flex;
     padding-bottom: 0.5em;
+
+    .status-body:hover {
+      --_still-image-img-visibility: visible;
+      --_still-image-canvas-visibility: hidden;
+      --_still-image-label-visibility: hidden;
+    }
   }
 
   .avatar-wrapper {

+ 6 - 12
src/components/chat_title/chat_title.vue

@@ -1,5 +1,4 @@
 <template>
-  <!-- eslint-disable vue/no-v-html -->
   <div
     class="chat-title"
     :title="title"
@@ -14,12 +13,13 @@
         height="23px"
       />
     </router-link>
-    <span
+    <RichContent
       class="username"
-      v-html="htmlTitle"
+      :title="'@'+user.screen_name_ui"
+      :html="htmlTitle"
+      :emoji="user.emoji"
     />
   </div>
-  <!-- eslint-enable vue/no-v-html -->
 </template>
 
 <script src="./chat_title.js"></script>
@@ -34,6 +34,8 @@
   white-space: nowrap;
   align-items: center;
 
+  --emoji-size: 14px;
+
   .username {
     max-width: 100%;
     text-overflow: ellipsis;
@@ -41,14 +43,6 @@
     display: inline;
     word-wrap: break-word;
     overflow: hidden;
-    text-overflow: ellipsis;
-
-    .emoji {
-      width: 14px;
-      height: 14px;
-      vertical-align: middle;
-      object-fit: contain
-    }
   }
 
   .Avatar {

+ 7 - 1
src/components/mention_link/mention_link.js

@@ -87,7 +87,7 @@ const MentionLink = {
     classnames () {
       return [
         {
-          '-you': this.isYou,
+          '-you': this.isYou && this.shouldBoldenYou,
           '-highlighted': this.highlight
         },
         this.highlightType
@@ -115,6 +115,12 @@ const MentionLink = {
     shouldShowAvatar () {
       return this.mergedConfig.mentionLinkShowAvatar
     },
+    shouldShowYous () {
+      return this.mergedConfig.mentionLinkShowYous
+    },
+    shouldBoldenYou () {
+      return this.mergedConfig.mentionLinkBoldenYou
+    },
     shouldFadeDomain () {
       return this.mergedConfig.mentionLinkFadeDomain
     },

+ 9 - 4
src/components/mention_link/mention_link.scss

@@ -3,12 +3,13 @@
 .MentionLink {
   position: relative;
   white-space: normal;
-  display: inline-block;
+  display: inline;
   color: var(--link);
+  word-break: normal;
 
   & .new,
   & .original {
-    display: inline-block;
+    display: inline;
     border-radius: 2px;
   }
 
@@ -38,8 +39,8 @@
     user-select: all;
   }
 
-  .short.-with-tooltip,
-  .you {
+  & .short.-with-tooltip,
+  & .you {
     user-select: none;
   }
 
@@ -48,6 +49,10 @@
     white-space: nowrap;
   }
 
+  .shortName {
+    white-space: normal;
+  }
+
   .new {
     &.-you {
       & .shortName,

+ 6 - 10
src/components/mention_link/mention_link.vue

@@ -9,9 +9,7 @@
       class="original"
       target="_blank"
       v-html="content"
-    />
-    <!-- eslint-enable vue/no-v-html -->
-    <span
+    /><!-- eslint-enable vue/no-v-html --><span
       v-if="user"
       class="new"
       :style="style"
@@ -43,14 +41,12 @@
           class="serverName"
           :class="{ '-faded': shouldFadeDomain }"
           v-html="'@' + serverName"
-        /></span>
-        <span
-          v-if="isYou"
-          class="you"
-        >{{ $t('status.you') }}</span>
+        /></span><span
+          v-if="isYou && shouldShowYous"
+          :class="{ '-you': shouldBoldenYou }"
+        > {{ $t('status.you') }}</span>
         <!-- eslint-enable vue/no-v-html -->
-      </a>
-      <span
+      </a><span
         v-if="shouldShowTooltip"
         class="full popover-default"
         :class="[highlightType]"

+ 7 - 5
src/components/mentions_line/mentions_line.scss

@@ -1,11 +1,13 @@
 .MentionsLine {
+  word-break: break-all;
+
+  .mention-link:not(:first-child)::before {
+    content: ' ';
+  }
+
   .showMoreLess {
+    margin-left: 0.5em;
     white-space: normal;
     color: var(--link);
   }
-
-  .fullExtraMentions,
-  .mention-link:not(:last-child) {
-    margin-right: 0.25em;
-  }
 }

+ 1 - 1
src/components/popover/popover.vue

@@ -33,7 +33,7 @@
 @import '../../_variables.scss';
 
 .popover-trigger-button {
-  display: block;
+  display: inline-block;
 }
 
 .popover {

+ 2 - 1
src/components/rich_content/rich_content.jsx

@@ -120,7 +120,8 @@ export default Vue.component('RichContent', {
           // don't include spaces when processing mentions - we'll include them
           // in MentionsLine
           lastSpacing = item
-          return currentMentions !== null ? item.trim() : item
+          // Don't remove last space in a container (fixes poast mentions)
+          return (index !== array.length - 1) && (currentMentions !== null) ? item.trim() : item
         }
 
         currentMentions = null

+ 10 - 0
src/components/settings_modal/tabs/general_tab.vue

@@ -147,6 +147,11 @@
             {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="mentionLinkShowYous">
+            {{ $t('settings.show_yous') }}
+          </BooleanSetting>
+        </li>
         <li>
           <ChoiceSetting
             id="mentionLinkDisplay"
@@ -181,6 +186,11 @@
               {{ $t('settings.mention_link_fade_domain') }}
             </BooleanSetting>
           </li>
+          <li>
+            <BooleanSetting path="mentionLinkBoldenYou">
+              {{ $t('settings.mention_link_bolden_you') }}
+            </BooleanSetting>
+          </li>
         </ul>
       </ul>
     </div>

+ 10 - 3
src/components/status/status.scss

@@ -5,6 +5,8 @@ $status-margin: 0.75em;
 .Status {
   min-width: 0;
   white-space: normal;
+  word-wrap: break-word;
+  word-break: break-word;
 
   &:hover {
     --_still-image-img-visibility: visible;
@@ -164,18 +166,24 @@ $status-margin: 0.75em;
     position: relative;
     align-content: baseline;
     font-size: 12px;
-    line-height: 160%;
+    margin-top: 0.2em;
+    line-height: 130%;
     max-width: 100%;
     align-items: stretch;
   }
 
   & .reply-to-popover,
-  & .reply-to-no-popover {
+  & .reply-to-no-popover,
+  & .mentions {
     min-width: 0;
     margin-right: 0.4em;
     flex-shrink: 0;
   }
 
+  .reply-glued-label {
+    margin-right: 0.5em;
+  }
+
   .reply-to-popover {
     .reply-to:hover::before {
       content: '';
@@ -209,7 +217,6 @@ $status-margin: 0.75em;
   & .reply-to {
     white-space: nowrap;
     position: relative;
-    padding-right: 0.25em;
   }
 
   & .mentions-text,

+ 1 - 1
src/components/status/status.vue

@@ -227,7 +227,7 @@
             >
               <span
                 v-if="isReply"
-                class="glued-label"
+                class="glued-label reply-glued-label"
               >
                 <StatusPopover
                   v-if="!isPreview"

+ 10 - 1
src/components/still-image/still-image.js

@@ -5,7 +5,9 @@ const StillImage = {
     'mimetype',
     'imageLoadError',
     'imageLoadHandler',
-    'alt'
+    'alt',
+    'height',
+    'width'
   ],
   data () {
     return {
@@ -15,6 +17,13 @@ const StillImage = {
   computed: {
     animated () {
       return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif'))
+    },
+    style () {
+      const appendPx = (str) => /\d$/.test(str) ? str + 'px' : str
+      return {
+        height: this.height ? appendPx(this.height) : null,
+        width: this.width ? appendPx(this.width) : null
+      }
     }
   },
   methods: {

+ 1 - 0
src/components/still-image/still-image.vue

@@ -2,6 +2,7 @@
   <div
     class="still-image"
     :class="{ animated: animated }"
+    :style="style"
   >
     <canvas
       v-if="animated"

+ 1 - 0
src/components/user_card/user_card.vue

@@ -275,6 +275,7 @@
         class="user-card-bio"
         :html="user.description_html"
         :emoji="user.emoji"
+        :handle-links="true"
       />
     </div>
   </div>

+ 8 - 1
src/components/user_list_popover/user_list_popover.vue

@@ -22,7 +22,12 @@
             />
             <div class="user-list-names">
               <!-- eslint-disable vue/no-v-html -->
-              <span v-html="user.name_html" />
+              <RichContent
+                class="username"
+                :title="'@'+user.screen_name_ui"
+                :html="user.name_html"
+                :emoji="user.emoji"
+              />
               <!-- eslint-enable vue/no-v-html -->
               <span class="user-list-screen-name">{{ user.screen_name_ui }}</span>
             </div>
@@ -48,6 +53,8 @@
 .user-list-popover {
   padding: 0.5em;
 
+  --emoji-size: 16px;
+
   .user-list-row {
     padding: 0.25em;
     display: flex;

+ 2 - 0
src/i18n/en.json

@@ -493,8 +493,10 @@
     "mention_link_show_tooltip": "Show full user names as tooltip for remote users",
     "mention_link_show_avatar": "Show user avatar beside the link",
     "mention_link_fade_domain": "Fade domains (e.g. @example.org in @foo@example.org)",
+    "mention_link_bolden_you": "Highlight mention of you when you are mentioned",
     "fun": "Fun",
     "greentext": "Meme arrows",
+    "show_yous": "Show (You)s",
     "notifications": "Notifications",
     "notification_setting_filters": "Filters",
     "notification_setting_block_from_strangers": "Block notifications from users who you do not follow",

+ 2 - 0
src/modules/config.js

@@ -76,6 +76,8 @@ export const defaultState = {
   mentionLinkShowTooltip: undefined, // instance default
   mentionLinkShowAvatar: undefined, // instance default
   mentionLinkFadeDomain: undefined, // instance default
+  mentionLinkShowYous: undefined, // instance default
+  mentionLinkBoldenYou: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default

+ 2 - 0
src/modules/instance.js

@@ -25,6 +25,8 @@ const defaultState = {
   mentionLinkShowTooltip: true,
   mentionLinkShowAvatar: false,
   mentionLinkFadeDomain: true,
+  mentionLinkShowYous: false,
+  mentionLinkBoldenYou: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,

+ 2 - 1
src/services/html_converter/html_tree_converter.service.js

@@ -1,4 +1,5 @@
 import { getTagName } from './utility.service.js'
+import { unescape } from 'lodash'
 
 /**
  * This is a not-so-tiny purpose-built HTML parser/processor. This parses html
@@ -49,7 +50,7 @@ export const convertHtmlToTree = (html = '') => {
 
   const handleOpen = (tag) => {
     const curBuf = getCurrentBuffer()
-    const newLevel = [tag, []]
+    const newLevel = [unescape(tag), []]
     levels.push(newLevel)
     curBuf.push(newLevel)
   }

+ 77 - 0
test/unit/specs/components/rich_content.spec.js

@@ -350,12 +350,89 @@ describe('RichContent', () => {
         '<span>',
         '</span>',
         '</a>',
+        '<!---->', // v-if placeholder, mentionlink's "new" (i.e. rich) display
+        '</span>',
+        '<!---->', // v-if placeholder, mentionsline's extra mentions and stuff
+        '</span>'
+      ),
+      p(
+        'Testing'
+      )
+    ].join('')
+
+    const wrapper = mount(RichContent, {
+      localVue,
+      propsData: {
+        attentions,
+        handleLinks: true,
+        greentext: true,
+        emoji: [],
+        html
+      }
+    })
+
+    expect(wrapper.html()).to.eql(compwrap(expected))
+  })
+
+  it('rich contents of nested mentions are handled properly', () => {
+    attentions.push({ statusnet_profile_url: 'lol' })
+    const html = [
+      p(
+        '<span class="poast-style">',
+        '<a href="lol" class="mention">',
+        '<span>',
+        'https://</span>',
+        '<span>',
+        'lol.tld/</span>',
+        '<span>',
+        '</span>',
+        '</a>',
         ' ',
+        '<a href="lol" class="mention">',
+        '<span>',
+        'https://</span>',
+        '<span>',
+        'lol.tld/</span>',
+        '<span>',
+        '</span>',
+        '</a>',
+        '</span>'
+      ),
+      p(
+        'Testing'
+      )
+    ].join('')
+    const expected = [
+      p(
+        '<span class="poast-style">',
+        '<span class="MentionsLine">',
+        '<span class="MentionLink mention-link">',
+        '<a href="lol" target="_blank" class="original">',
+        '<span>',
+        'https://</span>',
+        '<span>',
+        'lol.tld/</span>',
+        '<span>',
+        '</span>',
+        '</a>',
+        '<!---->', // v-if placeholder, mentionlink's "new" (i.e. rich) display
+        '</span>',
+        '<span class="MentionLink mention-link">',
+        '<a href="lol" target="_blank" class="original">',
+        '<span>',
+        'https://</span>',
+        '<span>',
+        'lol.tld/</span>',
+        '<span>',
+        '</span>',
+        '</a>',
         '<!---->', // v-if placeholder, mentionlink's "new" (i.e. rich) display
         '</span>',
         '<!---->', // v-if placeholder, mentionsline's extra mentions and stuff
+        '</span>',
         '</span>'
       ),
+      ' ',
       p(
         'Testing'
       )