Merge "Highlight comment after saving"

This commit is contained in:
jenkins-bot 2019-12-03 16:49:01 +00:00 committed by Gerrit Code Review
commit a7db61d43f
6 changed files with 106 additions and 11 deletions

View file

@ -8,6 +8,7 @@
"OO": "readonly",
"ve": "readonly",
"require": "readonly",
"module": "readonly"
"module": "readonly",
"RangeFix": "readonly"
}
}

View file

@ -52,6 +52,7 @@
],
"styles": "dt.init.less",
"dependencies": [
"rangefix",
"mediawiki.Uri",
"ext.discussionTools.parser",
"ext.discussionTools.modifier",

View file

@ -1,9 +1,23 @@
'use strict';
var $pageContainer,
var $pageContainer, pageComments, pageThreads,
scrollPadding = { top: 10, bottom: 10 },
replyWidgetPromise = mw.loader.using( 'ext.discussionTools.ReplyWidget' );
function getReplyIndex( comment ) {
var commentIndex = pageComments.indexOf( comment );
function countReplies( c ) {
var count = c.replies.length;
c.replies.forEach( function ( r ) {
count += countReplies( r );
} );
return count;
}
return commentIndex + countReplies( comment ) + 1;
}
function setupComment( comment ) {
var $replyLink, widgetPromise, newList, newListItem,
$tsNode = $( comment.range.endContainer );
@ -18,7 +32,11 @@ function setupComment( comment ) {
// TODO: i18n
.text( 'Reply' )
.on( 'click', function () {
var $link = $( this );
var $link = $( this ),
userCommentsBeforeReply = pageComments.slice( 0, getReplyIndex( comment ) )
.filter( function ( c ) {
return c.author === mw.user.getName();
} ).length;
$link.addClass( 'dt-init-replylink-active' );
// TODO: Allow users to use multiple reply widgets simlutaneously
@ -33,7 +51,7 @@ function setupComment( comment ) {
$( newListItem ).text( 'Loading...' );
widgetPromise = replyWidgetPromise.then( function () {
var replyWidget = new mw.dt.ui.ReplyWidget(
comment,
comment, userCommentsBeforeReply,
{
// TODO: Remove placeholder
doc: '<p>Reply to ' + comment.author + '</p>',
@ -110,22 +128,59 @@ function postReply( widget, parsoidData ) {
} );
}
function init( $container ) {
var pageComments, pageThreads, parsoidPromise, parsoidComments, parsoidDoc,
function highlight( comment ) {
var padding = 5,
containerRect = RangeFix.getBoundingClientRect( $pageContainer[ 0 ] ),
rect = RangeFix.getBoundingClientRect( comment.range ),
$highlight = $( '<div>' ).addClass( 'dt-init-highlight' );
$highlight.css( {
top: rect.top - containerRect.top - padding,
left: rect.left - containerRect.left - padding,
width: rect.width + ( padding * 2 ),
height: rect.height + ( padding * 2 )
} );
setTimeout( function () {
$highlight.addClass( 'dt-init-highlight-fade' );
setTimeout( function () {
$highlight.remove();
}, 500 );
}, 500 );
$pageContainer.prepend( $highlight );
}
function init( $container, state ) {
var parsoidPromise, parsoidComments, parsoidDoc,
parsoidPageData = {
pageName: mw.config.get( 'wgRelevantPageName' ),
oldId: mw.config.get( 'wgRevisionId' ),
token: mw.user.tokens.get( 'csrfToken' )
};
state = state || {};
$pageContainer = $container;
pageComments = mw.dt.parser.getComments( $pageContainer[ 0 ] );
pageThreads = mw.dt.parser.groupThreads( pageComments );
pageThreads.forEach( traverseNode );
$pageContainer.addClass( 'dt-init-done' );
$pageContainer.removeClass( 'dt-init-replylink-open' );
// For debugging
mw.dt.pageThreads = pageThreads;
if ( state.userCommentsBeforeReply ) {
highlight(
pageComments.filter( function ( comment ) {
// TODO: Find anon comments?
return comment.author === mw.user.getName();
} )[ state.userCommentsBeforeReply ]
);
state.userCommentsBeforeReply = null;
}
parsoidPromise = mw.loader.using( 'ext.visualEditor.targetLoader' ).then( function () {
return mw.libs.ve.targetLoader.requestPageData(
'visual', parsoidPageData.pageName, { oldId: parsoidPageData.oldId }

View file

@ -13,6 +13,10 @@ mw.dt = {
if ( new mw.Uri().query.dtdebug ) {
mw.loader.load( 'ext.discussionTools.debug' );
} else {
// eslint-disable-next-line no-jquery/no-global-selector
mw.dt.controller.init( $( '#mw-content-text' ) );
mw.hook( 'wikipage.content' ).add( function ( $container ) {
// Don't re-run if we already handled this element
if ( $container.closest( '.dt-init-done' ).length === 0 ) {
mw.dt.controller.init( $container.find( '#mw-content-text' ).addBack( '#mw-content-text' ) );
}
} );
}

View file

@ -11,3 +11,15 @@
pointer-events: none;
}
}
.dt-init-highlight {
background: rgba( 255, 204, 51, 0.5 );
position: absolute;
pointer-events: none;
opacity: 1;
transition: opacity 500ms;
}
.dt-init-highlight-fade {
opacity: 0;
}

View file

@ -5,13 +5,15 @@
* @extends OO.ui.Widget
* @constructor
* @param {Object} comment Parsed comment object
* @param {number} userCommentsBeforeReply User comments before this reply
* @param {Object} [config] Configuration options
*/
mw.dt.ui.ReplyWidget = function ( comment, config ) {
mw.dt.ui.ReplyWidget = function ( comment, userCommentsBeforeReply, config ) {
// Parent constructor
mw.dt.ui.ReplyWidget.super.call( this, config );
this.comment = comment;
this.userCommentsBeforeReply = userCommentsBeforeReply;
this.textWidget = new OO.ui.MultilineTextInputWidget( $.extend( {
rows: 3,
@ -63,7 +65,27 @@ mw.dt.ui.ReplyWidget.prototype.onReplyClick = function () {
this.comment.parsoidPromise.then( function ( parsoidData ) {
return mw.dt.controller.postReply( widget, parsoidData );
} ).then( function () {
location.reload();
} ).then( function ( data ) {
// eslint-disable-next-line no-jquery/no-global-selector
var $container = $( '#mw-content-text' );
// Update page state
$container.html( data.content );
mw.config.set( {
wgCurRevisionId: data.newrevid,
wgRevisionId: data.newrevid
} );
mw.config.set( data.jsconfigvars );
mw.loader.load( data.modules );
// TODO update categories, lastmodified
// (see ve.init.mw.DesktopArticleTarget.prototype.replacePageContent)
// Re-initialize
mw.dt.controller.init( $container, {
userCommentsBeforeReply: widget.userCommentsBeforeReply
} );
mw.hook( 'wikipage.content' ).fire( $container );
// TODO: Tell controller to teardown all previous widgets
} );
};