mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/DiscussionTools
synced 2024-11-11 17:02:28 +00:00
Merge "Show a "Return to reply/new topic" button when widget is scrolled off the screen"
This commit is contained in:
commit
6e57e3ba78
|
@ -194,6 +194,8 @@
|
|||
"discussiontools-replywidget-preferences",
|
||||
"discussiontools-replywidget-preview",
|
||||
"discussiontools-replywidget-reply",
|
||||
"discussiontools-replywidget-return-to-newtopic",
|
||||
"discussiontools-replywidget-return-to-reply",
|
||||
"discussiontools-replywidget-summary",
|
||||
"discussiontools-replywidget-transcluded",
|
||||
"ooui-popup-widget-close-button-aria-label",
|
||||
|
|
|
@ -97,6 +97,8 @@
|
|||
"discussiontools-replywidget-preview": "Preview",
|
||||
"discussiontools-replywidget-reply": "Reply",
|
||||
"discussiontools-replywidget-reply-link": "https://www.mediawiki.org/wiki/Special:MyLanguage/Talk_pages_project/Replying",
|
||||
"discussiontools-replywidget-return-to-newtopic": "Return to new topic",
|
||||
"discussiontools-replywidget-return-to-reply": "Return to reply",
|
||||
"discussiontools-replywidget-signature-body": "$1 has been transformed into your signature. To undo this, type $2. Note that you don't need to sign comments with this tool. Your signature will be added automatically.",
|
||||
"discussiontools-replywidget-signature-title": "Signature markup detected",
|
||||
"discussiontools-replywidget-summary": "Summary",
|
||||
|
|
|
@ -108,6 +108,8 @@
|
|||
"discussiontools-replywidget-preview": "Label for the preview area of the reply widget",
|
||||
"discussiontools-replywidget-reply": "Label for the button to submit a reply in the reply widget",
|
||||
"discussiontools-replywidget-reply-link": "{{notranslate}}\nUsed by {{msg-mw|Tag-discussiontools-reply}} as a link to a page where users learn about the feature. Defaults to a page on MediaWiki.org.",
|
||||
"discussiontools-replywidget-return-to-newtopic": "Label for the button to scroll the new topic widget back into view.",
|
||||
"discussiontools-replywidget-return-to-reply": "Label for the button to scroll the reply widget back into view.",
|
||||
"discussiontools-replywidget-signature-body": "Body of the warning about typing in your signature.\n\nParameters:\n* $1 – the signature markup, i.e. <code><nowiki>~~~~</nowiki></code>\n* $2 – localised keyboard shortcut to undo, for example <kbd><kbd>Ctrl</kbd>+<kbd>Z</kbd></kbd>",
|
||||
"discussiontools-replywidget-signature-title": "Title of the warning about typing in your signature",
|
||||
"discussiontools-replywidget-summary": "Label for the summary field that describes your comment. This will be stored as an edit summary, but in the context of the reply tool we don't want to refer to 'edits'\n{{identical|Summary}}",
|
||||
|
|
|
@ -47,6 +47,14 @@ function ReplyWidget( commentController, commentDetails, config ) {
|
|||
// eslint-disable-next-line no-jquery/no-global-selector
|
||||
this.contentDir = $( '#mw-content-text' ).css( 'direction' );
|
||||
this.hideNewCommentsWarning = false;
|
||||
// Floating position for scroll back buttons: 'top', 'bottom', or null
|
||||
this.floating = null;
|
||||
// Copied from ve.init.Platform.static.isIos
|
||||
this.isIos = /ipad|iphone|ipod/i.test( navigator.userAgent );
|
||||
|
||||
this.$window = $( this.getElementWindow() );
|
||||
this.onWindowScrollThrottled = OO.ui.throttle( this.onWindowScroll.bind( this ), 100 );
|
||||
this.onViewportChangeThrottled = OO.ui.throttle( this.onViewportChange.bind( this ), 100 );
|
||||
|
||||
var inputConfig = $.extend(
|
||||
{
|
||||
|
@ -200,6 +208,28 @@ function ReplyWidget( commentController, commentDetails, config ) {
|
|||
);
|
||||
this.$actionsWrapper.append( this.$footer, this.$actions );
|
||||
|
||||
this.viewportScrollContainer = OO.ui.Element.static.getClosestScrollableContainer( document.body );
|
||||
this.scrollBackTopButton = new OO.ui.ButtonWidget( {
|
||||
classes: [ 'ext-discussiontools-ui-replyWidget-scrollback-top' ],
|
||||
icon: 'collapse',
|
||||
label: mw.msg(
|
||||
this.isNewTopic ?
|
||||
'discussiontools-replywidget-return-to-newtopic' :
|
||||
'discussiontools-replywidget-return-to-reply'
|
||||
),
|
||||
flags: [ 'progressive' ]
|
||||
} );
|
||||
this.scrollBackBottomButton = new OO.ui.ButtonWidget( {
|
||||
classes: [ 'ext-discussiontools-ui-replyWidget-scrollback-bottom' ],
|
||||
icon: 'expand',
|
||||
label: mw.msg(
|
||||
this.isNewTopic ?
|
||||
'discussiontools-replywidget-return-to-newtopic' :
|
||||
'discussiontools-replywidget-return-to-reply'
|
||||
),
|
||||
flags: [ 'progressive' ]
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.replyButton.connect( this, { click: 'onReplyClick' } );
|
||||
this.cancelButton.connect( this, { click: 'tryTeardown' } );
|
||||
|
@ -213,6 +243,8 @@ function ReplyWidget( commentController, commentDetails, config ) {
|
|||
if ( this.isNewTopic ) {
|
||||
this.commentController.sectionTitle.$input.on( 'keydown', this.onKeyDown.bind( this, false ) );
|
||||
}
|
||||
this.scrollBackTopButton.connect( this, { click: 'onScrollBackButtonClick' } );
|
||||
this.scrollBackBottomButton.connect( this, { click: 'onScrollBackButtonClick' } );
|
||||
|
||||
this.onInputChangeThrottled = OO.ui.throttle( this.onInputChange.bind( this ), 1000 );
|
||||
|
||||
|
@ -223,7 +255,9 @@ function ReplyWidget( commentController, commentDetails, config ) {
|
|||
this.$preview,
|
||||
this.advancedToggle.$element,
|
||||
this.advanced.$element,
|
||||
this.$actionsWrapper
|
||||
this.$actionsWrapper,
|
||||
this.scrollBackTopButton.$element,
|
||||
this.scrollBackBottomButton.$element
|
||||
);
|
||||
// Set direction to interface direction
|
||||
this.$element.attr( 'dir', $( document.body ).css( 'direction' ) );
|
||||
|
@ -364,6 +398,41 @@ ReplyWidget.prototype.clearStorage = function () {
|
|||
this.emit( 'clearStorage' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle window scroll events
|
||||
*/
|
||||
ReplyWidget.prototype.onWindowScroll = function () {
|
||||
var rect = this.$element[ 0 ].getBoundingClientRect();
|
||||
var viewportHeight = window.visualViewport ? visualViewport.height : this.viewportScrollContainer.clientHeight;
|
||||
var floating = rect.bottom < 0 ? 'top' :
|
||||
( rect.top > viewportHeight ? 'bottom' : null );
|
||||
|
||||
if ( floating !== this.floating ) {
|
||||
this.floating = floating;
|
||||
// Always remove classes as we have switched directly from top to bottom with a fast scroll
|
||||
this.$element
|
||||
.removeClass( 'ext-discussiontools-ui-replyWidget-floating-top ext-discussiontools-ui-replyWidget-floating-bottom' );
|
||||
|
||||
if ( this.floating ) {
|
||||
// The following classes are used here:
|
||||
// * ext-discussiontools-ui-replyWidget-floating-top
|
||||
// * ext-discussiontools-ui-replyWidget-floating-bottom
|
||||
this.$element.addClass( 'ext-discussiontools-ui-replyWidget-floating-' + this.floating );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle events which change the visualViewport (scroll/resize)
|
||||
*/
|
||||
ReplyWidget.prototype.onViewportChange = function () {
|
||||
if ( this.floating ) {
|
||||
var isKeyboardOpen = visualViewport.height < this.viewportScrollContainer.clientHeight;
|
||||
this.scrollBackBottomButton.toggle( !isKeyboardOpen );
|
||||
this.scrollBackTopButton.toggle( !isKeyboardOpen );
|
||||
}
|
||||
};
|
||||
|
||||
ReplyWidget.prototype.setPending = function ( pending ) {
|
||||
this.pending = pending;
|
||||
if ( pending ) {
|
||||
|
@ -554,6 +623,12 @@ ReplyWidget.prototype.setup = function ( data ) {
|
|||
|
||||
mw.hook( 'wikipage.watchlistChange' ).add( this.onWatchToggleHandler );
|
||||
|
||||
// TODO: Use ve.addPassiveEventListener
|
||||
this.$window.on( 'scroll', this.onWindowScrollThrottled );
|
||||
if ( this.isIos && window.visualViewport ) {
|
||||
$( visualViewport ).on( 'scroll resize', this.onViewportChangeThrottled );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -639,6 +714,10 @@ ReplyWidget.prototype.teardown = function ( mode ) {
|
|||
this.modeTabSelect.blur();
|
||||
}
|
||||
this.unbindBeforeUnloadHandler();
|
||||
this.$window.off( 'scroll', this.onWindowScrollThrottled );
|
||||
if ( this.isIos && window.visualViewport ) {
|
||||
$( visualViewport ).off( 'scroll resize', this.onViewportChangeThrottled );
|
||||
}
|
||||
mw.hook( 'wikipage.watchlistChange' ).remove( this.onWatchToggleHandler );
|
||||
|
||||
this.clear( mode === 'refresh' );
|
||||
|
@ -1008,4 +1087,11 @@ ReplyWidget.prototype.onReplyClick = function () {
|
|||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle click events on one of the scroll back buttons
|
||||
*/
|
||||
ReplyWidget.prototype.onScrollBackButtonClick = function () {
|
||||
this.commentController.showAndFocus();
|
||||
};
|
||||
|
||||
module.exports = ReplyWidget;
|
||||
|
|
|
@ -48,6 +48,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
&-scrollback-top {
|
||||
transform: translate( -50%, -150% );
|
||||
top: 0;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
&-scrollback-bottom {
|
||||
transform: translate( -50%, 150% );
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
&-scrollback-top,
|
||||
&-scrollback-bottom {
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
transition: transform 250ms, opacity 250ms;
|
||||
z-index: 1;
|
||||
margin: 1em 0;
|
||||
box-shadow: 0 2px 2px 0 rgba( 0, 0, 0, 0.25 );
|
||||
|
||||
.skin-monobook & {
|
||||
box-shadow: 0 0.2em 1em rgba( 0, 0, 0, 0.3 );
|
||||
}
|
||||
}
|
||||
|
||||
&-floating-top &-scrollback-top,
|
||||
&-floating-bottom &-scrollback-bottom {
|
||||
opacity: 1;
|
||||
transform: translate( -50%, 0 );
|
||||
}
|
||||
|
||||
.ve-ui-targetToolbar > .oo-ui-toolbar-bar {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
|
|
Loading…
Reference in a new issue