diff options
Diffstat (limited to 'src/components')
89 files changed, 801 insertions, 684 deletions
diff --git a/src/components/account_actions/account_actions.vue b/src/components/account_actions/account_actions.vue index e3ae376e..ab5d1d29 100644 --- a/src/components/account_actions/account_actions.vue +++ b/src/components/account_actions/account_actions.vue @@ -4,6 +4,7 @@ trigger="click" placement="bottom" :bound-to="{ x: 'container' }" + remove-padding > <div slot="content" @@ -13,14 +14,14 @@ <template v-if="relationship.following"> <button v-if="relationship.showing_reblogs" - class="btn btn-default dropdown-item" + class="btn button-default dropdown-item" @click="hideRepeats" > {{ $t('user_card.hide_repeats') }} </button> <button v-if="!relationship.showing_reblogs" - class="btn btn-default dropdown-item" + class="btn button-default dropdown-item" @click="showRepeats" > {{ $t('user_card.show_repeats') }} @@ -32,27 +33,27 @@ </template> <button v-if="relationship.blocking" - class="btn btn-default btn-block dropdown-item" + class="btn button-default btn-block dropdown-item" @click="unblockUser" > {{ $t('user_card.unblock') }} </button> <button v-else - class="btn btn-default btn-block dropdown-item" + class="btn button-default btn-block dropdown-item" @click="blockUser" > {{ $t('user_card.block') }} </button> <button - class="btn btn-default btn-block dropdown-item" + class="btn button-default btn-block dropdown-item" @click="reportUser" > {{ $t('user_card.report') }} </button> <button v-if="pleromaChatMessagesAvailable" - class="btn btn-default btn-block dropdown-item" + class="btn button-default btn-block dropdown-item" @click="openChat" > {{ $t('user_card.message') }} @@ -61,7 +62,7 @@ </div> <div slot="trigger" - class="btn btn-default ellipsis-button" + class="ellipsis-button" > <FAIcon class="icon" diff --git a/src/components/async_component_error/async_component_error.vue b/src/components/async_component_error/async_component_error.vue index b68b98f9..b1b59638 100644 --- a/src/components/async_component_error/async_component_error.vue +++ b/src/components/async_component_error/async_component_error.vue @@ -8,7 +8,7 @@ {{ $t('general.error_retry') }} </p> <button - class="btn" + class="btn button-default" @click="retry" > {{ $t('general.retry') }} diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index e23fcb1b..5f5779a0 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -8,14 +8,18 @@ import { faFile, faMusic, faImage, - faVideo + faVideo, + faPlayCircle, + faTimes } from '@fortawesome/free-solid-svg-icons' library.add( faFile, faMusic, faImage, - faVideo + faVideo, + faPlayCircle, + faTimes ) const Attachment = { diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index f1fac2c8..2c1c1682 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -42,15 +42,13 @@ icon="play-circle" /> </a> - <div + <button v-if="nsfw && hideNsfwLocal && !hidden" - class="hider" + class="button-unstyled hider" + @click.prevent="toggleHidden" > - <a - href="#" - @click.prevent="toggleHidden" - >Hide</a> - </div> + <FAIcon icon="times" /> + </button> <a v-if="type === 'image' && (!hidden || preloadImage)" @@ -234,15 +232,23 @@ .hider { position: absolute; right: 0; - white-space: nowrap; margin: 10px; - padding: 5px; - background: rgba(230,230,230,0.6); - font-weight: bold; + padding: 0; z-index: 4; - line-height: 1; border-radius: $fallback--tooltipRadius; border-radius: var(--tooltipRadius, $fallback--tooltipRadius); + text-align: center; + width: 2em; + height: 2em; + font-size: 1.25em; + // TODO: theming? hard to theme with unknown background image color + background: rgba(230, 230, 230, 0.7); + .svg-inline--fa { + color: rgba(0, 0, 0, 0.6); + } + &:hover .svg-inline--fa { + color: rgba(0, 0, 0, 0.9); + } } video { diff --git a/src/components/block_card/block_card.vue b/src/components/block_card/block_card.vue index 5b00b738..2fe66d4c 100644 --- a/src/components/block_card/block_card.vue +++ b/src/components/block_card/block_card.vue @@ -3,7 +3,7 @@ <div class="block-card-content-container"> <button v-if="blocked" - class="btn btn-default" + class="btn button-default" :disabled="progress" @click="unblockUser" > @@ -16,7 +16,7 @@ </button> <button v-else - class="btn btn-default" + class="btn button-default" :disabled="progress" @click="blockUser" > diff --git a/src/components/chat_list/chat_list.vue b/src/components/chat_list/chat_list.vue index 17e2f795..e23eec13 100644 --- a/src/components/chat_list/chat_list.vue +++ b/src/components/chat_list/chat_list.vue @@ -10,7 +10,10 @@ <span class="title"> {{ $t("chats.chats") }} </span> - <button @click="newChat"> + <button + class="button-default" + @click="newChat" + > {{ $t("chats.new") }} </button> </div> diff --git a/src/components/chat_message/chat_message.scss b/src/components/chat_message/chat_message.scss index 5af744a3..e4351d3b 100644 --- a/src/components/chat_message/chat_message.scss +++ b/src/components/chat_message/chat_message.scss @@ -31,9 +31,6 @@ color: $fallback--text; color: var(--text, $fallback--text); } - - border-radius: $fallback--chatMessageRadius; - border-radius: var(--chatMessageRadius, $fallback--chatMessageRadius); } .popover { diff --git a/src/components/chat_message/chat_message.vue b/src/components/chat_message/chat_message.vue index 3849ab6e..0777f880 100644 --- a/src/components/chat_message/chat_message.vue +++ b/src/components/chat_message/chat_message.vue @@ -53,7 +53,7 @@ <div slot="content"> <div class="dropdown-menu"> <button - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click="deleteMessage" > <FAIcon icon="times" /> {{ $t("chats.delete") }} @@ -62,7 +62,7 @@ </div> <button slot="trigger" - class="menu-icon" + class="button-default menu-icon" :title="$t('chats.more')" > <FAIcon icon="ellipsis-h" /> diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index e0b9fcc5..353859b8 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -10,12 +10,13 @@ class="panel-heading conversation-heading" > <span class="title"> {{ $t('timeline.conversation') }} </span> - <span v-if="collapsable"> - <a - href="#" - @click.prevent="toggleExpanded" - >{{ $t('timeline.collapse') }}</a> - </span> + <button + v-if="collapsable" + class="button-unstyled -link" + @click.prevent="toggleExpanded" + > + {{ $t('timeline.collapse') }} + </button> </div> <status v-for="status in conversation" @@ -57,13 +58,6 @@ } &.-expanded { - .conversation-status { - border-color: $fallback--border; - border-color: var(--border, $fallback--border); - border-left-color: $fallback--cRed; - border-left-color: var(--cRed, $fallback--cRed); - } - .conversation-status:last-child { border-bottom: none; border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; diff --git a/src/components/desktop_nav/desktop_nav.scss b/src/components/desktop_nav/desktop_nav.scss index 028692a9..2d468588 100644 --- a/src/components/desktop_nav/desktop_nav.scss +++ b/src/components/desktop_nav/desktop_nav.scss @@ -5,6 +5,10 @@ width: 100%; position: fixed; + a { + color: var(--topBarLink, $fallback--link); + } + .inner-nav { display: grid; grid-template-rows: 50px; @@ -21,7 +25,7 @@ grid-template-areas: "logo sitename actions"; } - button { + .button-default { &, svg { color: $fallback--text; color: var(--btnTopBarText, $fallback--text); @@ -80,12 +84,13 @@ .nav-icon { margin-left: 0.2em; width: 2em; + height: 100%; text-align: center; - } - a, a svg { - color: $fallback--link; - color: var(--topBarLink, $fallback--link); + .svg-inline--fa { + color: $fallback--link; + color: var(--topBarLink, $fallback--link); + } } .sitename { diff --git a/src/components/desktop_nav/desktop_nav.vue b/src/components/desktop_nav/desktop_nav.vue index 3a6e4033..762aa610 100644 --- a/src/components/desktop_nav/desktop_nav.vue +++ b/src/components/desktop_nav/desktop_nav.vue @@ -36,9 +36,8 @@ @toggled="onSearchBarToggled" @click.stop.native /> - <a - href="#" - class="nav-icon" + <button + class="button-unstyled nav-icon" @click.stop="openSettingsModal" > <FAIcon @@ -47,29 +46,32 @@ icon="cog" :title="$t('nav.preferences')" /> - </a> + </button> <a v-if="currentUser && currentUser.role === 'admin'" href="/pleroma/admin/#/login-pleroma" class="nav-icon" target="_blank" - ><FAIcon - fixed-width - class="fa-scale-110 fa-old-padding" - icon="tachometer-alt" - :title="$t('nav.administration')" - /></a> - <a + > + <FAIcon + fixed-width + class="fa-scale-110 fa-old-padding" + icon="tachometer-alt" + :title="$t('nav.administration')" + /> + </a> + <button v-if="currentUser" - href="#" - class="nav-icon" + class="button-unstyled nav-icon" @click.prevent="logout" - ><FAIcon - fixed-width - class="fa-scale-110 fa-old-padding" - icon="sign-out-alt" - :title="$t('login.logout')" - /></a> + > + <FAIcon + fixed-width + class="fa-scale-110 fa-old-padding" + icon="sign-out-alt" + :title="$t('login.logout')" + /> + </button> </div> </div> </nav> diff --git a/src/components/domain_mute_card/domain_mute_card.vue b/src/components/domain_mute_card/domain_mute_card.vue index 97aee243..3b5aec14 100644 --- a/src/components/domain_mute_card/domain_mute_card.vue +++ b/src/components/domain_mute_card/domain_mute_card.vue @@ -6,7 +6,7 @@ <ProgressButton v-if="muted" :click="unmuteDomain" - class="btn btn-default" + class="btn button-default" > {{ $t('domain_mute_card.unmute') }} <template slot="progress"> @@ -16,7 +16,7 @@ <ProgressButton v-else :click="muteDomain" - class="btn btn-default" + class="btn button-default" > {{ $t('domain_mute_card.mute') }} <template slot="progress"> diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 87303d08..2068a598 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -114,7 +114,8 @@ const EmojiInput = { showPicker: false, temporarilyHideSuggestions: false, keepOpen: false, - disableClickOutside: false + disableClickOutside: false, + suggestions: [] } }, components: { @@ -124,21 +125,6 @@ const EmojiInput = { padEmoji () { return this.$store.getters.mergedConfig.padEmoji }, - suggestions () { - const firstchar = this.textAtCaret.charAt(0) - if (this.textAtCaret === firstchar) { return [] } - const matchedSuggestions = this.suggest(this.textAtCaret) - if (matchedSuggestions.length <= 0) { - return [] - } - return take(matchedSuggestions, 5) - .map(({ imageUrl, ...rest }, index) => ({ - ...rest, - // eslint-disable-next-line camelcase - img: imageUrl || '', - highlighted: index === this.highlighted - })) - }, showSuggestions () { return this.focused && this.suggestions && @@ -188,6 +174,23 @@ const EmojiInput = { watch: { showSuggestions: function (newValue) { this.$emit('shown', newValue) + }, + textAtCaret: async function (newWord) { + const firstchar = newWord.charAt(0) + this.suggestions = [] + if (newWord === firstchar) return + const matchedSuggestions = await this.suggest(newWord) + // Async: cancel if textAtCaret has changed during wait + if (this.textAtCaret !== newWord) return + if (matchedSuggestions.length <= 0) return + this.suggestions = take(matchedSuggestions, 5) + .map(({ imageUrl, ...rest }) => ({ + ...rest, + img: imageUrl || '' + })) + }, + suggestions (newValue) { + this.$nextTick(this.resize) } }, methods: { diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 224e72cf..4becdc41 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -6,13 +6,13 @@ > <slot /> <template v-if="enableEmojiPicker"> - <div + <button v-if="!hideEmojiButton" - class="emoji-picker-icon" + class="button-unstyled emoji-picker-icon" @click.prevent="togglePicker" > <FAIcon :icon="['far', 'smile-beam']" /> - </div> + </button> <EmojiPicker v-if="enableEmojiPicker" ref="picker" @@ -37,7 +37,7 @@ v-for="(suggestion, index) in suggestions" :key="index" class="autocomplete-item" - :class="{ highlighted: suggestion.highlighted }" + :class="{ highlighted: index === highlighted }" @click.stop.prevent="onClick($event, suggestion)" > <span class="image"> diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js index 8330345b..14a2b41e 100644 --- a/src/components/emoji_input/suggestor.js +++ b/src/components/emoji_input/suggestor.js @@ -1,4 +1,3 @@ -import { debounce } from 'lodash' /** * suggest - generates a suggestor function to be used by emoji-input * data: object providing source information for specific types of suggestions: @@ -11,19 +10,19 @@ import { debounce } from 'lodash' * doesn't support user linking you can just provide only emoji. */ -const debounceUserSearch = debounce((data, input) => { - data.updateUsersList(input) -}, 500) - -export default data => input => { - const firstChar = input[0] - if (firstChar === ':' && data.emoji) { - return suggestEmoji(data.emoji)(input) - } - if (firstChar === '@' && data.users) { - return suggestUsers(data)(input) +export default data => { + const emojiCurry = suggestEmoji(data.emoji) + const usersCurry = data.store && suggestUsers(data.store) + return input => { + const firstChar = input[0] + if (firstChar === ':' && data.emoji) { + return emojiCurry(input) + } + if (firstChar === '@' && usersCurry) { + return usersCurry(input) + } + return [] } - return [] } export const suggestEmoji = emojis => input => { @@ -57,50 +56,75 @@ export const suggestEmoji = emojis => input => { }) } -export const suggestUsers = data => input => { - const noPrefix = input.toLowerCase().substr(1) - const users = data.users - - const newUsers = users.filter( - user => - user.screen_name.toLowerCase().startsWith(noPrefix) || - user.name.toLowerCase().startsWith(noPrefix) - - /* taking only 20 results so that sorting is a bit cheaper, we display - * only 5 anyway. could be inaccurate, but we ideally we should query - * backend anyway - */ - ).slice(0, 20).sort((a, b) => { - let aScore = 0 - let bScore = 0 - - // Matches on screen name (i.e. user@instance) makes a priority - aScore += a.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0 - bScore += b.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0 - - // Matches on name takes second priority - aScore += a.name.toLowerCase().startsWith(noPrefix) ? 1 : 0 - bScore += b.name.toLowerCase().startsWith(noPrefix) ? 1 : 0 - - const diff = (bScore - aScore) * 10 - - // Then sort alphabetically - const nameAlphabetically = a.name > b.name ? 1 : -1 - const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 - - return diff + nameAlphabetically + screenNameAlphabetically - /* eslint-disable camelcase */ - }).map(({ screen_name, name, profile_image_url_original }) => ({ - displayText: screen_name, - detailText: name, - imageUrl: profile_image_url_original, - replacement: '@' + screen_name + ' ' - })) - - // BE search users to get more comprehensive results - if (data.updateUsersList) { - debounceUserSearch(data, noPrefix) +export const suggestUsers = ({ dispatch, state }) => { + // Keep some persistent values in closure, most importantly for the + // custom debounce to work. Lodash debounce does not return a promise. + let suggestions = [] + let previousQuery = '' + let timeout = null + let cancelUserSearch = null + + const userSearch = (query) => dispatch('searchUsers', { query }) + const debounceUserSearch = (query) => { + cancelUserSearch && cancelUserSearch() + return new Promise((resolve, reject) => { + timeout = setTimeout(() => { + userSearch(query).then(resolve).catch(reject) + }, 300) + cancelUserSearch = () => { + clearTimeout(timeout) + resolve([]) + } + }) + } + + return async input => { + const noPrefix = input.toLowerCase().substr(1) + if (previousQuery === noPrefix) return suggestions + + suggestions = [] + previousQuery = noPrefix + // Fetch more and wait, don't fetch if there's the 2nd @ because + // the backend user search can't deal with it. + // Reference semantics make it so that we get the updated data after + // the await. + if (!noPrefix.includes('@')) { + await debounceUserSearch(noPrefix) + } + + const newSuggestions = state.users.users.filter( + user => + user.screen_name.toLowerCase().startsWith(noPrefix) || + user.name.toLowerCase().startsWith(noPrefix) + ).slice(0, 20).sort((a, b) => { + let aScore = 0 + let bScore = 0 + + // Matches on screen name (i.e. user@instance) makes a priority + aScore += a.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0 + bScore += b.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0 + + // Matches on name takes second priority + aScore += a.name.toLowerCase().startsWith(noPrefix) ? 1 : 0 + bScore += b.name.toLowerCase().startsWith(noPrefix) ? 1 : 0 + + const diff = (bScore - aScore) * 10 + + // Then sort alphabetically + const nameAlphabetically = a.name > b.name ? 1 : -1 + const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 + + return diff + nameAlphabetically + screenNameAlphabetically + /* eslint-disable camelcase */ + }).map(({ screen_name, name, profile_image_url_original }) => ({ + displayText: screen_name, + detailText: name, + imageUrl: profile_image_url_original, + replacement: '@' + screen_name + ' ' + })) + /* eslint-enable camelcase */ + + suggestions = newSuggestions || [] + return suggestions } - return newUsers - /* eslint-enable camelcase */ } diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue index 2f14b5b2..51d50359 100644 --- a/src/components/emoji_reactions/emoji_reactions.vue +++ b/src/components/emoji_reactions/emoji_reactions.vue @@ -6,7 +6,7 @@ :users="accountsForEmoji[reaction.name]" > <button - class="emoji-reaction btn btn-default" + class="emoji-reaction btn button-default" :class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }" @click="emojiOnClick(reaction.name, $event)" @mouseenter="fetchEmojiReactionsByIfMissing()" diff --git a/src/components/export_import/export_import.vue b/src/components/export_import/export_import.vue index ae00487f..8ffe34f8 100644 --- a/src/components/export_import/export_import.vue +++ b/src/components/export_import/export_import.vue @@ -2,13 +2,13 @@ <div class="import-export-container"> <slot name="before" /> <button - class="btn" + class="btn button-default" @click="exportData" > {{ exportLabel }} </button> <button - class="btn" + class="btn button-default" @click="importData" > {{ importLabel }} diff --git a/src/components/exporter/exporter.vue b/src/components/exporter/exporter.vue index ecd71bf1..d6a03088 100644 --- a/src/components/exporter/exporter.vue +++ b/src/components/exporter/exporter.vue @@ -11,7 +11,7 @@ </div> <button v-else - class="btn btn-default" + class="btn button-default" @click="process" > {{ exportButtonLabel }} diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js index 1a8eef72..b5b29e8a 100644 --- a/src/components/extra_buttons/extra_buttons.js +++ b/src/components/extra_buttons/extra_buttons.js @@ -5,7 +5,8 @@ import { faBookmark, faEyeSlash, faThumbtack, - faShareAlt + faShareAlt, + faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons' import { faBookmark as faBookmarkReg @@ -17,7 +18,8 @@ library.add( faBookmarkReg, faEyeSlash, faThumbtack, - faShareAlt + faShareAlt, + faExternalLinkAlt ) const ExtraButtons = { diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue index a33f6e87..dc790cad 100644 --- a/src/components/extra_buttons/extra_buttons.vue +++ b/src/components/extra_buttons/extra_buttons.vue @@ -1,9 +1,11 @@ <template> <Popover + class="ExtraButtons" trigger="click" placement="top" - class="extra-button-popover" + :offset="{ y: 5 }" :bound-to="{ x: 'container' }" + remove-padding > <div slot="content" @@ -12,7 +14,7 @@ <div class="dropdown-menu"> <button v-if="canMute && !status.thread_muted" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="muteConversation" > <FAIcon @@ -22,7 +24,7 @@ </button> <button v-if="canMute && status.thread_muted" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="unmuteConversation" > <FAIcon @@ -32,7 +34,7 @@ </button> <button v-if="!status.pinned && canPin" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="pinStatus" @click="close" > @@ -43,7 +45,7 @@ </button> <button v-if="status.pinned && canPin" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="unpinStatus" @click="close" > @@ -54,7 +56,7 @@ </button> <button v-if="!status.bookmarked" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="bookmarkStatus" @click="close" > @@ -65,7 +67,7 @@ </button> <button v-if="status.bookmarked" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="unbookmarkStatus" @click="close" > @@ -76,7 +78,7 @@ </button> <button v-if="canDelete" - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="deleteStatus" @click="close" > @@ -86,7 +88,7 @@ /><span>{{ $t("status.delete") }}</span> </button> <button - class="dropdown-item dropdown-item-icon" + class="button-default dropdown-item dropdown-item-icon" @click.prevent="copyLink" @click="close" > @@ -95,11 +97,26 @@ icon="share-alt" /><span>{{ $t("status.copy_link") }}</span> </button> + <a + v-if="!status.is_local" + class="button-default dropdown-item dropdown-item-icon" + title="Source" + :href="status.external_url" + target="_blank" + > + <FAIcon + fixed-width + icon="external-link-alt" + /><span>{{ $t("status.external_source") }}</span> + </a> </div> </div> - <span slot="trigger"> + <span + slot="trigger" + class="popover-trigger" + > <FAIcon - class="ExtraButtons fa-scale-110 fa-old-padding" + class="fa-scale-110 fa-old-padding" icon="ellipsis-h" /> </span> @@ -112,13 +129,15 @@ @import '../../_variables.scss'; .ExtraButtons { - cursor: pointer; - position: static; + .popover-trigger { + position: static; + padding: 10px; + margin: -10px; - &:hover, - .extra-button-popover.open & { - color: $fallback--text; - color: var(--text, $fallback--text); + &:hover .svg-inline--fa { + color: $fallback--text; + color: var(--text, $fallback--text); + } } } </style> diff --git a/src/components/favorite_button/favorite_button.js b/src/components/favorite_button/favorite_button.js index 2a2ee84a..5cd05f73 100644 --- a/src/components/favorite_button/favorite_button.js +++ b/src/components/favorite_button/favorite_button.js @@ -31,11 +31,6 @@ const FavoriteButton = { } }, computed: { - classes () { - return { - '-favorited': this.status.favorited - } - }, ...mapGetters(['mergedConfig']) } } diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue index dfe12f86..dce25e24 100644 --- a/src/components/favorite_button/favorite_button.vue +++ b/src/components/favorite_button/favorite_button.vue @@ -1,23 +1,31 @@ <template> - <div v-if="loggedIn"> - <FAIcon - :class="classes" - class="FavoriteButton fa-scale-110 fa-old-padding -interactive" + <div class="FavoriteButton"> + <button + v-if="loggedIn" + class="button-unstyled interactive" + :class="status.favorited && '-favorited'" :title="$t('tool_tip.favorite')" - :icon="[status.favorited ? 'fas' : 'far', 'star']" - :spin="animated" @click.prevent="favorite()" - /> - <span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span> - </div> - <div v-else> - <FAIcon - :class="classes" - class="FavoriteButton fa-scale-110 fa-old-padding" - :title="$t('tool_tip.favorite')" - :icon="['far', 'star']" - /> - <span v-if="!mergedConfig.hidePostStats && status.fave_num > 0">{{ status.fave_num }}</span> + > + <FAIcon + class="fa-scale-110 fa-old-padding" + :icon="[status.favorited ? 'fas' : 'far', 'star']" + :spin="animated" + /> + </button> + <span v-else> + <FAIcon + class="fa-scale-110 fa-old-padding" + :title="$t('tool_tip.favorite')" + :icon="['far', 'star']" + /> + </span> + <span + v-if="!mergedConfig.hidePostStats && status.fave_num > 0" + class="action-counter" + > + {{ status.fave_num }} + </span> </div> </template> @@ -27,19 +35,28 @@ @import '../../_variables.scss'; .FavoriteButton { - &.-interactive { - cursor: pointer; - animation-duration: 0.6s; + display: flex; + + > :first-child { + padding: 10px; + margin: -10px -8px -10px -10px; + } + + .action-counter { + pointer-events: none; + user-select: none; + } + + .interactive { + .svg-inline--fa { + animation-duration: 0.6s; + } - &:hover { + &:hover .svg-inline--fa, + &.-favorited .svg-inline--fa { color: $fallback--cOrange; color: var(--cOrange, $fallback--cOrange); } } - - &.-favorited { - color: $fallback--cOrange; - color: var(--cOrange, $fallback--cOrange); - } } </style> diff --git a/src/components/features_panel/features_panel.js b/src/components/features_panel/features_panel.js index 620a85ea..8b142d08 100644 --- a/src/components/features_panel/features_panel.js +++ b/src/components/features_panel/features_panel.js @@ -1,3 +1,5 @@ +import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' + const FeaturesPanel = { computed: { chat: function () { return this.$store.state.instance.chatAvailable }, @@ -6,7 +8,8 @@ const FeaturesPanel = { whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled }, mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable }, minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode }, - textlimit: function () { return this.$store.state.instance.textlimit } + textlimit: function () { return this.$store.state.instance.textlimit }, + uploadlimit: function () { return fileSizeFormatService.fileSizeFormat(this.$store.state.instance.uploadlimit) } } } diff --git a/src/components/features_panel/features_panel.vue b/src/components/features_panel/features_panel.vue index 608b11c8..9605d09d 100644 --- a/src/components/features_panel/features_panel.vue +++ b/src/components/features_panel/features_panel.vue @@ -25,6 +25,7 @@ </li> <li>{{ $t('features_panel.scope_options') }}</li> <li>{{ $t('features_panel.text_limit') }} = {{ textlimit }}</li> + <li>{{ $t('features_panel.upload_limit') }} = {{ uploadlimit.num }} {{ $t('upload.file_size_units.' + uploadlimit.unit) }}</li> </ul> </div> </div> diff --git a/src/components/follow_button/follow_button.vue b/src/components/follow_button/follow_button.vue index bfdc137b..7f85f1d7 100644 --- a/src/components/follow_button/follow_button.vue +++ b/src/components/follow_button/follow_button.vue @@ -1,6 +1,6 @@ <template> <button - class="btn btn-default follow-button" + class="btn button-default follow-button" :class="{ toggled: isPressed }" :disabled="inProgress" :title="title" diff --git a/src/components/follow_request_card/follow_request_card.vue b/src/components/follow_request_card/follow_request_card.vue index b217b8ed..1b12ba4b 100644 --- a/src/components/follow_request_card/follow_request_card.vue +++ b/src/components/follow_request_card/follow_request_card.vue @@ -2,13 +2,13 @@ <basic-user-card :user="user"> <div class="follow-request-card-content-container"> <button - class="btn btn-default" + class="btn button-default" @click="approveUser" > {{ $t('user_card.approve') }} </button> <button - class="btn btn-default" + class="btn button-default" @click="denyUser" > {{ $t('user_card.deny') }} diff --git a/src/components/global_notice_list/global_notice_list.vue b/src/components/global_notice_list/global_notice_list.vue index 8a33b9eb..049e23db 100644 --- a/src/components/global_notice_list/global_notice_list.vue +++ b/src/components/global_notice_list/global_notice_list.vue @@ -9,11 +9,15 @@ <div class="notice-message"> {{ $t(notice.messageKey, notice.messageArgs) }} </div> - <FAIcon - class="fa-scale-110 fa-old-padding" - icon="times" + <button + class="button-unstyled close-notice" @click="closeNotice(notice)" - /> + > + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="times" + /> + </button> </div> </div> </template> @@ -54,7 +58,7 @@ .global-error { background-color: var(--alertPopupError, $fallback--cRed); color: var(--alertPopupErrorText, $fallback--text); - i { + .svg-inline--fa { color: var(--alertPopupErrorText, $fallback--text); } } @@ -62,7 +66,7 @@ .global-warning { background-color: var(--alertPopupWarning, $fallback--cOrange); color: var(--alertPopupWarningText, $fallback--text); - i { + .svg-inline--fa { color: var(--alertPopupWarningText, $fallback--text); } } @@ -70,9 +74,16 @@ .global-info { background-color: var(--alertPopupNeutral, $fallback--fg); color: var(--alertPopupNeutralText, $fallback--text); - i { + .svg-inline--fa { color: var(--alertPopupNeutralText, $fallback--text); } } + + .close-notice { + padding-right: 0.2em; + .svg-inline--fa:hover { + opacity: 0.6; + } + } } </style> diff --git a/src/components/image_cropper/image_cropper.js b/src/components/image_cropper/image_cropper.js index 59e4d07e..e8d5ec6d 100644 --- a/src/components/image_cropper/image_cropper.js +++ b/src/components/image_cropper/image_cropper.js @@ -2,12 +2,10 @@ import Cropper from 'cropperjs' import 'cropperjs/dist/cropper.css' import { library } from '@fortawesome/fontawesome-svg-core' import { - faTimes, faCircleNotch } from '@fortawesome/free-solid-svg-icons' library.add( - faTimes, faCircleNotch ) @@ -53,8 +51,7 @@ const ImageCropper = { cropper: undefined, dataUrl: undefined, filename: undefined, - submitting: false, - submitError: null + submitting: false } }, computed: { @@ -66,9 +63,6 @@ const ImageCropper = { }, cancelText () { return this.cancelButtonLabel || this.$t('image_cropper.cancel') - }, - submitErrorMsg () { - return this.submitError && this.submitError instanceof Error ? this.submitError.toString() : this.submitError } }, methods: { @@ -82,12 +76,8 @@ const ImageCropper = { }, submit (cropping = true) { this.submitting = true - this.avatarUploadError = null this.submitHandler(cropping && this.cropper, this.file) .then(() => this.destroy()) - .catch((err) => { - this.submitError = err - }) .finally(() => { this.submitting = false }) @@ -113,9 +103,6 @@ const ImageCropper = { reader.readAsDataURL(this.file) this.$emit('changed', this.file, reader) } - }, - clearError () { - this.submitError = null } }, mounted () { diff --git a/src/components/image_cropper/image_cropper.vue b/src/components/image_cropper/image_cropper.vue index 75def612..8c48a387 100644 --- a/src/components/image_cropper/image_cropper.vue +++ b/src/components/image_cropper/image_cropper.vue @@ -11,21 +11,21 @@ </div> <div class="image-cropper-buttons-wrapper"> <button - class="btn" + class="button-default btn" type="button" :disabled="submitting" @click="submit()" v-text="saveText" /> <button - class="btn" + class="button-default btn" type="button" :disabled="submitting" @click="destroy" v-text="cancelText" /> <button - class="btn" + class="button-default btn" type="button" :disabled="submitting" @click="submit(false)" @@ -37,17 +37,6 @@ icon="circle-notch" /> </div> - <div - v-if="submitError" - class="alert error" - > - {{ submitErrorMsg }} - <FAIcon - class="fa-scale-110 fa-old-padding" - icon="times" - @click="clearError" - /> - </div> </div> <input ref="input" diff --git a/src/components/importer/importer.vue b/src/components/importer/importer.vue index c4fe5b00..210823f5 100644 --- a/src/components/importer/importer.vue +++ b/src/components/importer/importer.vue @@ -15,7 +15,7 @@ /> <button v-else - class="btn btn-default" + class="btn button-default" @click="submit" > {{ submitButtonLabel }} diff --git a/src/components/link-preview/link-preview.js b/src/components/link-preview/link-preview.js index 444aafbe..add7c563 100644 --- a/src/components/link-preview/link-preview.js +++ b/src/components/link-preview/link-preview.js @@ -1,3 +1,5 @@ +import { mapGetters } from 'vuex' + const LinkPreview = { name: 'LinkPreview', props: [ @@ -15,11 +17,20 @@ const LinkPreview = { // Currently BE shoudn't give cards if tagged NSFW, this is a bit paranoid // as it makes sure to hide the image if somehow NSFW tagged preview can // exist. - return this.card.image && !this.nsfw && this.size !== 'hide' + return this.card.image && !this.censored && this.size !== 'hide' + }, + censored () { + return this.nsfw && this.hideNsfwConfig }, useDescription () { return this.card.description && /\S/.test(this.card.description) - } + }, + hideNsfwConfig () { + return this.mergedConfig.hideNsfw + }, + ...mapGetters([ + 'mergedConfig' + ]) }, created () { if (this.useImage) { diff --git a/src/components/link-preview/link-preview.vue b/src/components/link-preview/link-preview.vue index 69171977..d3ca39b8 100644 --- a/src/components/link-preview/link-preview.vue +++ b/src/components/link-preview/link-preview.vue @@ -9,12 +9,17 @@ <div v-if="useImage && imageLoaded" class="card-image" - :class="{ 'small-image': size === 'small' }" > <img :src="card.image"> </div> <div class="card-content"> - <span class="card-host faint">{{ card.provider_name }}</span> + <span class="card-host faint"> + <span + v-if="censored" + class="nsfw-alert alert warning" + >{{ $t('status.nsfw') }}</span> + {{ card.provider_name }} + </span> <h4 class="card-title">{{ card.title }}</h4> <p v-if="useDescription" @@ -50,10 +55,6 @@ } } - .small-image { - width: 80px; - } - .card-content { max-height: 100%; margin: 0.5em; @@ -76,6 +77,10 @@ max-height: calc(1.2em * 3 - 1px); } + .nsfw-alert { + margin: 2em 0; + } + color: $fallback--text; color: var(--text, $fallback--text); border-style: solid; diff --git a/src/components/login_form/login_form.vue b/src/components/login_form/login_form.vue index a1f77210..bfabb946 100644 --- a/src/components/login_form/login_form.vue +++ b/src/components/login_form/login_form.vue @@ -61,7 +61,7 @@ <button :disabled="loggingIn" type="submit" - class="btn btn-default" + class="btn button-default" > {{ $t('login.login') }} </button> diff --git a/src/components/media_upload/media_upload.vue b/src/components/media_upload/media_upload.vue index 88251a26..e955aa72 100644 --- a/src/components/media_upload/media_upload.vue +++ b/src/components/media_upload/media_upload.vue @@ -1,33 +1,29 @@ <template> - <div + <label class="media-upload" :class="{ disabled: disabled }" + :title="$t('tool_tip.media_upload')" > - <label - class="label" - :title="$t('tool_tip.media_upload')" + <FAIcon + v-if="uploading" + class="progress-icon" + icon="circle-notch" + spin + /> + <FAIcon + v-if="!uploading" + class="new-icon" + icon="upload" + /> + <input + v-if="uploadReady" + :disabled="disabled" + type="file" + style="position: fixed; top: -100em" + multiple="true" + @change="change" > - <FAIcon - v-if="uploading" - class="progress-icon" - icon="circle-notch" - spin - /> - <FAIcon - v-if="!uploading" - class="new-icon" - icon="upload" - /> - <input - v-if="uploadReady" - :disabled="disabled" - type="file" - style="position: fixed; top: -100em" - multiple="true" - @change="change" - > - </label> - </div> + </label> </template> <script src="./media_upload.js" ></script> @@ -36,12 +32,6 @@ @import '../../_variables.scss'; .media-upload { - .label { - display: inline-block; - } - - .new-icon { - cursor: pointer; - } + cursor: pointer; } </style> diff --git a/src/components/mfa_form/recovery_form.vue b/src/components/mfa_form/recovery_form.vue index 78953649..0bf68e27 100644 --- a/src/components/mfa_form/recovery_form.vue +++ b/src/components/mfa_form/recovery_form.vue @@ -23,23 +23,23 @@ <div class="form-group"> <div class="login-bottom"> <div> - <a - href="#" + <button + class="button-unstyled -link" @click.prevent="requireTOTP" > {{ $t('login.enter_two_factor_code') }} - </a> + </button> <br> - <a - href="#" + <button + class="button-unstyled -link" @click.prevent="abortMFA" > {{ $t('general.cancel') }} - </a> + </button> </div> <button type="submit" - class="btn btn-default" + class="btn button-default" > {{ $t('general.verify') }} </button> diff --git a/src/components/mfa_form/totp_form.vue b/src/components/mfa_form/totp_form.vue index 9401cad5..79230148 100644 --- a/src/components/mfa_form/totp_form.vue +++ b/src/components/mfa_form/totp_form.vue @@ -25,23 +25,23 @@ <div class="form-group"> <div class="login-bottom"> <div> - <a - href="#" + <button + class="button-unstyled -link" @click.prevent="requireRecovery" > {{ $t('login.enter_recovery_code') }} - </a> + </button> <br> - <a - href="#" + <button + class="button-unstyled -link" @click.prevent="abortMFA" > {{ $t('general.cancel') }} - </a> + </button> </div> <button type="submit" - class="btn btn-default" + class="btn button-default" > {{ $t('general.verify') }} </button> diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue index 5304a500..0f0ea457 100644 --- a/src/components/mobile_nav/mobile_nav.vue +++ b/src/components/mobile_nav/mobile_nav.vue @@ -9,9 +9,8 @@ @click="scrollToTop()" > <div class="item"> - <a - href="#" - class="mobile-nav-button" + <button + class="button-unstyled mobile-nav-button" @click.stop.prevent="toggleMobileSidebar()" > <FAIcon @@ -22,7 +21,7 @@ v-if="unreadChatCount" class="alert-dot" /> - </a> + </button> <router-link v-if="!hideSitename" class="site-name" @@ -33,10 +32,9 @@ </router-link> </div> <div class="item right"> - <a + <button v-if="currentUser" - class="mobile-nav-button" - href="#" + class="button-unstyled mobile-nav-button" @click.stop.prevent="openMobileNotifications()" > <FAIcon @@ -47,7 +45,7 @@ v-if="unseenNotificationsCount" class="alert-dot" /> - </a> + </button> </div> </nav> <div diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.vue b/src/components/mobile_post_status_button/mobile_post_status_button.vue index 50529878..767f8244 100644 --- a/src/components/mobile_post_status_button/mobile_post_status_button.vue +++ b/src/components/mobile_post_status_button/mobile_post_status_button.vue @@ -1,7 +1,7 @@ <template> <div v-if="isLoggedIn"> <button - class="new-status-button" + class="button-default new-status-button" :class="{ 'hidden': isHidden }" @click="openPostForm" > diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue index 60fa6ceb..5c7b82ec 100644 --- a/src/components/moderation_tools/moderation_tools.vue +++ b/src/components/moderation_tools/moderation_tools.vue @@ -12,13 +12,13 @@ <div class="dropdown-menu"> <span v-if="user.is_local"> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleRight("admin")" > {{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }} </button> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleRight("moderator")" > {{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }} @@ -29,13 +29,13 @@ /> </span> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleActivationStatus()" > {{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }} </button> <button - class="dropdown-item" + class="button-default dropdown-item" @click="deleteUserDialog(true)" > {{ $t('user_card.admin_menu.delete_account') }} @@ -47,7 +47,7 @@ /> <span v-if="hasTagPolicy"> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.FORCE_NSFW)" > {{ $t('user_card.admin_menu.force_nsfw') }} @@ -57,7 +57,7 @@ /> </button> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.STRIP_MEDIA)" > {{ $t('user_card.admin_menu.strip_media') }} @@ -67,7 +67,7 @@ /> </button> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.FORCE_UNLISTED)" > {{ $t('user_card.admin_menu.force_unlisted') }} @@ -77,7 +77,7 @@ /> </button> <button - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.SANDBOX)" > {{ $t('user_card.admin_menu.sandbox') }} @@ -88,7 +88,7 @@ </button> <button v-if="user.is_local" - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)" > {{ $t('user_card.admin_menu.disable_remote_subscription') }} @@ -99,7 +99,7 @@ </button> <button v-if="user.is_local" - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)" > {{ $t('user_card.admin_menu.disable_any_subscription') }} @@ -110,7 +110,7 @@ </button> <button v-if="user.is_local" - class="dropdown-item" + class="button-default dropdown-item" @click="toggleTag(tags.QUARANTINE)" > {{ $t('user_card.admin_menu.quarantine') }} @@ -124,7 +124,7 @@ </div> <button slot="trigger" - class="btn btn-default btn-block" + class="btn button-default btn-block" :class="{ toggled }" > {{ $t('user_card.admin_menu.moderation') }} @@ -141,13 +141,13 @@ <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p> <template slot="footer"> <button - class="btn btn-default" + class="btn button-default" @click="deleteUserDialog(false)" > {{ $t('general.cancel') }} </button> <button - class="btn btn-default danger" + class="btn button-default danger" @click="deleteUser()" > {{ $t('user_card.admin_menu.delete_user') }} diff --git a/src/components/mute_card/mute_card.vue b/src/components/mute_card/mute_card.vue index 9611fb82..ca33c6c5 100644 --- a/src/components/mute_card/mute_card.vue +++ b/src/components/mute_card/mute_card.vue @@ -3,7 +3,7 @@ <div class="mute-card-content-container"> <button v-if="muted" - class="btn btn-default" + class="btn button-default" :disabled="progress" @click="unmuteUser" > @@ -16,7 +16,7 @@ </button> <button v-else - class="btn btn-default" + class="btn button-default" :disabled="progress" @click="muteUser" > diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 2bbde108..f56aa977 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -14,14 +14,15 @@ {{ notification.from_profile.screen_name }} </router-link> </small> - <a - href="#" - class="unmute" + <button + class="button-unstyled unmute" @click.prevent="toggleMute" - ><FAIcon - class="fa-scale-110 fa-old-padding" - icon="eye-slash" - /></a> + > + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="eye-slash" + /> + </button> </div> <div v-else @@ -132,14 +133,16 @@ /> </span> </div> - <a + <button v-if="needMute" - href="#" + class="button-unstyled" @click.prevent="toggleMute" - ><FAIcon - class="fa-scale-110 fa-old-padding" - icon="eye-slash" - /></a> + > + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="eye-slash" + /> + </button> </span> <div v-if="notification.type === 'follow' || notification.type === 'follow_request'" diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 4b479e13..49258563 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -6,6 +6,7 @@ import { filteredNotificationsFromStore, unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils.js' +import FaviconService from '../../services/favicon_service/favicon_service.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' @@ -75,8 +76,10 @@ const Notifications = { watch: { unseenCountTitle (count) { if (count > 0) { + FaviconService.drawFaviconBadge() this.$store.dispatch('setPageTitle', `(${count})`) } else { + FaviconService.clearFaviconBadge() this.$store.dispatch('setPageTitle', '') } } diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue index bd875cca..725d1ad4 100644 --- a/src/components/notifications/notifications.vue +++ b/src/components/notifications/notifications.vue @@ -15,16 +15,9 @@ class="badge badge-notification unseen-count" >{{ unseenCount }}</span> </div> - <div - v-if="error" - class="loadmore-error alert error" - @click.prevent - > - {{ $t('timeline.error_fetching') }} - </div> <button v-if="unseenCount" - class="read-button" + class="button-default read-button" @click.prevent="markAsSeen" > {{ $t('notifications.read') }} @@ -48,15 +41,15 @@ > {{ $t('notifications.no_more_notifications') }} </div> - <a + <button v-else-if="!loading" - href="#" + class="button-unstyled -link -fullwidth" @click.prevent="fetchOlderNotifications()" > <div class="new-status-notification text-center panel-footer"> {{ minimalMode ? $t('interactions.load_older') : $t('notifications.load_older') }} </div> - </a> + </button> <div v-else class="new-status-notification text-center panel-footer" diff --git a/src/components/password_reset/password_reset.vue b/src/components/password_reset/password_reset.vue index 0deb9ccf..a931cb5a 100644 --- a/src/components/password_reset/password_reset.vue +++ b/src/components/password_reset/password_reset.vue @@ -51,7 +51,7 @@ <button :disabled="isPending" type="submit" - class="btn btn-default btn-block" + class="btn button-default btn-block" > {{ $t('general.submit') }} </button> diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue index 5f54b416..42819c19 100644 --- a/src/components/poll/poll.vue +++ b/src/components/poll/poll.vue @@ -42,14 +42,15 @@ :value="index" > <label class="option-vote"> - <div>{{ option.title }}</div> + <!-- eslint-disable-next-line vue/no-v-html --> + <div v-html="option.title_html" /> </label> </div> </div> <div class="footer faint"> <button v-if="!showResults" - class="btn btn-default poll-vote-button" + class="btn button-default poll-vote-button" type="button" :disabled="isDisabled" @click="vote" diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 695f73b9..5e417fa0 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -21,7 +21,10 @@ const Popover = { // 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 + 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 }, data () { return { @@ -96,9 +99,15 @@ const Popover = { if (origin.y + content.offsetHeight > yBounds.max) usingTop = true if (origin.y - content.offsetHeight < yBounds.min) usingTop = false + let vPadding = 0 + if (this.removePadding && usingTop) { + const anchorStyle = getComputedStyle(anchorEl) + vPadding = parseFloat(anchorStyle.paddingTop) + parseFloat(anchorStyle.paddingBottom) + } + const yOffset = (this.offset && this.offset.y) || 0 const translateY = usingTop - ? -anchorEl.offsetHeight - yOffset - content.offsetHeight + ? -anchorEl.offsetHeight + vPadding - yOffset - content.offsetHeight : yOffset const xOffset = (this.offset && this.offset.x) || 0 diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue index 9b8680e5..2252c68f 100644 --- a/src/components/popover/popover.vue +++ b/src/components/popover/popover.vue @@ -3,12 +3,13 @@ @mouseenter="onMouseenter" @mouseleave="onMouseleave" > - <div + <button ref="trigger" + class="button-unstyled -fullwidth popover-trigger-button" @click="onClick" > <slot name="trigger" /> - </div> + </button> <div v-if="!hidden" ref="content" @@ -30,6 +31,10 @@ <style lang="scss"> @import '../../_variables.scss'; +.popover-trigger-button { + display: block; +} + .popover { z-index: 8; position: absolute; @@ -90,6 +95,7 @@ box-shadow: none; width: 100%; height: 100%; + box-sizing: border-box; --btnText: var(--popoverText, $fallback--text); diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index de583269..4148381c 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -159,8 +159,7 @@ const PostStatusForm = { ...this.$store.state.instance.emoji, ...this.$store.state.instance.customEmoji ], - users: this.$store.state.users.users, - updateUsersList: (query) => this.$store.dispatch('searchUsers', { query }) + store: this.$store }) }, emojiSuggestor () { @@ -531,7 +530,7 @@ const PostStatusForm = { !(isFormBiggerThanScroller && this.$refs.textarea.selectionStart !== this.$refs.textarea.value.length) const totalDelta = shouldScrollToBottom ? bottomChangeDelta : 0 - const targetScroll = currentScroll + totalDelta + const targetScroll = Math.round(currentScroll + totalDelta) if (scrollerRef === window) { scrollerRef.scroll(0, targetScroll) diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 42d3152b..ed830f57 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -24,12 +24,12 @@ tag="p" class="visibility-notice" > - <a - href="#" + <button + class="button-unstyled -link" @click="openProfileTab" > {{ $t('post_status.account_not_locked_warning_link') }} - </a> + </button> </i18n> <p v-if="!hideScopeNotice && newStatus.visibility === 'public'" @@ -243,38 +243,34 @@ @upload-failed="uploadFailed" @all-uploaded="finishedUploadingFiles" /> - <div - class="emoji-icon" + <button + class="emoji-icon button-unstyled" + :title="$t('emoji.add_emoji')" + @click="showEmojiPicker" > - <div - :title="$t('emoji.add_emoji')" - class="btn btn-default" - @click="showEmojiPicker" - > - <FAIcon icon="smile-beam" /> - </div> - </div> - <div + <FAIcon icon="smile-beam" /> + </button> + <button v-if="pollsAvailable" - class="poll-icon" + class="poll-icon button-unstyled" :class="{ selected: pollFormVisible }" :title="$t('polls.add_poll')" @click="togglePollForm" > <FAIcon icon="poll-h" /> - </div> + </button> </div> <button v-if="posting" disabled - class="btn btn-default" + class="btn button-default" > {{ $t('post_status.posting') }} </button> <button v-else-if="isOverLengthLimit" disabled - class="btn btn-default" + class="btn button-default" > {{ $t('general.submit') }} </button> @@ -282,7 +278,7 @@ <button v-else :disabled="uploadingFiles || disableSubmit" - class="btn btn-default" + class="btn button-default" @touchstart.stop.prevent="postStatus($event, newStatus)" @click.stop.prevent="postStatus($event, newStatus)" > diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js index de0df70c..5e7b7580 100644 --- a/src/components/react_button/react_button.js +++ b/src/components/react_button/react_button.js @@ -27,13 +27,21 @@ const ReactButton = { }, computed: { commonEmojis () { - return ['👍', '😠', '👀', '😂', '🔥'] + return [ + { displayText: 'thumbsup', replacement: '👍' }, + { displayText: 'angry', replacement: '😠' }, + { displayText: 'eyes', replacement: '👀' }, + { displayText: 'joy', replacement: '😂' }, + { displayText: 'fire', replacement: '🔥' } + ] }, emojis () { if (this.filterWord !== '') { const filterWordLowercase = this.filterWord.toLowerCase() let orderedEmojiList = [] for (const emoji of this.$store.state.instance.emoji) { + if (emoji.replacement === this.filterWord) return [emoji] + const indexOfFilterWord = emoji.displayText.toLowerCase().indexOf(filterWordLowercase) if (indexOfFilterWord > -1) { if (!Array.isArray(orderedEmojiList[indexOfFilterWord])) { diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue index e508a3e9..ac940b98 100644 --- a/src/components/react_button/react_button.vue +++ b/src/components/react_button/react_button.vue @@ -3,8 +3,8 @@ trigger="click" placement="top" :offset="{ y: 5 }" - class="react-button-popover" :bound-to="{ x: 'container' }" + remove-padding > <div slot="content" @@ -20,17 +20,19 @@ <div class="reaction-picker"> <span v-for="emoji in commonEmojis" - :key="emoji" + :key="emoji.replacement" class="emoji-button" - @click="addReaction($event, emoji, close)" + :title="emoji.displayText" + @click="addReaction($event, emoji.replacement, close)" > - {{ emoji }} + {{ emoji.replacement }} </span> <div class="reaction-picker-divider" /> <span v-for="(emoji, key) in emojis" :key="key" class="emoji-button" + :title="emoji.displayText" @click="addReaction($event, emoji.replacement, close)" > {{ emoji.replacement }} @@ -38,11 +40,14 @@ <div class="reaction-bottom-fader" /> </div> </div> - <span slot="trigger"> + <span + slot="trigger" + class="ReactButton" + :title="$t('tool_tip.add_reaction')" + > <FAIcon - class="fa-scale-110 fa-old-padding add-reaction-button" + class="fa-scale-110 fa-old-padding" :icon="['far', 'smile-beam']" - :title="$t('tool_tip.add_reaction')" /> </span> </Popover> @@ -102,10 +107,11 @@ } } -.add-reaction-button { - cursor: pointer; +.ReactButton { + padding: 10px; + margin: -10px; - &:hover { + &:hover .svg-inline--fa { color: $fallback--text; color: var(--text, $fallback--text); } diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index a83ca1e5..100df0d6 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -211,7 +211,7 @@ <button :disabled="isPending" type="submit" - class="btn btn-default" + class="btn button-default" > {{ $t('general.submit') }} </button> diff --git a/src/components/remote_follow/remote_follow.vue b/src/components/remote_follow/remote_follow.vue index cb1c2a1b..be827400 100644 --- a/src/components/remote_follow/remote_follow.vue +++ b/src/components/remote_follow/remote_follow.vue @@ -16,7 +16,7 @@ > <button click="submit" - class="remote-button" + class="button-default remote-button" > {{ $t('user_card.remote_follow') }} </button> diff --git a/src/components/reply_button/reply_button.vue b/src/components/reply_button/reply_button.vue index a0ac8941..c17041da 100644 --- a/src/components/reply_button/reply_button.vue +++ b/src/components/reply_button/reply_button.vue @@ -1,20 +1,28 @@ <template> - <div> - <FAIcon + <div class="ReplyButton"> + <button v-if="loggedIn" - class="ReplyButton fa-scale-110 fa-old-padding -interactive" - icon="reply" - :title="$t('tool_tip.reply')" + class="button-unstyled interactive" :class="{'-active': replying}" - @click.prevent="$emit('toggle')" - /> - <FAIcon - v-else - icon="reply" - class="ReplyButton fa-scale-110 fa-old-padding" :title="$t('tool_tip.reply')" - /> - <span v-if="status.replies_count > 0"> + @click.prevent="$emit('toggle')" + > + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="reply" + /> + </button> + <span v-else> + <FAIcon + icon="reply" + class="fa-scale-110 fa-old-padding" + :title="$t('tool_tip.reply')" + /> + </span> + <span + v-if="status.replies_count > 0" + class="action-counter" + > {{ status.replies_count }} </span> </div> @@ -26,14 +34,25 @@ @import '../../_variables.scss'; .ReplyButton { - &.-interactive { - cursor: pointer; + display: flex; - &:hover, - &.-active { + > :first-child { + padding: 10px; + margin: -10px -8px -10px -10px; + } + + .action-counter { + pointer-events: none; + user-select: none; + } + + .interactive { + &:hover .svg-inline--fa, + &.-active .svg-inline--fa { color: $fallback--cBlue; color: var(--cBlue, $fallback--cBlue); } } + } </style> diff --git a/src/components/retweet_button/retweet_button.js b/src/components/retweet_button/retweet_button.js index 5ee4179a..2103fd0b 100644 --- a/src/components/retweet_button/retweet_button.js +++ b/src/components/retweet_button/retweet_button.js @@ -24,11 +24,6 @@ const RetweetButton = { } }, computed: { - classes () { - return { - '-repeated': this.status.repeated - } - }, mergedConfig () { return this.$store.getters.mergedConfig } diff --git a/src/components/retweet_button/retweet_button.vue b/src/components/retweet_button/retweet_button.vue index b234f3d9..859ce499 100644 --- a/src/components/retweet_button/retweet_button.vue +++ b/src/components/retweet_button/retweet_button.vue @@ -1,33 +1,38 @@ <template> - <div v-if="loggedIn"> - <template v-if="visibility !== 'private' && visibility !== 'direct'"> + <div class="RetweetButton"> + <button + v-if="visibility !== 'private' && visibility !== 'direct' && loggedIn" + class="button-unstyled interactive" + :class="status.repeated && '-repeated'" + :title="$t('tool_tip.repeat')" + @click.prevent="retweet()" + > <FAIcon - :class="classes" - class="RetweetButton fa-scale-110 fa-old-padding -interactive" + class="fa-scale-110 fa-old-padding" icon="retweet" :spin="animated" - :title="$t('tool_tip.repeat')" - @click.prevent="retweet()" /> - <span v-if="!mergedConfig.hidePostStats && status.repeat_num > 0">{{ status.repeat_num }}</span> - </template> - <template v-else> + </button> + <span v-else-if="loggedIn"> <FAIcon - :class="classes" - class="RetweetButton fa-scale-110 fa-old-padding" + class="fa-scale-110 fa-old-padding" icon="lock" :title="$t('timeline.no_retweet_hint')" /> - </template> - </div> - <div v-else-if="!loggedIn"> - <FAIcon - :class="classes" - class="fa-scale-110 fa-old-padding" - icon="retweet" - :title="$t('tool_tip.repeat')" - /> - <span v-if="!mergedConfig.hidePostStats && status.repeat_num > 0">{{ status.repeat_num }}</span> + </span> + <span v-else> + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="retweet" + :title="$t('tool_tip.repeat')" + /> + </span> + <span + v-if="!mergedConfig.hidePostStats && status.repeat_num > 0" + class="no-event" + > + {{ status.repeat_num }} + </span> </div> </template> @@ -37,19 +42,28 @@ @import '../../_variables.scss'; .RetweetButton { - &.-interactive { - cursor: pointer; - animation-duration: 0.6s; + display: flex; - &:hover { + > :first-child { + padding: 10px; + margin: -10px -8px -10px -10px; + } + + .action-counter { + pointer-events: none; + user-select: none; + } + + .interactive { + .svg-inline--fa { + animation-duration: 0.6s; + } + + &:hover .svg-inline--fa, + &.-repeated .svg-inline--fa { color: $fallback--cGreen; color: var(--cGreen, $fallback--cGreen); } } - - &.-repeated { - color: $fallback--cGreen; - color: var(--cGreen, $fallback--cGreen); - } } </style> diff --git a/src/components/scope_selector/scope_selector.vue b/src/components/scope_selector/scope_selector.vue index a22a4fda..66ac612e 100644 --- a/src/components/scope_selector/scope_selector.vue +++ b/src/components/scope_selector/scope_selector.vue @@ -3,9 +3,9 @@ v-if="!showNothing" class="ScopeSelector" > - <span + <button v-if="showDirect" - class="scope" + class="button-unstyled scope" :class="css.direct" :title="$t('post_status.scope.direct')" @click="changeVis('direct')" @@ -14,10 +14,10 @@ icon="envelope" class="fa-scale-110 fa-old-padding" /> - </span> - <span + </button> + <button v-if="showPrivate" - class="scope" + class="button-unstyled scope" :class="css.private" :title="$t('post_status.scope.private')" @click="changeVis('private')" @@ -26,10 +26,10 @@ icon="lock" class="fa-scale-110 fa-old-padding" /> - </span> - <span + </button> + <button v-if="showUnlisted" - class="scope" + class="button-unstyled scope" :class="css.unlisted" :title="$t('post_status.scope.unlisted')" @click="changeVis('unlisted')" @@ -38,10 +38,10 @@ icon="lock-open" class="fa-scale-110 fa-old-padding" /> - </span> - <span + </button> + <button v-if="showPublic" - class="scope" + class="button-unstyled scope" :class="css.public" :title="$t('post_status.scope.public')" @click="changeVis('public')" @@ -50,7 +50,7 @@ icon="globe" class="fa-scale-110 fa-old-padding" /> - </span> + </button> </div> </template> diff --git a/src/components/search/search.vue b/src/components/search/search.vue index 665390f9..a6503c9f 100644 --- a/src/components/search/search.vue +++ b/src/components/search/search.vue @@ -14,7 +14,7 @@ @keyup.enter="newQuery(searchTerm)" > <button - class="btn search-button" + class="btn button-default search-button" @click="newQuery(searchTerm)" > <FAIcon icon="search" /> diff --git a/src/components/search_bar/search_bar.vue b/src/components/search_bar/search_bar.vue index 89a601c8..6cf9179e 100644 --- a/src/components/search_bar/search_bar.vue +++ b/src/components/search_bar/search_bar.vue @@ -3,17 +3,18 @@ class="SearchBar" :class="{ '-expanded': !hidden }" > - <a + <button v-if="hidden" - href="#" - class="nav-icon" + class="button-unstyled nav-icon" :title="$t('nav.search')" - ><FAIcon - fixed-width - class="fa-scale-110 fa-old-padding" - icon="search" @click.prevent.stop="toggleHidden" - /></a> + > + <FAIcon + fixed-width + class="fa-scale-110 fa-old-padding" + icon="search" + /> + </button> <template v-else> <input id="search-bar-input" @@ -25,7 +26,7 @@ @keyup.enter="find(searchTerm)" > <button - class="btn search-button" + class="button-default search-button" @click="find(searchTerm)" > <FAIcon @@ -33,14 +34,16 @@ icon="search" /> </button> - <span> + <button + class="button-unstyled cancel-search" + @click.prevent.stop="toggleHidden" + > <FAIcon fixed-width icon="times" class="cancel-icon fa-scale-110 fa-old-padding" - @click.prevent.stop="toggleHidden" /> - </span> + </button> </template> </div> </template> @@ -69,8 +72,11 @@ flex: 1 0 auto; } + .cancel-search { + height: 50px; + } + .cancel-icon { - cursor: pointer; color: $fallback--text; color: var(--btnTopBarText, $fallback--text); } diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue index 6bc64ed0..552ca41f 100644 --- a/src/components/settings_modal/settings_modal.vue +++ b/src/components/settings_modal/settings_modal.vue @@ -30,13 +30,13 @@ </template> </transition> <button - class="btn" + class="btn button-default" @click="peekModal" > {{ $t('general.peek') }} </button> <button - class="btn" + class="btn button-default" @click="closeModal" > {{ $t('general.close') }} diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index 813dc4cd..8f850c8b 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -75,6 +75,7 @@ <p>{{ $t('settings.filtering_explanation') }}</p> <textarea id="muteWords" + class="resize-height" v-model="muteWordsString" /> </div> diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index df592a10..029ee7a1 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -34,6 +34,10 @@ const GeneralTab = { return this.$store.state.instance.postFormats || [] }, instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel }, + instanceWallpaperUsed () { + return this.$store.state.instance.background && + !this.$store.state.users.currentUser.background_image + }, ...SharedComputedObject() } } diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index c1d0d0ec..a9081793 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -11,6 +11,11 @@ {{ $t('settings.hide_isp') }} </Checkbox> </li> + <li v-if="instanceWallpaperUsed"> + <Checkbox v-model="hideInstanceWallpaper"> + {{ $t('settings.hide_wallpaper') }} + </Checkbox> + </li> </ul> </div> <div class="setting-item"> diff --git a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue index 5a1cf2c0..63d36bf9 100644 --- a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue +++ b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue @@ -27,7 +27,7 @@ <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" - class="btn btn-default bulk-action-button" + class="btn button-default bulk-action-button" :click="() => blockUsers(selected)" > {{ $t('user_card.block') }} @@ -37,7 +37,7 @@ </ProgressButton> <ProgressButton v-if="selected.length > 0" - class="btn btn-default" + class="btn button-default" :click="() => unblockUsers(selected)" > {{ $t('user_card.unblock') }} @@ -85,7 +85,7 @@ <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" - class="btn btn-default" + class="btn button-default" :click="() => muteUsers(selected)" > {{ $t('user_card.mute') }} @@ -95,7 +95,7 @@ </ProgressButton> <ProgressButton v-if="selected.length > 0" - class="btn btn-default" + class="btn button-default" :click="() => unmuteUsers(selected)" > {{ $t('user_card.unmute') }} @@ -141,7 +141,7 @@ <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" - class="btn btn-default" + class="btn button-default" :click="() => unmuteDomains(selected)" > {{ $t('domain_mute_card.unmute') }} diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue index 86eed3f5..8f8fe48e 100644 --- a/src/components/settings_modal/tabs/notifications_tab.vue +++ b/src/components/settings_modal/tabs/notifications_tab.vue @@ -21,7 +21,7 @@ <p>{{ $t('settings.notification_mutes') }}</p> <p>{{ $t('settings.notification_blocks') }}</p> <button - class="btn btn-default" + class="btn button-default" @click="updateNotificationSettings" > {{ $t('general.submit') }} diff --git a/src/components/settings_modal/tabs/profile_tab.js b/src/components/settings_modal/tabs/profile_tab.js index a3e4feaf..9709424c 100644 --- a/src/components/settings_modal/tabs/profile_tab.js +++ b/src/components/settings_modal/tabs/profile_tab.js @@ -45,9 +45,7 @@ const ProfileTab = { banner: null, bannerPreview: null, background: null, - backgroundPreview: null, - bannerUploadError: null, - backgroundUploadError: null + backgroundPreview: null } }, components: { @@ -68,8 +66,7 @@ const ProfileTab = { ...this.$store.state.instance.emoji, ...this.$store.state.instance.customEmoji ], - users: this.$store.state.users.users, - updateUsersList: (query) => this.$store.dispatch('searchUsers', { query }) + store: this.$store }) }, emojiSuggestor () { @@ -79,10 +76,7 @@ const ProfileTab = { ] }) }, userSuggestor () { - return suggestor({ - users: this.$store.state.users.users, - updateUsersList: (query) => this.$store.dispatch('searchUsers', { query }) - }) + return suggestor({ store: this.$store }) }, fieldsLimits () { return this.$store.state.instance.fieldsLimits @@ -166,18 +160,18 @@ const ProfileTab = { if (file.size > this.$store.state.instance[slot + 'limit']) { const filesize = fileSizeFormatService.fileSizeFormat(file.size) const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit']) - this[slot + 'UploadError'] = [ - this.$t('upload.error.base'), - this.$t( - 'upload.error.file_too_big', - { + this.$store.dispatch('pushGlobalNotice', { + messageKey: 'upload.error.message', + messageArgs: [ + this.$t('upload.error.file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit - } - ) - ].join(' ') + }) + ], + level: 'error' + }) return } // eslint-disable-next-line no-undef @@ -217,8 +211,9 @@ const ProfileTab = { that.$store.commit('setCurrentUser', user) resolve() }) - .catch((err) => { - reject(new Error(that.$t('upload.error.base') + ' ' + err.message)) + .catch((error) => { + that.displayUploadError(error) + reject(error) }) } @@ -239,24 +234,27 @@ const ProfileTab = { this.$store.commit('setCurrentUser', user) this.bannerPreview = null }) - .catch((err) => { - this.bannerUploadError = this.$t('upload.error.base') + ' ' + err.message - }) - .then(() => { this.bannerUploading = false }) + .catch(this.displayUploadError) + .finally(() => { this.bannerUploading = false }) }, submitBackground (background) { if (!this.backgroundPreview && background !== '') { return } this.backgroundUploading = true - this.$store.state.api.backendInteractor.updateProfileImages({ background }).then((data) => { - if (!data.error) { + this.$store.state.api.backendInteractor.updateProfileImages({ background }) + .then((data) => { this.$store.commit('addNewUsers', [data]) this.$store.commit('setCurrentUser', data) this.backgroundPreview = null - } else { - this.backgroundUploadError = this.$t('upload.error.base') + data.error - } - this.backgroundUploading = false + }) + .catch(this.displayUploadError) + .finally(() => { this.backgroundUploading = false }) + }, + displayUploadError (error) { + this.$store.dispatch('pushGlobalNotice', { + messageKey: 'upload.error.message', + messageArgs: [error.message], + level: 'error' }) } } diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue index d62bc392..b7ef21d7 100644 --- a/src/components/settings_modal/tabs/profile_tab.vue +++ b/src/components/settings_modal/tabs/profile_tab.vue @@ -11,7 +11,7 @@ <input id="username" v-model="newName" - classname="name-changer" + class="name-changer" > </EmojiInput> <p>{{ $t('settings.bio') }}</p> @@ -22,7 +22,7 @@ > <textarea v-model="newBio" - classname="bio" + class="bio resize-height" /> </EmojiInput> <p> @@ -150,7 +150,7 @@ </p> <button :disabled="newName && newName.length === 0" - class="btn btn-default" + class="btn button-default" @click="updateProfile" > {{ $t('general.submit') }} @@ -179,7 +179,7 @@ <button v-show="pickAvatarBtnVisible" id="pick-avatar" - class="btn" + class="button-default btn" type="button" > {{ $t('settings.upload_a_photo') }} @@ -224,22 +224,11 @@ /> <button v-else-if="bannerPreview" - class="btn btn-default" + class="btn button-default" @click="submitBanner(banner)" > {{ $t('general.submit') }} </button> - <div - v-if="bannerUploadError" - class="alert error" - > - Error: {{ bannerUploadError }} - <FAIcon - class="fa-scale-110 fa-old-padding" - icon="times" - @click="clearUploadError('banner')" - /> - </div> </div> <div class="setting-item"> <h2>{{ $t('settings.profile_background') }}</h2> @@ -274,23 +263,11 @@ /> <button v-else-if="backgroundPreview" - class="btn btn-default" + class="btn button-default" @click="submitBackground(background)" > {{ $t('general.submit') }} </button> - <div - v-if="backgroundUploadError" - class="alert error" - > - Error: {{ backgroundUploadError }} - <FAIcon - size="lg" - class="fa-scale-110 fa-old-padding" - icon="times" - @click="clearUploadError('background')" - /> - </div> </div> </div> </template> diff --git a/src/components/settings_modal/tabs/security_tab/confirm.vue b/src/components/settings_modal/tabs/security_tab/confirm.vue index 69b3811b..38c2a610 100644 --- a/src/components/settings_modal/tabs/security_tab/confirm.vue +++ b/src/components/settings_modal/tabs/security_tab/confirm.vue @@ -2,14 +2,14 @@ <div> <slot /> <button - class="btn btn-default" + class="btn button-default" :disabled="disabled" @click="confirm" > {{ $t('general.confirm') }} </button> <button - class="btn btn-default" + class="btn button-default" :disabled="disabled" @click="cancel" > diff --git a/src/components/settings_modal/tabs/security_tab/mfa.vue b/src/components/settings_modal/tabs/security_tab/mfa.vue index 7aca3c8d..455d17b6 100644 --- a/src/components/settings_modal/tabs/security_tab/mfa.vue +++ b/src/components/settings_modal/tabs/security_tab/mfa.vue @@ -29,7 +29,7 @@ /> <button v-if="!confirmNewBackupCodes" - class="btn btn-default" + class="btn button-default" @click="getBackupCodes" > {{ $t('settings.mfa.generate_new_recovery_codes') }} @@ -61,7 +61,7 @@ <button v-if="canSetupOTP" - class="btn btn-default" + class="btn button-default" @click="cancelSetup" > {{ $t('general.cancel') }} @@ -69,7 +69,7 @@ <button v-if="canSetupOTP" - class="btn btn-default" + class="btn button-default" @click="setupOTP" > {{ $t('settings.mfa.setup_otp') }} @@ -108,13 +108,13 @@ > <div class="confirm-otp-actions"> <button - class="btn btn-default" + class="btn button-default" @click="doConfirmOTP" > {{ $t('settings.mfa.confirm_and_enable') }} </button> <button - class="btn btn-default" + class="btn button-default" @click="cancelSetup" > {{ $t('general.cancel') }} diff --git a/src/components/settings_modal/tabs/security_tab/mfa_totp.vue b/src/components/settings_modal/tabs/security_tab/mfa_totp.vue index c6f2cc7b..8e767bd0 100644 --- a/src/components/settings_modal/tabs/security_tab/mfa_totp.vue +++ b/src/components/settings_modal/tabs/security_tab/mfa_totp.vue @@ -4,7 +4,7 @@ <strong>{{ $t('settings.mfa.otp') }}</strong> <button v-if="!isActivated" - class="btn btn-default" + class="btn button-default" @click="doActivate" > {{ $t('general.enable') }} @@ -12,7 +12,7 @@ <button v-if="isActivated" - class="btn btn-default" + class="btn button-default" :disabled="deactivate" @click="doDeactivate" > diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.vue b/src/components/settings_modal/tabs/security_tab/security_tab.vue index 3d32d73d..56bea1f4 100644 --- a/src/components/settings_modal/tabs/security_tab/security_tab.vue +++ b/src/components/settings_modal/tabs/security_tab/security_tab.vue @@ -19,7 +19,7 @@ > </div> <button - class="btn btn-default" + class="btn button-default" @click="changeEmail" > {{ $t('general.submit') }} @@ -57,7 +57,7 @@ > </div> <button - class="btn btn-default" + class="btn button-default" @click="changePassword" > {{ $t('general.submit') }} @@ -92,7 +92,7 @@ <td>{{ oauthToken.validUntil }}</td> <td class="actions"> <button - class="btn btn-default" + class="btn button-default" @click="revokeToken(oauthToken.id)" > {{ $t('settings.revoke_token') }} @@ -116,7 +116,7 @@ type="password" > <button - class="btn btn-default" + class="btn button-default" @click="deleteAccount" > {{ $t('settings.delete_account') }} @@ -130,7 +130,7 @@ </p> <button v-if="!deletingAccount" - class="btn btn-default" + class="btn button-default" @click="confirmDelete" > {{ $t('general.submit') }} diff --git a/src/components/settings_modal/tabs/theme_tab/preview.vue b/src/components/settings_modal/tabs/theme_tab/preview.vue index 02fea0b6..7ac7b9d3 100644 --- a/src/components/settings_modal/tabs/theme_tab/preview.vue +++ b/src/components/settings_modal/tabs/theme_tab/preview.vue @@ -15,7 +15,7 @@ <span class="alert error"> {{ $t('settings.style.preview.error') }} </span> - <button class="btn"> + <button class="btn button-default"> {{ $t('settings.style.preview.button') }} </button> </div> @@ -102,7 +102,7 @@ > <label for="preview_checkbox">{{ $t('settings.style.preview.checkbox') }}</label> </span> - <button class="btn"> + <button class="btn button-default"> {{ $t('settings.style.preview.button') }} </button> </div> diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.scss b/src/components/settings_modal/tabs/theme_tab/theme_tab.scss index 926eceff..1b7d9f31 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.scss +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.scss @@ -165,7 +165,8 @@ border-color: var(--border, $fallback--border); margin: 1em 0; padding: 1em; - background: var(--body-background-image); + background-color: var(--wallpaper); + background-image: var(--body-background-image); background-size: cover; background-position: 50% 50%; diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue index 280e1955..b8add42f 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue @@ -12,13 +12,13 @@ <div class="buttons"> <template v-if="themeWarning.type === 'snapshot_source_mismatch'"> <button - class="btn" + class="btn button-default" @click="forceLoad" > {{ $t('settings.style.switcher.use_source') }} </button> <button - class="btn" + class="btn button-default" @click="forceSnapshot" > {{ $t('settings.style.switcher.use_snapshot') }} @@ -26,7 +26,7 @@ </template> <template v-else-if="themeWarning.noActionsPossible"> <button - class="btn" + class="btn button-default" @click="dismissWarning" > {{ $t('general.dismiss') }} @@ -34,13 +34,13 @@ </template> <template v-else> <button - class="btn" + class="btn button-default" @click="forceLoad" > {{ $t('settings.style.switcher.load_theme') }} </button> <button - class="btn" + class="btn button-default" @click="dismissWarning" > {{ $t('settings.style.switcher.keep_as_is') }} @@ -131,13 +131,13 @@ <p>{{ $t('settings.theme_help') }}</p> <div class="tab-header-buttons"> <button - class="btn" + class="btn button-default" @click="clearOpacity" > {{ $t('settings.style.switcher.clear_opacity') }} </button> <button - class="btn" + class="btn button-default" @click="clearV1" > {{ $t('settings.style.switcher.clear_all') }} @@ -238,13 +238,13 @@ <div class="tab-header"> <p>{{ $t('settings.theme_help') }}</p> <button - class="btn" + class="btn button-default" @click="clearOpacity" > {{ $t('settings.style.switcher.clear_opacity') }} </button> <button - class="btn" + class="btn button-default" @click="clearV1" > {{ $t('settings.style.switcher.clear_all') }} @@ -617,6 +617,15 @@ /> </div> <div class="color-item"> + <h4>{{ $t('settings.style.advanced_colors.wallpaper') }}</h4> + <ColorInput + v-model="wallpaperColorLocal" + name="wallpaper" + :label="$t('settings.style.advanced_colors.wallpaper')" + :fallback="previewTheme.colors.wallpaper" + /> + </div> + <div class="color-item"> <h4>{{ $t('settings.style.advanced_colors.poll') }}</h4> <ColorInput v-model="pollColorLocal" @@ -806,7 +815,7 @@ <div class="tab-header"> <p>{{ $t('settings.radii_help') }}</p> <button - class="btn" + class="btn button-default" @click="clearRoundness" > {{ $t('settings.style.switcher.clear_all') }} @@ -936,7 +945,7 @@ /> </div> <button - class="btn" + class="btn button-default" @click="clearShadows" > {{ $t('settings.style.switcher.clear_all') }} @@ -980,7 +989,7 @@ <div class="tab-header"> <p>{{ $t('settings.style.fonts.help') }}</p> <button - class="btn" + class="btn button-default" @click="clearFonts" > {{ $t('settings.style.switcher.clear_all') }} @@ -1017,14 +1026,14 @@ <div class="apply-container"> <button - class="btn submit" + class="btn button-default submit" :disabled="!themeValid" @click="setCustomTheme" > {{ $t('general.apply') }} </button> <button - class="btn" + class="btn button-default" @click="clearAll" > {{ $t('settings.style.switcher.reset') }} diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue index 78f0e544..37d491f0 100644 --- a/src/components/shadow_control/shadow_control.vue +++ b/src/components/shadow_control/shadow_control.vue @@ -84,7 +84,7 @@ /> </label> <button - class="btn btn-default" + class="btn button-default" :disabled="!ready || !present" @click="del" > @@ -94,7 +94,7 @@ /> </button> <button - class="btn btn-default" + class="btn button-default" :disabled="!moveUpValid" @click="moveUp" > @@ -104,7 +104,7 @@ /> </button> <button - class="btn btn-default" + class="btn button-default" :disabled="!moveDnValid" @click="moveDn" > @@ -114,7 +114,7 @@ /> </button> <button - class="btn btn-default" + class="btn button-default" :disabled="usingFallback" @click="add" > diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index 28c888fe..695ae03b 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -144,8 +144,8 @@ </router-link> </li> <li @click="toggleDrawer"> - <a - href="#" + <button + class="button-unstyled -link -fullwidth" @click="openSettingsModal" > <FAIcon @@ -153,7 +153,7 @@ class="fa-scale-110 fa-old-padding" icon="cog" /> {{ $t("settings.settings") }} - </a> + </button> </li> <li @click="toggleDrawer"> <router-link :to="{ name: 'about'}"> @@ -183,8 +183,8 @@ v-if="currentUser" @click="toggleDrawer" > - <a - href="#" + <button + class="button-unstyled -link -fullwidth" @click="doLogout" > <FAIcon @@ -192,7 +192,7 @@ class="fa-scale-110 fa-old-padding" icon="sign-out-alt" /> {{ $t("login.logout") }} - </a> + </button> </li> </ul> </div> @@ -331,7 +331,7 @@ .side-drawer li { padding: 0; - a { + a, button { box-sizing: border-box; display: block; height: 3em; diff --git a/src/components/status/status.js b/src/components/status/status.js index 142e1fc6..f9c710ab 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -26,7 +26,6 @@ import { faTimes, faRetweet, faReply, - faExternalLinkSquareAlt, faPlusSquare, faSmileBeam, faEllipsisH, @@ -44,7 +43,6 @@ library.add( faTimes, faRetweet, faReply, - faExternalLinkSquareAlt, faPlusSquare, faStar, faSmileBeam, diff --git a/src/components/status/status.scss b/src/components/status/status.scss index 0a94de32..58b55bc8 100644 --- a/src/components/status/status.scss +++ b/src/components/status/status.scss @@ -29,6 +29,8 @@ $status-margin: 0.75em; &.-conversation { border-left-width: 4px; border-left-style: solid; + border-left-color: $fallback--cRed; + border-left-color: var(--cRed, $fallback--cRed); } .gravestone { @@ -137,6 +139,20 @@ $status-margin: 0.75em; .heading-right { display: flex; flex-shrink: 0; + + .button-unstyled { + padding: 5px; + margin: -5px; + + &:hover svg { + color: $fallback--lightText; + color: var(--lightText, $fallback--lightText); + } + } + + .svg-inline--fa { + margin-left: 0.25em; + } } .timeago { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 21412faa..6ee8117f 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -47,16 +47,15 @@ > {{ muteWordHits.join(', ') }} </small> - <a - href="#" - class="unmute fa-scale-110 fa-old-padding" + <button + class="unmute button-unstyled" @click.prevent="toggleMute" > <FAIcon icon="eye-slash" class="fa-scale-110 fa-old-padding" /> - </a> + </button> </div> </template> <template v-else> @@ -185,43 +184,34 @@ :title="status.visibility | capitalize" > <FAIcon - class="fa-scale-110 fa-old-padding" + fixed-width + class="fa-scale-110" :icon="visibilityIcon(status.visibility)" /> </span> - <a - v-if="!status.is_local && !isPreview" - :href="status.external_url" - target="_blank" - class="source_url" - title="Source" - > - <FAIcon - class="fa-scale-110 fa-old-padding" - icon="external-link-square-alt" - /> - </a> - <a + <button v-if="expandable && !isPreview" - href="#" - title="Expand" + class="button-unstyled" + :title="$t('status.expand')" @click.prevent="toggleExpanded" > <FAIcon - class="fa-scale-110 fa-old-padding" + fixed-width + class="fa-scale-110" icon="plus-square" /> - </a> - <a + </button> + <button v-if="unmuted" - href="#" + class="button-unstyled" @click.prevent="toggleMute" > <FAIcon + fixed-width icon="eye-slash" - class="fa-scale-110 fa-old-padding" + class="fa-scale-110" /> - </a> + </button> </span> </div> @@ -237,9 +227,8 @@ style="min-width: 0" :class="{ '-strikethrough': !status.parent_visible }" > - <a - class="reply-to" - href="#" + <button + class="button-unstyled reply-to" :aria-label="$t('tool_tip.reply')" @click.prevent="gotoOriginal(status.in_reply_to_status_id)" > @@ -253,7 +242,7 @@ > {{ $t('status.reply_to') }} </span> - </a> + </button> </StatusPopover> <span @@ -286,11 +275,12 @@ :key="reply.id" :status-id="reply.id" > - <a - href="#" - class="reply-link" + <button + class="button-unstyled -link reply-link" @click.prevent="gotoOriginal(reply.id)" - >{{ reply.name }}</a> + > + {{ reply.name }} + </button> </StatusPopover> </div> </div> diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue index 321cd477..90bfaf40 100644 --- a/src/components/status_content/status_content.vue +++ b/src/components/status_content/status_content.vue @@ -12,35 +12,34 @@ @click.prevent="linkClicked" v-html="status.summary_html" /> - <a + <button v-if="longSubject && showingLongSubject" - href="#" - class="tall-subject-hider" + class="button-unstyled -link tall-subject-hider" @click.prevent="showingLongSubject=false" - >{{ $t("status.hide_full_subject") }}</a> - <a + > + {{ $t("status.hide_full_subject") }} + </button> + <button v-else-if="longSubject" - class="tall-subject-hider" + class="button-unstyled -link tall-subject-hider" :class="{ 'tall-subject-hider_focused': focused }" - href="#" @click.prevent="showingLongSubject=true" > {{ $t("status.show_full_subject") }} - </a> + </button> </div> <div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" > - <a + <button v-if="hideTallStatus" - class="tall-status-hider" + class="button-unstyled -link tall-status-hider" :class="{ 'tall-status-hider_focused': focused }" - href="#" @click.prevent="toggleShowMore" > {{ $t("general.show_more") }} - </a> + </button> <div v-if="!hideSubjectStatus" :class="{ 'single-line': singleLine }" @@ -48,10 +47,9 @@ @click.prevent="linkClicked" v-html="postBodyHtml" /> - <a + <button v-if="hideSubjectStatus" - href="#" - class="cw-status-hider" + class="button-unstyled -link cw-status-hider" @click.prevent="toggleShowMore" > {{ $t("status.show_content") }} @@ -79,15 +77,14 @@ v-if="status.card" icon="link" /> - </a> - <a + </button> + <button v-if="showingMore && !fullContent" - href="#" - class="status-unhider" + class="button-unstyled -link status-unhider" @click.prevent="toggleShowMore" > {{ tallStatus ? $t("general.show_less") : $t("status.hide_content") }} - </a> + </button> </div> <div v-if="status.poll && status.poll.options && !hideSubjectStatus"> diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js index 6e6e8193..76e7ef03 100644 --- a/src/components/tab_switcher/tab_switcher.js +++ b/src/components/tab_switcher/tab_switcher.js @@ -81,7 +81,7 @@ export default Vue.component('tab-switcher', { const tabs = this.$slots.default .map((slot, index) => { if (!slot.tag) return - const classesTab = ['tab'] + const classesTab = ['tab', 'button-default'] const classesWrapper = ['tab-wrapper'] if (this.activeIndex === index) { classesTab.push('active') diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index cba46daf..665d195e 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -50,17 +50,10 @@ const Timeline = { TimelineMenu }, computed: { - timelineError () { - return this.$store.state.statuses.error - }, - errorData () { - return this.$store.state.statuses.errorData - }, newStatusCount () { return this.timeline.newStatusCount }, showLoadButton () { - if (this.timelineError || this.errorData) return false return this.timeline.newStatusCount > 0 || this.timeline.flushMarker !== 0 }, loadButtonString () { @@ -171,11 +164,12 @@ const Timeline = { userId: this.userId, tag: this.tag }).then(({ statuses }) => { - store.commit('setLoading', { timeline: this.timelineName, value: false }) if (statuses && statuses.length === 0) { this.bottomedOut = true } - }) + }).finally(() => + store.commit('setLoading', { timeline: this.timelineName, value: false }) + ) }, 1000, this), determineVisibleStatuses () { if (!this.$refs.timeline) return diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 04859852..4c43fe5c 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -2,23 +2,9 @@ <div :class="[classes.root, 'Timeline']"> <div :class="classes.header"> <TimelineMenu v-if="!embedded" /> - <div - v-if="timelineError" - class="loadmore-error alert error" - @click.prevent - > - {{ $t('timeline.error_fetching') }} - </div> - <div - v-else-if="errorData" - class="loadmore-error alert error" - @click.prevent - > - {{ errorData.statusText }} - </div> <button - v-else-if="showLoadButton" - class="loadmore-button" + v-if="showLoadButton" + class="button-default loadmore-button" @click.prevent="showNewStatuses" > {{ loadButtonString }} @@ -75,19 +61,15 @@ > {{ $t('timeline.no_more_statuses') }} </div> - <a - v-else-if="!timeline.loading && !errorData" - href="#" + <button + v-else-if="!timeline.loading" + class="button-unstyled -link -fullwidth" @click.prevent="fetchOlderStatuses()" > - <div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div> - </a> - <a - v-else-if="errorData" - href="#" - > - <div class="new-status-notification text-center panel-footer">{{ errorData.error }}</div> - </a> + <div class="new-status-notification text-center panel-footer"> + {{ $t('timeline.load_older') }} + </div> + </button> <div v-else class="new-status-notification text-center panel-footer" @@ -120,6 +102,7 @@ .timeline-heading { max-width: 100%; flex-wrap: nowrap; + align-items: center; .loadmore-button { flex-shrink: 0; } diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js index 4ccd52b4..8d6a58b1 100644 --- a/src/components/timeline_menu/timeline_menu.js +++ b/src/components/timeline_menu/timeline_menu.js @@ -19,7 +19,7 @@ library.add( faChevronDown ) -// Route -> i18n key mapping, exported andnot in the computed +// Route -> i18n key mapping, exported and not in the computed // because nav panel benefits from the same information. export const timelineNames = () => { return { @@ -27,8 +27,7 @@ export const timelineNames = () => { 'bookmarks': 'nav.bookmarks', 'dms': 'nav.dms', 'public-timeline': 'nav.public_tl', - 'public-external-timeline': 'nav.twkn', - 'tag-timeline': 'tag' + 'public-external-timeline': 'nav.twkn' } } @@ -60,6 +59,14 @@ const TimelineMenu = { this.isOpen = true }, 25) }, + blockOpen (event) { + // For the blank area inside the button element. + // Just setting @click.stop="" makes unintuitive behavior when + // menu is open and clicking on the blank area doesn't close it. + if (!this.isOpen) { + event.stopPropagation() + } + }, timelineName () { const route = this.$route.name if (route === 'tag-timeline') { diff --git a/src/components/timeline_menu/timeline_menu.vue b/src/components/timeline_menu/timeline_menu.vue index c46531be..3c86842b 100644 --- a/src/components/timeline_menu/timeline_menu.vue +++ b/src/components/timeline_menu/timeline_menu.vue @@ -65,10 +65,16 @@ slot="trigger" class="title timeline-menu-title" > - <span>{{ timelineName() }}</span> - <FAIcon - size="sm" - icon="chevron-down" + <span class="timeline-title">{{ timelineName() }}</span> + <span> + <FAIcon + size="sm" + icon="chevron-down" + /> + </span> + <span + class="click-blocker" + @click="blockOpen" /> </div> </Popover> @@ -117,8 +123,9 @@ cursor: pointer; user-select: none; width: 100%; + display: flex; - span { + .timeline-menu-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -128,6 +135,11 @@ margin-left: 0.6em; transition: transform 100ms; } + + .click-blocker { + cursor: default; + flex-grow: 1; + } } &.open .timeline-menu-title svg { diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index f916af9d..16dd5249 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -162,7 +162,7 @@ <template v-if="relationship.following"> <ProgressButton v-if="!relationship.subscribing" - class="btn btn-default" + class="btn button-default" :click="subscribeUser" :title="$t('user_card.subscribe')" > @@ -170,7 +170,7 @@ </ProgressButton> <ProgressButton v-else - class="btn btn-default toggled" + class="btn button-default toggled" :click="unsubscribeUser" :title="$t('user_card.unsubscribe')" > @@ -192,14 +192,14 @@ <div> <button v-if="relationship.muting" - class="btn btn-default btn-block toggled" + class="btn button-default btn-block toggled" @click="unmuteUser" > {{ $t('user_card.muted') }} </button> <button v-else - class="btn btn-default btn-block" + class="btn button-default btn-block" @click="muteUser" > {{ $t('user_card.mute') }} @@ -207,7 +207,7 @@ </div> <div> <button - class="btn btn-default btn-block" + class="btn button-default btn-block" @click="mentionUser" > {{ $t('user_card.mention') }} diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index f1f51840..745e795d 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -20,14 +20,13 @@ :key="index" class="user-profile-field" > + <!-- eslint-disable vue/no-v-html --> <dt :title="user.fields_text[index].name" class="user-profile-field-name" @click.prevent="linkClicked" - > - {{ field.name }} - </dt> - <!-- eslint-disable vue/no-v-html --> + v-html="field.name" + /> <dd :title="user.fields_text[index].value" class="user-profile-field-value" diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue index 2a8d8d48..fb43094f 100644 --- a/src/components/user_reporting_modal/user_reporting_modal.vue +++ b/src/components/user_reporting_modal/user_reporting_modal.vue @@ -29,7 +29,7 @@ </div> <div> <button - class="btn btn-default" + class="btn button-default" :disabled="processing" @click="reportUser" > diff --git a/src/components/video_attachment/video_attachment.vue b/src/components/video_attachment/video_attachment.vue index a4bf01e8..8a3ea1e3 100644 --- a/src/components/video_attachment/video_attachment.vue +++ b/src/components/video_attachment/video_attachment.vue @@ -1,6 +1,7 @@ <template> <video class="video" + preload="metadata" :src="attachment.url" :loop="loopVideo" :controls="controls" |
