Florianschmidtwelzow has uploaded a new change for review. https://gerrit.wikimedia.org/r/254776
Change subject: [WIP] Add link preview feature to beta mode ...................................................................... [WIP] Add link preview feature to 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 i18n/en.json M i18n/qqq.json M includes/Resources.php A resources/mobile.linkpreview.init/initLinkPreview.js A resources/mobile.linkpreview/LinkPreview.less A resources/mobile.linkpreview/LinkPreviewApi.js A resources/mobile.linkpreview/LinkPreviewDrawer.hogan A resources/mobile.linkpreview/LinkPreviewDrawer.js 8 files changed, 265 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend refs/changes/76/254776/1 diff --git a/i18n/en.json b/i18n/en.json index d0d9be6..6c16ce7 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -205,6 +205,7 @@ "mobile-frontend-last-modified-years": "Last edited {{PLURAL:$1|$1 year|$1 years}} ago", "mobile-frontend-lead-image-tutorial-confirm": "Start uploading", "mobile-frontend-lead-image-tutorial-summary": "Ensure that your image can help illustrate the page. It should be an image that you created which does not violate copyright.", + "mobile-frontend-linkpreview-continue-to-article": "Continue to article", "mobile-frontend-logged-in-homepage-notification": "{{GENDER:$1|Welcome}}, $1!", "mobile-frontend-logged-in-toast-notification": "Logged in as $1.", "mobile-frontend-main-menu": "Main Menu", diff --git a/i18n/qqq.json b/i18n/qqq.json index c223075..0c425e4 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -201,6 +201,7 @@ "mobile-frontend-last-modified-years": "Text displayed on page to show how long ago the page was updated. Parameters:\n* $1 - number of years\n{{Related|Mobile-frontend-last-modified}}", "mobile-frontend-lead-image-tutorial-confirm": "Call to action that when clicked starts uploading an image to a page from tutorial.", "mobile-frontend-lead-image-tutorial-summary": "Briefly summarise that a lead image should illustrate the page whilst not violating copyright. Shown to new users after logging in", + "mobile-frontend-linkpreview-continue-to-article": "Button label visible in the link preview drawer. When clicked, the brwoser redirects to the target article.", "mobile-frontend-logged-in-homepage-notification": "Heading at top of homepage telling user they are logged in. Parameters:\n* $1 - username", "mobile-frontend-logged-in-toast-notification": "Message telling user that they are logged in. Shows as a notification at bottom of page\n*$1 - username", "mobile-frontend-main-menu": "Message that is displayed as a tooltip for the main menu icon in the header", diff --git a/includes/Resources.php b/includes/Resources.php index 684a59c..d7ee94b 100644 --- a/includes/Resources.php +++ b/includes/Resources.php @@ -1193,6 +1193,35 @@ ), ), + 'mobile.linkpreview.init' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.context', + 'mobile.settings', + ), + 'scripts' => array( + 'resources/mobile.linkpreview.init/initLinkPreview.js', + ), + ), + + 'mobile.linkpreview' => $wgMFResourceFileModuleBoilerplate + array( + 'dependencies' => array( + 'mobile.linkpreview.init', + 'mobile.drawers', + ), + 'scripts' => array( + 'resources/mobile.linkpreview/LinkPreviewDrawer.js' + ), + 'templates' => array( + 'LinkPreviewDrawer.hogan' => 'resources/mobile.linkpreview/LinkPreviewDrawer.hogan', + ), + 'styles' => array( + 'resources/mobile.linkpreview/LinkPreview.less', + ), + 'messages' => array( + 'mobile-frontend-linkpreview-continue-to-article', + ), + ), + // Custom ResourceLoaderModule classes 'mobile.site' => array( 'dependencies' => array( 'mobile.startup' ), @@ -1638,6 +1667,7 @@ // load code under certain conditions. 'mobile.search.beta', 'mobile.backtotop', + 'mobile.linkpreview.init', ), 'scripts' => array( 'resources/skins.minerva.beta.scripts/commonsCategory.js', diff --git a/resources/mobile.linkpreview.init/initLinkPreview.js b/resources/mobile.linkpreview.init/initLinkPreview.js new file mode 100644 index 0000000..02b16b3 --- /dev/null +++ b/resources/mobile.linkpreview.init/initLinkPreview.js @@ -0,0 +1,19 @@ +( function ( M, $ ) { + var context = M.require( 'mobile.context/context' ), + settings = M.require( 'mobile.settings/settings' ); + + if ( context.isBetaGroupMember() && !settings.get( 'mf-disable-linkpreview' ) ) { + mw.loader.using( 'mobile.linkpreview' ).done( function () { + var LinkPreviewDrawer = M.require( 'mobile.linkpreview/LinkPreviewDrawer' ), + drawer = new LinkPreviewDrawer(); + + // 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 ) { + drawer.loadNew( ev.target.title ); + + return false; + } ); + } ); + } +}( mw.mobileFrontend, jQuery ) ); diff --git a/resources/mobile.linkpreview/LinkPreview.less b/resources/mobile.linkpreview/LinkPreview.less new file mode 100644 index 0000000..28dfdf5 --- /dev/null +++ b/resources/mobile.linkpreview/LinkPreview.less @@ -0,0 +1,33 @@ +.drawer.linkpreview { + position: fixed; + background-color: white; + text-align: left; + padding: 0 15px 20px; +} + +.linkpreview-title { + font-family: Georgia; + font-size: 22px; + margin-top: 20px; +} + +.linkpreview-content { + font-size: 15px; + margin-top: 20px; +} + +.linkpreview-continue { + text-align: center; + margin-top: 20px; + + .mw-ui-button { + margin-bottom: 0; + } +} + +@media all and (min-width: @wgMFDeviceWidthTablet) { + .drawer.linkpreview { + padding-left: 30px; + padding-right: 30px; + } +} diff --git a/resources/mobile.linkpreview/LinkPreviewApi.js b/resources/mobile.linkpreview/LinkPreviewApi.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/resources/mobile.linkpreview/LinkPreviewApi.js diff --git a/resources/mobile.linkpreview/LinkPreviewDrawer.hogan b/resources/mobile.linkpreview/LinkPreviewDrawer.hogan new file mode 100644 index 0000000..571947b --- /dev/null +++ b/resources/mobile.linkpreview/LinkPreviewDrawer.hogan @@ -0,0 +1,6 @@ +<div class="linkpreview"> + <div class="linkpreview-title"></div> + <div class="linkpreview-content"></div> + <div class="linkpreview-continue">{{#continueButton}}{{>Button}}{{/continueButton}}</div> +</div> +{{{spinner}}} diff --git a/resources/mobile.linkpreview/LinkPreviewDrawer.js b/resources/mobile.linkpreview/LinkPreviewDrawer.js new file mode 100644 index 0000000..e2dd002 --- /dev/null +++ b/resources/mobile.linkpreview/LinkPreviewDrawer.js @@ -0,0 +1,175 @@ +( 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( { + /** + * @inheritdoc + * @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( 'mobile-frontend-linkpreview-continue-to-article' ) + } ).options + }, + + /** + * @inheritdoc + */ + template: mw.template.get( 'mobile.linkpreview', 'LinkPreviewDrawer.hogan' ), + + /** + * @inheritdoc + */ + templatePartials: { + Button: Button.prototype.template + }, + + /** + * @inheritdoc + */ + events: $.extend( {}, Drawer.prototype.events, { + 'click .linkpreview-continue a': 'onContinueClick' + } ), + + /** + * @inheritdoc + */ + className: 'drawer linkpreview', + + /** + * @inheritdoc + */ + closeOnScroll: false, + + /** + * Cache for the api queries. + * + * @property {Object} + */ + cache: {}, + + /** + * @inheritdoc + */ + postRender: function () { + Drawer.prototype.postRender.apply( this, arguments ); + + this.$linkpreview = this.$( '.linkpreview' ); + this.$spinner = this.$( '.spinner' ); + this.api = new mw.Api(); + }, + + /** + * 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.$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.$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( 'mobile.linkpreview/LinkPreviewDrawer', LinkPreviewDrawer ); +}( mw.mobileFrontend, jQuery ) ); -- To view, visit https://gerrit.wikimedia.org/r/254776 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Idbaae9fe2decd89b73e623a25fbd39464c316fb2 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/MobileFrontend Gerrit-Branch: master Gerrit-Owner: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits