summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-10-27 22:29:56 +0200
committerRaindropsSys <raindrops@equestria.dev>2023-10-27 22:29:56 +0200
commit4d4308c46d4f7801c657cc79d2243e1a81831334 (patch)
treea2e392e0af92b9a3ca3d1b5afb841640276e2294 /app
parent9f9d66afebc59c6c265c4424f7b8fb36d8876541 (diff)
downloadmist-4d4308c46d4f7801c657cc79d2243e1a81831334.tar.gz
mist-4d4308c46d4f7801c657cc79d2243e1a81831334.tar.bz2
mist-4d4308c46d4f7801c657cc79d2243e1a81831334.zip
Updated 32 files, added 279 files, deleted 3 files and renamed 14 files (automated)
Diffstat (limited to 'app')
-rw-r--r--app/.DS_Storebin0 -> 6148 bytes
-rw-r--r--app/explore.php137
-rw-r--r--app/index.php263
-rw-r--r--app/songs.php4
-rw-r--r--app/ui/albums.php (renamed from app/albums.php)16
-rw-r--r--app/ui/download.php (renamed from app/download.php)16
-rw-r--r--app/ui/explore.php44
-rw-r--r--app/ui/favorites.php (renamed from app/favorites.php)4
-rw-r--r--app/ui/info.php (renamed from app/info.php)5
-rw-r--r--app/ui/listing.php (renamed from app/listing.php)16
-rw-r--r--app/ui/lyrics.php (renamed from app/lyrics.php)16
-rw-r--r--app/ui/modal.php (renamed from app/modal.php)17
-rw-r--r--app/ui/navigation.php (renamed from app/navigation.php)26
-rw-r--r--app/ui/player-mobile.php (renamed from app/player-mobile.php)53
-rw-r--r--app/ui/player.php (renamed from app/player.php)16
-rw-r--r--app/ui/queue.php (renamed from app/queue.php)16
-rw-r--r--app/ui/search.php (renamed from app/search.php)16
-rw-r--r--app/ui/settings.php (renamed from app/settings.php)38
-rw-r--r--app/ui/songs.php5
-rw-r--r--app/ui/update.php67
-rw-r--r--app/ui/welcome.php49
21 files changed, 513 insertions, 311 deletions
diff --git a/app/.DS_Store b/app/.DS_Store
new file mode 100644
index 0000000..1848aaa
--- /dev/null
+++ b/app/.DS_Store
Binary files differ
diff --git a/app/explore.php b/app/explore.php
deleted file mode 100644
index 4887022..0000000
--- a/app/explore.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs; global $albums; ?>
-<!doctype html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport"
- content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>explore</title>
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
- <link href="/assets/dark.css" rel="stylesheet">
- <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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
- <link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
-</head>
-<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
- <div class="container">
- <br>
- <h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Explore</h2>
-
- <form action="search.php">
- <div style="margin-left: 10px;" class="input-group mb-3">
- <input name="q" type="text" id="search" class="form-control" placeholder="Search on Mist">
- <button class="btn btn-outline-secondary" type="submit" id="btn-search">Search</button>
- </div>
- </form>
-
- <hr style="margin-left: 10px;">
-
- <?php if (count($songs) === 0 && count($albums) === 0): ?>
- <div class="text-muted" style="position: fixed; display: flex; inset: 0; align-items: center; justify-content: center;">
- <div style="text-align: center;">
- <img class="icon" src="/assets/logo-transparent.svg" style="filter: grayscale(1) invert(1); width: 96px; height: 96px;" alt="">
- <h4 style="opacity: .75;">Upload music to this server</h4>
- <p style="max-width: 300px; margin-left: auto; margin-right: auto;">Add millions of songs and let your users play them whenever they want.</p>
- </div>
- </div>
- <?php endif; ?>
- <div id="album-grid" style="display: grid; grid-template-columns: repeat(5, 1fr);">
- <?php global $albums;
-
- uasort($albums, function ($a, $b) {
- return strcmp($a["title"], $b["title"]);
- });
-
- uasort($albums, function ($a, $b) {
- return strcmp($a["artist"], $b["artist"]);
- });
-
- foreach ($albums as $id => $album): ?>
- <a id="album-<?= $id ?>" data-item-track="<?= $album["title"] ?>" data-item-artist="<?= $album["artist"] ?>" href="listing.php?a=<?= $id ?>" style="padding: 10px; color: inherit; text-decoration: inherit;" class="album">
- <img class="album-list-art" alt="" src="/assets/content/<?= $id ?>.jpg" style="width: 100%; aspect-ratio: 1; border-radius: 5px; margin-bottom: 5px;">
- <div class="album-list-item" style="max-width: calc(80vw / 5); white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;"><?= $album["title"] ?></div>
- <div class="album-list-item" style="max-width: calc(80vw / 5); opacity: .5; white-space: nowrap; overflow: hidden !important; text-overflow: ellipsis;"><?= $album["artist"] ?></div>
- </a>
- <?php endforeach; ?>
- </div>
- <div id="search-results" style="display: none; grid-template-columns: repeat(5, 1fr);"></div>
- <?php global $songs; displayList($songs); ?>
- <div class="list-group" style="margin-left: 10px; margin-top: 20px; display: none;" id="search-results-2"></div>
- </div>
-
- <script>
- let items = Array.from(document.getElementsByClassName("album")).map(i => { return { title: i.getAttribute("data-item-track"), artist: i.getAttribute("data-item-artist"), id: i.id } });
-
- const fuse = new Fuse(items, {
- keys: [
- {
- name: 'title',
- weight: 1
- },
- {
- name: 'artist',
- weight: .5
- }
- ]
- });
-
- let items2 = Array.from(document.getElementsByClassName("track")).map(i => { return { title: i.getAttribute("data-item-track"), artist: i.getAttribute("data-item-artist"), id: i.id } });
-
- const fuse2 = new Fuse(items2, {
- keys: [
- {
- name: 'title',
- weight: 1
- },
- {
- name: 'artist',
- weight: .5
- }
- ]
- });
-
- function updateFilter() {
- let query = document.getElementById("filter").value.trim();
-
- if (query !== "") {
- document.getElementById("search-results").style.display = "grid";
- document.getElementById("album-grid").style.display = "none";
-
- let results = fuse.search(query);
- document.getElementById("search-results").innerHTML = "";
-
- for (let result of results) {
- document.getElementById("search-results").innerHTML += document.getElementById(result.item.id).outerHTML;
- }
-
- document.getElementById("search-results-2").style.display = "flex";
- document.getElementById("main-list").style.display = "none";
-
- let results2 = fuse2.search(query);
- document.getElementById("search-results-2").innerHTML = "";
-
- for (let result of results2) {
- document.getElementById("search-results-2").innerHTML += document.getElementById(result.item.id).outerHTML;
- }
- } else {
- document.getElementById("search-results").style.display = "none";
- document.getElementById("album-grid").style.display = "grid";
- document.getElementById("search-results-2").style.display = "none";
- document.getElementById("main-list").style.display = "flex";
- }
- }
- </script>
-
- <br><br>
-</body>
-</html> \ No newline at end of file
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
diff --git a/app/songs.php b/app/songs.php
deleted file mode 100644
index 086df66..0000000
--- a/app/songs.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-unset($_GET["a"]);
-require_once "./listing.php"; \ No newline at end of file
diff --git a/app/albums.php b/app/ui/albums.php
index a5fcfe5..e383f81 100644
--- a/app/albums.php
+++ b/app/ui/albums.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/albums";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -13,16 +18,11 @@
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div class="container">
<br>
<h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Albums<input placeholder="Filter" id="filter" class="form-control" style="width: 256px; float: right;" onchange="updateFilter();" onkeyup="updateFilter();"></h2>
diff --git a/app/download.php b/app/ui/download.php
index dd1321c..13f76b0 100644
--- a/app/download.php
+++ b/app/ui/download.php
@@ -1,4 +1,4 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs;
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs;
if (!isset($_GET["i"]) || !isset($songs[$_GET["i"]])) {
die();
@@ -27,6 +27,11 @@ function getSize($bytes) {
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -38,16 +43,11 @@ function getSize($bytes) {
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform" style="background-color: transparent !important;">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div style="padding: 1rem;">
<p>
<?= $song["artist"] ?> — <?= $song["title"] ?><br>
diff --git a/app/ui/explore.php b/app/ui/explore.php
new file mode 100644
index 0000000..7edfdf1
--- /dev/null
+++ b/app/ui/explore.php
@@ -0,0 +1,44 @@
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs; global $albums; ?>
+<!doctype html>
+<html lang="en">
+<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/explore";
+ }
+ </script>
+ <meta charset="UTF-8">
+ <meta name="viewport"
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <title>explore</title>
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/assets/dark.css" rel="stylesheet">
+ <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/fuse.min.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
+ <link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
+</head>
+<body class="crossplatform">
+ <script src="/assets/js/common.js"></script>
+ <div class="container">
+ <br>
+ <h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Explore</h2>
+
+ <form action="search.php">
+ <div style="width: calc(100% - 20px); margin-left: 10px;" class="input-group mb-3">
+ <input name="q" type="text" id="search" class="form-control" placeholder="Search on Mist">
+ <button class="btn btn-outline-secondary" type="submit" id="btn-search">Search</button>
+ </div>
+ </form>
+
+ <hr style="width: calc(100% - 20px); margin-left: 10px;">
+
+ <p style="margin-left: 10px;">To search for content on Mist, start by typing the name of a song, artist or album. Any corresponding results will show up. Should anything you need be missing, you can contact your administrator to ask for more content to be added.</p>
+ </div>
+
+ <br><br>
+</body>
+</html> \ No newline at end of file
diff --git a/app/favorites.php b/app/ui/favorites.php
index 9690523..f1ebe30 100644
--- a/app/favorites.php
+++ b/app/ui/favorites.php
@@ -1,5 +1,6 @@
<?php
+header("X-Frame-Options: SAMEORIGIN");
require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php";
global $songs; global $favorites;
@@ -8,7 +9,8 @@ $favoritesList = true;
$list = [];
foreach ($favorites as $id) {
- $list[$id] = $songs[$id];
+ if (isset($songs[$id])) $list[$id] = $songs[$id];
}
+unset($_GET["a"]);
require_once "listing.php"; \ No newline at end of file
diff --git a/app/info.php b/app/ui/info.php
index cfc7bc2..fd4fad5 100644
--- a/app/info.php
+++ b/app/ui/info.php
@@ -1,4 +1,4 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs;
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $songs;
if (!isset($_GET["i"]) || !isset($songs[$_GET["i"]])) {
die();
@@ -87,6 +87,7 @@ function getChannelConfiguration($c) {
<!doctype html>
<html lang="en">
<head>
+ <script src="/assets/js/common.js"></script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -98,7 +99,7 @@ function getChannelConfiguration($c) {
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform" style="background-color: transparent !important;">
diff --git a/app/listing.php b/app/ui/listing.php
index 9d50178..9ad227f 100644
--- a/app/listing.php
+++ b/app/ui/listing.php
@@ -1,4 +1,4 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE; global $library;
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE; global $library;
if (isset($list)) {
$presetList = true;
@@ -41,6 +41,11 @@ if (!$presetList) {
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/songs";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -51,17 +56,12 @@ if (!$presetList) {
<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>
<script src="/assets/fuse.min.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<?php if ($hasAlbum): ?>
<script>
window.parent.location.hash = "#/albums/<?= $_GET["a"] ?>";
diff --git a/app/lyrics.php b/app/ui/lyrics.php
index 4a7537d..bd24832 100644
--- a/app/lyrics.php
+++ b/app/ui/lyrics.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/lyrics";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -12,7 +17,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 id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
<style>
.synced-lyrics-item {
@@ -39,12 +44,7 @@
</style>
</head>
<body class="crossplatform" style="background-color: transparent !important;">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div id="lyrics-outer">
<div id="not-playing" style="position: fixed; inset: 16px; display: flex; align-items: center; justify-content: center; opacity: .5; text-align: center;">
Lyrics will appear here when you start playing a song. If supported, they will also scroll as the song plays.
diff --git a/app/modal.php b/app/ui/modal.php
index b939996..b8f1cfb 100644
--- a/app/modal.php
+++ b/app/ui/modal.php
@@ -1,6 +1,12 @@
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -12,20 +18,15 @@
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform" style="background-color: transparent !important;">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div class="modal fade" id="modal">
<div class="modal-dialog">
<div class="modal-content">
- <div class="modal-header">
+ <div class="modal-header" id="modal-header">
<h4 class="modal-title" id="modal-title">Title</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
diff --git a/app/navigation.php b/app/ui/navigation.php
index 00d1457..9344791 100644
--- a/app/navigation.php
+++ b/app/ui/navigation.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; global $_PROFILE ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -13,22 +18,17 @@
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
<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 id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
-<body class="crossplatform navigation-body">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
- <div class="navigation-container-inner container" style="margin-left: 20px;">
+<body class="crossplatform navigation-body" style="overflow: hidden;">
+ <script src="/assets/js/common.js"></script>
+ <div class="navigation-container-inner container" style="margin-left: 20px; overflow: hidden;">
<div id="navigation-left">
- <div id="navigation-gradient" style="background-image: radial-gradient(circle, rgba(122,195,245,.25) 0%, rgba(255,255,255,0) 75%); top: -256px; left: 0; right: 0; height: 512px; position: fixed; z-index: -1;"></div>
- <div id="navigation-top" style="-webkit-app-region: drag; position: fixed; top: 0; right: 0; left: 0; height: 128px;"></div>
+ <div id="navigation-gradient" style="background-image: radial-gradient(circle, rgba(122,195,245,.25) 0%, rgba(255,255,255,0) 75%); top: -256px; left: 0; right: 0; height: calc(512px + var(--android-status-bar)); position: fixed; z-index: -1;"></div>
+ <div id="navigation-top" style="-webkit-app-region: drag; position: fixed; top: 0; right: 0; left: 0; height: calc(128px + var(--android-status-bar));"></div>
<br><br><br>
- <h3 style="margin-left: 10px;">
+ <h3 style="margin-top: var(--android-status-bar); margin-left: 10px;">
<img src="/assets/logo-display.png" alt="" style="width: 32px; height: 32px; vertical-align: middle;">
<span style="vertical-align: middle;" class="navigation-desktop">&nbsp;Mist</span>
</h3>
diff --git a/app/player-mobile.php b/app/ui/player-mobile.php
index 8308eda..5266961 100644
--- a/app/player-mobile.php
+++ b/app/ui/player-mobile.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -11,7 +16,7 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<link href="/assets/dark.css" rel="stylesheet">
<link href="/assets/styles.css" rel="stylesheet">
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<style>
.player-btn {
filter: invert(1);
@@ -20,16 +25,36 @@
</style>
</head>
<body>
- <div id="act-1" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; top: 0; left: 0; right: 0; height: 20px;"></div>
- <div id="act-2" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; left: 0; right: 0; height: 20px;"></div>
- <div id="act-2" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; left: 0; top: 0; width: 20px;"></div>
- <div id="act-2" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; right: 0; top: 0; width: 20px;"></div>
+ <script>
+ let style = document.createElement("style");
+
+ if (window.MistAndroid) {
+ style.innerHTML =
+ `:root {
+ --android-navigation-bar: ${window.MistAndroid.getNavigationBarHeight()}px;
+ --android-status-bar: ${window.MistAndroid.getStatusBarHeight()}px;
+ }`;
+ } else {
+ style.innerHTML =
+ `:root {
+ --android-navigation-bar: 0px;
+ --android-status-bar: 0px;
+ }`;
+ }
+
+ document.head.append(style);
+ </script>
+ <div id="act-1" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; top: 0; left: 0; right: 0; height: calc(20px + var(--android-status-bar));"></div>
+ <div id="act-2" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; left: 0; right: 0; height: calc(20px + var(--android-navigation-bar))"></div>
+ <div id="act-3" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; left: 0; top: 0; width: 20px;"></div>
+ <div id="act-4" onclick="window.parent.hideMobilePlayer();" style="position: fixed; z-index: 9999999; bottom: 0; right: 0; top: 0; width: 20px;"></div>
+ <div id="android" style="position: fixed; z-index: 9999999; bottom: 0; right: 0; left: 0; height: var(--android-navigation-bar); border-top: 1px solid rgba(255, 255, 255, .1);"></div>
<div id="album-art-bg" style="position: fixed;inset: 0;background-position: center;background-size: cover; z-index: 5;"></div>
<div id="album-art-bg2" style="background-color: rgba(0, 0, 0, .1); z-index: 10; position: fixed;inset: 0; backdrop-filter: blur(100px);"></div>
- <div id="player" class="bg-white mobile-player" style="background-color: transparent !important; color: white;position: fixed; bottom: 0; left: 0; right: 0; height: 64px; z-index: 9999;">
+ <div id="player" class="bg-white mobile-player" style="background-color: transparent !important; color: white;position: fixed; bottom: var(--android-navigation-bar); left: 0; right: 0; height: 64px; z-index: 9999;">
<div class="container" style="display: grid; grid-template-columns: 1fr 1.5fr 1fr;">
- <div id="buttons" style="height: 48px;position: fixed;width: max-content;left: 0;right: 0;margin: 8px auto;bottom: 30px;">
+ <div id="buttons" style="height: 48px;position: fixed;width: max-content;left: 0;right: 0;margin: 8px auto;bottom: calc(30px + var(--android-navigation-bar));">
<span onclick="window.parent.toggleShuffle();" class="player-btn" style="border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; height: 48px; width: 48px;" id="btn-shuffle">
<img alt="" src="/assets/icons/shuffle-off.svg" style="pointer-events: none; width: 32px; height: 32px;" id="btn-shuffle-icon">
</span>
@@ -46,28 +71,28 @@
<img alt="" src="/assets/icons/repeat-off.svg" style="pointer-events: none; width: 32px; height: 32px;" id="btn-repeat-icon">
</span>
</div>
- <div style="position: fixed;top: 30px;left: 30px;right: 30px;">
+ <div style="position: fixed;top: calc(30px + var(--android-status-bar));left: 30px;right: 30px;">
<img alt="" id="album-art" style="border-radius: 5px; background-color: rgba(0, 0, 0, .1); height: 48px !important; width: 48px !important;">
- <div id="info-grid" style="display: grid;grid-template-rows: 22px 22px;position: fixed;top: 30px;left: 88px;">
+ <div id="info-grid" style="display: grid;grid-template-rows: 22px 22px;position: fixed;top: calc(30px + var(--android-status-bar));left: 88px;">
<div id="info-grid-title" style="white-space: nowrap;overflow: hidden !important;text-overflow: ellipsis;display: flex;font-size: 0.91rem;align-items: end;text-align: left;justify-content: left; opacity: .75;"><span id="title">Title</span></div>
<div id="info-grid-info" style="white-space: nowrap;overflow: hidden !important;text-overflow: ellipsis;display: flex;font-size: 0.91rem;align-items: start;text-align: left;justify-content: left;opacity: .35;"><span id="artist">Artist</span><span style="display: none;">&nbsp;—&nbsp;<span id="album">Album</span></span></div>
- <div id="info-grid-time" style="font-size: 9px;opacity: .5;margin-left: 2px;margin-right: 2px;position: fixed;bottom: 125px;left: 30px;right: 30px;">
+ <div id="info-grid-time" style="font-size: 9px;opacity: .5;margin-left: 2px;margin-right: 2px;position: fixed;bottom: calc(125px + var(--android-navigation-bar));left: 30px;right: 30px;">
<span id="elapsed-time">0:00</span>
<span id="remaining-time" style="float: right;">-0:00</span>
</div>
- <div style="background-color: rgba(255, 255, 255, .05);position: fixed;bottom: 150px;left: 30px;right: 30px;border-radius: 999px;" id="seekbar-container">
+ <div style="background-color: rgba(255, 255, 255, .05);position: fixed;bottom: calc(150px + var(--android-navigation-bar));left: 30px;right: 30px;border-radius: 999px;" id="seekbar-container">
<div id="seekbar" style="pointer-events: none;background-color: rgba(255, 255, 255, .25); width: 0; height: 8px;border-radius: 999px;"></div>
</div>
</div>
</div>
<div style="text-align: right; display: flex; align-items: center; justify-content: right;" id="badges">
<span id="badge-lossy" style="display: none;"></span>
- <span id="badge-cd" style="display: block;border: 1px solid transparent;color: rgba(255, 255, 255, .75);background-color: rgba(255, 255, 255, .25);padding: 2px 5px;border-radius: 5px;font-size: 12px;position: fixed;margin-left: auto;margin-right: auto;width: max-content;left: 0;right: 0;bottom: 120px;">
+ <span id="badge-cd" style="display: block;border: 1px solid transparent;color: rgba(255, 255, 255, .75);background-color: rgba(255, 255, 255, .25);padding: 2px 5px;border-radius: 5px;font-size: 12px;position: fixed;margin-left: auto;margin-right: auto;width: max-content;left: 0;right: 0;bottom: calc(120px + var(--android-navigation-bar));">
<span style="display: grid; grid-template-columns: max-content max-content">
<span><img src="/assets/icons/lossless.svg" alt="" class="player-badge-icon" style="filter: invert(1); opacity: .75;">Lossless</span>
</span>
</span>
- <span id="badge-hires" style="display: block;border: 1px solid transparent;color: rgba(255, 255, 255, .75);background-color: rgba(255, 255, 255, .25);padding: 2px 5px;border-radius: 5px;font-size: 12px;position: fixed;margin-left: auto;margin-right: auto;width: max-content;left: 0;right: 0;bottom: 120px;">
+ <span id="badge-hires" style="display: block;border: 1px solid transparent;color: rgba(255, 255, 255, .75);background-color: rgba(255, 255, 255, .25);padding: 2px 5px;border-radius: 5px;font-size: 12px;position: fixed;margin-left: auto;margin-right: auto;width: max-content;left: 0;right: 0;bottom: calc(120px + var(--android-navigation-bar));">
<span style="display: grid; grid-template-columns: max-content max-content">
<span><img src="/assets/icons/lossless.svg" alt="" class="player-badge-icon" style="filter: invert(1); opacity: .75;">Hi-Res Lossless</span>
</span>
diff --git a/app/player.php b/app/ui/player.php
index e2334ce..ea60889 100644
--- a/app/player.php
+++ b/app/ui/player.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -11,16 +16,11 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<link href="/assets/dark.css" rel="stylesheet">
<link href="/assets/styles.css" rel="stylesheet">
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div id="player" class="bg-white desktop-player" style="position: fixed; bottom: 0; left: 0; right: 0; height: 64px; z-index: 9999;">
<div id="desktop-player-action" onclick="window.parent.showMobilePlayer();" style="display: none;"></div>
<audio id="player-audio"></audio>
diff --git a/app/queue.php b/app/ui/queue.php
index 86fda0e..c4403a4 100644
--- a/app/queue.php
+++ b/app/ui/queue.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/queue";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -13,16 +18,11 @@
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div class="container">
<br>
<h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Queue</h2>
diff --git a/app/search.php b/app/ui/search.php
index 2f5f164..7d9fbba 100644
--- a/app/search.php
+++ b/app/ui/search.php
@@ -1,4 +1,4 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php";
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php";
if (!isset($_GET["q"]) || trim($_GET["q"]) === "" || trim(preg_replace("/ +/m", " ", preg_replace("/[^a-z\d ]/m", " ", strtolower($_GET["q"])))) === "") {
header("Location: explore.php");
@@ -9,6 +9,11 @@ if (!isset($_GET["q"]) || trim($_GET["q"]) === "" || trim(preg_replace("/ +/m",
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/explore";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -20,16 +25,11 @@ if (!isset($_GET["q"]) || trim($_GET["q"]) === "" || trim(preg_replace("/ +/m",
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div class="container">
<br>
<h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Search results for "<?= strip_tags($_GET["q"]) ?>"</h2>
diff --git a/app/settings.php b/app/ui/settings.php
index a80fad1..e6dc9ba 100644
--- a/app/settings.php
+++ b/app/ui/settings.php
@@ -1,7 +1,12 @@
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
<!doctype html>
<html lang="en">
<head>
+ <script>
+ if (typeof window.parent.openModal === "undefined") {
+ location.href = "/app/#/settings";
+ }
+ </script>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@@ -13,16 +18,11 @@
<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/fuse.min.js"></script>
- <script src="/assets/shortcuts.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
<link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
</head>
<body class="crossplatform">
- <script>
- if (navigator.userAgent.includes("MistNative/darwin") || navigator.userAgent.includes("MistNative/win32")) {
- document.getElementById("native-css").disabled = false;
- document.body.classList.remove("crossplatform");
- }
- </script>
+ <script src="/assets/js/common.js"></script>
<div class="container">
<br>
<h2 style="margin-top: 10px; margin-bottom: 20px; margin-left: 10px;">Settings</h2>
@@ -54,6 +54,28 @@
</script>
<?php endif; ?>
+ <?php if (str_contains($_SERVER['HTTP_USER_AGENT'], "MistNative/")): ?>
+ <div class="form-check form-switch" style="margin-top: 10px;">
+ <input onchange="saveRP();" class="form-check-input" type="checkbox" role="switch" id="rich-presence">
+ <label class="form-check-label" for="desktop-notification">Show the song you are listening to on Discord</label>
+ <div class="text-muted small">Using Discord Rich Presence, Mist can display on Discord the song you are currently listening to. You need to have the Discord desktop app installed and running on your computer for this to work.</div>
+ </div>
+ <script>
+ if (localStorage.getItem("rich-presence") === "true") document.getElementById("rich-presence").checked = true;
+ function saveRP() {
+ localStorage.setItem("rich-presence", document.getElementById("rich-presence").checked ? "true" : "false");
+
+ if (localStorage.getItem("rich-presence") === "false") {
+ window.parent.discordRichPresenceData = null;
+ } else {
+ window.parent.discordRichPresenceData = {
+ largeImageKey: "logo"
+ };
+ }
+ }
+ </script>
+ <?php endif; ?>
+
<hr>
<?php if (str_contains($_SERVER['HTTP_USER_AGENT'], "MistNative/")): ?>
<a onclick="window.parent.MistNative.about();" href="#">About Mist</a>
diff --git a/app/ui/songs.php b/app/ui/songs.php
new file mode 100644
index 0000000..cc81f3b
--- /dev/null
+++ b/app/ui/songs.php
@@ -0,0 +1,5 @@
+<?php
+
+header("X-Frame-Options: SAMEORIGIN");
+unset($_GET["a"]);
+require_once "./listing.php"; \ No newline at end of file
diff --git a/app/ui/update.php b/app/ui/update.php
new file mode 100644
index 0000000..1117e95
--- /dev/null
+++ b/app/ui/update.php
@@ -0,0 +1,67 @@
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<!doctype html>
+<html lang="en">
+<head>
+ <script>
+ if (typeof window.parent.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
+ <meta charset="UTF-8">
+ <meta name="viewport"
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <title>update</title>
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/assets/dark.css" rel="stylesheet">
+ <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/fuse.min.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
+ <link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
+</head>
+<body class="crossplatform" style="background-color: transparent !important;">
+ <script src="/assets/js/common.js"></script>
+ <div style="padding: 1rem;">
+ <div style="text-align: center;">
+ <h2 style="margin-top: 30px;">What's new in Mist?</h2>
+
+ <div style="text-align: left; margin-top: 50px;">
+ <div style="display: grid; grid-template-columns: 48px 1fr; grid-gap: 20px; margin-bottom: 20px;">
+ <img src="/assets/icons/notes-security.svg" style="width: 48px;" class="icon" alt="">
+ <div>
+ <div><b>Enhanced security</b></div>
+ <div>Listening to your favorite songs shouldn't come at the expense of your security and your privacy. Mist now includes protections against the most common forms of attacks.</div>
+ </div>
+ </div>
+ <div style="display: grid; grid-template-columns: 48px 1fr; grid-gap: 20px; margin-bottom: 20px;">
+ <img src="/assets/icons/notes-connect.svg" style="width: 48px;" class="icon" alt="">
+ <div>
+ <div><b>Mist is now on Discord</b></div>
+ <div>If you are using the desktop app, Mist can now use Discord Rich Presence to show the music you are playing to all of your friends. You will also need the Discord desktop app.</div>
+ </div>
+ </div>
+ <div style="display: grid; grid-template-columns: 48px 1fr; grid-gap: 20px; margin-bottom: 20px;">
+ <img src="/assets/icons/notes-android.svg" style="width: 48px;" class="icon" alt="">
+ <div>
+ <div><b>Native Android application</b></div>
+ <div>You can now quit using the Progressive Web App, and instead use the official Mist Android app. Lower battery and resource usage, along with better OS integrations.</div>
+ </div>
+ </div>
+ </div>
+
+ <a style="margin-top: 50px; margin-bottom: 30px; display: block;" class="btn btn-primary" onclick="localStorage.setItem('lastUpdate', '<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")) ?>|<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>'); window.parent._modal.hide();">Continue</a>
+ </div>
+ </div>
+
+ <script>
+ window.sizeInterval = setInterval(() => {
+ if (document.body.clientHeight > 0) {
+ clearInterval(sizeInterval);
+ window.parent.document.getElementById("modal-frame").style.height = document.body.clientHeight + "px";
+ }
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/app/ui/welcome.php b/app/ui/welcome.php
new file mode 100644
index 0000000..800da74
--- /dev/null
+++ b/app/ui/welcome.php
@@ -0,0 +1,49 @@
+<?php header("X-Frame-Options: SAMEORIGIN"); require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/session.php"; ?>
+<!doctype html>
+<html lang="en">
+<head>
+ <script>
+ if (typeof window.parent.parent.openModal === "undefined") {
+ location.href = "/app/";
+ }
+ </script>
+ <meta charset="UTF-8">
+ <meta name="viewport"
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <title>welcome</title>
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/assets/dark.css" rel="stylesheet">
+ <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/fuse.min.js"></script>
+ <script src="/assets/js/shortcuts.js"></script>
+ <link id="native-css" href="/assets/native.css" rel="stylesheet" disabled>
+</head>
+<body class="crossplatform" style="background-color: transparent !important;">
+ <script src="/assets/js/common.js"></script>
+ <div style="padding: 1rem;">
+ <div style="text-align: center;">
+ <img src="/assets/logo-display.png" alt="Logo" style="width: 96px; margin-bottom: 15px; margin-top: 30px;">
+ <h2>Welcome to<br>Mist</h2>
+
+ <h4 style="margin-top: 30px; font-weight: normal;">The best way to discover and rediscover your favorite music.</h4>
+
+ <p style="margin-top: 100px;" class="small text-muted">Your searches, favorites and library help improve the service. The administrators can provide you with more information about how your data is managed.</p>
+ <p class="small text-muted">With your Equestria.dev Account, you will be able to sign in to available services. Equestria.dev records certain data for security, support and reporting purposes. <a target="_blank" href="https://equestria.dev/legal/privacy">See how this data is managed.</a></p>
+
+ <a style="margin-bottom: 30px; display: block;" class="btn btn-primary" onclick="localStorage.setItem('welcomed', 'true'); localStorage.setItem('lastUpdate', '<?= trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version")) ?>|<?= trim(file_exists("/opt/spotify/build.txt") ? file_get_contents("/opt/spotify/build.txt") : "trunk") ?>'); window.parent._modal.hide();">Continue</a>
+ </div>
+ </div>
+
+ <script>
+ window.sizeInterval = setInterval(() => {
+ if (document.body.clientHeight > 0) {
+ clearInterval(sizeInterval);
+ window.parent.document.getElementById("modal-frame").style.height = document.body.clientHeight + "px";
+ }
+ });
+ </script>
+</body>
+</html> \ No newline at end of file