Florianschmidtwelzow has uploaded a new change for review.
https://gerrit.wikimedia.org/r/260578
Change subject: [WIP/MobileFrontend] Add link preview feature to mobile beta
mode
......................................................................
[WIP/MobileFrontend] Add link preview feature to mobile beta mode
Linkpreview will try to fetch a text extract using the api and, if this
doesn't fail, show the extract as a drawer with a button "Continue to
article". If the query fails, it will redirect the user to the article
directly.
ToDo:
* There should be an option to disable this feature (maybe in mobile
settings, or in the drawer)
Bug: T113243
Change-Id: Idbaae9fe2decd89b73e623a25fbd39464c316fb2
---
M Popups.hooks.php
M extension.json
M i18n/en.json
M i18n/qqq.json
A resources/ext.popups.mobilelinkpreview.init/initLinkPreview.js
A resources/ext.popups.mobilelinkpreview/LinkPreview.less
A resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.hogan
A resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.js
8 files changed, 349 insertions(+), 2 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Popups
refs/changes/78/260578/1
diff --git a/Popups.hooks.php b/Popups.hooks.php
index 2743b02..b02f597 100644
--- a/Popups.hooks.php
+++ b/Popups.hooks.php
@@ -66,6 +66,8 @@
* @return bool
*/
public static function onResourceLoaderRegisterModules( ResourceLoader
$rl ) {
+ global $wgMFResourceFileModuleBoilerplate;
+
$moduleDependencies = array(
'mediawiki.api',
'mediawiki.RegExp',
@@ -119,6 +121,49 @@
'localBasePath' => __DIR__,
) );
+ // if MobileFrontend is installed, register mobile popups
modules
+ // FIXME: Use ExtensionRegistry::getInstance()->isLoaded(
'MobileFrontend' ) once T88057
+ // is fixed
+ if ( class_exists( 'MobileFrontendHooks' ) &&
MobileContext::singleton()->isBetaGroupMember() ) {
+ $rl->register( 'ext.popups.mobilelinkpreview.init',
array(
+ 'dependencies' => array(
+ 'mobile.context',
+ 'mobile.settings',
+ ),
+ 'scripts' => array(
+
'resources/ext.popups.mobilelinkpreview.init/initLinkPreview.js',
+ ),
+ 'targets' => array( 'mobile' ),
+ 'remoteExtPath' => 'Popups',
+ 'localBasePath' => __DIR__,
+ )
+ );
+
+ $rl->register( 'ext.popups.mobilelinkpreview', array(
+ 'dependencies' => array(
+
'ext.popups.mobilelinkpreview.init',
+ 'mobile.drawers',
+ ),
+ 'scripts' => array(
+
'resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.js'
+ ),
+ 'templates' => array(
+ 'LinkPreviewDrawer.hogan' =>
'resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.hogan',
+ ),
+ 'styles' => array(
+
'resources/ext.popups.mobilelinkpreview/LinkPreview.less',
+ ),
+ 'messages' => array(
+
'popups-mobile-continue-to-article',
+ 'popups-mobile-dismiss',
+ ),
+ 'targets' => array( 'mobile' ),
+ 'remoteExtPath' => 'Popups',
+ 'localBasePath' => __DIR__,
+ )
+ );
+ }
+
return true;
}
@@ -151,6 +196,19 @@
}
/**
+ * Handler for MobileFrontend's BeforePageDisplay hook, which is only
called in mobile mode.
+ *
+ * @param OutputPage &$out,
+ * @param Skin &$skin
+ */
+ public static function onBeforePageDisplayMobile( OutputPage &$out,
Skin &$skin ) {
+ // enable mobile link preview in mobile beta
+ if ( MobileContext::singleton()->isBetaGroupMember() ) {
+ $out->addModules( 'ext.popups.mobilelinkpreview.init' );
+ }
+ }
+
+ /**
* @param array &$testModules
* @param ResourceLoader $resourceLoader
* @return bool
diff --git a/extension.json b/extension.json
index 56111f6..a2a0e26 100644
--- a/extension.json
+++ b/extension.json
@@ -32,6 +32,9 @@
],
"ResourceLoaderGetConfigVars": [
"PopupsHooks::onResourceLoaderGetConfigVars"
+ ],
+ "BeforePageDisplayMobile": [
+ "PopupsHooks::onBeforePageDisplayMobile"
]
},
"MessagesDirs": {
diff --git a/i18n/en.json b/i18n/en.json
index d1c30d2..5edc08a 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -19,5 +19,7 @@
"popups-settings-cancel": "Cancel",
"popups-settings-help": "You can turn previews back on using a link in
the footer of the page.",
"popups-settings-enable": "Enable previews",
- "popups-send-feedback": "Send Feedback (external link)"
+ "popups-send-feedback": "Send Feedback (external link)",
+ "popups-mobile-continue-to-article": "Continue to article",
+ "popups-mobile-dismiss": "Dismiss"
}
diff --git a/i18n/qqq.json b/i18n/qqq.json
index f0d21b1..fe39d56 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -24,5 +24,7 @@
"popups-settings-cancel": "Cancel button for the setting's
dialog\n{{Identical|Cancel}}",
"popups-settings-help": "Help text explaining how to re-enable
previews",
"popups-settings-enable": "Link on the footer to enable hovercards if
its disabled.\n\nSee also:\n* {{msg-mw|Popups-settings-option-off}}",
- "popups-send-feedback": "Tooltip for the send feedback icon on the
hovercard. Should mention that its an external link.\n{{Identical|Send
feedback}}"
+ "popups-send-feedback": "Tooltip for the send feedback icon on the
hovercard. Should mention that its an external link.\n{{Identical|Send
feedback}}",
+ "popups-mobile-continue-to-articl": "Button label visible in the link
preview drawer. When clicked, the brwoser redirects to the target article.",
+ "popups-mobile-dismiss": "Label of button that dismisses the link
preview overlay."
}
diff --git a/resources/ext.popups.mobilelinkpreview.init/initLinkPreview.js
b/resources/ext.popups.mobilelinkpreview.init/initLinkPreview.js
new file mode 100644
index 0000000..9875cd0
--- /dev/null
+++ b/resources/ext.popups.mobilelinkpreview.init/initLinkPreview.js
@@ -0,0 +1,22 @@
+( function ( M, $ ) {
+ var context = M.require( 'mobile.context/context' ),
+ settings = M.require( 'mobile.settings/settings' );
+
+ if ( !settings.get( 'mf-disable-linkpreview' ) ) {
+ mw.loader.using( 'ext.popups.mobilelinkpreview' ).done(
function () {
+ var LinkPreviewDrawer = M.require(
'ext.popups.mobilelinkpreview/LinkPreviewDrawer' ),
+ drawer;
+
+ // show linkpreview only for internal and existing
links. All others should work
+ // like "normal" links (redirecting to the target)"
+ $( '#bodyContent a:not(.new .external)' ).on( 'click',
function ( ev ) {
+ if ( !drawer ) {
+ drawer = new LinkPreviewDrawer();
+ }
+ drawer.loadNew( ev.target.title );
+
+ return false;
+ } );
+ } );
+ }
+}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/ext.popups.mobilelinkpreview/LinkPreview.less
b/resources/ext.popups.mobilelinkpreview/LinkPreview.less
new file mode 100644
index 0000000..fcb6cc1
--- /dev/null
+++ b/resources/ext.popups.mobilelinkpreview/LinkPreview.less
@@ -0,0 +1,51 @@
+@import "minerva.variables";
+
+.drawer.linkpreview {
+ position: fixed;
+ background-color: white;
+ text-align: left;
+ padding: 0 15px 20px;
+
+ &.loading {
+ padding: 10px;
+ }
+}
+
+.linkpreview-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ z-index: @z-indexOverlay;
+ background-color: rgba(0,0,0,0.1);
+ background-attachment: fixed;
+}
+
+.linkpreview-title {
+ font-family: Georgia;
+ font-size: 22px;
+ margin-top: 20px;
+ line-height: 1;
+}
+
+.linkpreview-content {
+ font-size: 15px;
+ margin-top: 20px;
+}
+
+.linkpreview-actions {
+ margin-top: 20px;
+ text-align: right;
+
+ .mw-ui-button {
+ margin-bottom: 0 !important;
+ }
+}
+
+@media all and (min-width: @wgMFDeviceWidthTablet) {
+ .drawer.linkpreview {
+ padding-left: 30px;
+ padding-right: 30px;
+ }
+}
diff --git a/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.hogan
b/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.hogan
new file mode 100644
index 0000000..5899505
--- /dev/null
+++ b/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.hogan
@@ -0,0 +1,6 @@
+<div class="linkpreview">
+ <div class="linkpreview-title"></div>
+ <div class="linkpreview-content"></div>
+ <div
class="linkpreview-actions">{{#dismissButton}}{{>Button}}{{/dismissButton}}{{#continueButton}}{{>Button}}{{/continueButton}}</div>
+</div>
+{{{spinner}}}
diff --git a/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.js
b/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.js
new file mode 100644
index 0000000..1320c4c
--- /dev/null
+++ b/resources/ext.popups.mobilelinkpreview/LinkPreviewDrawer.js
@@ -0,0 +1,203 @@
+( function ( M, $ ) {
+ var LinkPreviewDrawer,
+ Drawer = M.require( 'mobile.drawers/Drawer' ),
+ Button = M.require( 'mobile.startup/Button' ),
+ icons = M.require( 'mobile.startup/icons' );
+
+ LinkPreviewDrawer = Drawer.extend( {
+ /**
+ * @cfg {Object} defaults Default options hash.
+ * @cfg {String} defaults.spinner html of spinner icon
+ * @cfg {Object} defaults.continueButton HTML of the continue
button.
+ */
+ defaults: {
+ spinner: icons.spinner().toHtmlString(),
+ continueButton: new Button( {
+ progressive: true,
+ label: mw.msg(
'popups-mobile-continue-to-article' ),
+ additionalClassNames: 'linkpreview-continue'
+ } ).options,
+ dismissButton: new Button( {
+ label: mw.msg( 'popups-mobile-dismiss' ),
+ additionalClassNames: 'linkpreview-dismiss'
+ } ).options
+ },
+
+ /**
+ * @inheritdoc
+ */
+ template: mw.template.get( 'ext.popups.mobilelinkpreview',
'LinkPreviewDrawer.hogan' ),
+
+ /**
+ * @inheritdoc
+ */
+ templatePartials: {
+ Button: Button.prototype.template
+ },
+
+ /**
+ * @inheritdoc
+ */
+ events: $.extend( {}, Drawer.prototype.events, {
+ 'click .linkpreview-continue': 'onContinueClick',
+ 'click .linkpreview-dismiss': 'hide'
+ } ),
+
+ /**
+ * @inheritdoc
+ */
+ className: 'drawer linkpreview',
+
+ /**
+ * @inheritdoc
+ */
+ closeOnScroll: false,
+
+ /**
+ * Cache for the api queries.
+ *
+ * @property {Object}
+ */
+ cache: {},
+
+ /**
+ * @inheritdoc
+ */
+ postRender: function () {
+ var $linkpreviewOverlay;
+
+ Drawer.prototype.postRender.apply( this, arguments );
+
+ $linkpreviewOverlay = $( '<div>' )
+ .addClass( 'linkpreview-overlay hidden' );
+ this.$el.before( $linkpreviewOverlay );
+ this.$linkpreview = this.$( '.linkpreview' );
+ this.$spinner = this.$( '.spinner' );
+ this.api = new mw.Api();
+ },
+
+ /**
+ * @inheritdoc
+ */
+ show: function () {
+ $( '.linkpreview-overlay' ).removeClass( 'hidden' );
+ Drawer.prototype.show.apply( this, arguments );
+ },
+
+ /**
+ * @inheritdoc
+ */
+ hide: function () {
+ Drawer.prototype.hide.apply( this, arguments );
+ $( '.linkpreview-overlay' ).addClass( 'hidden' );
+ },
+
+ /**
+ * Show the drawer with the initial spinner (and hide the
content,
+ * that was (maybe) already added.
+ *
+ * @return {Object} this
+ */
+ showWithSpinner: function () {
+ this.$spinner.removeClass( 'hidden' );
+ this.$el.addClass( 'loading' );
+ this.$linkpreview.addClass( 'hidden' );
+ this.show();
+
+ return this;
+ },
+
+ /**
+ * Hide the spinner (if any) and show the content of the drawer.
+ *
+ * @return {Object} this
+ */
+ showContent: function () {
+ this.$spinner.addClass( 'hidden' );
+ this.$el.removeClass( 'loading' );
+ this.$linkpreview.removeClass( 'hidden' );
+
+ return this;
+ },
+
+ /**
+ * Load content from a given title, show it or redirect to this
+ * title if something went wrong.
+ *
+ * @param {String} title The target title
+ */
+ loadNew: function ( title ) {
+ var self = this;
+
+ this.showWithSpinner();
+ this.title = title;
+
+ if ( !this.cache[title] ) {
+ this.api.get( {
+ action: 'query',
+ titles: title,
+ prop: 'extracts',
+ explaintext: true,
+ exintro: true,
+ exchars: 140,
+ formatversion: 2
+ } ).done( function ( result ) {
+ var data;
+
+ if ( result.query.pages[0] ) {
+ data = result.query.pages[0];
+ self
+ .setTitle( data.title )
+ .setContent(
data.extract )
+ .showContent();
+
+ self.cache[title] = data;
+ } else {
+ self.onContinueClick();
+ }
+ } ).fail( function () {
+ self.onContinueClick();
+ } );
+ } else {
+ self
+ .setTitle( this.cache[title].title )
+ .setContent( this.cache[title].extract )
+ .showContent();
+ }
+ },
+
+ /**
+ * Replace the current visible title with the given one.
+ *
+ * @param {String} title The new title (HTML isn't supported)
+ * @return {Object} this
+ */
+ setTitle: function ( title ) {
+ this.$( '.linkpreview-title' ).text( title );
+
+ return this;
+ },
+
+ /**
+ * Replace the current visible content with the given one.
+ *
+ * @param {String} content The new content (HTML isn't
supported)
+ * @return {Object} this
+ */
+ setContent: function ( content ) {
+ this.$( '.linkpreview-content' ).text( content );
+
+ return this;
+ },
+
+ /**
+ * Handle the click on the "continue to article" button and
redirect to the
+ * title (this.title).
+ */
+ onContinueClick: function () {
+ window.location.href = mw.util.getUrl( this.title );
+ }
+ } );
+
+ M.define( 'ext.popups.mobilelinkpreview/LinkPreviewDrawer',
LinkPreviewDrawer );
+}( mw.mobileFrontend, jQuery ) );
--
To view, visit https://gerrit.wikimedia.org/r/260578
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idbaae9fe2decd89b73e623a25fbd39464c316fb2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Popups
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits