Skip to content

Commit

Permalink
Enhance settings and perform code cleanup
Browse files Browse the repository at this point in the history
- Add setting section dividers
- Implement regex/count mass removal feature
- Introduce 'Copy tag counts' option
- Added '[artist:<artist>]' tag option options
- Convert 'Export playlist tags' to a toggle

Also refactored some functions and made minor code adjustments
  • Loading branch information
Bergbok committed Apr 1, 2024
1 parent b63c3f3 commit f0028fc
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 261 deletions.
4 changes: 2 additions & 2 deletions CustomApps/playlist-tags/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion CustomApps/playlist-tags/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "playlist-tags",
"version": "1.5.3",
"version": "1.6.0",
"private": true,
"scripts": {
"build": "spicetify-creator",
Expand Down
8 changes: 4 additions & 4 deletions CustomApps/playlist-tags/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { renderPlaylists, getPlaylistMetadata, getCurrentPageURI, getPlaylistsTaggedAs, getAllTags, addPlaylistsToQueue, removeTagFromAllPlaylists, removeStringFromStringArray, escapeRegExp } from './funcs';
import { PlaylistMetadata } from './types/playlist_metadata.d'
import { renderPlaylists, getPlaylistMetadata, getCurrentPageURI, getPlaylistsTaggedAs, getAllTags, addPlaylistsToQueue, removeTagFromAllPlaylists, removeStringFromStringArray } from './funcs';
import { waitForSpicetify, waitForPlatformApi } from '@shared/utils/spicetify-utils';
import FilterDropdown from './components/filter_dropdown';
import PlayButton from './components/play_button';
Expand Down Expand Up @@ -248,11 +248,11 @@ const App = () => {
break;
// Adds tag to search
default:
setFilterQuery(filter_query_terms.slice(0, -1).join(' ') + ' ' + tag_with_exclusion);
setFilterQuery(filter_query_terms.slice(0, -1).join(' ') + ' ' + tag_with_exclusion + ' ');
break;
}
}}
onContextMenu={() => {removeTagFromAllPlaylists(tag); setFilterQuery(removeStringFromStringArray(filter_query_terms, tag)); updateTagList()}}>{/* {tag} */}
onContextMenu={() => {removeTagFromAllPlaylists(new RegExp(escapeRegExp(tag))); setFilterQuery(removeStringFromStringArray(filter_query_terms, tag)); updateTagList()}}>{/* {tag} */}
<p dangerouslySetInnerHTML={{ __html: `<span style="color: ${filterQuery.replace(/!/g, '').split(' ').includes(tag) ? 'black' : 'var(--spice-text)'}">${tag}</span>` }}></p>
</SpotifyChip>
);
Expand Down Expand Up @@ -296,7 +296,7 @@ const App = () => {
}
setActiveLink('Search');
}}
onContextMenu={() => {removeTagFromAllPlaylists(tag); updateTagList()}}>{tag}
onContextMenu={() => {removeTagFromAllPlaylists(new RegExp(tag)); updateTagList()}}>{tag}
</SpotifyChip>
))
}
Expand Down
180 changes: 102 additions & 78 deletions CustomApps/playlist-tags/src/extensions/extension.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { handlePageChange, getCurrentPageURI, getPlaylistTags, renderPlaylistPageElements, clearMetadataCache, clearAllTags, importTags, exportTags, appendTagsToFolderPlaylists, clearContentsCache, getLocalStorageKeySizes, appendTagToPlaylistsContainingLocalFiles, appendCreatorDisplayNameTagToAllPlaylists, appendArtistTagToPlaylistsContainingOneArtist, appendUnplayableTagToUnplayable, appendYearTagToPlaylistsContaingYearInDescription } from '../funcs';
import { handlePageChange, getCurrentPageURI, getPlaylistTags, renderPlaylistPageElements, clearMetadataCache, clearAllTags, importTags, exportTags, appendTagsToFolderPlaylists, clearContentsCache, getLocalStorageKeySizes, removeTagFromAllPlaylists, appendTagToAllPlaylists, getTagCounts } from '../funcs';
import { MassTagOperation } from '../types/mass_tag_operations.d';
import { SettingsSection } from 'spcr-settings';
import { waitForSpicetify, waitForPlatformApi } from '@shared/utils/spicetify-utils';
import { version as CURRENT_VERSION } from '../../package.json';
import { waitForSpicetify, waitForPlatformApi } from '@shared/utils/spicetify-utils';

