Merge branch 'develop' of git.pleroma.social:pleroma/pleroma-fe into develop

This commit is contained in:
sadposter 2021-03-03 13:51:57 +00:00
commit d1bffd7659
59 changed files with 609 additions and 143 deletions

View file

@ -42,7 +42,7 @@
class="basic-user-card-screen-name"
:to="userProfileLink(user)"
>
@{{ user.screen_name }}
@{{ user.screen_name_ui }}
</router-link>
</div>
<slot />

View file

@ -73,7 +73,7 @@ const Chat = {
},
formPlaceholder () {
if (this.recipient) {
return this.$t('chats.message_user', { nickname: this.recipient.screen_name })
return this.$t('chats.message_user', { nickname: this.recipient.screen_name_ui })
} else {
return ''
}
@ -234,6 +234,13 @@ const Chat = {
const scrollable = this.$refs.scrollable
return scrollable && scrollable.scrollTop <= 0
},
cullOlderCheck () {
window.setTimeout(() => {
if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) {
this.$store.dispatch('cullOlderMessages', this.currentChatMessageService.chatId)
}
}, 5000)
},
handleScroll: _.throttle(function () {
if (!this.currentChat) { return }
@ -241,6 +248,7 @@ const Chat = {
this.fetchChat({ maxId: this.currentChatMessageService.minId })
} else if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) {
this.jumpToBottomButtonVisible = false
this.cullOlderCheck()
if (this.newMessageCount > 0) {
// Use a delay before marking as read to prevent situation where new messages
// arrive just as you're leaving the view and messages that you didn't actually

View file

@ -98,10 +98,10 @@
.unread-message-count {
font-size: 0.8em;
left: 50%;
transform: translate(-50%, 0);
border-radius: 100%;
margin-top: -1rem;
padding: 0;
padding: 0.1em;
border-radius: 50px;
position: absolute;
}
.chat-loading-error {

View file

@ -12,7 +12,7 @@ export default Vue.component('chat-title', {
],
computed: {
title () {
return this.user ? this.user.screen_name : ''
return this.user ? this.user.screen_name_ui : ''
},
htmlTitle () {
return this.user ? this.user.name_html : ''

View file

@ -50,7 +50,6 @@
.Conversation {
.conversation-status {
border-left: none;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: var(--border, $fallback--border);

View file

@ -194,11 +194,18 @@ const EmojiInput = {
}
},
methods: {
focusPickerInput () {
const pickerEl = this.$refs.picker.$el
if (!pickerEl) return
const pickerInput = pickerEl.querySelector('input')
if (pickerInput) pickerInput.focus()
},
triggerShowPicker () {
this.showPicker = true
this.$refs.picker.startEmojiLoad()
this.$nextTick(() => {
this.scrollIntoView()
this.focusPickerInput()
})
// This temporarily disables "click outside" handler
// since external trigger also means click originates
@ -214,6 +221,7 @@ const EmojiInput = {
if (this.showPicker) {
this.scrollIntoView()
this.$refs.picker.startEmojiLoad()
this.$nextTick(this.focusPickerInput)
}
},
replace (replacement) {

View file

@ -9,8 +9,8 @@
<button
v-if="!hideEmojiButton"
class="button-unstyled emoji-picker-icon"
@click.prevent="togglePicker"
type="button"
@click.prevent="togglePicker"
>
<FAIcon :icon="['far', 'smile-beam']" />
</button>

View file

@ -116,8 +116,8 @@ export const suggestUsers = ({ dispatch, state }) => {
return diff + nameAlphabetically + screenNameAlphabetically
/* eslint-disable camelcase */
}).map(({ screen_name, name, profile_image_url_original }) => ({
displayText: screen_name,
}).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({
displayText: screen_name_ui,
detailText: name,
imageUrl: profile_image_url_original,
replacement: '@' + screen_name + ' '

View file

@ -73,11 +73,21 @@
}
}
@keyframes media-fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.modal-image {
max-width: 90%;
max-height: 90%;
box-shadow: 0px 5px 15px 0 rgba(0, 0, 0, 0.5);
image-orientation: from-image; // NOTE: only FF supports this
animation: 0.1s cubic-bezier(0.7, 0, 1, 0.6) media-fadein;
}
.modal-view-button-arrow {

View file

@ -25,16 +25,16 @@
<div>
<button
class="button-unstyled -link"
@click.prevent="requireTOTP"
type="button"
@click.prevent="requireTOTP"
>
{{ $t('login.enter_two_factor_code') }}
</button>
<br>
<button
class="button-unstyled -link"
@click.prevent="abortMFA"
type="button"
@click.prevent="abortMFA"
>
{{ $t('general.cancel') }}
</button>

View file

@ -27,16 +27,16 @@
<div>
<button
class="button-unstyled -link"
@click.prevent="requireRecovery"
type="button"
@click.prevent="requireRecovery"
>
{{ $t('login.enter_recovery_code') }}
</button>
<br>
<button
class="button-unstyled -link"
@click.prevent="abortMFA"
type="button"
@click.prevent="abortMFA"
>
{{ $t('general.cancel') }}
</button>

View file

@ -50,74 +50,74 @@
class="button-default dropdown-item"
@click="toggleTag(tags.FORCE_NSFW)"
>
{{ $t('user_card.admin_menu.force_nsfw') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"
/>
{{ $t('user_card.admin_menu.force_nsfw') }}
</button>
<button
class="button-default dropdown-item"
@click="toggleTag(tags.STRIP_MEDIA)"
>
{{ $t('user_card.admin_menu.strip_media') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"
/>
{{ $t('user_card.admin_menu.strip_media') }}
</button>
<button
class="button-default dropdown-item"
@click="toggleTag(tags.FORCE_UNLISTED)"
>
{{ $t('user_card.admin_menu.force_unlisted') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"
/>
{{ $t('user_card.admin_menu.force_unlisted') }}
</button>
<button
class="button-default dropdown-item"
@click="toggleTag(tags.SANDBOX)"
>
{{ $t('user_card.admin_menu.sandbox') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"
/>
{{ $t('user_card.admin_menu.sandbox') }}
</button>
<button
v-if="user.is_local"
class="button-default dropdown-item"
@click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)"
>
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"
/>
{{ $t('user_card.admin_menu.disable_remote_subscription') }}
</button>
<button
v-if="user.is_local"
class="button-default dropdown-item"
@click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)"
>
{{ $t('user_card.admin_menu.disable_any_subscription') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"
/>
{{ $t('user_card.admin_menu.disable_any_subscription') }}
</button>
<button
v-if="user.is_local"
class="button-default dropdown-item"
@click="toggleTag(tags.QUARANTINE)"
>
{{ $t('user_card.admin_menu.quarantine') }}
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"
/>
{{ $t('user_card.admin_menu.quarantine') }}
</button>
</span>
</div>
@ -163,25 +163,6 @@
<style lang="scss">
@import '../../_variables.scss';
.menu-checkbox {
float: right;
min-width: 22px;
max-width: 22px;
min-height: 22px;
max-height: 22px;
line-height: 22px;
text-align: center;
border-radius: 0px;
background-color: $fallback--fg;
background-color: var(--input, $fallback--fg);
box-shadow: 0px 0px 2px black inset;
box-shadow: var(--inputShadow);
&.menu-checkbox-checked::after {
content: '✓';
}
}
.moderation-tools-popover {
height: 100%;
.trigger {

View file

@ -11,7 +11,7 @@
>
<small>
<router-link :to="userProfileLink">
{{ notification.from_profile.screen_name }}
{{ notification.from_profile.screen_name_ui }}
</router-link>
</small>
<button
@ -54,14 +54,14 @@
<bdi
v-if="!!notification.from_profile.name_html"
class="username"
:title="'@'+notification.from_profile.screen_name"
:title="'@'+notification.from_profile.screen_name_ui"
v-html="notification.from_profile.name_html"
/>
<!-- eslint-enable vue/no-v-html -->
<span
v-else
class="username"
:title="'@'+notification.from_profile.screen_name"
:title="'@'+notification.from_profile.screen_name_ui"
>{{ notification.from_profile.name }}</span>
<span v-if="notification.type === 'like'">
<FAIcon
@ -152,7 +152,7 @@
:to="userProfileLink"
class="follow-name"
>
@{{ notification.from_profile.screen_name }}
@{{ notification.from_profile.screen_name_ui }}
</router-link>
<div
v-if="notification.type === 'follow_request'"
@ -177,7 +177,7 @@
class="move-text"
>
<router-link :to="targetUserProfileLink">
@{{ notification.target.screen_name }}
@{{ notification.target.screen_name_ui }}
</router-link>
</div>
<template v-else>

View file

@ -151,6 +151,7 @@
border: none;
box-shadow: none;
background-color: transparent;
padding-right: 0.75em;
}
}

View file

@ -3,25 +3,32 @@ const Popover = {
props: {
// Action to trigger popover: either 'hover' or 'click'
trigger: String,
// Either 'top' or 'bottom'
placement: String,
// Takes object with properties 'x' and 'y', values of these can be
// 'container' for using offsetParent as boundaries for either axis
// or 'viewport'
boundTo: Object,
// Takes a selector to use as a replacement for the parent container
// for getting boundaries for x an y axis
boundToSelector: String,
// Takes a top/bottom/left/right object, how much space to leave
// between boundary and popover element
margin: Object,
// Takes a x/y object and tells how many pixels to offset from
// anchor point on either axis
offset: Object,
// Replaces the classes you may want for the popover container.
// Use 'popover-default' in addition to get the default popover
// styles with your custom class.
popoverClass: String,
// If true, subtract padding when calculating position for the popover,
// use it when popover offset looks to be different on top vs bottom.
removePadding: Boolean
@ -121,9 +128,12 @@ const Popover = {
}
},
showPopover () {
if (this.hidden) this.$emit('show')
const wasHidden = this.hidden
this.hidden = false
this.$nextTick(this.updateStyles)
this.$nextTick(() => {
if (wasHidden) this.$emit('show')
this.updateStyles()
})
},
hidePopover () {
if (!this.hidden) this.$emit('close')

View file

@ -6,8 +6,8 @@
<button
ref="trigger"
class="button-unstyled -fullwidth popover-trigger-button"
@click="onClick"
type="button"
@click="onClick"
>
<slot name="trigger" />
</button>
@ -82,10 +82,9 @@
.dropdown-item {
line-height: 21px;
margin-right: 5px;
overflow: auto;
display: block;
padding: .25rem 1.0rem .25rem 1.5rem;
padding: .5em 0.75em;
clear: both;
font-weight: 400;
text-align: inherit;
@ -101,10 +100,9 @@
--btnText: var(--popoverText, $fallback--text);
&-icon {
padding-left: 0.5rem;
svg {
margin-right: 0.25rem;
width: 22px;
margin-right: 0.75rem;
color: var(--menuPopoverIcon, $fallback--icon)
}
}
@ -123,6 +121,33 @@
}
}
.menu-checkbox {
display: inline-block;
vertical-align: middle;
min-width: 22px;
max-width: 22px;
min-height: 22px;
max-height: 22px;
line-height: 22px;
text-align: center;
border-radius: 0px;
background-color: $fallback--fg;
background-color: var(--input, $fallback--fg);
box-shadow: 0px 0px 2px black inset;
box-shadow: var(--inputShadow);
margin-right: 0.75em;
&.menu-checkbox-checked::after {
font-size: 1.25em;
content: '✓';
}
&.menu-checkbox-radio::after {
font-size: 2em;
content: '•';
}
}
}
}
</style>

View file

@ -115,7 +115,7 @@ const PostStatusForm = {
? this.copyMessageScope
: this.$store.state.users.currentUser.default_scope
const { postContentType: contentType } = this.$store.getters.mergedConfig
const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig
return {
dropFiles: [],
@ -126,7 +126,7 @@ const PostStatusForm = {
newStatus: {
spoilerText: this.subject || '',
status: statusText,
nsfw: false,
nsfw: !!sensitiveByDefault,
files: [],
poll: {},
mediaDescriptions: {},

View file

@ -23,6 +23,12 @@ const ReactButton = {
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
}
close()
},
focusInput () {
this.$nextTick(() => {
const input = this.$el.querySelector('input')
if (input) input.focus()
})
}
},
computed: {

View file

@ -6,6 +6,7 @@
:offset="{ y: 5 }"
:bound-to="{ x: 'container' }"
remove-padding
@show="focusInput"
>
<div
slot="content"

View file

@ -10,7 +10,8 @@ const registration = {
fullname: '',
username: '',
password: '',
confirm: ''
confirm: '',
reason: ''
},
captcha: {}
}),
@ -24,7 +25,8 @@ const registration = {
confirm: {
required,
sameAsPassword: sameAs('password')
}
},
reason: { required: requiredIf(() => this.accountApprovalRequired) }
}
}
},
@ -38,7 +40,10 @@ const registration = {
computed: {
token () { return this.$route.params.token },
bioPlaceholder () {
return this.$t('registration.bio_placeholder').replace(/\s*\n\s*/g, ' \n')
return this.replaceNewlines(this.$t('registration.bio_placeholder'))
},
reasonPlaceholder () {
return this.replaceNewlines(this.$t('registration.reason_placeholder'))
},
...mapState({
registrationOpen: (state) => state.instance.registrationOpen,
@ -46,7 +51,8 @@ const registration = {
isPending: (state) => state.users.signUpPending,
serverValidationErrors: (state) => state.users.signUpErrors,
termsOfService: (state) => state.instance.tos,
accountActivationRequired: (state) => state.instance.accountActivationRequired
accountActivationRequired: (state) => state.instance.accountActivationRequired,
accountApprovalRequired: (state) => state.instance.accountApprovalRequired
})
},
methods: {
@ -73,6 +79,9 @@ const registration = {
},
setCaptcha () {
this.getCaptcha().then(cpt => { this.captcha = cpt })
},
replaceNewlines (str) {
return str.replace(/\s*\n\s*/g, ' \n')
}
}
}

View file

@ -162,6 +162,23 @@
</ul>
</div>
<div
v-if="accountApprovalRequired"
class="form-group"
>
<label
class="form--label"
for="reason"
>{{ $t('registration.reason') }}</label>
<textarea
id="reason"
v-model="user.reason"
:disabled="isPending"
class="form-control"
:placeholder="reasonPlaceholder"
/>
</div>
<div
v-if="captcha.type != 'none'"
id="captcha-group"

View file

@ -8,8 +8,8 @@
class="button-unstyled scope"
:class="css.direct"
:title="$t('post_status.scope.direct')"
@click="changeVis('direct')"
type="button"
@click="changeVis('direct')"
>
<FAIcon
icon="envelope"
@ -21,8 +21,8 @@
class="button-unstyled scope"
:class="css.private"
:title="$t('post_status.scope.private')"
@click="changeVis('private')"
type="button"
@click="changeVis('private')"
>
<FAIcon
icon="lock"
@ -34,8 +34,8 @@
class="button-unstyled scope"
:class="css.unlisted"
:title="$t('post_status.scope.unlisted')"
@click="changeVis('unlisted')"
type="button"
@click="changeVis('unlisted')"
>
<FAIcon
icon="lock-open"
@ -47,8 +47,8 @@
class="button-unstyled scope"
:class="css.public"
:title="$t('post_status.scope.public')"
@click="changeVis('public')"
type="button"
@click="changeVis('public')"
>
<FAIcon
icon="globe"

View file

@ -15,8 +15,8 @@
>
<button
class="btn button-default search-button"
@click="newQuery(searchTerm)"
type="submit"
@click="newQuery(searchTerm)"
>
<FAIcon icon="search" />
</button>

View file

@ -7,8 +7,8 @@
v-if="hidden"
class="button-unstyled nav-icon"
:title="$t('nav.search')"
@click.prevent.stop="toggleHidden"
type="button"
@click.prevent.stop="toggleHidden"
>
<FAIcon
fixed-width
@ -28,8 +28,8 @@
>
<button
class="button-default search-button"
@click="find(searchTerm)"
type="submit"
@click="find(searchTerm)"
>
<FAIcon
fixed-width
@ -38,8 +38,8 @@
</button>
<button
class="button-unstyled cancel-search"
@click.prevent.stop="toggleHidden"
type="button"
@click.prevent.stop="toggleHidden"
>
<FAIcon
fixed-width

View file

@ -4,13 +4,13 @@
>
<Checkbox
:checked="state"
@change="update"
:disabled="disabled"
@change="update"
>
<span
v-if="!!$slots.default"
class="label"
>
>
<slot />
</span>
<ModifiedIndicator :changed="isChanged" />
@ -23,14 +23,14 @@ import { get, set } from 'lodash'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ModifiedIndicator from './modified_indicator.vue'
export default {
props: [
'path',
'disabled'
],
components: {
Checkbox,
ModifiedIndicator
},
props: [
'path',
'disabled'
],
computed: {
pathDefault () {
const [firstSegment, ...rest] = this.path.split('.')

View file

@ -2,21 +2,21 @@
<span
v-if="changed"
class="ModifiedIndicator"
>
>
<Popover
trigger="hover"
>
>
<span slot="trigger">
&nbsp;
<FAIcon
icon="wrench"
/>
<FAIcon
icon="wrench"
/>
</span>
<div
class="modified-tooltip"
slot="content"
>
{{ $t('settings.setting_changed') }}
class="modified-tooltip"
>
{{ $t('settings.setting_changed') }}
</div>
</Popover>
</span>
@ -32,8 +32,8 @@ library.add(
)
export default {
props: ['changed'],
components: { Popover }
components: { Popover },
props: ['changed']
}
</script>

View file

@ -75,8 +75,8 @@
<p>{{ $t('settings.filtering_explanation') }}</p>
<textarea
id="muteWords"
class="resize-height"
v-model="muteWordsString"
class="resize-height"
/>
</div>
<div>

View file

@ -144,7 +144,12 @@
</li>
<li>
<BooleanSetting path="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }} {{ minimalScopesModeDefaultValue }}
{{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="sensitiveByDefault">
{{ $t('settings.sensitive_by_default') }}
</BooleanSetting>
</li>
<li>

View file

@ -136,7 +136,7 @@ const Status = {
}
},
retweet () { return !!this.statusoid.retweeted_status },
retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name },
retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name_ui },
retweeterHtml () { return this.statusoid.user.name_html },
retweeterProfileLink () { return this.generateUserProfileLink(this.statusoid.user.id, this.statusoid.user.screen_name) },
status () {
@ -216,7 +216,7 @@ const Status = {
return this.status.in_reply_to_screen_name
} else {
const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)
return user && user.screen_name
return user && user.screen_name_ui
}
},
replySubject () {

View file

@ -26,7 +26,7 @@
icon="retweet"
/>
<router-link :to="userProfileLink">
{{ status.user.screen_name }}
{{ status.user.screen_name_ui }}
</router-link>
</small>
<small
@ -156,10 +156,10 @@
</h4>
<router-link
class="account-name"
:title="status.user.screen_name"
:title="status.user.screen_name_ui"
:to="userProfileLink"
>
{{ status.user.screen_name }}
{{ status.user.screen_name_ui }}
</router-link>
<img
v-if="!!(status.user && status.user.favicon)"

View file

@ -2,12 +2,14 @@ import Status from '../status/status.vue'
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
import Conversation from '../conversation/conversation.vue'
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
import TimelineQuickSettings from './timeline_quick_settings.vue'
import { debounce, throttle, keyBy } from 'lodash'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
import { faCircleNotch, faCog } from '@fortawesome/free-solid-svg-icons'
library.add(
faCircleNotch
faCircleNotch,
faCog
)
export const getExcludedStatusIdsByPinning = (statuses, pinnedStatusIds) => {
@ -47,7 +49,8 @@ const Timeline = {
components: {
Status,
Conversation,
TimelineMenu
TimelineMenu,
TimelineQuickSettings
},
computed: {
newStatusCount () {

View file

@ -16,6 +16,7 @@
>
{{ $t('timeline.up_to_date') }}
</div>
<TimelineQuickSettings v-if="!embedded" />
</div>
<div :class="classes.body">
<div
@ -103,9 +104,12 @@
max-width: 100%;
flex-wrap: nowrap;
align-items: center;
position: relative;
.loadmore-button {
flex-shrink: 0;
}
.loadmore-text {
flex-shrink: 0;
line-height: 1em;

View file

@ -0,0 +1,63 @@
import Popover from '../popover/popover.vue'
import BooleanSetting from '../settings_modal/helpers/boolean_setting.vue'
import { mapGetters } from 'vuex'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons'
library.add(
faFilter,
faFont,
faWrench
)
const TimelineQuickSettings = {
components: {
Popover,
BooleanSetting
},
methods: {
setReplyVisibility (visibility) {
this.$store.dispatch('setOption', { name: 'replyVisibility', value: visibility })
this.$store.dispatch('queueFlushAll')
},
openTab (tab) {
this.$store.dispatch('openSettingsModalTab', tab)
}
},
computed: {
...mapGetters(['mergedConfig']),
loggedIn () {
return !!this.$store.state.users.currentUser
},
replyVisibilitySelf: {
get () { return this.mergedConfig.replyVisibility === 'self' },
set () { this.setReplyVisibility('self') }
},
replyVisibilityFollowing: {
get () { return this.mergedConfig.replyVisibility === 'following' },
set () { this.setReplyVisibility('following') }
},
replyVisibilityAll: {
get () { return this.mergedConfig.replyVisibility === 'all' },
set () { this.setReplyVisibility('all') }
},
hideMedia: {
get () { return this.mergedConfig.hideAttachments || this.mergedConfig.hideAttachmentsInConv },
set () {
const value = !this.hideMedia
this.$store.dispatch('setOption', { name: 'hideAttachments', value })
this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
}
},
hideMutedPosts: {
get () { return this.mergedConfig.hideMutedPosts || this.mergedConfig.hideFilteredStatuses },
set () {
const value = !this.hideMutedPosts
this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value })
}
}
}
}
export default TimelineQuickSettings

View file

@ -0,0 +1,107 @@
<template>
<Popover
trigger="click"
class="TimelineQuickSettings"
:bound-to="{ x: 'container' }"
>
<div
slot="content"
class="timeline-settings-menu dropdown-menu"
>
<div v-if="loggedIn">
<button
class="button-default dropdown-item"
@click="replyVisibilityAll = true"
>
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-radio': replyVisibilityAll }"
/>{{ $t('settings.reply_visibility_all') }}
</button>
<button
class="button-default dropdown-item"
@click="replyVisibilityFollowing = true"
>
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-radio': replyVisibilityFollowing }"
/>{{ $t('settings.reply_visibility_following_short') }}
</button>
<button
class="button-default dropdown-item"
@click="replyVisibilitySelf = true"
>
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-radio': replyVisibilitySelf }"
/>{{ $t('settings.reply_visibility_self_short') }}
</button>
<div
role="separator"
class="dropdown-divider"
/>
</div>
<button
class="button-default dropdown-item"
@click="hideMedia = !hideMedia"
>
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hideMedia }"
/>{{ $t('settings.hide_media_previews') }}
</button>
<button
class="button-default dropdown-item"
@click="hideMutedPosts = !hideMutedPosts"
>
<span
class="menu-checkbox"
:class="{ 'menu-checkbox-checked': hideMutedPosts }"
/>{{ $t('settings.hide_all_muted_posts') }}
</button>
<button
class="button-default dropdown-item dropdown-item-icon"
@click="openTab('filtering')"
>
<FAIcon icon="font" />{{ $t('settings.word_filter') }}
</button>
<button
class="button-default dropdown-item dropdown-item-icon"
@click="openTab('general')"
>
<FAIcon icon="wrench" />{{ $t('settings.more_settings') }}
</button>
</div>
<div slot="trigger">
<FAIcon icon="filter" />
</div>
</Popover>
</template>
<script src="./timeline_quick_settings.js"></script>
<style lang="scss">
.TimelineQuickSettings {
align-self: stretch;
> button {
font-size: 1.2em;
padding-left: 0.7em;
padding-right: 0.2em;
line-height: 100%;
height: 100%;
}
.dropdown-item {
margin: 0;
}
.timeline-settings-menu {
display: flex;
min-width: 12em;
flex-direction: column;
}
}
</style>

View file

@ -2,8 +2,8 @@
<StillImage
v-if="user"
class="Avatar"
:alt="user.screen_name"
:title="user.screen_name"
:alt="user.screen_name_ui"
:title="user.screen_name_ui"
:src="imgSrc(user.profile_image_url_original)"
:class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
:image-load-error="imageLoadError"

View file

@ -73,10 +73,10 @@
<div class="bottom-line">
<router-link
class="user-screen-name"
:title="user.screen_name"
:title="user.screen_name_ui"
:to="userProfileLink(user)"
>
@{{ user.screen_name }}
@{{ user.screen_name_ui }}
</router-link>
<template v-if="!hideBio">
<span

View file

@ -26,7 +26,7 @@
<!-- eslint-disable vue/no-v-html -->
<span v-html="user.name_html" />
<!-- eslint-enable vue/no-v-html -->
<span class="user-list-screen-name">{{ user.screen_name }}</span>
<span class="user-list-screen-name">{{ user.screen_name_ui }}</span>
</div>
</div>
</div>

View file

@ -6,7 +6,7 @@
<div class="user-reporting-panel panel">
<div class="panel-heading">
<div class="title">
{{ $t('user_reporting.title', [user.screen_name]) }}
{{ $t('user_reporting.title', [user.screen_name_ui]) }}
</div>
</div>
<div class="panel-body">