diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/media_modal/media_modal.js | 2 | ||||
| -rw-r--r-- | src/components/notification/notification.js | 6 | ||||
| -rw-r--r-- | src/components/notification/notification.vue | 6 | ||||
| -rw-r--r-- | src/components/notifications/notifications.scss | 6 | ||||
| -rw-r--r-- | src/components/react_button/react_button.js | 2 | ||||
| -rw-r--r-- | src/components/settings_modal/tabs/filtering_tab.js | 20 | ||||
| -rw-r--r-- | src/components/settings_modal/tabs/helpers/shared_computed_object.js | 10 | ||||
| -rw-r--r-- | src/components/status/status.js | 55 | ||||
| -rw-r--r-- | src/components/status/status.vue | 72 | ||||
| -rw-r--r-- | src/components/status_content/status_content.js | 4 | ||||
| -rw-r--r-- | src/components/still-image/still-image.vue | 11 |
11 files changed, 145 insertions, 49 deletions
diff --git a/src/components/media_modal/media_modal.js b/src/components/media_modal/media_modal.js index abb18c7d..24764e80 100644 --- a/src/components/media_modal/media_modal.js +++ b/src/components/media_modal/media_modal.js @@ -84,10 +84,12 @@ const MediaModal = { } }, mounted () { + window.addEventListener('popstate', this.hide) document.addEventListener('keyup', this.handleKeyupEvent) document.addEventListener('keydown', this.handleKeydownEvent) }, destroyed () { + window.removeEventListener('popstate', this.hide) document.removeEventListener('keyup', this.handleKeyupEvent) document.removeEventListener('keydown', this.handleKeydownEvent) } diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 1cf4c9bc..5aa40e98 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -1,3 +1,4 @@ +import StatusContent from '../status_content/status_content.vue' import Status from '../status/status.vue' import UserAvatar from '../user_avatar/user_avatar.vue' import UserCard from '../user_card/user_card.vue' @@ -16,10 +17,11 @@ const Notification = { }, props: [ 'notification' ], components: { - Status, + StatusContent, UserAvatar, UserCard, - Timeago + Timeago, + Status }, methods: { toggleUserExpanded () { diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 0e46a2a7..044ac871 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -157,11 +157,9 @@ </router-link> </div> <template v-else> - <status + <status-content class="faint" - :compact="true" - :statusoid="notification.action" - :no-heading="true" + :status="notification.action" /> </template> </div> diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss index 9efcfcf8..b675af5a 100644 --- a/src/components/notifications/notifications.scss +++ b/src/components/notifications/notifications.scss @@ -36,6 +36,8 @@ border-bottom: 1px solid; border-color: $fallback--border; border-color: var(--border, $fallback--border); + word-wrap: break-word; + word-break: break-word; &:hover .animated.avatar { canvas { @@ -46,10 +48,6 @@ } } - .muted { - padding: .25em .6em; - } - .non-mention { display: flex; flex: 1; diff --git a/src/components/react_button/react_button.js b/src/components/react_button/react_button.js index abc3bf07..f0931446 100644 --- a/src/components/react_button/react_button.js +++ b/src/components/react_button/react_button.js @@ -24,7 +24,7 @@ const ReactButton = { }, computed: { commonEmojis () { - return ['โค๏ธ', '๐ ', '๐', '๐', '๐ฅ'] + return ['๐', '๐ ', '๐', '๐', '๐ฅ'] }, emojis () { if (this.filterWord !== '') { diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js index ec330667..dd7ecaf7 100644 --- a/src/components/settings_modal/tabs/filtering_tab.js +++ b/src/components/settings_modal/tabs/filtering_tab.js @@ -1,13 +1,31 @@ +import { filter, trim } from 'lodash' import Checkbox from 'src/components/checkbox/checkbox.vue' import SharedComputedObject from './helpers/shared_computed_object.js' const FilteringTab = { + data () { + return { + muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n') + } + }, components: { Checkbox }, computed: { - ...SharedComputedObject() + ...SharedComputedObject(), + muteWordsString: { + get () { + return this.muteWordsStringLocal + }, + set (value) { + this.muteWordsStringLocal = value + this.$store.dispatch('setOption', { + name: 'muteWords', + value: filter(value.split('\n'), (word) => trim(word).length > 0) + }) + } + } }, // Updating nested properties watch: { diff --git a/src/components/settings_modal/tabs/helpers/shared_computed_object.js b/src/components/settings_modal/tabs/helpers/shared_computed_object.js index b6a18e9c..86703697 100644 --- a/src/components/settings_modal/tabs/helpers/shared_computed_object.js +++ b/src/components/settings_modal/tabs/helpers/shared_computed_object.js @@ -1,4 +1,3 @@ -import { filter, trim } from 'lodash' import { instanceDefaultProperties, multiChoiceProperties, @@ -38,15 +37,6 @@ const SharedComputedObject = () => ({ }]) .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), // Special cases (need to transform values or perform actions first) - muteWordsString: { - get () { return this.$store.getters.mergedConfig.muteWords.join('\n') }, - set (value) { - this.$store.dispatch('setOption', { - name: 'muteWords', - value: filter(value.split('\n'), (word) => trim(word).length > 0) - }) - } - }, useStreamingApi: { get () { return this.$store.getters.mergedConfig.useStreamingApi }, set (value) { diff --git a/src/components/status/status.js b/src/components/status/status.js index 9cd9d61c..73382521 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -12,7 +12,8 @@ import StatusPopover from '../status_popover/status_popover.vue' import EmojiReactions from '../emoji_reactions/emoji_reactions.vue' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' -import { filter, unescape, uniqBy } from 'lodash' +import { muteWordHits } from '../../services/status_parser/status_parser.js' +import { unescape, uniqBy } from 'lodash' import { mapGetters, mapState } from 'vuex' const Status = { @@ -44,6 +45,12 @@ const Status = { muteWords () { return this.mergedConfig.muteWords }, + showReasonMutedThread () { + return ( + this.status.thread_muted || + (this.status.reblog && this.status.reblog.thread_muted) + ) && !this.inConversation + }, repeaterClass () { const user = this.statusoid.user return highlightClass(user) @@ -93,20 +100,42 @@ const Status = { return !!this.currentUser }, muteWordHits () { - const statusText = this.status.text.toLowerCase() - const statusSummary = this.status.summary.toLowerCase() - const hits = filter(this.muteWords, (muteWord) => { - return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase()) - }) - - return hits + return muteWordHits(this.status, this.muteWords) }, muted () { - const relationship = this.$store.getters.relationship(this.status.user.id) - return !this.unmuted && ( - (!(this.inProfile && this.status.user.id === this.profileUserId) && relationship.muting) || - (!this.inConversation && this.status.thread_muted) || - this.muteWordHits.length > 0) + const { status } = this + const { reblog } = status + const relationship = this.$store.getters.relationship(status.user.id) + const relationshipReblog = reblog && this.$store.getters.relationship(reblog.user.id) + const reasonsToMute = ( + // Post is muted according to BE + status.muted || + // Reprรถรถt of a muted post according to BE + (reblog && reblog.muted) || + // Muted user + relationship.muting || + // Muted user of a reprรถรถt + (relationshipReblog && relationshipReblog.muting) || + // Thread is muted + status.thread_muted || + // Wordfiltered + this.muteWordHits.length > 0 + ) + const excusesNotToMute = ( + ( + this.inProfile && ( + // Don't mute user's posts on user timeline (except reblogs) + (!reblog && status.user.id === this.profileUserId) || + // Same as above but also allow self-reblogs + (reblog && reblog.user.id === this.profileUserId) + ) + ) || + // Don't mute statuses in muted conversation when said conversation is opened + (this.inConversation && status.thread_muted) + // No excuses if post has muted words + ) && !this.muteWordHits.length > 0 + + return !this.unmuted && !excusesNotToMute && reasonsToMute }, hideFilteredStatuses () { return this.mergedConfig.hideFilteredStatuses diff --git a/src/components/status/status.vue b/src/components/status/status.vue index e4c7545b..336f912a 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -17,12 +17,33 @@ </div> <template v-if="muted && !isPreview"> <div class="media status container muted"> - <small> + <small class="username"> + <i + v-if="muted && retweet" + class="button-icon icon-retweet" + /> <router-link :to="userProfileLink"> {{ status.user.screen_name }} </router-link> </small> - <small class="muteWords">{{ muteWordHits.join(', ') }}</small> + <small + v-if="showReasonMutedThread" + class="mute-thread" + > + {{ $t('status.thread_muted') }} + </small> + <small + v-if="showReasonMutedThread && muteWordHits.length > 0" + class="mute-thread" + > + {{ $t('status.thread_muted_and_words') }} + </small> + <small + class="mute-words" + :title="muteWordHits.join(', ')" + > + {{ muteWordHits.join(', ') }} + </small> <a href="#" class="unmute" @@ -637,19 +658,48 @@ $status-margin: 0.75em; } .muted { - padding: 0.25em 0.5em; - button { - margin-left: auto; + padding: .25em .6em; + height: 1.2em; + line-height: 1.2em; + text-overflow: ellipsis; + overflow: hidden; + display: flex; + flex-wrap: nowrap; + + .username, .mute-thread, .mute-words { + word-wrap: normal; + word-break: normal; + white-space: nowrap; } - .muteWords { - margin-left: 10px; + .username, .mute-words { + text-overflow: ellipsis; + overflow: hidden; + } + + .username { + flex: 0 1 auto; + margin-right: .2em; + } + + .mute-thread { + flex: 0 0 auto; } -} -a.unmute { - display: block; - margin-left: auto; + .mute-words { + flex: 1 0 5em; + margin-left: .2em; + &::before { + content: ' ' + } + } + + .unmute { + flex: 0 0 auto; + margin-left: auto; + display: block; + margin-left: auto; + } } .reply-body { diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js index ccc01b6f..c0a71e8f 100644 --- a/src/components/status_content/status_content.js +++ b/src/components/status_content/status_content.js @@ -176,8 +176,8 @@ const StatusContent = { } } if (target.rel.match(/(?:^|\s)tag(?:$|\s)/) || target.className.match(/hashtag/)) { - // Extract tag name from link url - const tag = extractTagFromUrl(target.href) + // Extract tag name from dataset or link url + const tag = target.dataset.tag || extractTagFromUrl(target.href) if (tag) { const link = this.generateTagLink(tag) this.$router.push(link) diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue index 4137bd59..08af26f6 100644 --- a/src/components/still-image/still-image.vue +++ b/src/components/still-image/still-image.vue @@ -23,12 +23,21 @@ <style lang="scss"> @import '../../_variables.scss'; +.contain-fit { + .still-image { + img { + height: 100%; + } + } +} + .still-image { position: relative; line-height: 0; overflow: hidden; width: 100%; height: 100%; + display: flex; &:hover canvas { display: none; @@ -36,8 +45,8 @@ img { width: 100%; - height: 100%; object-fit: contain; + align-self: center; } &.animated { |
