logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 58d0f9678b749d1b2ef8aa7d6fb4a91da9cf947d
parent ddee8bb686fb18baf5212089653a8b4e40feedd6
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date:   Sun, 20 Feb 2022 15:11:52 +0000

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

Fix newfound bugs with rich mentions + user suggestions

See merge request pleroma/pleroma-fe!1430

Diffstat:

Msrc/components/chat_message/chat_message.scss7+++++++
Msrc/components/chat_title/chat_title.vue18++++++------------
Msrc/components/mention_link/mention_link.js8+++++++-
Msrc/components/mention_link/mention_link.scss13+++++++++----
Msrc/components/mention_link/mention_link.vue16++++++----------
Msrc/components/mentions_line/mentions_line.scss12+++++++-----
Msrc/components/popover/popover.vue2+-
Msrc/components/rich_content/rich_content.jsx3++-
Msrc/components/settings_modal/tabs/general_tab.vue10++++++++++
Msrc/components/status/status.scss13++++++++++---
Msrc/components/status/status.vue2+-
Msrc/components/still-image/still-image.js11++++++++++-
Msrc/components/still-image/still-image.vue1+
Msrc/components/user_card/user_card.vue1+
Msrc/components/user_list_popover/user_list_popover.vue9++++++++-
Msrc/i18n/en.json2++
Msrc/modules/config.js2++
Msrc/modules/instance.js2++
Msrc/services/html_converter/html_tree_converter.service.js3++-
Mtest/unit/specs/components/rich_content.spec.js77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 files changed, 171 insertions(+), 41 deletions(-)

diff --git a/src/components/chat_message/chat_message.scss b/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 { diff --git a/src/components/chat_title/chat_title.vue b/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 { diff --git a/src/components/mention_link/mention_link.js b/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 }, diff --git a/src/components/mention_link/mention_link.scss b/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, diff --git a/src/components/mention_link/mention_link.vue b/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]" diff --git a/src/components/mentions_line/mentions_line.scss b/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; - } } diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue @@ -33,7 +33,7 @@ @import '../../_variables.scss'; .popover-trigger-button { - display: block; + display: inline-block; } .popover { diff --git a/src/components/rich_content/rich_content.jsx b/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 diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue @@ -148,6 +148,11 @@ </BooleanSetting> </li> <li> + <BooleanSetting path="mentionLinkShowYous"> + {{ $t('settings.show_yous') }} + </BooleanSetting> + </li> + <li> <ChoiceSetting id="mentionLinkDisplay" path="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> diff --git a/src/components/status/status.scss b/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, diff --git a/src/components/status/status.vue b/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" diff --git a/src/components/still-image/still-image.js b/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: { diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue @@ -2,6 +2,7 @@ <div class="still-image" :class="{ animated: animated }" + :style="style" > <canvas v-if="animated" diff --git a/src/components/user_card/user_card.vue b/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> diff --git a/src/components/user_list_popover/user_list_popover.vue b/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; diff --git a/src/i18n/en.json b/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", diff --git a/src/modules/config.js b/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 diff --git a/src/modules/instance.js b/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, diff --git a/src/services/html_converter/html_tree_converter.service.js b/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) } diff --git a/test/unit/specs/components/rich_content.spec.js b/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' )