From d3fb67bec3a00c0c743f9d3796c3ee000f444308 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Mon, 16 Sep 2019 22:36:24 -0700 Subject: [PATCH] feat: show unread follow requests on community page (#1493) * feat: show unread follow requests on community page fixes #477 * fixup * fixup --- src/routes/_actions/followRequests.js | 34 ++++++---- src/routes/_api/followRequests.js | 17 +++++ src/routes/_components/NavItem.html | 12 +++- src/routes/_database/meta.js | 8 +++ src/routes/_pages/community/index.html | 13 +++- src/routes/_pages/requests.html | 17 ++++- .../computations/timelineComputations.js | 10 +++ .../_store/observers/instanceObservers.js | 6 +- src/routes/_store/store.js | 1 + tests/serverActions.js | 2 +- tests/spec/116-follow-requests.js | 66 ++++++++++++++++--- 11 files changed, 153 insertions(+), 33 deletions(-) create mode 100644 src/routes/_api/followRequests.js diff --git a/src/routes/_actions/followRequests.js b/src/routes/_actions/followRequests.js index 0099644b..6d078e5e 100644 --- a/src/routes/_actions/followRequests.js +++ b/src/routes/_actions/followRequests.js @@ -1,17 +1,25 @@ -import { DEFAULT_TIMEOUT, get, post, WRITE_TIMEOUT } from '../_utils/ajax' -import { auth, basename } from '../_api/utils' +import { store } from '../_store/store' +import { cacheFirstUpdateAfter } from '../_utils/sync' +import { database } from '../_database/database' +import { getFollowRequests } from '../_api/followRequests' -export async function getFollowRequests (instanceName, accessToken) { - const url = `${basename(instanceName)}/api/v1/follow_requests` - return get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) -} +export async function updateFollowRequestCountIfLockedAccount (instanceName) { + const { verifyCredentials, loggedInInstances } = store.get() -export async function authorizeFollowRequest (instanceName, accessToken, id) { - const url = `${basename(instanceName)}/api/v1/follow_requests/${id}/authorize` - return post(url, null, auth(accessToken), { timeout: WRITE_TIMEOUT }) -} + if (!verifyCredentials[instanceName].locked) { + return + } -export async function rejectFollowRequest (instanceName, accessToken, id) { - const url = `${basename(instanceName)}/api/v1/follow_requests/${id}/reject` - return post(url, null, auth(accessToken), { timeout: WRITE_TIMEOUT }) + const accessToken = loggedInInstances[instanceName].access_token + + await cacheFirstUpdateAfter( + async () => (await getFollowRequests(instanceName, accessToken)).length, + () => database.getFollowRequestCount(instanceName), + followReqsCount => database.setFollowRequestCount(instanceName, followReqsCount), + followReqsCount => { + const { followRequestCounts } = store.get() + followRequestCounts[instanceName] = followReqsCount + store.set({ followRequestCounts }) + } + ) } diff --git a/src/routes/_api/followRequests.js b/src/routes/_api/followRequests.js new file mode 100644 index 00000000..7f6c87c5 --- /dev/null +++ b/src/routes/_api/followRequests.js @@ -0,0 +1,17 @@ +import { DEFAULT_TIMEOUT, get, post, WRITE_TIMEOUT } from '../_utils/ajax' +import { auth, basename } from './utils' + +export async function getFollowRequests (instanceName, accessToken) { + const url = `${basename(instanceName)}/api/v1/follow_requests` + return get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) +} + +export async function authorizeFollowRequest (instanceName, accessToken, id) { + const url = `${basename(instanceName)}/api/v1/follow_requests/${id}/authorize` + return post(url, null, auth(accessToken), { timeout: WRITE_TIMEOUT }) +} + +export async function rejectFollowRequest (instanceName, accessToken, id) { + const url = `${basename(instanceName)}/api/v1/follow_requests/${id}/reject` + return post(url, null, auth(accessToken), { timeout: WRITE_TIMEOUT }) +} diff --git a/src/routes/_components/NavItem.html b/src/routes/_components/NavItem.html index ed3e33dd..39ec22af 100644 --- a/src/routes/_components/NavItem.html +++ b/src/routes/_components/NavItem.html @@ -148,18 +148,24 @@ // special case – these should both highlight the notifications tab icon (name === 'notifications' && page === 'notifications/mentions') }, - ariaLabel: ({ selected, name, label, $numberOfNotifications }) => { + ariaLabel: ({ selected, name, label, $numberOfNotifications, $numberOfFollowRequests }) => { let res = label if (selected) { res += ' (current page)' } if (name === 'notifications' && $numberOfNotifications) { res += ` (${$numberOfNotifications} notification${$numberOfNotifications === 1 ? '' : 's'})` + } else if (name === 'community' && $numberOfFollowRequests) { + res += ` (${$numberOfFollowRequests} follow request${$numberOfFollowRequests === 1 ? '' : 's'})` } return res }, - showBadge: ({ name, $hasNotifications }) => name === 'notifications' && $hasNotifications, - badgeNumber: ({ name, $numberOfNotifications }) => name === 'notifications' && $numberOfNotifications + showBadge: ({ name, $hasNotifications, $hasFollowRequests }) => ( + (name === 'notifications' && $hasNotifications) || (name === 'community' && $hasFollowRequests) + ), + badgeNumber: ({ name, $numberOfNotifications, $numberOfFollowRequests }) => ( + (name === 'notifications' && $numberOfNotifications) || (name === 'community' && $numberOfFollowRequests) + ) }, methods: { onClick (e) { diff --git a/src/routes/_database/meta.js b/src/routes/_database/meta.js index 868db0f6..526ea3ef 100644 --- a/src/routes/_database/meta.js +++ b/src/routes/_database/meta.js @@ -55,3 +55,11 @@ export async function getCustomEmoji (instanceName) { export async function setCustomEmoji (instanceName, value) { return setMetaProperty(instanceName, 'customEmoji', value) } + +export async function getFollowRequestCount (instanceName) { + return getMetaProperty(instanceName, 'followRequestCount') +} + +export async function setFollowRequestCount (instanceName, value) { + return setMetaProperty(instanceName, 'followRequestCount', value) +} diff --git a/src/routes/_pages/community/index.html b/src/routes/_pages/community/index.html index e0e77cb8..237c01e0 100644 --- a/src/routes/_pages/community/index.html +++ b/src/routes/_pages/community/index.html @@ -53,7 +53,7 @@ {#if isLockedAccount} {/if} @@ -109,12 +109,16 @@ import PageList from '../../_components/community/PageList.html' import PageListItem from '../../_components/community/PageListItem.html' import { updateListsForInstance } from '../../_actions/lists' + import { updateFollowRequestCountIfLockedAccount } from '../../_actions/followRequests' export default { async oncreate () { const { currentInstance } = this.store.get() if (currentInstance) { - await updateListsForInstance(currentInstance) + await Promise.all([ + updateListsForInstance(currentInstance), + updateFollowRequestCountIfLockedAccount(currentInstance) + ]) } }, store: () => store, @@ -125,7 +129,10 @@ PageListItem }, computed: { - isLockedAccount: ({ $currentVerifyCredentials }) => $currentVerifyCredentials && $currentVerifyCredentials.locked + isLockedAccount: ({ $currentVerifyCredentials }) => $currentVerifyCredentials && $currentVerifyCredentials.locked, + followRequestsLabel: ({ $hasFollowRequests, $numberOfFollowRequests }) => ( + `Follow requests${$hasFollowRequests ? ` (${$numberOfFollowRequests})` : ''}` + ) } } diff --git a/src/routes/_pages/requests.html b/src/routes/_pages/requests.html index 5134160a..55655e8b 100644 --- a/src/routes/_pages/requests.html +++ b/src/routes/_pages/requests.html @@ -5,9 +5,18 @@