Skip to content

Commit

Permalink
Add recently played albums and artists on home (#647)
Browse files Browse the repository at this point in the history
  • Loading branch information
robbevp authored Nov 20, 2021
1 parent 83f8133 commit ff247ea
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 8 deletions.
9 changes: 9 additions & 0 deletions src/comparators.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,12 @@ export function compareAlbumsByReleaseFirst(newestFirst = false) {
return (order = order === 0 ? compareStrings(a1.id, a2.id) : order);
};
}

export function compareByRecentlyPlayed(stats) {
return function (i1, i2) {
return (
(stats[i2.id]?.last_played_at || new Date(0)) -
(stats[i1.id]?.last_played_at || new Date(0))
);
};
}
12 changes: 8 additions & 4 deletions src/components/TracksTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@
<TrackGenres :track="props.item" />
</template>
<template v-slot:item.play_count="props">
{{ playCountsByTrack[props.item.id] || 0 }}
{{
(playStatsByTrack[props.item.id] &&
playStatsByTrack[props.item.id].count) ||
0
}}
</template>
<template v-slot:item.actions="props">
<TrackActions :track="props.item" />
Expand Down Expand Up @@ -193,7 +197,7 @@ export default {
computed: {
...mapGetters("auth", ["isModerator"]),
...mapGetters("player", ["currentTrack"]),
...mapGetters("plays", ["playCountsByTrack"]),
...mapGetters("plays", ["playStatsByTrack"]),
...mapState("albums", ["albums"]),
...mapState("genres", ["genres"]),
...mapState("tracks", { tracksObj: "tracks" }),
Expand Down Expand Up @@ -242,8 +246,8 @@ export default {
break;
case "play_count":
sortFunction = (t1, t2) =>
(this.playCountsByTrack[t1.id] || 0) -
(this.playCountsByTrack[t2.id] || 0);
(this.playStatsByTrack[t1.id]?.count || 0) -
(this.playStatsByTrack[t2.id]?.count || 0);
break;
case "title":
sortFunction = (t1, t2) =>
Expand Down
2 changes: 2 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@
"random-artists": "Random artists",
"recently-added-albums": "Recently added albums",
"recently-added-artists": "Recently added artists",
"recently-played-albums": "Recently played albums",
"recently-played-artists": "Recently played artists",
"recently-released": "Recently released"
},
"image": {
Expand Down
2 changes: 2 additions & 0 deletions src/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@
"random-artists": "Random artiesten",
"recently-added-albums": "Recent toegevoegde albums",
"recently-added-artists": "Recent toegevoegde artiesten",
"recently-played-albums": "Recent afgespeelde albums",
"recently-played-artists": "Recent afgespeelde artiesten",
"recently-released": "Recent uitgebracht"
},
"image": {
Expand Down
66 changes: 63 additions & 3 deletions src/store/plays.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,73 @@ export default {
},
getters: {
plays: (state) => Object.values(state.plays),
playCountsByTrack: (state, getters) => {
playStatsByTrack: (state, getters) => {
const result = {};
for (let play of getters.plays) {
if (!(play.track_id in result)) {
result[play.track_id] = 0;
result[play.track_id] = {
count: 1,
last_played_at: new Date(play.played_at),
};
} else {
result[play.track_id].count++;

if (result[play.track_id].last_played_at < new Date(play.played_at)) {
result[play.track_id].last_played_at = new Date(play.played_at);
}
}
}
return result;
},
playStatsByAlbum: (state, getters, rootState) => {
const result = {};
for (let track_id in getters.playStatsByTrack) {
// If this track is not (yet) loaded, we need to skip it
if (!rootState.tracks.tracks[track_id]) {
continue;
}

const album_id = rootState.tracks.tracks[track_id].album_id;
if (!(album_id in result)) {
result[album_id] = {
last_played_at: getters.playStatsByTrack[track_id].last_played_at,
};
} else if (
result[album_id].last_played_at <
getters.playStatsByTrack[track_id].plast_layed_at
) {
result[album_id].last_played_at =
getters.playStatsByTrack[track_id].last_played_at;
}
}
return result;
},
playStatsByArtist: (state, getters, rootState) => {
const result = {};
for (let track_id in getters.playStatsByTrack) {
// If this track is not (yet) loaded, we need to skip it
if (!rootState.tracks.tracks[track_id]) {
continue;
}

for (let ta of rootState.tracks.tracks[track_id].track_artists) {
if (!(ta.artist_id in result)) {
result[ta.artist_id] = {
count: getters.playStatsByTrack[track_id].count,
last_played_at: getters.playStatsByTrack[track_id].last_played_at,
};
} else {
result[ta.artist_id].count +=
getters.playStatsByTrack[track_id].count;
if (
result[ta.artist_id].last_played_at <
getters.playStatsByTrack[track_id].plast_layed_at
) {
result[ta.artist_id].last_played_at =
getters.playStatsByTrack[track_id].last_played_at;
}
}
}
result[play.track_id]++;
}
return result;
},
Expand Down
78 changes: 77 additions & 1 deletion src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,82 @@
</template>
</VDataIterator>
</VContainer>
<VContainer fluid>
<VDataIterator
:footer-props="{
disableItemsPerPage: true,
itemsPerPageOptions: [numberOfItems],
}"
:items="albums"
:custom-sort="recentlyPlayedAlbumsSort"
:items-per-page="numberOfItems"
>
<template v-slot:header>
<h2 class="text-h4">
{{ $t("home.recently-played-albums") }}
</h2>
</template>
<template v-slot:default="props">
<VRow class="my-0">
<VCol
v-for="item in props.items"
:key="item.id"
lg="3"
md="4"
sm="6"
xl="2"
cols="6"
>
<AlbumCard :album="item" />
</VCol>
</VRow>
</template>
</VDataIterator>
</VContainer>
<VContainer fluid>
<VDataIterator
:footer-props="{
disableItemsPerPage: true,
itemsPerPageOptions: [numberOfItems],
}"
:items="artists"
:custom-sort="recentlyPlayedArtistsSort"
:items-per-page="numberOfItems"
>
<template v-slot:header>
<h2 class="text-h4">
{{ $t("home.recently-played-artists") }}
</h2>
</template>
<template v-slot:default="props">
<VRow class="my-0">
<VCol
v-for="item in props.items"
:key="item.id"
lg="3"
md="4"
sm="6"
xl="2"
cols="6"
>
<ArtistCard :artist="item" />
</VCol>
</VRow>
</template>
</VDataIterator>
</VContainer>
</div>
</template>

<script>
import { mapGetters } from "vuex";
import AlbumCard from "../components/AlbumCard";
import ArtistCard from "../components/ArtistCard";
import { compareAlbumsByReleaseFirst, compareStrings } from "../comparators";
import {
compareAlbumsByReleaseFirst,
compareByRecentlyPlayed,
compareStrings,
} from "../comparators";
export default {
name: "Home",
Expand All @@ -217,6 +285,12 @@ export default {
});
return items;
},
recentlyPlayedAlbumsSort(albums) {
return albums.sort(compareByRecentlyPlayed(this.playStatsByAlbum));
},
recentlyPlayedArtistsSort(artists) {
return artists.sort(compareByRecentlyPlayed(this.playStatsByArtist));
},
randomSort(items) {
const newItems = [...items];
for (let i = newItems.length - 1; i > 0; i--) {
Expand All @@ -231,6 +305,8 @@ export default {
albums: "albums/albums",
albumsOnThisDay: "albums/albumsOnThisDay",
artists: "artists/artists",
playStatsByAlbum: "plays/playStatsByAlbum",
playStatsByArtist: "plays/playStatsByArtist",
}),
randomAlbums() {
return this.randomSort(this.albums);
Expand Down

0 comments on commit ff247ea

Please sign in to comment.