jenkins-bot has submitted this change and it was merged. Change subject: Rewrite mobile login page to be less hacky and closer to core version ......................................................................
Rewrite mobile login page to be less hacky and closer to core version This makes it easier for other extensions, such as Gather, to pass their own messages to the page (without using hooks). This removes the mobile-only login message header, which should be implemented in the core login page if it is actually useful. This will also simplify the transition from a custom mobile login page to sharing the login page with core. Bug: T95065 Change-Id: If5ec2ca2f345ab95851ecd2d658332d94a8d4270 --- M i18n/en.json M includes/MobileFrontend.hooks.php M includes/skins/SkinMinerva.php M includes/skins/UserAccountCreateMobileTemplate.php M includes/skins/UserLoginAndCreateTemplate.php M includes/skins/UserLoginMobileTemplate.php M includes/specials/SpecialMobileEditWatchlist.php M includes/specials/SpecialMobileWatchlist.php M javascripts/modules/editor/EditorOverlay.js M javascripts/modules/editor/init.js M javascripts/modules/watchstar/Watchstar.js M less/specials/common.less M less/specials/userlogin.less M less/ui.less 14 files changed, 99 insertions(+), 210 deletions(-) Approvals: Jhernandez: Looks good to me, approved Jdlrobson: Looks good to me, but someone else must approve jenkins-bot: Verified diff --git a/i18n/en.json b/i18n/en.json index 306f504..3847da8 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -45,17 +45,15 @@ "mobile-frontend-dismiss-notification": "dismiss this notification", "mobile-frontend-donate-image-anon": "Please log in to view the uploads page.", "mobile-frontend-donate-image-heading": "Your recent contributions", - "mobile-frontend-donate-image-login": "Media on {{SITENAME}} is donated by people like you.", - "mobile-frontend-donate-image-login-action": "Log in to share your media.", + "mobile-frontend-donate-image-login-action": "<strong>Media on {{SITENAME}} is donated by people like you.</strong><br/>Log in to share your media.", "mobile-frontend-donate-image-nouploads": "No uploads.", "mobile-frontend-donate-image-signup-action": "Sign up to share your media with the world.", "mobile-frontend-donate-image-title": "Uploads", "mobile-frontend-donate-photo-first-upload-success": "Success! Thanks for your first contribution!", "mobile-frontend-donate-photo-upload-success": "Success! Your image can now be used on {{SITENAME}}!", "mobile-frontend-drawer-cancel": "Cancel", - "mobile-frontend-edit-login": "Help improve the $1 page.", - "mobile-frontend-edit-login-action": "Log in to edit.", - "mobile-frontend-edit-signup-action": "Sign up to edit.", + "mobile-frontend-edit-login-action": "<strong>Help improve {{SITENAME}}.</strong><br/>Log in to edit.", + "mobile-frontend-edit-signup-action": "<strong>Help improve {{SITENAME}}.</strong><br/>Sign up to edit.", "mobile-frontend-editor-abusefilter-disallow": "This edit cannot be saved because we have detected an issue.", "mobile-frontend-editor-abusefilter-read-more": "Read more", "mobile-frontend-editor-abusefilter-warning": "Warning: Are you sure you want to save this edit? There may be an issue with it.", @@ -346,9 +344,9 @@ "mobile-frontend-watchlist-more": "more", "mobile-frontend-watchlist-please-wait": "Please wait, watch action is taking longer than expected.", "mobile-frontend-watchlist-error": "There was a problem watching this page. Please try again.", - "mobile-frontend-watchlist-purpose": "A watchlist helps you bookmark pages and keep track of changes to them.", + "mobile-frontend-watchlist-purpose": "<strong>A watchlist helps you bookmark pages and keep track of changes to them.</strong><br>Log in to see it.", "mobile-frontend-watchlist-removed": "Removed $1 from your watchlist", - "mobile-frontend-watchlist-signup-action": "Sign up to start one now.", + "mobile-frontend-watchlist-signup-action": "<strong>A watchlist helps you bookmark pages and keep track of changes to them.</strong>Sign up to start one now.", "mobile-frontend-watchlist-view": "View your watchlist", "mobile-frontend-quick-lookup-looking": "Looking for \"$1\".", "mobile-frontend-quick-lookup-no-results": "Couldn't find anything matching \"$1\".", diff --git a/includes/MobileFrontend.hooks.php b/includes/MobileFrontend.hooks.php index f786c93..db37754 100644 --- a/includes/MobileFrontend.hooks.php +++ b/includes/MobileFrontend.hooks.php @@ -1024,6 +1024,15 @@ * @param array $messages Array of already added messages */ public static function onLoginFormValidErrorMessages( &$messages ) { - $messages[] = 'mobile-frontend-donate-image-anon'; + $messages = array_merge( $messages, + array( + 'mobile-frontend-watchlist-signup-action', // watchstart sign up CTA + 'mobile-frontend-watchlist-purpose', // Watchlist and watchstar sign in CTA + 'mobile-frontend-donate-image-anon', // Uploads link + 'mobile-frontend-edit-login-action', // Edit button sign in CTA + 'mobile-frontend-edit-signup-action', // Edit button sign-up CTA + 'mobile-frontend-donate-image-login-action', + ) + ); } } diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php index d54746a..f8d7bac 100644 --- a/includes/skins/SkinMinerva.php +++ b/includes/skins/SkinMinerva.php @@ -307,14 +307,22 @@ /** * Return a url to a resource or to a login screen that redirects to that resource. * @param Title $title - * @param array $query representation of query string parameters + * @param string $warning Key of message to display on login page (optional) + * @param array $query representation of query string parameters (optional) * @return string url */ - protected function getPersonalUrl( Title $title, array $query = array() ) { + protected function getPersonalUrl( Title $title, $warning, array $query = array() ) { if ( $this->getUser()->isLoggedIn() ) { return $title->getLocalUrl( $query ); } else { - return $this->getLoginUrl( array( 'returnto' => $title ) ); + $loginQueryParams['returnto'] = $title; + if ( $query ) { + $loginQueryParams['returntoquery'] = wfArrayToCgi( $query ); + } + if ( $warning ) { + $loginQueryParams['warning'] = $warning; + } + return $this->getLoginUrl( $loginQueryParams ); } } @@ -346,7 +354,11 @@ 'links' => array( array( 'text' => wfMessage( 'mobile-frontend-main-menu-watchlist' )->escaped(), - 'href' => $this->getPersonalUrl( $watchTitle, $watchlistQuery ), + 'href' => $this->getPersonalUrl( + $watchTitle, + 'mobile-frontend-watchlist-purpose', + $watchlistQuery + ), 'class' => MobileUI::iconClass( 'watchlist', 'before' ), 'data-event-name' => 'watchlist', ), @@ -360,7 +372,10 @@ 'links' => array( array( 'text' => wfMessage( 'mobile-frontend-main-menu-upload' )->escaped(), - 'href' => $this->getPersonalUrl( $donateTitle ), + 'href' => $this->getPersonalUrl( + $donateTitle, + 'mobile-frontend-donate-image-anon' + ), 'class' => MobileUI::iconClass( 'uploads', 'before', 'menu-item-upload' ), 'data-event-name' => 'uploads', ), @@ -384,7 +399,10 @@ 'links' => array( array( 'text' => wfMessage( 'preferences' )->escaped(), - 'href' => $this->getPersonalUrl( SpecialPage::getTitleFor( 'Preferences' ) ), + 'href' => $this->getPersonalUrl( + SpecialPage::getTitleFor( 'Preferences' ), + 'prefsnologintext2' + ), 'class' => MobileUI::iconClass( 'settings', 'before' ), 'data-event-name' => 'preferences', ), diff --git a/includes/skins/UserAccountCreateMobileTemplate.php b/includes/skins/UserAccountCreateMobileTemplate.php index 4301963..dcbf9f5 100644 --- a/includes/skins/UserAccountCreateMobileTemplate.php +++ b/includes/skins/UserAccountCreateMobileTemplate.php @@ -7,18 +7,6 @@ * Provides a custom account creation form for mobile devices */ class UserAccountCreateMobileTemplate extends UserLoginAndCreateTemplate { - /** @var array $actionMessages Message keys for page actions */ - protected $actionMessages = array( - 'watch' => 'mobile-frontend-watchlist-signup-action', - 'edit' => 'mobile-frontend-edit-signup-action', - 'signup-edit' => 'mobile-frontend-edit-signup-action', - '' => 'mobile-frontend-generic-signup-action', - ); - /** @var array $actionMessages Message keys for site links */ - protected $pageMessages = array( - 'Uploads' => 'mobile-frontend-donate-image-signup-action', - 'Watchlist' => 'mobile-frontend-watchlist-signup-action', - ); /** * Render Login/Create specific template @@ -93,8 +81,7 @@ $stickHTTPS . Html::closeElement( 'form' ); echo Html::openElement( 'div', array( 'id' => 'mw-mf-accountcreate', 'class' => 'content' ) ); - $this->renderGuiderMessage(); - $this->renderMessageHtml( true ); + $this->renderMessageHtml( 'signup', true ); echo $form; echo Html::closeElement( 'div' ); } diff --git a/includes/skins/UserLoginAndCreateTemplate.php b/includes/skins/UserLoginAndCreateTemplate.php index ec804ad..763f99e 100644 --- a/includes/skins/UserLoginAndCreateTemplate.php +++ b/includes/skins/UserLoginAndCreateTemplate.php @@ -11,27 +11,6 @@ * special mobile-specific magic. */ abstract class UserLoginAndCreateTemplate extends BaseTemplate { - /** @var array $actionMessagesHeaders Message keys for site links */ - protected $pageMessageHeaders = array( - 'Uploads' => 'mobile-frontend-donate-image-login', - 'Watchlist' => 'mobile-frontend-watchlist-purpose', - ); - /** @var array $actionMessages Message keys for site links */ - protected $pageMessages = array(); - - /** @var array $actionMessagesHeaders Message keys for page actions */ - protected $actionMessageHeaders = array( - 'watch' => 'mobile-frontend-watchlist-purpose', - 'edit' => 'mobile-frontend-edit-login', - 'signup-edit' => 'mobile-frontend-edit-login', - '' => 'mobile-frontend-generic-login', - ); - - /** - * Message keys for page actions - * @var array $actionMessages - */ - protected $actionMessages = array(); /** * Overload the parent constructor @@ -48,35 +27,35 @@ /** * Render message box with system messages, e.g. errors or already logged-in notices * + * @param string $action The type of action the page is used for ('login' or 'signup') * @param bool $register Whether the user can register an account */ - protected function renderMessageHtml( $register = false ) { + protected function renderMessageHtml( $action, $register = false ) { $msgBox = ''; // placeholder for displaying any login-related system messages (eg errors) - - // Render logged-in notice (beta/alpha) - if ( $this->data['loggedin'] ) { - $msg = ( $register ) ? 'mobile-frontend-userlogin-loggedin-register' : 'userlogin-loggedin'; - $msgBox .= Html::element( 'div', array( 'class' => 'alert warning' ), - wfMessage( $msg )->params( - $this->data['loggedinuser'] )->parse() ); - } - - // Render login errors $message = $this->data['message']; $messageType = $this->data['messagetype']; - if ( $message ) { - $heading = ''; - $class = 'alert'; - if ( $messageType == 'error' ) { - $heading = wfMessage( 'mobile-frontend-sign-in-error-heading' )->text(); - $class .= ' error'; - } - $msgBox .= Html::openElement( 'div', array( 'class' => $class ) ); - $msgBox .= ( $heading ) ? Html::rawElement( 'h2', array(), $heading ) : ''; + // FIXME: Migrate this to a server-side Mustache template + // If there is a system message (error, warning, or success) display that + if ( $message && $messageType ) { + $msgBox .= Html::openElement( 'div', array( 'class' => $messageType . 'box' ) ); $msgBox .= $message; $msgBox .= Html::closeElement( 'div' ); + // Render already logged-in notice + } elseif ( $this->data['loggedin'] ) { + $msg = ( $register ) ? 'mobile-frontend-userlogin-loggedin-register' : 'userlogin-loggedin'; + $msgBox .= Html::openElement( 'div', array( 'class' => 'warningbox' ) ); + $msgBox .= wfMessage( $msg )->params( $this->data['loggedinuser'] )->parse(); + $msgBox .= Html::closeElement( 'div' ); + // Show default welcome message } else { + // The warningbox class is used more for informational purposes than actual warnings. + $msgBox .= Html::openElement( 'div', array( 'class' => 'warningbox' ) ); + $headerMsg = wfMessage( 'mobile-frontend-generic-login' )->parse(); + $msgBox .= Html::element( 'strong', array(), $headerMsg ); + $msgBox .= Html::element( 'br' ); + $msgBox .= wfMessage( "mobile-frontend-generic-{$action}-action" )->plain(); + $msgBox .= Html::closeElement( 'div' ); $msgBox .= $this->getLogoHtml(); } echo $msgBox; @@ -130,90 +109,6 @@ return true; } return false; - } - - /** - * Gets the message that should guide a user who is creating an account or - * logging in to an account. - * @return array First element is header of message and second is the content. - */ - protected function getGuiderMessage() { - $req = $this->getRequestContext()->getRequest(); - // omit UserLogin's own messages in this template to avoid duplicate messages - bug T73771, T86031 - if ( $this->data['messagetype'] !== 'error' ) { - $this->data['message'] = ''; - } - - if ( $req->getVal( 'returnto' ) - && ( $title = Title::newFromText( $req->getVal( 'returnto' ) ) ) - ) { - list( $returnto, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() ); - $title = $title->getText(); - } else { - $returnto = ''; - $title = ''; - } - $returnToQuery = wfCgiToArray( $req->getVal( 'returntoquery' ) ); - if ( isset( $returnToQuery['article_action'] ) ) { - $action = $returnToQuery['article_action']; - } else { - $action = ''; - } - - $heading = ''; - $content = ''; - - $pageMessageHeaders = $this->getPageMessageHeaders(); - if ( isset( $pageMessageHeaders[$returnto] ) ) { - $heading = wfMessage( $pageMessageHeaders[$returnto] )->parse(); - if ( isset( $this->pageMessages[$returnto] ) ) { - $content = wfMessage( $this->pageMessages[$returnto] )->parse(); - } - } elseif ( isset( $this->actionMessageHeaders[$action] ) ) { - $heading = wfMessage( $this->actionMessageHeaders[$action], $title )->parse(); - if ( isset( $this->actionMessages[$action] ) ) { - $content = wfMessage( $this->actionMessages[$action], $title )->parse(); - } - } - return array( $heading, $content ); - } - - /** - * Returns an array of all valid login info messages. - * - * @return array - */ - protected function getPageMessageHeaders() { - static $messages = null; - if ( !$messages ) { - // default MobileFrontend messages - $messages = $this->pageMessageHeaders; - // reuse core hook to allow extensions to add their own messages - // currently extensions needs to add two messages for full mobile support, one - // withput a key and one with the returnto target as the key, example from Gather: - // $messages['Gather'] = 'gather-loginpage-desc'; -> for mobile custom login page - // $messages[] = 'gather-anon-view-lists'; -> // for core login page (and mobile alpha) - Hooks::run( 'LoginFormValidErrorMessages', array( &$messages ) ); - } - return $messages; - } - - /** - * Renders a prompt above the login or upload screen - * - */ - protected function renderGuiderMessage() { - if ( !$this->data['loggedin'] ) { - $msgs = $this->getGuiderMessage(); - if ( $msgs[0] ) { - echo Html::openElement( 'div', array( 'class' => 'headmsg' ) ); - echo Html::element( 'strong', array(), $msgs[0] ); - if ( $msgs[1] ) { - echo Html::element( 'div', array(), $msgs[1] ); - } - echo Html::closeElement( 'div' ); - } - } } /** diff --git a/includes/skins/UserLoginMobileTemplate.php b/includes/skins/UserLoginMobileTemplate.php index 8dc92b8..96121b3 100644 --- a/includes/skins/UserLoginMobileTemplate.php +++ b/includes/skins/UserLoginMobileTemplate.php @@ -7,18 +7,6 @@ * Provides a custom login form for mobile devices */ class UserLoginMobileTemplate extends UserLoginAndCreateTemplate { - /** @var array $actionMessages Message keys for page actions */ - protected $actionMessages = array( - 'watch' => 'mobile-frontend-watchlist-login-action', - 'edit' => 'mobile-frontend-edit-login-action', - '' => 'mobile-frontend-generic-login-action', - ); - /** @var array $actionMessages Message keys for site links */ - protected $pageMessages = array( - 'Uploads' => 'mobile-frontend-donate-image-login-action', - 'Watchlist' => 'mobile-frontend-watchlist-login-action', - 'Gather' => 'gather-anon-view-lists', - ); /** * Build the login page @@ -113,8 +101,7 @@ $signupLink . Html::closeElement( 'div' ); echo $login; - $this->renderGuiderMessage(); - $this->renderMessageHtml(); + $this->renderMessageHtml( 'login' ); echo $form; echo Html::closeElement( 'div' ); } diff --git a/includes/specials/SpecialMobileEditWatchlist.php b/includes/specials/SpecialMobileEditWatchlist.php index 9412e17..4a6873c 100644 --- a/includes/specials/SpecialMobileEditWatchlist.php +++ b/includes/specials/SpecialMobileEditWatchlist.php @@ -75,7 +75,7 @@ */ public function execute( $mode ) { // Anons don't get a watchlist edit - $this->requireLogin( 'watchlistanontext' ); + $this->requireLogin( 'mobile-frontend-watchlist-purpose' ); $out = $this->getOutput(); // turn off #content element diff --git a/includes/specials/SpecialMobileWatchlist.php b/includes/specials/SpecialMobileWatchlist.php index aa08f7c..5b8394a 100644 --- a/includes/specials/SpecialMobileWatchlist.php +++ b/includes/specials/SpecialMobileWatchlist.php @@ -54,7 +54,7 @@ */ function executeWhenAvailable( $par ) { // Anons don't get a watchlist - $this->requireLogin( 'watchlistanontext' ); + $this->requireLogin( 'mobile-frontend-watchlist-purpose' ); $ctx = MobileContext::singleton(); $this->usePageImages = !$ctx->imagesDisabled() && defined( 'PAGE_IMAGES_INSTALLED' ); diff --git a/javascripts/modules/editor/EditorOverlay.js b/javascripts/modules/editor/EditorOverlay.js index 23f9a15..2ae2917 100644 --- a/javascripts/modules/editor/EditorOverlay.js +++ b/javascripts/modules/editor/EditorOverlay.js @@ -173,10 +173,12 @@ var params = $.extend( { // use wgPageName as this includes the namespace if outside Main returnto: options.returnTo || mw.config.get( 'wgPageName' ), - returntoquery: 'action=edit§ion=' + options.sectionId + returntoquery: 'action=edit§ion=' + options.sectionId, + warning: 'mobile-frontend-edit-login-action' }, options.queryParams ), signupParams = $.extend( { - type: 'signup' + type: 'signup', + warning: 'mobile-frontend-edit-signup-action' }, options.signupQueryParams ); options.loginUrl = mw.util.getUrl( 'Special:UserLogin', params ); diff --git a/javascripts/modules/editor/init.js b/javascripts/modules/editor/init.js index 5df4e2c..416bd68 100644 --- a/javascripts/modules/editor/init.js +++ b/javascripts/modules/editor/init.js @@ -63,13 +63,6 @@ * @param {Number} section number representing the section */ function makeCta( $el, section ) { - var options = { - queryParams: { - returnto: mw.config.get( 'wgPageName' ), - returntoquery: 'action=edit§ion=' + section - } - }; - $el .on( 'click', function ( ev ) { ev.preventDefault(); @@ -79,16 +72,19 @@ if ( !drawer ) { drawer = new CtaDrawer( { queryParams: { + returnto: mw.config.get( 'wgPageName' ), + returntoquery: 'action=edit§ion=' + section, + warning: 'mobile-frontend-edit-login-action', campaign: 'mobile_editPageActionCta' }, signupQueryParams: { - returntoquery: 'article_action=signup-edit' + returntoquery: 'article_action=signup-edit', + warning: 'mobile-frontend-edit-signup-action' }, content: mw.msg( 'mobile-frontend-editor-cta' ) } ); } drawer - .render( options ) .toggle(); } ) // needed until we use tap everywhere to prevent the link from being followed diff --git a/javascripts/modules/watchstar/Watchstar.js b/javascripts/modules/watchstar/Watchstar.js index b210b4f..c0c3d63 100644 --- a/javascripts/modules/watchstar/Watchstar.js +++ b/javascripts/modules/watchstar/Watchstar.js @@ -51,8 +51,12 @@ ctaDrawerOptions: { content: mw.msg( 'mobile-frontend-watchlist-cta' ), queryParams: { + warning: 'mobile-frontend-watchlist-purpose', campaign: 'mobile_watchPageActionCta', returntoquery: 'article_action=watch' + }, + signupQueryParams: { + warning: 'mobile-frontend-watchlist-signup-action' } }, tagName: 'div', diff --git a/less/specials/common.less b/less/specials/common.less index b96a4b8..292824a 100644 --- a/less/specials/common.less +++ b/less/specials/common.less @@ -58,7 +58,6 @@ } // used in Special:Nearby and Special:UserLogin -// FIXME: Move .errorbox to nearby.less if userlogin uses desktop code in stable. .errorbox, .error { color: @colorErrorText; diff --git a/less/specials/userlogin.less b/less/specials/userlogin.less index c1ad286..a250382 100644 --- a/less/specials/userlogin.less +++ b/less/specials/userlogin.less @@ -6,6 +6,16 @@ display: none; } +// In theory, these 2 rules should be consolidated into a single semantic class like +// 'alert', but we want to keep the CSS sharable between stable, beta, and alpha modes, +// and alpha mode uses the core login page which doesn't have such a shared class. +.errorbox, +.successbox, +.warningbox { + padding: .5em 1em; + margin: 1em 0; +} + .stable, .beta { #mw-mf-login, #mw-mf-accountcreate { @@ -61,22 +71,6 @@ padding: 4px 0px 4px 26px; } } -} - -// Styles apply to alpha version of login form. -#mw-mf-accountcreate .headmsg, -#mw-mf-login .headmsg, -// Styles for new login form. -.alpha .warningbox { - padding: 0.5em 1em; - margin: 1em 0; -} - -#mw-mf-accountcreate .headmsg, -#mw-mf-login .headmsg { - background-color: @colorGray14; - border: 1px solid @colorGray12; - color: @grayDark; } .alpha { @@ -138,13 +132,6 @@ .mw-ui-vform { margin: auto; - - .errorbox, - .successbox, - .warningbox { - padding: 1em @contentMargin; - margin: 0 0 1em; - } .mw-ui-input { padding: .8em .5em; diff --git a/less/ui.less b/less/ui.less index 10893ac..508a456 100644 --- a/less/ui.less +++ b/less/ui.less @@ -87,20 +87,27 @@ border-bottom: 1px solid @grayLight; } -// Used for messages on login screen, page lists and uploads and when showing old revisions -.warningbox, +// Used for messages on page lists and uploads and when showing old revisions .alert.warning { color: @colorWarningText; background: @colorWarningBackground; } +// Used for messages on login screen (They're more informational than actual warnings.) +.warningbox { + border: 1px solid @colorGray12; + background-color: @colorGray14; + color: @grayDark; +} + +.successbox { + color: @colorSuccessText; + background: @colorSuccessBackground; +} + .alert { padding: 1em @contentMargin; margin: 0 0 1em; - - &.successbox { - background: @colorSuccessBackground; - } h2 { font: bold 100% @fontFamily; -- To view, visit https://gerrit.wikimedia.org/r/204977 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If5ec2ca2f345ab95851ecd2d658332d94a8d4270 Gerrit-PatchSet: 12 Gerrit-Project: mediawiki/extensions/MobileFrontend Gerrit-Branch: master Gerrit-Owner: Kaldari <rkald...@wikimedia.org> Gerrit-Reviewer: Bmansurov <bmansu...@wikimedia.org> Gerrit-Reviewer: Florianschmidtwelzow <florian.schmidt.wel...@t-online.de> Gerrit-Reviewer: Jdlrobson <jrob...@wikimedia.org> Gerrit-Reviewer: Jhernandez <jhernan...@wikimedia.org> Gerrit-Reviewer: Kaldari <rkald...@wikimedia.org> Gerrit-Reviewer: Phuedx <g...@samsmith.io> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits