Fix timeline UI with multiple clients

This commit is contained in:
ABelliqueux 2023-01-08 16:54:25 +01:00
parent 7e0d217cf3
commit ce38295600
4 changed files with 88 additions and 51 deletions

4
app.py
View File

@ -140,7 +140,7 @@ else:
# Network/link utilities # Network/link utilities
# https://www.metageek.com/training/resources/understanding-rssi/
def send_HTTP_request(listed_host, port, time_out=3, request_="/"): def send_HTTP_request(listed_host, port, time_out=3, request_="/"):
''' '''
Send a http request with http auth Send a http request with http auth
@ -536,7 +536,7 @@ def send_pilpil_command(host, arg0, arg1, arg2):
data = send_HTTP_request(host, port_, time_out=3, request_=HTTP_request) data = send_HTTP_request(host, port_, time_out=3, request_=HTTP_request)
if debug: if debug:
if data: if data:
print(str(host) + " - data length:" + str(len(data))) print(str(host) + " - data length:" + str(len(data)) + " : " + str(data))
if not data: if not data:
print("No data was received.") print("No data was received.")
return 0 return 0

View File

@ -58,6 +58,7 @@ async function update_sort_VLC_playlist(host) {
// Reversed loop // Reversed loop
for (let i=media_count, l=0; i>l; i--) { for (let i=media_count, l=0; i>l; i--) {
// Find current's timeline element children's 'media_id' value // Find current's timeline element children's 'media_id' value
//~ console.log(document.getElementById(`timeline_${host}`).children[i-1].children[0])
let to_shift = document.getElementById(`timeline_${host}`).children[i-1].children[0].getAttribute("media_id"); let to_shift = document.getElementById(`timeline_${host}`).children[i-1].children[0].getAttribute("media_id");
//~ console.log(to_shift + " : " + document.getElementById(`timeline_${host}`).children[i-1].children[0].innerText); //~ console.log(to_shift + " : " + document.getElementById(`timeline_${host}`).children[i-1].children[0].innerText);
// Move 'to_shift' after element with id '1' : // Move 'to_shift' after element with id '1' :
@ -69,16 +70,31 @@ async function update_sort_VLC_playlist(host) {
// Un-freeze timeline update flag // Un-freeze timeline update flag
currentUser.freeze_timeline_update = 0; currentUser.freeze_timeline_update = 0;
} }
function get_child_by_id(id, parent_element, depth=0){
// TODO : fix this ofc
Array.from(parent_element.children).forEach(function(child){
if (depth){
if (child.children[0].id == id){
//~ console.log(child.children[0]);
result = child.children[0];
}
} else if (child.id == id) {
result = child;
}
});
return result;
}
async function update_delete_VLC_playlist(host, delete_element_id) { async function update_delete_VLC_playlist(host, delete_element_id) {
let delete_media = document.getElementById(delete_element_id);
let current_timeline = document.getElementById("timeline_" + host);
let delete_media = get_child_by_id(delete_element_id, current_timeline, 1);
let delete_media_cont = delete_media.parentElement; let delete_media_cont = delete_media.parentElement;
let delete_media_id = delete_media.getAttribute("media_id"); let delete_media_id = delete_media.getAttribute("media_id");
document.getElementById("timeline_" + host).removeChild(delete_media_cont); current_timeline.removeChild(delete_media_cont);
send_ajax_cmd("/" + host + "/delete/" + delete_media_id); send_ajax_cmd("/" + host + "/delete/" + delete_media_id);
await sleep(90); await sleep(120);
adjust_timeline(); adjust_timeline(host);
currentUser.freeze_timeline_update = 0; currentUser.freeze_timeline_update = 0;
} }
@ -124,10 +140,12 @@ function allow_drop(event) {
function drag_over_bin(event) { function drag_over_bin(event) {
event.preventDefault(); event.preventDefault();
let dropped_id = event.dataTransfer.getData("text"); let dropped_id = event.dataTransfer.getData("target_id");
let source_element = document.getElementById(dropped_id); let source_id = event.dataTransfer.getData("parent_element_id");
let current_host = source_element.parentElement.parentElement.id.split("_")[1]; let source_element = document.getElementById(source_id);
source_element.style.border = "2px #FFDE00 solid"; let cont_element = get_child_by_id(dropped_id, source_element, 1);
let current_host = source_id.split("_")[1];
cont_element.style.opacity = .5;
document.getElementById("delete_" + current_host).style.backgroundColor = "#f00"; document.getElementById("delete_" + current_host).style.backgroundColor = "#f00";
document.getElementById("delete_" + current_host).style.boxShadow = "0 0 10px #fff;"; document.getElementById("delete_" + current_host).style.boxShadow = "0 0 10px #fff;";
} }
@ -135,10 +153,12 @@ function drag_over_bin(event) {
function drag_leave_bin(event) { function drag_leave_bin(event) {
event.preventDefault(); event.preventDefault();
let dropped_id = event.dataTransfer.getData("text"); let dropped_id = event.dataTransfer.getData("target_id");
let source_element = document.getElementById(dropped_id); let source_id = event.dataTransfer.getData("parent_element_id");
let current_host = source_element.parentElement.parentElement.id.split("_")[1]; let source_element = document.getElementById(source_id);
source_element.style.border = "none"; let cont_element = get_child_by_id(dropped_id, source_element, 1);
let current_host = source_id.split("_")[1];
cont_element.style.opacity = 1;
document.getElementById("delete_" + current_host).style.backgroundColor = "#df7474"; document.getElementById("delete_" + current_host).style.backgroundColor = "#df7474";
} }
@ -146,7 +166,8 @@ function drag_leave_bin(event) {
function drag(event, source) { function drag(event, source) {
// Freeze timeline update flag // Freeze timeline update flag
currentUser.freeze_timeline_update = 1; currentUser.freeze_timeline_update = 1;
event.dataTransfer.setData("text", event.target.id); event.dataTransfer.setData("target_id", event.target.id);
event.dataTransfer.setData("parent_element_id", source.parentElement.parentElement.id);
} }
@ -155,19 +176,23 @@ function drop(event, target_element) {
// shift HTML elements in the timeline to the left or right from the target element. // shift HTML elements in the timeline to the left or right from the target element.
event.preventDefault(); event.preventDefault();
// Get dragged element id // Get dragged element id
let dropped_id = event.dataTransfer.getData("text"); let dropped_id = event.dataTransfer.getData("target_id");
let source_element = document.getElementById(dropped_id); let source_id = event.dataTransfer.getData("parent_element_id");
let current_host = source_element.parentElement.parentElement.id.split("_")[1]; let source_element = document.getElementById(source_id);
let current_host = source_id.split("_")[1];
source_element.style.border = "none";
// Only shift if not dropping on self // Only shift if not dropping on self
if (source_element.id != target_element.id) { if (source_element.id != target_element.id) {
if ( target_element.id.indexOf("delete_") > -1 ) { if ( target_element.id.indexOf("delete_") > -1 ) {
update_delete_VLC_playlist(current_host, dropped_id); update_delete_VLC_playlist(current_host, dropped_id);
} else { } else {
let dropTarget = shift_elements(source_element.parentElement, target_element); dropped_element = get_child_by_id(dropped_id, source_element, 1);
let dropTarget = shift_elements(dropped_element.parentElement, target_element);
//~ if (dropTarget) { //~ if (dropTarget) {
// Append dropped element to drop target. // Append dropped element to drop target.
target_element.appendChild(source_element); //~ target_element.appendChild(source_element);
update_sort_VLC_playlist(current_host); target_element.appendChild(dropped_element);
update_sort_VLC_playlist(current_host);
//~ } //~ }
} }
// Un-freeze timeline update flag // Un-freeze timeline update flag
@ -177,9 +202,10 @@ function drop(event, target_element) {
} }
function adjust_timeline() { function adjust_timeline(host) {
// Adapt timeline's UI elements to fit the width of their parent container. // Adapt timeline's UI elements to fit the width of their parent container.
let timeline_div = document.querySelector('[id^="timeline_"]').children; //~ let timeline_div = document.querySelector('[id^="timeline_"]').children;
let timeline_div = document.getElementById("timeline_" + host).children;
let div_width = 100 / timeline_div.length; let div_width = 100 / timeline_div.length;
for (let i=0, l=timeline_div.length; i<l; i++) { for (let i=0, l=timeline_div.length; i<l; i++) {
timeline_div[i].style.width= div_width + "%"; timeline_div[i].style.width= div_width + "%";
@ -249,7 +275,8 @@ function update_status(infos_array_element) {
document.getElementById("status_" + infos_array_element.host).innerHTML = infos_array_element.file + " <br/> " + infos_array_element.time + " / " + infos_array_element.leng; document.getElementById("status_" + infos_array_element.host).innerHTML = infos_array_element.file + " <br/> " + infos_array_element.time + " / " + infos_array_element.leng;
currentUser.medias_status[infos_array_element.id] = infos_array_element.pos; currentUser.medias_status[infos_array_element.id] = infos_array_element.pos;
// Highlight currently playing element // Highlight currently playing element
let timeline_medias_array = Array.from(document.querySelectorAll('[media_id]')); let current_timeline = document.getElementById("timeline_" + infos_array_element.host);
let timeline_medias_array = Array.from(current_timeline.querySelectorAll('[media_id]'));
timeline_medias_array.forEach(function(media_element){ timeline_medias_array.forEach(function(media_element){
if ( media_element.getAttribute("media_id") == infos_array_element.id ) { if ( media_element.getAttribute("media_id") == infos_array_element.id ) {
let first_CSS_gradient_stop = infos_array_element.pos * 100; let first_CSS_gradient_stop = infos_array_element.pos * 100;
@ -288,20 +315,23 @@ function update_list(infos_array_element){
document.getElementById("timeline_" + host).removeChild(child); document.getElementById("timeline_" + host).removeChild(child);
}); });
} else { } else {
current_timeline = document.getElementById("timeline_" + host);
items_array.forEach(function(item, j){ items_array.forEach(function(item, j){
item_meta = item.split(';'); item_meta = item.split(';');
let child_node = add_HTML_element("div", tl_drag_attr, item_meta, j); let child_node = add_HTML_element("div", tl_drag_attr, item_meta, j);
let len = document.getElementById("timeline_" + host).children.length; let len = current_timeline.children.length;
add_HTML_attr("timeline_" + host, "length", len); add_HTML_attr("timeline_" + host, "length", len);
if ( len < items_array.length ) { if ( len < items_array.length ) {
document.getElementById("timeline_" + host).appendChild( add_HTML_element("div", tl_cont_attr, 0, len) ); current_timeline.appendChild( add_HTML_element("div", tl_cont_attr, 0, len) );
} }
document.getElementById(tl_cont_attr.id + j).replaceChildren(child_node); //~ document.getElementById(tl_cont_attr.id + j).replaceChildren(child_node);
let media_name = document.getElementById(tl_cont_attr.id + j).children[0].innerText; current_timeline_children = Array.from(current_timeline.children);
current_timeline_children[j].replaceChildren(child_node);
let media_name = current_timeline_children[j].children[0].innerText;
let media_url_str = "url(https://" + host + ":" + CMD_PORT + "/thumb/" + media_name + ")"; let media_url_str = "url(https://" + host + ":" + CMD_PORT + "/thumb/" + media_name + ")";
document.getElementById(tl_cont_attr.id + j).children[0].style.backgroundImage = media_url_str; current_timeline_children[j].children[0].style.backgroundImage = media_url_str;
// Adjust elements width // Adjust elements width
adjust_timeline(); adjust_timeline(host);
}); });
} }
return items_array.length; return items_array.length;
@ -345,6 +375,7 @@ function update_remote_filelist(infos_array_element) {
function update_rssi_indicator(infos_array_element){ function update_rssi_indicator(infos_array_element){
let base_height = 0.5;
let signal_color = 40; let signal_color = 40;
let best_rssi = 30; let best_rssi = 30;
let worst_rssi = 70; let worst_rssi = 70;
@ -352,11 +383,13 @@ function update_rssi_indicator(infos_array_element){
signal_color = (rssi_norm-1) * signal_color; signal_color = (rssi_norm-1) * signal_color;
// Reset to grey // Reset to grey
for (let i=0, l=4; i<l; i++) { for (let i=0, l=4; i<l; i++) {
document.getElementById("wl_"+i).style.backgroundColor = "hsl(0, 0%, 65%)"; document.getElementById("wl_" + infos_array_element.host + "_" +i).style.height = base_height + i * 0.15 + "em";
document.getElementById("wl_" + infos_array_element.host + "_" + i).style.backgroundColor = "hsl(0, 0%, 65%)";
} }
// Color it // Color it
for (let i=0, l=rssi_norm > 4 ? 4 : rssi_norm; i<l; i++) { for (let i=0, l=rssi_norm > 4 ? 4 : rssi_norm; i<l; i++) {
document.getElementById("wl_"+i).style.backgroundColor = "hsl(" + signal_color + ", 100%, 50%)"; document.getElementById("wl_" + infos_array_element.host + "_" +i).style.height = base_height + i * 0.15 + "em";
document.getElementById("wl_" + infos_array_element.host + "_" +i).style.backgroundColor = "hsl(" + signal_color + ", 100%, 50%)";
} }
return rssi_norm; return rssi_norm;
} }
@ -386,6 +419,7 @@ function update_host_list(infos_array){
let host_down = infos_array[1]; let host_down = infos_array[1];
if (host_up.length) { if (host_up.length) {
host_up.forEach(function(host){ host_up.forEach(function(host){
adjust_timeline(host);
document.getElementById(host).style.display = 'block'; document.getElementById(host).style.display = 'block';
send_ajax_cmd("/" + host + "/list"); send_ajax_cmd("/" + host + "/list");
send_ajax_cmd("/" + host + "/rssi"); send_ajax_cmd("/" + host + "/rssi");
@ -408,7 +442,7 @@ function display_upload_status(command) {
// Upload dialog container / background // Upload dialog container / background
let upload_dialog_cont_attributes = {"id":"ul_dialog_cont_", "class": "upload_dialog_cont"}; let upload_dialog_cont_attributes = {"id":"ul_dialog_cont_", "class": "upload_dialog_cont"};
let upload_dialog_cont_element = add_HTML_element("div", upload_dialog_cont_attributes, 0, host); let upload_dialog_cont_element = add_HTML_element("div", upload_dialog_cont_attributes, 0, host);
let ul_cont_exists = document.getElementById(upload_dialog_cont_attributes["id"] + host); let ul_cont_exists = document.getElementById(upload_dialog_cont_attributes.id + host);
// Upload dialog // Upload dialog
//~ let upload_dialog_attributes = {"id":"ul_dialog_", "class": "upload_dialog"}; //~ let upload_dialog_attributes = {"id":"ul_dialog_", "class": "upload_dialog"};
//~ let upload_dialog_element = add_HTML_element("div", upload_dialog_attributes, 0, host); //~ let upload_dialog_element = add_HTML_element("div", upload_dialog_attributes, 0, host);
@ -429,19 +463,19 @@ function display_upload_status(command) {
</tr> </tr>
</tbody> </tbody>
</table> </table>
` `;
let upload_dialog_HTML = ` let upload_dialog_HTML = `
<div id='ul_dialog_${host}' class='upload_dialog'> <div id='ul_dialog_${host}' class='upload_dialog'>
<div id="ul_status_${host}" class="upload_status"></div> <div id="ul_status_${host}" class="upload_status"></div>
<div id="ul_progress_${host}" class="progress_bar"></div> <div id="ul_progress_${host}" class="progress_bar"></div>
<button id="ul_stop_btn_${host}" value="/sync/${host}/stop" class="command btn btn-block btn-lg btn-default" role="button">&#x23f9;<span class="btn_txt">Stop</span></button> <button id="ul_stop_btn_${host}" value="/sync/${host}/stop" class="command btn btn-block btn-lg btn-default" role="button">&#x23f9;<span class="btn_txt">Stop</span></button>
</div> </div>
` `;
if ( ul_cont_exists != undefined) { if ( ul_cont_exists != undefined) {
container_element.removeChild(ul_cont_exists); container_element.removeChild(ul_cont_exists);
} }
container_element.insertBefore(upload_dialog_cont_element, siblings[0]); container_element.insertBefore(upload_dialog_cont_element, siblings[0]);
document.getElementById(upload_dialog_cont_attributes["id"] + host).innerHTML = upload_dialog_HTML; document.getElementById(upload_dialog_cont_attributes.id + host).innerHTML = upload_dialog_HTML;
document.getElementById("ul_stop_btn_" + host).addEventListener("click", send_btn_cmd, false); document.getElementById("ul_stop_btn_" + host).addEventListener("click", send_btn_cmd, false);
document.getElementById("ul_status_" + host).innerHTML = upload_status_table; document.getElementById("ul_status_" + host).innerHTML = upload_status_table;
} }
@ -461,10 +495,10 @@ async function update_upload_status(current_upload) {
console.log("Updating upload status..."); console.log("Updating upload status...");
//~ console.log(current_upload); //~ console.log(current_upload);
if (current_upload.status == -1){ if (current_upload.status == -1){
console.log("Destroying dialog..." + current_upload.host) console.log("Destroying dialog..." + current_upload.host);
destroy_upload_status(); destroy_upload_status();
} else if (current_upload.status) { } else if (current_upload.status) {
console.log("Filling dialog...") console.log("Filling dialog...");
document.getElementById("ul_dialog_cont_" + current_upload.host).style.display = "block"; document.getElementById("ul_dialog_cont_" + current_upload.host).style.display = "block";
// Fill table // Fill table
document.getElementById("ul_status_progress_cnt_" + current_upload.host).innerHTML = current_upload.progress + " / " + current_upload.total_count + t9n[LOCALE].upload_sent_count_msg; document.getElementById("ul_status_progress_cnt_" + current_upload.host).innerHTML = current_upload.progress + " / " + current_upload.total_count + t9n[LOCALE].upload_sent_count_msg;
@ -583,7 +617,7 @@ function scan_hosts() {
// UI // UI
addEventListener("DOMContentLoaded", function() { addEventListener("DOMContentLoaded", function() {
adjust_timeline(); //~ adjust_timeline();
let commandButtons = document.querySelectorAll(".command"); let commandButtons = document.querySelectorAll(".command");
for (let i=0, l=commandButtons.length; i<l; i++) { for (let i=0, l=commandButtons.length; i<l; i++) {
let button = commandButtons[i]; let button = commandButtons[i];
@ -619,7 +653,7 @@ addEventListener("DOMContentLoaded", function() {
request.onload = send_ajax_cmd(command); request.onload = send_ajax_cmd(command);
} else if ( command.indexOf("/sync/") > -1 ) { } else if ( command.indexOf("/sync/") > -1 ) {
console.log("Sync command detected") console.log("Sync command detected");
currentUser.status_all = t9n[LOCALE].sync; currentUser.status_all = t9n[LOCALE].sync;
// Display dialog // Display dialog
display_upload_status(command); display_upload_status(command);

View File

@ -92,8 +92,13 @@ tr:nth-child(2n+1) {background-color: #888;}
height: 75px; height: 75px;
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 1px solid #aaaaaa; background-color:#F00;
} }
/*
[id^="tl_cont"]:nth-child(2n+1) [id^="tl_drag"] {
background-color:#255E70;
}
*/
[id^="tl_drag"] { [id^="tl_drag"] {
cursor: grab; cursor: grab;
text-align:center; text-align:center;
@ -101,12 +106,10 @@ tr:nth-child(2n+1) {background-color: #888;}
line-height: 75px; line-height: 75px;
width:100%; width:100%;
background-color:#1F7B99; background-color:#1F7B99;
background-size: 100% 100%; background-size: cover;
background-position: center;
box-shadow: inset 0 0 20px #0008; box-shadow: inset 0 0 20px #0008;
} }
[id^="tl_cont"]:nth-child(2n+1) [id^="tl_drag"] {
background-color:#255E70;
}
.client_container:nth-child(2n+1) {background-color:#444;} .client_container:nth-child(2n+1) {background-color:#444;}
.command {margin: 0 !important;} .command {margin: 0 !important;}

View File

@ -40,10 +40,10 @@
<p id="status_{{host}}">{{status_message}}</p> <p id="status_{{host}}">{{status_message}}</p>
<p id="signal_{{host}}"> <p id="signal_{{host}}">
<span style="">{{gui_l10n['str_link']}}:</span> <span style="">{{gui_l10n['str_link']}}:</span>
<span class="wl_indicator" id="wl_0"></span> <span class="wl_indicator" id="wl_{{host}}_0"></span>
<span class="wl_indicator" id="wl_1"></span> <span class="wl_indicator" id="wl_{{host}}_1"></span>
<span class="wl_indicator" id="wl_2"></span> <span class="wl_indicator" id="wl_{{host}}_2"></span>
<span class="wl_indicator" id="wl_3"></span> <span class="wl_indicator" id="wl_{{host}}_3"></span>
</p> </p>
<p id="loop_ind_{{host}}" class="indicator">{{gui_l10n['str_loop']}}</p> <p id="loop_ind_{{host}}" class="indicator">{{gui_l10n['str_loop']}}</p>
<p id="repeat_ind_{{host}}" class="indicator">{{gui_l10n['str_repeat']}}</p> <p id="repeat_ind_{{host}}" class="indicator">{{gui_l10n['str_repeat']}}</p>