commit: 954d03150f1dc097b9950cfef2fed2e4f55b6442
parent 42d5d8e43338d0b97cc922ff1d14b77f3ff9d448
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date: Tue, 31 Oct 2023 11:29:04 +0000
Merge branch 'tusooa/extra-notifications' into 'develop'
Extra notifications
See merge request pleroma/pleroma-fe!1853
Diffstat:
12 files changed, 274 insertions(+), 8 deletions(-)
diff --git a/changelog.d/extra-notifications.add b/changelog.d/extra-notifications.add
@@ -0,0 +1 @@
+Support showing extra notifications in the notifications column
diff --git a/src/components/extra_notifications/extra_notifications.js b/src/components/extra_notifications/extra_notifications.js
@@ -0,0 +1,48 @@
+import { mapGetters } from 'vuex'
+
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+ faUserPlus,
+ faComments,
+ faBullhorn
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+ faUserPlus,
+ faComments,
+ faBullhorn
+)
+
+const ExtraNotifications = {
+ computed: {
+ shouldShowChats () {
+ return this.mergedConfig.showExtraNotifications && this.mergedConfig.showChatsInExtraNotifications && this.unreadChatCount
+ },
+ shouldShowAnnouncements () {
+ return this.mergedConfig.showExtraNotifications && this.mergedConfig.showAnnouncementsInExtraNotifications && this.unreadAnnouncementCount
+ },
+ shouldShowFollowRequests () {
+ return this.mergedConfig.showExtraNotifications && this.mergedConfig.showFollowRequestsInExtraNotifications && this.followRequestCount
+ },
+ hasAnythingToShow () {
+ return this.shouldShowChats || this.shouldShowAnnouncements || this.shouldShowFollowRequests
+ },
+ shouldShowCustomizationTip () {
+ return this.mergedConfig.showExtraNotificationsTip && this.hasAnythingToShow
+ },
+ currentUser () {
+ return this.$store.state.users.currentUser
+ },
+ ...mapGetters(['unreadChatCount', 'unreadAnnouncementCount', 'followRequestCount', 'mergedConfig'])
+ },
+ methods: {
+ openNotificationSettings () {
+ return this.$store.dispatch('openSettingsModalTab', 'notifications')
+ },
+ dismissConfigurationTip () {
+ return this.$store.dispatch('setOption', { name: 'showExtraNotificationsTip', value: false })
+ }
+ }
+}
+
+export default ExtraNotifications
diff --git a/src/components/extra_notifications/extra_notifications.vue b/src/components/extra_notifications/extra_notifications.vue
@@ -0,0 +1,113 @@
+<template>
+ <div class="ExtraNotifications">
+ <div
+ v-if="shouldShowChats"
+ class="notification unseen"
+ >
+ <div class="notification-overlay" />
+ <router-link
+ class="button-unstyled -link extra-notification"
+ :to="{ name: 'chats', params: { username: currentUser.screen_name } }"
+ >
+ <FAIcon
+ fixed-width
+ class="fa-scale-110 icon"
+ icon="comments"
+ />
+ {{ $tc('notifications.unread_chats', unreadChatCount, { num: unreadChatCount }) }}
+ </router-link>
+ </div>
+ <div
+ v-if="shouldShowAnnouncements"
+ class="notification unseen"
+ >
+ <div class="notification-overlay" />
+ <router-link
+ class="button-unstyled -link extra-notification"
+ :to="{ name: 'announcements' }"
+ >
+ <FAIcon
+ fixed-width
+ class="fa-scale-110 icon"
+ icon="bullhorn"
+ />
+ {{ $tc('notifications.unread_announcements', unreadAnnouncementCount, { num: unreadAnnouncementCount }) }}
+ </router-link>
+ </div>
+ <div
+ v-if="shouldShowFollowRequests"
+ class="notification unseen"
+ >
+ <div class="notification-overlay" />
+ <router-link
+ class="button-unstyled -link extra-notification"
+ :to="{ name: 'friend-requests' }"
+ >
+ <FAIcon
+ fixed-width
+ class="fa-scale-110 icon"
+ icon="user-plus"
+ />
+ {{ $tc('notifications.unread_follow_requests', followRequestCount, { num: followRequestCount }) }}
+ </router-link>
+ </div>
+ <i18n-t
+ v-if="shouldShowCustomizationTip"
+ tag="span"
+ class="notification tip extra-notification"
+ keypath="notifications.configuration_tip"
+ >
+ <template #theSettings>
+ <button
+ class="button-unstyled -link"
+ @click="openNotificationSettings"
+ >
+ {{ $t('notifications.configuration_tip_settings') }}
+ </button>
+ </template>
+ <template #dismiss>
+ <button
+ class="button-unstyled -link"
+ @click="dismissConfigurationTip"
+ >
+ {{ $t('notifications.configuration_tip_dismiss') }}
+ </button>
+ </template>
+ </i18n-t>
+ </div>
+</template>
+
+<script src="./extra_notifications.js" />
+
+<style lang="scss">
+@import "../../variables";
+
+.ExtraNotifications {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+
+ .notification {
+ width: 100%;
+ border-bottom: 1px solid;
+ border-color: $fallback--border;
+ border-color: var(--border, $fallback--border);
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .extra-notification {
+ padding: 1em;
+ }
+
+ .icon {
+ margin-right: 0.5em;
+ }
+
+ .tip {
+ display: inline;
+ }
+}
+</style>
diff --git a/src/components/interactions/interactions.vue b/src/components/interactions/interactions.vue
@@ -39,6 +39,7 @@
<Notifications
ref="notifications"
:no-heading="true"
+ :no-extra="true"
:minimal-mode="true"
:filter-mode="filterMode"
/>
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
@@ -1,7 +1,10 @@
import SideDrawer from '../side_drawer/side_drawer.vue'
import Notifications from '../notifications/notifications.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
-import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
+import {
+ unseenNotificationsFromStore,
+ countExtraNotifications
+} from '../../services/notification_utils/notification_utils'
import GestureService from '../../services/gesture_service/gesture_service'
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
import { mapGetters } from 'vuex'
@@ -50,7 +53,7 @@ const MobileNav = {
return unseenNotificationsFromStore(this.$store)
},
unseenNotificationsCount () {
- return this.unseenNotifications.length
+ return this.unseenNotifications.length + countExtraNotifications(this.$store)
},
hideSitename () { return this.$store.state.instance.hideSitename },
sitename () { return this.$store.state.instance.name },
diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
@@ -1,12 +1,14 @@
import { computed } from 'vue'
import { mapGetters } from 'vuex'
import Notification from '../notification/notification.vue'
+import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
import NotificationFilters from './notification_filters.vue'
import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js'
import {
notificationsFromStore,
filteredNotificationsFromStore,
- unseenNotificationsFromStore
+ unseenNotificationsFromStore,
+ countExtraNotifications
} from '../../services/notification_utils/notification_utils.js'
import FaviconService from '../../services/favicon_service/favicon_service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
@@ -23,7 +25,8 @@ const DEFAULT_SEEN_TO_DISPLAY_COUNT = 30
const Notifications = {
components: {
Notification,
- NotificationFilters
+ NotificationFilters,
+ ExtraNotifications
},
props: {
// Disables panel styles, unread mark, potentially other notification-related actions
@@ -31,6 +34,11 @@ const Notifications = {
minimalMode: Boolean,
// Custom filter mode, an array of strings, possible values 'mention', 'repeat', 'like', 'follow', used to override global filter for use in "Interactions" timeline
filterMode: Array,
+ // Do not show extra notifications
+ noExtra: {
+ type: Boolean,
+ default: false
+ },
// Disable teleporting (i.e. for /users/user/notifications)
disableTeleport: Boolean
},
@@ -65,11 +73,17 @@ const Notifications = {
filteredNotifications () {
return filteredNotificationsFromStore(this.$store, this.filterMode)
},
+ unseenCountBadgeText () {
+ return `${this.unseenCount ? this.unseenCount : ''}${this.extraNotificationsCount ? '*' : ''}`
+ },
unseenCount () {
return this.unseenNotifications.length
},
+ extraNotificationsCount () {
+ return countExtraNotifications(this.$store)
+ },
unseenCountTitle () {
- return this.unseenCount + (this.unreadChatCount) + this.unreadAnnouncementCount
+ return this.unseenNotifications.length + (this.unreadChatCount) + this.unreadAnnouncementCount
},
loading () {
return this.$store.state.statuses.notifications.loading
@@ -94,6 +108,9 @@ const Notifications = {
return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount)
},
noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders },
+ showExtraNotifications () {
+ return !this.noExtra
+ },
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
},
mounted () {
diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue
@@ -17,9 +17,9 @@
<div class="title">
{{ $t('notifications.notifications') }}
<span
- v-if="unseenCount"
+ v-if="unseenCountBadgeText"
class="badge badge-notification unseen-count"
- >{{ unseenCount }}</span>
+ >{{ unseenCountBadgeText }}</span>
</div>
<div
v-if="showScrollTop"
@@ -55,6 +55,13 @@
role="feed"
>
<div
+ v-if="showExtraNotifications"
+ role="listitem"
+ class="notification"
+ >
+ <extra-notifications />
+ </div>
+ <div
v-for="notification in notificationsToDisplay"
:key="notification.id"
role="listitem"
diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue
@@ -51,6 +51,47 @@
</li>
</ul>
</li>
+ <li>
+ <BooleanSetting path="showExtraNotifications">
+ {{ $t('settings.notification_show_extra') }}
+ </BooleanSetting>
+ </li>
+ <li>
+ <ul class="setting-list suboptions">
+ <li>
+ <BooleanSetting
+ path="showChatsInExtraNotifications"
+ :disabled="!mergedConfig.showExtraNotifications"
+ >
+ {{ $t('settings.notification_extra_chats') }}
+ </BooleanSetting>
+ </li>
+ <li>
+ <BooleanSetting
+ path="showAnnouncementsInExtraNotifications"
+ :disabled="!mergedConfig.showExtraNotifications"
+ >
+ {{ $t('settings.notification_extra_announcements') }}
+ </BooleanSetting>
+ </li>
+ <li>
+ <BooleanSetting
+ path="showFollowRequestsInExtraNotifications"
+ :disabled="!mergedConfig.showExtraNotifications"
+ >
+ {{ $t('settings.notification_extra_follow_requests') }}
+ </BooleanSetting>
+ </li>
+ <li>
+ <BooleanSetting
+ path="showExtraNotificationsTip"
+ :disabled="!mergedConfig.showExtraNotifications"
+ >
+ {{ $t('settings.notification_extra_tip') }}
+ </BooleanSetting>
+ </li>
+ </ul>
+ </li>
</ul>
</div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -205,7 +205,13 @@
"migrated_to": "migrated to",
"reacted_with": "reacted with {0}",
"submitted_report": "submitted a report",
- "poll_ended": "poll has ended"
+ "poll_ended": "poll has ended",
+ "unread_announcements": "{num} unread announcement | {num} unread announcements",
+ "unread_chats": "{num} unread chat | {num} unread chats",
+ "unread_follow_requests": "{num} new follow request | {num} new follow requests",
+ "configuration_tip": "You can customize what to display here in {theSettings}. {dismiss}",
+ "configuration_tip_settings": "the settings",
+ "configuration_tip_dismiss": "Do not show again"
},
"polls": {
"add_poll": "Add poll",
@@ -561,6 +567,11 @@
"notification_visibility_moves": "User Migrates",
"notification_visibility_emoji_reactions": "Reactions",
"notification_visibility_polls": "Ends of polls you voted in",
+ "notification_show_extra": "Show extra notifications in the notifications column",
+ "notification_extra_chats": "Show unread chats",
+ "notification_extra_announcements": "Show unread announcements",
+ "notification_extra_follow_requests": "Show new follow requests",
+ "notification_extra_tip": "Show the customization tip for extra notifications",
"no_rich_text_description": "Strip rich text formatting from all posts",
"no_blocks": "No blocks",
"no_mutes": "No mutes",
diff --git a/src/modules/config.js b/src/modules/config.js
@@ -117,6 +117,11 @@ export const defaultState = {
conversationTreeAdvanced: undefined, // instance default
conversationOtherRepliesButton: undefined, // instance default
conversationTreeFadeAncestors: undefined, // instance default
+ showExtraNotifications: undefined, // instance default
+ showExtraNotificationsTip: undefined, // instance default
+ showChatsInExtraNotifications: undefined, // instance default
+ showAnnouncementsInExtraNotifications: undefined, // instance default
+ showFollowRequestsInExtraNotifications: undefined, // instance default
maxDepthInThread: undefined, // instance default
autocompleteSelect: undefined // instance default
}
diff --git a/src/modules/instance.js b/src/modules/instance.js
@@ -103,6 +103,11 @@ const defaultState = {
conversationTreeAdvanced: false,
conversationOtherRepliesButton: 'below',
conversationTreeFadeAncestors: false,
+ showExtraNotifications: true,
+ showExtraNotificationsTip: true,
+ showChatsInExtraNotifications: true,
+ showAnnouncementsInExtraNotifications: true,
+ showFollowRequestsInExtraNotifications: true,
maxDepthInThread: 6,
autocompleteSelect: false,
diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js
@@ -124,3 +124,17 @@ export const prepareNotificationObject = (notification, i18n) => {
return notifObj
}
+
+export const countExtraNotifications = (store) => {
+ const mergedConfig = store.getters.mergedConfig
+
+ if (!mergedConfig.showExtraNotifications) {
+ return 0
+ }
+
+ return [
+ mergedConfig.showChatsInExtraNotifications ? store.getters.unreadChatCount : 0,
+ mergedConfig.showAnnouncementsInExtraNotifications ? store.getters.unreadAnnouncementCount : 0,
+ mergedConfig.showFollowRequestsInExtraNotifications ? store.getters.followRequestCount : 0
+ ].reduce((a, c) => a + c, 0)
+}