|
@@ -5,21 +5,22 @@
|
|
<head>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta charset="UTF-8">
|
|
<meta name="theme-color" content="#232324">
|
|
<meta name="theme-color" content="#232324">
|
|
- <link rel="stylesheet" href="../script/tocas/tocas.css">
|
|
|
|
|
|
+ <link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
|
<link rel="icon" type="image/png" href="./img/small_icon.png">
|
|
<link rel="icon" type="image/png" href="./img/small_icon.png">
|
|
- <script src="../script/tocas/tocas.js"></script>
|
|
|
|
<script src="../script/jquery.min.js"></script>
|
|
<script src="../script/jquery.min.js"></script>
|
|
|
|
+ <script src="../script/semantic/semantic.min.js"></script>
|
|
<script src="../script/ao_module.js"></script>
|
|
<script src="../script/ao_module.js"></script>
|
|
<style>
|
|
<style>
|
|
body{
|
|
body{
|
|
padding:0px !important;
|
|
padding:0px !important;
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
height:100%;
|
|
height:100%;
|
|
|
|
+ background-color: transparent !important;
|
|
}
|
|
}
|
|
|
|
|
|
.coloredBackground{
|
|
.coloredBackground{
|
|
- background: rgb(58,58,58);
|
|
|
|
- background: linear-gradient(180deg, rgba(58,58,58,1) 2%, rgba(34,34,34,1) 57%, rgba(0,0,0,1) 100%);
|
|
|
|
|
|
+ background: rgb(253,255,254);
|
|
|
|
+ background: linear-gradient(321deg, rgba(253,255,254,1) 29%, rgba(240,250,255,1) 100%);
|
|
}
|
|
}
|
|
|
|
|
|
html, body { height: 100%; width: 100%; margin: 0; }
|
|
html, body { height: 100%; width: 100%; margin: 0; }
|
|
@@ -33,6 +34,10 @@
|
|
margin-left:0px !important;
|
|
margin-left:0px !important;
|
|
margin-right:0px !important;
|
|
margin-right:0px !important;
|
|
width:100% !important;
|
|
width:100% !important;
|
|
|
|
+ position: relative;
|
|
|
|
+ color: #404147;
|
|
|
|
+ background-color: #f9f9f9 !important;
|
|
|
|
+ overflow: hidden;
|
|
}
|
|
}
|
|
.parkLeft{
|
|
.parkLeft{
|
|
position:absolute !important;
|
|
position:absolute !important;
|
|
@@ -52,12 +57,25 @@
|
|
box-shadow: 2px 2px 2px 2px #bfbfbf;
|
|
box-shadow: 2px 2px 2px 2px #bfbfbf;
|
|
}
|
|
}
|
|
.playBtn{
|
|
.playBtn{
|
|
- color:#4b75ff !important;
|
|
|
|
|
|
+ color: white !important;
|
|
|
|
+ transition: opacity 0.1s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ #playpauseBtn{
|
|
|
|
+ width: 66px;
|
|
|
|
+ height: 66px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .playerControlWrapper .sidebuttons{
|
|
|
|
+ background-color: white !important;
|
|
|
|
+ }
|
|
|
|
+ .playerControlWrapper .white.icon.button:hover{
|
|
|
|
+ opacity: 0.6;
|
|
}
|
|
}
|
|
.playerControlWrapper{
|
|
.playerControlWrapper{
|
|
text-align: center;
|
|
text-align: center;
|
|
position:absolute;
|
|
position:absolute;
|
|
- bottom:50px;
|
|
|
|
|
|
+ margin-top: 3rem;
|
|
width:100% !important;
|
|
width:100% !important;
|
|
}
|
|
}
|
|
.rightPaddedOprButtons{
|
|
.rightPaddedOprButtons{
|
|
@@ -66,9 +84,9 @@
|
|
top:3px;
|
|
top:3px;
|
|
}
|
|
}
|
|
.modeEnabled{
|
|
.modeEnabled{
|
|
- background-color:#4b75ff !important;
|
|
|
|
|
|
+ background-color: #186ed2 !important;
|
|
color:white !important;
|
|
color:white !important;
|
|
- border: 1px solid #3d5fd1 !important;
|
|
|
|
|
|
+ border: 0px solid transparent !important;
|
|
}
|
|
}
|
|
#volControlOverlay{
|
|
#volControlOverlay{
|
|
background-color: rgba(255,255,255,0.01);
|
|
background-color: rgba(255,255,255,0.01);
|
|
@@ -85,12 +103,13 @@
|
|
display:inline-box;
|
|
display:inline-box;
|
|
left:5px;
|
|
left:5px;
|
|
top:5px;
|
|
top:5px;
|
|
- color:white;
|
|
|
|
|
|
+ color:#77767b;
|
|
height:22px;
|
|
height:22px;
|
|
text-overflow: ellipsis;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
width: 100%;
|
|
width: 100%;
|
|
white-space: nowrap;
|
|
white-space: nowrap;
|
|
|
|
+ font-weight: bold;
|
|
}
|
|
}
|
|
.durationDisplay{
|
|
.durationDisplay{
|
|
position:absolute;
|
|
position:absolute;
|
|
@@ -99,22 +118,25 @@
|
|
padding-right:5px;
|
|
padding-right:5px;
|
|
padding-bottom:5px;
|
|
padding-bottom:5px;
|
|
margin: 0px !important;
|
|
margin: 0px !important;
|
|
|
|
+ color: #77767b;
|
|
}
|
|
}
|
|
.bottomBackground{
|
|
.bottomBackground{
|
|
- background-color: rgba(48,48,48,0.95);
|
|
|
|
|
|
+ background-color: white;
|
|
|
|
+ position:relative;
|
|
height:58px;
|
|
height:58px;
|
|
width:100%;
|
|
width:100%;
|
|
}
|
|
}
|
|
.sameDirFileList{
|
|
.sameDirFileList{
|
|
width:100%;
|
|
width:100%;
|
|
height:calc(100% - 220px) !important;
|
|
height:calc(100% - 220px) !important;
|
|
- background-color:rgba(52,52,52,0.9);
|
|
|
|
|
|
+ background-color:rgba(243, 243, 243, 0.8);
|
|
overflow-y:auto;
|
|
overflow-y:auto;
|
|
overflow-x:hidden;
|
|
overflow-x:hidden;
|
|
}
|
|
}
|
|
|
|
+
|
|
@supports ((-webkit-backdrop-filter: blur(2em)) or (backdrop-filter: blur(2em))) {
|
|
@supports ((-webkit-backdrop-filter: blur(2em)) or (backdrop-filter: blur(2em))) {
|
|
.sameDirFileList {
|
|
.sameDirFileList {
|
|
- background-color:rgba(52,52,52,0.5);
|
|
|
|
|
|
+ background-color:rgba(240, 240, 240, 0.5);
|
|
-webkit-backdrop-filter: blur(2em);
|
|
-webkit-backdrop-filter: blur(2em);
|
|
backdrop-filter: blur(2em);
|
|
backdrop-filter: blur(2em);
|
|
}
|
|
}
|
|
@@ -123,50 +145,55 @@
|
|
.listitem{
|
|
.listitem{
|
|
border-bottom: 1px solid #404040;
|
|
border-bottom: 1px solid #404040;
|
|
padding: 12px;
|
|
padding: 12px;
|
|
- color:white;
|
|
|
|
|
|
+ color:rgb(43, 43, 43);
|
|
font-size:120%;
|
|
font-size:120%;
|
|
cursor:pointer;
|
|
cursor:pointer;
|
|
}
|
|
}
|
|
.listitem:hover{
|
|
.listitem:hover{
|
|
- background-color:#545454;
|
|
|
|
|
|
+ background-color:#eff1f3;
|
|
}
|
|
}
|
|
.listitem.selected{
|
|
.listitem.selected{
|
|
- background-color:#5e5e5e;
|
|
|
|
|
|
+ background-color:#eff1f3;
|
|
|
|
+ }
|
|
|
|
+ .noradius{
|
|
|
|
+ border-radius: 0px !important;
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|
|
</head>
|
|
</head>
|
|
<body>
|
|
<body>
|
|
- <div id="playerUI" class="playerInterface ts container">
|
|
|
|
|
|
+ <div id="playerUI" class="playerInterface ui container">
|
|
|
|
+ <img id="Albumnart" class="ui fluid image" src="img/nothumb.png" style="position: absolute; top: -75px; opacity: 0.3; pointer-events: none; user-select: none;">
|
|
|
|
+
|
|
<div class="parkLeft">
|
|
<div class="parkLeft">
|
|
- <div class="ts primary small progress rotateNinetyDegree" style="width:120px !important;">
|
|
|
|
- <div id="volControl" class="bar" style="width: 60%;background-color:#ff4b4b;"></div>
|
|
|
|
|
|
+ <div class="ui primary small progress rotateNinetyDegree" style="width:120px !important; background-color: white;">
|
|
|
|
+ <div id="volControl" class="bar" style="min-width: 0%; width: 60%;background-color:#4576c5;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
<div id="volControlOverlay"></div>
|
|
<div id="volControlOverlay"></div>
|
|
<div class="playerControlWrapper" align="center">
|
|
<div class="playerControlWrapper" align="center">
|
|
- <button class="ts huge icon button roundbtn playlistStepBtn" onClick="lastSong();"><i class="step backward icon"></i></button>
|
|
|
|
- <button class="ts massive icon button roundbtn playBtn" onClick="togglePlay(this);"><i class="pause icon"></i></button>
|
|
|
|
- <button class="ts huge icon button roundbtn playlistStepBtn" onClick="nextSong();"><i class="step forward icon"></i></button>
|
|
|
|
|
|
+ <button class="ui white huge icon button sidebuttons roundbtn playlistStepBtn" onClick="lastSong();"><i class="step backward icon"></i></button>
|
|
|
|
+ <button id="playpauseBtn" style="background-color:#186ed2;" class="ui white massive icon button roundbtn playBtn" onClick="togglePlay(this);"><i class="pause icon"></i></button>
|
|
|
|
+ <button class="ui huge white icon button sidebuttons roundbtn playlistStepBtn" onClick="nextSong();"><i class="step forward icon"></i></button>
|
|
</div>
|
|
</div>
|
|
<div class="rightPaddedOprButtons">
|
|
<div class="rightPaddedOprButtons">
|
|
- <button id="repeatModeBtn" class="ts icon button" style="margin-bottom:5px;" onClick="toggleRepeat(this);"><i class="retweet icon"></i></button><br>
|
|
|
|
- <button id="showListBtn" class="ts icon button" onClick="showRelatedFileList();"><i class="content icon"></i></button>
|
|
|
|
- <!-- <button class="ts icon button"><i class="exchange icon"></i></button> -->
|
|
|
|
|
|
+ <button id="repeatModeBtn" class="ui icon button" style="margin-bottom:5px;" onClick="toggleRepeat(this);"><i class="retweet icon"></i></button><br>
|
|
|
|
+ <button id="showListBtn" class="ui icon button" onClick="showRelatedFileList();"><i class="content icon"></i></button>
|
|
|
|
+ <!-- <button class="ui icon button"><i class="exchange icon"></i></button> -->
|
|
</div>
|
|
</div>
|
|
<!-- Adding in some labels for the progress bars and song information-->
|
|
<!-- Adding in some labels for the progress bars and song information-->
|
|
- <p class="rotateNinetyDegree" style="position:absolute;top:55px;left:5px;"><i class="minus icon"></i> Volume <i class="plus icon"></i></p>
|
|
|
|
|
|
+ <p class="rotateNinetyDegree" style="position:absolute;top:65px;left:8px; font-weight: lighter;"><i class="small minus icon"></i> Volume <i class="small plus icon"></i></p>
|
|
<p class="durationDisplay">0:00 / 0:00</p>
|
|
<p class="durationDisplay">0:00 / 0:00</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
- <div id="progressControl" class="ts attached small progress">
|
|
|
|
- <div id="playbackProgress" class="bar" style="width: 0%;background-color: #4b75ff;"></div>
|
|
|
|
|
|
+ <div id="progressControl" class="ui attached small progress" style="height: 0.8rem; background: rgba(255,255,255,0.8);">
|
|
|
|
+ <div id="playbackProgress" class="bar" style="min-width: 0%; width: 0%;background-color: #4576c5; "></div>
|
|
</div>
|
|
</div>
|
|
- <div class="bottomBackground">
|
|
|
|
|
|
+ <div class="bottomBackground" >
|
|
<!-- Song Title at the bottom black area-->
|
|
<!-- Song Title at the bottom black area-->
|
|
<div id="songtitle" class="songlabel">Loading Song Information...</div>
|
|
<div id="songtitle" class="songlabel">Loading Song Information...</div>
|
|
- <div id="fileSize" style="position:absolute;bottom:5px;left:5px;color:white;">N/A</div>
|
|
|
|
- <div style="position:absolute;right:3px;bottom:3px;color:white;"><i class='leaf icon'></i>AirMusic</div>
|
|
|
|
|
|
+ <div id="fileSize" style="position:absolute;bottom:5px;left:5px;color:#77767b;">N/A</div>
|
|
|
|
+ <div style="position:absolute;right:3px;bottom:3px;color:#77767b;"><i class='leaf icon'></i>AirMusic</div>
|
|
</div>
|
|
</div>
|
|
<!-- The sections below are for mobile interfaces -->
|
|
<!-- The sections below are for mobile interfaces -->
|
|
<div id="nearbyFilelist" class="sameDirFileList">
|
|
<div id="nearbyFilelist" class="sameDirFileList">
|
|
@@ -216,6 +243,8 @@
|
|
player.src = "../media?file=" + encodeURIComponent(data[i][1]);
|
|
player.src = "../media?file=" + encodeURIComponent(data[i][1]);
|
|
//Update window title
|
|
//Update window title
|
|
ao_module_setWindowTitle(data[i][0]);
|
|
ao_module_setWindowTitle(data[i][0]);
|
|
|
|
+
|
|
|
|
+ updatePlayerThemeAndBackground(data[i][1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -419,16 +448,41 @@
|
|
updatePlayingSongSelection();
|
|
updatePlayingSongSelection();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ function uuidv4() {
|
|
|
|
+ return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
|
|
|
|
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
function createPlayList(){
|
|
function createPlayList(){
|
|
$(".sameDirFileList").html("");
|
|
$(".sameDirFileList").html("");
|
|
- var template = '<div class="listitem" filename="{rawname}" onClick="playThis(this);"><i class="file audio outline icon"></i> {songname} ({filesize})</div>';
|
|
|
|
for (var i = 0; i < songList.length; i++){
|
|
for (var i = 0; i < songList.length; i++){
|
|
- var box = template;
|
|
|
|
- box = box.split("{rawname}").join(songList[i][0]);
|
|
|
|
- box = box.split("{songname}").join(ao_module_codec.decodeUmFilename(songList[i][0]));
|
|
|
|
- box = box.split("{filesize}").join(songList[i][3]);
|
|
|
|
//console.log(box);
|
|
//console.log(box);
|
|
- $(".sameDirFileList").append(box);
|
|
|
|
|
|
+ let thisFileItemID = "thumb_" + uuidv4();
|
|
|
|
+ $(".sameDirFileList").append(`<div class="listitem" filename="${songList[i][0]}" onClick="playThis(this);">
|
|
|
|
+ <div class="ui unstackable grid">
|
|
|
|
+ <div class="three wide column" align="right">
|
|
|
|
+ <img id="${thisFileItemID}" class="ui image noradius" style="height: 2rem;" src="img/eq.svg">
|
|
|
|
+ </div>
|
|
|
|
+ <div class="thirteen wide column">
|
|
|
|
+ ${ao_module_codec.decodeUmFilename(songList[i][0])} (${songList[i][3]})
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ </div>`);
|
|
|
|
+
|
|
|
|
+ ao_module_agirun("Music/functions/getThumbnail.js", {
|
|
|
|
+ file: songList[i][1],
|
|
|
|
+ }, function(data){
|
|
|
|
+ if (data.error !== undefined){
|
|
|
|
+
|
|
|
|
+ }else{
|
|
|
|
+ $("#" + thisFileItemID).attr("src","data:image/jpg;base64," + data);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -498,7 +552,7 @@
|
|
|
|
|
|
function loadSongFromSongInfo(playSongInfo){
|
|
function loadSongFromSongInfo(playSongInfo){
|
|
var songName = ao_module_codec.decodeUmFilename(playSongInfo[0]);
|
|
var songName = ao_module_codec.decodeUmFilename(playSongInfo[0]);
|
|
- var songPath = filterExternalStoragePath(playSongInfo[1]);
|
|
|
|
|
|
+ var songPath = playSongInfo[1];
|
|
var fileSize = playSongInfo[3];
|
|
var fileSize = playSongInfo[3];
|
|
|
|
|
|
$(player).attr('src',"/media?file=" + encodeURIComponent(songPath));
|
|
$(player).attr('src',"/media?file=" + encodeURIComponent(songPath));
|
|
@@ -506,6 +560,37 @@
|
|
ao_module_setWindowTitle(songName);
|
|
ao_module_setWindowTitle(songName);
|
|
songInfo = playSongInfo;
|
|
songInfo = playSongInfo;
|
|
updateDisplayInformation(ao_module_codec.decodeUmFilename(songInfo[0]),songInfo[3]);
|
|
updateDisplayInformation(ao_module_codec.decodeUmFilename(songInfo[0]),songInfo[3]);
|
|
|
|
+ updatePlayerThemeAndBackground(songPath);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Update the player background and theme color
|
|
|
|
+ function updatePlayerThemeAndBackground(songPath){
|
|
|
|
+ ao_module_agirun("Music/functions/getThumbnail.js", {
|
|
|
|
+ file: songPath,
|
|
|
|
+ }, function(data){
|
|
|
|
+ if (data.error == undefined){
|
|
|
|
+ let imageSrc = "data:image/jpg;base64," + data;
|
|
|
|
+ $("#Albumnart").attr("src",imageSrc);
|
|
|
|
+ //Get theme color and update the player theme color
|
|
|
|
+ let themeColor = getAverageRGB($("#Albumnart")[0]);
|
|
|
|
+ updateThemeColor(themeColor);
|
|
|
|
+ }else{
|
|
|
|
+ //No thumbnail. Restore to default theme color
|
|
|
|
+ updateThemeColor({r:24, g: 110, b: 210});
|
|
|
|
+ $("#Albumnart").attr("src","img/nothumb.png");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Update the theme color, require something like { r: 231, g: 159, b: 140 }
|
|
|
|
+ function updateThemeColor(newRGBColor){
|
|
|
|
+ let colorText = `rgb(${newRGBColor.r} ,${newRGBColor.g} ,${newRGBColor.b})`
|
|
|
|
+ $("#playbackProgress").css("background-color", colorText);
|
|
|
|
+ $("#playpauseBtn").css("background-color", colorText);
|
|
|
|
+ $("#volControl").css("background-color", colorText);
|
|
|
|
+ $(".modeEnabled")[0].style.setProperty( "background-color", colorText, 'important' );
|
|
|
|
+ //$(".sameDirFileList").css("background-color", `rgba(${newRGBColor.r}, ${newRGBColor.g}, ${newRGBColor.b}, 0.1)`);
|
|
}
|
|
}
|
|
|
|
|
|
function updateDisplayInformation(songname, filesize){
|
|
function updateDisplayInformation(songname, filesize){
|
|
@@ -513,14 +598,10 @@
|
|
$("#fileSize").html("<i class='file outline icon'></i> " + filesize);
|
|
$("#fileSize").html("<i class='file outline icon'></i> " + filesize);
|
|
}
|
|
}
|
|
|
|
|
|
- function filterExternalStoragePath(filepath){
|
|
|
|
- return filepath;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
function updateDurationDisplay(pos,dur){
|
|
function updateDurationDisplay(pos,dur){
|
|
pos = secondsToHMS(pos);
|
|
pos = secondsToHMS(pos);
|
|
dur = secondsToHMS(dur);
|
|
dur = secondsToHMS(dur);
|
|
- $(".durationDisplay").html('<i class="clock icon"></i>' + pos.trim() + " / " + dur.trim());
|
|
|
|
|
|
+ $(".durationDisplay").html(pos.trim() + " / " + dur.trim());
|
|
}
|
|
}
|
|
|
|
|
|
function secondsToHMS(sec){
|
|
function secondsToHMS(sec){
|
|
@@ -611,6 +692,51 @@
|
|
});
|
|
});
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ function getAverageRGB(imgEl) {
|
|
|
|
+ var blockSize = 5,
|
|
|
|
+ defaultRGB = {r:0,g:0,b:0},
|
|
|
|
+ canvas = document.createElement('canvas'),
|
|
|
|
+ context = canvas.getContext && canvas.getContext('2d'),
|
|
|
|
+ data, width, height,
|
|
|
|
+ i = -4,
|
|
|
|
+ length,
|
|
|
|
+ rgb = {r:0,g:0,b:0},
|
|
|
|
+ count = 0;
|
|
|
|
+
|
|
|
|
+ if (!context) {
|
|
|
|
+ return defaultRGB;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
|
|
|
|
+ width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
|
|
|
|
+
|
|
|
|
+ context.drawImage(imgEl, 0, 0);
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ data = context.getImageData(0, 0, width, height);
|
|
|
|
+ } catch(e) {
|
|
|
|
+ /* security error, img on diff domain */
|
|
|
|
+ return defaultRGB;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ length = data.data.length;
|
|
|
|
+
|
|
|
|
+ while ( (i += blockSize * 4) < length ) {
|
|
|
|
+ ++count;
|
|
|
|
+ rgb.r += data.data[i];
|
|
|
|
+ rgb.g += data.data[i+1];
|
|
|
|
+ rgb.b += data.data[i+2];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ~~ used to floor values
|
|
|
|
+ rgb.r = ~~(rgb.r/count);
|
|
|
|
+ rgb.g = ~~(rgb.g/count);
|
|
|
|
+ rgb.b = ~~(rgb.b/count);
|
|
|
|
+
|
|
|
|
+ return rgb;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
</script>
|
|
</script>
|
|
</body>
|
|
</body>
|