From 5d58951225dba66402fc113d390ec602043d263e Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 15 Sep 2020 15:51:42 -0300 Subject: better hiding track numbering in queue --- playlist-utils.js | 80 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 23 deletions(-) (limited to 'playlist-utils.js') diff --git a/playlist-utils.js b/playlist-utils.js index 452b705..68cba56 100644 --- a/playlist-utils.js +++ b/playlist-utils.js @@ -520,36 +520,70 @@ function getTrackIndexInParent(track) { const nameWithoutTrackNumberSymbol = Symbol('Cached name without track number') function getNameWithoutTrackNumber(track) { - // Be lazy and reuse an old value if possible! Don't do this if the track's - // name has changed. - const [oldName, cachedValue] = track[nameWithoutTrackNumberSymbol] || [] - if (cachedValue && track.name === oldName) { - return cachedValue + // A "part" is a series of numeric digits, separated from other parts by + // whitespace and dashes, always preceding either the first non-numeric/ + // separator character or (if there are no such characters) the first word + // (i.e. last whitespace). + const getNumberOfParts = ({ name }) => { + const match = name.match(/[^0-9\-\s]/) + if (match) { + name = name.slice(0, match.index) + } else if (name.includes(' ')) { + name = name.slice(0, name.lastIndexOf(' ')) + } else { + return 0 + } + name = name.replace(/[\-\s]+$/, '') + return name.split(/[\-\s]+/g).length + } + + const removeParts = (name, numParts) => { + const regex = new RegExp(`([0-9]+[\\-\\s]+){${numParts},${numParts}}`) + return track.name.replace(regex, '') } - // This is the expression that matches a track number at the start of - // a track's title. - const regex = /^[0-9\-\s]+/ + // Despite this function returning a single string for one track, that value + // depends on the names of all other tracks under the same parent. We still + // store individual track -> name data on the track object, but the parent + // gets an additional cache for the names of its children tracks as well as + // the number of "parts" (the value directly based upon those names, and + // useful in computing the name data for other children tracks). - // First we need to determine whether every track in the group even starts - // with a track number. const parent = track[parentSymbol] if (parent) { - const names = parent.items.filter(isTrack).map(t => t.name) - if (names.some(name => !regex.test(name))) { - // If any of the names don't match the track number regex, just return - // the track name unmodified. - return track.name + const [trackNames, cachedNumParts] = parent[nameWithoutTrackNumberSymbol] || [] + const tracks = parent.items.filter(isTrack) + if (trackNames && tracks.length === trackNames.length && tracks.every((t, i) => t.name === trackNames[i])) { + const [, oldName, oldNumParts, cachedValue] = track[nameWithoutTrackNumberSymbol] || [] + if (cachedValue && track.name === oldName && cachedNumParts === oldNumParts) { + return cachedValue + } else { + // Individual track cache outdated. + const value = removeParts(track.name, cachedNumParts) + track[nameWithoutTrackNumberSymbol] = [true, track.name, cachedNumParts, value] + return value + } + } else { + // Group (parent) cache outdated. + const numParts = Math.min(...tracks.map(getNumberOfParts)) + parent[nameWithoutTrackNumberSymbol] = [tracks.map(t => t.name), numParts] + // Parent changed so track cache changed is outdated too. + const value = removeParts(track.name, numParts) + track[nameWithoutTrackNumberSymbol] = [true, track.name, numParts, value] + return value + } + } else { + const [oldHadParent, oldName, , cachedValue] = track[nameWithoutTrackNumberSymbol] || [] + if (cachedValue && !oldHadParent && track.name === oldName) { + return cachedValue + } else { + // Track cache outdated. + const numParts = getNumberOfParts(track) + const value = removeParts(track.name, numParts) + track[nameWithoutTrackNumberSymbol] = [false, track.name, numParts, value] + return value } } - - // Now actually perform the replacement to get rid of the track number! - const value = track.name.replace(regex, '') - - // Cache the value, so we don't need to do this whole process again. - track[nameWithoutTrackNumberSymbol] = [track.name, value] - - return value } function isGroup(obj) { -- cgit 1.3.0-6-gf8a5