Softening light theme

This commit is contained in:
James Barnsley
2019-08-20 16:56:08 +12:00
parent 99616e162c
commit f6e227f85c
13 changed files with 2408 additions and 2246 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -51970,7 +51970,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/** @license MIT License (c) copyright 2010-20
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});
exports.App = undefined;
@ -52196,286 +52196,346 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
;
var App = exports.App = function (_React$Component) {
_inherits(App, _React$Component);
_inherits(App, _React$Component);
function App(props) {
_classCallCheck(this, App);
function App(props) {
_classCallCheck(this, App);
var _this = _possibleConstructorReturn(this, (App.__proto__ || Object.getPrototypeOf(App)).call(this, props));
var _this = _possibleConstructorReturn(this, (App.__proto__ || Object.getPrototypeOf(App)).call(this, props));
_this.handleInstallPrompt = _this.handleInstallPrompt.bind(_this);
_this.handleFocusAndBlur = _this.handleFocusAndBlur.bind(_this);
return _this;
}
_this.handleInstallPrompt = _this.handleInstallPrompt.bind(_this);
_this.handleFocusAndBlur = _this.handleFocusAndBlur.bind(_this);
return _this;
}
_createClass(App, [{
key: 'componentWillMount',
value: function componentWillMount() {
window.addEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.addEventListener("focus", this.handleFocusAndBlur, false);
window.addEventListener("blur", this.handleFocusAndBlur, false);
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
window.removeEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.removeEventListener("focus", this.handleFocusAndBlur, false);
window.removeEventListener("blur", this.handleFocusAndBlur, false);
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this2 = this;
_createClass(App, [{
key: "componentWillMount",
value: function componentWillMount() {
window.addEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.addEventListener("focus", this.handleFocusAndBlur, false);
window.addEventListener("blur", this.handleFocusAndBlur, false);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
window.removeEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.removeEventListener("focus", this.handleFocusAndBlur, false);
window.removeEventListener("blur", this.handleFocusAndBlur, false);
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
if (this.props.allow_reporting) {
_reactGa2.default.initialize('UA-64701652-3');
}
if (this.props.allow_reporting) {
_reactGa2.default.initialize("UA-64701652-3");
}
// Fire up our services
this.props.mopidyActions.connect();
this.props.pusherActions.connect();
this.props.coreActions.getBroadcasts();
// Fire up our services
this.props.mopidyActions.connect();
this.props.pusherActions.connect();
this.props.coreActions.getBroadcasts();
// Check for url-parsed configuration values
var url_vars = this.props.location.query;
if (url_vars) {
var has_values = false;
var values = {};
if (url_vars.host !== undefined) {
has_values = true;
values.host = url_vars.host;
}
if (url_vars.port !== undefined) {
has_values = true;
values.port = url_vars.port;
}
// Check for url-parsed configuration values
var url_vars = this.props.location.query;
if (url_vars) {
var has_values = false;
var values = {};
if (url_vars.host !== undefined) {
has_values = true;
values.host = url_vars.host;
}
if (url_vars.port !== undefined) {
has_values = true;
values.port = url_vars.port;
}
if (has_values) {
this.props.mopidyActions.set(values);
if (has_values) {
this.props.mopidyActions.set(values);
// Allow 100ms for the action above to complete before we re-route
setTimeout(function () {
_this2.props.history.push('/');
}, 100);
}
}
// Allow 100ms for the action above to complete before we re-route
setTimeout(function () {
_this2.props.history.push("/");
}, 100);
}
}
// show initial setup if required
if (!this.props.initial_setup_complete) {
this.props.history.push('/initial-setup');
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
// show initial setup if required
if (!this.props.initial_setup_complete) {
this.props.history.push("/initial-setup");
}
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
// When we have navigated to a new route
if (this.props.location !== prevProps.location) {
// Log our pageview
if (this.props.allow_reporting) {
_reactGa2.default.set({ page: this.props.location.pathname });
_reactGa2.default.pageview(this.props.location.pathname);
}
// When we have navigated to a new route
if (this.props.location !== prevProps.location) {
// If the location has a "scroll_position" state variable, scroll to it.
// This is invisibly injected to the history by the Link component when navigating, so
// hitting back in the browser allows us to restore the position
var location_state = this.props.location.state ? this.props.location.state : {};
if (location_state.scroll_position) {
helpers.scrollTo(parseInt(location_state.scroll_position), false);
}
// Log our pageview
if (this.props.allow_reporting) {
_reactGa2.default.set({ page: this.props.location.pathname });
_reactGa2.default.pageview(this.props.location.pathname);
}
// Hide our sidebar
this.props.uiActions.toggleSidebar(false);
// If the location has a "scroll_position" state variable, scroll to it.
// This is invisibly injected to the history by the Link component when navigating, so
// hitting back in the browser allows us to restore the position
var location_state = this.props.location.state ? this.props.location.state : {};
if (location_state.scroll_position) {
helpers.scrollTo(parseInt(location_state.scroll_position), false);
}
// Unselect any tracks
this.props.uiActions.setSelectedTracks([]);
// Hide our sidebar
this.props.uiActions.toggleSidebar(false);
// Close context menu
if (this.props.context_menu) {
this.props.uiActions.hideContextMenu();
}
}
}
// Unselect any tracks
this.props.uiActions.setSelectedTracks([]);
/**
* Using Visibility API, detect whether the browser is in focus or not
*
* This is used to keep background requests lean, preventing a queue of requests building up
* for when focus is retained. Seems most obvious on mobile devices with Chrome as it has throttled
* quota significantly: https://developers.google.com/web/updates/2017/03/background_tabs
*
* @param e Event
**/
// Close context menu
if (this.props.context_menu) {
this.props.uiActions.hideContextMenu();
}
};
}
}, {
key: "handleFocusAndBlur",
value: function handleFocusAndBlur(e) {
this.props.uiActions.setWindowFocus(document.hasFocus());
}
}, {
key: "handleInstallPrompt",
value: function handleInstallPrompt(e) {
e.preventDefault();
console.log("Install prompt detected");
this.props.uiActions.installPrompt(e);
}
}, {
key: "render",
value: function render() {
var className = this.props.theme + "-theme";
if (this.props.wide_scrollbar_enabled) {
className += " wide-scrollbar";
}
if (this.props.dragging) {
className += " dragging";
}
if (this.props.sidebar_open) {
className += " sidebar-open";
}
if (this.props.touch_dragging) {
className += " touch-dragging";
console.log("TOUCH DRAGGING");
}
if (this.props.context_menu) {
className += " context-menu-open";
}
if (this.props.slim_mode) {
className += " slim-mode";
}
if (this.props.smooth_scrolling_enabled) {
className += " smooth-scrolling-enabled";
}
if (helpers.isTouchDevice()) {
className += " touch";
} else {
className += " notouch";
}
/**
* Using Visibility API, detect whether the browser is in focus or not
*
* This is used to keep background requests lean, preventing a queue of requests building up
* for when focus is retained. Seems most obvious on mobile devices with Chrome as it has throttled
* quota significantly: https://developers.google.com/web/updates/2017/03/background_tabs
*
* @param e Event
**/
return _react2.default.createElement(
"div",
{ className: className },
_react2.default.createElement(
"div",
{ className: "body" },
_react2.default.createElement(
_reactRouterDom.Switch,
null,
_react2.default.createElement(_reactRouterDom.Route, { path: "/initial-setup", component: _InitialSetup2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/kiosk-mode", component: _KioskMode2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/add-to-playlist/:uris", component: _AddToPlaylist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/image-zoom", component: _ImageZoom2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/share-configuration", component: _ShareConfiguration2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/edit-command/:id?", component: _EditCommand2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/queue/radio", component: _EditRadio2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/queue/add-uri", component: _AddToQueue2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/playlist/create", component: _CreatePlaylist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/playlist/:uri/edit", component: _EditPlaylist2.default }),
_react2.default.createElement(
_reactRouterDom.Route,
null,
_react2.default.createElement(
"div",
null,
_react2.default.createElement(_Sidebar2.default, {
location: this.props.location,
history: this.props.history,
tabIndex: "3"
}),
_react2.default.createElement(_PlaybackControls2.default, {
history: this.props.history,
slim_mode: this.props.slim_mode,
tabIndex: "2"
}),
_react2.default.createElement(
"main",
{ id: "main", className: "smooth-scroll", tabIndex: "1" },
_react2.default.createElement(
_reactRouterDom.Switch,
null,
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/", component: _Queue2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/queue", component: _Queue2.default }),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/queue/history",
component: _QueueHistory2.default
}),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/settings/debug", component: _Debug2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: "/settings", component: _Settings2.default }),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/search/:type?/:term?",
component: _Search2.default
}),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/album/:uri", component: _Album2.default }),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/artist/:uri/:sub_view?",
component: _Artist2.default
}),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/playlist/:uri", component: _Playlist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/user/:uri", component: _User2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: "/track/:uri", component: _Track2.default }),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/discover/recommendations/:seeds?",
component: _DiscoverRecommendations2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/discover/featured",
component: _DiscoverFeatured2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/discover/categories/:id",
component: _DiscoverCategory2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/discover/categories",
component: _DiscoverCategories2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/discover/new-releases",
component: _DiscoverNewReleases2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/artists",
component: _LibraryArtists2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/albums",
component: _LibraryAlbums2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/tracks",
component: _LibraryTracks2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/playlists",
component: _LibraryPlaylists2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/browse",
component: _LibraryBrowse2.default
}),
_react2.default.createElement(_reactRouterDom.Route, {
exact: true,
path: "/library/browse/:uri",
component: _LibraryBrowseDirectory2.default
}),
_react2.default.createElement(
_reactRouterDom.Route,
null,
_react2.default.createElement(
_ErrorMessage2.default,
{ type: "not-found", title: "Not found" },
_react2.default.createElement(
"p",
null,
"Oops, that link could not be found"
)
)
)
)
)
)
)
)
),
_react2.default.createElement(_ResizeListener2.default, {
uiActions: this.props.uiActions,
slim_mode: this.props.slim_mode
}),
this.props.hotkeys_enabled && _react2.default.createElement(_Hotkeys2.default, null),
_react2.default.createElement(_ContextMenu2.default, null),
_react2.default.createElement(_Dragger2.default, null),
_react2.default.createElement(_Notifications2.default, null),
this.props.debug_info ? _react2.default.createElement(_DebugInfo2.default, null) : null
);
}
}]);
}, {
key: 'handleFocusAndBlur',
value: function handleFocusAndBlur(e) {
this.props.uiActions.setWindowFocus(document.hasFocus());
}
}, {
key: 'handleInstallPrompt',
value: function handleInstallPrompt(e) {
e.preventDefault();
console.log("Install prompt detected");
this.props.uiActions.installPrompt(e);
}
}, {
key: 'render',
value: function render() {
var className = this.props.theme + '-theme';
if (this.props.wide_scrollbar_enabled) {
className += ' wide-scrollbar';
}
if (this.props.dragging) {
className += ' dragging';
}
if (this.props.sidebar_open) {
className += ' sidebar-open';
}
if (this.props.touch_dragging) {
className += ' touch-dragging';
console.log("TOUCH DRAGGING");
}
if (this.props.context_menu) {
className += ' context-menu-open';
}
if (this.props.slim_mode) {
className += ' slim-mode';
}
if (this.props.smooth_scrolling_enabled) {
className += ' smooth-scrolling-enabled';
}
if (helpers.isTouchDevice()) {
className += ' touch';
} else {
className += ' notouch';
}
return _react2.default.createElement(
'div',
{ className: className },
_react2.default.createElement(
'div',
{ className: 'body' },
_react2.default.createElement(
_reactRouterDom.Switch,
null,
_react2.default.createElement(_reactRouterDom.Route, { path: '/initial-setup', component: _InitialSetup2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/kiosk-mode', component: _KioskMode2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/add-to-playlist/:uris', component: _AddToPlaylist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/image-zoom', component: _ImageZoom2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/share-configuration', component: _ShareConfiguration2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/edit-command/:id?', component: _EditCommand2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/queue/radio', component: _EditRadio2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/queue/add-uri', component: _AddToQueue2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/playlist/create', component: _CreatePlaylist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/playlist/:uri/edit', component: _EditPlaylist2.default }),
_react2.default.createElement(
_reactRouterDom.Route,
null,
_react2.default.createElement(
'div',
null,
_react2.default.createElement(_Sidebar2.default, { location: this.props.location, history: this.props.history, tabIndex: '3' }),
_react2.default.createElement(_PlaybackControls2.default, { history: this.props.history, slim_mode: this.props.slim_mode, tabIndex: '2' }),
_react2.default.createElement(
'main',
{ id: 'main', className: 'smooth-scroll', tabIndex: '1' },
_react2.default.createElement(
_reactRouterDom.Switch,
null,
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/', component: _Queue2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/queue', component: _Queue2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/queue/history', component: _QueueHistory2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/settings/debug', component: _Debug2.default }),
_react2.default.createElement(_reactRouterDom.Route, { path: '/settings', component: _Settings2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/search/:type?/:term?', component: _Search2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/album/:uri', component: _Album2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/artist/:uri/:sub_view?', component: _Artist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/playlist/:uri', component: _Playlist2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/user/:uri', component: _User2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/track/:uri', component: _Track2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/discover/recommendations/:seeds?', component: _DiscoverRecommendations2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/discover/featured', component: _DiscoverFeatured2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/discover/categories/:id', component: _DiscoverCategory2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/discover/categories', component: _DiscoverCategories2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/discover/new-releases', component: _DiscoverNewReleases2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/artists', component: _LibraryArtists2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/albums', component: _LibraryAlbums2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/tracks', component: _LibraryTracks2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/playlists', component: _LibraryPlaylists2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/browse', component: _LibraryBrowse2.default }),
_react2.default.createElement(_reactRouterDom.Route, { exact: true, path: '/library/browse/:uri', component: _LibraryBrowseDirectory2.default }),
_react2.default.createElement(
_reactRouterDom.Route,
null,
_react2.default.createElement(
_ErrorMessage2.default,
{ type: 'not-found', title: 'Not found' },
_react2.default.createElement(
'p',
null,
'Oops, that link could not be found'
)
)
)
)
)
)
)
)
),
_react2.default.createElement(_ResizeListener2.default, {
uiActions: this.props.uiActions,
slim_mode: this.props.slim_mode
}),
this.props.hotkeys_enabled && _react2.default.createElement(_Hotkeys2.default, null),
_react2.default.createElement(_ContextMenu2.default, null),
_react2.default.createElement(_Dragger2.default, null),
_react2.default.createElement(_Notifications2.default, null),
this.props.debug_info ? _react2.default.createElement(_DebugInfo2.default, null) : null
);
}
}]);
return App;
return App;
}(_react2.default.Component);
var mapStateToProps = function mapStateToProps(state, ownProps) {
return {
theme: state.ui.theme,
wide_scrollbar_enabled: state.ui.wide_scrollbar_enabled,
smooth_scrolling_enabled: state.ui.smooth_scrolling_enabled,
hotkeys_enabled: state.ui.hotkeys_enabled,
allow_reporting: state.ui.allow_reporting,
touch_dragging: state.ui.touch_dragging,
initial_setup_complete: state.ui.initial_setup_complete,
slim_mode: state.ui.slim_mode,
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorization,
sidebar_open: state.ui.sidebar_open,
dragging: state.ui.dragger && state.ui.dragger.active,
context_menu: state.ui.context_menu,
debug_info: state.ui.debug_info
};
return {
theme: state.ui.theme,
wide_scrollbar_enabled: state.ui.wide_scrollbar_enabled,
smooth_scrolling_enabled: state.ui.smooth_scrolling_enabled,
hotkeys_enabled: state.ui.hotkeys_enabled,
allow_reporting: state.ui.allow_reporting,
touch_dragging: state.ui.touch_dragging,
initial_setup_complete: state.ui.initial_setup_complete,
slim_mode: state.ui.slim_mode,
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorization,
sidebar_open: state.ui.sidebar_open,
dragging: state.ui.dragger && state.ui.dragger.active,
context_menu: state.ui.context_menu,
debug_info: state.ui.debug_info
};
};
var mapDispatchToProps = function mapDispatchToProps(dispatch) {
return {
coreActions: (0, _redux.bindActionCreators)(coreActions, dispatch),
uiActions: (0, _redux.bindActionCreators)(uiActions, dispatch),
pusherActions: (0, _redux.bindActionCreators)(pusherActions, dispatch),
mopidyActions: (0, _redux.bindActionCreators)(mopidyActions, dispatch),
spotifyActions: (0, _redux.bindActionCreators)(spotifyActions, dispatch),
lastfmActions: (0, _redux.bindActionCreators)(lastfmActions, dispatch),
geniusActions: (0, _redux.bindActionCreators)(geniusActions, dispatch),
snapcastActions: (0, _redux.bindActionCreators)(snapcastActions, dispatch)
};
return {
coreActions: (0, _redux.bindActionCreators)(coreActions, dispatch),
uiActions: (0, _redux.bindActionCreators)(uiActions, dispatch),
pusherActions: (0, _redux.bindActionCreators)(pusherActions, dispatch),
mopidyActions: (0, _redux.bindActionCreators)(mopidyActions, dispatch),
spotifyActions: (0, _redux.bindActionCreators)(spotifyActions, dispatch),
lastfmActions: (0, _redux.bindActionCreators)(lastfmActions, dispatch),
geniusActions: (0, _redux.bindActionCreators)(geniusActions, dispatch),
snapcastActions: (0, _redux.bindActionCreators)(snapcastActions, dispatch)
};
};
exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(App);

