Implemented socket.io
Started work on darkmode Implemented queue system Started work on download tab
This commit is contained in:
parent
d58fca7266
commit
55268c72b5
7
public/css/darkMode.css
Normal file
7
public/css/darkMode.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
:root {
|
||||||
|
--main-background: #141414;
|
||||||
|
--secondary-background: #242424;
|
||||||
|
--main-text: #eeeeee;
|
||||||
|
--panels-background: #1a1a1a;
|
||||||
|
--panels-text: #ffffff;
|
||||||
|
}
|
@ -1,20 +1,32 @@
|
|||||||
|
:root {
|
||||||
|
--main-background: #ffffff;
|
||||||
|
--secondary-background: #eeeeee;
|
||||||
|
--main-text: #333333;
|
||||||
|
--main-scroll: #555;
|
||||||
|
--panels-background: #222324;
|
||||||
|
--panels-text: #ffffff;
|
||||||
|
--accent-color: #0A84FF;
|
||||||
|
--tag-background: #0062c4;
|
||||||
|
--tag-text: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
html{height: 100%;}
|
html{height: 100%;}
|
||||||
body{margin: 0px;width: 100%;height: 100%;font-family: sans-serif; overflow: hidden; background-color: #ffffff; color: #333333;}
|
body{margin: 0px;width: 100%;height: 100%;font-family: sans-serif; overflow: hidden; background-color: var(--main-background); color: var(--main-text);}
|
||||||
|
|
||||||
/* Sidebar section selector */
|
/* Sidebar section selector */
|
||||||
aside#sidebar{
|
aside#sidebar{
|
||||||
background-color: #222324;
|
background-color: var(--panels-background);
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: #ffffff;
|
color: var(--panels-text);
|
||||||
}
|
}
|
||||||
aside#sidebar > .side_icon{
|
aside#sidebar > .side_icon{
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
}
|
}
|
||||||
.side_icon.active{
|
.side_icon.active{
|
||||||
color: #0A84FF;
|
color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rest of the app */
|
/* Rest of the app */
|
||||||
@ -27,7 +39,7 @@ main#main_content{
|
|||||||
|
|
||||||
/* Middle section */
|
/* Middle section */
|
||||||
div#middle_section {
|
div#middle_section {
|
||||||
background-color: #ffffff;
|
background-color: var(--main-background);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-width: 10px;
|
min-width: 10px;
|
||||||
@ -41,10 +53,10 @@ div#middle_section {
|
|||||||
margin: 8px;
|
margin: 8px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: #eeeeee;
|
background-color: var(--secondary-background);
|
||||||
}
|
}
|
||||||
#content{
|
#content{
|
||||||
background-color: #ffffff;
|
background-color: var(--main-background);
|
||||||
width: calc(100% - 10px);
|
width: calc(100% - 10px);
|
||||||
height: calc(100% - 48px);
|
height: calc(100% - 48px);
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@ -56,11 +68,11 @@ div#middle_section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#content::-webkit-scrollbar-track {
|
#content::-webkit-scrollbar-track {
|
||||||
background: #ffffff;
|
background: var(--main-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
#content::-webkit-scrollbar-thumb {
|
#content::-webkit-scrollbar-thumb {
|
||||||
background: #555;
|
background: var(--main-scroll);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
padding: 0px 2px;
|
padding: 0px 2px;
|
||||||
@ -145,8 +157,8 @@ div#middle_section {
|
|||||||
|
|
||||||
/* Download tab section */
|
/* Download tab section */
|
||||||
div#download_tab_container{
|
div#download_tab_container{
|
||||||
background-color: #222324;
|
background-color: var(--panels-background);
|
||||||
color: #ffffff;
|
color: var(--panels-text);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: auto;
|
width: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -186,12 +198,12 @@ img.circle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.coverart{
|
.coverart{
|
||||||
background-color: #eee;
|
background-color: var(--secondary-background);
|
||||||
}
|
}
|
||||||
span.tag {
|
span.tag {
|
||||||
background-color: #222324;
|
background-color: var(--tag-background);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color: #ffffff;
|
color: var(--tag-text);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
|
@ -4,9 +4,15 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>deemix</title>
|
<title>deemix</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/public/css/style.css">
|
<link rel="stylesheet" type="text/css" href="/public/css/style.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/public/css/darkMode.css" name="darkMode" disabled/>
|
||||||
<link rel="stylesheet" type="text/css" href="/public/css/animate.css">
|
<link rel="stylesheet" type="text/css" href="/public/css/animate.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/public/css/material-icons.css"/>
|
<link rel="stylesheet" type="text/css" href="/public/css/material-icons.css"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0">
|
||||||
|
<script type='text/javascript'>
|
||||||
|
if (eval(localStorage.darkMode)){
|
||||||
|
document.getElementsByName("darkMode")[0].removeAttribute("disabled");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<aside id="sidebar">
|
<aside id="sidebar">
|
||||||
@ -153,12 +159,20 @@ <h1>No Playlists found</h1>
|
|||||||
</div>
|
</div>
|
||||||
<div id="download_tab">
|
<div id="download_tab">
|
||||||
<i id="hide_download_tab" class="material-icons download_bar_icon">chevron_right</i>
|
<i id="hide_download_tab" class="material-icons download_bar_icon">chevron_right</i>
|
||||||
|
<div id="download_list">
|
||||||
|
<div v-for="item in queue">
|
||||||
|
{{ item.artist }} - {{ item.title }} | {{ item.downloaded }} {{ item.size }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
<script type="text/javascript" src="/public/js/socket.io.js"></script>
|
||||||
<script type="text/javascript" src="/public/js/jquery-3.3.1.min.js"></script>
|
<script type="text/javascript" src="/public/js/jquery-3.3.1.min.js"></script>
|
||||||
<script type="text/javascript" src="/public/js/vue.min.js"></script>
|
<script type="text/javascript" src="/public/js/vue.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/public/js/init.js"></script>
|
||||||
<script type="text/javascript" src="/public/js/utils.js"></script>
|
<script type="text/javascript" src="/public/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/public/js/frontend.js"></script>
|
<script type="text/javascript" src="/public/js/app.js"></script>
|
||||||
|
<script type="text/javascript" src="/public/js/downloadList.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,81 +1,54 @@
|
|||||||
// Initialization
|
// Debug messages for socketio
|
||||||
doAjax("/init", "POST");
|
socket.emit("init");
|
||||||
search_selected = ""
|
socket.on("message", function(msg){
|
||||||
main_selected=""
|
console.log(msg)
|
||||||
|
})
|
||||||
|
|
||||||
// Functions to connect to the Flask server
|
$(function() {
|
||||||
function getHttpRequestObject(){
|
// Check if download tab should be open
|
||||||
var xmlHttpRequst = false;
|
if (eval(localStorage.getItem("downloadTabOpen")))
|
||||||
if (window.XMLHttpRequest){
|
$("#show_download_tab").click()
|
||||||
xmlHttpRequst = new XMLHttpRequest();
|
else
|
||||||
}else if (window.ActiveXObject){
|
$("#hide_download_tab").click()
|
||||||
xmlHttpRequst = new ActiveXObject("Microsoft.XMLHTTP");
|
})
|
||||||
}
|
|
||||||
return xmlHttpRequst;
|
|
||||||
}
|
|
||||||
function doAjax(url, method, responseHandler, data){
|
|
||||||
url = url || "";
|
|
||||||
method = method || "GET";
|
|
||||||
async = true;
|
|
||||||
data = data || {};
|
|
||||||
|
|
||||||
if(url == ""){
|
|
||||||
alert("URL cannot be null/blank");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var xmlHttpRequest = getHttpRequestObject();
|
|
||||||
|
|
||||||
if(xmlHttpRequest != false){
|
|
||||||
xmlHttpRequest.open(method, url, async);
|
|
||||||
if(method == "POST"){
|
|
||||||
xmlHttpRequest.setRequestHeader("Content-Type", "application/json");
|
|
||||||
}
|
|
||||||
if (typeof responseHandler === "function"){
|
|
||||||
xmlHttpRequest.onreadystatechange = function(){
|
|
||||||
if(this.readyState === XMLHttpRequest.DONE && this.status === 200) {
|
|
||||||
responseHandler(JSON.parse(this.responseText))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlHttpRequest.send(JSON.stringify(data));
|
|
||||||
}else{
|
|
||||||
alert("Please use a browser with Ajax support!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show/Hide Download Tab
|
// Show/Hide Download Tab
|
||||||
document.querySelector("#show_download_tab").onclick = (ev)=>{
|
document.querySelector("#show_download_tab").onclick = (ev)=>{
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
document.querySelector("#download_tab_bar").style.display = "none";
|
document.querySelector("#download_tab_bar").style.display = "none";
|
||||||
document.querySelector("#download_tab").style.display = "block";
|
document.querySelector("#download_tab").style.display = "block";
|
||||||
|
localStorage.setItem("downloadTabOpen", true)
|
||||||
}
|
}
|
||||||
document.querySelector("#hide_download_tab").onclick = (ev)=>{
|
document.querySelector("#hide_download_tab").onclick = (ev)=>{
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
document.querySelector("#download_tab_bar").style.display = "block";
|
document.querySelector("#download_tab_bar").style.display = "block";
|
||||||
document.querySelector("#download_tab").style.display = "none";
|
document.querySelector("#download_tab").style.display = "none";
|
||||||
|
localStorage.setItem("downloadTabOpen", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTab(evt, section, tabName) {
|
function changeTab(evt, section, tabName) {
|
||||||
var i, tabcontent, tablinks;
|
var i, tabcontent, tablinks;
|
||||||
tabcontent = document.getElementsByClassName(section+"_tabcontent");
|
tabcontent = document.getElementsByClassName(section+"_tabcontent");
|
||||||
for (i = 0; i < tabcontent.length; i++) {
|
for (i = 0; i < tabcontent.length; i++) {
|
||||||
tabcontent[i].style.display = "none";
|
tabcontent[i].style.display = "none";
|
||||||
}
|
}
|
||||||
tablinks = document.getElementsByClassName(section+"_tablinks");
|
tablinks = document.getElementsByClassName(section+"_tablinks");
|
||||||
for (i = 0; i < tablinks.length; i++) {
|
for (i = 0; i < tablinks.length; i++) {
|
||||||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||||
}
|
}
|
||||||
document.getElementById(tabName).style.display = "block";
|
document.getElementById(tabName).style.display = "block";
|
||||||
window[section+"_selected"] = tabName
|
window[section+"_selected"] = tabName
|
||||||
evt.currentTarget.className += " active";
|
evt.currentTarget.className += " active";
|
||||||
|
// Check if you need to load more content in the search tab
|
||||||
if (document.getElementById("content").offsetHeight >= document.getElementById("content").scrollHeight && main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){
|
if (document.getElementById("content").offsetHeight >= document.getElementById("content").scrollHeight && main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){
|
||||||
scrolledSearch(window[search_selected.split("_")[0]+"Search"])
|
scrolledSearch(window[search_selected.split("_")[0]+"Search"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load more content when the search page is at the end
|
||||||
$('#content').on('scroll', function() {
|
$('#content').on('scroll', function() {
|
||||||
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
|
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
|
||||||
if (main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){
|
if (main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){
|
||||||
scrolledSearch(window[search_selected.split("_")[0]+"Search"])
|
scrolledSearch(window[search_selected.split("_")[0]+"Search"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +57,7 @@ $('#content').on('scroll', function() {
|
|||||||
function scrolledSearch(vueTab){
|
function scrolledSearch(vueTab){
|
||||||
query = vueTab.query
|
query = vueTab.query
|
||||||
if (vueTab.results.next < vueTab.results.total){
|
if (vueTab.results.next < vueTab.results.total){
|
||||||
doAjax("/search", "POST", searchUpadate, {term: vueTab.query, type: vueTab.type, start: vueTab.results.next, nb: vueTab.nb});
|
socket.emit("search", {term: vueTab.query, type: vueTab.type, start: vueTab.results.next, nb: vueTab.nb});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +83,7 @@ function searchUpadate(result){
|
|||||||
vueTab.results.data = vueTab.results.data.concat(result.data)
|
vueTab.results.data = vueTab.results.data.concat(result.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
socket.on("search", function(result){searchUpadate(result)})
|
||||||
|
|
||||||
function clickElement(button){
|
function clickElement(button){
|
||||||
return document.getElementById(button).click()
|
return document.getElementById(button).click()
|
||||||
@ -125,7 +99,7 @@ var mainSearch = new Vue({
|
|||||||
"ALBUM": "Albums",
|
"ALBUM": "Albums",
|
||||||
"PLAYLIST": "Playlists"
|
"PLAYLIST": "Playlists"
|
||||||
},
|
},
|
||||||
results: {
|
results: {
|
||||||
QUERY: "",
|
QUERY: "",
|
||||||
ORDER: [],
|
ORDER: [],
|
||||||
ALBUM: {},
|
ALBUM: {},
|
||||||
@ -149,7 +123,7 @@ var trackSearch = new Vue({
|
|||||||
type: "TRACK",
|
type: "TRACK",
|
||||||
nb: 40,
|
nb: 40,
|
||||||
query: "",
|
query: "",
|
||||||
results: {
|
results: {
|
||||||
data: [],
|
data: [],
|
||||||
next: 0,
|
next: 0,
|
||||||
total: 0
|
total: 0
|
||||||
@ -163,7 +137,7 @@ var albumSearch = new Vue({
|
|||||||
type: "ALBUM",
|
type: "ALBUM",
|
||||||
nb: 20,
|
nb: 20,
|
||||||
query: "",
|
query: "",
|
||||||
results: {
|
results: {
|
||||||
data: [],
|
data: [],
|
||||||
next: 0,
|
next: 0,
|
||||||
total: 0
|
total: 0
|
||||||
@ -177,7 +151,7 @@ var artistSearch = new Vue({
|
|||||||
type: "ARTIST",
|
type: "ARTIST",
|
||||||
nb: 20,
|
nb: 20,
|
||||||
query: "",
|
query: "",
|
||||||
results: {
|
results: {
|
||||||
data: [],
|
data: [],
|
||||||
next: 0,
|
next: 0,
|
||||||
total: 0
|
total: 0
|
||||||
@ -191,7 +165,7 @@ var playlistSearch = new Vue({
|
|||||||
type: "PLAYLIST",
|
type: "PLAYLIST",
|
||||||
nb: 20,
|
nb: 20,
|
||||||
query: "",
|
query: "",
|
||||||
results: {
|
results: {
|
||||||
data: [],
|
data: [],
|
||||||
next: 0,
|
next: 0,
|
||||||
total: 0
|
total: 0
|
||||||
@ -205,15 +179,15 @@ $("#searchbar").keyup(function(e){
|
|||||||
term = this.value
|
term = this.value
|
||||||
console.log(term)
|
console.log(term)
|
||||||
if (isValidURL(term))
|
if (isValidURL(term))
|
||||||
doAjax("/download", "POST", null, {url: term});
|
socket.emit("addToQueue", {url: term});
|
||||||
else{
|
else{
|
||||||
document.getElementById("search_tab_content").style.display = "none";
|
document.getElementById("search_tab_content").style.display = "none";
|
||||||
doAjax("/mainsearch", "POST", searchHandler, {term: term});
|
socket.emit("mainSearch", {term: term});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function searchHandler(result){
|
function mainSearchHandler(result){
|
||||||
console.log(result)
|
console.log(result)
|
||||||
mainSearch.results = result
|
mainSearch.results = result
|
||||||
trackSearch.results = result.TRACK
|
trackSearch.results = result.TRACK
|
||||||
@ -228,6 +202,7 @@ function searchHandler(result){
|
|||||||
document.getElementById("search_tab_content").style.display = "block";
|
document.getElementById("search_tab_content").style.display = "block";
|
||||||
document.getElementById("show_searchtab").click();
|
document.getElementById("show_searchtab").click();
|
||||||
}
|
}
|
||||||
|
socket.on("mainSearch", function(result){mainSearchHandler(result)})
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
document.getElementById("main_defaultopen").click();
|
document.getElementById("main_defaultopen").click();
|
21
public/js/downloadList.js
Normal file
21
public/js/downloadList.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
var downloadList = new Vue({
|
||||||
|
el: '#download_list',
|
||||||
|
data: {
|
||||||
|
queue: [],
|
||||||
|
queueList: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("addedToQueue", function(queueItem){
|
||||||
|
downloadList.queueList[queueItem.uuid] = queueItem
|
||||||
|
downloadList.queue.push(queueItem)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("updateQueue", function(update){
|
||||||
|
if (update.uuid && downloadList.queue.indexOf(update.uuid) > -1){
|
||||||
|
console.log(update)
|
||||||
|
if (update.downloaded) downloadList.queueList[update.uuid].downloaded++
|
||||||
|
if (update.failed) downloadList.queueList[update.uuid].failed++
|
||||||
|
if (update.progress) downloadList.queueList[update.uuid].progress = update.progress
|
||||||
|
}
|
||||||
|
})
|
5
public/js/init.js
Normal file
5
public/js/init.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Initialization
|
||||||
|
const socket = io.connect(window.location.href)
|
||||||
|
localStorage = window.localStorage;
|
||||||
|
search_selected = ""
|
||||||
|
main_selected=""
|
9
public/js/socket.io.js
Normal file
9
public/js/socket.io.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/socket.io.js.map
Executable file
1
public/js/socket.io.js.map
Executable file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user