diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index fe5b701840..c86f22bb91 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -21,6 +21,9 @@ const Notification = { }, userProfileLink (user) { return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames) + }, + dismiss () { + this.$store.dispatch('dismissNotifications', { id: this.notification.id }) } }, computed: { diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 5e9cef97d5..b281c7cfa6 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -1,44 +1,57 @@ + + \ No newline at end of file diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 9fc5e38a28..68004d5434 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -53,7 +53,10 @@ const Notifications = { }, methods: { markAsSeen () { - this.$store.dispatch('markNotificationsAsSeen', this.visibleNotifications) + this.$store.dispatch('markNotificationsAsSeen') + }, + clear () { + this.$store.dispatch('clearNotifications') }, fetchOlderNotifications () { const store = this.$store diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue index 6f162b625f..6438361d84 100644 --- a/src/components/notifications/notifications.vue +++ b/src/components/notifications/notifications.vue @@ -9,7 +9,8 @@
{{$t('timeline.error_fetching')}}
- + +
diff --git a/src/i18n/en.json b/src/i18n/en.json index 01fe2fba21..38abfaf52a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -62,6 +62,8 @@ "load_older": "Load older notifications", "notifications": "Notifications", "read": "Read!", + "clear": "Clear!", + "dismiss": "Dismiss!", "repeated_you": "repeated your status", "no_more_notifications": "No more notifications" }, diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 6b512fa372..fde783a5c5 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -1,4 +1,4 @@ -import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray } from 'lodash' +import { remove, slice, each, find, findIndex, maxBy, minBy, merge, first, last, isArray } from 'lodash' import apiService from '../services/api/api.service.js' // import parse from '../services/status_parser/status_parser.js' @@ -390,6 +390,27 @@ export const mutations = { notification.seen = true }) }, + clearNotifications (state) { + state.notifications.data = [] + state.notifications.idStore = {} + state.notifications.maxId = 0 + state.notifications.minId = 0 + }, + dismissNotifications (state, { id }) { + const { data } = state.notifications + const idx = findIndex(data, { id }) + + if (idx !== -1) { + const notification = data[idx] + data.splice(idx, 1) + delete state.notifications.idStore[id] + if (state.notifications.maxId === notification.id) { + state.notifications.maxId = data.length ? maxBy(data, 'id').id : 0 + } else if (state.notifications.minId === notification.id) { + state.notifications.minId = data.length ? minBy(data, 'id').id : 0 + } + } + }, queueFlush (state, { timeline, id }) { state.timelines[timeline].flushMarker = id } @@ -474,6 +495,19 @@ const statuses = { id: rootState.statuses.notifications.maxId, credentials: rootState.users.currentUser.credentials }) + }, + clearNotifications ({ rootState, commit }) { + commit('clearNotifications') + apiService.clearNotifications({ + credentials: rootState.users.currentUser.credentials + }) + }, + dismissNotifications ({ rootState, commit }, { id }) { + commit('dismissNotifications', { id }) + apiService.dismissNotifications({ + id, + credentials: rootState.users.currentUser.credentials + }) } }, mutations diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 2de87026e6..9d3139ce4c 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -29,7 +29,6 @@ const BANNER_UPDATE_URL = '/api/account/update_profile_banner.json' const PROFILE_UPDATE_URL = '/api/account/update_profile.json' const EXTERNAL_PROFILE_URL = '/api/externalprofile/show.json' const QVITTER_USER_TIMELINE_URL = '/api/qvitter/statuses/user_timeline.json' -const QVITTER_USER_NOTIFICATIONS_URL = '/api/qvitter/statuses/notifications.json' const QVITTER_USER_NOTIFICATIONS_READ_URL = '/api/qvitter/statuses/notifications/read.json' const BLOCKING_URL = '/api/blocks/create.json' const UNBLOCKING_URL = '/api/blocks/destroy.json' @@ -43,6 +42,9 @@ const DENY_USER_URL = '/api/pleroma/friendships/deny' const SUGGESTIONS_URL = '/api/v1/suggestions' const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites' +const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications' +const MASTODON_USER_NOTIFICATIONS_CLEAR_URL = '/api/v1/notifications/clear' +const MASTODON_USER_NOTIFICATIONS_DISMISS_URL = '/api/v1/notifications/dismiss' import { each, map } from 'lodash' import { parseStatus, parseUser, parseNotification } from '../entity_normalizer/entity_normalizer.service.js' @@ -345,7 +347,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use friends: FRIENDS_TIMELINE_URL, mentions: MENTIONS_URL, dms: DM_TIMELINE_URL, - notifications: QVITTER_USER_NOTIFICATIONS_URL, + notifications: MASTODON_USER_NOTIFICATIONS_URL, 'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL, user: QVITTER_USER_TIMELINE_URL, media: QVITTER_USER_TIMELINE_URL, @@ -575,6 +577,25 @@ const markNotificationsAsSeen = ({id, credentials}) => { }).then((data) => data.json()) } +const clearNotifications = ({ credentials }) => { + return fetch(MASTODON_USER_NOTIFICATIONS_CLEAR_URL, { + headers: authHeaders(credentials), + method: 'POST' + }).then((data) => data.json()) +} + +const dismissNotifications = ({ id, credentials }) => { + const body = new FormData() + + body.append('id', id) + + return fetch(MASTODON_USER_NOTIFICATIONS_DISMISS_URL, { + body, + headers: authHeaders(credentials), + method: 'POST' + }).then((data) => data.json()) +} + const apiService = { verifyCredentials, fetchTimeline, @@ -615,7 +636,9 @@ const apiService = { approveUser, denyUser, suggestions, - markNotificationsAsSeen + markNotificationsAsSeen, + clearNotifications, + dismissNotifications } export default apiService diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index d20ce77f77..81b88bf051 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -249,6 +249,18 @@ export const parseStatus = (data) => { return output } +export const parseFollow = (data) => { + const output = {} + output.id = String(data.id) + output.visibility = true + output.created_at = new Date(data.created_at) + + // Converting to string, the right way. + output.user = parseUser(data.account) + + return output +} + export const parseNotification = (data) => { const mastoDict = { 'favourite': 'like', @@ -260,7 +272,9 @@ export const parseNotification = (data) => { if (masto) { output.type = mastoDict[data.type] || data.type output.seen = null // missing - output.status = parseStatus(data.status) + output.status = output.type === 'follow' + ? parseFollow(data) + : parseStatus(data.status) output.action = output.status // not sure output.from_profile = parseUser(data.account) } else {