File diff suppressed because one or more lines are too long

View File

@ -100,7 +100,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1566185717";
var build = "1566275450";
var version = "3.39.0";
// Construct the script tag

View File

@ -1,324 +1,386 @@
import React from 'react';
import { bindActionCreators } from 'redux';
import React from "react";
import { bindActionCreators } from "redux";
import { Route, Switch } from "react-router-dom";
import { connect } from 'react-redux';
import ReactGA from 'react-ga';
import { connect } from "react-redux";
import ReactGA from "react-ga";
import Sidebar from './components/Sidebar';;
import PlaybackControls from './components/PlaybackControls';
import ContextMenu from './components/ContextMenu';
import Dragger from './components/Dragger';
import Notifications from './components/Notifications';
import ResizeListener from './components/ResizeListener';
import Hotkeys from './components/Hotkeys';
import DebugInfo from './components/DebugInfo';
import ErrorMessage from './components/ErrorMessage';
import Sidebar from "./components/Sidebar";
import PlaybackControls from "./components/PlaybackControls";
import ContextMenu from "./components/ContextMenu";
import Dragger from "./components/Dragger";
import Notifications from "./components/Notifications";
import ResizeListener from "./components/ResizeListener";
import Hotkeys from "./components/Hotkeys";
import DebugInfo from "./components/DebugInfo";
import ErrorMessage from "./components/ErrorMessage";
import Album from './views/Album';
import Artist from './views/Artist';
import Playlist from './views/Playlist';
import User from './views/User';
import Track from './views/Track';
import Queue from './views/Queue';
import QueueHistory from './views/QueueHistory';
import Debug from './views/Debug';
import Search from './views/Search';
import Settings from './views/Settings';
import Album from "./views/Album";
import Artist from "./views/Artist";
import Playlist from "./views/Playlist";
import User from "./views/User";
import Track from "./views/Track";
import Queue from "./views/Queue";
import QueueHistory from "./views/QueueHistory";
import Debug from "./views/Debug";
import Search from "./views/Search";
import Settings from "./views/Settings";
import DiscoverRecommendations from './views/discover/DiscoverRecommendations';
import DiscoverFeatured from './views/discover/DiscoverFeatured';
import DiscoverCategories from './views/discover/DiscoverCategories';
import DiscoverCategory from './views/discover/DiscoverCategory';
import DiscoverNewReleases from './views/discover/DiscoverNewReleases';
import DiscoverRecommendations from "./views/discover/DiscoverRecommendations";
import DiscoverFeatured from "./views/discover/DiscoverFeatured";
import DiscoverCategories from "./views/discover/DiscoverCategories";
import DiscoverCategory from "./views/discover/DiscoverCategory";
import DiscoverNewReleases from "./views/discover/DiscoverNewReleases";
import LibraryArtists from './views/library/LibraryArtists';
import LibraryAlbums from './views/library/LibraryAlbums';
import LibraryTracks from './views/library/LibraryTracks';
import LibraryPlaylists from './views/library/LibraryPlaylists';
import LibraryBrowse from './views/library/LibraryBrowse';
import LibraryBrowseDirectory from './views/library/LibraryBrowseDirectory';
import LibraryArtists from "./views/library/LibraryArtists";
import LibraryAlbums from "./views/library/LibraryAlbums";
import LibraryTracks from "./views/library/LibraryTracks";
import LibraryPlaylists from "./views/library/LibraryPlaylists";
import LibraryBrowse from "./views/library/LibraryBrowse";
import LibraryBrowseDirectory from "./views/library/LibraryBrowseDirectory";
import EditPlaylist from './views/modals/EditPlaylist';
import CreatePlaylist from './views/modals/CreatePlaylist';
import EditRadio from './views/modals/EditRadio';
import AddToQueue from './views/modals/AddToQueue';
import InitialSetup from './views/modals/InitialSetup';
import KioskMode from './views/modals/KioskMode';
import ShareConfiguration from './views/modals/ShareConfiguration';
import AddToPlaylist from './views/modals/AddToPlaylist';
import ImageZoom from './views/modals/ImageZoom';
import EditCommand from './views/modals/EditCommand';
import EditPlaylist from "./views/modals/EditPlaylist";
import CreatePlaylist from "./views/modals/CreatePlaylist";
import EditRadio from "./views/modals/EditRadio";
import AddToQueue from "./views/modals/AddToQueue";
import InitialSetup from "./views/modals/InitialSetup";
import KioskMode from "./views/modals/KioskMode";
import ShareConfiguration from "./views/modals/ShareConfiguration";
import AddToPlaylist from "./views/modals/AddToPlaylist";
import ImageZoom from "./views/modals/ImageZoom";
import EditCommand from "./views/modals/EditCommand";
import * as helpers from './helpers';
import * as coreActions from './services/core/actions';
import * as uiActions from './services/ui/actions';
import * as pusherActions from './services/pusher/actions';
import * as mopidyActions from './services/mopidy/actions';
import * as spotifyActions from './services/spotify/actions';
import * as lastfmActions from './services/lastfm/actions';
import * as geniusActions from './services/genius/actions';
import * as snapcastActions from './services/snapcast/actions';
import * as helpers from "./helpers";
import * as coreActions from "./services/core/actions";
import * as uiActions from "./services/ui/actions";
import * as pusherActions from "./services/pusher/actions";
import * as mopidyActions from "./services/mopidy/actions";
import * as spotifyActions from "./services/spotify/actions";
import * as lastfmActions from "./services/lastfm/actions";
import * as geniusActions from "./services/genius/actions";
import * as snapcastActions from "./services/snapcast/actions";
export class App extends React.Component{
export class App extends React.Component {
constructor(props) {
super(props);
this.handleInstallPrompt = this.handleInstallPrompt.bind(this);
this.handleFocusAndBlur = this.handleFocusAndBlur.bind(this);
}
constructor(props){
super(props);
this.handleInstallPrompt = this.handleInstallPrompt.bind(this);
this.handleFocusAndBlur = this.handleFocusAndBlur.bind(this);
}
componentWillMount() {
window.addEventListener(
"beforeinstallprompt",
this.handleInstallPrompt,
false
);
window.addEventListener("focus", this.handleFocusAndBlur, false);
window.addEventListener("blur", this.handleFocusAndBlur, false);
}
componentWillMount(){
window.addEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.addEventListener("focus", this.handleFocusAndBlur, false);
window.addEventListener("blur", this.handleFocusAndBlur, false);
}
componentWillUnmount() {
window.removeEventListener(
"beforeinstallprompt",
this.handleInstallPrompt,
false
);
window.removeEventListener("focus", this.handleFocusAndBlur, false);
window.removeEventListener("blur", this.handleFocusAndBlur, false);
}
componentWillUnmount(){
window.removeEventListener("beforeinstallprompt", this.handleInstallPrompt, false);
window.removeEventListener("focus", this.handleFocusAndBlur, false);
window.removeEventListener("blur", this.handleFocusAndBlur, false);
}
componentDidMount() {
if (this.props.allow_reporting) {
ReactGA.initialize("UA-64701652-3");
}
componentDidMount(){
// Fire up our services
this.props.mopidyActions.connect();
this.props.pusherActions.connect();
this.props.coreActions.getBroadcasts();
if (this.props.allow_reporting){
ReactGA.initialize('UA-64701652-3');
}
// Fire up our services
this.props.mopidyActions.connect();
this.props.pusherActions.connect();
this.props.coreActions.getBroadcasts();
// Check for url-parsed configuration values
var url_vars = this.props.location.query;
if (url_vars) {
var has_values = false;
var values = {};
if (url_vars.host !== undefined) {
has_values = true;
values.host = url_vars.host;
}
if (url_vars.port !== undefined) {
has_values = true;
values.port = url_vars.port;
}
// Check for url-parsed configuration values
var url_vars = this.props.location.query;
if (url_vars){
var has_values = false;
var values = {};
if (url_vars.host !== undefined){
has_values = true;
values.host = url_vars.host;
}
if (url_vars.port !== undefined){
has_values = true;
values.port = url_vars.port;
}
if (has_values) {
this.props.mopidyActions.set(values);
if (has_values){
this.props.mopidyActions.set(values);
// Allow 100ms for the action above to complete before we re-route
setTimeout(() => {
this.props.history.push("/");
}, 100);
}
}
// Allow 100ms for the action above to complete before we re-route
setTimeout(
() => {
this.props.history.push('/');
},
100
);
}
}
// show initial setup if required
if (!this.props.initial_setup_complete) {
this.props.history.push("/initial-setup");
}
}
// show initial setup if required
if (!this.props.initial_setup_complete){
this.props.history.push('/initial-setup');
}
}
componentDidUpdate(prevProps) {
// When we have navigated to a new route
if (this.props.location !== prevProps.location) {
// Log our pageview
if (this.props.allow_reporting) {
ReactGA.set({ page: this.props.location.pathname });
ReactGA.pageview(this.props.location.pathname);
}
componentDidUpdate(prevProps){
// If the location has a "scroll_position" state variable, scroll to it.
// This is invisibly injected to the history by the Link component when navigating, so
// hitting back in the browser allows us to restore the position
var location_state = this.props.location.state
? this.props.location.state
: {};
if (location_state.scroll_position) {
helpers.scrollTo(parseInt(location_state.scroll_position), false);
}
// When we have navigated to a new route
if (this.props.location !== prevProps.location){
// Hide our sidebar
this.props.uiActions.toggleSidebar(false);
// Log our pageview
if (this.props.allow_reporting){
ReactGA.set({ page: this.props.location.pathname });
ReactGA.pageview(this.props.location.pathname);
}
// Unselect any tracks
this.props.uiActions.setSelectedTracks([]);
// If the location has a "scroll_position" state variable, scroll to it.
// This is invisibly injected to the history by the Link component when navigating, so
// hitting back in the browser allows us to restore the position
var location_state = (this.props.location.state ? this.props.location.state : {});
if (location_state.scroll_position){
helpers.scrollTo(parseInt(location_state.scroll_position), false);
}
// Close context menu
if (this.props.context_menu) {
this.props.uiActions.hideContextMenu();
}
}
}
// Hide our sidebar
this.props.uiActions.toggleSidebar(false);
/**
* Using Visibility API, detect whether the browser is in focus or not
*
* This is used to keep background requests lean, preventing a queue of requests building up
* for when focus is retained. Seems most obvious on mobile devices with Chrome as it has throttled
* quota significantly: https://developers.google.com/web/updates/2017/03/background_tabs
*
* @param e Event
**/
handleFocusAndBlur(e) {
this.props.uiActions.setWindowFocus(document.hasFocus());
}
// Unselect any tracks
this.props.uiActions.setSelectedTracks([]);
handleInstallPrompt(e) {
e.preventDefault();
console.log("Install prompt detected");
this.props.uiActions.installPrompt(e);
}
// Close context menu
if (this.props.context_menu){
this.props.uiActions.hideContextMenu();
}
};
}
render() {
let className = this.props.theme + "-theme";
if (this.props.wide_scrollbar_enabled) {
className += " wide-scrollbar";
}
if (this.props.dragging) {
className += " dragging";
}
if (this.props.sidebar_open) {
className += " sidebar-open";
}
if (this.props.touch_dragging) {
className += " touch-dragging";
console.log("TOUCH DRAGGING");
}
if (this.props.context_menu) {
className += " context-menu-open";
}
if (this.props.slim_mode) {
className += " slim-mode";
}
if (this.props.smooth_scrolling_enabled) {
className += " smooth-scrolling-enabled";
}
if (helpers.isTouchDevice()) {
className += " touch";
} else {
className += " notouch";
}
/**
* Using Visibility API, detect whether the browser is in focus or not
*
* This is used to keep background requests lean, preventing a queue of requests building up
* for when focus is retained. Seems most obvious on mobile devices with Chrome as it has throttled
* quota significantly: https://developers.google.com/web/updates/2017/03/background_tabs
*
* @param e Event
**/
handleFocusAndBlur(e){
this.props.uiActions.setWindowFocus(document.hasFocus());
}
return (
<div className={className}>
<div className="body">
<Switch>
<Route path="/initial-setup" component={InitialSetup} />
<Route path="/kiosk-mode" component={KioskMode} />
<Route path="/add-to-playlist/:uris" component={AddToPlaylist} />
<Route path="/image-zoom" component={ImageZoom} />
<Route path="/share-configuration" component={ShareConfiguration} />
<Route path="/edit-command/:id?" component={EditCommand} />
handleInstallPrompt(e){
e.preventDefault();
console.log("Install prompt detected");
this.props.uiActions.installPrompt(e);
}
<Route path="/queue/radio" component={EditRadio} />
<Route path="/queue/add-uri" component={AddToQueue} />
<Route path="/playlist/create" component={CreatePlaylist} />
<Route path="/playlist/:uri/edit" component={EditPlaylist} />
render(){
let className = this.props.theme+'-theme';
if (this.props.wide_scrollbar_enabled){
className += ' wide-scrollbar';
}
if (this.props.dragging){
className += ' dragging';
}
if (this.props.sidebar_open){
className += ' sidebar-open';
}
if (this.props.touch_dragging){
className += ' touch-dragging';
console.log("TOUCH DRAGGING")
}
if (this.props.context_menu){
className += ' context-menu-open';
}
if (this.props.slim_mode){
className += ' slim-mode';
}
if (this.props.smooth_scrolling_enabled){
className += ' smooth-scrolling-enabled';
}
if (helpers.isTouchDevice()){
className += ' touch';
} else {
className += ' notouch';
}
<Route>
<div>
<Sidebar
location={this.props.location}
history={this.props.history}
tabIndex="3"
/>
<PlaybackControls
history={this.props.history}
slim_mode={this.props.slim_mode}
tabIndex="2"
/>
return (
<div className={className}>
<div className="body">
<main id="main" className="smooth-scroll" tabIndex="1">
<Switch>
<Route exact path="/" component={Queue} />
<Switch>
<Route exact path="/queue" component={Queue} />
<Route
exact
path="/queue/history"
component={QueueHistory}
/>
<Route exact path="/settings/debug" component={Debug} />
<Route path="/settings" component={Settings} />
<Route path="/initial-setup" component={InitialSetup} />
<Route path="/kiosk-mode" component={KioskMode} />
<Route path="/add-to-playlist/:uris" component={AddToPlaylist} />
<Route path="/image-zoom" component={ImageZoom} />
<Route path="/share-configuration" component={ShareConfiguration} />
<Route path="/edit-command/:id?" component={EditCommand} />
<Route path="/queue/radio" component={EditRadio} />
<Route path="/queue/add-uri" component={AddToQueue} />
<Route path="/playlist/create" component={CreatePlaylist} />
<Route path="/playlist/:uri/edit" component={EditPlaylist} />
<Route
exact
path="/search/:type?/:term?"
component={Search}
/>
<Route exact path="/album/:uri" component={Album} />
<Route
exact
path="/artist/:uri/:sub_view?"
component={Artist}
/>
<Route exact path="/playlist/:uri" component={Playlist} />
<Route exact path="/user/:uri" component={User} />
<Route exact path="/track/:uri" component={Track} />
<Route>
<div>
<Sidebar location={this.props.location} history={this.props.history} tabIndex="3" />
<PlaybackControls history={this.props.history} slim_mode={this.props.slim_mode} tabIndex="2"/>
<Route
exact
path="/discover/recommendations/:seeds?"
component={DiscoverRecommendations}
/>
<Route
exact
path="/discover/featured"
component={DiscoverFeatured}
/>
<Route
exact
path="/discover/categories/:id"
component={DiscoverCategory}
/>
<Route
exact
path="/discover/categories"
component={DiscoverCategories}
/>
<Route
exact
path="/discover/new-releases"
component={DiscoverNewReleases}
/>
<main id="main" className="smooth-scroll" tabIndex="1">
<Switch>
<Route exact path="/" component={Queue} />
<Route
exact
path="/library/artists"
component={LibraryArtists}
/>
<Route
exact
path="/library/albums"
component={LibraryAlbums}
/>
<Route
exact
path="/library/tracks"
component={LibraryTracks}
/>
<Route
exact
path="/library/playlists"
component={LibraryPlaylists}
/>
<Route
exact
path="/library/browse"
component={LibraryBrowse}
/>
<Route
exact
path="/library/browse/:uri"
component={LibraryBrowseDirectory}
/>
<Route exact path="/queue" component={Queue} />
<Route exact path="/queue/history" component={QueueHistory} />
<Route exact path="/settings/debug" component={Debug} />
<Route path="/settings" component={Settings} />
<Route exact path="/search/:type?/:term?" component={Search} />
<Route exact path="/album/:uri" component={Album} />
<Route exact path="/artist/:uri/:sub_view?" component={Artist} />
<Route exact path="/playlist/:uri" component={Playlist} />
<Route exact path="/user/:uri" component={User} />
<Route exact path="/track/:uri" component={Track} />
<Route exact path="/discover/recommendations/:seeds?" component={DiscoverRecommendations} />
<Route exact path="/discover/featured" component={DiscoverFeatured} />
<Route exact path="/discover/categories/:id" component={DiscoverCategory} />
<Route exact path="/discover/categories" component={DiscoverCategories} />
<Route exact path="/discover/new-releases" component={DiscoverNewReleases} />
<Route>
<ErrorMessage type="not-found" title="Not found">
<p>Oops, that link could not be found</p>
</ErrorMessage>
</Route>
</Switch>
</main>
</div>
</Route>
</Switch>
</div>
<Route exact path="/library/artists" component={LibraryArtists} />
<Route exact path="/library/albums" component={LibraryAlbums} />
<Route exact path="/library/tracks" component={LibraryTracks} />
<Route exact path="/library/playlists" component={LibraryPlaylists} />
<Route exact path="/library/browse" component={LibraryBrowse} />
<Route exact path="/library/browse/:uri" component={LibraryBrowseDirectory} />
<ResizeListener
uiActions={this.props.uiActions}
slim_mode={this.props.slim_mode}
/>
{this.props.hotkeys_enabled && <Hotkeys />}
<ContextMenu />
<Dragger />
<Notifications />
<Route>
<ErrorMessage type="not-found" title="Not found">
<p>Oops, that link could not be found</p>
</ErrorMessage>
</Route>
</Switch>
</main>
</div>
</Route>
</Switch>
</div>
<ResizeListener
uiActions={this.props.uiActions}
slim_mode={this.props.slim_mode}
/>
{this.props.hotkeys_enabled && <Hotkeys />}
<ContextMenu />
<Dragger />
<Notifications />
{this.props.debug_info ? <DebugInfo /> : null}
</div>
);
}
{this.props.debug_info ? <DebugInfo /> : null}
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
theme: state.ui.theme,
wide_scrollbar_enabled: state.ui.wide_scrollbar_enabled,
smooth_scrolling_enabled: state.ui.smooth_scrolling_enabled,
hotkeys_enabled: state.ui.hotkeys_enabled,
allow_reporting: state.ui.allow_reporting,
touch_dragging: state.ui.touch_dragging,
initial_setup_complete: state.ui.initial_setup_complete,
slim_mode: state.ui.slim_mode,
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorization,
sidebar_open: state.ui.sidebar_open,
dragging: (state.ui.dragger && state.ui.dragger.active),
context_menu: state.ui.context_menu,
debug_info: state.ui.debug_info
}
}
return {
theme: state.ui.theme,
wide_scrollbar_enabled: state.ui.wide_scrollbar_enabled,
smooth_scrolling_enabled: state.ui.smooth_scrolling_enabled,
hotkeys_enabled: state.ui.hotkeys_enabled,
allow_reporting: state.ui.allow_reporting,
touch_dragging: state.ui.touch_dragging,
initial_setup_complete: state.ui.initial_setup_complete,
slim_mode: state.ui.slim_mode,
mopidy_connected: state.mopidy.connected,
spotify_authorized: state.spotify.authorization,
sidebar_open: state.ui.sidebar_open,
dragging: state.ui.dragger && state.ui.dragger.active,
context_menu: state.ui.context_menu,
debug_info: state.ui.debug_info
};
};
const mapDispatchToProps = (dispatch) => {
return {
coreActions: bindActionCreators(coreActions, dispatch),
uiActions: bindActionCreators(uiActions, dispatch),
pusherActions: bindActionCreators(pusherActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
lastfmActions: bindActionCreators(lastfmActions, dispatch),
geniusActions: bindActionCreators(geniusActions, dispatch),
snapcastActions: bindActionCreators(snapcastActions, dispatch)
}
}
const mapDispatchToProps = dispatch => {
return {
coreActions: bindActionCreators(coreActions, dispatch),
uiActions: bindActionCreators(uiActions, dispatch),
pusherActions: bindActionCreators(pusherActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
lastfmActions: bindActionCreators(lastfmActions, dispatch),
geniusActions: bindActionCreators(geniusActions, dispatch),
snapcastActions: bindActionCreators(snapcastActions, dispatch)
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App)
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);

View File

@ -1,306 +1,303 @@
.grid {
&,
* {
-webkit-backface-visibility: hidden;
}
&, * {
-webkit-backface-visibility: hidden;
}
&__item {
position: relative !important;
display: inline-block !important;
vertical-align: top;
border-bottom: 0 !important;
cursor: pointer;
&__item {
position: relative !important;
display: inline-block !important;
vertical-align: top;
border-bottom: 0 !important;
cursor: pointer;
&__wrapper {
display: inline-block;
}
&__wrapper {
display: inline-block;
}
&__thumbnail {
@include animate();
max-width: 100%;
}
&__thumbnail {
@include animate();
max-width: 100%;
}
&__name {
@include one_line_text;
padding-top: 12px;
font-size: 15px;
}
&__name {
@include one_line_text;
padding-top: 12px;
font-size: 15px;
}
&__secondary {
@include one_line_text;
padding-top: 2px;
color: colour(secondary_grey);
&__secondary {
@include one_line_text;
padding-top: 2px;
color: colour(secondary_grey);
.source {
padding-right: 6px;
}
}
.source {
padding-right: 6px;
}
}
&:hover {
.thumbnail {
&__image {
transform: scale(1.01);
&:hover {
.thumbnail {
&__image {
transform: scale(1.01);
&--glow {
@include blur(20px);
transform: rotateX(6deg);
}
}
}
}
&--glow {
@include blur(20px);
transform: rotateX(6deg);
}
}
}
}
&:active,
&:focus {
.thumbnail {
&__image {
@include noanimate();
-moz-transform: scale(0.98);
-webkit-transform: scale(0.98);
transform: scale(0.98);
}
}
}
}
&:active,
&:focus {
.thumbnail {
&__image {
@include noanimate();
-moz-transform: scale(0.98);
-webkit-transform: scale(0.98);
transform: scale(0.98);
}
}
}
}
&--tiles {
.grid__item {
position: relative;
&--tiles {
.grid__item {
position: relative;
&__name {
position: absolute;
bottom: 15%;
left: 0;
right: 0;
text-align: center;
font-size: 14px;
font-weight: 600;
color: colour(white);
z-index: 2;
}
}
&__name {
position: absolute;
bottom: 15%;
left: 0;
right: 0;
text-align: center;
font-size: 14px;
font-weight: 600;
color: colour(white);
z-index: 2;
}
}
@include responsive(null, $bp_wide) {
.grid__item {
&__name {
font-size: 16px;
}
}
}
}
@include responsive(null, $bp_wide){
.grid__item {
&__name {
font-size: 16px;
}
}
}
}
@include responsive(null, $bp_huge) {
&--mini {
.grid__item {
@include grid_item(3);
}
&--single-row {
.grid-item:nth-child(1n + 4) {
display: none;
}
}
}
&:not(.grid--mini) {
.grid__item {
@include grid_item(5);
}
&--single-row {
.grid-item:nth-child(1n + 6) {
display: none;
}
}
}
}
@include responsive(null, $bp_huge){
&--mini {
.grid__item {
@include grid_item(3);
}
&--single-row {
.grid-item:nth-child(1n+4){
display: none;
}
}
}
&:not(.grid--mini){
.grid__item {
@include grid_item(5);
}
&--single-row {
.grid-item:nth-child(1n+6){
display: none;
}
}
}
}
@include responsive($bp_huge, 1200px) {
&--mini {
.grid__item {
@include grid_item(2);
}
&--single-row {
.grid-item:nth-child(1n + 3) {
display: none;
}
}
}
&:not(.grid--mini) {
.grid__item {
@include grid_item(4);
}
&--single-row {
.grid-item:nth-child(1n + 5) {
display: none;
}
}
}
}
@include responsive($bp_huge, 1200px){
&--mini {
.grid__item {
@include grid_item(2);
}
&--single-row {
.grid-item:nth-child(1n+3){
display: none;
}
}
}
&:not(.grid--mini){
.grid__item {
@include grid_item(4);
}
&--single-row {
.grid-item:nth-child(1n+5){
display: none;
}
}
}
}
@include responsive(1200px, 800px) {
&--mini {
.grid__item {
@include grid_item(2);
}
&--single-row {
.grid-item:nth-child(1n + 3) {
display: none;
}
}
}
&:not(.grid--mini) {
.grid__item {
@include grid_item(4);
}
&--single-row {
.grid-item:nth-child(1n + 5) {
display: none;
}
}
}
}
@include responsive(1200px, 800px){
&--mini {
.grid__item {
@include grid_item(2);
}
&--single-row {
.grid-item:nth-child(1n+3){
display: none;
}
}
}
&:not(.grid--mini){
.grid__item {
@include grid_item(4);
}
&--single-row {
.grid-item:nth-child(1n+5){
display: none;
}
}
}
}
@include responsive(800px, 500px) {
&--mini {
.grid__item {
@include grid_item(6, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n + 7) {
display: none;
}
}
}
&:not(.grid--mini) {
.grid__item {
@include grid_item(3, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n + 4) {
display: none;
}
}
}
}
@include responsive(800px, 500px){
&--mini{
.grid__item {
@include grid_item(6, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n+7){
display: none;
}
}
}
&:not(.grid--mini){
.grid__item {
@include grid_item(3, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n+4){
display: none;
}
}
}
}
@include responsive(500px){
&--mini{
.grid__item {
@include grid_item(3, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n+4){
display: none;
}
}
}
&:not(.grid--mini){
.grid__item {
@include grid_item(2, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n+5){
display: none;
}
}
}
}
@include responsive(500px) {
&--mini {
.grid__item {
@include grid_item(3, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n + 4) {
display: none;
}
}
}
&:not(.grid--mini) {
.grid__item {
@include grid_item(2, 2%, 4%);
}
&--single-row {
.grid-item:nth-child(1n + 5) {
display: none;
}
}
}
}
}
.tiles {
padding-bottom: 60px;
padding-bottom: 60px;
.tile {
color: colour(white);
text-align: center;
position: relative;
z-index: 1;
float: left;
overflow: hidden;
border-radius: 3px;
.tile {
color: colour(white);
text-align: center;
position: relative;
z-index: 1;
float: left;
overflow: hidden;
border-radius: 3px;
.light-theme & {
color: colour(darkest_grey);
}
.light-theme & {
color: colour(darkest_grey);
}
.content {
display: block;
position: absolute;
top: 50%;
left: 10%;
right: 10%;
vertical-align: top;
margin-top: -12px;
font-size: 16px;
z-index: 2;
}
.content {
display: block;
position: absolute;
top: 50%;
left: 10%;
right: 10%;
vertical-align: top;
margin-top: -12px;
font-size: 16px;
z-index: 2;
}
&:last-child {
@include clearfix();
}
&:last-child {
@include clearfix();
}
&:before {
content: '';
display: block;
width: 100%;
padding-bottom: 100%;
background: lighten(colour(dark_grey), 2%);
z-index: -2;
&:before {
content: "";
display: block;
width: 100%;
padding-bottom: 100%;
background: lighten(colour(dark_grey), 2%);
z-index: -2;
.light-theme & {
background: colour(faint_grey);
}
}
.light-theme & {
background: darken(colour(faint_grey), 5%);
}
}
&.thumbnail-wrapper {
&:before {
display: none;
}
}
}
&.thumbnail-wrapper {
&:before {
display: none;
}
}
}
&.artist-stats {
&.artist-stats {
.tile {
.content {
.icon {
display: block;
position: absolute;
top: 50%;
left: 10%;
right: 10%;
text-align: center;
margin-top: -27px;
font-size: 60px;
z-index: -1;
opacity: 0.1;
}
}
}
.tile {
.content {
.icon {
display: block;
position: absolute;
top: 50%;
left: 10%;
right: 10%;
text-align: center;
margin-top: -27px;
font-size: 60px;
z-index: -1;
opacity: 0.1;
}
}
}
@include responsive(null, $bp_medium) {
.tile {
@include grid_item(2);
}
}
@include responsive(null, $bp_medium){
.tile {
@include grid_item(2);;
}
}
@include responsive($bp_medium) {
padding-bottom: 20px;
@include responsive($bp_medium){
padding-bottom: 20px;
.tile {
@include grid_item(3);;
}
}
.tile {
@include grid_item(3);
}
}
@include responsive($bp_narrow){
.tile {
.text {
font-size: 14px;
.icon {
font-size: 28px;
margin-top: -12px;
}
}
}
}
}
}
@include responsive($bp_narrow) {
.tile {
.text {
font-size: 14px;
.icon {
font-size: 28px;
margin-top: -12px;
}
}
}
}
}
}

View File

@ -1,406 +1,397 @@
.playback-controls {
position: fixed;
z-index: 99;
bottom: 0;
right: 0;
left: 0;
height: 60px;
background: colour(white);
color: colour(darkest_grey);
transform-style: preserve-3d;
border-left: 230px solid colour(white);
box-shadow: 0 -1px 8px rgba(0,0,0,0.1);
position: fixed;
z-index: 99;
bottom: 0;
right: 0;
left: 0;
height: 60px;
background: colour(white);
color: colour(darkest_grey);
transform-style: preserve-3d;
border-left: 230px solid colour(white);
box-shadow: 0 -1px 8px rgba(0, 0, 0, 0.1);
.light-theme & {
background: colour(faint_grey);
border-left-color: colour(faint_grey);
}
.current-track {
position: absolute;
bottom: 0;
width: 210px;
left: -230px;
z-index: 1;
text-decoration: none;
.current-track {
position: absolute;
bottom: 0;
width: 210px;
left: -230px;
z-index: 1;
text-decoration: none;
@keyframes slide_left {
0% {
transform: translateX(0px);
opacity: 1;
}
100% {
transform: translateX(-15px);
opacity: 0;
}
}
@keyframes slide_left {
0% {
transform: translateX(0px);
opacity: 1;
}
100% {
transform: translateX(-15px);
opacity: 0;
}
}
@keyframes slide_right {
0% {
transform: translateX(0px);
opacity: 1;
}
100% {
transform: translateX(15px);
opacity: 0;
}
}
@keyframes slide_right {
0% {
transform: translateX(0px);
opacity: 1;
}
100% {
transform: translateX(15px);
opacity: 0;
}
}
&__transition {
z-index: 2;
background: lighten(colour(white), 15%);
&__transition {
z-index: 2;
background: lighten(colour(white), 15%);
.text {
@include animate(0.15s);
opacity: 0;
}
.text {
@include animate(0.15s);
opacity: 0;
}
@include responsive($bp_medium) {
animation-duration: 0.25s;
animation-timing-function: ease-out;
@include responsive($bp_medium){
animation-duration: 0.25s;
animation-timing-function: ease-out;
&--previous {
animation-name: slide_right;
}
&--previous {
animation-name: slide_right;
}
&--next {
animation-name: slide_left;
}
}
}
&--next {
animation-name: slide_left;
}
}
}
.thumbnail {
float: left;
cursor: pointer;
width: 44px;
margin: 8px;
margin-right: 12px;
.thumbnail {
float: left;
cursor: pointer;
width: 44px;
margin: 8px;
margin-right: 12px;
&__image {
background-color: colour(faint_grey);
}
&__image {
background-color: colour(faint_grey);
}
&:before {
@include animate();
display: block;
content: "\f065";
font-family: "FontAwesome";
position: absolute;
top: 50%;
left: 0;
bottom: 0;
right: 0;
margin-top: -9px;
text-align: center;
font-size: 18px;
color: colour(white);
z-index: 3;
opacity: 0;
}
&:before {
@include animate();
display: block;
content: "\f065";
font-family: "FontAwesome";
position: absolute;
top: 50%;
left: 0;
bottom: 0;
right: 0;
margin-top: -9px;
text-align: center;
font-size: 18px;
color: colour(white);
z-index: 3;
opacity: 0;
}
&:after {
@include animate();
content: "";
display: block;
background: rgba(0, 0, 0, 0.75);
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
border-radius: 3px;
opacity: 0;
z-index: 2;
}
&:after {
@include animate();
content: '';
display: block;
background: rgba(0,0,0,0.75);
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
border-radius: 3px;
opacity: 0;
z-index: 2;
}
&:hover {
&:after,
&:before {
opacity: 1;
}
}
}
&:hover{
&:after,
&:before {
opacity: 1;
}
}
}
.text {
opacity: 1;
line-height: 1.1rem;
font-size: 0.9rem;
padding-top: 1.05rem;
.text {
opacity: 1;
line-height: 1.1rem;
font-size: 0.9rem;
padding-top: 1.05rem;
.title {
@include one_line_text;
}
.title {
@include one_line_text;
}
.artist-sentence {
opacity: 0.5;
display: block;
@include one_line_text;
.artist {
color: inherit;
text-decoration: none;
border-bottom: 1px dotted transparent;
}
}
}
}
.artist-sentence {
opacity: 0.5;
display: block;
@include one_line_text;
.control {
@include animate();
@include noselect();
@include click_feedback();
cursor: pointer;
padding: 12px 8px;
display: inline-block;
vertical-align: bottom;
background: none;
.artist {
color: inherit;
text-decoration: none;
border-bottom: 1px dotted transparent;
}
}
}
}
.icon {
font-size: 0.9rem;
margin-bottom: 0;
}
.control {
@include animate();
@include noselect();
@include click_feedback();
cursor: pointer;
padding: 12px 8px;
display: inline-block;
vertical-align: bottom;
background: none;
&--active {
color: colour(turquoise) !important;
}
.icon {
font-size: 0.9rem;
margin-bottom: 0;
}
&:hover,
&:focus {
opacity: 1;
}
}
&--active {
color: colour(turquoise) !important;
}
section {
position: absolute;
bottom: 10px;
&:hover,
&:focus {
opacity: 1;
}
}
&.playback {
bottom: 7px;
left: 0;
width: 10rem;
section {
position: absolute;
bottom: 10px;
.control {
padding-left: 4px;
padding-right: 4px;
&.playback {
bottom: 7px;
left: 0;
width: 10rem;
.icon {
font-size: 1.3rem;
}
.control {
padding-left: 4px;
padding-right: 4px;
&.play {
margin-bottom: -0.8rem;
color: colour(turquoise);
.icon {
font-size: 1.3rem;
}
.icon {
font-size: 3rem;
}
}
}
}
&.play {
margin-bottom: -0.8rem;
color: colour(turquoise);
&.progress {
bottom: 13px;
left: 10rem;
right: 25rem;
padding-left: 20px;
padding-right: 20px;
color: colour(mid_grey);
.icon {
font-size: 3rem;
}
}
}
}
.slider {
position: absolute;
bottom: 2px;
left: 60px;
right: 60px;
&.progress {
bottom: 13px;
left: 10rem;
right: 25rem;
padding-left: 20px;
padding-right: 20px;
color: colour(mid_grey);
&__track {
&__progress {
@include animate(0.2s, linear);
}
}
}
.slider {
position: absolute;
bottom: 2px;
left: 60px;
right: 60px;
.current {
font-size: 11px;
position: absolute;
bottom: 6px;
left: 0;
width: 50px;
text-align: right;
}
&__track {
&__progress {
@include animate(0.2s, linear);
}
}
}
.total {
font-size: 11px;
position: absolute;
bottom: 6px;
right: 0;
width: 50px;
}
}
.current {
font-size: 11px;
position: absolute;
bottom: 6px;
left: 0;
width: 50px;
text-align: right;
}
&.settings {
right: 14rem;
width: 10rem;
text-align: center;
}
.total {
font-size: 11px;
position: absolute;
bottom: 6px;
right: 0;
width: 50px;
}
}
&.volume {
right: 2rem;
width: 10rem;
font-size: 18px;
&.settings {
right: 14rem;
width: 10rem;
text-align: center;
}
.slider__wrapper {
position: absolute;
bottom: 6px;
right: 0;
left: 30px;
}
}
&.volume {
right: 2rem;
width: 10rem;
font-size: 18px;
&.triggers {
display: none;
}
}
.slider__wrapper {
position: absolute;
bottom: 6px;
right: 0;
left: 30px;
}
}
@include responsive($bp_medium){
border-left: none;
&.triggers {
display: none;
}
}
&--touch-enabled .control.next {
display: none;
}
@include responsive($bp_medium) {
border-left: none;
.current-track {
width: auto;
bottom: 0.65rem;
left: 80px;
right: 80px;
text-align: center;
font-size: 0.9rem;
line-height: 1.2em;
margin: auto;
&--touch-enabled .control.next {
display: none;
}
.title,
.artist {
padding-top: 0;
}
.current-track {
width: auto;
bottom: 0.65rem;
left: 80px;
right: 80px;
text-align: center;
font-size: 0.9rem;
line-height: 1.2em;
margin: auto;
.thumbnail {
display: none;
}
}
.title,
.artist {
padding-top: 0;
}
section {
.thumbnail {
display: none;
}
}
&.playback {
left: 0;
width: 6rem;
section {
&.playback {
left: 0;
width: 6rem;
.control {
&.play {
margin-bottom: -1rem;
}
.control {
&.play {
margin-bottom: -1rem;
}
&.previous {
display: none;
}
&.stop {
display: none;
}
}
}
&.previous {
display: none;
}
&.settings {
display: none;
}
&.stop {
display: none;
}
}
}
&.volume {
display: none;
}
&.settings {
display: none;
}
&.progress {
display: none;
}
&.volume {
display: none;
}
&.triggers {
display: block;
right: 10px;
&.progress {
display: none;
}
.icon {
font-size: 1.2rem;
}
&.triggers {
display: block;
right: 10px;
@include resolution(2){
bottom: 4px;
.icon {
font-size: 1.4rem;
}
}
.icon {
font-size: 1.2rem;
}
.sidebar-toggle.open {
opacity: 1 !important;
@include resolution(2) {
bottom: 4px;
&:before {
background: rgba(0,0,0,0.8);
content: '';
display: block;
position: fixed;
bottom: 0;
right: 0;
width: 100vw;
height: 100vh;
z-index: 99;
}
}
}
}
.icon {
font-size: 1.4rem;
}
}
&--expanded {
height: 140px;
max-height: 100%;
.sidebar-toggle.open {
opacity: 1 !important;
section {
&.settings {
display: block;
right: 0;
bottom: 90px;
padding-right: 10px;
text-align: right;
width: 100px;
}
&:before {
background: rgba(0, 0, 0, 0.8);
content: "";
display: block;
position: fixed;
bottom: 0;
right: 0;
width: 100vw;
height: 100vh;
z-index: 99;
}
}
}
}
&.volume {
width: auto;
display: block;
right: 100px;
left: 10px;
bottom: 88px;
&--expanded {
height: 140px;
max-height: 100%;
@include resolution(2){
right: 115px;
.slider__wrapper {
bottom: 9px;
}
}
}
section {
&.settings {
display: block;
right: 0;
bottom: 90px;
padding-right: 10px;
text-align: right;
width: 100px;
}
&.progress {
display: block;
bottom: 55px;
left: -15px;
right: -15px;
}
}
}
&.volume {
width: auto;
display: block;
right: 100px;
left: 10px;
bottom: 88px;
@include resolution(2){
@include resolution(2) {
right: 115px;
.control {
padding: 14px 8px;
}
}
}
.slider__wrapper {
bottom: 9px;
}
}
}
&.progress {
display: block;
bottom: 55px;
left: -15px;
right: -15px;
}
}
}
@include resolution(2) {
.control {
padding: 14px 8px;
}
}
}
}

View File

@ -1,175 +1,170 @@
.sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
z-index: 96;
width: 220px;
overflow: hidden;
color: colour(white);
box-sizing: border-box;
transform-style: preserve-3d;
position: fixed;
top: 0;
left: 0;
bottom: 0;
z-index: 96;
width: 220px;
overflow: hidden;
color: colour(white);
box-sizing: border-box;
transform-style: preserve-3d;
.light-theme & {
background: colour(white);
}
&__liner {
overflow-y: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 60px;
box-sizing: border-box;
z-index: 2;
overflow-y: auto;
}
&__liner {
overflow-y: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 60px;
box-sizing: border-box;
z-index: 2;
overflow-y: auto;
}
&__menu {
z-index: 2;
position: relative;
padding-top: 20px;
line-height: 1em;
&__menu {
z-index: 2;
position: relative;
padding-top: 20px;
line-height: 1em;
&__item {
@include gradient_overlay(3px);
font-family: "Overpass";
font-weight: 600;
font-size: 15px;
color: colour(white);
text-decoration: none;
display: block;
padding: 13px 10px 10px;
margin: 0 18px;
border-radius: 3px;
&__item {
@include gradient_overlay(3px);
font-family: "Overpass";
font-weight: 600;
font-size: 15px;
color: colour(white);
text-decoration: none;
display: block;
padding: 13px 10px 10px;
margin: 0 18px;
border-radius: 3px;
.light-theme & {
color: colour(darkest_grey);
font-weight: 600;
}
.light-theme & {
color: colour(darkest_grey);
font-weight: 600;
}
.icon {
padding-right: 8px;
font-size: 1em;
}
.icon {
padding-right: 8px;
font-size: 1em;
}
.status {
margin-left: 5px;
float: right;
.status {
margin-left: 5px;
float: right;
.icon {
padding-right: 0;
padding-left: 8px;
}
}
.icon {
padding-right: 0;
padding-left: 8px;
}
}
&--active {
background: colour(turquoise);
color: colour(white);
.light-theme & {
color: colour(white);
}
&--active {
background: colour(turquoise);
color: colour(white);
.status {
.icon {
color: colour(white) !important;
}
}
.light-theme & {
color: colour(white);
}
&:before {
opacity: 0.15;
}
}
.status {
.icon {
color: colour(white) !important;
}
}
&[disabled] {
opacity: 0.3;
cursor: not-allowed;
}
&:before {
opacity: 0.15;
}
}
&:hover:not([disabled]){
&:before {
opacity: 0.15;
}
}
&[disabled] {
opacity: 0.3;
cursor: not-allowed;
}
&:focus:not([disabled]):not(.sidebar__menu__item--active){
background: rgba(128,128,128,0.25);
}
&:hover:not([disabled]) {
&:before {
opacity: 0.15;
}
}
&:active {
@include noanimate();
transform: translate(1px,1px);
}
}
&:focus:not([disabled]):not(.sidebar__menu__item--active) {
background: rgba(128, 128, 128, 0.25);
}
&__section {
padding-bottom: 25px;
&:active {
@include noanimate();
transform: translate(1px, 1px);
}
}
&__title {
display: block;
padding: 0 26px 5px 26px;
font-size: 12px;
text-transform: uppercase;
opacity: 0.5;
color: colour(mid_grey);
}
}
}
&__section {
padding-bottom: 25px;
.close {
display: none;
position: absolute;
bottom: 4px;
right: 4px;
padding: 10px 8px;
display: inline-block;
opacity: 0.5;
z-index: 99;
.light-theme & {
color: colour(darkest_grey);
}
}
&__title {
display: block;
padding: 0 26px 5px 26px;
font-size: 12px;
text-transform: uppercase;
opacity: 0.5;
color: colour(mid_grey);
}
}
}
@include responsive($bp_medium){
@include animate(0.15s);
width: 220px;
left: auto;
right: -220px;
padding-bottom: 0;
position: fixed;
z-index: 100;
.close {
display: none;
position: absolute;
bottom: 4px;
right: 4px;
padding: 10px 8px;
display: inline-block;
opacity: 0.5;
z-index: 99;
.sidebar-open & {
-ms-transform: translate(-220px, 0);
-webkit-transform: translate(-220px, 0);
transform: translate(-220px, 0);
}
.light-theme & {
color: colour(darkest_grey);
}
}
&__liner {
bottom: 0 !important;
padding-bottom: 30px;
}
@include responsive($bp_medium) {
@include animate(0.15s);
width: 220px;
left: auto;
right: -220px;
padding-bottom: 0;
position: fixed;
z-index: 100;
.thumbnail {
display: none;
}
.sidebar-open & {
-ms-transform: translate(-220px, 0);
-webkit-transform: translate(-220px, 0);
transform: translate(-220px, 0);
}
.close {
display: block;
}
&__liner {
bottom: 0 !important;
padding-bottom: 30px;
}
&__menu {
&__section {
padding-bottom: 10px;
.thumbnail {
display: none;
}
&__title {
padding-bottom: 2px;
}
}
}
}
}
.close {
display: block;
}
&__menu {
&__section {
padding-bottom: 10px;
&__title {
padding-bottom: 2px;
}
}
}
}
}

