Upgrading links sentence; multi-seed radio
This commit is contained in:
@ -3088,21 +3088,21 @@ footer {
|
||||
border-radius: 3px;
|
||||
vertical-align: bottom;
|
||||
margin: 0 8px 1px; }
|
||||
.flag.blue {
|
||||
.flag--blue {
|
||||
background: #32b5f2;
|
||||
color: #FFFFFF; }
|
||||
.flag.info {
|
||||
.flag--info {
|
||||
background: #FFF39C; }
|
||||
.flag.warning {
|
||||
.flag--warning {
|
||||
background: #f16f19;
|
||||
color: #FFFFFF; }
|
||||
.flag.error, .flag.bad {
|
||||
.flag--error, .flag--bad {
|
||||
background: #cf2d2d;
|
||||
color: #FFFFFF; }
|
||||
.flag.dark {
|
||||
.flag--dark {
|
||||
background: #323232;
|
||||
color: #a3a19f; }
|
||||
.flag.large {
|
||||
.flag--large {
|
||||
padding: 8px 10px 7px;
|
||||
font-size: 12px; }
|
||||
h1 .flag,
|
||||
@ -4070,10 +4070,14 @@ select {
|
||||
display: inline-block;
|
||||
margin-left: -8px;
|
||||
padding-right: 6px; }
|
||||
.list__item__column__item--added .from:before {
|
||||
content: '('; }
|
||||
.list__item__column__item--added .from:after {
|
||||
content: ')'; }
|
||||
.list__item__column__item--added .by {
|
||||
opacity: 0.5; }
|
||||
.list__item__column__item--added .by:before {
|
||||
content: '('; }
|
||||
.list__item__column__item--added .by:after {
|
||||
content: ')'; }
|
||||
.list__item__column__item--added .by--with-spacing {
|
||||
padding-left: 0.25em; }
|
||||
.list__item__column__item--context-menu-trigger {
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
@ -4676,13 +4680,13 @@ select {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.playback-controls .current-track .text .artist-sentence {
|
||||
.playback-controls .current-track .text .links-sentence {
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.playback-controls .current-track .text .artist-sentence .artist {
|
||||
.playback-controls .current-track .text .links-sentence__item {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted transparent; }
|
||||
@ -6914,21 +6918,11 @@ main .track-view {
|
||||
margin-right: 2%; }
|
||||
.queue-view .current-track__artwork a {
|
||||
border: 0 !important;
|
||||
display: inline-block;
|
||||
display: block;
|
||||
position: relative; }
|
||||
.queue-view .current-track__artwork .thumbnail {
|
||||
width: 30vh;
|
||||
display: inline-block; }
|
||||
.queue-view .current-track__artwork--radio-enabled .thumbnail {
|
||||
box-sizing: border-box; }
|
||||
.queue-view .current-track__artwork--radio-enabled .radio-overlay {
|
||||
position: absolute;
|
||||
top: -15%;
|
||||
left: -15%;
|
||||
width: 130%;
|
||||
height: 130%;
|
||||
z-index: 2;
|
||||
pointer-events: none; }
|
||||
.queue-view .current-track__details {
|
||||
width: 48%;
|
||||
margin-left: 2%; }
|
||||
@ -7554,7 +7548,7 @@ main .track-view {
|
||||
.modal--kiosk-mode .content .current-track {
|
||||
padding-top: 80px;
|
||||
font-size: 30px; }
|
||||
.modal--kiosk-mode .content .current-track .artist-sentence {
|
||||
.modal--kiosk-mode .content .current-track .links-sentence {
|
||||
opacity: 0.5; }
|
||||
.modal--kiosk-mode .content .progress-wrapper {
|
||||
margin: 0 auto;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -57404,90 +57404,6 @@ exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/js/components/ArtistSentence.js":
|
||||
/*!*********************************************!*\
|
||||
!*** ./src/js/components/ArtistSentence.js ***!
|
||||
\*********************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _URILink = __webpack_require__(/*! ./URILink */ "./src/js/components/URILink.js");
|
||||
|
||||
var _URILink2 = _interopRequireDefault(_URILink);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
exports.default = (0, _react.memo)(function (props) {
|
||||
if (!props.artists) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: props.className ? props.className + ' artist-sentence' : 'artist-sentence' },
|
||||
'-'
|
||||
);
|
||||
}
|
||||
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: props.className ? props.className + ' artist-sentence' : 'artist-sentence' },
|
||||
props.artists.map(function (artist, index) {
|
||||
if (!artist) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
'-'
|
||||
);
|
||||
}
|
||||
|
||||
var separator = null;
|
||||
if (index == props.artists.length - 2) {
|
||||
separator = ' and ';
|
||||
} else if (index < props.artists.length - 2) {
|
||||
separator = ', ';
|
||||
}
|
||||
|
||||
if (!artist.name) {
|
||||
var content = _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
'-'
|
||||
);
|
||||
} else if (!artist.uri || props.nolinks) {
|
||||
var content = _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
artist.name
|
||||
);
|
||||
} else {
|
||||
var content = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ className: 'artist', type: 'artist', uri: artist.uri },
|
||||
artist.name
|
||||
);
|
||||
}
|
||||
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ key: 'index_' + artist.uri },
|
||||
content,
|
||||
separator
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/js/components/CategoryGrid.js":
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/js/components/CategoryGrid.js ***!
|
||||
@ -58892,23 +58808,21 @@ var durationTime = function durationTime() {
|
||||
var durationSentence = function durationSentence() {
|
||||
var milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||||
|
||||
if (!milliseconds) return null;
|
||||
|
||||
var string = '';
|
||||
var total_hours = void 0;var total_minutes = void 0;var total_seconds = void 0;var minutes = void 0;var seconds = void 0;
|
||||
if (milliseconds === null) return null;
|
||||
|
||||
// get total values for each
|
||||
total_seconds = Math.floor(milliseconds / 1000);
|
||||
total_minutes = Math.floor(milliseconds / (1000 * 60));
|
||||
total_hours = Math.floor(milliseconds / (1000 * 60 * 60));
|
||||
var totalSeconds = Math.floor(milliseconds / 1000);
|
||||
var totalMinutes = Math.floor(milliseconds / (1000 * 60));
|
||||
var totalHours = Math.floor(milliseconds / (1000 * 60 * 60));
|
||||
|
||||
if (total_hours > 1) return total_hours + '+ hrs';
|
||||
if (total_minutes > 1) return total_minutes + ' mins';
|
||||
if (total_seconds) return total_seconds + ' sec';
|
||||
if (totalHours > 1) return totalHours + '+ hrs';
|
||||
if (totalMinutes > 1) return totalMinutes + ' mins';
|
||||
if (totalSeconds) return totalSeconds + ' sec';
|
||||
return '0 mins';
|
||||
};
|
||||
|
||||
exports.default = (0, _react.memo)(function (props) {
|
||||
if (!props.data) {
|
||||
if (props.data === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -59582,9 +59496,9 @@ var _Link = __webpack_require__(/*! ../Link */ "./src/js/components/Link.js");
|
||||
|
||||
var _Link2 = _interopRequireDefault(_Link);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _helpers = __webpack_require__(/*! ../../helpers */ "./src/js/helpers.js");
|
||||
|
||||
@ -59713,7 +59627,7 @@ var AddSeedField = function (_React$Component) {
|
||||
'span',
|
||||
{ className: 'mid_grey-text' },
|
||||
' ',
|
||||
_react2.default.createElement(_ArtistSentence2.default, { artists: item.artists, nolinks: true })
|
||||
_react2.default.createElement(_LinksSentence2.default, { items: item.artists, nolinks: true })
|
||||
) : null
|
||||
);
|
||||
})
|
||||
@ -62327,7 +62241,7 @@ var SourcesPriority = function (_React$Component) {
|
||||
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'source flag grey', key: scheme, 'data-id': scheme },
|
||||
{ className: 'source flag flag--grey', key: scheme, 'data-id': scheme },
|
||||
_react2.default.createElement(_Icon2.default, { name: 'drag_indicator' }),
|
||||
name
|
||||
);
|
||||
@ -62753,9 +62667,9 @@ var _Thumbnail = __webpack_require__(/*! ./Thumbnail */ "./src/js/components/Thu
|
||||
|
||||
var _Thumbnail2 = _interopRequireDefault(_Thumbnail);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ./ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ./LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
@ -62849,7 +62763,7 @@ var GridItem = function (_React$Component) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'grid__item__secondary__content' },
|
||||
item.artists !== undefined ? _react2.default.createElement(_ArtistSentence2.default, { nolinks: true, artists: item.artists }) : null
|
||||
item.artists !== undefined ? _react2.default.createElement(_LinksSentence2.default, { nolinks: true, items: item.artists }) : null
|
||||
);
|
||||
break;
|
||||
|
||||
@ -62857,7 +62771,7 @@ var GridItem = function (_React$Component) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'grid__item__secondary__content' },
|
||||
item.artists !== undefined ? _react2.default.createElement(_ArtistSentence2.default, { nolinks: true, artists: item.artists }) : null,
|
||||
item.artists !== undefined ? _react2.default.createElement(_LinksSentence2.default, { nolinks: true, items: item.artists }) : null,
|
||||
item.followers !== undefined ? item.followers.toLocaleString() + ' followers' : null
|
||||
);
|
||||
}
|
||||
@ -63630,6 +63544,90 @@ exports.default = (0, _reactRouter.withRouter)(CustomLink);
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/js/components/LinksSentence.js":
|
||||
/*!********************************************!*\
|
||||
!*** ./src/js/components/LinksSentence.js ***!
|
||||
\********************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _URILink = __webpack_require__(/*! ./URILink */ "./src/js/components/URILink.js");
|
||||
|
||||
var _URILink2 = _interopRequireDefault(_URILink);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
exports.default = (0, _react.memo)(function (props) {
|
||||
if (!props.items) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: props.className ? props.className + ' links-sentence' : 'links-sentence' },
|
||||
'-'
|
||||
);
|
||||
}
|
||||
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ className: props.className ? props.className + ' links-sentence' : 'links-sentence' },
|
||||
props.items.map(function (item, index) {
|
||||
if (!item) {
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
'-'
|
||||
);
|
||||
}
|
||||
|
||||
var separator = null;
|
||||
if (index == props.items.length - 2) {
|
||||
separator = ' and ';
|
||||
} else if (index < props.items.length - 2) {
|
||||
separator = ', ';
|
||||
}
|
||||
|
||||
if (!item.name) {
|
||||
var content = _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
'-'
|
||||
);
|
||||
} else if (!item.uri || props.nolinks) {
|
||||
var content = _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
item.name
|
||||
);
|
||||
} else {
|
||||
var content = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ className: 'links-sentence__item links-sentence__item--link', uri: item.uri },
|
||||
item.name
|
||||
);
|
||||
}
|
||||
|
||||
return _react2.default.createElement(
|
||||
'span',
|
||||
{ key: 'index_' + item.uri },
|
||||
content,
|
||||
separator
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./src/js/components/List.js":
|
||||
/*!***********************************!*\
|
||||
!*** ./src/js/components/List.js ***!
|
||||
@ -63777,9 +63775,9 @@ var _react = __webpack_require__(/*! react */ "./node_modules/react/index.js");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ./ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ./LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Dater = __webpack_require__(/*! ./Dater */ "./src/js/components/Dater.js");
|
||||
|
||||
@ -63933,7 +63931,7 @@ var ListItem = function (_React$Component) {
|
||||
value.id
|
||||
);
|
||||
if (key_string === 'popularity') return _react2.default.createElement(_Popularity2.default, { full: true, popularity: value });
|
||||
if (key_string === 'artists') return _react2.default.createElement(_ArtistSentence2.default, { artists: value });
|
||||
if (key_string === 'artists') return _react2.default.createElement(_LinksSentence2.default, { items: value });
|
||||
if (value === true) return _react2.default.createElement(_Icon2.default, { name: 'check' });
|
||||
if (typeof value === 'number') return _react2.default.createElement(
|
||||
'span',
|
||||
@ -64710,9 +64708,9 @@ var _Dater = __webpack_require__(/*! ./Dater */ "./src/js/components/Dater.js");
|
||||
|
||||
var _Dater2 = _interopRequireDefault(_Dater);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ./ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ./LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Thumbnail = __webpack_require__(/*! ./Thumbnail */ "./src/js/components/Thumbnail.js");
|
||||
|
||||
@ -65083,7 +65081,7 @@ var PlaybackControls = function (_React$Component) {
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
{ className: 'artist' },
|
||||
_react2.default.createElement(_ArtistSentence2.default, { artists: this.state.transition_track.artists, nolinks: true })
|
||||
_react2.default.createElement(_LinksSentence2.default, { items: this.state.transition_track.artists, nolinks: true })
|
||||
)
|
||||
)
|
||||
) : null,
|
||||
@ -65119,7 +65117,7 @@ var PlaybackControls = function (_React$Component) {
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
{ className: 'artist' },
|
||||
current_track ? _react2.default.createElement(_ArtistSentence2.default, { artists: current_track.artists }) : _react2.default.createElement(_ArtistSentence2.default, null)
|
||||
current_track ? _react2.default.createElement(_LinksSentence2.default, { items: current_track.artists }) : _react2.default.createElement(_LinksSentence2.default, null)
|
||||
)
|
||||
)
|
||||
),
|
||||
@ -67363,9 +67361,9 @@ var _Icon = __webpack_require__(/*! ./Icon */ "./src/js/components/Icon.js");
|
||||
|
||||
var _Icon2 = _interopRequireDefault(_Icon);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ./ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ./LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Dater = __webpack_require__(/*! ./Dater */ "./src/js/components/Dater.js");
|
||||
|
||||
@ -67588,7 +67586,7 @@ var Track = function (_React$Component) {
|
||||
track_details.push(_react2.default.createElement(
|
||||
'li',
|
||||
{ className: 'details__item details__item--artists', key: 'artists' },
|
||||
track.artists ? _react2.default.createElement(_ArtistSentence2.default, { artists: track.artists }) : '-'
|
||||
track.artists ? _react2.default.createElement(_LinksSentence2.default, { items: track.artists }) : '-'
|
||||
));
|
||||
}
|
||||
|
||||
@ -67622,8 +67620,7 @@ var Track = function (_React$Component) {
|
||||
'span',
|
||||
null,
|
||||
_react2.default.createElement(_Dater2.default, { type: 'ago', data: track.played_at }),
|
||||
' ',
|
||||
'ago'
|
||||
' ago'
|
||||
) : '-'
|
||||
);
|
||||
} else if (this.props.track_context == 'queue') {
|
||||
@ -67635,7 +67632,7 @@ var Track = function (_React$Component) {
|
||||
var link = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: 'recommendations', uri: helpers.getFromUri('seeds', track.added_from) },
|
||||
'discover'
|
||||
'Discover'
|
||||
);
|
||||
break;
|
||||
|
||||
@ -67643,7 +67640,7 @@ var Track = function (_React$Component) {
|
||||
var link = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: 'browse', uri: track.added_from.replace('iris:browse:', '') },
|
||||
'browse'
|
||||
'Browse'
|
||||
);
|
||||
break;
|
||||
|
||||
@ -67651,7 +67648,7 @@ var Track = function (_React$Component) {
|
||||
var link = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: 'search', uri: track.added_from.replace('iris:', '') },
|
||||
'search'
|
||||
'Search'
|
||||
);
|
||||
break;
|
||||
|
||||
@ -67667,7 +67664,7 @@ var Track = function (_React$Component) {
|
||||
var link = _react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: type, uri: track.added_from },
|
||||
type
|
||||
helpers.titleCase(type)
|
||||
);
|
||||
}
|
||||
|
||||
@ -67676,14 +67673,13 @@ var Track = function (_React$Component) {
|
||||
{ className: 'list__item__column__item list__item__column__item--added' },
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'by' },
|
||||
track.added_by + ' '
|
||||
{ className: 'from' },
|
||||
link
|
||||
),
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'from' },
|
||||
'from ',
|
||||
link
|
||||
{ className: 'by by--with-spacing' },
|
||||
'' + track.added_by
|
||||
)
|
||||
);
|
||||
} else if (track.added_by) {
|
||||
@ -67770,7 +67766,7 @@ var Track = function (_React$Component) {
|
||||
),
|
||||
track.explicit ? _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'flag dark' },
|
||||
{ className: 'flag flag--dark' },
|
||||
'EXPLICIT'
|
||||
) : null,
|
||||
track.playing ? _react2.default.createElement(_Icon2.default, { className: 'js--' + this.props.play_state, name: 'playing', type: 'css' }) : null
|
||||
@ -68401,17 +68397,25 @@ var _Link = __webpack_require__(/*! ./Link */ "./src/js/components/Link.js");
|
||||
|
||||
var _Link2 = _interopRequireDefault(_Link);
|
||||
|
||||
var _helpers = __webpack_require__(/*! ../helpers */ "./src/js/helpers.js");
|
||||
|
||||
var helpers = _interopRequireWildcard(_helpers);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
exports.default = (0, _react.memo)(function (props) {
|
||||
var to = null;
|
||||
var uri = props.uri;
|
||||
var uri = props.uri,
|
||||
type = props.type;
|
||||
|
||||
var uriType = type || helpers.uriType(uri);
|
||||
if (!props.unencoded) {
|
||||
uri = encodeURIComponent(uri);
|
||||
}
|
||||
|
||||
switch (props.type) {
|
||||
switch (uriType) {
|
||||
case 'playlist':
|
||||
to = '/playlist/' + uri;
|
||||
break;
|
||||
@ -82653,9 +82657,9 @@ var _Parallax = __webpack_require__(/*! ../components/Parallax */ "./src/js/comp
|
||||
|
||||
var _Parallax2 = _interopRequireDefault(_Parallax);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../components/ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../components/LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Loader = __webpack_require__(/*! ../components/Loader */ "./src/js/components/Loader.js");
|
||||
|
||||
@ -82888,7 +82892,7 @@ var Album = exports.Album = function (_React$Component) {
|
||||
album.artists && album.artists.length > 0 ? _react2.default.createElement(
|
||||
'li',
|
||||
null,
|
||||
_react2.default.createElement(_ArtistSentence2.default, { artists: album.artists })
|
||||
_react2.default.createElement(_LinksSentence2.default, { items: album.artists })
|
||||
) : null,
|
||||
album.release_date ? _react2.default.createElement(
|
||||
'li',
|
||||
@ -84854,9 +84858,9 @@ var _Dater = __webpack_require__(/*! ../components/Dater */ "./src/js/components
|
||||
|
||||
var _Dater2 = _interopRequireDefault(_Dater);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../components/ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../components/LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Thumbnail = __webpack_require__(/*! ../components/Thumbnail */ "./src/js/components/Thumbnail.js");
|
||||
|
||||
@ -85023,28 +85027,6 @@ var Queue = function (_React$Component) {
|
||||
value: function reorderTracks(indexes, index) {
|
||||
this.props.mopidyActions.reorderTracklist(indexes, index);
|
||||
}
|
||||
}, {
|
||||
key: 'renderQueueStats',
|
||||
value: function renderQueueStats() {
|
||||
var current_tracklist = this.props.current_tracklist;
|
||||
|
||||
|
||||
return _react2.default.createElement(
|
||||
'div',
|
||||
{ className: 'queue-stats mid_grey-text' },
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
(current_tracklist.length || 0) + ' tracks'
|
||||
),
|
||||
'\xA0\xA0|\xA0\xA0',
|
||||
current_tracklist.length > 0 ? _react2.default.createElement(_Dater2.default, { type: 'total-time', data: current_tracklist }) : _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
'0 mins'
|
||||
)
|
||||
);
|
||||
}
|
||||
}, {
|
||||
key: 'renderArtwork',
|
||||
value: function renderArtwork(image) {
|
||||
@ -85068,7 +85050,7 @@ var Queue = function (_React$Component) {
|
||||
{ className: 'current-track__artwork' },
|
||||
_react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: 'album', uri: uri },
|
||||
{ uri: uri },
|
||||
_react2.default.createElement(_Thumbnail2.default, { glow: true, image: image })
|
||||
)
|
||||
);
|
||||
@ -85081,24 +85063,48 @@ var Queue = function (_React$Component) {
|
||||
if (!added_from_uri) return null;
|
||||
|
||||
var uri_type = helpers.uriType(added_from_uri);
|
||||
var item_uri = added_from_uri;
|
||||
var item_type = uri_type;
|
||||
var items = [];
|
||||
|
||||
// Radio nests it's seed URIs in an encoded URI format
|
||||
if (uri_type === 'radio') {
|
||||
var radio_seeds = helpers.getFromUri('seeds', added_from_uri);
|
||||
|
||||
// For now we only care about the first seed
|
||||
// TODO: Support for multiple seeds
|
||||
item_uri = radio_seeds[0];
|
||||
item_type = helpers.uriType(item_uri);
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = radio_seeds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var seed = _step.value;
|
||||
|
||||
var item_type = helpers.uriType(seed);
|
||||
var item_library = this.props[item_type + 's'];
|
||||
if (item_library && item_library[seed]) {
|
||||
items.push(item_library[seed]);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var _item_library = this.props[uri_type + 's'];
|
||||
if (_item_library && _item_library[added_from_uri]) {
|
||||
items.push(_item_library[added_from_uri]);
|
||||
}
|
||||
}
|
||||
|
||||
var item_library = this.props[item_type + 's'];
|
||||
if (!item_library) return null;
|
||||
|
||||
var item = item_library[item_uri];
|
||||
if (!item) return null;
|
||||
if (items.length <= 0) return null;
|
||||
|
||||
return _react2.default.createElement(
|
||||
'div',
|
||||
@ -85106,29 +85112,24 @@ var Queue = function (_React$Component) {
|
||||
_react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{
|
||||
type: item_type,
|
||||
uri: item.uri,
|
||||
uri: items[0].uri,
|
||||
className: 'current-track__added-from__thumbnail'
|
||||
},
|
||||
_react2.default.createElement(_Thumbnail2.default, {
|
||||
images: item.images,
|
||||
images: items[0].images,
|
||||
size: 'small',
|
||||
circle: item_type === 'artist'
|
||||
circle: helpers.uriType(items[0].uri) === 'artist'
|
||||
})
|
||||
),
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
{ className: 'current-track__added-from__text' },
|
||||
'Playing from ',
|
||||
_react2.default.createElement(
|
||||
_URILink2.default,
|
||||
{ type: item_type, uri: item.uri },
|
||||
item.name
|
||||
),
|
||||
_react2.default.createElement(_LinksSentence2.default, { items: items }),
|
||||
uri_type === 'radio' && _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
' radio'
|
||||
{ className: 'flag flag--blue' },
|
||||
'Radio'
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -85156,17 +85157,12 @@ var Queue = function (_React$Component) {
|
||||
var options = _react2.default.createElement(
|
||||
'span',
|
||||
null,
|
||||
this.props.spotify_enabled ? _react2.default.createElement(
|
||||
this.props.spotify_enabled && _react2.default.createElement(
|
||||
_Link2.default,
|
||||
{ className: 'button button--no-hover', to: '/queue/radio' },
|
||||
_react2.default.createElement(_Icon2.default, { name: 'radio' }),
|
||||
'Radio',
|
||||
this.props.radio && this.props.radio.enabled ? _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'flag blue' },
|
||||
'On'
|
||||
) : null
|
||||
) : null,
|
||||
'Radio'
|
||||
),
|
||||
_react2.default.createElement(
|
||||
_Link2.default,
|
||||
{ className: 'button button--no-hover', to: '/queue/history' },
|
||||
@ -85214,10 +85210,10 @@ var Queue = function (_React$Component) {
|
||||
'-'
|
||||
)
|
||||
),
|
||||
current_track ? _react2.default.createElement(_ArtistSentence2.default, {
|
||||
current_track ? _react2.default.createElement(_LinksSentence2.default, {
|
||||
className: 'current-track__artists',
|
||||
artists: current_track.artists
|
||||
}) : _react2.default.createElement(_ArtistSentence2.default, { className: 'current-track__artists' }),
|
||||
items: current_track.artists
|
||||
}) : _react2.default.createElement(_LinksSentence2.default, { className: 'current-track__artists' }),
|
||||
this.renderAddedFrom(),
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
@ -85235,17 +85231,14 @@ var Queue = function (_React$Component) {
|
||||
null,
|
||||
_react2.default.createElement(_Dater2.default, { type: 'total-time', data: queue_tracks })
|
||||
),
|
||||
_react2.default.createElement(
|
||||
queue_tracks.length > 0 && _react2.default.createElement(
|
||||
'li',
|
||||
null,
|
||||
_react2.default.createElement(
|
||||
'a',
|
||||
{
|
||||
onClick: function onClick(e) {
|
||||
_this2.props.mopidyActions.clearTracklist();
|
||||
_this2.props.uiActions.hideContextMenu();
|
||||
}
|
||||
},
|
||||
{ onClick: function onClick(e) {
|
||||
return _this2.props.mopidyActions.clearTracklist();
|
||||
} },
|
||||
_react2.default.createElement(_Icon2.default, { name: 'delete_sweep' }),
|
||||
'Clear queue'
|
||||
)
|
||||
@ -85297,13 +85290,13 @@ var mapStateToProps = function mapStateToProps(state, ownProps) {
|
||||
var queue_tracks = [];
|
||||
|
||||
if (state.core.queue && state.core.tracks) {
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
var _iteratorNormalCompletion2 = true;
|
||||
var _didIteratorError2 = false;
|
||||
var _iteratorError2 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = state.core.queue[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var queue_track = _step.value;
|
||||
for (var _iterator2 = state.core.queue[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||
var queue_track = _step2.value;
|
||||
|
||||
var track = _extends({}, queue_track);
|
||||
|
||||
@ -85328,16 +85321,16 @@ var mapStateToProps = function mapStateToProps(state, ownProps) {
|
||||
queue_tracks.push(track);
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
_didIteratorError2 = true;
|
||||
_iteratorError2 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||
_iterator2.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
if (_didIteratorError2) {
|
||||
throw _iteratorError2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86985,12 +86978,12 @@ var Settings = function (_React$Component) {
|
||||
'installed',
|
||||
this.props.pusher.version.upgrade_available ? _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'flag dark' },
|
||||
{ className: 'flag flag--dark' },
|
||||
_react2.default.createElement(_Icon2.default, { name: 'cloud_download', className: 'blue-text' }),
|
||||
'\xA0 Upgrade available'
|
||||
) : _react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'flag dark' },
|
||||
{ className: 'flag flag--dark' },
|
||||
_react2.default.createElement(_Icon2.default, { name: 'check', className: 'green-text' }),
|
||||
'\xA0 Up-to-date'
|
||||
)
|
||||
@ -87177,9 +87170,9 @@ var _Thumbnail = __webpack_require__(/*! ../components/Thumbnail */ "./src/js/co
|
||||
|
||||
var _Thumbnail2 = _interopRequireDefault(_Thumbnail);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../components/ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../components/LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _ArtistGrid = __webpack_require__(/*! ../components/ArtistGrid */ "./src/js/components/ArtistGrid.js");
|
||||
|
||||
@ -87511,7 +87504,7 @@ var Track = function (_React$Component) {
|
||||
track.album && !track.album.uri ? track.album.name : null,
|
||||
!track.album ? 'Unknown album' : null,
|
||||
' by ',
|
||||
_react2.default.createElement(_ArtistSentence2.default, { artists: track.artists })
|
||||
_react2.default.createElement(_LinksSentence2.default, { items: track.artists })
|
||||
),
|
||||
_react2.default.createElement(
|
||||
'ul',
|
||||
@ -87531,7 +87524,7 @@ var Track = function (_React$Component) {
|
||||
null,
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
{ className: 'flag dark' },
|
||||
{ className: 'flag flag--dark' },
|
||||
'EXPLICIT'
|
||||
)
|
||||
) : null,
|
||||
@ -88815,9 +88808,9 @@ var _Header = __webpack_require__(/*! ../../components/Header */ "./src/js/compo
|
||||
|
||||
var _Header2 = _interopRequireDefault(_Header);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../../components/ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../../components/LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _ArtistGrid = __webpack_require__(/*! ../../components/ArtistGrid */ "./src/js/components/ArtistGrid.js");
|
||||
|
||||
@ -93447,7 +93440,7 @@ var EditRadio = function (_React$Component) {
|
||||
|
||||
if (valid_seeds) {
|
||||
this.props.pusherActions.updateRadio(this.state.seeds);
|
||||
this.props.uiActions.closeModal();
|
||||
window.history.back();
|
||||
} else {
|
||||
this.setState({ error_message: 'Invalid seed URI(s)' });
|
||||
}
|
||||
@ -94128,9 +94121,9 @@ var _Thumbnail = __webpack_require__(/*! ../../components/Thumbnail */ "./src/js
|
||||
|
||||
var _Thumbnail2 = _interopRequireDefault(_Thumbnail);
|
||||
|
||||
var _ArtistSentence = __webpack_require__(/*! ../../components/ArtistSentence */ "./src/js/components/ArtistSentence.js");
|
||||
var _LinksSentence = __webpack_require__(/*! ../../components/LinksSentence */ "./src/js/components/LinksSentence.js");
|
||||
|
||||
var _ArtistSentence2 = _interopRequireDefault(_ArtistSentence);
|
||||
var _LinksSentence2 = _interopRequireDefault(_LinksSentence);
|
||||
|
||||
var _Dater = __webpack_require__(/*! ../../components/Dater */ "./src/js/components/Dater.js");
|
||||
|
||||
@ -94252,7 +94245,7 @@ var KioskMode = function (_React$Component) {
|
||||
'-'
|
||||
)
|
||||
),
|
||||
this.props.current_track ? _react2.default.createElement(_ArtistSentence2.default, { nolinks: true, artists: this.props.current_track.artists }) : _react2.default.createElement(_ArtistSentence2.default, null)
|
||||
this.props.current_track ? _react2.default.createElement(_LinksSentence2.default, { nolinks: true, items: this.props.current_track.artists }) : _react2.default.createElement(_LinksSentence2.default, null)
|
||||
),
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -100,7 +100,7 @@
|
||||
|
||||
// Release details
|
||||
// These are automatically injected to built HTML
|
||||
var build = "1570045026";
|
||||
var build = "1570135951";
|
||||
var version = "3.40.0";
|
||||
|
||||
// Construct the script tag
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import URILink from './URILink';
|
||||
|
||||
export default memo((props) => {
|
||||
if (!props.artists) {
|
||||
return <span className={props.className ? `${props.className} artist-sentence` : 'artist-sentence'}>-</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={props.className ? `${props.className} artist-sentence` : 'artist-sentence'}>
|
||||
{
|
||||
props.artists.map((artist, index) => {
|
||||
if (!artist) {
|
||||
return <span>-</span>;
|
||||
}
|
||||
|
||||
let separator = null;
|
||||
if (index == props.artists.length - 2) {
|
||||
separator = ' and ';
|
||||
} else if (index < props.artists.length - 2) {
|
||||
separator = ', ';
|
||||
}
|
||||
|
||||
if (!artist.name) {
|
||||
var content = <span>-</span>;
|
||||
} else if (!artist.uri || props.nolinks) {
|
||||
var content = <span>{ artist.name }</span>;
|
||||
} else {
|
||||
var content = <URILink className="artist" type="artist" uri={artist.uri}>{ artist.name }</URILink>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span key={`index_${artist.uri}`}>
|
||||
{ content }
|
||||
{ separator }
|
||||
</span>
|
||||
);
|
||||
})
|
||||
}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
@ -43,24 +43,21 @@ const durationTime = (milliseconds = null) => {
|
||||
* @return string (eg 2+ hours)
|
||||
* */
|
||||
const durationSentence = (milliseconds = null) => {
|
||||
if (!milliseconds) return null;
|
||||
|
||||
const string = '';
|
||||
let total_hours; let total_minutes; let total_seconds; let minutes; let
|
||||
seconds;
|
||||
if (milliseconds === null) return null;
|
||||
|
||||
// get total values for each
|
||||
total_seconds = Math.floor(milliseconds / 1000);
|
||||
total_minutes = Math.floor(milliseconds / (1000 * 60));
|
||||
total_hours = Math.floor(milliseconds / (1000 * 60 * 60));
|
||||
const totalSeconds = Math.floor(milliseconds / 1000);
|
||||
const totalMinutes = Math.floor(milliseconds / (1000 * 60));
|
||||
const totalHours = Math.floor(milliseconds / (1000 * 60 * 60));
|
||||
|
||||
if (total_hours > 1) return `${total_hours}+ hrs`;
|
||||
if (total_minutes > 1) return `${total_minutes} mins`;
|
||||
if (total_seconds) return `${total_seconds} sec`;
|
||||
if (totalHours > 1) return `${totalHours}+ hrs`;
|
||||
if (totalMinutes > 1) return `${totalMinutes} mins`;
|
||||
if (totalSeconds) return `${totalSeconds} sec`;
|
||||
return '0 mins';
|
||||
};
|
||||
|
||||
export default memo((props) => {
|
||||
if (!props.data) {
|
||||
if (props.data === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -5,13 +5,13 @@ import { bindActionCreators } from 'redux';
|
||||
|
||||
|
||||
import Link from '../Link';
|
||||
import ArtistSentence from '../ArtistSentence';
|
||||
import LinksSentence from '../LinksSentence';
|
||||
import * as helpers from '../../helpers';
|
||||
import * as coreActions from '../../services/core/actions';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
|
||||
class AddSeedField extends React.Component {
|
||||
class AddSeedField extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -71,7 +71,7 @@ class AddSeedField extends React.Component {
|
||||
} if (this.props.results[this.id] === undefined) {
|
||||
return null;
|
||||
}
|
||||
return this.props.results[this.id];
|
||||
return this.props.results[this.id];
|
||||
}
|
||||
|
||||
renderResults(type) {
|
||||
@ -88,11 +88,11 @@ class AddSeedField extends React.Component {
|
||||
items.map((item) => (
|
||||
<div className="result" key={item.uri} onClick={(e) => this.handleSelect(e, item)}>
|
||||
{item.name}
|
||||
{type == 'tracks' ? (
|
||||
<span className="mid_grey-text">
|
||||
{' '}
|
||||
<ArtistSentence artists={item.artists} nolinks />
|
||||
</span>
|
||||
{type == 'tracks' ? (
|
||||
<span className="mid_grey-text">
|
||||
{' '}
|
||||
<LinksSentence items={item.artists} nolinks />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
))
|
||||
@ -113,7 +113,7 @@ class AddSeedField extends React.Component {
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={(e) => this.handleChange(e, e.target.value)}
|
||||
placeholder={this.props.placeholder ? this.props.placeholder : 'Start typing...'}
|
||||
placeholder={this.props.placeholder ? this.props.placeholder : 'Start typing...'}
|
||||
/>
|
||||
</div>
|
||||
<div className="results">
|
||||
@ -137,4 +137,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddSeedField);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddSeedField);
|
||||
|
||||
@ -5,13 +5,13 @@ import { bindActionCreators } from 'redux';
|
||||
|
||||
import Link from './Link';
|
||||
|
||||
import ArtistSentence from '../ArtistSentence';
|
||||
import LinksSentence from '../LinksSentence';
|
||||
import * as helpers from '../../helpers';
|
||||
import * as coreActions from '../../services/core/actions';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
|
||||
class AddSeedField extends React.Component {
|
||||
class AddSeedField extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -65,7 +65,7 @@ class AddSeedField extends React.Component {
|
||||
this.props.spotifyActions.clearAutocompleteResults(this.id);
|
||||
|
||||
// Add our selected item to our global index
|
||||
switch (helpers.uriType(item.uri)) {
|
||||
switch (helpers.uriType(item.uri)) {
|
||||
case 'artist':
|
||||
this.props.coreActions.artistsLoaded(item);
|
||||
break;
|
||||
@ -82,7 +82,7 @@ class AddSeedField extends React.Component {
|
||||
} if (typeof (this.props.results[this.id]) === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return this.props.results[this.id];
|
||||
return this.props.results[this.id];
|
||||
}
|
||||
|
||||
renderResults(type) {
|
||||
@ -99,11 +99,11 @@ class AddSeedField extends React.Component {
|
||||
items.map((item) => (
|
||||
<div className="result" key={item.uri} onClick={(e) => this.handleSelect(e, item)}>
|
||||
{item.name}
|
||||
{type == 'tracks' ? (
|
||||
<span className="mid_grey-text">
|
||||
{' '}
|
||||
<ArtistSentence artists={item.artists} nolinks />
|
||||
</span>
|
||||
{type == 'tracks' ? (
|
||||
<span className="mid_grey-text">
|
||||
{' '}
|
||||
<LinksSentence items={item.artists} nolinks />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
))
|
||||
@ -124,7 +124,7 @@ class AddSeedField extends React.Component {
|
||||
type="text"
|
||||
value={this.state.value}
|
||||
onChange={(e) => this.handleChange(e, e.target.value)}
|
||||
placeholder={this.props.placeholder ? this.props.placeholder : 'Start typing...'}
|
||||
placeholder={this.props.placeholder ? this.props.placeholder : 'Start typing...'}
|
||||
/>
|
||||
</div>
|
||||
<div className="results">
|
||||
@ -148,4 +148,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddSeedField);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AddSeedField);
|
||||
|
||||
@ -4,7 +4,7 @@ import Sortable from 'react-sortablejs';
|
||||
import Icon from '../Icon';
|
||||
import * as helpers from '../../helpers';
|
||||
|
||||
export default class SourcesPriority extends React.Component {
|
||||
export default class SourcesPriority extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
@ -40,14 +40,14 @@ export default class SourcesPriority extends React.Component {
|
||||
className={className}
|
||||
onChange={(order, sortable, e) => {
|
||||
this.handleSort(order);
|
||||
}}
|
||||
}}
|
||||
>
|
||||
{
|
||||
ordered_schemes.map((scheme) => {
|
||||
const name = helpers.titleCase(scheme.replace(':', '').replace('+', ' '));
|
||||
|
||||
return (
|
||||
<span className="source flag grey" key={scheme} data-id={scheme}>
|
||||
<span className="source flag flag--grey" key={scheme} data-id={scheme}>
|
||||
<Icon name="drag_indicator" />
|
||||
{name}
|
||||
</span>
|
||||
@ -57,4 +57,4 @@ export default class SourcesPriority extends React.Component {
|
||||
</Sortable>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import * as helpers from '../helpers';
|
||||
import Link from './Link';
|
||||
import Icon from './Icon';
|
||||
import Thumbnail from './Thumbnail';
|
||||
import ArtistSentence from './ArtistSentence';
|
||||
import LinksSentence from './LinksSentence';
|
||||
|
||||
export default class GridItem extends React.Component {
|
||||
componentDidMount() {
|
||||
@ -75,7 +75,7 @@ tracks
|
||||
case 'album':
|
||||
return (
|
||||
<span className="grid__item__secondary__content">
|
||||
{item.artists !== undefined ? <ArtistSentence nolinks artists={item.artists} /> : null}
|
||||
{item.artists !== undefined ? <LinksSentence nolinks items={item.artists} /> : null}
|
||||
</span>
|
||||
);
|
||||
break;
|
||||
@ -83,7 +83,7 @@ tracks
|
||||
default:
|
||||
return (
|
||||
<span className="grid__item__secondary__content">
|
||||
{ item.artists !== undefined ? <ArtistSentence nolinks artists={item.artists} /> : null }
|
||||
{ item.artists !== undefined ? <LinksSentence nolinks items={item.artists} /> : null }
|
||||
{ item.followers !== undefined ? `${item.followers.toLocaleString()} followers` : null }
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -5,12 +5,12 @@ import { createStore, bindActionCreators } from 'redux';
|
||||
|
||||
import Link from './Link';
|
||||
|
||||
import ArtistSentence from './ArtistSentence';
|
||||
import LinksSentence from './LinksSentence';
|
||||
import Thumbnail from './Thumbnail';
|
||||
|
||||
import * as uiActions from '../services/ui/actions';
|
||||
|
||||
class GridSlider extends React.Component {
|
||||
class GridSlider extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -47,7 +47,7 @@ class GridSlider extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.tracks) {
|
||||
if (this.props.tracks) {
|
||||
let className = 'grid-slider-wrapper';
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
|
||||
@ -69,16 +69,16 @@ class GridSlider extends React.Component {
|
||||
(track, index) => {
|
||||
const album = { ...track.album, artists: track.artists };
|
||||
return (
|
||||
<div
|
||||
<div
|
||||
className="grid-item"
|
||||
key={index}
|
||||
onClick={(e) => this.handleClick(e, `/album/${album.uri}`)}
|
||||
onContextMenu={(e) => this.handleContextMenu(e, album)}
|
||||
onContextMenu={(e) => this.handleContextMenu(e, album)}
|
||||
>
|
||||
<Thumbnail size="medium" images={album.images} />
|
||||
<div className="name">{ album.name }</div>
|
||||
<div className="secondary">
|
||||
{ album.artists ? <ArtistSentence artists={album.artists} /> : <span>-</span> }
|
||||
{ album.artists ? <LinksSentence items={album.artists} /> : <span>-</span> }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
43
src/js/components/LinksSentence.js
Executable file
43
src/js/components/LinksSentence.js
Executable file
@ -0,0 +1,43 @@
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import URILink from './URILink';
|
||||
|
||||
export default memo((props) => {
|
||||
if (!props.items) {
|
||||
return <span className={props.className ? `${props.className} links-sentence` : 'links-sentence'}>-</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={props.className ? `${props.className} links-sentence` : 'links-sentence'}>
|
||||
{
|
||||
props.items.map((item, index) => {
|
||||
if (!item) {
|
||||
return <span>-</span>;
|
||||
}
|
||||
|
||||
let separator = null;
|
||||
if (index == props.items.length - 2) {
|
||||
separator = ' and ';
|
||||
} else if (index < props.items.length - 2) {
|
||||
separator = ', ';
|
||||
}
|
||||
|
||||
if (!item.name) {
|
||||
var content = <span>-</span>;
|
||||
} else if (!item.uri || props.nolinks) {
|
||||
var content = <span>{ item.name }</span>;
|
||||
} else {
|
||||
var content = <URILink className="links-sentence__item links-sentence__item--link" uri={item.uri}>{ item.name }</URILink>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span key={`index_${item.uri}`}>
|
||||
{ content }
|
||||
{ separator }
|
||||
</span>
|
||||
);
|
||||
})
|
||||
}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ArtistSentence from './ArtistSentence';
|
||||
import LinksSentence from './LinksSentence';
|
||||
import Dater from './Dater';
|
||||
import URILink from './URILink';
|
||||
import ContextMenuTrigger from './ContextMenuTrigger';
|
||||
@ -11,7 +11,7 @@ import Popularity from './Popularity';
|
||||
|
||||
import * as helpers from '../helpers';
|
||||
|
||||
export default class ListItem extends React.Component {
|
||||
export default class ListItem extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
@ -23,7 +23,7 @@ export default class ListItem extends React.Component {
|
||||
// If the item that has just been mounted doesn't have images,
|
||||
// try fetching them from LastFM
|
||||
if (!item.images) {
|
||||
switch (helpers.uriType(item.uri)) {
|
||||
switch (helpers.uriType(item.uri)) {
|
||||
case 'artist':
|
||||
if (discogsActions) {
|
||||
discogsActions.getArtistImages(item.uri, item);
|
||||
@ -39,7 +39,7 @@ export default class ListItem extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
handleClick(e) {
|
||||
// make sure we haven't clicked a nested link (ie Artist name)
|
||||
if (e.target.tagName.toLowerCase() !== 'a') {
|
||||
e.preventDefault();
|
||||
@ -48,7 +48,7 @@ export default class ListItem extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseDown(e) {
|
||||
handleMouseDown(e) {
|
||||
// make sure we haven't clicked a nested link (ie Artist name)
|
||||
if (e.target.tagName.toLowerCase() !== 'a') {
|
||||
e.preventDefault();
|
||||
@ -74,40 +74,40 @@ export default class ListItem extends React.Component {
|
||||
} if (typeof (value[key[i]]) === 'string' && value[key[i]].replace(' ', '') == '') {
|
||||
return null;
|
||||
}
|
||||
value = value[key[i]];
|
||||
value = value[key[i]];
|
||||
}
|
||||
|
||||
if (key_string === 'tracks_total' || key_string === 'tracks_uris.length') {
|
||||
return (
|
||||
<span>
|
||||
{value}
|
||||
{' '}
|
||||
tracks
|
||||
</span>
|
||||
);
|
||||
if (key_string === 'tracks_total' || key_string === 'tracks_uris.length') {
|
||||
return (
|
||||
<span>
|
||||
{value}
|
||||
{' '}
|
||||
tracks
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (key_string === 'followers') {
|
||||
return (
|
||||
<span>
|
||||
{value.toLocaleString()}
|
||||
{' '}
|
||||
followers
|
||||
</span>
|
||||
);
|
||||
if (key_string === 'followers') {
|
||||
return (
|
||||
<span>
|
||||
{value.toLocaleString()}
|
||||
{' '}
|
||||
followers
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (key_string === 'added_at') {
|
||||
return (
|
||||
<span>
|
||||
Added
|
||||
<Dater type="ago" data={value} />
|
||||
{' '}
|
||||
ago
|
||||
</span>
|
||||
);
|
||||
if (key_string === 'added_at') {
|
||||
return (
|
||||
<span>
|
||||
Added
|
||||
<Dater type="ago" data={value} />
|
||||
{' '}
|
||||
ago
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (key_string === 'owner') return <URILink type="user" uri={value.uri}>{value.id}</URILink>;
|
||||
if (key_string === 'popularity') return <Popularity full popularity={value} />;
|
||||
if (key_string === 'artists') return <ArtistSentence artists={value} />;
|
||||
if (key_string === 'artists') return <LinksSentence items={value} />;
|
||||
if (value === true) return <Icon name="check" />;
|
||||
if (typeof (value) === 'number') return <span>{value.toLocaleString()}</span>;
|
||||
return <span>{value}</span>;
|
||||
@ -140,11 +140,11 @@ ago
|
||||
<div
|
||||
className={class_name}
|
||||
onClick={(e) => this.handleClick(e)}
|
||||
onContextMenu={(e) => this.handleContextMenu(e)}
|
||||
onContextMenu={(e) => this.handleContextMenu(e)}
|
||||
>
|
||||
|
||||
{this.props.right_column && !this.props.nocontext
|
||||
&& (
|
||||
&& (
|
||||
<div className="list__item__column list__item__column--right">
|
||||
{
|
||||
(this.props.right_column ? this.props.right_column.map((column, index) => (
|
||||
@ -156,7 +156,7 @@ ago
|
||||
|
||||
{this.props.nocontext ? null : <ContextMenuTrigger className="list__item__column__item list__item__column__item--context-menu-trigger subtle" onTrigger={(e) => this.handleContextMenu(e)} />}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="list__item__column list__item__column--name">
|
||||
@ -167,7 +167,7 @@ ago
|
||||
{item.name !== undefined ? this.renderValue('name') : <span className="grey-text">{item.uri}</span>}
|
||||
</div>
|
||||
|
||||
{this.props.details ? (
|
||||
{this.props.details ? (
|
||||
<ul className="list__item__column__item list__item__column__item--details details">
|
||||
{
|
||||
this.props.details.map((detail, index) => {
|
||||
@ -184,11 +184,11 @@ ago
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</ul>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{this.props.middle_column ? (
|
||||
{this.props.middle_column ? (
|
||||
<div className="list__item__column list__item__column--middle">
|
||||
{
|
||||
(this.props.middle_column ? this.props.middle_column.map((column, index) => (
|
||||
@ -197,7 +197,7 @@ ago
|
||||
</span>
|
||||
)) : null)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -9,7 +9,7 @@ import VolumeControl from './Fields/VolumeControl';
|
||||
import MuteControl from './Fields/MuteControl';
|
||||
import OutputControl from './Fields/OutputControl';
|
||||
import Dater from './Dater';
|
||||
import ArtistSentence from './ArtistSentence';
|
||||
import LinksSentence from './LinksSentence';
|
||||
import Thumbnail from './Thumbnail';
|
||||
import Icon from './Icon';
|
||||
|
||||
@ -18,7 +18,7 @@ import * as uiActions from '../services/ui/actions';
|
||||
import * as coreActions from '../services/core/actions';
|
||||
import * as mopidyActions from '../services/mopidy/actions';
|
||||
|
||||
class PlaybackControls extends React.Component {
|
||||
class PlaybackControls extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.stream = null;
|
||||
@ -31,7 +31,7 @@ class PlaybackControls extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.http_streaming_enabled) {
|
||||
if (this.props.http_streaming_enabled) {
|
||||
// Bust our cache, and by consequence, play our stream
|
||||
this.props.coreActions.cachebustHttpStream();
|
||||
}
|
||||
@ -41,7 +41,7 @@ class PlaybackControls extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
playStream(props = this.props) {
|
||||
playStream(props = this.props) {
|
||||
if (!this.stream) {
|
||||
this.stream = new Audio();
|
||||
} else {
|
||||
@ -60,7 +60,7 @@ class PlaybackControls extends React.Component {
|
||||
console.log(`Playing stream: ${this.stream.src}`);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Cachebuster changed
|
||||
// This happens when playback changes, so that the stream is "new", rather
|
||||
// than the original stream. This prevents the browser cache from starting
|
||||
@ -74,7 +74,7 @@ class PlaybackControls extends React.Component {
|
||||
this.playStream(nextProps);
|
||||
}
|
||||
|
||||
if (this.stream) {
|
||||
if (this.stream) {
|
||||
// Just been muted
|
||||
if (this.props.http_streaming_mute !== nextProps.http_streaming_mute) {
|
||||
this.stream.muted = nextProps.http_streaming_mute;
|
||||
@ -104,7 +104,7 @@ class PlaybackControls extends React.Component {
|
||||
|
||||
// Images have just loaded
|
||||
// A bit niggly to have to deeply check this...
|
||||
if (this.props.current_track && nextProps.current_track) {
|
||||
if (this.props.current_track && nextProps.current_track) {
|
||||
if ((this.props.current_track.images && !nextProps.current_track.images) || (!this.props.current_track.images && nextProps.current_track.images)) {
|
||||
this.setState({ current_track: nextProps.current_track });
|
||||
}
|
||||
@ -139,11 +139,11 @@ class PlaybackControls extends React.Component {
|
||||
// Make sure there's enough distance between start and end before we handle
|
||||
// this event as a 'tap'
|
||||
if (this.start_position.x + tap_distance_threshold > end_position.x
|
||||
&& this.start_position.x - tap_distance_threshold < end_position.x) {
|
||||
&& this.start_position.x - tap_distance_threshold < end_position.x) {
|
||||
// Scroll to top (without smooth_scroll)
|
||||
helpers.scrollTo(null, false);
|
||||
this.props.history.push('/queue');
|
||||
} else {
|
||||
} else {
|
||||
// Swipe to the left = previous track
|
||||
if (this.start_position.x < end_position.x) {
|
||||
this.setTransition('previous');
|
||||
@ -187,54 +187,54 @@ class PlaybackControls extends React.Component {
|
||||
}
|
||||
|
||||
renderConsumeButton() {
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setConsume(true)}>
|
||||
<Icon name="restaurant" type="material" />
|
||||
<span className="tooltip__content">Consume</span>
|
||||
</button>
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setConsume(true)}>
|
||||
<Icon name="restaurant" type="material" />
|
||||
<span className="tooltip__content">Consume</span>
|
||||
</button>
|
||||
);
|
||||
if (this.props.consume) {
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setConsume(false)}>
|
||||
<Icon name="restaurant" type="material" />
|
||||
<span className="tooltip__content">Consume</span>
|
||||
</button>
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setConsume(false)}>
|
||||
<Icon name="restaurant" type="material" />
|
||||
<span className="tooltip__content">Consume</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
renderRandomButton() {
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setRandom(true)}>
|
||||
<Icon name="shuffle" type="material" />
|
||||
<span className="tooltip__content">Shuffle</span>
|
||||
</button>
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setRandom(true)}>
|
||||
<Icon name="shuffle" type="material" />
|
||||
<span className="tooltip__content">Shuffle</span>
|
||||
</button>
|
||||
);
|
||||
if (this.props.random) {
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setRandom(false)}>
|
||||
<Icon name="shuffle" type="material" />
|
||||
<span className="tooltip__content">Shuffle</span>
|
||||
</button>
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setRandom(false)}>
|
||||
<Icon name="shuffle" type="material" />
|
||||
<span className="tooltip__content">Shuffle</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
renderRepeatButton() {
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setRepeat(true)}>
|
||||
<Icon name="repeat" />
|
||||
<span className="tooltip__content">Repeat</span>
|
||||
</button>
|
||||
let button = (
|
||||
<button className="control tooltip" onClick={() => this.props.mopidyActions.setRepeat(true)}>
|
||||
<Icon name="repeat" />
|
||||
<span className="tooltip__content">Repeat</span>
|
||||
</button>
|
||||
);
|
||||
if (this.props.repeat) {
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setRepeat(false)}>
|
||||
<Icon name="repeat" />
|
||||
<span className="tooltip__content">Repeat</span>
|
||||
</button>
|
||||
button = (
|
||||
<button className="control control--active tooltip" onClick={() => this.props.mopidyActions.setRepeat(false)}>
|
||||
<Icon name="repeat" />
|
||||
<span className="tooltip__content">Repeat</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
return button;
|
||||
@ -254,26 +254,26 @@ class PlaybackControls extends React.Component {
|
||||
|
||||
{next_track && next_track.images ? <Thumbnail className="hide" size="large" images={next_track.images} /> : null}
|
||||
|
||||
{this.state.transition_track && this.state.transition_direction ? (
|
||||
{this.state.transition_track && this.state.transition_direction ? (
|
||||
<div
|
||||
className={`current-track current-track__transition current-track__transition--${this.state.transition_direction}`}
|
||||
className={`current-track current-track__transition current-track__transition--${this.state.transition_direction}`}
|
||||
>
|
||||
<div className="text">
|
||||
<div className="title">
|
||||
{this.state.transition_track.name}
|
||||
</div>
|
||||
<div className="artist">
|
||||
<ArtistSentence artists={this.state.transition_track.artists} nolinks />
|
||||
<LinksSentence items={this.state.transition_track.artists} nolinks />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div
|
||||
className={this.state.transition_track && this.state.transition_direction ? 'current-track current-track--transitioning' : 'current-track'}
|
||||
onTouchStart={(e) => touch_enabled && this.handleTouchStart(e)}
|
||||
onTouchEnd={(e) => touch_enabled && this.handleTouchEnd(e)}
|
||||
tabIndex="-1"
|
||||
tabIndex="-1"
|
||||
>
|
||||
<Link className="thumbnail-wrapper" to="/kiosk-mode" tabIndex="-1">
|
||||
<Thumbnail size="small" images={images} />
|
||||
@ -283,7 +283,7 @@ class PlaybackControls extends React.Component {
|
||||
{current_track ? current_track.name : <span>-</span>}
|
||||
</div>
|
||||
<div className="artist">
|
||||
{current_track ? <ArtistSentence artists={current_track.artists} /> : <ArtistSentence />}
|
||||
{current_track ? <LinksSentence items={current_track.artists} /> : <LinksSentence />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -314,13 +314,13 @@ class PlaybackControls extends React.Component {
|
||||
<section className="volume">
|
||||
<MuteControl
|
||||
mute={this.props.mute}
|
||||
onMuteChange={(mute) => this.props.mopidyActions.setMute(mute)}
|
||||
onMuteChange={(mute) => this.props.mopidyActions.setMute(mute)}
|
||||
/>
|
||||
<VolumeControl
|
||||
scrollWheel
|
||||
volume={this.props.volume}
|
||||
mute={this.props.mute}
|
||||
onVolumeChange={(percent) => this.props.mopidyActions.setVolume(percent)}
|
||||
onVolumeChange={(percent) => this.props.mopidyActions.setVolume(percent)}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -366,4 +366,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PlaybackControls);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PlaybackControls);
|
||||
|
||||
@ -3,7 +3,7 @@ import React from 'react';
|
||||
import Link from './Link';
|
||||
|
||||
import Icon from './Icon';
|
||||
import ArtistSentence from './ArtistSentence';
|
||||
import LinksSentence from './LinksSentence';
|
||||
import Dater from './Dater';
|
||||
import URILink from './URILink';
|
||||
import ContextMenuTrigger from './ContextMenuTrigger';
|
||||
@ -183,7 +183,7 @@ export default class Track extends React.Component {
|
||||
if (track.artists) {
|
||||
track_details.push(
|
||||
<li className="details__item details__item--artists" key="artists">
|
||||
{track.artists ? <ArtistSentence artists={track.artists} /> : '-'}
|
||||
{track.artists ? <LinksSentence items={track.artists} /> : '-'}
|
||||
</li>,
|
||||
);
|
||||
}
|
||||
@ -208,8 +208,7 @@ export default class Track extends React.Component {
|
||||
{track.played_at ? (
|
||||
<span>
|
||||
<Dater type="ago" data={track.played_at} />
|
||||
{' '}
|
||||
ago
|
||||
{' ago'}
|
||||
</span>
|
||||
) : '-'}
|
||||
</div>
|
||||
@ -220,15 +219,15 @@ ago
|
||||
|
||||
switch (type) {
|
||||
case 'discover':
|
||||
var link = <URILink type="recommendations" uri={helpers.getFromUri('seeds', track.added_from)}>discover</URILink>;
|
||||
var link = <URILink type="recommendations" uri={helpers.getFromUri('seeds', track.added_from)}>Discover</URILink>;
|
||||
break;
|
||||
|
||||
case 'browse':
|
||||
var link = <URILink type="browse" uri={track.added_from.replace('iris:browse:', '')}>browse</URILink>;
|
||||
var link = <URILink type="browse" uri={track.added_from.replace('iris:browse:', '')}>Browse</URILink>;
|
||||
break;
|
||||
|
||||
case 'search':
|
||||
var link = <URILink type="search" uri={track.added_from.replace('iris:', '')}>search</URILink>;
|
||||
var link = <URILink type="search" uri={track.added_from.replace('iris:', '')}>Search</URILink>;
|
||||
break;
|
||||
|
||||
case 'radio':
|
||||
@ -236,18 +235,17 @@ ago
|
||||
break;
|
||||
|
||||
default:
|
||||
var link = <URILink type={type} uri={track.added_from}>{type}</URILink>;
|
||||
var link = <URILink type={type} uri={track.added_from}>{helpers.titleCase(type)}</URILink>;
|
||||
}
|
||||
|
||||
var track_middle_column = (
|
||||
<div className="list__item__column__item list__item__column__item--added">
|
||||
<span className="by">
|
||||
{`${track.added_by} `}
|
||||
</span>
|
||||
<span className="from">
|
||||
{`from `}
|
||||
{link}
|
||||
</span>
|
||||
<span className="by by--with-spacing">
|
||||
{`${track.added_by}`}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
} else if (track.added_by) {
|
||||
@ -299,7 +297,7 @@ ago
|
||||
<div className="list__item__column list__item__column--name">
|
||||
<div className="list__item__column__item--name">
|
||||
{track.name ? track.name : <span className="mid_grey-text">{track.uri}</span>}
|
||||
{track.explicit ? <span className="flag dark">EXPLICIT</span> : null}
|
||||
{track.explicit ? <span className="flag flag--dark">EXPLICIT</span> : null}
|
||||
{track.playing ? <Icon className={`js--${this.props.play_state}`} name="playing" type="css" /> : null}
|
||||
</div>
|
||||
{track_details ? (
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import Link from './Link';
|
||||
import * as helpers from '../helpers';
|
||||
|
||||
export default memo((props) => {
|
||||
export default memo((props) => {
|
||||
let to = null;
|
||||
let { uri } = props;
|
||||
let { uri, type } = props;
|
||||
const uriType = type || helpers.uriType(uri);
|
||||
if (!props.unencoded) {
|
||||
uri = encodeURIComponent(uri);
|
||||
}
|
||||
|
||||
switch (props.type) {
|
||||
switch (uriType) {
|
||||
case 'playlist':
|
||||
to = `/playlist/${uri}`;
|
||||
break;
|
||||
@ -52,7 +54,7 @@ export default memo((props) => {
|
||||
<Link
|
||||
className={props.className ? props.className : null}
|
||||
to={to}
|
||||
onContextMenu={(e) => (props.handleContextMenu ? props.handleContextMenu(e) : null)}
|
||||
onContextMenu={(e) => (props.handleContextMenu ? props.handleContextMenu(e) : null)}
|
||||
>
|
||||
{props.children}
|
||||
</Link>
|
||||
@ -62,5 +64,5 @@ export default memo((props) => {
|
||||
<span className={props.className ? props.className : null}>
|
||||
{props.children}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
);
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ import Header from '../components/Header';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Parallax from '../components/Parallax';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import Loader from '../components/Loader';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
import NiceNumber from '../components/NiceNumber';
|
||||
@ -186,7 +186,7 @@ export class Album extends React.Component {
|
||||
) : null}
|
||||
{album.artists && album.artists.length > 0 ? (
|
||||
<li>
|
||||
<ArtistSentence artists={album.artists} />
|
||||
<LinksSentence items={album.artists} />
|
||||
</li>
|
||||
) : null}
|
||||
{album.release_date ? (
|
||||
|
||||
@ -7,7 +7,7 @@ import Icon from '../components/Icon';
|
||||
import Parallax from '../components/Parallax';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Dater from '../components/Dater';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import Header from '../components/Header';
|
||||
import URILink from '../components/URILink';
|
||||
@ -112,24 +112,6 @@ class Queue extends React.Component {
|
||||
this.props.mopidyActions.reorderTracklist(indexes, index);
|
||||
}
|
||||
|
||||
renderQueueStats() {
|
||||
const { current_tracklist } = this.props;
|
||||
|
||||
return (
|
||||
<div className="queue-stats mid_grey-text">
|
||||
<span>
|
||||
{`${current_tracklist.length || 0} tracks`}
|
||||
</span>
|
||||
|
|
||||
{current_tracklist.length > 0 ? (
|
||||
<Dater type="total-time" data={current_tracklist} />
|
||||
) : (
|
||||
<span>0 mins</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderArtwork(image) {
|
||||
const { current_track } = this.props;
|
||||
|
||||
@ -147,7 +129,7 @@ class Queue extends React.Component {
|
||||
}
|
||||
return (
|
||||
<div className="current-track__artwork">
|
||||
<URILink type="album" uri={uri}>
|
||||
<URILink uri={uri}>
|
||||
<Thumbnail glow image={image} />
|
||||
</URILink>
|
||||
</div>
|
||||
@ -159,44 +141,44 @@ class Queue extends React.Component {
|
||||
if (!added_from_uri) return null;
|
||||
|
||||
const uri_type = helpers.uriType(added_from_uri);
|
||||
let item_uri = added_from_uri;
|
||||
let item_type = uri_type;
|
||||
const items = [];
|
||||
|
||||
// Radio nests it's seed URIs in an encoded URI format
|
||||
if (uri_type === 'radio') {
|
||||
const radio_seeds = helpers.getFromUri('seeds', added_from_uri);
|
||||
|
||||
// For now we only care about the first seed
|
||||
// TODO: Support for multiple seeds
|
||||
item_uri = radio_seeds[0];
|
||||
item_type = helpers.uriType(item_uri);
|
||||
|
||||
for (let seed of radio_seeds) {
|
||||
let item_type = helpers.uriType(seed);
|
||||
let item_library = this.props[`${item_type}s`];
|
||||
if (item_library && item_library[seed]) {
|
||||
items.push(item_library[seed]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const item_library = this.props[`${uri_type}s`];
|
||||
if (item_library && item_library[added_from_uri]) {
|
||||
items.push(item_library[added_from_uri]);
|
||||
}
|
||||
}
|
||||
|
||||
const item_library = this.props[`${item_type}s`];
|
||||
if (!item_library) return null;
|
||||
|
||||
const item = item_library[item_uri];
|
||||
if (!item) return null;
|
||||
if (items.length <= 0) return null;
|
||||
|
||||
return (
|
||||
<div className="current-track__added-from">
|
||||
<URILink
|
||||
type={item_type}
|
||||
uri={item.uri}
|
||||
uri={items[0].uri}
|
||||
className="current-track__added-from__thumbnail"
|
||||
>
|
||||
<Thumbnail
|
||||
images={item.images}
|
||||
images={items[0].images}
|
||||
size="small"
|
||||
circle={item_type === 'artist'}
|
||||
circle={helpers.uriType(items[0].uri) === 'artist'}
|
||||
/>
|
||||
</URILink>
|
||||
<div className="current-track__added-from__text">
|
||||
{'Playing from '}
|
||||
<URILink type={item_type} uri={item.uri}>
|
||||
{item.name}
|
||||
</URILink>
|
||||
{uri_type === 'radio' && <span> radio</span>}
|
||||
<LinksSentence items={items} />
|
||||
{uri_type === 'radio' && <span className="flag flag--blue">Radio</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -217,15 +199,12 @@ class Queue extends React.Component {
|
||||
|
||||
const options = (
|
||||
<span>
|
||||
{this.props.spotify_enabled ? (
|
||||
{this.props.spotify_enabled && (
|
||||
<Link className="button button--no-hover" to="/queue/radio">
|
||||
<Icon name="radio" />
|
||||
Radio
|
||||
{this.props.radio && this.props.radio.enabled ? (
|
||||
<span className="flag blue">On</span>
|
||||
) : null}
|
||||
</Link>
|
||||
) : null}
|
||||
)}
|
||||
<Link className="button button--no-hover" to="/queue/history">
|
||||
<Icon name="history" />
|
||||
History
|
||||
@ -259,12 +238,12 @@ class Queue extends React.Component {
|
||||
</div>
|
||||
|
||||
{current_track ? (
|
||||
<ArtistSentence
|
||||
<LinksSentence
|
||||
className="current-track__artists"
|
||||
artists={current_track.artists}
|
||||
items={current_track.artists}
|
||||
/>
|
||||
) : (
|
||||
<ArtistSentence className="current-track__artists" />
|
||||
<LinksSentence className="current-track__artists" />
|
||||
)}
|
||||
|
||||
{this.renderAddedFrom()}
|
||||
@ -273,17 +252,14 @@ class Queue extends React.Component {
|
||||
<ul className="details">
|
||||
<li>{`${queue_tracks.length} tracks`}</li>
|
||||
<li><Dater type="total-time" data={queue_tracks} /></li>
|
||||
<li>
|
||||
<a
|
||||
onClick={(e) => {
|
||||
this.props.mopidyActions.clearTracklist();
|
||||
this.props.uiActions.hideContextMenu();
|
||||
}}
|
||||
>
|
||||
<Icon name="delete_sweep" />
|
||||
Clear queue
|
||||
</a>
|
||||
</li>
|
||||
{queue_tracks.length > 0 && (
|
||||
<li>
|
||||
<a onClick={e => this.props.mopidyActions.clearTracklist()}>
|
||||
<Icon name="delete_sweep" />
|
||||
Clear queue
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -448,12 +448,12 @@ Advanced
|
||||
{' '}
|
||||
installed
|
||||
{this.props.pusher.version.upgrade_available ? (
|
||||
<span className="flag dark">
|
||||
<span className="flag flag--dark">
|
||||
<Icon name="cloud_download" className="blue-text" />
|
||||
Upgrade available
|
||||
</span>
|
||||
) : (
|
||||
<span className="flag dark">
|
||||
<span className="flag flag--dark">
|
||||
<Icon name="check" className="green-text" />
|
||||
Up-to-date
|
||||
</span>
|
||||
|
||||
@ -8,7 +8,7 @@ import ErrorMessage from '../components/ErrorMessage';
|
||||
import Header from '../components/Header';
|
||||
import TrackList from '../components/TrackList';
|
||||
import Thumbnail from '../components/Thumbnail';
|
||||
import ArtistSentence from '../components/ArtistSentence';
|
||||
import LinksSentence from '../components/LinksSentence';
|
||||
import ArtistGrid from '../components/ArtistGrid';
|
||||
import FollowButton from '../components/Fields/FollowButton';
|
||||
import LastfmLoveButton from '../components/Fields/LastfmLoveButton';
|
||||
@ -232,13 +232,13 @@ Could not find track with URI "
|
||||
{track.album && !track.album.uri ? track.album.name : null}
|
||||
{!track.album ? 'Unknown album' : null}
|
||||
{' by '}
|
||||
<ArtistSentence artists={track.artists} />
|
||||
<LinksSentence items={track.artists} />
|
||||
</h2>
|
||||
|
||||
<ul className="details">
|
||||
{!this.props.slim_mode ? <li className="source"><Icon type="fontawesome" name={helpers.sourceIcon(this.props.uri)} /></li> : null}
|
||||
{track.date ? <li><Dater type="date" data={track.date} /></li> : null}
|
||||
{track.explicit ? <li><span className="flag dark">EXPLICIT</span></li> : null}
|
||||
{track.explicit ? <li><span className="flag flag--dark">EXPLICIT</span></li> : null}
|
||||
<li>
|
||||
{track.disc_number > 0 && <span>Disc {track.disc_number}</span>}
|
||||
{track.disc_number > 0 && track.track_number > 0 && <span>, </span>}
|
||||
|
||||
@ -5,7 +5,7 @@ import { bindActionCreators } from 'redux';
|
||||
import InputRange from 'react-input-range';
|
||||
|
||||
import Header from '../../components/Header';
|
||||
import ArtistSentence from '../../components/ArtistSentence';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import ArtistGrid from '../../components/ArtistGrid';
|
||||
import AlbumGrid from '../../components/AlbumGrid';
|
||||
import TrackList from '../../components/TrackList';
|
||||
@ -23,7 +23,7 @@ import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
import * as spotifyActions from '../../services/spotify/actions';
|
||||
|
||||
class Discover extends React.Component {
|
||||
class Discover extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
@ -157,14 +157,14 @@ class Discover extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps, newState) {
|
||||
componentWillReceiveProps(newProps, newState) {
|
||||
// New seeds via URL
|
||||
if (newProps.match.params.seeds != this.props.match.params.seeds) {
|
||||
this.handleURLSeeds(newProps.match.params.seeds);
|
||||
}
|
||||
}
|
||||
|
||||
handleContextMenu(e) {
|
||||
handleContextMenu(e) {
|
||||
var uri = 'iris:discover';
|
||||
if (this.state.seeds) {
|
||||
uri += ':';
|
||||
@ -195,14 +195,14 @@ class Discover extends React.Component {
|
||||
this.props.uiActions.showContextMenu(data);
|
||||
}
|
||||
|
||||
handleURLSeeds(seeds_string = this.props.match.params.seeds) {
|
||||
handleURLSeeds(seeds_string = this.props.match.params.seeds) {
|
||||
// Rejoin if we've had to uri-encode these as strings
|
||||
// We'd need to do this if our URL has been encoded so the whole URL can become
|
||||
// it's own URI (eg iris:discover:spotify_artist_1234) where we can't use ":"
|
||||
const seeds = seeds_string.split('_').join(':').split(',');
|
||||
|
||||
for (let i = 0; i < seeds.length; i++) {
|
||||
switch (helpers.uriType(seeds[i])) {
|
||||
switch (helpers.uriType(seeds[i])) {
|
||||
case 'artist':
|
||||
this.props.spotifyActions.getArtist(seeds[i]);
|
||||
break;
|
||||
@ -263,7 +263,7 @@ class Discover extends React.Component {
|
||||
for (let i = 0; i < this.state.seeds.length; i++) {
|
||||
const uri = this.state.seeds[i];
|
||||
|
||||
switch (helpers.uriType(uri)) {
|
||||
switch (helpers.uriType(uri)) {
|
||||
case 'track':
|
||||
if (typeof (this.props.tracks[uri]) !== 'undefined') {
|
||||
seeds_objects.push(this.props.tracks[uri]);
|
||||
@ -345,7 +345,7 @@ class Discover extends React.Component {
|
||||
const addable_tunabilities = [];
|
||||
const enabled_tunabilities = [];
|
||||
for (const key in this.state.tunabilities) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
const tunability = {
|
||||
|
||||
...this.state.tunabilities[key],
|
||||
@ -380,7 +380,7 @@ class Discover extends React.Component {
|
||||
minValue={tunability.min}
|
||||
maxValue={tunability.max}
|
||||
value={tunability.value}
|
||||
onChange={(value) => this.setTunability(tunability.name, value)}
|
||||
onChange={(value) => this.setTunability(tunability.name, value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -390,7 +390,7 @@ class Discover extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderResults() {
|
||||
renderResults() {
|
||||
// Results not in
|
||||
if (!this.props.recommendations || this.props.recommendations.albums_uris === undefined || this.props.recommendations.artists_uris === undefined) {
|
||||
return <div className="content-wrapper recommendations-results" />;
|
||||
@ -479,7 +479,7 @@ class Discover extends React.Component {
|
||||
const is_loading = helpers.isLoading(this.props.load_queue, ['spotify_recommendations']);
|
||||
const addable_tunabilities = [];
|
||||
for (const key in this.state.tunabilities) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
if (this.state.tunabilities.hasOwnProperty(key)) {
|
||||
const tunability = {
|
||||
|
||||
...this.state.tunabilities[key],
|
||||
@ -516,7 +516,7 @@ class Discover extends React.Component {
|
||||
<AddSeedField onSelect={(e, uri) => this.handleSelect(e, uri)} />
|
||||
<DropdownField className="add-properties" name="Properties" options={addable_tunabilities} no_status_icon button="default" handleChange={(val) => { this.toggleTunability(val); }} />
|
||||
<span className={`submit button button--primary button--large${is_loading ? ' button--working' : ''}`} onClick={(e) => this.getRecommendations()}>
|
||||
<Icon name="explore" />
|
||||
<Icon name="explore" />
|
||||
|
||||
Find recommendations
|
||||
</span>
|
||||
@ -551,4 +551,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Discover);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Discover);
|
||||
|
||||
@ -79,7 +79,7 @@ class EditRadio extends React.Component {
|
||||
|
||||
if (valid_seeds) {
|
||||
this.props.pusherActions.updateRadio(this.state.seeds);
|
||||
this.props.uiActions.closeModal();
|
||||
window.history.back();
|
||||
} else {
|
||||
this.setState({ error_message: 'Invalid seed URI(s)' });
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import Link from '../../components/Link';
|
||||
|
||||
import Modal from './Modal';
|
||||
import Thumbnail from '../../components/Thumbnail';
|
||||
import ArtistSentence from '../../components/ArtistSentence';
|
||||
import LinksSentence from '../../components/LinksSentence';
|
||||
import Dater from '../../components/Dater';
|
||||
import Icon from '../../components/Icon';
|
||||
import ProgressSlider from '../../components/Fields/ProgressSlider';
|
||||
@ -15,7 +15,7 @@ import * as helpers from '../../helpers';
|
||||
import * as uiActions from '../../services/ui/actions';
|
||||
import * as mopidyActions from '../../services/mopidy/actions';
|
||||
|
||||
class KioskMode extends React.Component {
|
||||
class KioskMode extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
@ -73,7 +73,7 @@ class KioskMode extends React.Component {
|
||||
<div className="player">
|
||||
<div className="current-track">
|
||||
<div className="title">{ this.props.current_track ? this.props.current_track.name : <span>-</span> }</div>
|
||||
{ this.props.current_track ? <ArtistSentence nolinks artists={this.props.current_track.artists} /> : <ArtistSentence /> }
|
||||
{ this.props.current_track ? <LinksSentence nolinks items={this.props.current_track.artists} /> : <LinksSentence /> }
|
||||
</div>
|
||||
|
||||
<div className="progress-wrapper">
|
||||
@ -95,4 +95,4 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
mopidyActions: bindActionCreators(mopidyActions, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(KioskMode);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(KioskMode);
|
||||
|
||||
@ -217,13 +217,19 @@
|
||||
}
|
||||
|
||||
&--added {
|
||||
.from {
|
||||
.by {
|
||||
opacity: 0.5;
|
||||
|
||||
&:before {
|
||||
content: '(';
|
||||
}
|
||||
&:after {
|
||||
content: ')';
|
||||
}
|
||||
|
||||
&--with-spacing {
|
||||
padding-left: 0.25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -126,12 +126,12 @@
|
||||
@include one_line_text;
|
||||
}
|
||||
|
||||
.artist-sentence {
|
||||
.links-sentence {
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
@include one_line_text;
|
||||
|
||||
.artist {
|
||||
&__item {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted transparent;
|
||||
|
||||
@ -562,32 +562,32 @@ footer {
|
||||
vertical-align: bottom;
|
||||
margin: 0 8px 1px;
|
||||
|
||||
&.blue {
|
||||
&--blue {
|
||||
background: colour(blue);
|
||||
color: colour(white);
|
||||
}
|
||||
|
||||
&.info {
|
||||
&--info {
|
||||
background: colour(yellow);
|
||||
}
|
||||
|
||||
&.warning {
|
||||
&--warning {
|
||||
background: colour(orange);
|
||||
color: colour(white);
|
||||
}
|
||||
|
||||
&.error,
|
||||
&.bad {
|
||||
&--error,
|
||||
&--bad {
|
||||
background: colour(red);
|
||||
color: colour(white);
|
||||
}
|
||||
|
||||
&.dark {
|
||||
&--dark {
|
||||
background: lighten(colour(dark_grey), 10%);
|
||||
color: colour(mid_grey);
|
||||
}
|
||||
|
||||
&.large {
|
||||
&--large {
|
||||
padding: 8px 10px 7px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@ -319,7 +319,7 @@
|
||||
padding-top: 80px;
|
||||
font-size: 30px;
|
||||
|
||||
.artist-sentence {
|
||||
.links-sentence {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
a {
|
||||
border: 0 !important;
|
||||
display: inline-block;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@ -23,22 +23,6 @@
|
||||
width: 30vh;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&--radio-enabled {
|
||||
.thumbnail {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.radio-overlay {
|
||||
position: absolute;
|
||||
top: -15%;
|
||||
left: -15%;
|
||||
width: 130%;
|
||||
height: 130%;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__details {
|
||||
|
||||
Reference in New Issue
Block a user