From a948f0deb2fdeeee6ce6b7db8de722ba24a0b86a Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 22 Sep 2021 18:44:33 -0700 Subject: [PATCH] Remove ordered favorite, add batch star/unstar We don't need add a delay to favorite, since we can just add multiple id params in order inside the request --- src/api/api.ts | 78 +++++++++++++++++++++++++++ src/components/shared/ContextMenu.tsx | 60 ++++++++++++--------- src/redux/miscSlice.ts | 1 - 3 files changed, 112 insertions(+), 27 deletions(-) diff --git a/src/api/api.ts b/src/api/api.ts index cfdc5a0..1f941bb 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -434,6 +434,84 @@ export const unstar = async (id: string, type: string) => { return data; }; +export const batchStar = async (ids: string[], type: string) => { + const idChunks = _.chunk(ids, 325); + + let idParam: string; + switch (type) { + case 'music': + idParam = 'id'; + break; + case 'album': + idParam = 'albumId'; + break; + case 'artist': + idParam = 'artistId'; + break; + default: + break; + } + + const res: any[] = []; + for (let i = 0; i < idChunks.length; i += 1) { + const params = new URLSearchParams(); + + idChunks[i].forEach((id: string) => params.append(idParam, id)); + _.mapValues(authParams, (value: string, key: string) => { + params.append(key, value); + }); + + res.push( + ( + await api.get(`/star`, { + params, + }) + ).data + ); + } + + return res; +}; + +export const batchUnstar = async (ids: string[], type: string) => { + const idChunks = _.chunk(ids, 325); + + let idParam: string; + switch (type) { + case 'music': + idParam = 'id'; + break; + case 'album': + idParam = 'albumId'; + break; + case 'artist': + idParam = 'artistId'; + break; + default: + break; + } + + const res: any[] = []; + for (let i = 0; i < idChunks.length; i += 1) { + const params = new URLSearchParams(); + + idChunks[i].forEach((id: string) => params.append(idParam, id)); + _.mapValues(authParams, (value: string, key: string) => { + params.append(key, value); + }); + + res.push( + ( + await api.get(`/unstar`, { + params, + }) + ).data + ); + } + + return res; +}; + export const setRating = async (id: string, rating: number) => { const { data } = await api.get(`/setRating`, { params: { diff --git a/src/components/shared/ContextMenu.tsx b/src/components/shared/ContextMenu.tsx index 53a2a74..f23bd00 100644 --- a/src/components/shared/ContextMenu.tsx +++ b/src/components/shared/ContextMenu.tsx @@ -3,13 +3,13 @@ import React, { useRef, useState } from 'react'; import _ from 'lodash'; import { useQuery, useQueryClient } from 'react-query'; import { useHistory } from 'react-router'; -import { Form, Input, Popover, Whisper } from 'rsuite'; +import { Form, Input, Whisper } from 'rsuite'; import { getPlaylists, updatePlaylistSongsLg, - star, - unstar, createPlaylist, + batchStar, + batchUnstar, } from '../../api/api'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import { @@ -33,7 +33,7 @@ import { StyledPopover, } from './styled'; import { notifyToast } from './toast'; -import { errorMessages, isFailedResponse, sleep } from '../../shared/utils'; +import { errorMessages, isFailedResponse } from '../../shared/utils'; export const ContextMenuButton = ({ text, children, ...rest }: any) => { return ( @@ -188,22 +188,28 @@ export const GlobalContextMenu = () => { }); }; - const handleFavorite = async (ordered: boolean) => { + const handleFavorite = async () => { dispatch(setContextMenu({ show: false })); const sortedEntries = [...multiSelect.selected].sort( (a: any, b: any) => a.rowIndex - b.rowIndex ); - for (let i = 0; i < sortedEntries.length; i += 1) { - await star(sortedEntries[i].id, sortedEntries[i].type); - dispatch(setStar({ id: sortedEntries[i].id, type: 'star' })); - if (ordered) { - await sleep(350); + const ids = _.map(sortedEntries, 'id'); + + try { + const res = await batchStar(ids, sortedEntries[0].type); + + if (isFailedResponse(res)) { + notifyToast('error', errorMessages(res)[0]); + } else { + ids.forEach((id) => dispatch(setStar({ id, type: 'star' }))); } - } - await refetchAfterFavorite(); + await refetchAfterFavorite(); + } catch (err) { + notifyToast('error', err); + } }; const handleUnfavorite = async () => { @@ -213,12 +219,21 @@ export const GlobalContextMenu = () => { (entry: any) => entry.starred ); - for (let i = 0; i < starredEntries.length; i += 1) { - await unstar(starredEntries[i].id, starredEntries[i].type); - dispatch(setStar({ id: starredEntries[i].id, type: 'unstar' })); - } + const ids = _.map(starredEntries, 'id'); + + try { + const res = await batchUnstar(ids, starredEntries[0].type); - await refetchAfterFavorite(); + if (isFailedResponse(res)) { + notifyToast('error', errorMessages(res)[0]); + } else { + ids.forEach((id) => dispatch(setStar({ id, type: 'unstar' }))); + } + + await refetchAfterFavorite(); + } catch (err) { + notifyToast('error', err); + } }; return ( @@ -228,7 +243,7 @@ export const GlobalContextMenu = () => { xPos={misc.contextMenu.xPos} yPos={misc.contextMenu.yPos} width={190} - numOfButtons={7} + numOfButtons={6} numOfDividers={3} > { handleFavorite(false)} + onClick={handleFavorite} disabled={misc.contextMenu.disabledOptions.includes( 'addToFavorites' )} /> - handleFavorite(true)} - disabled={misc.contextMenu.disabledOptions.includes( - 'addToFavoritesOrdered' - )} - />