diff --git a/i18n/en.json b/i18n/en.json index d26dbdc..896ea11 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -8,6 +8,9 @@ "mobile-frontend-editor-disabled": "This page is protected to prevent vandalism.", "mobile-frontend-editor-edit": "Edit", "minerva-download": "Download", + "skin-minerva-share": "Share", + "skin-minerva-mobile-option-MinervaShareButton": "Share", + "skin-minerva-mobile-option-MinervaShareButton-description": "Share current article via browser share feature", "mobile-frontend-editor-redlink-create": "Create page", "mobile-frontend-editor-redlink-explain": "This page has not yet been created.", "mobile-frontend-editor-redlink-leave": "No, thanks.", diff --git a/i18n/qqq.json b/i18n/qqq.json index 7216597..ec072af 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -17,6 +17,9 @@ "mobile-frontend-editor-disabled": "Toast message that appears when a user is unable to edit a page and clicks edit icon.", "mobile-frontend-editor-edit": "Caption for the link showing edit form. (In the imperative mood)\n{{Identical|Edit}}", "minerva-download": "Caption for the download button (in the imperative mood).\n{{Identical|Download}}", + "skin-minerva-share": "Caption for the share button (in the imperative mood).\n{{Identical|Share}}", + "skin-minerva-mobile-option-MinervaShareButton": "Label for Share mobile web beta feature", + "skin-minerva-mobile-option-MinervaShareButton-description": "Description label for share mobile web beta feature", "mobile-frontend-editor-redlink-create": "Label for a create page button.\n{{Identical|Create page}}", "mobile-frontend-editor-redlink-explain": "Question for the user, if he want to edit a page, which link he clicked and that does not exist yet, or not.", "mobile-frontend-editor-redlink-leave": "Used as a label for a button which the user can click to avoid editing a page which does not exist yet (red link): the question/alternative button is {{msg-mw|mobile-frontend-editor-redlink-create}}\n----\n{{Identical|No thanks}}", diff --git a/includes/MinervaHooks.php b/includes/MinervaHooks.php index 08c51b3..2ede615 100644 --- a/includes/MinervaHooks.php +++ b/includes/MinervaHooks.php @@ -53,6 +53,13 @@ class MinervaHooks { $config->get( 'MinervaEnableBackToTop' ) ) ); + $featureManager->registerFeature( + new MobileFrontend\Features\Feature( + 'MinervaShareButton', + 'skin-minerva', + $config->get( 'MinervaShowShareButton' ) + ) + ); } catch ( RuntimeException $e ) { // features already registered... // due to a bug it's possible for this to run twice @@ -175,6 +182,8 @@ class MinervaHooks { $mobileContext ), SkinMinerva::OPTION_BACK_TO_TOP => $featureManager->isFeatureAvailableInContext( 'MinervaEnableBackToTop', $mobileContext ), + SkinMinerva::OPTION_SHARE_BUTTON + => $featureManager->isFeatureAvailableInContext( 'MinervaShareButton', $mobileContext ), SkinMinerva::OPTION_TOGGLING => true, SkinMinerva::OPTION_MOBILE_OPTIONS => true, ] ); diff --git a/includes/skins/SkinMinerva.php b/includes/skins/SkinMinerva.php index a5e8fc0..17ccbc6 100644 --- a/includes/skins/SkinMinerva.php +++ b/includes/skins/SkinMinerva.php @@ -32,6 +32,7 @@ class SkinMinerva extends SkinTemplate { const OPTION_MOBILE_OPTIONS = 'mobileOptionsLink'; const OPTION_CATEGORIES = 'categories'; const OPTION_BACK_TO_TOP = 'backToTop'; + const OPTION_SHARE_BUTTON = 'shareButton'; const OPTION_TOGGLING = 'toggling'; const OPTIONS_MOBILE_BETA = 'beta'; /** @const LEAD_SECTION_NUMBER integer which corresponds to the lead section @@ -99,6 +100,8 @@ class SkinMinerva extends SkinTemplate { self::OPTION_CATEGORIES => false, /** Whether a back to top button appears at the bottom of the view page */ self::OPTION_BACK_TO_TOP => false, + /** Whether a share button should appear in icons section */ + self::OPTION_SHARE_BUTTON => false, /** Whether sections can be collapsed (requires MobileFrontend and MobileFormatter) */ self::OPTION_TOGGLING => false, ]; @@ -1344,7 +1347,9 @@ class SkinMinerva extends SkinTemplate { if ( $this->hasSkinOptions() ) { $modules[] = 'skins.minerva.options'; } - + if ( $this->getSkinOption( self::OPTION_SHARE_BUTTON ) ) { + $modules[] = 'skins.minerva.share'; + } return $modules; } diff --git a/resources/skins.minerva.options/ShareIcon.js b/resources/skins.minerva.options/ShareIcon.js new file mode 100644 index 0000000..905d1c3 --- /dev/null +++ b/resources/skins.minerva.options/ShareIcon.js @@ -0,0 +1,41 @@ +( function ( M, msg, config ) { + var GLYPH = 'share', + Icon = M.require( 'mobile.startup/Icon' ); + + /** + * A download icon for triggering print functionality + * @class ShareIcon + * @extends Icon + + * @constructor + */ + function ShareIcon() { + var options = {}; + options.tagName = 'li'; + options.glyphPrefix = 'minerva'; + options.title = msg( 'skin-minerva-share' ); + options.name = GLYPH; + Icon.call( this, options ); + } + + OO.mfExtend( ShareIcon, Icon, { + /** + * onClick handler for button that invokes print function + * + * @memberof ShareIcon + * @instance + */ + onClick: function () { + navigator.share( { + title: config.get( 'wgTitle' ), + text: config.get( 'wgTitle' ), + url: window.location.href.split( '#' )[ 0 ] + } ); + }, + events: { + click: 'onClick' + } + } ); + + M.define( 'skins.minerva.share/ShareIcon', ShareIcon ); +}( mw.mobileFrontend, mw.msg, mw.config ) ); diff --git a/resources/skins.minerva.options/share.js b/resources/skins.minerva.options/share.js new file mode 100644 index 0000000..188547e --- /dev/null +++ b/resources/skins.minerva.options/share.js @@ -0,0 +1,23 @@ +( function ( M, config ) { + var ShareIcon = M.require( 'skins.minerva.share/ShareIcon' ), + features = config.get( 'wgMinervaFeatures', {} ); + + /** + * Checks whether ShareIcon is available for given user agent + * + * @return {boolean} + */ + function isShareAvailable() { + return navigator.share !== undefined; + } + + // check if browser supports share feature and the feature is enabled + if ( isShareAvailable() && features.shareButton ) { + // Because the page actions are floated to the right, their order in the + // DOM is reversed in the display. The watchstar is last in the DOM and + // left-most in the display. Since we want the download button to be to + // the left of the watchstar, we put it after it in the DOM. + new ShareIcon().$el.insertAfter( '#ca-watch' ); + } + +}( mw.mobileFrontend, mw.config ) ); diff --git a/resources/skins.minerva.options/share.svg b/resources/skins.minerva.options/share.svg new file mode 100644 index 0000000..4be5899 --- /dev/null +++ b/resources/skins.minerva.options/share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/skin.json b/skin.json index 2cc0373..0ee99df 100644 --- a/skin.json +++ b/skin.json @@ -40,6 +40,11 @@ "base": false, "beta": true }, + "MinervaShowShareButton": { + "prefix": "skin-minerva-", + "base": false, + "beta": true + }, "MinervaEnableBackToTop": { "prefix": "skin-minerva-", "base": false, @@ -516,6 +521,13 @@ "resources/skins.minerva.editor/init.js" ] }, + "skins.minerva.options.share.icon": { + "class": "ResourceLoaderImageModule", + "selector": ".mw-ui-icon-minerva-{name}:before", + "images": { + "share": "resources/skins.minerva.options/share.svg" + } + }, "skins.minerva.options": { "targets": [ "mobile", @@ -523,8 +535,13 @@ ], "dependencies": [ "skins.minerva.scripts", + "mediawiki.language", "mobile.toggle", - "mobile.startup" + "mobile.startup", + "skins.minerva.options.share.icon" + ], + "messages": [ + "skin-minerva-share" ], "templates": { "BackToTopOverlay.hogan": "resources/skins.minerva.options/BackToTopOverlay.hogan" @@ -535,7 +552,9 @@ "scripts": [ "resources/skins.minerva.options/BackToTopOverlay.js", "resources/skins.minerva.options/backtotop.js", - "resources/skins.minerva.options/categories.js" + "resources/skins.minerva.options/categories.js", + "resources/skins.minerva.options/ShareIcon.js", + "resources/skins.minerva.options/share.js" ] }, "skins.minerva.talk": {