summaryrefslogtreecommitdiff
path: root/app/index.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/index.php')
-rw-r--r--app/index.php263
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