import 'jquery/src/jquery.js';
import 'jquery-migrate/src/migrate.js';
import Popper from 'popper.js/dist/esm/popper.js';
import {
Modal,
Toast,
Tooltip,
} from 'bootstrap/js/src/index.js';
import {
getColor,
isOverflown,
setProgressBar,
secondsToStr,
} from './lib/util.mjs';
import {limitChars} from './lib/text.mjs';
$('#uploadSelectFile').on('change', function() {
// get the file name
const fileName = $(this).val().replace('C:\\fakepath\\', ' ');
// replace the "Choose a file" label
$(this).next('.custom-file-label').html(fileName);
});
// ----------------------
// ------ Playlist ------
// ----------------------
const pl_item_template = $('.playlist-item-template');
const pl_id_element = $('.playlist-item-id');
const pl_index_element = $('.playlist-item-index');
const pl_title_element = $('.playlist-item-title');
const pl_artist_element = $('.playlist-item-artist');
const pl_thumb_element = $('.playlist-item-thumbnail');
const pl_type_element = $('.playlist-item-type');
const pl_path_element = $('.playlist-item-path');
const pl_tag_edit_element = $('.playlist-item-edit');
const notag_element = $('.library-item-notag'); // these elements are shared with library
const tag_element = $('.library-item-tag');
const addTagModal = new Modal(document.getElementById('addTagModal'));
const playlist_loading = $('#playlist-loading');
const playlist_table = $('#playlist-table');
const playlist_empty = $('#playlist-empty');
const playlist_expand = $('.playlist-expand');
let playlist_items = null;
let playlist_ver = 0;
let playlist_current_index = 0;
let playlist_range_from = 0;
let playlist_range_to = 0;
let last_volume = 0;
let playing = false;
const playPauseBtn = $('#play-pause-btn');
const fastForwardBtn = $('#fast-forward-btn');
const volumeSlider = document.getElementById('volume-slider');
const playModeBtns = {
'one-shot': $('#one-shot-mode-btn'),
'random': $('#random-mode-btn'),
'repeat': $('#repeat-mode-btn'),
'autoplay': $('#autoplay-mode-btn'),
};
const playModeIcon = {
'one-shot': 'fa-tasks',
'random': 'fa-random',
'repeat': 'fa-redo',
'autoplay': 'fa-robot',
};
playPauseBtn.on('click', togglePlayPause);
fastForwardBtn.on('click', () => {
request('post', {
action: 'next',
});
});
document.getElementById('clear-playlist-btn').addEventListener('click', () => {
request('post', {action: 'clear'});
});
// eslint-disable-next-line guard-for-in
for (const playMode in playModeBtns) {
playModeBtns[playMode].on('click', () => {
changePlayMode(playMode);
});
}
function request(_url, _data, refresh = false) {
console.log(_data);
$.ajax({
type: 'POST',
url: _url,
data: _data,
statusCode: {
200: function(data) {
if (data.ver !== playlist_ver) {
checkForPlaylistUpdate();
}
updateControls(data.empty, data.play, data.mode, data.volume);
updatePlayerPlayhead(data.playhead);
},
403: function() {
location.reload(true);
},
},
});
if (refresh) {
location.reload(true);
}
}
function addPlaylistItem(item) {
pl_id_element.val(item.id);
pl_index_element.html(item.index + 1);
pl_title_element.html(item.title);
pl_artist_element.html(item.artist);
pl_thumb_element.attr('src', item.thumbnail);
pl_thumb_element.attr('alt', limitChars(item.title));
pl_type_element.html(item.type);
pl_path_element.html(item.path);
const item_copy = pl_item_template.clone();
item_copy.attr('id', 'playlist-item-' + item.index);
item_copy.addClass('playlist-item').removeClass('d-none');
const tags = item_copy.find('.playlist-item-tags');
tags.empty();
const tag_edit_copy = pl_tag_edit_element.clone();
tag_edit_copy.click(function() {
addTagModalShow(item.id, item.title, item.tags);
});
tag_edit_copy.appendTo(tags);
if (item.tags.length > 0) {
item.tags.forEach(function(tag_tuple) {
const tag_copy = tag_element.clone();
tag_copy.html(tag_tuple[0]);
tag_copy.addClass('badge-' + tag_tuple[1]);
tag_copy.appendTo(tags);
});
} else {
const tag_copy = notag_element.clone();
tag_copy.appendTo(tags);
}
item_copy.appendTo(playlist_table);
}
function displayPlaylist(data) {
playlist_table.animate({
opacity: 0,
}, 200, function() {
playlist_loading.hide();
$('.playlist-item').remove();
const items = data.items;
const length = data.length;
if (items.length === 0) {
playlist_empty.removeClass('d-none');
playlist_table.animate({opacity: 1}, 200);
return;
}
playlist_items = {};
for (const i in items) {
playlist_items[items[i].index] = items[i];
}
const start_from = data.start_from;
playlist_range_from = start_from;
playlist_range_to = start_from + items.length - 1;
if (items.length < length && start_from > 0) {
let _from = start_from - 5;
_from = _from > 0 ? _from : 0;
const _to = start_from - 1;
if (_to > 0) {
insertExpandPrompt(_from, start_from + length - 1, _from, _to, length);
}
}
items.forEach(
function(item) {
addPlaylistItem(item);
},
);
if (items.length < length && start_from + items.length < length) {
const _from = start_from + items.length;
let _to = start_from + items.length - 1 + 10;
_to = _to < length - 1 ? _to : length - 1;
if (start_from + items.length < _to) {
insertExpandPrompt(start_from, _to, _from, _to, length);
}
}
displayActiveItem(data.current_index);
updatePlayerInfo(playlist_items[data.current_index]);
bindPlaylistEvent();
playlist_table.animate({opacity: 1}, 200);
});
}
function displayActiveItem(current_index) {
$('.playlist-item').removeClass('table-active');
$('#playlist-item-' + current_index).addClass('table-active');
}
function insertExpandPrompt(real_from, real_to, display_from, display_to, total_length) {
const expand_copy = playlist_expand.clone();
expand_copy.addClass('playlist-item');
expand_copy.removeClass('d-none');
if (display_from !== display_to) {
expand_copy.find('.playlist-expand-item-range').html((display_from + 1) + '~' + (display_to + 1) +
' of ' + (total_length) + ' items');
} else {
expand_copy.find('.playlist-expand-item-range').html(display_from + ' of ' + (total_length) + ' items');
}
expand_copy.addClass('playlist-item');
expand_copy.appendTo(playlist_table);
expand_copy.click(function() {
playlist_range_from = real_from;
playlist_range_to = real_to;
updatePlaylist();
});
}
function updatePlaylist() {
playlist_table.animate({
opacity: 0,
}, 200, function() {
playlist_empty.addClass('d-none');
playlist_loading.show();
playlist_table.find('.playlist-item').css('opacity', 0);
let data = {};
if (!(playlist_range_from === 0 && playlist_range_to === 0)) {
data = {
range_from: playlist_range_from,
range_to: playlist_range_to,
};
}
$.ajax({
type: 'GET',
url: 'playlist',
data: data,
statusCode: {
200: displayPlaylist,
},
});
playlist_table.animate({
opacity: 1,
}, 200);
});
}
function checkForPlaylistUpdate() {
$.ajax({
type: 'POST',
url: 'post',
statusCode: {
200: function(data) {
if (data.ver !== playlist_ver) {
playlist_ver = data.ver;
playlist_range_from = 0;
playlist_range_to = 0;
updatePlaylist();
}
if (data.current_index !== playlist_current_index) {
if (data.current_index !== -1) {
if ((data.current_index > playlist_range_to || data.current_index < playlist_range_from)) {
playlist_range_from = 0;
playlist_range_to = 0;
updatePlaylist();
} else {
playlist_current_index = data.current_index;
updatePlayerInfo(playlist_items[data.current_index]);
displayActiveItem(data.current_index);
}
}
}
updateControls(data.empty, data.play, data.mode, data.volume);
if (!data.empty) {
updatePlayerPlayhead(data.playhead);
}
},
},
});
}
function bindPlaylistEvent() {
$('.playlist-item-play').unbind().click(
function(e) {
request('post', {
'play_music': ($(e.currentTarget).parent().parent().parent().find('.playlist-item-index').html() - 1),
});
},
);
$('.playlist-item-trash').unbind().click(
function(e) {
request('post', {
'delete_music': ($(e.currentTarget).parent().parent().parent().find('.playlist-item-index').html() - 1),
});
},
);
}
function updateControls(empty, play, mode, volume) {
updatePlayerControls(play, empty);
if (empty) {
playPauseBtn.prop('disabled', true);
fastForwardBtn.prop('disabled', true);
} else {
playPauseBtn.prop('disabled', false);
fastForwardBtn.prop('disabled', false);
if (play) {
playing = true;
playPauseBtn.find('[data-fa-i2svg]').removeClass('fa-play').addClass('fa-pause');
// PR #180: Since this button changes behavior dynamically, we change its
// ARIA labels in JS instead of only adding them statically in the HTML
playPauseBtn.attr('aria-label', 'Pause');
} else {
playing = false;
playPauseBtn.find('[data-fa-i2svg]').removeClass('fa-pause').addClass('fa-play');
// PR #180: Since this button changes behavior dynamically, we change its
// ARIA labels in JS instead of only adding them statically in the HTML
playPauseBtn.attr('aria-label', 'Play');
}
}
for (const otherMode of Object.values(playModeBtns)) {
otherMode.removeClass('active');
}
playModeBtns[mode].addClass('active');
const playModeIndicator = $('#modeIndicator');
for (const icon_class of Object.values(playModeIcon)) {
playModeIndicator.removeClass(icon_class);
}
playModeIndicator.addClass(playModeIcon[mode]);
if (volume !== last_volume) {
last_volume = volume;
if (volume > 1) {
volumeSlider.value = 1;
} else if (volume < 0) {
volumeSlider.value = 0;
} else {
volumeSlider.value = volume;
}
}
}
function togglePlayPause() {
if (playing) {
request('post', {
action: 'pause',
});
} else {
request('post', {
action: 'resume',
});
}
}
function changePlayMode(mode) {
request('post', {
action: mode,
});
}
// ---------------------
// ------ Browser ------
// ---------------------
const filters = {
file: $('#filter-type-file'),
url: $('#filter-type-url'),
radio: $('#filter-type-radio'),
};
const filter_dir = $('#filter-dir');
const filter_keywords = $('#filter-keywords');
// eslint-disable-next-line guard-for-in
for (const filter in filters) {
filters[filter].on('click', (e) => {
setFilterType(e, filter);
});
}
function setFilterType(event, type) {
event.preventDefault();
if (filters[type].hasClass('active')) {
filters[type].removeClass('active btn-primary').addClass('btn-secondary');
filters[type].find('input[type=radio]').removeAttr('checked');
} else {
filters[type].removeClass('btn-secondary').addClass('active btn-primary');
filters[type].find('input[type=radio]').attr('checked', 'checked');
}
if (type === 'file') {
filter_dir.prop('disabled', !filters['file'].hasClass('active'));
}
updateResults();
}
filter_dir.change(function() {
updateResults();
});
filter_keywords.change(function() {
updateResults();
});
const item_template = $('#library-item');
function bindLibraryResultEvent() {
$('.library-thumb-col').unbind().hover(
function(e) {
$(e.currentTarget).find('.library-thumb-grp').addClass('library-thumb-grp-hover');
},
function(e) {
$(e.currentTarget).find('.library-thumb-grp').removeClass('library-thumb-grp-hover');
},
);
$('.library-info-title').unbind().hover(
function(e) {
$(e.currentTarget).parent().find('.library-thumb-grp').addClass('library-thumb-grp-hover');
},
function(e) {
$(e.currentTarget).parent().find('.library-thumb-grp').removeClass('library-thumb-grp-hover');
},
);
$('.library-item-play').unbind().click(
function(e) {
request('post', {
'add_item_at_once': $(e.currentTarget).parent().parent().parent().find('.library-item-id').val(),
});
},
);
$('.library-item-trash').unbind().click(
function(e) {
request('post', {
'delete_item_from_library': $(e.currentTarget).parent().parent().find('.library-item-id').val(),
});
updateResults(active_page);
},
);
$('.library-item-download').unbind().click(
function(e) {
const id = $(e.currentTarget).parent().parent().find('.library-item-id').val();
// window.open('/download?id=' + id);
downloadId(id);
},
);
$('.library-item-add-next').unbind().click(
function(e) {
const id = $(e.currentTarget).parent().parent().find('.library-item-id').val();
request('post', {
'add_item_next': id,
});
},
);
$('.library-item-add-bottom').unbind().click(
function(e) {
const id = $(e.currentTarget).parent().parent().find('.library-item-id').val();
request('post', {
'add_item_bottom': id,
});
},
);
}
const lib_filter_tag_group = $('#filter-tags');
const lib_filter_tag_element = $('.filter-tag');
const lib_group = $('#library-group');
const id_element = $('.library-item-id');
const title_element = $('.library-item-title');
const artist_element = $('.library-item-artist');
const thumb_element = $('.library-item-thumb');
const type_element = $('.library-item-type');
const path_element = $('.library-item-path');
const tag_edit_element = $('.library-item-edit');
// var notag_element = $(".library-item-notag");
// var tag_element = $(".library-item-tag");
const library_tags = [];
function updateLibraryControls() {
$.ajax({
type: 'GET',
url: 'library/info',
statusCode: {
200: displayLibraryControls,
403: function() {
location.reload(true);
},
},
});
}
function displayLibraryControls(data) {
$('#maxUploadFileSize').val(data.max_upload_file_size);
if (data.upload_enabled) {
$('#uploadDisabled').val('false');
$('#upload').show();
} else {
$('#uploadDisabled').val('true');
$('#upload').hide();
}
if (data.delete_allowed) {
$('#deleteAllowed').val('true');
$('.library-delete').show();
} else {
$('#uploadDisabled').val('false');
$('.library-delete').hide();
}
const select = $('#filter-dir');
const dataList = $('#upload-target-dirs');
select.find('option').remove();
dataList.find('option').remove();
if (data.dirs.length > 0) {
console.log(data.dirs);
data.dirs.forEach(function(dir) {
$('').appendTo(select);
$('