diff options
Diffstat (limited to 'app/index.php')
-rw-r--r-- | app/index.php | 263 |
1 files changed, 195 insertions, 68 deletions
diff --git a/app/index.php b/app/index.php index 0f22e2f..3dc4b44 100644 --- a/app/index.php +++ b/app/index.php @@ -1,4 +1,6 @@ -<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE; ?> +<?php +header("X-Frame-Options: DENY"); +require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE; ?> <!doctype html> <html lang="en"> <head> @@ -12,7 +14,7 @@ <link href="/assets/styles.css" rel="stylesheet"> <!--<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>--> <script src="/assets/localforage.min.js"></script> - <script src="/assets/shortcuts.js"></script> + <script src="/assets/js/shortcuts.js"></script> <link rel="shortcut icon" href="/assets/logo-display.svg" type="image/svg+xml"> <link rel="manifest" href="/manifest.json" /> <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> @@ -22,8 +24,14 @@ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" media="(prefers-color-scheme: dark)"> <meta name="apple-mobile-web-app-status-bar-style" content="white-translucent" media="(prefers-color-scheme: light)"> <meta name="description" content="Mist Audio Player"> + <style> + body { + font-family: system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + } + </style> </head> <body <?php if (!str_contains($_SERVER['HTTP_USER_AGENT'], "MistNative/")): ?>class="web"<?php endif; ?>> + <script src="/assets/js/common.js"></script> <script> if (location.hash.trim() === "") location.hash = "#/albums"; @@ -36,15 +44,22 @@ <span id="loading-text">Initializing...</span> </div> - <iframe title="Player" id="player" src="player.php" style="position: fixed; top: 0; left: 320px; right: 0; width: calc(100vw - 320px); height: 64px; border-bottom: 1px solid rgba(0, 0, 0, .25); z-index: 9999;"></iframe> - <iframe title="Navigation" id="navigation" src="navigation.php" style="position: fixed; top: 0; bottom: 0; left: 0; height: 100vh; width: 320px; z-index: 9999;"></iframe> - <iframe title="UI" id="ui" style="position: fixed; top: 65px; bottom: 0; left: 320px; height: calc(100vh - 64px); width: calc(100vw - 320px); z-index: 9999;"></iframe> - <iframe title="Lyrics" id="lyrics-page" src="lyrics.php" style="display: none; position: fixed; top: 64px; bottom: 0; left: 320px; height: calc(100vh - 64px); width: calc(100vw - 320px); z-index: 9999;"></iframe> + <iframe title="Player" id="player" src="ui/player.php" style="position: fixed; top: var(--android-status-bar); left: 320px; right: 0; width: calc(100vw - 320px); height: 64px; border-bottom: 1px solid rgba(0, 0, 0, .25); z-index: 9999;"></iframe> + <iframe title="Navigation" id="navigation" src="ui/navigation.php" style="position: fixed; top: 0; bottom: var(--android-navigation-bar); left: 0; height: calc(100vh - var(--android-navigation-bar)); width: 320px; z-index: 9999;"></iframe> + <iframe title="UI" id="ui" style="position: fixed; top: calc(65px + var(--android-status-bar)); bottom: var(--android-navigation-bar); left: 320px; height: calc(100vh - 64px - var(--android-status-bar) - var(--android-navigation-bar)); width: calc(100vw - 320px); z-index: 9999;"></iframe> + <iframe title="Lyrics" id="lyrics-page" src="ui/lyrics.php" style="display: none; position: fixed; top: calc(64px + var(--android-status-bar)); bottom: var(--android-navigation-bar); left: 320px; height: calc(100vh - 64px - var(--android-status-bar) - var(--android-navigation-bar)); width: calc(100vw - 320px); z-index: 9999;"></iframe> <div id="player-mobile-container" style="background-color: white; position: fixed; left: 0; right: 0; height: 100vh; bottom: -100vh; transition: bottom 200ms; z-index: 99999;"> - <iframe title="Mobile player" style="background: #ddd; width: 100%; height: 100%;" src="player-mobile.php" id="player-mobile"></iframe> + <iframe title="Mobile player" style="background: #ddd; width: 100%; height: 100%;" src="ui/player-mobile.php" id="player-mobile"></iframe> </div> <script> + window.onerror = (_1, _2, _3, _4, err) => { + document.body.innerHTML = ""; + let pre = document.createElement("pre"); + pre.innerText = err.stack; + document.body.append(pre); + } + window.playlist = []; window.showLyrics = () => { @@ -60,7 +75,7 @@ location.hash = "#/" + name; document.getElementById("lyrics-page").style.display = "none"; document.getElementById("ui").style.display = ""; - document.getElementById("ui").src = name + ".php"; + document.getElementById("ui").src = "ui/" + name + ".php"; Array.from(document.getElementById("navigation").contentDocument.getElementsByClassName("navigation-item")).map(i => i.classList.remove("active")); document.getElementById("navigation").contentDocument.getElementById(name).classList.add("active"); } @@ -68,11 +83,11 @@ let name = location.hash.split("/")[1]; if (name === "lyrics") { - document.getElementById("ui").src = "albums.php"; + document.getElementById("ui").src = "ui/albums.php"; } else if (name === "albums" && location.hash.split("/")[2]) { - document.getElementById("ui").src = "listing.php?a=" + location.hash.split("/")[2]; + document.getElementById("ui").src = "ui/listing.php?a=" + location.hash.split("/")[2]; } else { - document.getElementById("ui").src = name + ".php"; + document.getElementById("ui").src = "ui/" + name + ".php"; } document.getElementById("navigation").onload = () => { @@ -133,6 +148,15 @@ } window.stop = () => { + if (window.MistAndroid) { + window.MistAndroid.removeNotification(); + window.MistAndroid.removeService(); + } + + if (window.discordRichPresenceData !== null) window.discordRichPresenceData = { + largeImageKey: "logo" + }; + document.title = "Mist"; window.currentSong = null; window.currentSongID = null; @@ -143,6 +167,12 @@ document.getElementById("player").onload = () => { window.playerDocument = document.getElementById("player").contentDocument; + if (window.innerWidth <= 863) { + document.getElementById("player").contentDocument.getElementById("player").classList.add("mobilified"); + } else { + document.getElementById("player").contentDocument.getElementById("player").classList.remove("mobilified"); + } + playerDocument.getElementById("player-audio").ontimeupdate = playerDocument.getElementById("player-audio").onchange = playerDocument.getElementById("player-audio").onunload = playerDocument.getElementById("player-audio").onstop = playerDocument.getElementById("player-audio").onplay = playerDocument.getElementById("player-audio").onpause = () => { updateDisplay(); } @@ -157,6 +187,8 @@ } window.showMobilePlayer = () => { + if (window.MistAndroid) window.MistAndroid.setStatusBarTheme(false); + if (window.currentSongID !== null) { document.getElementById("player-mobile-container").style.bottom = "0"; document.getElementById("lyrics-page").classList.add("mobile-show"); @@ -164,6 +196,8 @@ } window.hideMobilePlayer = () => { + if (window.MistAndroid) window.MistAndroid.setStatusBarTheme(true); + document.getElementById("player-mobile-container").style.bottom = "-100vh"; document.getElementById("lyrics-page").classList.remove("mobile-show"); } @@ -175,6 +209,7 @@ } window.currentPlaylistPosition = 0; + window.buffering = false; window.next = () => { if (window.repeat) { @@ -203,6 +238,19 @@ } function updateDisplay() { + if (window.MistAndroid && currentSong) { + window.MistAndroid.setNotificationData(currentSong.title, + currentSong.artist, + currentSong.album, + Math.round(playerDocument.getElementById("player-audio").currentTime * 1000), + Math.round(playerDocument.getElementById("player-audio").duration * 1000), + !playerDocument.getElementById("player-audio").paused), + buffering, + shuffle, + repeat + ; + } + if (playerDocument.getElementById("player-audio").paused) { document.title = "Mist"; } else if (currentSong) { @@ -211,59 +259,70 @@ document.title = "Mist"; } + if (window.discordRichPresenceData !== null && currentSong) window.discordRichPresenceData = { + largeImageKey: "https://" + location.hostname + "/albumart.php?i=" + currentSongID, + state: currentSong.title, + details: currentSong.artist, + smallImageKey: "logo", + smallImageText: "Listening on Mist", + largeImageText: currentSong.album ?? currentSong.artist + }; + playerDocument.getElementById("info").style.display = "grid"; playerDocument.getElementById("cover").style.display = "none"; - document.getElementById("player").contentWindow.navigator.mediaSession.playbackState = playerDocument.getElementById("player-audio").paused ? "paused" : "playing"; - let state = { - duration: isFinite(playerDocument.getElementById("player-audio").duration) ? playerDocument.getElementById("player-audio").duration : 0, - position: playerDocument.getElementById("player-audio").currentTime, - playbackRate: 1 - } - document.getElementById("player").contentWindow.navigator.mediaSession.setPositionState(state); - - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("play", () => { - playPause(); - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("pause", () => { - playPause(); - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("stop", () => { - stop(); - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekbackward", (e) => { - let time = e.seekOffset ?? 10; - - if (playerDocument.getElementById("player-audio").currentTime >= time) { - playerDocument.getElementById("player-audio").currentTime -= time; - } else { - playerDocument.getElementById("player-audio").currentTime = 0; + if ('mediaSession' in document.getElementById("player").contentWindow.navigator) { + document.getElementById("player").contentWindow.navigator.mediaSession.playbackState = playerDocument.getElementById("player-audio").paused ? "paused" : "playing"; + let state = { + duration: isFinite(playerDocument.getElementById("player-audio").duration) ? playerDocument.getElementById("player-audio").duration : 0, + position: playerDocument.getElementById("player-audio").currentTime, + playbackRate: 1 } - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekforward", (e) => { - let time = e.seekOffset ?? 10; + document.getElementById("player").contentWindow.navigator.mediaSession.setPositionState(state); + + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("play", () => { + playPause(); + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("pause", () => { + playPause(); + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("stop", () => { + stop(); + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekbackward", (e) => { + let time = e.seekOffset ?? 10; + + if (playerDocument.getElementById("player-audio").currentTime >= time) { + playerDocument.getElementById("player-audio").currentTime -= time; + } else { + playerDocument.getElementById("player-audio").currentTime = 0; + } + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekforward", (e) => { + let time = e.seekOffset ?? 10; - if (playerDocument.getElementById("player-audio").currentTime + time < playerDocument.getElementById("player-audio").duration) { - playerDocument.getElementById("player-audio").currentTime += time; - } else { + if (playerDocument.getElementById("player-audio").currentTime + time < playerDocument.getElementById("player-audio").duration) { + playerDocument.getElementById("player-audio").currentTime += time; + } else { + next(); + } + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekto", (e) => { + if (e.seekTime) { + playerDocument.getElementById("player-audio").currentTime = e.seekTime; + } + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("previoustrack", () => { + if (playlist[currentPlaylistPosition - 1]) { + previous(); + } else { + playerDocument.getElementById("player-audio").currentTime = 0; + } + }); + document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("nexttrack", () => { next(); - } - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("seekto", (e) => { - if (e.seekTime) { - playerDocument.getElementById("player-audio").currentTime = e.seekTime; - } - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("previoustrack", () => { - if (playlist[currentPlaylistPosition - 1]) { - previous(); - } else { - playerDocument.getElementById("player-audio").currentTime = 0; - } - }); - document.getElementById("player").contentWindow.navigator.mediaSession.setActionHandler("nexttrack", () => { - next(); - }); + }); + } if (currentPlaylistPosition === 0) { playerDocument.getElementById("btn-previous").classList.add("disabled"); @@ -342,8 +401,10 @@ if (playerDocument.getElementById("player-audio").paused) { playerDocument.getElementById("player-audio").play(); + if (window.MistAndroid) window.MistAndroid.updateNotificationAlbumArt("https://" + location.hostname + "/albumart.php?i=" + currentSongID); } else { playerDocument.getElementById("player-audio").pause(); + if (window.MistAndroid) window.MistAndroid.removeService(); } } @@ -388,6 +449,18 @@ window.toggleRepeat = () => { window.repeat = !window.repeat; + updateRepeat(); + } + + window.setRepeat = (value) => { + window.repeat = value; + updateRepeat(); + } + + window.updateRepeat = () => { + if (window.currentSong) { + updateDisplay(); + } if (window.repeat) { playerDocument.getElementById("btn-repeat-icon").src = playerDocumentMobile.getElementById("btn-repeat-icon").src = "/assets/icons/repeat-on.svg"; @@ -413,6 +486,18 @@ window.toggleShuffle = () => { window.shuffle = !window.shuffle; + updateShuffle(); + } + + window.setShuffle = (value) => { + window.shuffle = value; + updateShuffle(); + } + + window.updateShuffle = () => { + if (window.currentSong) { + updateDisplay(); + } if (window.shuffle) { window.playlist = shuffleArray(window.playlist); @@ -490,6 +575,8 @@ if (document.getElementById("ui").contentWindow.refreshQueue) document.getElementById("ui").contentWindow.refreshQueue(); if (!window.preloaded[id]) { + window.buffering = true; + if (localStorage.getItem("data-saving") === "true") { window.preloaded[id] = URL.createObjectURL(new Blob([await (await fetch("/assets/content/" + id + ".m4a")).arrayBuffer()], { type: "audio/mp4" })); } else { @@ -502,6 +589,7 @@ playerDocument.getElementById("player-audio").src = window.preloaded[id]; playerDocument.getElementById("player-audio").play(); + window.buffering = false; if (window.MistNative && localStorage.getItem("desktop-notification") === "true") { window.MistNative.notification(currentSong, await (async function() { @@ -514,14 +602,24 @@ })()); } - document.getElementById("player").contentWindow.navigator.mediaSession.metadata = new MediaMetadata({ - title: currentSong.title, - artist: currentSong.artist, - album: currentSong.album, - artwork: [ - { src: location.protocol + "//" + location.host + '/assets/content/' + currentSongID + '.jpg', sizes: playerDocument.getElementById("album-art").naturalWidth + "x" + playerDocument.getElementById("album-art").naturalHeight, type: 'image/jpeg' }, - ] - }); + if ('mediaSession' in document.getElementById("player").contentWindow.navigator) { + document.getElementById("player").contentWindow.navigator.mediaSession.metadata = new MediaMetadata({ + title: currentSong.title, + artist: currentSong.artist, + album: currentSong.album, + artwork: [ + { + src: location.protocol + "//" + location.host + '/assets/content/' + currentSongID + '.jpg', + sizes: playerDocument.getElementById("album-art").naturalWidth + "x" + playerDocument.getElementById("album-art").naturalHeight, + type: 'image/jpeg' + }, + ] + }); + } + + if (window.MistAndroid) { + window.MistAndroid.updateNotificationAlbumArt("https://" + location.hostname + "/albumart.php?i=" + currentSongID); + } } } @@ -555,15 +653,44 @@ } </script> - <iframe id="modal" src="modal.php" style="width: 100vw; height: 100vh; border: none; inset: 0; position: fixed; z-index: 99999; display: none;"></iframe> + <iframe id="modal" src="ui/modal.php" style="width: 100vw; height: 100vh; border: none; inset: 0; position: fixed; z-index: 99999; display: none;"></iframe> <script> - function openModal(title, url) { + function openModal(title, url, hideTitle) { document.getElementById("modal").style.display = ""; + + if (hideTitle) { + document.getElementById("modal").contentWindow.document.getElementById("modal-header").style.display = "none"; + } else { + document.getElementById("modal").contentWindow.document.getElementById("modal-header").style.display = ""; + } + document.getElementById("modal").contentWindow.document.getElementById("modal-title").innerText = title; document.getElementById("modal").contentWindow.document.getElementById("modal-frame").src = url; document.getElementById("modal").contentWindow.document.getElementById("modal-frame").style.height = "calc(100vh - 130px)"; document.getElementById("modal").contentWindow._modal.show(); } + + document.getElementById("modal").onload = () => { + if (localStorage.getItem("welcomed") !== "true") { + openModal("Welcome to Mist", "welcome.php", true); + } else { + if (localStorage.getItem("lastUpdate") !== "<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")) ?>|<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>") { + openModal("What's new in Mist?", "update.php", true); + } + } + } + + if (!localStorage.getItem("rich-presence")) { + localStorage.setItem("rich-presence", "true"); + } + + if (localStorage.getItem("rich-presence") === "false") { + window.discordRichPresenceData = null; + } else { + window.discordRichPresenceData = { + largeImageKey: "logo" + }; + } </script> </body> </html>
\ No newline at end of file |