diff --git a/README.md b/README.md index c84283a9b..bba64518f 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ SmartTestFarm ================== -Feel free to support the development with a [**donation**](https://www.paypal.com/donate?hosted_button_id=JLQ4U468TWQPS) for the next improvements. +Feel free to support the development with a [**donation**](https://www.paypal.com/donate/?hosted_button_id=MNHYYCYHAKUVA) for the next improvements.

Zebrunner diff --git a/lib/units/ios-device/plugins/util/iosutil.js b/lib/units/ios-device/plugins/util/iosutil.js index 21ee0e055..5f319517e 100755 --- a/lib/units/ios-device/plugins/util/iosutil.js +++ b/lib/units/ios-device/plugins/util/iosutil.js @@ -113,6 +113,25 @@ let iosutil = { } }, swipe: function(orientation, params, deviceSize) { + + if (params.toX >= 2 || params.toY >= 2) { + if (params.fromY >= 0.5) { + params.fromY /= 2 + params.toY = 0.25 + } else { + params.fromY *= 2 + params.toY = 0.75 + } + + if (params.fromX >= 0.5) { + params.fromX /= 2 + params.toX = 0.25 + } else { + params.fromX *= 2 + params.toX = 0.75 + } + } + switch(orientation) { case 'PORTRAIT': return { diff --git a/lib/units/ios-device/plugins/wda.js b/lib/units/ios-device/plugins/wda.js index af11ac32a..2be4264e6 100755 --- a/lib/units/ios-device/plugins/wda.js +++ b/lib/units/ios-device/plugins/wda.js @@ -55,8 +55,11 @@ module.exports = syrup.serial() wdaClient.typeKey({value: [iosutil.asciiparser(message.text)]}) }) .on(wire.KeyDownMessage, (channel, message) => { - log.verbose("wire.TypeMessage: ", message) + log.verbose("wire.KeyDownMessage: ", message) wdaClient.typeKey({value: [iosutil.asciiparser(message.key)]}) + if (message.key === 'home') { + wdaClient.homeBtn() + } }) .on(wire.BrowserOpenMessage, (channel, message) => { wdaClient.openUrl(message) diff --git a/lib/util/datautil.js b/lib/util/datautil.js index 38b90f15e..0994f0277 100755 --- a/lib/util/datautil.js +++ b/lib/util/datautil.js @@ -18,7 +18,9 @@ datautil.applyData = function(device) { }) if (match) { - device.name = match.name.id + if (!device.name) { + device.name = match.name.id + } device.releasedAt = match.date device.image = match.image device.cpu = match.cpu diff --git a/res/app/components/stf/device/enhance-device/enhance-device-service.js b/res/app/components/stf/device/enhance-device/enhance-device-service.js index 464f96f5a..52147b040 100755 --- a/res/app/components/stf/device/enhance-device/enhance-device-service.js +++ b/res/app/components/stf/device/enhance-device/enhance-device-service.js @@ -46,7 +46,7 @@ module.exports = function EnhanceDeviceServiceFactory($filter, AppState) { } function enhanceDevice(device) { - device.enhancedName = device.model || device.product || device.marketName || device.serial || 'Unknown' + device.enhancedName = device.name || device.model || device.product || device.marketName || device.serial || 'Unknown' device.enhancedModel = device.model || 'Unknown' device.enhancedImage120 = '/static/app/devices/icon/x120/' + (device.platform || device.image || '_default.jpg') device.enhancedImage24 = '/static/app/devices/icon/x24/' + (device.platform || device.image || '_default.jpg') diff --git a/res/app/components/stf/landscape/landscape-directive.js b/res/app/components/stf/landscape/landscape-directive.js index 2ecf9deb9..6d0ea13b8 100755 --- a/res/app/components/stf/landscape/landscape-directive.js +++ b/res/app/components/stf/landscape/landscape-directive.js @@ -5,12 +5,6 @@ module.exports = link: function(scope) { var body = angular.element($document[0].body) - if (typeof $window.orientation !== 'undefined') { - if ($window.orientation !== 0) { - rotateGuest(false) - } - } - function rotateGuest(portrait) { if (portrait) { body.addClass('guest-portrait') @@ -31,20 +25,7 @@ module.exports = var isPortrait = (window.innerHeight > window.innerWidth) rotateGuest(isPortrait) } - - if (BrowserInfo.deviceorientation) { - window.addEventListener('orientationchange', guestDisplayRotated, - true) - } - - function off() { - if (BrowserInfo.deviceorientation) { - window.removeEventListener('orientationchange', - guestDisplayRotated) - } - } - - scope.$on('$destroy', off) + } } - } + } \ No newline at end of file diff --git a/res/app/components/stf/screen/screen-directive.js b/res/app/components/stf/screen/screen-directive.js index c56cd701d..6de36439f 100755 --- a/res/app/components/stf/screen/screen-directive.js +++ b/res/app/components/stf/screen/screen-directive.js @@ -106,6 +106,7 @@ module.exports = function DeviceScreenDirective( function handleScreen() { let ws, adjustedBoundSize const canvas = element.querySelector('.screen__canvas') + const g = canvas.getContext('2d') // const positioner = element.querySelector('div.positioner') const devicePixelRatio = window.devicePixelRatio || 1 @@ -272,13 +273,17 @@ module.exports = function DeviceScreenDirective( img.onload = function() { updateImageArea(this) - g.drawImage(img, 0, 0, img.width, img.height) + if (canvas.width === 2484 && canvas.height === 5376) { + g.drawImage(img, 0, 0, canvas.width, canvas.height) + return cleanData() + } // Try to forcefully clean everything to get rid of memory // leaks. Note that despite this effort, Chrome will still // leak huge amounts of memory when the developer tools are // open, probably to save the resources for inspection. When // the developer tools are closed no memory is leaked. + g.drawImage(img, 0, 0, img.width, img.height) cleanData() } @@ -448,6 +453,10 @@ module.exports = function DeviceScreenDirective( return screen.rotation === 90 || screen.rotation === 270 } + function canvasSizeExceeded() { + return $rootScope.basicMode && canvas.width * canvas.height >= 16777216 + } + function updateImageArea(img) { if (!hasImageAreaChanged(img)) { return @@ -465,6 +474,17 @@ module.exports = function DeviceScreenDirective( canvas.height = cachedImageHeight } + if (canvasSizeExceeded() && $scope.device.version !== '18.0') { + console.log(`exceeded canvas size limit, reducing previous size: ${canvas.width}x${canvas.height}`); + if ($scope.device.display.rotation === 90) { + canvas.width = 5376; + canvas.height = 2484; + return + } + canvas.width = 2484; + canvas.height = 5376; + } + cssRotation += rotator(cachedScreen.rotation, screen.rotation) // canvas.style[cssTransform] = 'rotate(' + cssRotation + 'deg)' @@ -750,6 +770,12 @@ module.exports = function DeviceScreenDirective( $document.bind('mouseup', mouseUpListener) $document.bind('mouseleave', mouseUpListener) + if (!$rootScope.basicMode) { + $element.bind('touchmove', mouseMoveListener) + $document.bind('touchend', mouseUpListener) + $document.bind('touchcancel', mouseUpListener) + } + if (lastPossiblyBuggyMouseUpEvent && lastPossiblyBuggyMouseUpEvent.timeStamp > e.timeStamp) { // We got mouseup before mousedown. See mouseUpBugWorkaroundListener @@ -938,6 +964,13 @@ module.exports = function DeviceScreenDirective( } function stopMousing() { + + if (!$rootScope.basicMode) { + $element.unbind('touchmove', mouseMoveListener) + $document.unbind('touchend', mouseUpListener) + $document.unbind('touchcancel', mouseUpListener) + } + $element.unbind('mousemove', mouseMoveListener) $document.unbind('mouseup', mouseUpListener) $document.unbind('mouseleave', mouseUpListener) @@ -1013,9 +1046,12 @@ module.exports = function DeviceScreenDirective( activateFinger(slot, x, y, pressure) } - $element.bind('touchmove', touchMoveListener) - $document.bind('touchend', touchEndListener) - $document.bind('touchleave', touchEndListener) + + if ($rootScope.basicMode) { + $element.bind('touchmove', touchMoveListener) + $document.bind('touchend', touchEndListener) + $document.bind('touchleave', touchEndListener) + } $scope.control.touchCommit(nextSeq()) } @@ -1043,9 +1079,13 @@ module.exports = function DeviceScreenDirective( $scope.device.ios ) - $scope.control.touchMove(nextSeq(), slot, scaled.xP, scaled.yP, pressure) - //$scope.control.touchMoveIos(nextSeq(), slot, scaled.xP, scaled.yP, pressure) - activateFinger(slot, x, y, pressure) + if ($scope.device.ios) { + const touchev = e.touches[0]; + + $scope.control.touchMoveIos(touchev.pageX, touchev.pageY, scaled.xP, scaled.yP, 0.5); + + activateFinger(slot, x, y, pressure); + } } $scope.control.touchCommit(nextSeq()) @@ -1096,7 +1136,12 @@ module.exports = function DeviceScreenDirective( $scope.control.gestureStop(nextSeq()) } - $element.on('touchstart', touchStartListener) + $element.on('touchstart', (e) => { + if (!$rootScope.basicMode) { + return mouseDownListener(e) + } + touchStartListener(e) + }) $element.on('mousedown', mouseDownListener) $element.on('mouseup', mouseUpBugWorkaroundListener) @@ -1104,4 +1149,4 @@ module.exports = function DeviceScreenDirective( } } } -} +} \ No newline at end of file diff --git a/res/app/control-panes/advanced/advanced.pug b/res/app/control-panes/advanced/advanced.pug index 4c91c4ac6..bdfedb72a 100755 --- a/res/app/control-panes/advanced/advanced.pug +++ b/res/app/control-panes/advanced/advanced.pug @@ -12,5 +12,5 @@ .col-md-6 div(ng-include='"control-panes/advanced/maintenance/maintenance.pug"') .col-md-6 - div(ng-include='"control-panes/advanced/device-settings/device-settings.pug"') + div(ng-include='"control-panes/advanced/device-settings/device-settings.pug"', style='{{$root.basicMode ? "height: 250px" : "height: auto;" }}') diff --git a/res/app/control-panes/control-panes.css b/res/app/control-panes/control-panes.css new file mode 100644 index 000000000..26bdad7ef --- /dev/null +++ b/res/app/control-panes/control-panes.css @@ -0,0 +1,5 @@ +@media (max-width: 400px) { + .pane-bottom-p.fa-pane.pane-fa-pane.fa-pane-orientation-vertical { + display: none; + } +} \ No newline at end of file diff --git a/res/app/control-panes/control-panes.pug b/res/app/control-panes/control-panes.pug index 3eaa5a1b8..31253440c 100755 --- a/res/app/control-panes/control-panes.pug +++ b/res/app/control-panes/control-panes.pug @@ -9,9 +9,10 @@ div(ng-controller='ControlPanesHotKeysCtrl').fill-height .remote-control div(ng-include='"control-panes/device-control/device-control.pug"').fill-height - div(fa-pane, pane-id='control-bottom-tabs', pane-anchor='south', pane-size='30% + 2px', pane-handle='4', style='{{!root.basicMode ? "display: none" : "display: initial"}}').pane-bottom-p + div(fa-pane, pane-id='control-bottom-tabs', pane-anchor='south', pane-size='30% + 2px', pane-handle='4').pane-bottom-p .widget-container.fluid-height nice-tabs(key='ControlBottomTabs', direction='below', tabs='belowTabs', filter='$root.platform') + div(fa-pane, pane-id='control-top-tabs', pane-anchor='' style='{{!$root.basicMode ? "" : "position: relative; height: auto; width: 350px" }}') .widget-container.fluid-height nice-tabs(key='ControlBottomTabs', tabs='topTabs', filter='$root.platform') diff --git a/res/app/control-panes/dashboard/dashboard.pug b/res/app/control-panes/dashboard/dashboard.pug index a28bea7d3..70990ac32 100755 --- a/res/app/control-panes/dashboard/dashboard.pug +++ b/res/app/control-panes/dashboard/dashboard.pug @@ -13,4 +13,4 @@ .col-md-6 div(ng-include='"control-panes/dashboard/apps/apps.pug"') .col-md-6 - div(ng-include='"control-panes/advanced/remote-debug/remote-debug.pug"') + div(ng-include='"control-panes/advanced/remote-debug/remote-debug.pug"', style='{{$root.basicMode ? "height: 150px" : "height: auto;" }}') diff --git a/res/app/control-panes/device-control/device-control-controller.js b/res/app/control-panes/device-control/device-control-controller.js index 370cf3a07..42a8090ce 100755 --- a/res/app/control-panes/device-control/device-control-controller.js +++ b/res/app/control-panes/device-control/device-control-controller.js @@ -3,6 +3,11 @@ var _ = require('lodash') module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService, $location, $timeout, $window, $rootScope, LogcatService, $route) { + if ($rootScope.basicMode) { + let scrollbarDiv = document.getElementsByClassName('pane-center fill-height ng-scope fa-pane-scroller')[0] + scrollbarDiv.scroll(0, 0) + } + $scope.showScreen = true $scope.groupTracker = DeviceService.trackGroup($scope) @@ -91,11 +96,19 @@ module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService, $scope.tryToRotate = function(rotation) { if (rotation === 'portrait') { $scope.control.rotate(0) + if ($rootScope.basicMode) { + $scope.currentRotation = 'portrait' + return + } $timeout(function() { isLandscape() ? $scope.currentRotation = 'landscape' : $scope.currentRotation = 'portrait' }, 400) } else if (rotation === 'landscape') { $scope.control.rotate(90) + if ($rootScope.basicMode) { + $scope.currentRotation = 'landscape' + return + } $timeout(function() { isPortrait() ? $scope.currentRotation = 'portrait' : $scope.currentRotation = 'landscape' }, 400) @@ -105,6 +118,10 @@ module.exports = function DeviceControlCtrl($scope, DeviceService, GroupService, $scope.currentRotation = 'portrait' $scope.$watch('device.display.rotation', function(newValue) { + if ($rootScope.basicMode) { + return + } + $scope.currentRotation = 'rotating' if (isPortrait(newValue)) { $timeout(function() { diff --git a/res/app/control-panes/device-control/device-control.pug b/res/app/control-panes/device-control/device-control.pug index d085686ce..fdada1770 100755 --- a/res/app/control-panes/device-control/device-control.pug +++ b/res/app/control-panes/device-control/device-control.pug @@ -6,11 +6,11 @@ .stf-vnc-right-buttons.pull-right .btn-group label.btn-sm.btn-primary-outline(type='button', ng-click='tryToRotate("portrait")', ng-hide='device.platform === "tvOS"', - ng-model='currentRotation', uib-btn-radio='"portrait"', + ng-model='currentRotation', uib-btn-radio='"portrait"', id='portrait-label', uib-tooltip='{{ "Portrait" | translate }} ({{ "Current rotation:" | translate }} {{ device.display.rotation }}°)', tooltip-placement='bottom').pointer i.fa.fa-mobile label.btn-sm.btn-primary-outline(type='button', ng-click='tryToRotate("landscape")', ng-hide='device.platform === "tvOS"', - ng-model='currentRotation', uib-btn-radio='"landscape"', + ng-model='currentRotation', uib-btn-radio='"landscape"', id='landscape-label', uib-tooltip='{{ "Landscape" | translate }} ({{ "Current rotation:" | translate }} {{ device.display.rotation }}°)', tooltip-placement='bottom').pointer i.fa.fa-mobile.fa-rotate-90 .button-spacer diff --git a/res/app/control-panes/index.js b/res/app/control-panes/index.js index 116b1fe94..98084cea9 100755 --- a/res/app/control-panes/index.js +++ b/res/app/control-panes/index.js @@ -1,3 +1,5 @@ +require('./control-panes.css') + module.exports = angular.module('control-panes', [ require('stf/common-ui/nice-tabs').name, require('stf/device').name, diff --git a/res/app/control-panes/info/info.pug b/res/app/control-panes/info/info.pug index 7c262a2a1..f396704f0 100755 --- a/res/app/control-panes/info/info.pug +++ b/res/app/control-panes/info/info.pug @@ -154,10 +154,10 @@ div.infocard-table__item {{device.manufacturer}} div.infocard-table__row div.infocard-table__item(translate) Product - div.infocard-table__item {{device.name ? device.name : '-'}} + div.infocard-table__item {{device.enhancedName}} div.infocard-table__row div.infocard-table__item(translate) Model - div.infocard-table__item {{device.model}} + div.infocard-table__item {{device.enhancedName}} div.infocard-table__row div.infocard-table__item(translate) Serial div.infocard-table__item {{device.serial}} diff --git a/res/app/device-list/column/device-column-service.js b/res/app/device-list/column/device-column-service.js index e064eea5a..a73821205 100755 --- a/res/app/device-list/column/device-column-service.js +++ b/res/app/device-list/column/device-column-service.js @@ -80,13 +80,13 @@ module.exports = function DeviceColumnService($filter, gettext, SettingsService, , model: DeviceModelCell({ title: gettext('Model') , value: function(device) { - return device.name || device.model || device.serial + return device.enhancedName } }) , name: DeviceNameCell({ title: gettext('Product') , value: function(device) { - return device.name || device.model || device.serial + return device.enhancedName } }, AppState.user.email) , platform: TextCell({ diff --git a/res/app/device-list/details/device-list-details-directive.js b/res/app/device-list/details/device-list-details-directive.js index c729b5250..96ca4cd6d 100755 --- a/res/app/device-list/details/device-list-details-directive.js +++ b/res/app/device-list/details/device-list-details-directive.js @@ -825,18 +825,24 @@ module.exports = function DeviceListDetailsDirective( }); document.addEventListener('DOMContentLoaded', function() { + if ($rootScope.basicMode) { + scrollbarDiv.scroll(0, 0) + } if (storedScrollPosition) { scrollbarDiv.scroll(0, parseInt(storedScrollPosition)) } }) window.addEventListener('load', function() { + if ($rootScope.basicMode) { + scrollbarDiv.scroll(0, 0) + } if (storedScrollPosition) { scrollbarDiv.scroll(0, parseInt(storedScrollPosition)) } }) - if (storedScrollPosition) { + if (storedScrollPosition && !$rootScope.basicMode) { scrollbarDiv.scroll(0, parseInt(storedScrollPosition)) } } diff --git a/res/app/device-list/device-list.pug b/res/app/device-list/device-list.pug index ff687ff9d..eb6a3b946 100755 --- a/res/app/device-list/device-list.pug +++ b/res/app/device-list/device-list.pug @@ -1,5 +1,5 @@ .stf-device-list - .row.stf-stats-container.unselectable + .row.stf-stats-container.unselectable(style='{{$root.basicMode ? "margin: 5px 0 0 0;" : "margin: 0;" }}') .col-md-12 device-list-stats(tracker='tracker') diff --git a/res/app/device-list/stats/device-list-stats.css b/res/app/device-list/stats/device-list-stats.css index 2ede24b5c..618470b70 100755 --- a/res/app/device-list/stats/device-list-stats.css +++ b/res/app/device-list/stats/device-list-stats.css @@ -72,7 +72,7 @@ .device-stats [class^="col-"] .text, .device-stats [class*="col-"] .text { - font-size: 0.8em; + font-size: 0.6em; font-weight: 500; } } diff --git a/res/app/group-list/group-list.css b/res/app/group-list/group-list.css index f6a9c4d61..693421132 100644 --- a/res/app/group-list/group-list.css +++ b/res/app/group-list/group-list.css @@ -190,7 +190,7 @@ .group-stats [class^="col-"] .text, .group-stats [class*="col-"] .text { - font-size: 0.8em; + font-size: 0.6em; font-weight: 500; } } diff --git a/res/app/layout/small.css b/res/app/layout/small.css index 87ed0db22..8d654d806 100755 --- a/res/app/layout/small.css +++ b/res/app/layout/small.css @@ -50,4 +50,4 @@ a uib-tab-heading i + span { table.table .btn { margin: 0; -} +} \ No newline at end of file diff --git a/res/app/menu/menu.css b/res/app/menu/menu.css index ffbd1fc4c..a30860e3f 100755 --- a/res/app/menu/menu.css +++ b/res/app/menu/menu.css @@ -35,9 +35,9 @@ .stf-menu .stf-nav > li > a { display: inline-block; text-align: left; - padding: 0 !important; - padding-right: 18px !important; - padding-left: 14px !important; + padding: 0; + padding-right: 18px; + padding-left: 14px; font-size: 15px; line-height: 44px; color: #777777; @@ -67,8 +67,19 @@ background-color: white; } -@media (min-width: 600px) { +@media (max-width: 600px) { .stf-menu .stf-nav > li { padding: 0; } + .stf-menu .stf-nav > li > a { + padding-left: 0; + padding-right: 10px; + } + + .stf-menu .stf-nav > li > a > span.fa { + display: inline-block; + float: left; + margin: 8px 3px 0 0; + font-size: 28px; + } } \ No newline at end of file diff --git a/res/app/menu/menu.pug b/res/app/menu/menu.pug index b5fd899b5..59d5226ec 100755 --- a/res/app/menu/menu.pug +++ b/res/app/menu/menu.pug @@ -3,9 +3,9 @@ // .navbar.stf-menu(ng-controller='MenuCtrl') - .container-fluid.stf-top-bar + .container-fluid.stf-top-bar(style='{{$root.basicMode ? "padding: 0 10px" : "padding: 0 10px;"}}') a.stf-logo(ng-href="/stf#!/devices") STF - ul.nav.stf-nav(nav-menu='current').unselectable + ul.nav.stf-nav(nav-menu='current', ng-if='!$root.basicMode').unselectable li(ng-cloak) a(ng-href='/stf#!/control/{{lastUsedDevice}}', ng-show='lastUsedDevice') span.fa.fa-mobile @@ -25,21 +25,38 @@ button(type='button', ng-model='$root.platform', uib-btn-radio="'web'", translate).btn.btn-sm.btn-default-outline Web button(type='button', ng-model='$root.platform', uib-btn-radio="'native'", translate).btn.btn-sm.btn-default-outline Native - li.stf-nav-web-native-button() + li.stf-nav-web-native-button(style="padding: 0") button.btn.btn-sm.btn-default-outline( + style='{{$root.basicMode ? "padding: 5px 0" : "padding: 5px 10px;" }}' type='button' ng-click='mailToSupport()') i.fa.fa-envelope-o span(translate) Contact Support - li.stf-nav-web-native-button() + li.stf-nav-web-native-button(style="padding: 0") button.btn.btn-sm.btn-default-outline( + style='{{$root.basicMode ? "padding: 5px 0" : "padding: 5px 10px;" }}' type='button' ng-click='logout()') i.fa.fa-sign-out span(translate) Logout - li() + li(style="padding: 0") a(ng-href='/stf#!/help', accesskey='6') i.fa.fa-question-circle.fa-fw | {{ "Help" | translate }} + + ul.nav.stf-nav(nav-menu='current', style='padding: 0; width: 100%', ng-if='$root.basicMode').unselectable + li(ng-cloak, style='width: 100%; margin-left: 10px') + a(ng-href='/stf#!/control/{{lastUsedDevice}}', ng-show='lastUsedDevice', style="padding-left: 0px; font-size: 10px") + span.fa.fa-mobile + span(translate) Control + a(accesskey='1', ng-click='scrollToStoredPosition()', style='cursor: pointer; padding-left: 0px; font-size: 10px') + span.fa.fa-sitemap + span(translate) Devices + a(ng-href='/stf#!/groups', , style="padding-left: 0px; font-size: 10px") + span.fa.fa-object-group + span(translate) Groups + a(ng-href='/stf#!/settings', style="padding-left: 0px; font-size: 10px") + span.fa.fa-gears + span(translate) Settings \ No newline at end of file diff --git a/res/app/views/index.pug b/res/app/views/index.pug index 8027347dd..102e729f7 100755 --- a/res/app/views/index.pug +++ b/res/app/views/index.pug @@ -16,7 +16,7 @@ html(ng-app='app') div(ng-controller='LayoutCtrl', basic-mode, admin-mode, standalone, landscape).fill-height .pane-top.fill-height(fa-pane) .pane-top-bar(fa-pane, pane-id='menu', pane-anchor='north', - pane-size='{{!$root.basicMode && !$root.standalone ? 44 : 80 }}px', + pane-size='{{$root.basicMode ? "88px" : "44px" }}', pane-handle='') div(ng-include='"menu.pug"') diff --git a/res/web_modules/nine-bootstrap/nine-bootstrap.scss b/res/web_modules/nine-bootstrap/nine-bootstrap.scss index 614d39064..3a73b792e 100755 --- a/res/web_modules/nine-bootstrap/nine-bootstrap.scss +++ b/res/web_modules/nine-bootstrap/nine-bootstrap.scss @@ -1107,4 +1107,29 @@ input[type="range"] { } } + .btn-primary-outline { + &:hover { + background: none; + color: $main; + + .caret { + border-top-color: $main; + } + } + } + + #portrait-label { + &:hover { + background: $main; + color: #fff + } + } + + #landscape-label { + &:hover { + background: $main; + color: #fff + } + } + }