Skip to content

Commit

Permalink
Merge pull request #2984 from metabrainz/ansh/cache-art-data
Browse files Browse the repository at this point in the history
Cache Album Art Queries
  • Loading branch information
MonkeyDo authored Oct 10, 2024
2 parents edeb79f + 50225ab commit c8e8efb
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 152 deletions.
69 changes: 44 additions & 25 deletions frontend/js/src/common/listens/ListenCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ import NiceModal from "@ebay/nice-modal-react";
import { faPlayCircle } from "@fortawesome/free-regular-svg-icons";
import { toast } from "react-toastify";
import { Link } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import {
fullLocalizedDateFromTimestampOrISODate,
getAlbumArtFromListenMetadata,
getAlbumArtFromListenMetadataKey,
getArtistLink,
getArtistMBIDs,
getArtistName,
Expand Down Expand Up @@ -94,10 +96,10 @@ export type ListenCardProps = {
export type ListenCardState = {
listen: Listen;
isCurrentlyPlaying: boolean;
thumbnailSrc?: string; // Full URL to the CoverArtArchive thumbnail
};

type ListenCardPropsWithDispatch = ListenCardProps & {
thumbnailSrc?: string;
dispatch: (action: BrainzPlayerActionType, callback?: () => void) => void;
};

Expand All @@ -118,7 +120,6 @@ export class ListenCard extends React.Component<

async componentDidMount() {
window.addEventListener("message", this.receiveBrainzPlayerMessage);
await this.getCoverArt();
}

async componentDidUpdate(
Expand All @@ -130,33 +131,12 @@ export class ListenCard extends React.Component<
if (Boolean(listen) && !isEqual(listen, oldListen)) {
this.setState({ listen });
}
if (!customThumbnail && Boolean(listen) && !isEqual(listen, oldListen)) {
await this.getCoverArt();
}
}

componentWillUnmount() {
window.removeEventListener("message", this.receiveBrainzPlayerMessage);
}

async getCoverArt() {
const { spotifyAuth, APIService, userPreferences } = this.context;
if (userPreferences?.saveData === true) {
return;
}
const { listen } = this.state;
const albumArtSrc = await getAlbumArtFromListenMetadata(
listen,
spotifyAuth,
APIService
);
if (albumArtSrc) {
this.setState({ thumbnailSrc: albumArtSrc });
} else {
this.setState({ thumbnailSrc: undefined });
}
}

playListen = () => {
const { listen, isCurrentlyPlaying } = this.state;
if (isCurrentlyPlaying) {
Expand Down Expand Up @@ -278,9 +258,10 @@ export class ListenCard extends React.Component<
additionalActions,
listen: listenFromProps,
dispatch: dispatchProp,
thumbnailSrc,
...otherProps
} = this.props;
const { listen, isCurrentlyPlaying, thumbnailSrc } = this.state;
const { listen, isCurrentlyPlaying } = this.state;
const { currentUser } = this.context;
const isLoggedIn = !isEmpty(currentUser);

Expand Down Expand Up @@ -765,5 +746,43 @@ export class ListenCard extends React.Component<

export default function ListenCardWrapper(props: ListenCardProps) {
const dispatch = useBrainzPlayerDispatch();
return <ListenCard {...props} dispatch={dispatch} />;
const { spotifyAuth, APIService, userPreferences } = React.useContext(
GlobalAppContext
);
const { listen, customThumbnail } = props;

const albumArtQueryKey = React.useMemo(
() => getAlbumArtFromListenMetadataKey(listen, spotifyAuth),
[listen, spotifyAuth]
);

const albumArtDisabled =
Boolean(customThumbnail) || !listen || userPreferences?.saveData;

const { data: thumbnailSrc } = useQuery({
queryKey: ["album-art", albumArtQueryKey, albumArtDisabled],
queryFn: async () => {
if (albumArtDisabled) {
return "";
}
try {
const albumArtURL = await getAlbumArtFromListenMetadata(
listen,
spotifyAuth,
APIService
);
return albumArtURL ?? "";
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error fetching album art", error);
return "";
}
},
staleTime: 1000 * 60 * 60 * 12,
gcTime: 1000 * 60 * 60 * 12,
});

return (
<ListenCard {...props} dispatch={dispatch} thumbnailSrc={thumbnailSrc} />
);
}
25 changes: 25 additions & 0 deletions frontend/js/src/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,30 @@ const getAlbumArtFromSpotifyTrackID = async (
return undefined;
};

const getAlbumArtFromListenMetadataKey = (
listen: BaseListenFormat,
spotifyUser?: SpotifyUser
): string | undefined => {
if (
SpotifyPlayer.isListenFromThisService(listen) &&
SpotifyPlayer.hasPermissions(spotifyUser)
) {
return `spotify:${SpotifyPlayer.getSpotifyTrackIDFromListen(listen)}`;
}
if (YoutubePlayer.isListenFromThisService(listen)) {
return `youtube:${YoutubePlayer.getVideoIDFromListen(listen)}`;
}
const userSubmittedReleaseMBID =
listen.track_metadata?.release_mbid ??
listen.track_metadata?.additional_info?.release_mbid;
const caaId = listen.track_metadata?.mbid_mapping?.caa_id;
const caaReleaseMbid = listen.track_metadata?.mbid_mapping?.caa_release_mbid;

return `ca:${userSubmittedReleaseMBID ?? ""}:${caaId ?? ""}:${
caaReleaseMbid ?? ""
}`;
};

const getAlbumArtFromListenMetadata = async (
listen: BaseListenFormat,
spotifyUser?: SpotifyUser,
Expand Down Expand Up @@ -1110,6 +1134,7 @@ export {
pinnedRecordingToListen,
getAlbumArtFromReleaseMBID,
getAlbumArtFromReleaseGroupMBID,
getAlbumArtFromListenMetadataKey,
getAlbumArtFromListenMetadata,
getAverageRGBOfImage,
getAdditionalContent,
Expand Down
21 changes: 16 additions & 5 deletions frontend/js/tests/common/brainzplayer/BrainzPlayer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from "../../../src/common/brainzplayer/BrainzPlayerContext";
import { renderWithProviders } from "../../test-utils/rtl-test-utils";
import { listenOrJSPFTrackToQueueItem } from "../../../src/common/brainzplayer/utils";
import { ReactQueryWrapper } from "../../test-react-query";

// Font Awesome generates a random hash ID for each icon everytime.
// Mocking Math.random() fixes this
Expand Down Expand Up @@ -175,7 +176,9 @@ describe("BrainzPlayer", () => {
...GlobalContextMock.context,
spotifyAuth: spotifyAccountWithPermissions,
},
{}
{
wrapper: ReactQueryWrapper,
}
);

const playButton = screen.getByTestId("bp-play-button");
Expand All @@ -201,7 +204,9 @@ describe("BrainzPlayer", () => {
...GlobalContextMock.context,
spotifyAuth: spotifyAccountWithPermissions,
},
{}
{
wrapper: ReactQueryWrapper,
}
);

const queueList = screen.getByTestId("queue");
Expand All @@ -224,7 +229,9 @@ describe("BrainzPlayer", () => {
...GlobalContextMock.context,
spotifyAuth: spotifyAccountWithPermissions,
},
{}
{
wrapper: ReactQueryWrapper,
}
);

const playButton = screen.getByTestId("bp-play-button");
Expand Down Expand Up @@ -256,7 +263,9 @@ describe("BrainzPlayer", () => {
...GlobalContextMock.context,
spotifyAuth: spotifyAccountWithPermissions,
},
{}
{
wrapper: ReactQueryWrapper,
}
);

const playButton = screen.getByTestId("bp-play-button");
Expand Down Expand Up @@ -287,7 +296,9 @@ describe("BrainzPlayer", () => {
...GlobalContextMock.context,
spotifyAuth: spotifyAccountWithPermissions,
},
{}
{
wrapper: ReactQueryWrapper,
}
);

const playButton = screen.getByTestId("bp-play-button");
Expand Down
Loading

0 comments on commit c8e8efb

Please sign in to comment.