diff --git a/.phan/config.php b/.phan/config.php
index 263ba3d4b..b02f7ccf8 100644
--- a/.phan/config.php
+++ b/.phan/config.php
@@ -10,6 +10,7 @@ $cfg['directory_list'] = array_merge(
'../../extensions/EventLogging',
'../../extensions/Gadgets',
'../../extensions/BetaFeatures',
+ '../../extensions/Thanks',
]
);
@@ -21,6 +22,7 @@ $cfg['exclude_analysis_directory_list'] = array_merge(
'../../extensions/EventLogging',
'../../extensions/Gadgets',
'../../extensions/BetaFeatures',
+ '../../extensions/Thanks',
]
);
diff --git a/extension.json b/extension.json
index 441f8fcfb..f6c857def 100644
--- a/extension.json
+++ b/extension.json
@@ -44,6 +44,7 @@
"topicsubscriptions.js",
"mobile.js",
"overflowMenu.js",
+ "thanks.js",
"LedeSectionDialog.js",
{
"name": "controller/contLangMessages.json",
@@ -154,7 +155,12 @@
"discussiontools-topicsubscription-notify-unsubscribed-body",
"discussiontools-topicsubscription-notify-unsubscribed-title",
"pagetitle",
- "skin-view-edit"
+ "skin-view-edit",
+ "cancel",
+ "thanks-button-thank",
+ "thanks-button-thanked",
+ "thanks-confirmation2",
+ "thanks-thanked-notice"
]
},
"ext.discussionTools.minervaicons": {
@@ -418,6 +424,7 @@
"RevisionDataUpdates": "dataupdates",
"LoadExtensionSchemaUpdates": "installer",
"GetDoubleUnderscoreIDs": "parser",
+ "ApiMain::moduleManager": "api",
"ParserAfterTidy": "parser",
"ParserOutputPostCacheTransform": "parser",
"BeforeDisplayNoArticleText": "page",
@@ -446,6 +453,9 @@
"installer": {
"class": "MediaWiki\\Extension\\DiscussionTools\\Hooks\\InstallerHooks"
},
+ "api": {
+ "class": "MediaWiki\\Extension\\DiscussionTools\\Hooks\\ApiHooks"
+ },
"page": {
"class": "MediaWiki\\Extension\\DiscussionTools\\Hooks\\PageHooks",
"services": [
@@ -561,6 +571,10 @@
"value": true,
"description": "Enable permalinks frontend features: 1. Convert signature timestamps to comment links. 2. Show notification when the target comment is found on another page."
},
+ "DiscussionToolsEnableThanks": {
+ "value": true,
+ "description": "Show a button to thank individual comments. Requires the 'Thanks' extension."
+ },
"DiscussionToolsAutoTopicSubEditor": {
"value": "any",
"description": "Editor which triggers automatic topic subscriptions. Either 'discussiontoolsapi' for edits made using DiscussionTools' API (e.g. reply and new topic tools), or 'any' for any editor."
diff --git a/i18n/api/en.json b/i18n/api/en.json
index 040533a33..4257b4bc8 100644
--- a/i18n/api/en.json
+++ b/i18n/api/en.json
@@ -38,5 +38,7 @@
"apihelp-discussiontoolssubscribe-param-commentname": "Name of the topic to subscribe to (or unsubscribe from)",
"apihelp-discussiontoolssubscribe-param-page": "A page on which the topic appears",
"apihelp-discussiontoolssubscribe-param-subscribe": "True to subscribe, false to unsubscribe",
- "apihelp-discussiontoolssubscribe-summary": "Subscribe (or unsubscribe) to receive notifications about a topic."
+ "apihelp-discussiontoolssubscribe-summary": "Subscribe (or unsubscribe) to receive notifications about a topic.",
+ "apihelp-discussiontoolsthank-param-commentid": "ID of the comment to thank.",
+ "apihelp-discussiontoolsthank-summary": "Send a public thank-you notification for a comment."
}
diff --git a/i18n/api/qqq.json b/i18n/api/qqq.json
index 84bb896c5..616a8c400 100644
--- a/i18n/api/qqq.json
+++ b/i18n/api/qqq.json
@@ -40,5 +40,7 @@
"apihelp-discussiontoolssubscribe-param-commentname": "{{doc-apihelp-param|discussiontoolssubscribe|commentname}}",
"apihelp-discussiontoolssubscribe-param-page": "{{doc-apihelp-param|discussiontoolssubscribe|page}}",
"apihelp-discussiontoolssubscribe-param-subscribe": "{{doc-apihelp-param|discussiontoolssubscribe|subscribe}}",
- "apihelp-discussiontoolssubscribe-summary": "{{doc-apihelp-summary|discussiontoolssubscribe}}"
+ "apihelp-discussiontoolssubscribe-summary": "{{doc-apihelp-summary|discussiontoolssubscribe}}",
+ "apihelp-discussiontoolsthank-param-commentid": "{{doc-apihelp-summary|discussiontoolsthank|commentid}}",
+ "apihelp-discussiontoolsthank-summary": "{{doc-apihelp-summary|discussiontoolsthank}}"
}
diff --git a/i18n/en.json b/i18n/en.json
index 8234ec364..7d5e0a788 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -71,6 +71,9 @@
"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-comment-thank-header": "$1 {{GENDER:$2|thanked}} {{GENDER:$4|you}} for your comment in \"$3\".",
+ "discussiontools-notification-comment-thank-header-bundled": "{{PLURAL:$1|One person|$1 people|100=99+ people}} thanked {{GENDER:$3|you}} for your comment in \"$2\".",
+ "discussiontools-notification-comment-thank-header-compact": "$1 {{GENDER:$2|thanked}} {{GENDER:$3|you}}.",
"discussiontools-notification-removed-topic-body": "{{GENDER:|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.",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 08ea287e4..2a68222af 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -85,6 +85,9 @@
"discussiontools-notification-added-topic-header-bundled": "Notification header for when multiple new topics have been started on a page.\n\n* $1 - number of new topics.\n* $2 - discussion page title.",
"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-notification-comment-thank-header": "Notification header for when you have been thanked for a comment. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the topic in which the thanked comment was posted.\n* $4 is the username of the user being thanked, for use in GENDER.",
+ "discussiontools-notification-comment-thank-header-bundled": "Notification header for when you have received multiple thanks for a comment. Parameters:\n* $1 is the number of users who sent thanks for the same comment. When used with PLURAL, the value 100 represents more than 99.\n* $2 is the topic in which the thanked comment was posted.\n* $3 is the username of the user being thanked, for use in GENDER.",
+ "discussiontools-notification-comment-thank-header-compact": "Notification compact header for when you have been thanked for a comment. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the username of the user being thanked, for use in GENDER.",
"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",
diff --git a/includes/ApiDiscussionToolsThank.php b/includes/ApiDiscussionToolsThank.php
new file mode 100644
index 000000000..18765607e
--- /dev/null
+++ b/includes/ApiDiscussionToolsThank.php
@@ -0,0 +1,158 @@
+revisionLookup = $revisionLookup;
+ $this->userFactory = $userFactory;
+ }
+
+ /**
+ * @inheritDoc
+ * @throws ApiUsageException
+ * @throws ResourceLimitExceededException
+ */
+ public function execute() {
+ $user = $this->getUser();
+ $this->dieOnBadUser( $user );
+ $this->dieOnUserBlockedFromThanks( $user );
+
+ $params = $this->extractRequestParams();
+
+ $title = Title::newFromText( $params['page'] );
+ $commentId = $params['commentid'];
+
+ if ( !$title ) {
+ $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['page'] ) ] );
+ }
+
+ // TODO: Using the data in the permalinks database would be much
+ // faster, we just wouldn't have the comment content.
+
+ // Support oldid?
+ $revision = $this->revisionLookup->getRevisionByTitle( $title );
+ if ( !$revision ) {
+ throw ApiUsageException::newWithMessage(
+ $this,
+ [ 'apierror-missingrev-title', wfEscapeWikiText( $title->getPrefixedText() ) ],
+ 'nosuchrevid'
+ );
+ }
+ $threadItemSet = HookUtils::parseRevisionParsoidHtml( $revision, __METHOD__ );
+
+ $comment = $threadItemSet->findCommentById( $commentId );
+
+ if ( !$comment || !( $comment instanceof ContentCommentItem ) ) {
+ $this->dieWithError( [ 'apierror-discussiontools-commentid-notfound', $commentId ] );
+ }
+
+ if ( $user->getRequest()->getSessionData( "discussiontools-thanked-{$comment->getId()}" ) ) {
+ $this->markResultSuccess( $comment->getAuthor() );
+ return;
+ }
+
+ $uniqueId = "discussiontools-{$comment->getId()}";
+ // Do one last check to make sure we haven't sent Thanks before
+ if ( $this->haveAlreadyThanked( $user, $uniqueId ) ) {
+ // Pretend the thanks were sent
+ $this->markResultSuccess( $comment->getAuthor() );
+ return;
+ }
+
+ $recipient = $this->userFactory->newFromName( $comment->getAuthor() );
+ if ( !$recipient || !$recipient->getId() ) {
+ $this->dieWithError( 'thanks-error-invalidrecipient', 'invalidrecipient' );
+ }
+
+ $this->dieOnBadRecipient( $user, $recipient );
+
+ $heading = $comment->getSubscribableHeading();
+ if ( !$heading ) {
+ $heading = $comment->getHeading();
+ }
+
+ // Create the notification via Echo extension
+ Event::create( [
+ 'type' => 'dt-thank',
+ 'title' => $title,
+ 'extra' => [
+ 'comment-id' => $comment->getId(),
+ 'comment-name' => $comment->getName(),
+ 'content' => $comment->getBodyText( true ),
+ 'section-title' => $heading->getLinkableTitle(),
+ 'thanked-user-id' => $recipient->getId(),
+ 'revid' => $revision->getId(),
+ ],
+ 'agent' => $user,
+ ] );
+
+ // And mark the thank in session for a cheaper check to prevent duplicates (T48690).
+ $user->getRequest()->setSessionData( "discussiontools-thanked-{$comment->getId()}", true );
+ // Set success message.
+ $this->markResultSuccess( $recipient->getName() );
+ $this->logThanks( $user, $recipient, $uniqueId );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAllowedParams() {
+ return [
+ 'page' => [
+ ParamValidator::PARAM_REQUIRED => true,
+ // Message will exist if DiscussionTools is installed as VE is a dependency
+ ApiBase::PARAM_HELP_MSG => 'apihelp-visualeditoredit-param-page',
+ ],
+ 'commentid' => [
+ ParamValidator::PARAM_REQUIRED => true,
+ ParamValidator::PARAM_TYPE => 'string',
+ ],
+ 'token' => [
+ ParamValidator::PARAM_REQUIRED => true,
+ ParamValidator::PARAM_TYPE => 'string',
+ ],
+ ];
+ }
+}
diff --git a/includes/Hooks/ApiHooks.php b/includes/Hooks/ApiHooks.php
new file mode 100644
index 000000000..f5921dce5
--- /dev/null
+++ b/includes/Hooks/ApiHooks.php
@@ -0,0 +1,43 @@
+isLoaded( 'Thanks' ) ) {
+ $moduleManager->addModule(
+ 'discussiontoolsthank',
+ 'action',
+ [
+ 'class' => ApiDiscussionToolsThank::class,
+ 'services' => [
+ 'PermissionManager',
+ 'ThanksLogStore',
+ 'RevisionLookup',
+ 'UserFactory',
+ ]
+ ]
+ );
+ }
+ }
+}
diff --git a/includes/Hooks/DiscussionToolsHooks.php b/includes/Hooks/DiscussionToolsHooks.php
index 7e1da14c3..6d6988d1b 100644
--- a/includes/Hooks/DiscussionToolsHooks.php
+++ b/includes/Hooks/DiscussionToolsHooks.php
@@ -9,8 +9,11 @@
namespace MediaWiki\Extension\DiscussionTools\Hooks;
+use ExtensionRegistry;
use IContextSource;
use MediaWiki\Extension\DiscussionTools\OverflowMenuItem;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\User\UserNameUtils;
class DiscussionToolsHooks implements
DiscussionToolsAddOverflowMenuItemsHook
@@ -41,5 +44,26 @@ class DiscussionToolsHooks implements
2
);
}
+
+ $dtConfig = MediaWikiServices::getInstance()->getConfigFactory()->makeConfig( 'discussiontools' );
+ if ( $dtConfig->get( 'DiscussionToolsEnableThanks' ) ) {
+ $user = $contextSource->getUser();
+ $showThanks = ExtensionRegistry::getInstance()->isLoaded( 'Thanks' );
+ if ( $showThanks && ( $threadItemData['type'] ?? null ) === 'comment' && $user->isNamed() ) {
+ $userNameUtils = MediaWikiServices::getInstance()->getUserNameUtils();
+ $recipient = $userNameUtils->getCanonical( $threadItemData['author'], UserNameUtils::RIGOR_NONE );
+
+ if (
+ $recipient !== $user->getName() &&
+ !$userNameUtils->isIP( $recipient )
+ ) {
+ $overflowMenuItems[] = new OverflowMenuItem(
+ 'thank',
+ 'heart',
+ $contextSource->msg( 'thanks-button-thank' ),
+ );
+ }
+ }
+ }
}
}
diff --git a/includes/Hooks/EchoHooks.php b/includes/Hooks/EchoHooks.php
index 74d5b5520..c646224e7 100644
--- a/includes/Hooks/EchoHooks.php
+++ b/includes/Hooks/EchoHooks.php
@@ -9,7 +9,9 @@
namespace MediaWiki\Extension\DiscussionTools\Hooks;
+use ExtensionRegistry;
use MediaWiki\Extension\DiscussionTools\Notifications\AddedTopicPresentationModel;
+use MediaWiki\Extension\DiscussionTools\Notifications\CommentThanksPresentationModel;
use MediaWiki\Extension\DiscussionTools\Notifications\EnhancedEchoEditUserTalkPresentationModel;
use MediaWiki\Extension\DiscussionTools\Notifications\EnhancedEchoMentionPresentationModel;
use MediaWiki\Extension\DiscussionTools\Notifications\EventDispatcher;
@@ -101,6 +103,25 @@ class EchoHooks implements
],
];
+ if ( ExtensionRegistry::getInstance()->isLoaded( 'Thanks' ) ) {
+ $notifications['dt-thank'] = [
+ 'category' => 'edit-thank',
+ 'group' => 'positive',
+ 'section' => 'message',
+ 'user-locators' => [
+ [
+ [ UserLocator::class, 'locateFromEventExtra' ],
+ [ 'thanked-user-id' ]
+ ]
+ ],
+ 'presentation-model' => CommentThanksPresentationModel::class,
+ 'bundle' => [
+ 'web' => true,
+ 'expandable' => true,
+ ],
+ ];
+ }
+
// Override default handlers
$notifications['edit-user-talk']['presentation-model'] = EnhancedEchoEditUserTalkPresentationModel::class;
$notifications['mention']['presentation-model'] = EnhancedEchoMentionPresentationModel::class;
@@ -116,6 +137,9 @@ class EchoHooks implements
$bundleString = $event->getType() . '-' . $event->getTitle()->getNamespace()
. '-' . $event->getTitle()->getDBkey();
break;
+ case 'dt-thank':
+ $bundleString = $event->getType() . '-' . $event->getExtraParam( 'comment-name' );
+ break;
}
}
diff --git a/includes/Hooks/PageHooks.php b/includes/Hooks/PageHooks.php
index 84bad781f..59c991155 100644
--- a/includes/Hooks/PageHooks.php
+++ b/includes/Hooks/PageHooks.php
@@ -304,12 +304,13 @@ class PageHooks implements
// Reply button: share
$output->addModuleStyles( 'oojs-ui.styles.icons-content' );
}
+ $output->addModuleStyles( [
+ // Overflow menu ('ellipsis' icon)
+ 'oojs-ui.styles.icons-interactions',
+ ] );
if ( $isMobile ) {
$output->addModuleStyles( [
- // Mobile overflow menu:
- // ellipsis
- 'oojs-ui.styles.icons-interactions',
- // edit
+ // Edit button in overflow menu ('edit' icon)
'oojs-ui.styles.icons-editing-core',
] );
}
diff --git a/includes/Notifications/CommentThanksPresentationModel.php b/includes/Notifications/CommentThanksPresentationModel.php
new file mode 100644
index 000000000..dcb08e27e
--- /dev/null
+++ b/includes/Notifications/CommentThanksPresentationModel.php
@@ -0,0 +1,150 @@
+section = new EchoPresentationModelSection( $event, $user, $language );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getIconType() {
+ return 'thanks';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canRender() {
+ return (bool)$this->event->getTitle();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getPrimaryLink() {
+ return [
+ 'url' => $this->getCommentLink() ?: $this->event->getTitle()->getFullURL(),
+ 'label' => $this->msg( 'discussiontools-notification-subscribed-new-comment-view' )->text()
+ ];
+ }
+
+ /**
+ * Get a link to the individual comment, if available.
+ *
+ * @return string|null Full URL linking to the comment, null if not available
+ */
+ protected function getCommentLink(): ?string {
+ if ( !$this->userCan( RevisionRecord::DELETED_TEXT ) ) {
+ return null;
+ }
+ // Thanks notifications are bundled by comment-id, so the link will always be to a single comment
+ // (unlike in DiscussionToolsEventTrait)
+ $commentId = $this->event->getExtraParam( 'comment-id' );
+ if ( !$commentId ) {
+ return null;
+ }
+ $title = $this->event->getTitle();
+ return $title->createFragmentTarget( $commentId )->getFullURL();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function getHeaderMessageKey() {
+ if ( $this->isBundled() ) {
+ return 'discussiontools-notification-comment-thank-header-bundled';
+ } else {
+ return 'discussiontools-notification-comment-thank-header';
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getHeaderMessage() {
+ $title = $this->section->getTruncatedSectionTitle();
+ if ( !$title ) {
+ // Comment could have been at the top of the page before
+ // any section titles. Use the page title instead.
+ $title = $this->event->getTitle()->getPrefixedText();
+ }
+ if ( $this->isBundled() ) {
+ $count = $this->getNotificationCountForOutput();
+ $msg = $this->msg( $this->getHeaderMessageKey() );
+
+ // Params 1, 2, 3:
+ $msg->numParams( $count );
+ $msg->plaintextParams( $title );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ } else {
+ $msg = parent::getHeaderMessage();
+ // Params 3, 4:
+ $msg->plaintextParams( $title );
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getCompactHeaderMessage() {
+ $msg = $this->getMessageWithAgent( 'discussiontools-notification-comment-thank-header-compact' );
+ // Param 3:
+ $msg->params( $this->getViewingUserForGender() );
+ return $msg;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getBodyMessage() {
+ if ( !$this->isBundled() ) {
+ return new RawMessage( '$1', [ Message::plaintextParam( $this->getContentSnippet() ) ] );
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSecondaryLinks() {
+ $pageLink = $this->getPageLink( $this->event->getTitle(), '', true );
+ if ( $this->isBundled() ) {
+ return [ $pageLink ];
+ } else {
+ return [ $this->getAgentLink(), $pageLink ];
+ }
+ }
+}
diff --git a/modules/controller.js b/modules/controller.js
index ed007e7e4..3d9cefe4c 100644
--- a/modules/controller.js
+++ b/modules/controller.js
@@ -27,6 +27,7 @@ let mobile = null;
if ( OO.ui.isMobile() && mw.config.get( 'skin' ) === 'minerva' ) {
mobile = require( './mobile.js' );
}
+require( './thanks.js' );
mw.messages.set( require( './controller/contLangMessages.json' ) );
diff --git a/modules/thanks.js b/modules/thanks.js
new file mode 100644
index 000000000..8f0bc0b67
--- /dev/null
+++ b/modules/thanks.js
@@ -0,0 +1,77 @@
+const cacheKey = 'dt-thanks';
+
+/**
+ * Thank a comment item
+ *
+ * @param {CommentItem} commentItem Comment item
+ * @return {jQuery.Promise} Resolves when thanks successfully sent, rejects on error
+ */
+function thankComment( commentItem ) {
+ // TODO: Add recipient gender for messages
+ const recipientGender = 'unknown';
+ return OO.ui.confirm( mw.msg( 'thanks-confirmation2', mw.user ), {
+ actions: [
+ {
+ action: 'accept',
+ label: mw.msg( 'thanks-button-thank', mw.user, recipientGender ),
+ flags: [ 'primary', 'progressive' ]
+ },
+ {
+ action: 'cancel',
+ label: mw.msg( 'cancel' ),
+ flags: 'safe'
+ }
+ ]
+ } ).then( ( confirmed ) => {
+ if ( !confirmed ) {
+ return $.Deferred().reject().promise();
+ }
+
+ const api = require( './controller.js' ).getApi();
+
+ return api.postWithToken( 'csrf', {
+ action: 'discussiontoolsthank',
+ // We don't need to store the correct transcluded comment page
+ // for a thank, any page the comment appears on will do.
+ page: mw.config.get( 'wgRelevantPageName' ),
+ commentid: commentItem.id
+ } ).then( () => {
+ mw.notify( mw.msg( 'thanks-thanked-notice', commentItem.author, recipientGender, mw.user ), { type: 'success' } );
+ cacheThanked( commentItem );
+ }, ( code, data ) => {
+ mw.notify( api.getErrorMessage( data ), { type: 'error' } );
+ return $.Deferred().reject().promise();
+ } );
+ } );
+}
+
+function isThanked( threadItem ) {
+ const cache = mw.storage.getObject( cacheKey ) || {};
+ return cache[ threadItem.id ];
+}
+
+function cacheThanked( threadItem ) {
+ const cache = mw.storage.getObject( cacheKey ) || {};
+ cache[ threadItem.id ] = true;
+ mw.storage.setObject( cacheKey, cache );
+}
+
+mw.hook( 'discussionToolsOverflowMenuOnChoose' ).add( ( id, menuItem, threadItem ) => {
+ // TODO: Add recipient gender for messages
+ const recipientGender = 'unknown';
+ if ( id === 'thank' ) {
+ thankComment( threadItem ).then( () => {
+ menuItem.setLabel( mw.msg( 'thanks-button-thanked', mw.user, recipientGender ) );
+ menuItem.setDisabled( true );
+ } );
+ }
+} );
+
+mw.hook( 'discussionToolsOverflowMenuOnAddItem' ).add( ( id, menuItem, threadItem ) => {
+ // TODO: Add recipient gender for messages
+ const recipientGender = 'unknown';
+ if ( id === 'thank' && isThanked( threadItem ) ) {
+ menuItem.setLabel( mw.msg( 'thanks-button-thanked', mw.user, recipientGender ) );
+ menuItem.setDisabled( true );
+ }
+} );