From 493ad2cb9b120a52b613a3818f1058f8c2b7fda8 Mon Sep 17 00:00:00 2001 From: flashwave Date: Fri, 30 Oct 2020 13:43:48 +0000 Subject: [PATCH] dynamic loading and like one animation, closes #1! --- components/footer.php | 7 +- components/header.php | 38 +++++---- pages/index.php | 20 +++-- public/assets/2020v2.css | 21 +++++ public/assets/2020v2.js | 164 +++++++++++++++++++++++++++++++++++---- public/index.php | 54 ++++++++++--- 6 files changed, 248 insertions(+), 56 deletions(-) diff --git a/components/footer.php b/components/footer.php index 9871070..1856152 100644 --- a/components/footer.php +++ b/components/footer.php @@ -1,14 +1,15 @@ - + + diff --git a/components/header.php b/components/header.php index 2dce642..c1940b2 100644 --- a/components/header.php +++ b/components/header.php @@ -2,6 +2,7 @@ $menu = isset($menu) && is_array($menu) ? $menu : FM_NAV; $backgrounds = isset($backgrounds) && is_array($backgrounds) ? $backgrounds : FM_BGS; $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST']; +$showNowPlaying = !empty($is_index) || !empty($do_fullscreen_header); ?> @@ -16,38 +17,35 @@ $baseUrl = empty($external) ? '' : '//' . $_SERVER['HTTP_HOST']; - +
0) echo " style=\"padding-bottom: {$offset}px\""; ?>> - - -
-
-
+
+
+
+
+
+
+ +
+
+
+
+
-
- -
-
-
-
-
-
- -
+
- + > +
-
-
- diff --git a/pages/index.php b/pages/index.php index e443d82..da64b90 100644 --- a/pages/index.php +++ b/pages/index.php @@ -30,13 +30,14 @@ if($reqPath === '/now-listening') { fm_component('header', [ 'title' => 'flash.moe / now listening', 'do_fullscreen_header' => true, + 'is_now_playing' => true, 'offset' => $offset, ]); -?> - - true, + 'onload' => [ + ['fm.initIndex', 10], + ], ]); return FM_HIT; @@ -88,11 +89,14 @@ if($reqPath === '/home') {
- true, 'skip_analytics' => true, + 'onload' => [ + ['fm.initClock'], + ['fm.initIndex', 10], + ], ]); return FM_HIT; @@ -180,7 +184,7 @@ if($reqPath === '/') { ?>
- + >
- true, + 'onload' => [ + ['fm.initIndex'], + ], ]); return FM_HIT; diff --git a/public/assets/2020v2.css b/public/assets/2020v2.css index ac1eecb..2730565 100644 --- a/public/assets/2020v2.css +++ b/public/assets/2020v2.css @@ -16,6 +16,10 @@ html { scrollbar-color: #4a3650 #111; } +.hidden { + display: none !important; +} + /* an attempt to replicate scrollbar-color for chromosome */ ::-webkit-scrollbar { width: 6px; @@ -46,6 +50,7 @@ body { width: 100%; height: 200px; overflow: hidden; + transition: height .5s; } @media (max-width: 700px) { .header { height: auto; } @@ -120,10 +125,21 @@ body { background-image: linear-gradient(0deg, #281430 0%, #392540 50%, #4a3650 50%, #6c5871 100%); -webkit-background-clip: text; } +.header-right { + display: flex; + flex-direction: column; + align-items: flex-end; +} .header-menu { display: flex; justify-content: center; flex: 0 0 auto; + margin-top: 10px; +} +.index .header-menu, +.fullscreen-header .header-menu, +.now-playing .header-menu { + display: none; } .header-menu a { display: block; @@ -167,6 +183,11 @@ body { } .footer {} +.index .footer, +.fullscreen-header .footer, +.now-playing .footer { + display: none; +} .footer-text { opacity: .2; font-size: .9em; diff --git a/public/assets/2020v2.js b/public/assets/2020v2.js index 9f60137..13ab044 100644 --- a/public/assets/2020v2.js +++ b/public/assets/2020v2.js @@ -12,14 +12,43 @@ Date.prototype.getWeekYear = function() { } window.fm = (function() { + var fm = this; + this.container = document.querySelector('.container'); this.headerBackground = null; this.originalHeaderBackground = null; this.defaultCoverImage = 'https://lastfm.freetls.fastly.net/i/u/174s/2a96cbd8b46e442fc41c2b86b821562f.png'; + this.indexIsPlaying = false; + this.indexPlayingDefaultCover = false; this.indexPlayingContainer = null; this.indexPlayingCover = null; this.indexPlayingTitle = null; this.indexPlayingArtist = null; this.indexLastNp = null; + this.indexPlayingInterval = null; + this.homeInterval = null; + + this.callByName = function(name, args) { + var ref = window, + parent = null, + parts = name.split('.'); + for(var i = 0; i < parts.length; ++i) { + parent = ref; + if(typeof ref[parts[i]] !== 'undefined') + ref = ref[parts[i]]; + else return; + } + if(typeof ref !== 'function') + return; + return ref.apply(parent, args); + }; + + this.runFuncs = function(funcs) { + for(var i = 0; i < funcs.length; ++i) + fm.callByName(funcs[i][0], funcs[i].slice(1)); + }; + + if(this.onload && Array.isArray(this.onload)) + window.addEventListener('load', function() { fm.runFuncs(fm.onload); }); if(sessionStorage.getItem('header-bgs') === null || sessionStorage.getItem('header-bgs-loaded') < Date.now() - 86400000) { @@ -32,6 +61,83 @@ window.fm = (function() { hXhr.send(); } + this.dynloadCurrent = function() { + return { + components: { + header: { + title: document.title, + is_index: document.body.classList.contains('index'), + do_fullscreen_header: document.body.classList.contains('fullscreen-header'), + is_now_playing: document.body.classList.contains('now-playing'), + }, + footer: { + onload: this.onload || [], + } + }, + raw_html: fm.container.innerHTML, + }; + }; + + this.dynloadApply = function(state) { + if((state.components || {}).header) { + document.title = state.components.header.title || ''; + document.body.classList[state.components.header.is_index ? 'add' : 'remove']('index'); + document.body.classList[state.components.header.do_fullscreen_header ? 'add' : 'remove']('fullscreen-header'); + document.body.classList[state.components.header.is_now_playing ? 'add' : 'remove']('now-playing'); + } + + if(typeof state.raw_html !== 'undefined') + this.container.innerHTML = state.raw_html; + + if((state.components || {}).footer) { + this.runFuncs(state.components.footer.onload || []); + } + + fm.dynloadInit(); + fm.setRandomHeaderBackgroundIfNotPlaying(); + }; + + this.dynloadInit = function(initial) { + if(initial) { + history.replaceState(this.dynloadCurrent(), document.title, location.toString()); + window.addEventListener('popstate', function(ev) { + fm.dynloadApply(ev.state || {}); + }); + } + + var dynload = document.querySelectorAll('[data-fm-dynload]'); + for(var i = 0; i < dynload.length; ++i) + (function(dc){ + dc.removeAttribute('data-fm-dynload'); + dc.addEventListener('click', function(ev) { + ev.stopPropagation(); + ev.preventDefault(); + + var xhr = new XMLHttpRequest; + xhr.onload = function() { + try { + var obj = JSON.parse(xhr.responseText); + } catch(ex) {} + if(!obj) { + location.assign(dc.href); + return; + } + var title = ((obj.components || {}).header || {}).title || ''; + history.pushState(obj, title, dc.href); + fm.dynloadApply(obj); + }; + xhr.onerror = function(ev) { + location.assign(dc.href); + }; + xhr.open('GET', dc.href); + xhr.setRequestHeader('Accept', 'application/x-fdynload+json'); + xhr.send(); + }, true); + })(dynload[i]); + }; + + this.dynloadInit(true); + this.selectTextInElement = function(elem) { // MSIE if(document.body.createTextRange) { @@ -86,14 +192,16 @@ window.fm = (function() { this.indexLastNp = info; } else return; + this.indexIsPlaying = info.now_playing; + this.indexPlayingDefaultCover = !info.cover || info.cover === this.defaultCoverImage; this.indexPlayingContainer.classList[info.now_playing ? 'remove' : 'add']('header-now-playing-hidden'); this.indexPlayingCover.alt = this.indexPlayingCover.src = (info.cover !== this.defaultCoverImage ? info.cover : '//now.flash.moe/resources/no-cover.png'); this.indexPlayingTitle.textContent = this.indexPlayingTitle.title = info.name; this.indexPlayingTitle.href = info.url; - this.indexPlayingArtist.textContent = this.indexPlayingArtist.title = info.artist.name; - this.indexPlayingArtist.href = info.artist.url; + this.indexPlayingArtist.textContent = this.indexPlayingArtist.title = (info.artist || {}).name || ''; + this.indexPlayingArtist.href = (info.artist || {}).url || ''; this.switchHeaderBackground( - info.now_playing && info.cover !== this.defaultCoverImage + info.now_playing && !this.indexPlayingDefaultCover ? this.indexPlayingCover.src : this.originalHeaderBackground ); @@ -104,20 +212,27 @@ window.fm = (function() { var set = JSON.parse(sessionStorage.getItem('header-bgs')); if(!set) return '/assets/errors/404.jpg'; - return set[parseInt(Math.random() * set.length)]; + return set[parseInt(Math.random() * set.length) - 1]; }; this.setRandomHeaderBackground = function() { this.switchHeaderBackground(this.getRandomHeaderBackground()); }; + this.setRandomHeaderBackgroundIfNotPlaying = function() { + if(!this.indexIsPlaying || this.indexPlayingDefaultCover) + this.setRandomHeaderBackground(); + }; + this.getCurrentHeaderBackground = function() { return this.headerBackground.querySelector('img').src; }; + this.headerBackgroundIsChanging = false; this.switchHeaderBackground = function(url) { - if(this.getCurrentHeaderBackground() === url) + if(this.headerBackgroundIsChanging || this.getCurrentHeaderBackground() === url) return; + this.headerBackgroundIsChanging = true; var newImg = document.createElement('img'), oldImg = this.headerBackground.querySelector('img'); newImg.alt = newImg.src = url; @@ -131,10 +246,12 @@ window.fm = (function() { setTimeout(function() { newImg.style.zIndex = null; this.headerBackground.removeChild(oldImg); + this.headerBackgroundIsChanging = false; }.bind(this), 500); }.bind(this), 50); }.bind(this); newImg.onerror = function() { + this.headerBackgroundIsChanging = false; this.switchHeaderBackground(this.originalHeaderBackground); }.bind(this); }; @@ -143,18 +260,29 @@ window.fm = (function() { this.originalHeaderBackground = this.headerBackground.querySelector('img').src; this.initIndex = function(npInterval) { - this.indexPlayingContainer = document.querySelector('.header-now-playing'); - this.indexPlayingCover = window.fm.indexPlayingContainer.querySelector('.header-now-playing-cover img'); - this.indexPlayingCover.onerror = function() { - this.indexPlayingCover.src = '//now.flash.moe/resources/no-cover.png'; - }.bind(this); - this.indexPlayingTitle = window.fm.indexPlayingContainer.querySelector('.header-now-playing-title a'); - this.indexPlayingArtist = window.fm.indexPlayingContainer.querySelector('.header-now-playing-artist a'); + if(!this.indexPlayingContainer) { + this.indexPlayingContainer = document.querySelector('.header-now-playing'); + this.indexPlayingCover = window.fm.indexPlayingContainer.querySelector('.header-now-playing-cover img'); + this.indexPlayingCover.onerror = function() { + this.indexPlayingCover.src = '//now.flash.moe/resources/no-cover.png'; + }.bind(this); + this.indexPlayingTitle = window.fm.indexPlayingContainer.querySelector('.header-now-playing-title a'); + this.indexPlayingArtist = window.fm.indexPlayingContainer.querySelector('.header-now-playing-artist a'); + } + + if(this.indexPlayingInterval) { + clearInterval(this.indexPlayingInterval); + this.indexPlayingInterval = null; + } + this.updateIndexNowListening(); - setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000); + this.indexPlayingInterval = setInterval(this.updateIndexNowListening, (npInterval || 30) * 1000); }; this.initClock = function() { + if(this.homeInterval) + return; + var digitalClock = document.querySelector('.php-time-digital'), analogClock = document.querySelector('.php-time-analog'), dateZone = document.querySelector('.php-time-date'), @@ -169,7 +297,13 @@ window.fm = (function() { dateMonth = dateZone.querySelector('.php-date-month'), dateYear = dateZone.querySelector('.php-date-year'); - setInterval(function() { + this.homeInterval = setInterval(function() { + if(!document.body.contains(digitalClock)) { + clearInterval(this.homeInterval); + this.homeInterval = null; + return; + } + var time = new Date; var dHour = time.getHours(), @@ -196,7 +330,7 @@ window.fm = (function() { angHours.style.setProperty('--hand-rotation', (rHour * 360).toString() + 'deg'); angMinutes.style.setProperty('--hand-rotation', (rMin * 360).toString() + 'deg'); angSeconds.style.setProperty('--hand-rotation', (rSec * 360).toString() + 'deg'); - }, 200); + }.bind(this), 200); }; return this; diff --git a/public/index.php b/public/index.php index fd24287..07d3889 100644 --- a/public/index.php +++ b/public/index.php @@ -67,7 +67,17 @@ define('FM_ERRS' , [ ], ]); +define('FM_DYNLOAD', filter_input(INPUT_SERVER, 'HTTP_ACCEPT') === 'application/x-fdynload+json'); + function fm_component(string $_component_name, array $vars = []) { + if(FM_DYNLOAD) { + global $fmComponentVars; + if(!isset($fmComponentVars)) + $fmComponentVars = []; + $fmComponentVars[$_component_name] = $vars; + return; + } + extract($vars); require __DIR__ . '/../components/' . $_component_name . '.php'; } @@ -129,6 +139,9 @@ if($reqMethod == 'HEAD') { $reqHead = true; } +if(FM_DYNLOAD) + ob_start(); + if(substr($reqPath, 0, 7) === '/error/') { $statusCode = intval(substr($reqPath, 7, 3)); } else { @@ -138,24 +151,43 @@ if(substr($reqPath, 0, 7) === '/error/') { if(($result & FM_HIT) === FM_HIT) { if($statusCode >= 100 && $statusCode <= 999) http_response_code($statusCode); - return; + else + $statusCode = 200; + break; } if(($result & FM_ERR) === FM_ERR) break; } + + // Make sure we have a valid error code + if($statusCode < 100) + $statusCode = 404; } -$errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404]; -http_response_code($errorInfo['code']); +if($statusCode >= 400 && $statusCode <= 599 && ob_get_length() < 1) { + $errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404]; + http_response_code($errorInfo['code']); -if(!$reqHead) { - fm_component('header', ['title' => $errorInfo['title']]); + if(!$reqHead) { + fm_component('header', ['title' => $errorInfo['title']]); ?> -
-

- <?=$errorInfo['image'];?> -
-
+
+

+ <?=$errorInfo['image'];?> +
+
$fmComponentVars ?? [], + 'raw_html' => $contents, + ]); }