View File

@ -1,43 +1,42 @@
.sub-views {
&__option {
@include feature_font();
color: colour(white);
display: inline-block;
margin-right: 25px;
font-size: 15px;
font-weight: 500;
border-bottom: 3px solid transparent !important;
cursor: pointer;
&__option {
@include feature_font();
color: colour(white);
display: inline-block;
margin-right: 25px;
font-size: 15px;
font-weight: 500;
border-bottom: 3px solid transparent !important;
cursor: pointer;
.light-theme & {
//color: colour(darkest_grey);
}
.light-theme & {
//color: colour(darkest_grey);
}
h4 {
margin: 8px 0 4px;
}
h4 {
margin: 8px 0 4px;
}
&--active {
border-color: colour(white) !important;
&--active {
border-color: colour(white) !important;
.light-theme & {
border-color: colour(darkest_grey)
}
}
.light-theme & {
border-color: colour(faint_grey) !important;
}
}
&:not(.sub-views__option--active):hover {
border-color: rgba(255,255,255,0.2) !important;
&:not(.sub-views__option--active):hover {
border-color: rgba(255, 255, 255, 0.2) !important;
.light-theme & {
border-color: rgba(0,0,0,0.2);
}
}
}
.light-theme & {
border-color: rgba(0, 0, 0, 0.2);
}
}
}
@include responsive($bp_medium){
&__option {
margin-right: 15px;
}
}
}
@include responsive($bp_medium) {
&__option {
margin-right: 15px;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,155 +1,152 @@
.artist-view {
.body-loader:not(.lazy-loader) {
padding: 15vh 0;
}
.body-loader:not(.lazy-loader){
padding: 15vh 0;
}
.intro {
position: relative;
@include clearfix();
.intro {
position: relative;
@include clearfix();
.liner {
position: relative;
z-index: 1;
padding: 35vh 40px 0;
.liner {
position: relative;
z-index: 1;
padding: 35vh 40px 0;
h1 {
padding-bottom: 25px;
font-size: 5rem;
line-height: 5rem;
h1 {
padding-bottom: 25px;
font-size: 5rem;
line-height: 5rem;
.light-theme & {
color: colour(white);
}
}
.light-theme & {
color: colour(white);
}
}
.actions {
.context-menu-trigger {
color: colour(white);
}
}
.actions {
.context-menu-trigger {
color: colour(white);
}
}
.sub-views {
padding-top: 25px;
}
}
}
.sub-views {
padding-top: 25px;
}
}
}
.content-wrapper {
background: colour(dark_grey);
.content-wrapper {
background: colour(dark_grey);
.light-theme & {
background: colour(faint_grey);
}
}
.light-theme & {
background: colour(white);
}
}
.body {
&.overview {
.albums {
padding-top: 30px;
}
}
.body {
&.about {
@include clearfix();
&.overview {
.albums {
padding-top: 30px;
}
}
.biography {
padding-left: 40px;
box-sizing: border-box;
&.about {
@include clearfix();
.biography-text {
overflow-wrap: break-word;
}
}
}
}
.biography {
padding-left: 40px;
box-sizing: border-box;
@include responsive($bp_wide) {
.intro {
.liner {
h1 {
font-size: 4rem;
line-height: 4rem;
}
}
}
}
.biography-text {
overflow-wrap: break-word;
}
}
}
}
@include responsive($bp_medium) {
.intro {
margin-bottom: 0;
@include responsive($bp_wide){
.intro {
.liner {
h1 {
font-size: 4rem;
line-height: 4rem;
}
}
}
}
.liner {
padding-left: 0;
padding-right: 0;
padding-top: 30vh;
@include responsive($bp_medium){
.intro {
margin-bottom: 0;
.thumbnail {
position: static;
float: left;
margin: 0 20px 0 20px;
width: 30%;
}
.liner {
padding-left: 0;
padding-right: 0;
padding-top: 30vh;
h1 {
@include clearfix();
padding: 15vw 10px 0;
font-size: 3rem;
line-height: 3rem;
}
.thumbnail {
position: static;
float: left;
margin: 0 20px 0 20px;
width: 30%;
}
.actions {
padding: 30px 10px 0;
}
h1 {
@include clearfix();
padding: 15vw 10px 0;
font-size: 3rem;
line-height: 3rem;
}
.sub-views {
margin-left: 5px;
padding-top: 10px;
.actions {
padding: 30px 10px 0;
}
.option {
margin: 0 8px;
}
}
}
}
.sub-views {
margin-left: 5px;
padding-top: 10px;
.body {
&.overview {
.top-tracks h4 {
display: none;
}
.albums h4 {
padding: 0;
margin: 0 0 -30px;
}
.col--w70 {
width: 100%;
}
.col--w5,
.related-artists {
display: none;
}
.grid-wrapper {
padding-top: 40px !important;
}
}
.option {
margin: 0 8px;
}
}
}
}
&.about {
.col {
&--w40,
&--w60 {
@include clearfix();
width: 100%;
float: none;
}
}
.body {
&.overview {
.top-tracks h4 {
display: none;
}
.albums h4 {
padding: 0;
margin: 0 0 -30px;
}
.col--w70 {
width: 100%;
}
.col--w5,
.related-artists {
display: none;
}
.grid-wrapper {
padding-top: 40px !important;
}
}
&.about {
.col {
&--w40,
&--w60 {
@include clearfix();
width: 100%;
float: none;
}
}
.biography {
padding-left: 0;
}
}
}
}
.biography {
padding-left: 0;
}
}
}
}
}

View File

@ -1,381 +1,380 @@
.modal {
@include fadein();
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: darken(colour(darkest_grey), 2%);
overflow-y: auto;
overflow-x: hidden;
min-height: 100%;
z-index: 98;
@include fadein();
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: darken(colour(darkest_grey), 2%);
overflow-y: auto;
overflow-x: hidden;
min-height: 100%;
z-index: 98;
.light-theme & {
color: colour(white);
}
.light-theme & {
background: darken(colour(faint_grey), 6%);
color: colour(darkest_grey);
}
.controls {
position: absolute;
top: 10px;
right: 10px;
z-index: 99;
.controls {
position: absolute;
top: 10px;
right: 10px;
z-index: 99;
.control {
@include animate();
display: block;
float: right;
opacity: 0.5;
cursor: pointer;
padding: 20px;
color: colour(white);
.control {
@include animate();
display: block;
float: right;
opacity: 0.5;
cursor: pointer;
padding: 20px;
color: colour(white);
&:hover {
opacity: 1;
}
&:hover {
opacity: 1;
}
.icon {
font-size: 35px;
}
}
}
.icon {
font-size: 35px;
}
.actions {
padding-top: 50px;
text-align: center;
.light-theme & {
color: colour(darkest_grey);
}
}
}
.button,
button {
margin: 0 3px;
}
}
.actions {
padding-top: 50px;
text-align: center;
.content {
padding: 80px 20%;
margin: 0 auto;
width: 60%;
color: colour(white);
.button,
button {
margin: 0 3px;
}
}
h1 {
padding-bottom: 20px;
padding-right: 60px;
.content {
padding: 80px 20%;
margin: 0 auto;
width: 60%;
color: inherit;
.light-theme & {
color: colour(white);
}
}
h1 {
padding-bottom: 20px;
padding-right: 60px;
}
.no-results {
padding: 0;
}
.no-results {
padding: 0;
}
form {
padding-top: 50px;
form {
padding-top: 50px;
.field {
padding-bottom: 20px;
position: relative;
.field {
padding-bottom: 20px;
position: relative;
.name {
font-size: 16px;
width: 18%;
padding-right: 2%;
float: left;
padding-top: 8px;
color: colour(mid_grey);
}
.name {
font-size: 16px;
width: 18%;
padding-right: 2%;
float: left;
padding-top: 8px;
color: colour(mid_grey);
}
.description {
padding-left: 0;
padding-right: 0;
}
.description {
padding-left: 0;
padding-right: 0;
}
&.radio,
&.checkbox {
padding-top: 8px;
}
}
}
&.radio,
&.checkbox {
padding-top: 8px;
}
}
}
.add-uri,
.remove-uri {
position: absolute;
top: 2px;
right: 6px;
padding: 8px;
margin: 0;
min-width: 0;
color: #FFFFFF;
background: transparent;
margin-top: 0 !important;
.add-uri,
.remove-uri {
position: absolute;
top: 2px;
right: 6px;
padding: 8px;
margin: 0;
min-width: 0;
color: #ffffff;
background: transparent;
margin-top: 0 !important;
&.remove-uri {
top: 6px;
}
&.remove-uri {
top: 6px;
}
&:before {
display: none !important;
}
&:before {
display: none !important;
}
&:hover {
color: colour(turquoise);
&:hover {
color: colour(turquoise);
&.remove-uri {
color: colour(red);
}
}
}
&.remove-uri {
color: colour(red);
}
}
}
@include responsive($bp_medium){
.add-uri {
top: 36px;
}
}
@include responsive($bp_medium) {
.add-uri {
top: 36px;
}
}
.list {
@include clearfix();
.list {
@include clearfix();
&__item {
@include animate();
box-sizing: border-box;
display: block;
padding: 14px 12px 12px;
position: relative;
border: 0;
border-radius: 3px;
margin-left: -12px;
margin-right: -12px;
font-size: 16px;
&__item {
@include animate();
box-sizing: border-box;
display: block;
padding: 14px 12px 12px;
position: relative;
border: 0;
border-radius: 3px;
margin-left: -12px;
margin-right: -12px;
font-size: 16px;
.source {
position: absolute;
top: 18px;
left: 10px;
}
.source {
position: absolute;
top: 18px;
left: 10px;
}
&:hover {
background: rgba(255,255,255,0.1);
}
}
&:hover {
background: rgba(255, 255, 255, 0.1);
}
}
&.playlists {
padding-top: 40px;
&.playlists {
padding-top: 40px;
.list__item {
margin: 5px 0;
padding: 10px;
cursor: pointer;
.list__item {
margin: 5px 0;
padding: 10px;
cursor: pointer;
&:before {
display: none;
}
&:before {
display: none;
}
.thumbnail {
float: left;
}
.thumbnail {
float: left;
}
&__name,
&__details {
padding-left: 70px;
}
&__name,
&__details {
padding-left: 70px;
}
&__name {
padding-top: 0;
margin-bottom: 5px;
}
&__name {
padding-top: 0;
margin-bottom: 5px;
}
.source {
position: static;
top: auto;
left: auto;
}
}
}
.source {
position: static;
top: auto;
left: auto;
}
}
}
&.small {
display: flex;
flex-wrap: wrap;
&.small {
display: flex;
flex-wrap: wrap;
.list__item {
width: 50%;
font-size: inherit;
}
}
}
}
.list__item {
width: 50%;
font-size: inherit;
}
}
}
}
&--image-zoom {
.content {
text-align: center;
padding: 100px 5%;
width: 90%;
box-sizing: border-box;
&--image-zoom {
.content {
text-align: center;
padding: 100px 5%;
width: 90%;
box-sizing: border-box;
img {
max-width: 100%;
}
}
}
img {
max-width: 100%;
}
}
}
&--edit-radio {
form {
.field {
position: relative;
margin-top: 50px;
&--edit-radio {
form {
.field {
position: relative;
margin-top: 50px;
input[type="text"]{
padding-right: 80px;
}
}
}
}
input[type="text"] {
padding-right: 80px;
}
}
}
}
&--share-configuration {
.field.checkbox {
.label {
.title {
font-size: 1.2rem;
}
&--share-configuration {
.field.checkbox {
.label {
.title {
font-size: 1.2rem;
}
.description {
padding-top: 4px;
}
}
}
}
.description {
padding-top: 4px;
}
}
}
}
&--kiosk-mode {
background: colour(black);
overflow: hidden;
&--kiosk-mode {
background: colour(black);
overflow: hidden;
.content {
padding: 5%;
width: 90%;
height: 90%;
text-align: center;
.content {
padding: 5%;
width: 90%;
height: 90%;
text-align: center;
.thumbnail.background {
position: absolute;
top: -5vh;
right: -5vw;
bottom: -5vh;
left: -5vw;
width: auto;
opacity: 0.2;
max-width: none;
.thumbnail.background {
position: absolute;
top: -5vh;
right: -5vw;
bottom: -5vh;
left: -5vw;
width: auto;
opacity: 0.2;
max-width: none;
.thumbnail__image {
@include blur(100px);
width: 110vw;
padding-bottom: 110vh;
}
}
.thumbnail__image {
@include blur(100px);
width: 110vw;
padding-bottom: 110vh;
}
}
.artwork {
width: 70vw;
margin: 0 auto;
max-width: 60vh;
max-height: 60vh;
z-index: 2;
position: relative;
cursor: pointer;
.artwork {
width: 70vw;
margin: 0 auto;
max-width: 60vh;
max-height: 60vh;
z-index: 2;
position: relative;
cursor: pointer;
.thumbnail {
max-width: none;
}
.thumbnail {
max-width: none;
}
.icon {
@include animate();
display: inline-block;
position: absolute;
color: colour(darkest_grey);
font-size: 20rem;
top: 25%;
left: 0;
right: 0;
text-align: center;
opacity: 0;
z-index: 2;
}
.icon {
@include animate();
display: inline-block;
position: absolute;
color: colour(darkest_grey);
font-size: 20rem;
top: 25%;
left: 0;
right: 0;
text-align: center;
opacity: 0;
z-index: 2;
}
&:hover {
.icon {
opacity: 0.75;
}
}
}
&:hover {
.icon {
opacity: 0.75;
}
}
}
.current-track {
padding-top: 80px;
font-size: 30px;
.current-track {
padding-top: 80px;
font-size: 30px;
.artist-sentence {
opacity: 0.5;
}
}
.artist-sentence {
opacity: 0.5;
}
}
.progress-wrapper {
margin: 0 auto;
padding-top: 50px;
width: 60vw;
max-width: 60vh;
.progress-wrapper {
margin: 0 auto;
padding-top: 50px;
width: 60vw;
max-width: 60vh;
.slider {
&__track {
background: rgba(128, 128, 128, 0.25);
}
}
}
}
}
.slider {
&__track {
background: rgba(128, 128, 128, 0.25);
}
}
}
}
}
@include responsive($bp_medium){
@include responsive($bp_medium) {
.controls {
top: 0;
right: 0;
.controls {
top: 0;
right: 0;
.control {
padding: 12px;
}
}
.control {
padding: 12px;
}
}
.content {
padding: 40px 5%;
width: 90%;
.content {
padding: 40px 5%;
width: 90%;
form {
padding-top: 20px;
form {
padding-top: 20px;
.field {
padding-bottom: 8px;
.field {
padding-bottom: 8px;
.name {
font-size: inherit;
width: auto;
float: none;
}
}
}
.name {
font-size: inherit;
width: auto;
float: none;
}
}
}
.list {
.list__item {
float: none !important;
width: auto;
margin-left: 0 !important;
border-top: 0;
width: auto !important;
margin: 0;
.list {
.list__item {
float: none !important;
width: auto;
margin-left: 0 !important;
border-top: 0;
width: auto !important;
margin: 0;
&.draggable {
.drag-handle {
padding-top: 14px;
padding-bottom: 14px;
}
}
}
}
}
}
}
&.draggable {
.drag-handle {
padding-top: 14px;
padding-bottom: 14px;
}
}
}
}
}
}
}