richcontent support in polls, user cards and user profiles

This commit is contained in:
Henry Jameson 2021-08-13 13:06:42 +03:00
parent 6c6df29ed3
commit 4c974f5ca2
14 changed files with 69 additions and 86 deletions

View file

@ -1,5 +1,6 @@
import UserCard from '../user_card/user_card.vue' import UserCard from '../user_card/user_card.vue'
import UserAvatar from '../user_avatar/user_avatar.vue' import UserAvatar from '../user_avatar/user_avatar.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
const BasicUserCard = { const BasicUserCard = {
@ -13,7 +14,8 @@ const BasicUserCard = {
}, },
components: { components: {
UserCard, UserCard,
UserAvatar UserAvatar,
RichContent
}, },
methods: { methods: {
toggleUserExpanded () { toggleUserExpanded () {

View file

@ -25,17 +25,11 @@
:title="user.name" :title="user.name"
class="basic-user-card-user-name" class="basic-user-card-user-name"
> >
<!-- eslint-disable vue/no-v-html --> <RichContent
<span
v-if="user.name_html"
class="basic-user-card-user-name-value" class="basic-user-card-user-name-value"
v-html="user.name_html" :html="user.name"
:emoji="user.emoji"
/> />
<!-- eslint-enable vue/no-v-html -->
<span
v-else
class="basic-user-card-user-name-value"
>{{ user.name }}</span>
</div> </div>
<div> <div>
<router-link <router-link

View file

@ -4,6 +4,7 @@ import Status from '../status/status.vue'
import UserAvatar from '../user_avatar/user_avatar.vue' import UserAvatar from '../user_avatar/user_avatar.vue'
import UserCard from '../user_card/user_card.vue' import UserCard from '../user_card/user_card.vue'
import Timeago from '../timeago/timeago.vue' import Timeago from '../timeago/timeago.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js' import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -44,7 +45,8 @@ const Notification = {
UserAvatar, UserAvatar,
UserCard, UserCard,
Timeago, Timeago,
Status Status,
RichContent
}, },
methods: { methods: {
toggleUserExpanded () { toggleUserExpanded () {

View file

@ -2,6 +2,8 @@
// TODO Copypaste from Status, should unify it somehow // TODO Copypaste from Status, should unify it somehow
.Notification { .Notification {
--emoji-size: 14px;
&.-muted { &.-muted {
padding: 0.25em 0.6em; padding: 0.25em 0.6em;
height: 1.2em; height: 1.2em;

View file

@ -51,12 +51,14 @@
<span class="notification-details"> <span class="notification-details">
<div class="name-and-action"> <div class="name-and-action">
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<bdi <bdi v-if="!!notification.from_profile.name_html">
v-if="!!notification.from_profile.name_html" <RichContent
class="username" class="username"
:title="'@'+notification.from_profile.screen_name_ui" :title="'@'+notification.from_profile.screen_name_ui"
v-html="notification.from_profile.name_html" :html="notification.from_profile.name_html"
:emoji="notification.from_profile.emoji"
/> />
</bdi>
<!-- eslint-enable vue/no-v-html --> <!-- eslint-enable vue/no-v-html -->
<span <span
v-else v-else

View file

@ -148,13 +148,6 @@
max-width: 100%; max-width: 100%;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
img {
width: 14px;
height: 14px;
vertical-align: middle;
object-fit: contain
}
} }
.timeago { .timeago {

View file

@ -17,7 +17,11 @@
<span class="result-percentage"> <span class="result-percentage">
{{ percentageForOption(option.votes_count) }}% {{ percentageForOption(option.votes_count) }}%
</span> </span>
<RichContent :html="option.title_html" :handle-links="false" :emoji="emoji" /> <RichContent
:html="option.title_html"
:handle-links="false"
:emoji="emoji"
/>
</div> </div>
<div <div
class="result-fill" class="result-fill"
@ -41,7 +45,11 @@
:value="index" :value="index"
> >
<label class="option-vote"> <label class="option-vote">
<RichContent :html="option.title_html" :handle-links="false" :emoji="emoji" /> <RichContent
:html="option.title_html"
:handle-links="false"
:emoji="emoji"
/>
</label> </label>
</div> </div>
</div> </div>

View file

@ -49,6 +49,7 @@
} }
.emoji { .emoji {
display: inline-block;
width: var(--emoji-size, 32px); width: var(--emoji-size, 32px);
height: var(--emoji-size, 32px); height: var(--emoji-size, 32px);
} }

View file

@ -7,7 +7,10 @@
@parseReady="$emit('parseReady', $event)" @parseReady="$emit('parseReady', $event)"
> >
<div v-if="status.poll && status.poll.options"> <div v-if="status.poll && status.poll.options">
<poll :base-poll="status.poll" :emoji="status.emojis" /> <Poll
:base-poll="status.poll"
:emoji="status.emojis"
/>
</div> </div>
<div <div

View file

@ -5,6 +5,7 @@ import FollowButton from '../follow_button/follow_button.vue'
import ModerationTools from '../moderation_tools/moderation_tools.vue' import ModerationTools from '../moderation_tools/moderation_tools.vue'
import AccountActions from '../account_actions/account_actions.vue' import AccountActions from '../account_actions/account_actions.vue'
import Select from '../select/select.vue' import Select from '../select/select.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@ -118,7 +119,8 @@ export default {
AccountActions, AccountActions,
ProgressButton, ProgressButton,
FollowButton, FollowButton,
Select Select,
RichContent
}, },
methods: { methods: {
muteUser () { muteUser () {

View file

@ -38,21 +38,12 @@
</router-link> </router-link>
<div class="user-summary"> <div class="user-summary">
<div class="top-line"> <div class="top-line">
<!-- eslint-disable vue/no-v-html --> <RichContent
<div
v-if="user.name_html"
:title="user.name" :title="user.name"
class="user-name" class="user-name"
v-html="user.name_html" :html="user.name"
:emoji="user.emoji"
/> />
<!-- eslint-enable vue/no-v-html -->
<div
v-else
:title="user.name"
class="user-name"
>
{{ user.name }}
</div>
<button <button
v-if="isOtherUser && !user.is_local" v-if="isOtherUser && !user.is_local"
:href="user.statusnet_profile_url" :href="user.statusnet_profile_url"
@ -255,20 +246,12 @@
<span>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</span> <span>{{ hideFollowersCount ? $t('user_card.hidden') : user.followers_count }}</span>
</div> </div>
</div> </div>
<!-- eslint-disable vue/no-v-html --> <RichContent
<p v-if="!hideBio"
v-if="!hideBio && user.description_html"
class="user-card-bio" class="user-card-bio"
@click.prevent="linkClicked" :html="user.description_html"
v-html="user.description_html" :emoji="user.emoji"
/> />
<!-- eslint-enable vue/no-v-html -->
<p
v-else-if="!hideBio"
class="user-card-bio"
>
{{ user.description }}
</p>
</div> </div>
</div> </div>
</template> </template>
@ -281,9 +264,10 @@
.user-card { .user-card {
position: relative; position: relative;
&:hover .Avatar { &:hover {
--_still-image-img-visibility: visible; --_still-image-img-visibility: visible;
--_still-image-canvas-visibility: hidden; --_still-image-canvas-visibility: hidden;
--_still-image-label-visibility: hidden;
} }
.panel-heading { .panel-heading {
@ -327,12 +311,12 @@
} }
} }
p {
margin-bottom: 0;
}
&-bio { &-bio {
text-align: center; text-align: center;
display: block;
line-height: 18px;
padding: 1em;
margin: 0;
a { a {
color: $fallback--link; color: $fallback--link;
@ -344,11 +328,6 @@
vertical-align: middle; vertical-align: middle;
max-width: 100%; max-width: 100%;
max-height: 400px; max-height: 400px;
&.emoji {
width: 32px;
height: 32px;
}
} }
} }
@ -450,13 +429,6 @@
// big one // big one
z-index: 1; z-index: 1;
img {
width: 26px;
height: 26px;
vertical-align: middle;
object-fit: contain
}
.top-line { .top-line {
display: flex; display: flex;
} }
@ -469,12 +441,7 @@
margin-right: 1em; margin-right: 1em;
font-size: 15px; font-size: 15px;
img { --emoji-size: 14px;
object-fit: contain;
height: 16px;
width: 16px;
vertical-align: middle;
}
} }
.bottom-line { .bottom-line {

View file

@ -4,6 +4,7 @@ import FollowCard from '../follow_card/follow_card.vue'
import Timeline from '../timeline/timeline.vue' import Timeline from '../timeline/timeline.vue'
import Conversation from '../conversation/conversation.vue' import Conversation from '../conversation/conversation.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
import RichContent from 'src/components/rich_content/rich_content.jsx'
import List from '../list/list.vue' import List from '../list/list.vue'
import withLoadMore from '../../hocs/with_load_more/with_load_more' import withLoadMore from '../../hocs/with_load_more/with_load_more'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@ -164,7 +165,8 @@ const UserProfile = {
FriendList, FriendList,
FollowCard, FollowCard,
TabSwitcher, TabSwitcher,
Conversation Conversation,
RichContent
} }
} }

View file

@ -20,20 +20,24 @@
:key="index" :key="index"
class="user-profile-field" class="user-profile-field"
> >
<!-- eslint-disable vue/no-v-html -->
<dt <dt
:title="user.fields_text[index].name" :title="user.fields_text[index].name"
class="user-profile-field-name" class="user-profile-field-name"
@click.prevent="linkClicked" >
v-html="field.name" <RichContent
:html="field.name"
:emoji="user.emoji"
/> />
</dt>
<dd <dd
:title="user.fields_text[index].value" :title="user.fields_text[index].value"
class="user-profile-field-value" class="user-profile-field-value"
@click.prevent="linkClicked" >
v-html="field.value" <RichContent
:html="field.value"
:emoji="user.emoji"
/> />
<!-- eslint-enable vue/no-v-html --> </dd>
</dl> </dl>
</div> </div>
<tab-switcher <tab-switcher

View file

@ -56,10 +56,11 @@ export const parseUser = (data) => {
output.emoji = data.emojis output.emoji = data.emojis
output.name = data.display_name output.name = data.display_name
output.name_html = addEmojis(escape(data.display_name), data.emojis) output.name_html = escape(data.display_name)
output.description = data.note output.description = data.note
output.description_html = addEmojis(data.note, data.emojis) // TODO cleanup this shit, output.description is overriden with source data
output.description_html = data.note
output.fields = data.fields output.fields = data.fields
output.fields_html = data.fields.map(field => { output.fields_html = data.fields.map(field => {