logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 6d7b5b157b64df5b189dd4e64e382bdda17e8897
parent a90910be8fb1f3ebde4177fcf08ec5024da44755
Author: Shpuld Shpludson <shp@cock.li>
Date:   Mon,  1 Mar 2021 12:12:12 +0000

Merge branch 'feat/timeline-quick-settings' into 'develop'

close #1050 - add a quick settings menu to timeline header

Closes #1050

See merge request pleroma/pleroma-fe!1355

Diffstat:

MCHANGELOG.md1+
Msrc/components/moderation_tools/moderation_tools.vue33+++++++--------------------------
Msrc/components/popover/popover.js7+++++++
Msrc/components/popover/popover.vue35++++++++++++++++++++++++++++++-----
Msrc/components/timeline/timeline.js9++++++---
Msrc/components/timeline/timeline.vue4++++
Asrc/components/timeline/timeline_quick_settings.js63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/timeline/timeline_quick_settings.vue107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/i18n/en.json6++++++
9 files changed, 231 insertions(+), 34 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Added reason field for registration when approval is required +- Added a quick settings to timeline header for easier access - Added option to mark posts as sensitive by default ## [2.2.3] - 2021-01-18 diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue @@ -50,74 +50,74 @@ class="button-default dropdown-item" @click="toggleTag(tags.FORCE_NSFW)" > - {{ $t('user_card.admin_menu.force_nsfw') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }" /> + {{ $t('user_card.admin_menu.force_nsfw') }} </button> <button class="button-default dropdown-item" @click="toggleTag(tags.STRIP_MEDIA)" > - {{ $t('user_card.admin_menu.strip_media') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }" /> + {{ $t('user_card.admin_menu.strip_media') }} </button> <button class="button-default dropdown-item" @click="toggleTag(tags.FORCE_UNLISTED)" > - {{ $t('user_card.admin_menu.force_unlisted') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }" /> + {{ $t('user_card.admin_menu.force_unlisted') }} </button> <button class="button-default dropdown-item" @click="toggleTag(tags.SANDBOX)" > - {{ $t('user_card.admin_menu.sandbox') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }" /> + {{ $t('user_card.admin_menu.sandbox') }} </button> <button v-if="user.is_local" class="button-default dropdown-item" @click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)" > - {{ $t('user_card.admin_menu.disable_remote_subscription') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }" /> + {{ $t('user_card.admin_menu.disable_remote_subscription') }} </button> <button v-if="user.is_local" class="button-default dropdown-item" @click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)" > - {{ $t('user_card.admin_menu.disable_any_subscription') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }" /> + {{ $t('user_card.admin_menu.disable_any_subscription') }} </button> <button v-if="user.is_local" class="button-default dropdown-item" @click="toggleTag(tags.QUARANTINE)" > - {{ $t('user_card.admin_menu.quarantine') }} <span class="menu-checkbox" :class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }" /> + {{ $t('user_card.admin_menu.quarantine') }} </button> </span> </div> @@ -163,25 +163,6 @@ <style lang="scss"> @import '../../_variables.scss'; -.menu-checkbox { - float: right; - min-width: 22px; - max-width: 22px; - min-height: 22px; - max-height: 22px; - line-height: 22px; - text-align: center; - border-radius: 0px; - background-color: $fallback--fg; - background-color: var(--input, $fallback--fg); - box-shadow: 0px 0px 2px black inset; - box-shadow: var(--inputShadow); - - &.menu-checkbox-checked::after { - content: '✓'; - } -} - .moderation-tools-popover { height: 100%; .trigger { diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js @@ -3,25 +3,32 @@ const Popover = { props: { // Action to trigger popover: either 'hover' or 'click' trigger: String, + // Either 'top' or 'bottom' placement: String, + // Takes object with properties 'x' and 'y', values of these can be // 'container' for using offsetParent as boundaries for either axis // or 'viewport' boundTo: Object, + // Takes a selector to use as a replacement for the parent container // for getting boundaries for x an y axis boundToSelector: String, + // Takes a top/bottom/left/right object, how much space to leave // between boundary and popover element margin: Object, + // Takes a x/y object and tells how many pixels to offset from // anchor point on either axis offset: Object, + // Replaces the classes you may want for the popover container. // Use 'popover-default' in addition to get the default popover // styles with your custom class. popoverClass: String, + // If true, subtract padding when calculating position for the popover, // use it when popover offset looks to be different on top vs bottom. removePadding: Boolean diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue @@ -82,10 +82,9 @@ .dropdown-item { line-height: 21px; - margin-right: 5px; overflow: auto; display: block; - padding: .25rem 1.0rem .25rem 1.5rem; + padding: .5em 0.75em; clear: both; font-weight: 400; text-align: inherit; @@ -101,10 +100,9 @@ --btnText: var(--popoverText, $fallback--text); &-icon { - padding-left: 0.5rem; - svg { - margin-right: 0.25rem; + width: 22px; + margin-right: 0.75rem; color: var(--menuPopoverIcon, $fallback--icon) } } @@ -123,6 +121,33 @@ } } + .menu-checkbox { + display: inline-block; + vertical-align: middle; + min-width: 22px; + max-width: 22px; + min-height: 22px; + max-height: 22px; + line-height: 22px; + text-align: center; + border-radius: 0px; + background-color: $fallback--fg; + background-color: var(--input, $fallback--fg); + box-shadow: 0px 0px 2px black inset; + box-shadow: var(--inputShadow); + margin-right: 0.75em; + + &.menu-checkbox-checked::after { + font-size: 1.25em; + content: '✓'; + } + + &.menu-checkbox-radio::after { + font-size: 2em; + content: '•'; + } + } + } } </style> diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js @@ -2,12 +2,14 @@ import Status from '../status/status.vue' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' import Conversation from '../conversation/conversation.vue' import TimelineMenu from '../timeline_menu/timeline_menu.vue' +import TimelineQuickSettings from './timeline_quick_settings.vue' import { debounce, throttle, keyBy } from 'lodash' import { library } from '@fortawesome/fontawesome-svg-core' -import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' +import { faCircleNotch, faCog } from '@fortawesome/free-solid-svg-icons' library.add( - faCircleNotch + faCircleNotch, + faCog ) export const getExcludedStatusIdsByPinning = (statuses, pinnedStatusIds) => { @@ -47,7 +49,8 @@ const Timeline = { components: { Status, Conversation, - TimelineMenu + TimelineMenu, + TimelineQuickSettings }, computed: { newStatusCount () { diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue @@ -16,6 +16,7 @@ > {{ $t('timeline.up_to_date') }} </div> + <TimelineQuickSettings v-if="!embedded" /> </div> <div :class="classes.body"> <div @@ -103,9 +104,12 @@ max-width: 100%; flex-wrap: nowrap; align-items: center; + position: relative; + .loadmore-button { flex-shrink: 0; } + .loadmore-text { flex-shrink: 0; line-height: 1em; diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/timeline/timeline_quick_settings.js @@ -0,0 +1,63 @@ +import Popover from '../popover/popover.vue' +import BooleanSetting from '../settings_modal/helpers/boolean_setting.vue' +import { mapGetters } from 'vuex' +import { library } from '@fortawesome/fontawesome-svg-core' +import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons' + +library.add( + faFilter, + faFont, + faWrench +) + +const TimelineQuickSettings = { + components: { + Popover, + BooleanSetting + }, + methods: { + setReplyVisibility (visibility) { + this.$store.dispatch('setOption', { name: 'replyVisibility', value: visibility }) + this.$store.dispatch('queueFlushAll') + }, + openTab (tab) { + this.$store.dispatch('openSettingsModalTab', tab) + } + }, + computed: { + ...mapGetters(['mergedConfig']), + loggedIn () { + return !!this.$store.state.users.currentUser + }, + replyVisibilitySelf: { + get () { return this.mergedConfig.replyVisibility === 'self' }, + set () { this.setReplyVisibility('self') } + }, + replyVisibilityFollowing: { + get () { return this.mergedConfig.replyVisibility === 'following' }, + set () { this.setReplyVisibility('following') } + }, + replyVisibilityAll: { + get () { return this.mergedConfig.replyVisibility === 'all' }, + set () { this.setReplyVisibility('all') } + }, + hideMedia: { + get () { return this.mergedConfig.hideAttachments || this.mergedConfig.hideAttachmentsInConv }, + set () { + const value = !this.hideMedia + this.$store.dispatch('setOption', { name: 'hideAttachments', value }) + this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value }) + } + }, + hideMutedPosts: { + get () { return this.mergedConfig.hideMutedPosts || this.mergedConfig.hideFilteredStatuses }, + set () { + const value = !this.hideMutedPosts + this.$store.dispatch('setOption', { name: 'hideMutedPosts', value }) + this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value }) + } + } + } +} + +export default TimelineQuickSettings diff --git a/src/components/timeline/timeline_quick_settings.vue b/src/components/timeline/timeline_quick_settings.vue @@ -0,0 +1,107 @@ +<template> + <Popover + trigger="click" + class="TimelineQuickSettings" + :bound-to="{ x: 'container' }" + > + <div + slot="content" + class="timeline-settings-menu dropdown-menu" + > + <div v-if="loggedIn"> + <button + class="button-default dropdown-item" + @click="replyVisibilityAll = true" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-radio': replyVisibilityAll }" + />{{ $t('settings.reply_visibility_all') }} + </button> + <button + class="button-default dropdown-item" + @click="replyVisibilityFollowing = true" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-radio': replyVisibilityFollowing }" + />{{ $t('settings.reply_visibility_following_short') }} + </button> + <button + class="button-default dropdown-item" + @click="replyVisibilitySelf = true" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-radio': replyVisibilitySelf }" + />{{ $t('settings.reply_visibility_self_short') }} + </button> + <div + role="separator" + class="dropdown-divider" + /> + </div> + <button + class="button-default dropdown-item" + @click="hideMedia = !hideMedia" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-checked': hideMedia }" + />{{ $t('settings.hide_media_previews') }} + </button> + <button + class="button-default dropdown-item" + @click="hideMutedPosts = !hideMutedPosts" + > + <span + class="menu-checkbox" + :class="{ 'menu-checkbox-checked': hideMutedPosts }" + />{{ $t('settings.hide_all_muted_posts') }} + </button> + <button + class="button-default dropdown-item dropdown-item-icon" + @click="openTab('filtering')" + > + <FAIcon icon="font" />{{ $t('settings.word_filter') }} + </button> + <button + class="button-default dropdown-item dropdown-item-icon" + @click="openTab('general')" + > + <FAIcon icon="wrench" />{{ $t('settings.more_settings') }} + </button> + </div> + <div slot="trigger"> + <FAIcon icon="filter" /> + </div> + </Popover> +</template> + +<script src="./timeline_quick_settings.js"></script> + +<style lang="scss"> + +.TimelineQuickSettings { + align-self: stretch; + + > button { + font-size: 1.2em; + padding-left: 0.7em; + padding-right: 0.2em; + line-height: 100%; + height: 100%; + } + + .dropdown-item { + margin: 0; + } + + .timeline-settings-menu { + display: flex; + min-width: 12em; + flex-direction: column; + } +} + +</style> diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -325,6 +325,7 @@ "export_theme": "Save preset", "filtering": "Filtering", "filtering_explanation": "All statuses containing these words will be muted, one per line", + "word_filter": "Word filter", "follow_export": "Follow export", "follow_export_button": "Export your follows to a csv file", "follow_import": "Follow import", @@ -335,7 +336,9 @@ "general": "General", "hide_attachments_in_convo": "Hide attachments in conversations", "hide_attachments_in_tl": "Hide attachments in timeline", + "hide_media_previews": "Hide media previews", "hide_muted_posts": "Hide posts of muted users", + "hide_all_muted_posts": "Hide muted posts", "max_thumbnails": "Maximum amount of thumbnails per post", "hide_isp": "Hide instance-specific panel", "hide_wallpaper": "Hide instance wallpaper", @@ -405,6 +408,8 @@ "reply_visibility_all": "Show all replies", "reply_visibility_following": "Only show replies directed at me or users I'm following", "reply_visibility_self": "Only show replies directed at me", + "reply_visibility_following_short": "Show replies to my follows", + "reply_visibility_self_short": "Show replies to self only", "autohide_floating_post_button": "Automatically hide New Post button (mobile)", "saving_err": "Error saving settings", "saving_ok": "Settings saved", @@ -459,6 +464,7 @@ "notification_mutes": "To stop receiving notifications from a specific user, use a mute.", "notification_blocks": "Blocking a user stops all notifications as well as unsubscribes them.", "enable_web_push_notifications": "Enable web push notifications", + "more_settings": "More settings", "style": { "switcher": { "keep_color": "Keep colors",