Implement shuffle from main menu
This commit is contained in:
1 parent
f8ef8b5667
commit
0bf16cda63
2 files changed
+120
-4
No files matched your search
+95
-2
@@ -14,7 +14,8 @@ var NavScope = Object.freeze({
|
||||
var cfg = JSON.parse(localStorage.getItem('clay-settings'));
|
||||
var currentArtist = null;
|
||||
|
||||
////////////////////// GENERAL API VARS //////////////////////
|
||||
////////////////////// GENERAL VARS //////////////////////
|
||||
var QUEUE_SIZE = 100;
|
||||
var USER_ID_CACHE_KEY = 'user-id';
|
||||
var jfSessionId;
|
||||
|
||||
@@ -229,6 +230,41 @@ function ringSlice(arr, start, end) {
|
||||
return Array.from({ length: count }, (_, k) => arr[(((start + k) % n) + n) % n]);
|
||||
}
|
||||
|
||||
// Fisher-Yates shuffles a copy of an array
|
||||
function shuffledCopy(arr) {
|
||||
const result = arr.slice();
|
||||
for (let i = result.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
const tmp = result[i];
|
||||
result[i] = result[j];
|
||||
result[j] = tmp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// flattens an album to tracks map into jfIds
|
||||
function albumMapJfIds(albumToTracksMap) {
|
||||
const jfIds = [];
|
||||
for (const tracks of albumToTracksMap.values()) {
|
||||
for (const track of tracks) {
|
||||
jfIds.push(track.JfId);
|
||||
}
|
||||
}
|
||||
return jfIds;
|
||||
}
|
||||
|
||||
// shuffle the order of whole groups while keeping each group's tracks together
|
||||
function groupedShuffle(groups, limit) {
|
||||
const result = [];
|
||||
for (const group of shuffledCopy(groups)) {
|
||||
for (const jfId of group) {
|
||||
result.push(jfId);
|
||||
if (result.length >= limit) { return result; }
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Pebble.addEventListener("appmessage", function (dict) {
|
||||
//console.log("payload", JSON.stringify(dict.payload));
|
||||
//console.log("expected NAV_SCOPE key", keys.BIDIR_MENU_NAV_SCOPE);
|
||||
@@ -236,12 +272,69 @@ Pebble.addEventListener("appmessage", function (dict) {
|
||||
const scope = payloadGet(dict.payload, "BIDIR_MENU_NAV_SCOPE");
|
||||
const subscope = payloadGet(dict.payload, "OUT_MENU_NAV_SUBSCOPE");
|
||||
const seqId = payloadGet(dict.payload, "OUT_PLAY_SEQ_ID");
|
||||
const shuffleMode = payloadGet(dict.payload, "OUT_SHUFFLE_MODE");
|
||||
|
||||
if (seqId !== undefined) {
|
||||
callAPI("POST", cfg.PRIV_BASE_URL + "/Sessions/" + jfSessionId + "/Playing?playCommand=PlayNow&itemIds=" + ringSlice(allJfIds, seqId, seqId+99), null);
|
||||
callAPI("POST", cfg.PRIV_BASE_URL + "/Sessions/" + jfSessionId + "/Playing?playCommand=PlayNow&itemIds=" + ringSlice(allJfIds, seqId, seqId+QUEUE_SIZE), null);
|
||||
}
|
||||
|
||||
if (scope !== undefined) {
|
||||
// scope shuffle
|
||||
if (shuffleMode) {
|
||||
// build a shuffled queue of jfIds for the current scope
|
||||
let queuedJfIds = [];
|
||||
switch (scope) {
|
||||
case NavScope.NAV_SCOPE_MAIN:
|
||||
if (shuffleMode == 1) {
|
||||
// choose 100 random jfIds from the entire library (truly random order)
|
||||
queuedJfIds = shuffledCopy(allJfIds).slice(0, QUEUE_SIZE);
|
||||
} else {
|
||||
// choose 100 random jfIds from the entire library (grouped by artist)
|
||||
const artistGroups = [];
|
||||
for (const artistToAlbumsMap of lookupMap.values()) {
|
||||
for (const albumToTracksMap of artistToAlbumsMap.values()) {
|
||||
artistGroups.push(albumMapJfIds(albumToTracksMap));
|
||||
}
|
||||
}
|
||||
queuedJfIds = groupedShuffle(artistGroups, QUEUE_SIZE);
|
||||
}
|
||||
break;
|
||||
case NavScope.NAV_SCOPE_ALBUMS: {
|
||||
const artistToAlbumsMap = lookupMap.get(Array.from(subscope)[0].toUpperCase());
|
||||
const albumToTracksMap = artistToAlbumsMap ? artistToAlbumsMap.get(subscope) : null;
|
||||
if (albumToTracksMap) {
|
||||
if (shuffleMode == 1) {
|
||||
// choose 100 random jfIds from the current artist (truly random order)
|
||||
queuedJfIds = shuffledCopy(albumMapJfIds(albumToTracksMap)).slice(0, QUEUE_SIZE);
|
||||
} else {
|
||||
// choose 100 random jfIds from the current artist (grouped by album)
|
||||
const albumGroups = [];
|
||||
for (const tracks of albumToTracksMap.values()) {
|
||||
albumGroups.push(tracks.map((track) => track.JfId));
|
||||
}
|
||||
queuedJfIds = groupedShuffle(albumGroups, QUEUE_SIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NavScope.NAV_SCOPE_ALBUM_TRACKS: {
|
||||
const artistToAlbumsMap = lookupMap.get(Array.from(currentArtist)[0].toUpperCase());
|
||||
const albumToTracksMap = artistToAlbumsMap ? artistToAlbumsMap.get(currentArtist) : null;
|
||||
const tracks = albumToTracksMap ? albumToTracksMap.get(subscope) : null;
|
||||
if (tracks) {
|
||||
// randomize the order of jfIds from the current album
|
||||
queuedJfIds = shuffledCopy(tracks.map((track) => track.JfId));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (queuedJfIds.length > 0) {
|
||||
callAPI("POST", cfg.PRIV_BASE_URL + "/Sessions/" + jfSessionId + "/Playing?playCommand=PlayNow&itemIds=" + queuedJfIds.join(','), null);
|
||||
}
|
||||
return; // no menu navigation
|
||||
}
|
||||
|
||||
// navigation
|
||||
let vanityList;
|
||||
let seqIdList = [];
|
||||
switch (scope) {
|
||||
|
||||
Reference in new issue
Block a user