diff --git a/package.json b/package.json index da874af9..6feb4b52 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "url": "ssh://git@phabricator.poniverse.net/diffusion/PF/pony-fm.git" }, "packages": {}, - "dependencies": {}, + "dependencies": { + "color-thief": "github:logic-dev/color-thief" + }, "devDependencies": { "angular": "1.5.6", "angular-chart.js": "1.0.0-alpha6", diff --git a/public/templates/artists/_show_layout.html b/public/templates/artists/_show_layout.html index 3993f21d..066898b0 100644 --- a/public/templates/artists/_show_layout.html +++ b/public/templates/artists/_show_layout.html @@ -1,7 +1,7 @@
@@ -11,7 +11,7 @@ 'other': '{} followers'}">
- + Follow Following! diff --git a/resources/assets/scripts/app/app.coffee b/resources/assets/scripts/app/app.coffee index 851c1c3e..657128b6 100644 --- a/resources/assets/scripts/app/app.coffee +++ b/resources/assets/scripts/app/app.coffee @@ -42,6 +42,7 @@ require 'script!../base/marked' require 'script!../base/moment' require '../base/soundmanager2-nodebug' require 'script!../base/tumblr' +require 'color-thief'; require 'angular-strap' # Just ignore this, blame webpack require '../../../../node_modules/angular-strap/dist/angular-strap.tpl' diff --git a/resources/assets/scripts/app/controllers/application.coffee b/resources/assets/scripts/app/controllers/application.coffee index 7e09bd5b..dda2144f 100644 --- a/resources/assets/scripts/app/controllers/application.coffee +++ b/resources/assets/scripts/app/controllers/application.coffee @@ -42,7 +42,7 @@ module.exports = angular.module('ponyfm').controller "application", [ notifications.markAllAsRead() $scope.notifActive = false - + $scope.notifPulloutToggle = () -> $scope.notifActive = !$scope.notifActive @@ -98,6 +98,9 @@ module.exports = angular.module('ponyfm').controller "application", [ $scope.notifActive = false $scope.isPinnedPlaylistSelected = false + if oldState.name.indexOf('content.artist.') != -1 && newState.name.indexOf('content.artist.') == -1 + $('.top-bar').css('background': '') + if newState.name == 'content.playlist' $scope.isPinnedPlaylistSelected = playlists.isPlaylistPinned newParams.id diff --git a/resources/assets/scripts/app/controllers/artist.coffee b/resources/assets/scripts/app/controllers/artist.coffee index a733f8d7..517b5555 100644 --- a/resources/assets/scripts/app/controllers/artist.coffee +++ b/resources/assets/scripts/app/controllers/artist.coffee @@ -21,13 +21,144 @@ window.pfm.preloaders['artist'] = [ ] module.exports = angular.module('ponyfm').controller "artist", [ - '$scope', 'artists', '$state', 'follow' - ($scope, artists, $state, follow) -> + '$scope', 'artists', '$state', 'follow', '$rootScope' + ($scope, artists, $state, follow, $rootScope) -> updateArtist = (force = false) -> artists.fetch($state.params.slug, force) .done (artistResponse) -> $scope.artist = artistResponse.artist + tempImg = document.createElement('img') + tempImg.setAttribute 'src', artistResponse.artist.avatars.small + tempImg.addEventListener 'load', -> + colorThief = new ColorThief(); + palette = colorThief.getPalette(tempImg, 2) + $('.top-bar').css('background': selectHeaderColour(palette[0], palette[1])) + $scope.headerStyle = {'background-image': createGradient(palette[0], palette[1])} + $scope.$apply() + + rgbArrayToCss = (array) -> + 'rgb(' + array[0] + ',' + array[1] + ',' + array[2] + ')' + + hslArrayToCss = (array) -> + 'hsl(' + array[0] + ',' + array[1] + '%,' + array[2] + '%)' + + dimColor = (colour) -> + hsl = rgbToHsl(colour) + + if hsl[2] >= 50 + hsl[2] = 50 + if hsl[1] <= 20 + hsl[1] = 30 + return hslToRgb(hsl) + else + return colour + + createGradient = (vib, dark) -> + if $(window).width() <= 480 + 'linear-gradient(180deg, ' + rgbArrayToCss(vib) + ' 5%, ' + rgbArrayToCss(dimColor(dark)) + ' 95%)' + else + 'linear-gradient(170deg, ' + rgbArrayToCss(vib) + ' 15%, ' + rgbArrayToCss(dark) + ' 110%)' + + findHighestSaturation = (hsl1, hsl2) -> + if hsl1[1] > hsl2[1] + return hsl1 + else + return hsl2 + + findBestColour = (hsl1, hsl2) -> + maxLumin = 60 + mid = 40 + best = undefined + + if Math.abs(hsl1[2] - mid) < Math.abs(hsl2[2] - mid) + best = hsl1 + else + best = findHighestSaturation(hsl1, hsl2) + + if best[2] > maxLumin + best[2] = maxLumin + + return best + + + selectHeaderColour = (colour1, colour2) -> + hsl1 = rgbToHsl(colour1) + hsl2 = rgbToHsl(colour2) + out = rgbArrayToCss(hslToRgb(findBestColour(hsl1, hsl2))) + return out + + rgbToHsl = (rgbArr) -> + r1 = rgbArr[0] / 255 + g1 = rgbArr[1] / 255 + b1 = rgbArr[2] / 255 + maxColor = Math.max(r1, g1, b1) + minColor = Math.min(r1, g1, b1) + L = (maxColor + minColor) / 2 + S = 0 + H = 0 + if maxColor != minColor + if L < 0.5 + S = (maxColor - minColor) / (maxColor + minColor) + else + S = (maxColor - minColor) / (2.0 - maxColor - minColor) + if r1 == maxColor + H = (g1 - b1) / (maxColor - minColor) + else if g1 == maxColor + H = 2.0 + (b1 - r1) / (maxColor - minColor) + else + H = 4.0 + (r1 - g1) / (maxColor - minColor) + L = L * 100 + S = S * 100 + H = H * 60 + if H < 0 + H += 360 + + round = (value, decimals) -> + Number Math.round(value + 'e' + decimals) + 'e-' + decimals + + [round(H, 6), round(S, 6), round(L, 6)] + + toPercent = (amount, limit) -> + amount / limit + + hueToRgb = (p, q, t) -> + if t < 0 + t += 1 + if t > 1 + t -= 1 + if t < 1 / 6 + return p + (q - p) * 6 * t + if t < 1 / 2 + return q + if t < 2 / 3 + return p + (q - p) * (2 / 3 - t) * 6 + + p + + hslToRgb = (bits) -> + rgb = [] + v = undefined + q = undefined + p = undefined + hsl = + h: toPercent(parseInt(bits[0], 10) % 360, 360) + s: toPercent(parseInt(bits[1], 10) % 101, 100) + l: toPercent(parseInt(bits[2], 10) % 101, 100) + if hsl.s == 0 + v = parseInt(Math.round(255 * hsl.l)) + rgb[0] = v + rgb[1] = v + rgb[2] = v + else + q = if hsl.l < 0.5 then hsl.l * (1 + hsl.s) else hsl.l + hsl.s - (hsl.l * hsl.s) + p = 2 * hsl.l - q + rgb[0] = parseInt((hueToRgb(p, q, hsl.h + 1 / 3) * 256).toFixed(0), 10) + rgb[1] = parseInt((hueToRgb(p, q, hsl.h) * 256).toFixed(0), 10) + rgb[2] = parseInt((hueToRgb(p, q, hsl.h - (1 / 3)) * 256).toFixed(0), 10) + + rgb + $scope.toggleFollow = () -> follow.toggle('artist', $scope.artist.id).then (res) -> $scope.artist.user_data.is_following = res.is_followed diff --git a/resources/assets/styles/components/components.less b/resources/assets/styles/components/components.less index 0b55eb53..f30c6564 100644 --- a/resources/assets/styles/components/components.less +++ b/resources/assets/styles/components/components.less @@ -236,6 +236,11 @@ html body { &.btn-flat { box-shadow: 0 0 0 transparent !important; + background-color: transparent; + + &.btn-default:hover { + background-color: rgba(255, 255, 255, 0.5); + } } } diff --git a/resources/assets/styles/components/search.less b/resources/assets/styles/components/search.less index ba618e6e..c3431f1e 100644 --- a/resources/assets/styles/components/search.less +++ b/resources/assets/styles/components/search.less @@ -28,7 +28,7 @@ } input.search-input { - background: lighten(@pfm-logo-purple, 10%); + background: rgba(255,255,255,0.15); color: #fff; border: 0; font-size: 13px; diff --git a/resources/assets/styles/content.less b/resources/assets/styles/content.less index b2912870..cae210e4 100644 --- a/resources/assets/styles/content.less +++ b/resources/assets/styles/content.less @@ -160,9 +160,10 @@ &.artist-details { > header { - padding: 15px; background-size: cover; background-position: center; + padding: 25px; + margin: -15px -15px 10px; > img { width: 150px; @@ -229,7 +230,7 @@ > header { padding: 5px; - background: #eee; + background: #ddd; overflow: hidden; margin-bottom: 10px; diff --git a/resources/assets/styles/embed.less b/resources/assets/styles/embed.less index 336e1bd5..e8a7cabc 100644 --- a/resources/assets/styles/embed.less +++ b/resources/assets/styles/embed.less @@ -18,7 +18,6 @@ @import 'https://fonts.googleapis.com/css?family=Material+Icons'; @import 'base/bootstrap/bootstrap'; -@import 'base/font-awesome/font-awesome'; @import 'variables'; @import 'mixins'; diff --git a/resources/assets/styles/layout.less b/resources/assets/styles/layout.less index 0b49933e..e80410a0 100644 --- a/resources/assets/styles/layout.less +++ b/resources/assets/styles/layout.less @@ -89,7 +89,6 @@ header { width: (@pfm-sidebar-size); height: 64px; line-height: 42px; - background: @pfm-logo-purple; color: #fff; font-size: 24pt; font-weight: lighter; @@ -99,7 +98,7 @@ header { position: relative; &:hover { - background: darken(@pfm-logo-purple, 15%); + background: rgba(0,0,0,0.3); color: #fff; text-decoration: none; } @@ -267,6 +266,7 @@ header { height: @pfm-top-bar-size; width: 100%; top: 0; + transition: background 0.5s @swift-ease-in-out; .material-shadow(1); .burger-wrapper { diff --git a/resources/assets/styles/mobile.less b/resources/assets/styles/mobile.less index 20786ca2..bc59cf4e 100644 --- a/resources/assets/styles/mobile.less +++ b/resources/assets/styles/mobile.less @@ -216,8 +216,8 @@ } > header { - margin-bottom: 0px; - padding-bottom: 40px !important; + margin: 0 !important; + padding: 20px 0 40px !important; > img { float: none !important; diff --git a/webpack.base.config.js b/webpack.base.config.js index 0a39769f..3d77dd53 100644 --- a/webpack.base.config.js +++ b/webpack.base.config.js @@ -13,7 +13,8 @@ module.exports = { plugins: [ new webpack.ProvidePlugin({ $: "jquery", - jQuery: "jquery" + jQuery: "jquery", + ColorThief: "color-thief" }), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/) ],