/**
* Checks for updates for Playlist Tags.
Expand All @@ -15,8 +16,6 @@ function checkForUpdate() {
.then(package_JSON => {
if (package_JSON.version !== CURRENT_VERSION) {
Spicetify.showNotification('An update is available for Playlist Tags');
} else {
console.log('No update available');
}
})
.catch(error => {
Expand All @@ -27,78 +26,104 @@ function checkForUpdate() {
/**
* Registers the settings for Playlist Tags using spcr-settings.
*/
function registerSettings() {
const settings = new SettingsSection('Playlist Tags Settings', 'playlist-tags-settings');

settings.addToggle('navbar-all-tags-page', 'Navigation Bar: All Tags', true);
settings.addToggle('navbar-all-tagged-playlists-page', 'Navigation Bar: All Tagged Playlists', true);
settings.addToggle('navbar-README', 'Navigation Bar: README', true);

settings.addToggle('use-metadata-cache', 'Use metadata cache', true);

settings.addButton('button-clear-metadata-cache', 'Remove metadata cache', 'Clear', () => {
clearMetadataCache();
Spicetify.showNotification('Metadata cache cleared');
});

settings.addToggle('use-contents-cache', 'Use tracklist cache', true);

settings.addButton('button-clear-contents-cache', 'Remove tracklist cache', 'Clear', () => {
clearContentsCache();
Spicetify.showNotification('Tracklist cache cleared');
});

settings.addButton('button-import-tags', 'Import tags from clipboard', 'Import', async () => {
const imported_tag_count = importTags(await Spicetify.Platform.ClipboardAPI.paste());
Spicetify.showNotification('Imported ' + imported_tag_count + ' playlist\'s tags!');
});

settings.addButton('button-export-tags', 'Export playlist tags to clipboard', 'Export', async () => {
await Spicetify.Platform.ClipboardAPI.copy(exportTags());
Spicetify.showNotification('Tags copied to clipboard!');
});

settings.addButton('button-export-tags-excluding-contains-local-files', 'Export playlist tags (excluding those tagged as [contains-local-files])', 'Export', async () => {
await Spicetify.Platform.ClipboardAPI.copy(exportTags(true));
Spicetify.showNotification('Tags copied to clipboard!');
});

settings.addButton('button-add-artist-tags', 'Add "[artist:<artist>]" tag to playlists containing one artist', 'Add', async () => {
appendArtistTagToPlaylistsContainingOneArtist();
Spicetify.showNotification('Processing playlists');
});

settings.addButton('button-add-creator-displayname-tags', 'Add "[by:<username>]" tag to all playlists', 'Add', async () => {
appendCreatorDisplayNameTagToAllPlaylists();
Spicetify.showNotification('Processing playlists');
});

settings.addButton('button-add-contains-local-files-tags', 'Add "[contains-local-files]" tag to playlists containing local files', 'Add', async () => {
appendTagToPlaylistsContainingLocalFiles('[contains-local-files]');
Spicetify.showNotification('Processing playlists');
});

settings.addButton('button-add-unplayable-tags', 'Add "[unplayable]" tag to unplayable playlists', 'Add', async () => {
appendUnplayableTagToUnplayable();
Spicetify.showNotification('Processing playlists');
});

settings.addButton('button-add-year-tags', 'Add "[year:<year>]" tag to playlists containing year in description', 'Add', async () => {
appendYearTagToPlaylistsContaingYearInDescription();
Spicetify.showNotification('Processing playlists');
});

settings.addButton('button-get-localstorage-key-sizes', 'Copy local storage key sizes', 'Copy', async () => {
await Spicetify.Platform.ClipboardAPI.copy(getLocalStorageKeySizes());
Spicetify.showNotification('Copied to clipboard!');
});
async function registerSettings() {
let settings = new SettingsSection('Playlist Tags Settings', 'playlist-tags-settings');
await settings.pushSettings();

const import_export_settings = new SettingsSection('Import / Export', 'playlist-tags-import-export-settings');
import_export_settings.addButton('button-import-tags', 'Import tags from clipboard', 'Import', async () => {
const imported_tag_count = importTags(await Spicetify.Platform.ClipboardAPI.paste());
Spicetify.showNotification('Imported ' + imported_tag_count + ' playlist\'s tags!');
});
import_export_settings.addButton('button-export-tags', 'Export playlist tags to clipboard', 'Export', async () => {
await Spicetify.Platform.ClipboardAPI.copy(exportTags(import_export_settings.getFieldValue('exclude-contains-local-files-tag')));
Spicetify.showNotification('Tags copied to clipboard!');
});
import_export_settings.addToggle('exclude-contains-local-files-tag', 'Exclude [contains-local-files] from export', true);
await import_export_settings.pushSettings();

settings = new SettingsSection('Navigation Bar', 'playlist-tags-navbar-settings');
settings.addToggle('navbar-all-tags-page', '• All Tags', true);
settings.addToggle('navbar-all-tagged-playlists-page', '• All Tagged Playlists', true);
settings.addToggle('navbar-README', '• README', true);
await settings.pushSettings();

settings = new SettingsSection('Cache', 'playlist-tags-cache-settings');
settings.addToggle('use-contents-cache', 'Use tracklist cache', true);
settings.addToggle('use-metadata-cache', 'Use metadata cache', true);
settings.addButton('button-clear-contents-cache', 'Remove tracklist cache', 'Remove', () => {
clearContentsCache();
Spicetify.showNotification('Tracklist cache cleared');
});
settings.addButton('button-clear-metadata-cache', 'Remove metadata cache', 'Remove', () => {
clearMetadataCache();
Spicetify.showNotification('Metadata cache cleared');
});
await settings.pushSettings();

settings.addButton('button-remove-all-tags', 'CAUTION: Remove ALL tags', 'Clear', () => {
clearAllTags();
Spicetify.showNotification('All tags removed');
});
const add_settings = new SettingsSection('Mass Tagging', 'playlist-tags-add-settings');
add_settings.addButton('button-add-year-tags', 'Add [year:<year>] tag to playlists containing year in description', 'Add', async () => {
appendTagToAllPlaylists(MassTagOperation.AddYearTag);
Spicetify.showNotification('Processing playlists');
});
add_settings.addButton('button-add-contains-local-files-tags', 'Add [contains-local-files] tag to playlists containing local files', 'Add', async () => {
appendTagToAllPlaylists(MassTagOperation.AddLocalFilesTag, '[contains-local-files]');
Spicetify.showNotification('Processing playlists');
});
add_settings.addButton('button-add-unplayable-tags', 'Add [unplayable] tag to unplayable playlists', 'Add', async () => {
appendTagToAllPlaylists(MassTagOperation.AddUnplayableTag, '[unplayable]');
Spicetify.showNotification('Processing playlists');
});
add_settings.addButton('button-add-creator-displayname-tags', 'Add [by:<username>] tag to all playlists', 'Add', async () => {
appendTagToAllPlaylists(MassTagOperation.AddCreatorDisplayNameTag);
Spicetify.showNotification('Processing playlists');
});
add_settings.addButton('button-add-artist-tags', 'Add [artist:<artist>] tags to all playlists', 'Add', async () => {
appendTagToAllPlaylists(MassTagOperation.AddArtistTag, undefined, add_settings.getFieldValue('ignore-non-english-characters'), parseInt(add_settings.getFieldValue('va-cutoff-count')));
Spicetify.showNotification('Processing playlists');
});
add_settings.addToggle('ignore-non-english-characters', '↳ Exclude non-english characters', true);
add_settings.addInput('va-cutoff-count', '↳ Threshold for [artist:VA] tag', '5', () => {
if (!Number.isInteger(parseInt(add_settings.getFieldValue('va-cutoff-count')))) {
Spicetify.showNotification('Invalid input, should be a positive integer', true, 1500);
add_settings.setFieldValue('va-cutoff-count', '5');
add_settings.rerender();
}
});
await add_settings.pushSettings();

const removal_settings = new SettingsSection('Mass Removal', 'playlist-tags-removal-settings');
removal_settings.addButton('button-mass-removal', 'Remove all tags that match:', 'Remove', () => {
const regex = new RegExp(removal_settings.getFieldValue('mass-removal-regex'));
const less_than_count = parseInt(removal_settings.getFieldValue('mass-removal-less-than-count'));
console.log(less_than_count);
removeTagFromAllPlaylists(regex, less_than_count);
Spicetify.showNotification('Removed tags!');
});
removal_settings.addInput('mass-removal-regex', '↳ Regular Expression', '');
removal_settings.addInput('mass-removal-less-than-count', '↳ That appear less than x times', '', () => {
if (!Number.isInteger(parseInt(removal_settings.getFieldValue('mass-removal-less-than-count')))) {
Spicetify.showNotification('Invalid input, should be a positive integer', true, 1500);
removal_settings.setFieldValue('mass-removal-less-than-count', '0');
removal_settings.rerender();
}
});
removal_settings.addButton('button-remove-all-tags', 'CAUTION: Remove ALL tags', 'Remove', () => {
clearAllTags();
Spicetify.showNotification('All tags removed');
});
await removal_settings.pushSettings();

settings.pushSettings();
settings = new SettingsSection('Miscellaneous', 'playlist-tags-misc-settings');
settings.addButton('button-copy-tag-counts', 'Copy tag counts', 'Copy', async () => {
await Spicetify.Platform.ClipboardAPI.copy(getTagCounts());
Spicetify.showNotification('Copied to clipboard!');
});
settings.addButton('button-copy-localstorage-key-sizes', 'Copy local storage key sizes', 'Copy', async () => {
await Spicetify.Platform.ClipboardAPI.copy(getLocalStorageKeySizes());
Spicetify.showNotification('Copied to clipboard!');
});
await settings.pushSettings();
};

/**
Expand All @@ -114,7 +139,7 @@ function registerFolderContextMenuItem() {
}

const folder_menu_item = new Spicetify.ContextMenu.Item(
"Add Tags",
'Add Tags',
uris => appendTagsToFolderPlaylists(uris[0]),
uris => Spicetify.URI.isFolder(uris[0]),
'plus-alt'
Expand All @@ -132,11 +157,10 @@ function registerFolderContextMenuItem() {
(async () => {
await waitForSpicetify();
await waitForPlatformApi('History');

await registerSettings();

checkForUpdate();

registerSettings();

registerFolderContextMenuItem();

if (Spicetify.Platform.History.location.pathname.startsWith('/playlist/')) {
Expand Down
Loading

0 comments on commit f0028fc

Please sign in to comment.