diff --git a/src/routes/_actions/streaming.js b/src/routes/_actions/streaming.js
index 829dbe2d..0476f857 100644
--- a/src/routes/_actions/streaming.js
+++ b/src/routes/_actions/streaming.js
@@ -6,15 +6,22 @@ import { addStatusOrNotification } from './addStatusOrNotification'
function processMessage (instanceName, timelineName, message) {
mark('processMessage')
let { event, payload } = message
+ if (['update', 'notification', 'conversation'].includes(event)) {
+ payload = JSON.parse(payload) // only these payloads are JSON-encoded for some reason
+ }
+
switch (event) {
case 'delete':
deleteStatus(instanceName, payload)
break
case 'update':
- addStatusOrNotification(instanceName, timelineName, JSON.parse(payload))
+ addStatusOrNotification(instanceName, timelineName, payload)
break
case 'notification':
- addStatusOrNotification(instanceName, 'notifications', JSON.parse(payload))
+ addStatusOrNotification(instanceName, 'notifications', payload)
+ if (payload.type === 'mention') {
+ addStatusOrNotification(instanceName, 'notifications/mentions', payload)
+ }
break
case 'conversation':
// This is a hack in order to mostly fit the conversation model into
@@ -22,7 +29,7 @@ function processMessage (instanceName, timelineName, message) {
// reproduce what is done for statuses for the conversation.
//
// It will add new DMs as new conversations instead of updating existing threads
- addStatusOrNotification(instanceName, timelineName, JSON.parse(payload).last_status)
+ addStatusOrNotification(instanceName, timelineName, payload.last_status)
break
}
stop('processMessage')
diff --git a/src/routes/_api/timelines.js b/src/routes/_api/timelines.js
index bb7f455d..addd0da0 100644
--- a/src/routes/_api/timelines.js
+++ b/src/routes/_api/timelines.js
@@ -9,6 +9,7 @@ function getTimelineUrlPath (timeline) {
case 'home':
return 'timelines/home'
case 'notifications':
+ case 'notifications/mentions':
return 'notifications'
case 'favorites':
return 'favourites'
@@ -61,6 +62,10 @@ export async function getTimeline (instanceName, accessToken, timeline, maxId, s
}
}
+ if (timeline === 'notifications/mentions') {
+ params.exclude_types = ['follow', 'favourite', 'reblog', 'poll']
+ }
+
url += '?' + paramsString(params)
const items = await get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT })
diff --git a/src/routes/_components/NavItem.html b/src/routes/_components/NavItem.html
index 066f92d2..2c50cd08 100644
--- a/src/routes/_components/NavItem.html
+++ b/src/routes/_components/NavItem.html
@@ -146,7 +146,11 @@
},
store: () => store,
computed: {
- selected: ({ page, name }) => page === name,
+ selected: ({ page, name }) => {
+ return page === name ||
+ // special case – these should both highlight the notifications tab icon
+ (name === 'notifications' && page === 'notifications/mentions')
+ },
ariaLabel: ({ selected, name, label, $numberOfNotifications }) => {
let res = label
if (selected) {
diff --git a/src/routes/_components/NotificationFilters.html b/src/routes/_components/NotificationFilters.html
new file mode 100644
index 00000000..bdcfd806
--- /dev/null
+++ b/src/routes/_components/NotificationFilters.html
@@ -0,0 +1,29 @@
+
+
diff --git a/src/routes/_components/TabSet.html b/src/routes/_components/TabSet.html
new file mode 100644
index 00000000..ca563410
--- /dev/null
+++ b/src/routes/_components/TabSet.html
@@ -0,0 +1,89 @@
+
+
+
diff --git a/src/routes/_components/profile/AccountProfileFilters.html b/src/routes/_components/profile/AccountProfileFilters.html
index 49c291ec..3223bdba 100644
--- a/src/routes/_components/profile/AccountProfileFilters.html
+++ b/src/routes/_components/profile/AccountProfileFilters.html
@@ -1,107 +1,36 @@
-
-
+
diff --git a/src/routes/_database/timelines/insertion.js b/src/routes/_database/timelines/insertion.js
index dd04852e..3e545862 100644
--- a/src/routes/_database/timelines/insertion.js
+++ b/src/routes/_database/timelines/insertion.js
@@ -111,7 +111,7 @@ async function insertStatusThread (instanceName, statusId, statuses) {
export async function insertTimelineItems (instanceName, timeline, timelineItems) {
/* no await */ scheduleCleanup()
- if (timeline === 'notifications') {
+ if (timeline === 'notifications' || timeline === 'notifications/mentions') {
return insertTimelineNotifications(instanceName, timeline, timelineItems)
} else if (timeline.startsWith('status/')) {
let statusId = timeline.split('/').slice(-1)[0]
diff --git a/src/routes/_database/timelines/pagination.js b/src/routes/_database/timelines/pagination.js
index 3cfdae59..c011c299 100644
--- a/src/routes/_database/timelines/pagination.js
+++ b/src/routes/_database/timelines/pagination.js
@@ -84,7 +84,7 @@ async function getStatusThread (instanceName, statusId) {
export async function getTimeline (instanceName, timeline, maxId, limit) {
maxId = maxId || null
limit = limit || TIMELINE_BATCH_SIZE
- if (timeline === 'notifications') {
+ if (timeline === 'notifications' || timeline === 'notifications/mentions') {
return getNotificationTimeline(instanceName, timeline, maxId, limit)
} else if (timeline.startsWith('status/')) {
let statusId = timeline.split('/').slice(-1)[0]
diff --git a/src/routes/_pages/community/index.html b/src/routes/_pages/community/index.html
index 4dc7c4ac..c87db6fc 100644
--- a/src/routes/_pages/community/index.html
+++ b/src/routes/_pages/community/index.html
@@ -90,6 +90,7 @@
Federated
Favorites
Conversations
+ Notification mentions
{/if}