-
-
Notifications
You must be signed in to change notification settings - Fork 64
Proof of Concept for sorting of playlists #225
Conversation
+ added ;0 which stops electron from cloning weird stuff (which causes errors) + added a catch for the javascript execution promise (which happens if there is a problem loading the script)
+ sorting of newly loaded element via the observer function + split up functionalities in different functions
+ using a map now for the dom data - acces through an id (song name + artist name + album name) + data that has been already set (merged) does not get overwritten with musickit cache anymore (which meant the data had to be merged again) + updated regex for language code of url - can be 2 to 5 characters now (not sure if stuff like 'en_EN' is used or only 'en') + regex check ok now pls?
+ check the data that gets read from cache if it's usable + if data is missing disable sort feature
+ moving functions around + split up a function that got a bit too large
+ duplicates will no longer be removed in the document by the sorting + duplicates and queue don't work together
Sorting the library does not seem viableBuggy behaviourApples API has problems fetching the songs Example:callApple({limit: 100, offset: 0});
async function callApple({limit, offset}) {
let developerToken = MusicKit.getInstance().api.library.developerToken;
let mediaToken = MusicKit.getInstance().api.library.userToken;
let url = 'https://amp-api.music.apple.com/v1/me/library/songs?limit=' + limit + '&offset=' + offset;
fetch(url, {
method: 'GET',
headers: {
'authorization': 'Bearer ' + developerToken,
'media-user-token': mediaToken
}
}).then(respone => respone.json()).then(data => {
console.log('offset:', offset, data);
if (data.next) {
callApple({limit: limit, offset: offset + 100});
}
}).catch(reason => console.error(reason));
} Apple returned 104 out of 221 songs (and even has false duplicates) DocumentApple creates skeleton elements that get filled with the actual song-data later on While scrolling elements get added and removed to the document (on top of managing their location by using the OtherThe cached object for library songs is not reliable in terms of handling duplicates If we were to implement sorting etc. it might be best to replace the current document with our own logic |
+ added support for sorting by different types + ascending / descending + removed the 'fixToAllowSort' stuff - might have been fixed by some other changes (it did not occur anymore) + generalised the sorting functions a bit + removed unused code for handling duplicates in queue
+ added an indicator which type of sorting is applied (placeholder version) + shuffled around functions to group them together a bit better + fixed a bug where sorting the queue did not happen (blockQueueSorting had the initial value of 'true') + created a compare function which gets used for both instances of sorting (queue and songs)
PerformanceTest with 100 elements Using one of these makes appending take ~ 5 ms while (contentNode.firstChild) {
contentNode.firstChild.remove();
} contentNode.replaceChildren(); Using this makes removing instant but appending will take ~ 35 ms contentNode.innerHTLM = ''; Apparently, before being able to append a node somewhere else it needs to be removed from its current parent Using You're basically running into the same problem (removing nodes from one parent and appending them to another) Using We cannot remove these elements entirely or simply change the text (of the artist name, etc.), since we cannot copy the event listeners of the nodes (and assign them to different nodes) |
Sorting Playlists
Getting the data
At the start we get the playlist ID of the currently loaded page
This also makes sure that we actually do something - no playlist ID means nothing to do
Once we know we are in a playlist page we go through the document and get all nodes
For each node we create a unique ID by combining the following elements:
After that we can access the cache for MusicKit to get the data that was requested
(Which means we won't have to call the API as well)
We go through each cached song and assign a node to it
We also store the original index, in case we want to return to the original sorting
Duplicates
For both the node elements and the cached song data we retain a count on how many instances (duplicates) of that element exist
We do that by having a map with the either the song ID or the combined ID of the node element as the key
Once we notice that the maps for the nodes or the songs aleady have the ID as an entry we interact with this duplicate map
Sorting
Once we click on a header cell (like album, artists, ...) we save the corresponding attribute name of the song element, which we can use to sort
If we sort by artists that would be
artistName
, if we sort by time it would bedurationInMillis
This allows us to have a single function which handles sorting by simply accessing these attributes like this:
songElement.data.attributes[sortConfig.attributeName]
Newly loaded items (infinite scroll)
Once we scroll to the end of the page new elements (nodes) get loaded
(And new request might get sent - if they're not already cached - that is why we process the cache again)
We handle these by appending an observer to the 'content node', to which these new nodes get appened to
In this observer we check for
DIV
nodes and add them to oursongNodes
mapAfter that we go through our
song
map to check if any of them are still missing theirnode
elementsOnce we have done all that we can sort again
Sorting the queue
Once the user double clicks a row, or clicks the play icon the queue will get loaded with all songs after the one you clicked on
In reality all songs of the playlist are in the queue but by using a
position
variable these elements get skippedSince we cannot rely on this variable if we want to sort the queue, we will have to remove all elements we do not need
The safest way to do that is to simply create a new queue and set it
We start by sorting the current queue list with our
sortConfig.attributeName
andsortConfig.order
After that we get the currently playing song - with our sorted list and this current song element (index) we can simply use the
splice()
function - this way we are only left with the songs we needWe then set the queue with our sorted list
As of now there is a timeout required to reliably start the playback
Change to load.js
I had to add the
;0
part because Electron seems to clone something in my code which it does not like = causing an errorSince the return (cloned values) do not get used anyway, this doesn't seem to be a loss