From c67be9acc2da19abd637d2dac8a0df9762c069f5 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Thu, 28 Apr 2022 08:18:50 -0700 Subject: [PATCH] fix: fix bell notifications, add tests --- bin/svgs.js | 2 + src/intl/en-US.js | 8 +- .../{notify.js => setAccountNotified.js} | 6 +- src/routes/_api/notify.js | 4 +- .../AccountProfileOptionsDialog.html | 28 +++++- .../components/StatusOptionsDialog.html | 29 +++++- .../_components/profile/AccountProfile.html | 8 +- .../profile/AccountProfileNotify.html | 92 ------------------- .../instance/NotificationFilterSettings.html | 8 +- .../instance/PushNotificationSettings.html | 4 + src/routes/_components/status/Status.html | 2 +- .../_components/status/StatusHeader.html | 4 + src/routes/_static/instanceSettings.js | 1 + .../timelineFilterComputations.js | 16 ++-- src/routes/_utils/createFilterFunction.js | 5 +- src/service-worker.js | 1 + tests/serverActions.js | 24 ++--- tests/spec/113-block-unblock.js | 11 +-- tests/spec/114-mute-unmute.js | 19 +--- tests/spec/139-notify-denotify.js | 49 ++++++++++ tests/utils.js | 8 ++ 21 files changed, 177 insertions(+), 152 deletions(-) rename src/routes/_actions/{notify.js => setAccountNotified.js} (83%) delete mode 100644 src/routes/_components/profile/AccountProfileNotify.html create mode 100644 tests/spec/139-notify-denotify.js diff --git a/bin/svgs.js b/bin/svgs.js index 0409f0fb..16d90adc 100644 --- a/bin/svgs.js +++ b/bin/svgs.js @@ -1,6 +1,7 @@ export default [ { id: 'pinafore-logo', src: 'src/static/sailboat.svg', inline: true }, { id: 'fa-bell', src: 'src/thirdparty/font-awesome-svg-png/white/svg/bell.svg', inline: true }, + { id: 'fa-bell-o', src: 'src/thirdparty/font-awesome-svg-png/white/svg/bell-o.svg' }, { id: 'fa-users', src: 'src/thirdparty/font-awesome-svg-png/white/svg/users.svg', inline: true }, { id: 'fa-globe', src: 'src/thirdparty/font-awesome-svg-png/white/svg/globe.svg' }, { id: 'fa-gear', src: 'src/thirdparty/font-awesome-svg-png/white/svg/gear.svg', inline: true }, @@ -22,6 +23,7 @@ export default [ { id: 'fa-user-plus', src: 'src/thirdparty/font-awesome-svg-png/white/svg/user-plus.svg' }, { id: 'fa-external-link', src: 'src/thirdparty/font-awesome-svg-png/white/svg/external-link.svg' }, { id: 'fa-search', src: 'src/thirdparty/font-awesome-svg-png/white/svg/search.svg', inline: true }, + { id: 'fa-comment', src: 'src/thirdparty/font-awesome-svg-png/white/svg/comment.svg' }, { id: 'fa-comments', src: 'src/thirdparty/font-awesome-svg-png/white/svg/comments.svg', inline: true }, { id: 'fa-paperclip', src: 'src/thirdparty/font-awesome-svg-png/white/svg/paperclip.svg' }, { id: 'fa-thumb-tack', src: 'src/thirdparty/font-awesome-svg-png/white/svg/thumb-tack.svg' }, diff --git a/src/intl/en-US.js b/src/intl/en-US.js index 297d1530..e0cb576d 100644 --- a/src/intl/en-US.js +++ b/src/intl/en-US.js @@ -309,10 +309,10 @@ export default { true {(follow requested)} other {} }`, - notifyLabel: `Subscribe`, - denotifyLabel: `Unsubscribe`, + notify: 'Subscribe to {account}', + denotify: 'Unsubscribe from {account}', subscribedAccount: 'Subscribed to account', - unsubscribedAccount: 'Unsubscribed to account', + unsubscribedAccount: 'Unsubscribed from account', unblock: 'Unblock', nameAndFollowing: 'Name and following', clickToSeeAvatar: 'Click to see avatar', @@ -474,6 +474,7 @@ export default { newFollowers: 'New followers', reblogs: 'Boosts', pollResults: 'Poll results', + subscriptions: 'Subscribed toots', needToReauthenticate: 'You need to reauthenticate in order to enable push notification. Log out of {instance}?', failedToUpdatePush: 'Failed to update push notification settings: {error}', // Themes @@ -508,6 +509,7 @@ export default { rebloggedYou: 'boosted your toot', favoritedYou: 'favorited your toot', followedYou: 'followed you', + posted: 'posted', pollYouCreatedEnded: 'A poll you created has ended', pollYouVotedEnded: 'A poll you voted on has ended', reblogged: 'boosted', diff --git a/src/routes/_actions/notify.js b/src/routes/_actions/setAccountNotified.js similarity index 83% rename from src/routes/_actions/notify.js rename to src/routes/_actions/setAccountNotified.js index 383182b0..f962825d 100644 --- a/src/routes/_actions/notify.js +++ b/src/routes/_actions/setAccountNotified.js @@ -4,7 +4,7 @@ import { toast } from '../_components/toast/toast.js' import { updateLocalRelationship } from './accounts.js' import { formatIntl } from '../_utils/formatIntl.js' -export async function setAccountNotify (accountId, notify, toastOnSuccess) { +export async function setAccountNotified (accountId, notify, toastOnSuccess) { const { currentInstance, accessToken } = store.get() try { let relationship @@ -15,11 +15,11 @@ export async function setAccountNotify (accountId, notify, toastOnSuccess) { } await updateLocalRelationship(currentInstance, accountId, relationship) if (toastOnSuccess) { - /* no await */ toast.say(follow ? 'intl.subscribedAccount' : 'intl.unsubscribedAccount') + /* no await */ toast.say(notify ? 'intl.subscribedAccount' : 'intl.unsubscribedAccount') } } catch (e) { console.error(e) - /* no await */ toast.say(follow + /* no await */ toast.say(notify ? formatIntl('intl.unableToSubscribe', { error: (e.message || '') }) : formatIntl('intl.unableToUnsubscribe', { error: (e.message || '') }) ) diff --git a/src/routes/_api/notify.js b/src/routes/_api/notify.js index e06fbb8b..8871120b 100644 --- a/src/routes/_api/notify.js +++ b/src/routes/_api/notify.js @@ -4,13 +4,13 @@ import { auth, basename } from './utils.js' export async function notifyAccount (instanceName, accessToken, accountId) { const url = `${basename(instanceName)}/api/v1/accounts/${accountId}/follow` return post(url, { - "notify": true, + notify: true }, auth(accessToken), { timeout: WRITE_TIMEOUT }) } export async function denotifyAccount (instanceName, accessToken, accountId) { const url = `${basename(instanceName)}/api/v1/accounts/${accountId}/follow` return post(url, { - "notify": false + notify: false }, auth(accessToken), { timeout: WRITE_TIMEOUT }) } diff --git a/src/routes/_components/dialog/components/AccountProfileOptionsDialog.html b/src/routes/_components/dialog/components/AccountProfileOptionsDialog.html index c369083d..5b44f64f 100644 --- a/src/routes/_components/dialog/components/AccountProfileOptionsDialog.html +++ b/src/routes/_components/dialog/components/AccountProfileOptionsDialog.html @@ -23,6 +23,7 @@ import { composeNewStatusMentioning } from '../../../_actions/mention.js' import { toggleMute } from '../../../_actions/toggleMute.js' import { reportStatusOrAccount } from '../../../_actions/report.js' import { formatIntl } from '../../../_utils/formatIntl.js' +import { setAccountNotified } from '../../../_actions/setAccountNotified.js' export default { oncreate, @@ -39,6 +40,7 @@ export default { username: ({ account }) => account.username, muting: ({ relationship }) => relationship && relationship.muting, blocking: ({ relationship }) => relationship && relationship.blocking, + notifying: ({ relationship }) => relationship && relationship.notifying, followLabel: ({ following, followRequested, account, username }) => { if (typeof following === 'undefined' || !account) { return '' @@ -86,7 +88,7 @@ export default { blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon, following, followRequested, accountId, verifyCredentialsId, username, isUser, showReblogsLabel, - domain, blockDomainLabel, reportLabel + domain, blockDomainLabel, reportLabel, notifying }) => ([ !isUser && { key: 'mention', @@ -98,6 +100,16 @@ export default { label: followLabel, icon: followIcon }, + !isUser && following && notifying === false && { // notifying could be undefined for old servers + key: 'notify', + label: formatIntl('intl.notify', { account: `@${username}` }), + icon: '#fa-bell' + }, + !isUser && following && notifying === true && { // notifying could be undefined for old servers + key: 'denotify', + label: formatIntl('intl.denotify', { account: `@${username}` }), + icon: '#fa-bell-o' + }, !isUser && { key: 'block', label: blockLabel, @@ -151,6 +163,10 @@ export default { return this.onCopyClicked() case 'report': return this.onReport() + case 'notify': + return this.onNotifyClicked() + case 'denotify': + return this.onDenotifyClicked() } }, async onMentionClicked () { @@ -193,6 +209,16 @@ export default { const { account } = this.get() this.close() await reportStatusOrAccount({ account }) + }, + async onNotifyClicked () { + const { accountId } = this.get() + this.close() + await setAccountNotified(accountId, /* notify */ true, /* toastOnSuccess */ true) + }, + async onDenotifyClicked () { + const { accountId } = this.get() + this.close() + await setAccountNotified(accountId, /* notify */ false, /* toastOnSuccess */ true) } }, components: { diff --git a/src/routes/_components/dialog/components/StatusOptionsDialog.html b/src/routes/_components/dialog/components/StatusOptionsDialog.html index d5b05088..d187652d 100644 --- a/src/routes/_components/dialog/components/StatusOptionsDialog.html +++ b/src/routes/_components/dialog/components/StatusOptionsDialog.html @@ -26,6 +26,7 @@ import { shareStatus } from '../../../_actions/share.js' import { toggleMute } from '../../../_actions/toggleMute.js' import { reportStatusOrAccount } from '../../../_actions/report.js' import { formatIntl } from '../../../_utils/formatIntl.js' +import { setAccountNotified } from '../../../_actions/setAccountNotified.js' export default { oncreate, @@ -53,6 +54,7 @@ export default { username: ({ account }) => account.username, muting: ({ relationship }) => relationship.muting, blocking: ({ relationship }) => relationship.blocking, + notifying: ({ relationship }) => relationship && relationship.notifying, followLabel: ({ following, followRequested, account, username }) => { if (typeof following === 'undefined' || !account) { return '' @@ -96,7 +98,8 @@ export default { items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon, following, followRequested, pinLabel, isUser, visibility, mentionsUser, mutingConversation, - muteConversationLabel, muteConversationIcon, supportsWebShare, isPublicOrUnlisted, bookmarkLabel + muteConversationLabel, muteConversationIcon, supportsWebShare, isPublicOrUnlisted, bookmarkLabel, + username, notifying }) => ([ isUser && { key: 'delete', @@ -113,6 +116,16 @@ export default { label: followLabel, icon: followIcon }, + !isUser && following && notifying === false && { // notifying could be undefined for old servers + key: 'notify', + label: formatIntl('intl.notify', { account: `@${username}` }), + icon: '#fa-bell' + }, + !isUser && following && notifying === true && { // notifying could be undefined for old servers + key: 'denotify', + label: formatIntl('intl.denotify', { account: `@${username}` }), + icon: '#fa-bell-o' + }, !isUser && { key: 'block', label: blockLabel, @@ -187,6 +200,10 @@ export default { return this.onReport() case 'bookmark': return this.onBookmark() + case 'notify': + return this.onNotifyClicked() + case 'denotify': + return this.onDenotifyClicked() } }, async onDeleteClicked () { @@ -244,6 +261,16 @@ export default { const { status } = this.get() this.close() await setStatusBookmarkedOrUnbookmarked(status.id, !status.bookmarked) + }, + async onNotifyClicked () { + const { accountId } = this.get() + this.close() + await setAccountNotified(accountId, /* notify */ true, /* toastOnSuccess */ true) + }, + async onDenotifyClicked () { + const { accountId } = this.get() + this.close() + await setAccountNotified(accountId, /* notify */ false, /* toastOnSuccess */ true) } } } diff --git a/src/routes/_components/profile/AccountProfile.html b/src/routes/_components/profile/AccountProfile.html index 0a2f5c12..19323172 100644 --- a/src/routes/_components/profile/AccountProfile.html +++ b/src/routes/_components/profile/AccountProfile.html @@ -8,7 +8,6 @@