From 49a2ab341755f3f63b5f034334f6e69890b8c493 Mon Sep 17 00:00:00 2001 From: Isarra Date: Wed, 28 Aug 2019 03:50:30 +0000 Subject: [PATCH] Add settings to use a particular layout even at higher resolutions (Cap at single column or single-sidebar instead of the default three- column mode.) Adds user preference options and a $wgTimelessDefaultLayout config to change the default wiki-wide. Intended for people who hate change and prefer the same navigation layout (sort of) as we've had forever, and for people who are really bad at change and just keep getting confused when everything keeps moving around across different sized devices, as well as anyone else who just likes... options, I guess? Whatever the case, this is seriously up there in the running for 'most requested feature'. Uses three separate modules to avoid sending all users the same styles twice regardless of what they'll even use, as each set is mostly the same, just with slightly different breakpoints. Not seeing any saner ways to do this, however, as even with LESS we can only use mixins/ includes/& afters to avoid the duplication in terms of what we work on, not what is generated. Bug: T131803 Change-Id: I0538d36c2ed7a5009b2a0f75952671ac9447fd56 --- i18n/en.json | 6 +++- i18n/qqq.json | 6 +++- includes/SkinTimeless.php | 67 +++++++++++++++++++++++++++++++++++++++ skin.json | 54 +++++++++++++++++++++++++------ 4 files changed, 122 insertions(+), 11 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 57a8911..326c606 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -23,5 +23,9 @@ "timeless-projects": "Other projects", "timeless-sitetitle": "{{int:Sitetitle}}", "timeless.css": "/* CSS placed here will affect users of the Timeless skin */", - "timeless.js": "/* Any JavaScript here will be loaded for users using the Timeless skin */" + "timeless.js": "/* Any JavaScript here will be loaded for users using the Timeless skin */", + "timeless-layout-preference": "Full-width desktop layout (Timeless skin):", + "timeless-pref-one-column": "Single column: no sidebars", + "timeless-pref-two-column": "Two-column: Left sidebar navigation only", + "timeless-pref-three-column": "Three-column: Navigation and tools on left and right sides of content" } diff --git a/i18n/qqq.json b/i18n/qqq.json index 4e367a4..ef278ab 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -30,5 +30,9 @@ "timeless-projects": "Label for the other projects dropdown", "timeless-sitetitle": "{{ignore}}\nSite title for site banner", "timeless.css": "{{optional}}\nCSS applied to users using Timeless skin.", - "timeless.js": "{{optional}}\nJS for users using Timeless skin." + "timeless.js": "{{optional}}\nJS for users using Timeless skin.", + "timeless-layout-preference": "Preferences label for full-width layout options", + "timeless-pref-one-column": "Label for single-column layout option", + "timeless-pref-two-column": "Label for two-column layout option", + "timeless-pref-three-column": "Label for three-column layout option" } diff --git a/includes/SkinTimeless.php b/includes/SkinTimeless.php index 937d2c1..8a0d117 100644 --- a/includes/SkinTimeless.php +++ b/includes/SkinTimeless.php @@ -29,6 +29,22 @@ class SkinTimeless extends SkinTemplate { 'mediawiki.skinning.content.externallinks', 'skins.timeless', ] ); + + $defaultLayout = $this->getConfig()->get( 'TimelessDefaultLayout' ); + $layout = $this->getUser()->getOption( 'timeless-layout', $defaultLayout ); + + if ( $layout == 'one-column' ) { + // version without the max-width set + $out->addModuleStyles( [ 'skins.timeless.onecolumn' ] ); + } elseif ( $layout == 'two-column' ) { + $out->addModuleStyles( [ 'skins.timeless.onecolumn.capped' ] ); + $out->addModuleStyles( [ 'skins.timeless.twocolumn' ] ); + } else { + $out->addModuleStyles( [ 'skins.timeless.onecolumn.capped' ] ); + $out->addModuleStyles( [ 'skins.timeless.twocolumn.capped' ] ); + $out->addModuleStyles( [ 'skins.timeless.threecolumn' ] ); + } + $out->addModules( [ 'skins.timeless.js', 'skins.timeless.mobile' @@ -46,4 +62,55 @@ class SkinTimeless extends SkinTemplate { public function setupSkinUserCss( OutputPage $out ) { parent::setupSkinUserCss( $out ); } + + /** + * Add class for maximum column mode to element + * + * @param OutputPage $out + * @param Skin $skin + * @param array &$bodyAttrs Existing attributes of the tag as an array + */ + public static function onOutputPageBodyAttributes( $out, $skin, &$bodyAttrs ) { + if ( $skin->getSkinName() == 'timeless' ) { + $defaultLayout = $out->getContext()->getConfig()->get( 'TimelessDefaultLayout' ); + $user = $out->getUser(); + $layout = $user->getOption( 'timeless-layout', $defaultLayout ); + + $bodyAttrs['class'] .= ' timeless-' . $layout; + } + } + + /** + * Add preference(s) + * + * @param User $user + * @param array &$preferences + */ + public static function onGetPreferences( User $user, array &$preferences ) { + $context = RequestContext::getMain(); + $useskin = $context->getRequest()->getVal( 'useskin', false ); + $skin = $useskin ?: $user->getOption( 'skin' ); + + $defaultLayout = $context->getConfig()->get( 'TimelessDefaultLayout' ); + + if ( $skin == 'timeless' ) { + $layouts = [ + 'one-column', + 'two-column', + 'three-column' + ]; + $layoutOptions = []; + foreach ( $layouts as $layoutOption ) { + $layoutOptions[$context->msg( "timeless-pref-$layoutOption" )->escaped()] = $layoutOption; + } + + $preferences['timeless-layout'] = [ + 'type' => 'select', + 'options' => $layoutOptions, + 'default' => $user->getOption( 'timeless-layout', $defaultLayout ), + 'label-message' => 'timeless-layout-preference', + 'section' => 'rendering/skin' + ]; + } + } } diff --git a/skin.json b/skin.json index 3efe5c6..3ba236f 100644 --- a/skin.json +++ b/skin.json @@ -20,6 +20,7 @@ }, "config": { "TimelessBackdropImage": "cat.svg", + "TimelessDefaultLayout": "three-column", "TimelessLogo": null, "TimelessWordmark": null }, @@ -40,15 +41,6 @@ "resources/screen-desktop.less": { "media": "screen and (min-width: 851px)" }, - "resources/screen-desktop-full.less": { - "media": "screen and (min-width: 1340px)" - }, - "resources/screen-desktop-mid.less": { - "media": "screen and (min-width: 1100px) and (max-width: 1339px)" - }, - "resources/screen-desktop-small.less": { - "media": "screen and (min-width: 851px) and (max-width: 1099px)" - }, "resources/screen-mobile.less": { "media": "screen and (max-width: 850px)" }, @@ -59,6 +51,46 @@ }, "@NOTE": "Remember to also update variables.less if you change the width cutoffs here. screen-misc.less and mobile.js may also need updating." }, + "skins.timeless.onecolumn.capped": { + "targets": [ "desktop" ], + "styles": { + "resources/screen-desktop-small.less": { + "media": "screen and (min-width: 851px) and (max-width: 1099px)" + } + } + }, + "skins.timeless.onecolumn": { + "targets": [ "desktop" ], + "styles": { + "resources/screen-desktop-small.less": { + "media": "screen and (min-width: 851px)" + } + } + }, + "skins.timeless.twocolumn.capped": { + "targets": [ "desktop" ], + "styles": { + "resources/screen-desktop-mid.less": { + "media": "screen and (min-width: 1100px) and (max-width: 1339px)" + } + } + }, + "skins.timeless.twocolumn": { + "targets": [ "desktop" ], + "styles": { + "resources/screen-desktop-mid.less": { + "media": "screen and (min-width: 1100px)" + } + } + }, + "skins.timeless.threecolumn": { + "targets": [ "desktop" ], + "styles": { + "resources/screen-desktop-full.less": { + "media": "screen and (min-width: 1340px)" + } + } + }, "skins.timeless.js": { "targets": [ "desktop" ], "scripts": [ @@ -96,5 +128,9 @@ "TimelessTemplate": "includes/TimelessTemplate.php", "TimelessVariablesModule": "includes/TimelessVariablesModule.php" }, + "Hooks": { + "GetPreferences": "SkinTimeless::onGetPreferences", + "OutputPageBodyAttributes": "SkinTimeless::onOutputPageBodyAttributes" + }, "manifest_version": 1 }