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.
*