diff options
Diffstat (limited to 'src/components')
36 files changed, 333 insertions, 104 deletions
diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 9e410610..c53f6a9c 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -42,7 +42,7 @@ class="basic-user-card-screen-name" :to="userProfileLink(user)" > - @{{ user.screen_name }} + @{{ user.screen_name_ui }} </router-link> </div> <slot /> diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 2780be75..b54f5fb2 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -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 '' } diff --git a/src/components/chat/chat.scss b/src/components/chat/chat.scss index aef58495..3a26686c 100644 --- a/src/components/chat/chat.scss +++ b/src/components/chat/chat.scss @@ -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 { diff --git a/src/components/chat_panel/chat_panel.js b/src/components/chat_panel/chat_panel.js index c3887098..556694ae 100644 --- a/src/components/chat_panel/chat_panel.js +++ b/src/components/chat_panel/chat_panel.js @@ -35,6 +35,18 @@ const chatPanel = { userProfileLink (user) { return generateProfileLink(user.id, user.username, this.$store.state.instance.restrictedNicknames) } + }, + watch: { + messages (newVal) { + const scrollEl = this.$el.querySelector('.chat-window') + if (!scrollEl) return + if (scrollEl.scrollTop + scrollEl.offsetHeight + 20 > scrollEl.scrollHeight) { + this.$nextTick(() => { + if (!scrollEl) return + scrollEl.scrollTop = scrollEl.scrollHeight - scrollEl.offsetHeight + }) + } + } } } diff --git a/src/components/chat_panel/chat_panel.vue b/src/components/chat_panel/chat_panel.vue index 7993c94d..8a829115 100644 --- a/src/components/chat_panel/chat_panel.vue +++ b/src/components/chat_panel/chat_panel.vue @@ -10,17 +10,15 @@ @click.stop.prevent="togglePanel" > <div class="title"> - <span>{{ $t('shoutbox.title') }}</span> + {{ $t('shoutbox.title') }} <FAIcon v-if="floating" icon="times" + class="close-icon" /> </div> </div> - <div - v-chat-scroll - class="chat-window" - > + <div class="chat-window"> <div v-for="message in messages" :key="message.id" @@ -94,6 +92,13 @@ .icon { color: $fallback--text; color: var(--text, $fallback--text); + margin-right: 0.5em; + } + + .title { + display: flex; + justify-content: space-between; + align-items: center; } } diff --git a/src/components/chat_title/chat_title.js b/src/components/chat_title/chat_title.js index e424bb1f..edfbe7a4 100644 --- a/src/components/chat_title/chat_title.js +++ b/src/components/chat_title/chat_title.js @@ -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 : '' diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 353859b8..3fb26d92 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -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); diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 2068a598..dc03bc9f 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -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) { diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 1d6c760e..ad62484d 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -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> diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js index 14a2b41e..e8efbd1e 100644 --- a/src/components/emoji_input/suggestor.js +++ b/src/components/emoji_input/suggestor.js @@ -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 + ' ' diff --git a/src/components/mfa_form/recovery_form.vue b/src/components/mfa_form/recovery_form.vue index 8457ec5d..7c594228 100644 --- a/src/components/mfa_form/recovery_form.vue +++ b/src/components/mfa_form/recovery_form.vue @@ -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> diff --git a/src/components/mfa_form/totp_form.vue b/src/components/mfa_form/totp_form.vue index 5d80e185..4ee13992 100644 --- a/src/components/mfa_form/totp_form.vue +++ b/src/components/mfa_form/totp_form.vue @@ -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> diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue index 5c7b82ec..bf25adc5 100644 --- a/src/components/moderation_tools/moderation_tools.vue +++ b/src/components/moderation_tools/moderation_tools.vue @@ -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 { diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index f56aa977..0081dee4 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -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> diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 5e417fa0..391d6422 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -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') diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue index 876dd61d..2e78a09e 100644 --- a/src/components/popover/popover.vue +++ b/src/components/popover/popover.vue @@ -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> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 4148381c..e540654b 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -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: {}, diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js index 5e7b7580..ce82c90d 100644 --- a/src/components/react_button/react_button.js +++ b/src/components/react_button/react_button.js @@ -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: { diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue index 04734674..4839024c 100644 --- a/src/components/react_button/react_button.vue +++ b/src/components/react_button/react_button.vue @@ -6,6 +6,7 @@ :offset="{ y: 5 }" :bound-to="{ x: 'container' }" remove-padding + @show="focusInput" > <div slot="content" diff --git a/src/components/scope_selector/scope_selector.vue b/src/components/scope_selector/scope_selector.vue index 60e8c3ba..a01242fc 100644 --- a/src/components/scope_selector/scope_selector.vue +++ b/src/components/scope_selector/scope_selector.vue @@ -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" diff --git a/src/components/search/search.vue b/src/components/search/search.vue index fa648365..b7bfc1f3 100644 --- a/src/components/search/search.vue +++ b/src/components/search/search.vue @@ -15,8 +15,8 @@ > <button class="btn button-default search-button" - @click="newQuery(searchTerm)" type="submit" + @click="newQuery(searchTerm)" > <FAIcon icon="search" /> </button> diff --git a/src/components/search_bar/search_bar.vue b/src/components/search_bar/search_bar.vue index a7432dcb..222f57ba 100644 --- a/src/components/search_bar/search_bar.vue +++ b/src/components/search_bar/search_bar.vue @@ -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 diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue index b600b63b..146ad6c1 100644 --- a/src/components/settings_modal/helpers/boolean_setting.vue +++ b/src/components/settings_modal/helpers/boolean_setting.vue @@ -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('.') diff --git a/src/components/settings_modal/helpers/modified_indicator.vue b/src/components/settings_modal/helpers/modified_indicator.vue index b75a2811..9f4e81fe 100644 --- a/src/components/settings_modal/helpers/modified_indicator.vue +++ b/src/components/settings_modal/helpers/modified_indicator.vue @@ -2,21 +2,21 @@ <span v-if="changed" class="ModifiedIndicator" - > + > <Popover trigger="hover" - > + > <span slot="trigger"> - <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> diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index 18dd4be9..402c2a4a 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -75,8 +75,8 @@ <p>{{ $t('settings.filtering_explanation') }}</p> <textarea id="muteWords" - class="resize-height" v-model="muteWordsString" + class="resize-height" /> </div> <div> diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index f93f4ea0..9228c78e 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -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> diff --git a/src/components/status/status.js b/src/components/status/status.js index 2bf93a9e..470c01f1 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -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 () { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 6ee8117f..00e962f3 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -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)" diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 665d195e..44f749c3 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -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 () { diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 4c43fe5c..286477c2 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -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; diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/timeline/timeline_quick_settings.js new file mode 100644 index 00000000..9ec1a007 --- /dev/null +++ b/src/components/timeline/timeline_quick_settings.js @@ -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 diff --git a/src/components/timeline/timeline_quick_settings.vue b/src/components/timeline/timeline_quick_settings.vue new file mode 100644 index 00000000..4ad2842b --- /dev/null +++ b/src/components/timeline/timeline_quick_settings.vue @@ -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> diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue index 0f7c584b..4040e263 100644 --- a/src/components/user_avatar/user_avatar.vue +++ b/src/components/user_avatar/user_avatar.vue @@ -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" diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 572943b5..4b7ee7d5 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -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 @@ -141,10 +141,10 @@ v-model="userHighlightType" class="userHighlightSel" > - <option value="disabled">No highlight</option> - <option value="solid">Solid bg</option> - <option value="striped">Striped bg</option> - <option value="side">Side stripe</option> + <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option> + <option value="solid">{{ $t('user_card.highlight.solid') }}</option> + <option value="striped">{{ $t('user_card.highlight.striped') }}</option> + <option value="side">{{ $t('user_card.highlight.side') }}</option> </select> <FAIcon class="select-down-icon" diff --git a/src/components/user_list_popover/user_list_popover.vue b/src/components/user_list_popover/user_list_popover.vue index 95673733..d0aa315e 100644 --- a/src/components/user_list_popover/user_list_popover.vue +++ b/src/components/user_list_popover/user_list_popover.vue @@ -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> diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue index fb43094f..a71c02c1 100644 --- a/src/components/user_reporting_modal/user_reporting_modal.vue +++ b/src/components/user_reporting_modal/user_reporting_modal.vue @@ -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"> |
