diff --git a/resources/assets/js/app.vue b/resources/assets/js/app.vue index 04b31604..a16a9807 100644 --- a/resources/assets/js/app.vue +++ b/resources/assets/js/app.vue @@ -187,6 +187,7 @@ * Load the Favorites view. */ loadFavorites() { + this.$broadcast('favorites:load'); this.loadMainView('favorites'); }, diff --git a/resources/assets/js/components/main-wrapper/main-content/favorites.vue b/resources/assets/js/components/main-wrapper/main-content/favorites.vue index 0304c878..7e2c7969 100644 --- a/resources/assets/js/components/main-wrapper/main-content/favorites.vue +++ b/resources/assets/js/components/main-wrapper/main-content/favorites.vue @@ -8,6 +8,12 @@ + + + {{ meta.songCount }} song{{ meta.songCount === 1 ? '' : 's' }} + • + {{ meta.totalLength }} +
@@ -50,16 +56,12 @@ + + diff --git a/resources/assets/js/components/main-wrapper/sidebar/playlists.vue b/resources/assets/js/components/main-wrapper/sidebar/playlists.vue index 25b9b99f..430a2f12 100644 --- a/resources/assets/js/components/main-wrapper/sidebar/playlists.vue +++ b/resources/assets/js/components/main-wrapper/sidebar/playlists.vue @@ -13,80 +13,38 @@ @@ -199,44 +62,6 @@ @import "resources/assets/sass/partials/_mixins.scss"; #playlists { - .menu { - a { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - a::before { - content: "\f0f6"; - } - - a.favorites::before { - content: "\f004"; - color: $colorHeart; - } - - .playlist { - user-select: none; - - input { - display: none; - - width: calc(100% - 32px); - margin: 5px 16px; - } - - &.editing { - a { - display: none; - } - - input { - display: block; - } - } - } - } - form.create { padding: 8px 16px; diff --git a/resources/assets/js/components/shared/song-list.vue b/resources/assets/js/components/shared/song-list.vue index fc0cfce1..e41d74b3 100644 --- a/resources/assets/js/components/shared/song-list.vue +++ b/resources/assets/js/components/shared/song-list.vue @@ -79,12 +79,19 @@ watch: { /** - * Watch the items, so that we can always make sure a queue is not sorted in any ways. + * Watch the items. */ items() { + // Make sure a queue is not sorted in any ways. if (this.type === 'queue') { this.sortKey = ''; } + + // Dispatch this event for the parent to update the song count and duration status. + this.$dispatch('songlist:changed', { + songCount: this.items.length, + totalLength: songStore.getLength(this.items, true), + }); }, }, diff --git a/resources/assets/js/mixins/has-add-to-menu.js b/resources/assets/js/mixins/has-add-to-menu.js deleted file mode 100644 index 4ac232cd..00000000 --- a/resources/assets/js/mixins/has-add-to-menu.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Add necessary functionalities into a (song-list type) component. - */ - -import addToMenu from '../components/shared/add-to-menu.vue'; - -export default { - components: { addToMenu }, - - data() { - return { - showingAddToMenu: false, - }; - }, - - events: { - 'add-to-menu:close': function () { - this.showingAddToMenu = false; - }, - }, -}; diff --git a/resources/assets/js/mixins/has-song-list.js b/resources/assets/js/mixins/has-song-list.js new file mode 100644 index 00000000..734513fe --- /dev/null +++ b/resources/assets/js/mixins/has-song-list.js @@ -0,0 +1,62 @@ +/** + * Add necessary functionalities into a view that contains a song-list component. + */ + +import _ from 'lodash'; + +import playback from '../services/playback'; +import addToMenu from '../components/shared/add-to-menu.vue'; +import songList from '../components/shared/song-list.vue'; + +export default { + components: { addToMenu, songList }, + + data() { + return { + /** + * Whether or not to show the "Add To" button in the header. + * + * @type {Boolean} + */ + showingAddToMenu: false, + + /** + * An array of selected songs in the list. + * + * @type {Array} + */ + selectedSongs: [], + + meta: { + songCount: 0, + totalLength: '00:00', + }, + }; + }, + + methods: { + /** + * Shuffles the currently selected songs. + */ + shuffleSelected() { + if (this.selectedSongs.length < 2) { + return; + } + + playback.queueAndPlay(this.selectedSongs, true); + }, + }, + + events: { + /** + * Listen to add-to-menu:close event to set showingAddToMenu to false (and subsequently close the menu). + */ + 'add-to-menu:close': function () { + this.showingAddToMenu = false; + }, + + 'songlist:changed': function (meta) { + this.meta = _.assign(this.meta, meta); + }, + }, +}; diff --git a/resources/assets/js/mixins/shuffle-selected.js b/resources/assets/js/mixins/shuffle-selected.js deleted file mode 100644 index 889e6ef2..00000000 --- a/resources/assets/js/mixins/shuffle-selected.js +++ /dev/null @@ -1,28 +0,0 @@ -import $ from 'jquery'; - -import playback from '../services/playback'; - -/** - * Add a "shuffle selected" functionality to any component containing a song-list component using this mixin. - * Such a component should: - * - pass "selectedSongs" SYNC prop into the song-list component, e.g. - * - * - trigger shuffling with shuffleSelected() method - */ -export default { - data() { - return { - selectedSongs: [], - }; - }, - - methods: { - shuffleSelected() { - if (this.selectedSongs.length < 2) { - return; - } - - playback.queueAndPlay(this.selectedSongs, true); - }, - }, -}; diff --git a/resources/assets/js/stores/favorite.js b/resources/assets/js/stores/favorite.js index d6f275c2..7ee49a9d 100644 --- a/resources/assets/js/stores/favorite.js +++ b/resources/assets/js/stores/favorite.js @@ -6,6 +6,8 @@ import utils from '../services/utils'; export default { state: { songs: [], + length: 0, + fmtLength: '', }, all() { diff --git a/resources/assets/js/stores/song.js b/resources/assets/js/stores/song.js index 85d1839f..b405989e 100644 --- a/resources/assets/js/stores/song.js +++ b/resources/assets/js/stores/song.js @@ -58,6 +58,24 @@ export default { }); }, + /** + * Get the total duration of some songs. + * + * @param {Array} songs + * @param {boolean} toHis Wheter to convert the duration into H:i:s format + * + * @return {float|string} + */ + getLength(songs, toHis) { + var duration = _.reduce(songs, (length, song) => length + song.length, 0); + + if (toHis) { + return utils.secondsToHis(duration); + } + + return duration; + }, + /** * Get all songs. *