forked from AkkomaGang/akkoma-fe
Merge branch 'fix-mentions-new-bugs' into 'develop'
Fix newfound bugs with rich mentions + user suggestions See merge request pleroma/pleroma-fe!1430
This commit is contained in:
commit
58d0f9678b
20 changed files with 172 additions and 42 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
/></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]"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
@import '../../_variables.scss';
|
||||
|
||||
.popover-trigger-button {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.popover {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -227,7 +227,7 @@
|
|||
>
|
||||
<span
|
||||
v-if="isReply"
|
||||
class="glued-label"
|
||||
class="glued-label reply-glued-label"
|
||||
>
|
||||
<StatusPopover
|
||||
v-if="!isPreview"
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<div
|
||||
class="still-image"
|
||||
:class="{ animated: animated }"
|
||||
:style="style"
|
||||
>
|
||||
<canvas
|
||||
v-if="animated"
|
||||
|
|
|
@ -275,6 +275,7 @@
|
|||
class="user-card-bio"
|
||||
:html="user.description_html"
|
||||
:emoji="user.emoji"
|
||||
:handle-links="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -350,7 +350,6 @@ 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
|
||||
|
@ -375,6 +374,84 @@ describe('RichContent', () => {
|
|||
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'
|
||||
)
|
||||
].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 a link are handled properly', () => {
|
||||
const html = [
|
||||
'<p>',
|
||||
|
|
Loading…
Reference in a new issue