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); $('