diff --git a/src/routes/_actions/streaming.js b/src/routes/_actions/streaming.js index 829dbe2..0476f85 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 bb7f455..addd0da 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 066f92d..2c50cd0 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 0000000..bdcfd80 --- /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 0000000..ca56341 --- /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 49c291e..3223bdb 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 dd04852..3e54586 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 3cfdae5..c011c29 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 4dc7c4a..c87db6f 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}