From 2bae1864bd78a3d39918a2f09985e2f92021961e Mon Sep 17 00:00:00 2001 From: Ed Sanders Date: Mon, 6 Feb 2023 15:29:28 +0000 Subject: [PATCH] New topic notifications Bug: T263821 Change-Id: Ied465e732122a1ee39ab4510f73aca11ef556c35 --- extension.json | 4 + i18n/en.json | 11 ++- i18n/qqq.json | 9 +++ includes/Hooks/EchoHooks.php | 15 ++++ .../AddedTopicPresentationModel.php | 73 +++++++++++++++++++ .../SubscribedNewCommentPresentationModel.php | 19 ++++- includes/TopicSubscriptionsPager.php | 10 ++- modules/topicsubscriptions.js | 27 +++++-- 8 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 includes/Notifications/AddedTopicPresentationModel.php diff --git a/extension.json b/extension.json index 6737db2ff..a0d130444 100644 --- a/extension.json +++ b/extension.json @@ -123,6 +123,10 @@ "discussiontools-newtopic-legacy-hint", "discussiontools-newtopic-placeholder-title", "discussiontools-newtopic-missing-title", + "discussiontools-newtopicssubscription-notify-subscribed-body", + "discussiontools-newtopicssubscription-notify-subscribed-title", + "discussiontools-newtopicssubscription-notify-unsubscribed-body", + "discussiontools-newtopicssubscription-notify-unsubscribed-title", "discussiontools-pagetitle-newtopic", "discussiontools-pagetitle-reply", "discussiontools-replylink", diff --git a/i18n/en.json b/i18n/en.json index 7f02cce5e..9aec1133b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -53,6 +53,14 @@ "discussiontools-newtopic-legacy-hint-return": "You are now viewing the legacy experience. You can [$1 return to the new experience] or visit preferences to [$2 set the legacy experience as your default].", "discussiontools-newtopic-missing-title": "Please provide a title for your discussion topic. If you click \"{{int:discussiontools-replywidget-newtopic}}\", your topic will be added without a title.", "discussiontools-newtopic-placeholder-title": "Subject", + "discussiontools-newtopicssubscription-notify-subscribed-body": "You will receive notifications when new topics are started on this page.", + "discussiontools-newtopicssubscription-notify-subscribed-title": "You have subscribed!", + "discussiontools-newtopicssubscription-notify-unsubscribed-body": "You will no longer receive notifications when new topics are started on this page.", + "discussiontools-newtopicssubscription-notify-unsubscribed-title": "You have unsubscribed.", + "discussiontools-notification-added-topic-header": "New topic \"$4\" created on $3 by $2.", + "discussiontools-notification-added-topic-header-bundled": "{{PLURAL:$1|One new topic|$1 new topics|100=99+ new topics}} on \"$2\".", + "discussiontools-notification-added-topic-header-compact": "$3: $4", + "discussiontools-notification-added-topic-view": "View topic", "discussiontools-notification-removed-topic-body": "You might no longer receive notifications about {{PLURAL:$1|this topic|these topics}}.", "discussiontools-notification-removed-topic-header": "Topic \"$4\" was archived or removed from $3.", "discussiontools-notification-removed-topic-header-bundled": "{{PLURAL:$1|One topic was|$1 topics were|100=99+ topics were}} archived or removed from $2.", @@ -144,7 +152,7 @@ "discussiontools-topicsubscription-button-subscribe-tooltip": "Subscribe to receive notifications about new comments.", "discussiontools-topicsubscription-button-unsubscribe": "unsubscribe", "discussiontools-topicsubscription-button-unsubscribe-label": "Unsubscribe", - "discussiontools-topicsubscription-button-unsubscribe-tooltip": "Unsubscribe to stop receiving notifications.", + "discussiontools-topicsubscription-button-unsubscribe-tooltip": "Unsubscribe to stop receiving notifications about new comments.", "discussiontools-topicsubscription-error-not-found-body": "The subscription specified in the URL was not found.", "discussiontools-topicsubscription-error-not-found-title": "Subscription not found", "discussiontools-topicsubscription-notify-subscribed-body": "You will receive notifications about new comments in this topic.", @@ -153,6 +161,7 @@ "discussiontools-topicsubscription-notify-unsubscribed-title": "You have unsubscribed.", "discussiontools-topicsubscription-pager-actions": "Actions", "discussiontools-topicsubscription-pager-created": "First subscribed", + "discussiontools-topicsubscription-pager-newtopics-label": "New topics", "discussiontools-topicsubscription-pager-notified": "Latest notification", "discussiontools-topicsubscription-pager-notified-never": "never", "discussiontools-topicsubscription-pager-page": "Page", diff --git a/i18n/qqq.json b/i18n/qqq.json index a5320c384..2cfe16d6a 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -67,6 +67,10 @@ "discussiontools-newtopic-legacy-hint-return": "Message shown on the legacy section adding tool", "discussiontools-newtopic-missing-title": "Warning message shown when leaving the title field empty while adding a new topic to the page.\n\nCopy {{int:discussiontools-replywidget-newtopic}} into your translation. It will be shown as {{msg-mw|discussiontools-replywidget-newtopic}}", "discussiontools-newtopic-placeholder-title": "Placeholder describing the heading field of a new topic\n{{identical|Subject}}", + "discussiontools-newtopicssubscription-notify-subscribed-body": "Body of notification shown when a user subscribes to notifications about new topics on this page.", + "discussiontools-newtopicssubscription-notify-subscribed-title": "Title of notification shown when a user subscribes to notifications about new topics on this page.", + "discussiontools-newtopicssubscription-notify-unsubscribed-body": "Body of notification shown when a user unsubscribes from notifications about new topics on this page.", + "discussiontools-newtopicssubscription-notify-unsubscribed-title": "Title of notification shown when a user unsubscribes from notifications about new topics on this page.", "discussiontools-notification-removed-topic-body": "Notification body text for when multiple topics were removed from a page.\n\nFollows {{msg-mw|discussiontools-notification-removed-topic-header}} or {{msg-mw|discussiontools-notification-removed-topic-header-bundled}}.\n\nParameters:\n* $1 - the number of topics removed", "discussiontools-notification-removed-topic-header": "Notification header text for when a topic was removed from a page. Parameters:\n* $1 - the formatted username of the user who replied to the topic (unused)\n* $2 - the username for gender purposes (unused)\n* $3 - title of the page\n* $4 - title of the topic", "discussiontools-notification-removed-topic-header-bundled": "Notification header text for when multiple topics were removed from a page. Parameters:\n* $1 - the number of topics removed\n* $2 - title of the page", @@ -159,6 +163,10 @@ "discussiontools-topicsubscription-button-unsubscribe": "Label for the unsubscribe link added to each section. Use the same casing as section edit links.\nAppears in the same area as:\n* {{msg-mw|editsection}}\n* {{msg-mw|visualeditor-ca-editsource-section}}\n* {{msg-mw|discussiontools-topicsubscription-button-subscribe}}\n* {{msg-mw|discussiontools-replylink}}", "discussiontools-topicsubscription-button-unsubscribe-label": "Label for the unsubscribe link added to each section. Use title case like normal buttons.", "discussiontools-topicsubscription-button-unsubscribe-tooltip": "Tooltip for the unsubscribe link added to each section.", + "discussiontools-notification-added-topic-header": "Notification header for when a new topic has been started on a page.", + "discussiontools-notification-added-topic-header-bundled": "Notification header for when multiple new topics have been started on a page.", + "discussiontools-notification-added-topic-header-compact": "Notification compact header for when a new topic has been started on a page.", + "discussiontools-notification-added-topic-view": "Label for button to view topic that was just posted.", "discussiontools-topicsubscription-error-not-found-body": "Body of error page shown when subscription not found.", "discussiontools-topicsubscription-error-not-found-title": "Title of error page shown when subscription not found.", "discussiontools-topicsubscription-notify-subscribed-body": "Body of notification shown when a user subscribes to a topic.", @@ -167,6 +175,7 @@ "discussiontools-topicsubscription-notify-unsubscribed-title": "Title of notification shown when a user unsubscribes from a topic.", "discussiontools-topicsubscription-pager-actions": "Used on [[mw:Special:TopicSubscriptions|Special:TopicSubscriptions]] as a table heading.\n{{identical|Action}}", "discussiontools-topicsubscription-pager-created": "Date of first subscription.\n\nUsed on [[mw:Special:TopicSubscriptions|Special:TopicSubscriptions]] as a table heading.", + "discussiontools-topicsubscription-pager-newtopics-label": "Label for a subscription to new topics on a page.", "discussiontools-topicsubscription-pager-notified": "Date of latest notification.\n\nUsed on [[mw:Special:TopicSubscriptions|Special:TopicSubscriptions]] as a table heading.", "discussiontools-topicsubscription-pager-notified-never": "Used on [[mw:Special:TopicSubscriptions|Special:TopicSubscriptions]] in the table. It means that a notification about a topic was never sent.\n{{identical|Never}}", "discussiontools-topicsubscription-pager-page": "Used on [[mw:Special:TopicSubscriptions|Special:TopicSubscriptions]] as a table heading.", diff --git a/includes/Hooks/EchoHooks.php b/includes/Hooks/EchoHooks.php index ebbbb3eed..dbeae0176 100644 --- a/includes/Hooks/EchoHooks.php +++ b/includes/Hooks/EchoHooks.php @@ -74,6 +74,21 @@ class EchoHooks { 'expandable' => true, ], ]; + $notifications['dt-added-topic'] = [ + 'category' => 'dt-subscription', + 'group' => 'interactive', + 'section' => 'message', + 'user-locators' => [ + 'MediaWiki\\Extension\\DiscussionTools\\Notifications\\EventDispatcher::locateSubscribedUsers' + ], + 'presentation-model' => + 'MediaWiki\\Extension\\DiscussionTools\\Notifications\\AddedTopicPresentationModel', + 'bundle' => [ + 'web' => true, + 'email' => true, + 'expandable' => true, + ], + ]; // Override default handlers $notifications['edit-user-talk']['presentation-model'] = diff --git a/includes/Notifications/AddedTopicPresentationModel.php b/includes/Notifications/AddedTopicPresentationModel.php new file mode 100644 index 000000000..9eba69a7d --- /dev/null +++ b/includes/Notifications/AddedTopicPresentationModel.php @@ -0,0 +1,73 @@ + $this->getCommentLink() ?: $this->section->getTitleWithSection()->getFullURL(), + 'label' => $this->msg( 'discussiontools-notification-added-topic-view' )->text() + ]; + } + + /** + * @inheritDoc + */ + protected function getHeaderMessageKey() { + if ( $this->isBundled() ) { + return 'discussiontools-notification-added-topic-header-bundled'; + } else { + return 'discussiontools-notification-added-topic-header'; + } + } + + /** + * @inheritDoc + */ + public function getHeaderMessage() { + if ( $this->isBundled() ) { + $count = $this->getNotificationCountForOutput(); + $msg = $this->msg( $this->getHeaderMessageKey() ); + + $msg->numParams( $count ); + $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) ); + return $msg; + } else { + $msg = parent::getHeaderMessage(); + $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) ); + $msg->plaintextParams( $this->section->getTruncatedSectionTitle() ); + return $msg; + } + } + + /** + * @inheritDoc + */ + public function getCompactHeaderMessage() { + $msg = $this->getMessageWithAgent( 'discussiontools-notification-added-topic-header-compact' ); + $msg->plaintextParams( $this->section->getTruncatedSectionTitle() ); + $msg->plaintextParams( $this->getContentSnippet() ); + return $msg; + } + + /** + * @inheritDoc + */ + protected function getUnsubscribeConfirmationMessageKeys() { + return [ + 'title' => 'discussiontools-newtopicssubscription-notify-unsubscribed-title', + 'description' => 'discussiontools-newtopicssubscription-notify-unsubscribed-body', + ]; + } +} diff --git a/includes/Notifications/SubscribedNewCommentPresentationModel.php b/includes/Notifications/SubscribedNewCommentPresentationModel.php index 19cdc7ad6..bbf4962b3 100644 --- a/includes/Notifications/SubscribedNewCommentPresentationModel.php +++ b/includes/Notifications/SubscribedNewCommentPresentationModel.php @@ -50,7 +50,7 @@ class SubscribedNewCommentPresentationModel extends EchoEventPresentationModel { */ public function getPrimaryLink() { return [ - 'url' => $this->getCommentLink() ?: $this->event->getTitle()->getFullURL(), + 'url' => $this->getCommentLink() ?: $this->section->getTitleWithSection()->getFullURL(), 'label' => $this->msg( 'discussiontools-notification-subscribed-new-comment-view' )->text() ]; } @@ -150,6 +150,7 @@ class SubscribedNewCommentPresentationModel extends EchoEventPresentationModel { $isSubscribed = count( $items ) && !$items[0]->isMuted(); if ( $isSubscribed ) { $commentName = $this->event->getExtraParam( 'subscribed-comment-name' ); + $messageKeys = $this->getUnsubscribeConfirmationMessageKeys(); $links[] = $this->getDynamicActionLink( $this->event->getTitle(), 'bellOutline', @@ -165,8 +166,8 @@ class SubscribedNewCommentPresentationModel extends EchoEventPresentationModel { ], 'messages' => [ 'confirmation' => [ - 'title' => $this->msg( 'discussiontools-topicsubscription-notify-unsubscribed-title' ), - 'description' => $this->msg( 'discussiontools-topicsubscription-notify-unsubscribed-body' ) + 'title' => $this->msg( $messageKeys[ 'title' ] ), + 'description' => $this->msg( $messageKeys[ 'description' ] ), ] ] ], @@ -179,4 +180,16 @@ class SubscribedNewCommentPresentationModel extends EchoEventPresentationModel { return $links; } + + /** + * Get message keys for the unsubscribe confirmation popup + * + * @return array Array with 'title' and 'description' keys + */ + protected function getUnsubscribeConfirmationMessageKeys() { + return [ + 'title' => 'discussiontools-topicsubscription-notify-unsubscribed-title', + 'description' => 'discussiontools-topicsubscription-notify-unsubscribed-body', + ]; + } } diff --git a/includes/TopicSubscriptionsPager.php b/includes/TopicSubscriptionsPager.php index 5fb01e29d..b501e91c1 100644 --- a/includes/TopicSubscriptionsPager.php +++ b/includes/TopicSubscriptionsPager.php @@ -73,8 +73,14 @@ class TopicSubscriptionsPager extends TablePager { switch ( $field ) { case '_topic': - $titleSection = Title::makeTitleSafe( $row->sub_namespace, $row->sub_title, $row->sub_section ); - return $linkRenderer->makeLink( $titleSection, $row->sub_section ); + if ( str_starts_with( $row->sub_item, 'p-topics-' ) ) { + return '' . + $this->msg( 'discussiontools-topicsubscription-pager-newtopics-label' )->escaped() . + ''; + } else { + $titleSection = Title::makeTitleSafe( $row->sub_namespace, $row->sub_title, $row->sub_section ); + return $linkRenderer->makeLink( $titleSection, $row->sub_section ); + } case '_page': $title = Title::makeTitleSafe( $row->sub_namespace, $row->sub_title ); diff --git a/modules/topicsubscriptions.js b/modules/topicsubscriptions.js index 62d139814..143528f1e 100644 --- a/modules/topicsubscriptions.js +++ b/modules/topicsubscriptions.js @@ -57,9 +57,10 @@ function updateSubscribeButton( button, state ) { * @param {string} title Page title * @param {string} commentName Comment name * @param {boolean} subscribe Subscription state + * @param {boolean} isNewTopics Subscription is for new topics * @return {jQuery.Promise} Promise which resolves after change of state */ -function changeSubscription( title, commentName, subscribe ) { +function changeSubscription( title, commentName, subscribe, isNewTopics ) { var promise = api.postWithToken( 'csrf', { action: 'discussiontoolssubscribe', page: title, @@ -73,14 +74,30 @@ function changeSubscription( title, commentName, subscribe ) { mw.notify( mw.msg( result.subscribe ? - 'discussiontools-topicsubscription-notify-subscribed-body' : - 'discussiontools-topicsubscription-notify-unsubscribed-body' + ( + isNewTopics ? + 'discussiontools-newtopicssubscription-notify-subscribed-body' : + 'discussiontools-topicsubscription-notify-subscribed-body' + ) : + ( + isNewTopics ? + 'discussiontools-newtopicssubscription-notify-unsubscribed-body' : + 'discussiontools-topicsubscription-notify-unsubscribed-body' + ) ), { title: mw.msg( result.subscribe ? - 'discussiontools-topicsubscription-notify-subscribed-title' : - 'discussiontools-topicsubscription-notify-unsubscribed-title' + ( + isNewTopics ? + 'discussiontools-newtopicssubscription-notify-subscribed-title' : + 'discussiontools-topicsubscription-notify-subscribed-title' + ) : + ( + isNewTopics ? + 'discussiontools-newtopicssubscription-notify-unsubscribed-title' : + 'discussiontools-topicsubscription-notify-unsubscribed-title' + ) ) } );