Added ability to hide certain types of notifications

This commit is contained in:
Henry Jameson 2018-08-28 21:21:29 +03:00
parent 66a22762c2
commit b0e0686c7f
7 changed files with 110 additions and 17 deletions

View file

@ -11,6 +11,14 @@ const Notifications = {
notificationsFetcher.startFetching({ store, credentials }) notificationsFetcher.startFetching({ store, credentials })
}, },
computed: { computed: {
visibleTypes () {
return [
this.$store.state.config.notificationVisibility.likes && 'like',
this.$store.state.config.notificationVisibility.mentions && 'mention',
this.$store.state.config.notificationVisibility.repeats && 'repeat',
this.$store.state.config.notificationVisibility.follows && 'follow'
].filter(_ => _)
},
notifications () { notifications () {
return this.$store.state.statuses.notifications.data return this.$store.state.statuses.notifications.data
}, },
@ -18,13 +26,13 @@ const Notifications = {
return this.$store.state.statuses.notifications.error return this.$store.state.statuses.notifications.error
}, },
unseenNotifications () { unseenNotifications () {
return filter(this.notifications, ({seen}) => !seen) return filter(this.visibleNotifications, ({seen}) => !seen)
}, },
visibleNotifications () { visibleNotifications () {
// Don't know why, but sortBy([seen, -action.id]) doesn't work. // Don't know why, but sortBy([seen, -action.id]) doesn't work.
let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id) let sortedNotifications = sortBy(this.notifications, ({action}) => -action.id)
sortedNotifications = sortBy(sortedNotifications, 'seen') sortedNotifications = sortBy(sortedNotifications, 'seen')
return sortedNotifications return sortedNotifications.filter((notification) => this.visibleTypes.includes(notification.type))
}, },
unseenCount () { unseenCount () {
return this.unseenNotifications.length return this.unseenNotifications.length

View file

@ -10,6 +10,7 @@ const settings = {
hideAttachmentsLocal: this.$store.state.config.hideAttachments, hideAttachmentsLocal: this.$store.state.config.hideAttachments,
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv, hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw, hideNsfwLocal: this.$store.state.config.hideNsfw,
notificationVisibilityLocal: this.$store.state.config.notificationVisibility,
replyVisibilityLocal: this.$store.state.config.replyVisibility, replyVisibilityLocal: this.$store.state.config.replyVisibility,
loopVideoLocal: this.$store.state.config.loopVideo, loopVideoLocal: this.$store.state.config.loopVideo,
loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly, loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
@ -49,6 +50,18 @@ const settings = {
hideNsfwLocal (value) { hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value }) this.$store.dispatch('setOption', { name: 'hideNsfw', value })
}, },
'notificationVisibilityLocal.likes' (value) {
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
},
'notificationVisibilityLocal.follows' (value) {
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
},
'notificationVisibilityLocal.repeats' (value) {
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
},
'notificationVisibilityLocal.mentions' (value) {
this.$store.dispatch('setOption', { name: 'notificationVisibility', value: this.$store.state.config.notificationVisibility })
},
replyVisibilityLocal (value) { replyVisibilityLocal (value) {
this.$store.dispatch('setOption', { name: 'replyVisibility', value }) this.$store.dispatch('setOption', { name: 'replyVisibility', value })
}, },

View file

@ -81,6 +81,37 @@
<div :label="$t('settings.filtering')" > <div :label="$t('settings.filtering')" >
<div class="setting-item"> <div class="setting-item">
<div class="select-multiple">
<span class="label">{{$t('settings.notification_visibility')}}</span>
<ul class="option-list">
<li>
<input type="checkbox" id="notification-visibility-likes" v-model="notificationVisibilityLocal.likes">
<label for="notification-visibility-likes">
{{$t('settings.notification_visibility_likes')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-repeats" v-model="notificationVisibilityLocal.repeats">
<label for="notification-visibility-repeats">
{{$t('settings.notification_visibility_repeats')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-follows" v-model="notificationVisibilityLocal.follows">
<label for="notification-visibility-follows">
{{$t('settings.notification_visibility_follows')}}
</label>
</li>
<li>
<input type="checkbox" id="notification-visibility-mentions" v-model="notificationVisibilityLocal.mentions">
<label for="notification-visibility-mentions">
{{$t('settings.notification_visibility_mentions')}}
</label>
</li>
</ul>
</label>
</div>
<div>
{{$t('settings.replies_in_timeline')}} {{$t('settings.replies_in_timeline')}}
<label for="replyVisibility" class="select"> <label for="replyVisibility" class="select">
<select id="replyVisibility" v-model="replyVisibilityLocal"> <select id="replyVisibility" v-model="replyVisibilityLocal">
@ -91,6 +122,7 @@
<i class="icon-down-open"/> <i class="icon-down-open"/>
</label> </label>
</div> </div>
</div>
<div class="setting-item"> <div class="setting-item">
<p>{{$t('settings.filtering_explanation')}}</p> <p>{{$t('settings.filtering_explanation')}}</p>
<textarea id="muteWords" v-model="muteWordsString"></textarea> <textarea id="muteWords" v-model="muteWordsString"></textarea>
@ -113,6 +145,13 @@
margin: 1em 1em 1.4em; margin: 1em 1em 1.4em;
padding-bottom: 1.4em; padding-bottom: 1.4em;
div {
margin-bottom: .5em;
&:last-child {
margin-bottom: 0;
}
}
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
padding-bottom: 0; padding-bottom: 0;
@ -159,7 +198,15 @@
width: 10em; width: 10em;
} }
} }
.setting-list { .select-multiple {
display: flex;
.option-list {
margin: 0;
padding-left: .5em;
}
}
.setting-list,
.option-list{
list-style-type: none; list-style-type: none;
padding-left: 2em; padding-left: 2em;
li { li {

View file

@ -331,6 +331,11 @@ const en = {
reply_visibility_all: 'Show all replies', reply_visibility_all: 'Show all replies',
reply_visibility_following: 'Only show replies directed at me or users I\'m following', 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_self: 'Only show replies directed at me',
notification_visibility: 'Types of notifications to show',
notification_visibility_likes: 'Likes',
notification_visibility_mentions: 'Mentions',
notification_visibility_repeats: 'Repeats',
notification_visibility_follows: 'Follows',
follow_import: 'Follow import', follow_import: 'Follow import',
import_followers_from_a_csv_file: 'Import follows from a csv file', import_followers_from_a_csv_file: 'Import follows from a csv file',
follows_imported: 'Follows imported! Processing them will take a while.', follows_imported: 'Follows imported! Processing them will take a while.',
@ -1679,6 +1684,11 @@ const ru = {
reply_visibility_all: 'Показывать все ответы', reply_visibility_all: 'Показывать все ответы',
reply_visibility_following: 'Показывать только ответы мне и тех на кого я подписан', reply_visibility_following: 'Показывать только ответы мне и тех на кого я подписан',
reply_visibility_self: 'Показывать только ответы мне', reply_visibility_self: 'Показывать только ответы мне',
notification_visibility: 'Показывать уведомления',
notification_visibility_likes: 'Лайки',
notification_visibility_mentions: 'Упоминания',
notification_visibility_repeats: 'Повторы',
notification_visibility_follows: 'Подписки',
follow_import: 'Импортировать читаемых', follow_import: 'Импортировать читаемых',
import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv', import_followers_from_a_csv_file: 'Импортировать читаемых из файла .csv',
follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..', follows_imported: 'Список читаемых импортирован. Обработка займёт некоторое время..',

View file

@ -50,6 +50,7 @@ const persistedStateOptions = {
'config.hideAttachmentsInConv', 'config.hideAttachmentsInConv',
'config.hideNsfw', 'config.hideNsfw',
'config.replyVisibility', 'config.replyVisibility',
'config.notificationVisibility',
'config.autoLoad', 'config.autoLoad',
'config.hoverPreview', 'config.hoverPreview',
'config.streaming', 'config.streaming',

View file

@ -18,6 +18,12 @@ const defaultState = {
pauseOnUnfocused: true, pauseOnUnfocused: true,
stopGifs: false, stopGifs: false,
replyVisibility: 'all', replyVisibility: 'all',
notificationVisibility: {
follows: true,
mentions: true,
likes: true,
repeats: true
},
muteWords: [], muteWords: [],
highlight: {}, highlight: {},
interfaceLanguage: browserLocale interfaceLanguage: browserLocale

View file

@ -68,6 +68,15 @@ export const prepareStatus = (status) => {
return status return status
} }
const visibleNotificationTypes = (rootState) => {
return [
rootState.config.notificationVisibility.likes && 'like',
rootState.config.notificationVisibility.mentions && 'mention',
rootState.config.notificationVisibility.repeats && 'repeat',
rootState.config.notificationVisibility.follows && 'follow'
].filter(_ => _)
}
export const statusType = (status) => { export const statusType = (status) => {
if (status.is_post_verb) { if (status.is_post_verb) {
return 'status' return 'status'
@ -86,8 +95,7 @@ export const statusType = (status) => {
return 'deletion' return 'deletion'
} }
// TODO change to status.activity_type === 'follow' when gs supports it if (status.text.match(/started following/) || status.activity_type === 'follow') {
if (status.text.match(/started following/)) {
return 'follow' return 'follow'
} }
@ -269,7 +277,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us
} }
} }
const addNewNotifications = (state, { dispatch, notifications, older }) => { const addNewNotifications = (state, { dispatch, notifications, older, visibleNotificationTypes }) => {
const allStatuses = state.allStatuses const allStatuses = state.allStatuses
const allStatusesObject = state.allStatusesObject const allStatusesObject = state.allStatusesObject
each(notifications, (notification) => { each(notifications, (notification) => {
@ -318,7 +326,7 @@ const addNewNotifications = (state, { dispatch, notifications, older }) => {
result.image = action.attachments[0].url result.image = action.attachments[0].url
} }
if (fresh && !state.notifications.desktopNotificationSilence) { if (fresh && !state.notifications.desktopNotificationSilence && visibleNotificationTypes.includes(notification.ntype)) {
let notification = new window.Notification(title, result) let notification = new window.Notification(title, result)
// Chrome is known for not closing notifications automatically // Chrome is known for not closing notifications automatically
// according to MDN, anyway. // according to MDN, anyway.
@ -405,7 +413,7 @@ const statuses = {
commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser }) commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser })
}, },
addNewNotifications ({ rootState, commit, dispatch }, { notifications, older }) { addNewNotifications ({ rootState, commit, dispatch }, { notifications, older }) {
commit('addNewNotifications', { dispatch, notifications, older }) commit('addNewNotifications', { visibleNotificationTypes: visibleNotificationTypes(rootState), dispatch, notifications, older })
}, },
setError ({ rootState, commit }, { value }) { setError ({ rootState, commit }, { value }) {
commit('setError', { value }) commit('setError', { value })