diff --git a/public/images/icons/app-icon-144.png b/public/images/icons/app-icon-144.png new file mode 100644 index 00000000..f54d5b33 Binary files /dev/null and b/public/images/icons/app-icon-144.png differ diff --git a/public/images/icons/app-icon-192.png b/public/images/icons/app-icon-192.png new file mode 100644 index 00000000..86e679ca Binary files /dev/null and b/public/images/icons/app-icon-192.png differ diff --git a/public/images/icons/app-icon-96.png b/public/images/icons/app-icon-96.png new file mode 100644 index 00000000..9b1806a0 Binary files /dev/null and b/public/images/icons/app-icon-96.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 00000000..0e256ba4 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,24 @@ +{ + "short_name": "Pony.fm", + "name": "Pony.fm", + "icons": [ + { + "src": "images/icons/app-icon-96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "images/icons/app-icon-144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "images/icons/app-icon-192.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "start_url": "/", + "display": "standalone", + "orientation": "portrait" +} diff --git a/public/service-worker.js b/public/service-worker.js new file mode 100644 index 00000000..5f0a0d39 --- /dev/null +++ b/public/service-worker.js @@ -0,0 +1,47 @@ +// Pony.fm - A community for pony fan music. +// Copyright (C) 2016 Josef Citrine +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +var urlsToCache = [ + '/', + '/build/styles/app.css', + '/build/scripts/app.js', + '/build/scripts/templates.js', + '/templates/directives/player.html', + '/templates/directives/search.html', + '/templates/directives/tracks-list.html', + '/templates/directives/users-list.html', + '/templates/directives/albums-list.html', + '/templates/directives/playlists-list.html', + '/templates/home/index.html', + +]; + +var CACHE_NAME = 'pfm-cache-v1'; + +// Set the callback for the install step +self.addEventListener('install', function(event) { + // Doesn't do anything right now + // Could never get offline to fully + // work without bugs :( + + // Perform install steps + event.waitUntil( + caches.open(CACHE_NAME) + .then(function(cache) { + console.log('Opened cache'); + }) + ); +}); diff --git a/resources/assets/scripts/app/controllers/application.coffee b/resources/assets/scripts/app/controllers/application.coffee index 9bcfc1cd..a8010494 100644 --- a/resources/assets/scripts/app/controllers/application.coffee +++ b/resources/assets/scripts/app/controllers/application.coffee @@ -21,9 +21,20 @@ module.exports = angular.module('ponyfm').controller "application", [ $scope.$state = $state $scope.$stateParams = $stateParams $scope.isPinnedPlaylistSelected = false + $scope.menuActive = false $loadingElement = null loadingStateName = null + if 'serviceWorker' of navigator + console.log 'Service Worker is supported' + navigator.serviceWorker.register('service-worker.js').then((reg) -> + console.log 'SW registered', reg + ).catch (err) -> + console.log 'SW register failed', err + + $scope.menuToggle = () -> + $scope.menuActive = !$scope.menuActive + if window.pfm.error $state.transitionTo 'errors-' + window.pfm.error @@ -60,6 +71,7 @@ module.exports = angular.module('ponyfm').controller "application", [ statesPreloaded = {} $scope.$on '$stateChangeStart', (e, newState, newParams, oldState, oldParams) -> + $scope.menuActive = false $scope.isPinnedPlaylistSelected = false if newState.name == 'content.playlist' diff --git a/resources/assets/scripts/shared/layout.coffee b/resources/assets/scripts/shared/layout.coffee index 47f1d7d1..b32c7897 100644 --- a/resources/assets/scripts/shared/layout.coffee +++ b/resources/assets/scripts/shared/layout.coffee @@ -16,8 +16,14 @@ window.handleResize = () -> windowHeight = $(window).height() + windowWidth = $(window).width() + isMobile = windowWidth <= 480 $siteBody = $ '.site-body' - $siteBody.height windowHeight - $('header').height() + + if isMobile + $siteBody.height windowHeight - $('.now-playing').height() * 2 + else + $siteBody.height windowHeight - $('header').height() $('.dropdown-menu').each () -> $this = $ this @@ -26,10 +32,11 @@ window.handleResize = () -> 'max-height': newMaxHeight $('.stretch-to-bottom').each () -> - $this = $ this - newHeight = windowHeight - $this.offset().top - if newHeight > 0 - $this.height newHeight + if !isMobile + $this = $ this + newHeight = windowHeight - $this.offset().top + if newHeight > 0 + $this.height newHeight $('.revealable').each () -> $this = $ this diff --git a/resources/assets/styles/app.less b/resources/assets/styles/app.less index d952709d..0ee068c4 100644 --- a/resources/assets/styles/app.less +++ b/resources/assets/styles/app.less @@ -36,3 +36,4 @@ @import 'components/uploader'; @import 'components/search'; @import 'components/track-editor'; +@import 'mobile'; diff --git a/resources/assets/styles/layout.less b/resources/assets/styles/layout.less index 5886807c..fbd1f155 100644 --- a/resources/assets/styles/layout.less +++ b/resources/assets/styles/layout.less @@ -31,35 +31,7 @@ html body { } header { - > a { - display: block; - float: left; - width: (@pfm-sidebar-size); - height: 64px; - line-height: 42px; - background: #84528A; - color: #fff; - font-size: 24pt; - font-weight: lighter; - position: relative; - z-index: 600; - font-family: 'Josefin Sans', sans-serif; - position: relative; - &:hover { - background: darken(#84528A, 25%); - color: #fff; - text-decoration: none; - } - - img.logo { - padding-left: 6px; - width: 100%; - max-width: 90%; - padding-top: 13px; - max-height: 45% - } - } .user-details { float: right; @@ -116,15 +88,46 @@ header { } .sidebar { + > a { + display: block; + float: left; + width: (@pfm-sidebar-size); + height: 64px; + line-height: 42px; + background: #84528A; + color: #fff; + font-size: 24pt; + font-weight: lighter; + position: relative; + z-index: 600; + font-family: 'Josefin Sans', sans-serif; + position: relative; + + &:hover { + background: darken(#84528A, 25%); + color: #fff; + text-decoration: none; + } + + img.logo { + padding-left: 6px; + width: 100%; + max-width: 90%; + padding-top: 13px; + max-height: 45% + } + } + background: #515151; width: @pfm-sidebar-size; height: 100%; - float: left; list-style: none; padding: 0px; margin: 0px; font-size: 10pt; - position: relative; + position: absolute; + bottom: 0; + left: 0; li { margin: 0px; @@ -251,3 +254,41 @@ header { .chart-btn-container { margin-bottom: 10px; } + +.mobile-header { + display: none; +} + +.burger-wrapper { + top:20px; + left: 20px; + position: absolute; +} + +.burger { + width: 25px; + height: 20px; + top: 20px; + left: 20px; +} + +.bun-top,.meat,.bun-bottom { + position: absolute; + display: block; + border-radius: 4px; + background: white; + width: 25px; + height: 2px; +} + +.bun-top { + top: 0; +} + +.meat { + top: 9px; +} + +.bun-bottom { + bottom: 0; +} diff --git a/resources/assets/styles/mobile.less b/resources/assets/styles/mobile.less new file mode 100644 index 00000000..a9b34a53 --- /dev/null +++ b/resources/assets/styles/mobile.less @@ -0,0 +1,127 @@ +@media only screen and (max-width: 480px) { + html, body { + overflow: hidden !important; + } + + body > header { + margin-top: 64px; + } + + .site-content { + margin-left: 0px; + overflow: scroll; + } + + .now-playing { + margin-left: 0px; + position: fixed; + width: 100%; + bottom: 0; + z-index: 1010; + box-shadow: 0 0 8px rgba(0,0,0,0.5); + } + + .user-details { + position: fixed; + top: 0; + right: 0; + z-index: 1002; + } + + .mobile-header { + display: block !important; + position: absolute; + z-index: 1001; + background: #84528A; + height: 64px; + width: 100%; + top: 0; + + .logo { + text-align: center; + vertical-align: middle; + display: block; + margin-left: auto; + margin-right: auto; + height: 40px; + width: 160px; + padding-top: 16px; + + > img { + max-height: 75%; + } + } + } + + .sidebar { + left: -170px; + transition: transform 0.5s ease; + transform: translateX(0px) translateZ(0); + perspective: 1000; + backface-visibility: hidden; + will-change: transform; + z-index: 1011; + height: ~"calc(100% - 64px)"; + box-shadow: 0 8px 8px rgba(0,0,0,0.5); + + > a { + display: none; + } + } + + .sidebar.active { + transform: translateX(170px) translateZ(0); + } + + .user-details > .avatar { + border: 0 !important; + box-shadow: initial !important; + background: transparent !important; + + > img { + border-radius: 20px; + } + + > span { + display: none !important; + } + } + + .track-player { + margin-right: 0px !important; + .buttons { + li.volume, li.status { + display: none; + } + } + } + + input.search-input { + border: 0; + } + + .dropdowns { + margin-bottom: 0px; + > li { + margin-bottom: 10px; + > .btn { + font-size: 10pt; + } + } + } + .details-columns { + .cboxElement { + display: none; + } + .right { + float: none; + padding: 0px; + width: auto; + } + .left { + margin-right: 0px; + margin-left: 0px; + margin-top: 10px; + } + } +} diff --git a/resources/views/shared/_app_layout.blade.php b/resources/views/shared/_app_layout.blade.php index 1017000a..515112d9 100644 --- a/resources/views/shared/_app_layout.blade.php +++ b/resources/views/shared/_app_layout.blade.php @@ -42,9 +42,16 @@
- - - +
+
+
+
+
+
+
+
+ +
@if (Auth::check())
-