Redesign Jellyfin API data operations

This commit is contained in:
RandyTheSilly committed 2026-10-10 17:47:12 -04:00
1 parent 79045d8b4b
commit f7b4805ba1
2 files changed
+48 -70

No files matched your search

+11 -26
View File
@@ -4,13 +4,10 @@
typedef enum {
NAV_SCOPE_MAIN = 0,
NAV_SCOPE_ALPHA = 1,
NAV_SCOPE_SEARCH = 1,
NAV_SCOPE_ARTISTS = 2,
NAV_SCOPE_ALBUMS = 3,
NAV_SCOPE_ALBUM_TRACKS = 4,
NAV_SCOPE_PLAYLISTS = 5,
NAV_SCOPE_PLAYLIST_TRACKS = 6,
NAV_SCOPE_NOW_PLAYING = 7
} NavScope;
// layer-age
@@ -40,7 +37,7 @@ static GFont s_font_chicago;
#endif
#endif
static const GRect s_menu_grect = GRect(MARGIN_X, BAR_HEIGHT + MARGIN_Y, PBL_DISPLAY_WIDTH - (MARGIN_X * 2), PBL_DISPLAY_HEIGHT - (MARGIN_Y * 2));
static const char *s_main_menu_options[3] = {"Artists", "Playlists", "Now Playing"};
static const char *s_main_menu_options[4] = {"Shuffle Songs", "Shuffle Artists", "> All Artists", "> Search Artists"};
////////////////////// PKJS //////////////////////
@@ -52,7 +49,7 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
}
}
static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleInScope) {
static void to_pkjs_scope_change(NavScope scope) {
if (!s_pkjs_ready) {
return;
}
@@ -65,16 +62,6 @@ static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleI
}
dict_write_uint8(out, MESSAGE_KEY_OUT_MENU_NAV_SCOPE, scope);
if (shuffleInScope) {
// tell PKJS to shuffle if a shuffle option was clicked
dict_write_uint8(out, MESSAGE_KEY_OUT_SHUFFLE_MODE, shuffleInScope); // if true, PKJS side shuffles IDs in scope and passes them to JF API
} else if (jfId) {
// otherwise, send the selected jfId, if present;
// for artists/albums/playlists, determines next data set returned to C;
// for tracks, starts sequential playback (sequential relative to entire library unless scope is playlist)
dict_write_cstring(out, MESSAGE_KEY_OUT_JFID, jfId);
}
result = app_message_outbox_send();
if (result != APP_MSG_OK) {
return;
@@ -84,12 +71,11 @@ static void to_pkjs_scope_change(NavScope scope, const char *jfId, bool shuffleI
static uint16_t menu_get_num_rows(MenuLayer *menu_layer, uint16_t section_index, void *context) {
switch (s_current_menu_scope) {
case NAV_SCOPE_MAIN:
return 3;
case NAV_SCOPE_ALPHA:
return 4;
case NAV_SCOPE_SEARCH:
case NAV_SCOPE_ARTISTS:
case NAV_SCOPE_ALBUMS:
case NAV_SCOPE_ALBUM_TRACKS:
case NAV_SCOPE_PLAYLISTS:
default:
return 99;
}
@@ -100,11 +86,10 @@ static void menu_draw_row(GContext *ctx, const Layer *cell_layer, MenuIndex *cel
case NAV_SCOPE_MAIN:
custom_menu_cell_title_draw(ctx, cell_layer, s_main_menu_options[cell_index->row], NULL, s_font_chicago, MARGIN_X);
break;
case NAV_SCOPE_ALPHA:
case NAV_SCOPE_SEARCH:
case NAV_SCOPE_ARTISTS:
case NAV_SCOPE_ALBUMS:
case NAV_SCOPE_ALBUM_TRACKS:
case NAV_SCOPE_PLAYLISTS:
default:
return;
}
@@ -115,20 +100,20 @@ static void menu_select_click(struct MenuLayer *menu_layer, MenuIndex *clicked_i
case NAV_SCOPE_MAIN:
switch (clicked_index->row) {
case 0:
to_pkjs_scope_change(NAV_SCOPE_ALPHA, NULL, false);
break;
case 1:
to_pkjs_scope_change(NAV_SCOPE_PLAYLISTS, NULL, false);
break;
case 2:
to_pkjs_scope_change(NAV_SCOPE_ARTISTS);
break;
default:
to_pkjs_scope_change(NAV_SCOPE_NOW_PLAYING, NULL, false); // TODO
to_pkjs_scope_change(NAV_SCOPE_SEARCH);
}
return;
case NAV_SCOPE_ALPHA:
case NAV_SCOPE_SEARCH:
case NAV_SCOPE_ARTISTS:
case NAV_SCOPE_ALBUMS:
case NAV_SCOPE_ALBUM_TRACKS:
case NAV_SCOPE_PLAYLISTS:
default:
return;
}
+37 -44
View File
@@ -7,7 +7,7 @@ var cfg = JSON.parse(localStorage.getItem('clay-settings'));
Pebble.addEventListener("ready", function () {
// store cache of library info from Jellyfin
if (cfg.PRIV_BASE_URL && cfg.PRIV_API_KEY && cfg.PRIV_USERNAME) {
// get userId
// get userId from Jellyfin
callAPI("GET", cfg.PRIV_BASE_URL + "/Users", function (userIdResp) {
if (userIdResp === null) { return; }
const userIdObj = JSON.parse(userIdResp);
@@ -19,63 +19,56 @@ Pebble.addEventListener("ready", function () {
}
}
// get library
callAPI("GET", cfg.PRIV_BASE_URL + "/Items?userId=" + userId + "&recursive=true&includeItemTypes=Audio&sortBy=AlbumArtist,Artist,ProductionYear,Album,IndexNumber,Name'", function (libResp) {
// get library response from Jellyfin
callAPI("GET", cfg.PRIV_BASE_URL + "/Items?userId=" + userId + "&recursive=true&includeItemTypes=Audio&sortBy=AlbumArtist,Artist,ProductionYear,Album,IndexNumber,Name", function (libResp) {
if (libResp === null) { return; }
const libObj = JSON.parse(libResp);
// extraction output:
// a map of artists to arrays of albums
// a map of albums to arrays of contained tracks
// extract alphanumerical list of artists
let artists = [];
let lastArtist = "";
let unknownFound = false;
// format response for jellyPod
//// build tracks array and lookupMap (currently just binds alpha to artists)
let jpTracksArr = [];
const lookupMap = new Map();
let lastAlbumInfo = {AlbumArtist: "", AlbumName: "", AlbumYear: 0};
for (const track of libObj.Items) {
if (!track.Name) {
continue;
}
let albumArtist = "unknown artist";
if (track.AlbumArtist) {
if (track.AlbumArtist != lastArtist) {
artists.push(track.AlbumArtist);
lastArtist = track.AlbumArtist;
}
albumArtist = track.AlbumArtist;
} else if (track.Artists.length > 0) {
if (track.Artists[0] != lastArtist) {
artists.push(track.Artists[0]);
lastArtist = track.Artists[0];
albumArtist = track.Artists[0]
}
} else if (!unknownFound) {
unknownFound = true;
}
}
if (unknownFound) {
artists.push("unknown artist");
}
console.log(artists);
// sort artists into arrays mapped to first characters
const charMap = new Map();
let currentChar = "";
let currentArr = [];
for (const artistName of artists) {
char = Array.from(artistName)[0].toUpperCase();
if (currentChar == "") {
currentChar = char;
}
if (char == currentChar) {
currentArr.push(artistName);
const albumName = track.Album ? track.Album : "unknown album";
if (lastAlbumInfo.AlbumArtist != albumArtist) {
firstChar = Array.from(albumArtist)[0].toUpperCase();
if (!lookupMap.has(firstChar)) {
lookupMap.set(firstChar, [albumArtist]);
} else {
charMap.set(currentChar, currentArr);
currentChar = char;
currentArr = [artistName];
lookupMap.get(firstChar).push(albumArtist);
};
if (lastAlbumInfo.AlbumName != albumName) {
lastAlbumInfo = {
AlbumArtist: albumArtist,
AlbumName: track.Album ? track.Album : "unknown album",
AlbumYear: track.ProductionYear ? track.ProductionYear : 1970
};
}
}
if (currentChar !== "") {
charMap.set(currentChar, currentArr);
}
console.log(...charMap);
jpTracksArr.push({
TrackName: track.Name,
JfId: track.Id,
AlbumInfo: lastAlbumInfo
});
}
//console.log(jpTracksArr);
//console.log("Items:", libObj.Items.length, "Tracks:", jpTracksArr.length);
//console.log(...lookupMap);
Pebble.sendAppMessage({ PKJS_READY: 1 });
});
});
}
});