Skip to content

Commit

Permalink
will throw error (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcoMadera authored Sep 16, 2023
1 parent 37f5075 commit 56e6c6f
Show file tree
Hide file tree
Showing 24 changed files with 437 additions and 468 deletions.
79 changes: 35 additions & 44 deletions components/CardTrack/CardTrack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
import { ITrack } from "types/spotify";
import {
ContentType,
handlePlayCurrentTrackError,
playCurrentTrack,
templateReplace,
ToastMessage,
Expand Down Expand Up @@ -136,50 +137,40 @@ function CardTrack({
"[index] 55px [first] 14fr [popularity] 1fr [last] minmax(60px,1fr)",
};

function playThisTrack() {
playCurrentTrack(track, {
allTracks,
player,
user,
accessToken,
deviceId,
playlistUri,
playlistId: pageDetails?.id,
setCurrentlyPlaying,
setPlaylistPlayingId,
isSingleTrack,
position,
setAccessToken,
uri,
uris,
}).then((status) => {
if (status === 404) {
(player as Spotify.Player).disconnect();
addToast({
variant: "error",
message: translations[ToastMessage.UnableToPlayReconnecting],
});
setReconnectionError(true);
}
if (status === 200) {
const source = pageDetails?.uri;
const isCollection = source?.split(":")?.[3];
setPlayedSource(
isCollection && pageDetails?.type && pageDetails?.id
? `spotify:${pageDetails.type}:${pageDetails.id}`
: source ?? track?.uri
);
}
if (status === 400) {
addToast({
variant: "error",
message: templateReplace(
translations[ToastMessage.ErrorPlayingThis],
[translations[ContentType.Track]]
),
});
}
});
async function playThisTrack() {
try {
const playlistPlayingId = await playCurrentTrack(track, {
allTracks,
player,
user,
accessToken,
deviceId,
playlistUri,
playlistId: pageDetails?.id,
setCurrentlyPlaying,
isSingleTrack,
position,
setAccessToken,
uri,
uris,
});

const source = pageDetails?.uri;
const isCollection = source?.split(":")?.[3];
setPlaylistPlayingId(playlistPlayingId);
setPlayedSource(
isCollection && pageDetails?.type && pageDetails?.id
? `spotify:${pageDetails.type}:${pageDetails.id}`
: source ?? track?.uri
);
} catch (error) {
handlePlayCurrentTrackError(error, {
addToast,
player: player as Spotify.Player,
setReconnectionError,
translations,
});
}
}

const id = useId();
Expand Down
13 changes: 9 additions & 4 deletions components/CardTrack/__tests__/CardTrack.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import { IUserContext } from "context/UserContext";
import { useOnScreen } from "hooks";
import { IUtilsMocks } from "types/mocks";
import { ISpotifyContext } from "types/spotify";
import { Language, playCurrentTrack } from "utils";
import {
BadRequestError,
Language,
NotFoundError,
playCurrentTrack,
} from "utils";

const { track, getAllTranslations } = jest.requireActual<IUtilsMocks>(
"utils/__tests__/__mocks__/mocks.ts"
Expand Down Expand Up @@ -70,7 +75,7 @@ describe("cardTrack", () => {
it("should play on double click", async () => {
expect.assertions(2);
(useOnScreen as jest.Mock).mockImplementationOnce(() => true);
(playCurrentTrack as jest.Mock<Promise<number>>).mockResolvedValue(200);
(playCurrentTrack as jest.Mock<Promise<string>>).mockResolvedValue("id");
const setPlayedSource = jest.fn();
const player = {
getCurrentState: jest.fn().mockResolvedValue({ position: 0 }),
Expand Down Expand Up @@ -113,7 +118,7 @@ describe("cardTrack", () => {
it("should add toast reconnection error", async () => {
expect.assertions(4);
(useOnScreen as jest.Mock).mockImplementationOnce(() => true);
(playCurrentTrack as jest.Mock<Promise<number>>).mockResolvedValue(404);
(playCurrentTrack as jest.Mock).mockRejectedValue(new NotFoundError());
const player = {
disconnect: jest.fn(),
activateElement: jest.fn().mockResolvedValue(200),
Expand Down Expand Up @@ -155,7 +160,7 @@ describe("cardTrack", () => {
it("should add toast with error playing this track", async () => {
expect.assertions(1);
(useOnScreen as jest.Mock).mockImplementationOnce(() => true);
(playCurrentTrack as jest.Mock<Promise<number>>).mockResolvedValue(400);
(playCurrentTrack as jest.Mock).mockRejectedValue(new BadRequestError());
const setReconnectionError = jest.fn();
const player = {
activateElement: jest.fn().mockResolvedValue(200),
Expand Down
96 changes: 42 additions & 54 deletions components/ContextMenu/ContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import {
ReactPortal,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";

import { createPortal } from "react-dom";
import { ReactElement, useLayoutEffect, useRef, useState } from "react";

import { CardContentContextMenu, CardTrackContextMenu } from "components";
import { ICardContentContextMenu } from "components/CardContentContextMenu";
import {
CardContentContextMenu,
CardTrackContextMenu,
PortalTarget,
} from "components";
import type { ICardContentContextMenu } from "components/CardContentContextMenu";
import { useContextMenu, useEventListener } from "hooks";
import { ITrack } from "types/spotify";
import type { ITrack } from "types/spotify";
import {
calculateContextMenuPosition,
CONTEXT_MENU_SIDE_OFFSET,
positionContextMenu,
} from "utils";

export default function ContextMenu(): ReactPortal | null {
const [targetNode, setTargetNode] = useState<Element | null>();
export default function ContextMenu(): ReactElement | null {
const { contextMenuData, removeContextMenu } = useContextMenu();
const [contextMenuPos, setContextMenuPos] = useState({
x: (contextMenuData?.position.x ?? 0) - 30,
Expand All @@ -31,10 +26,6 @@ export default function ContextMenu(): ReactPortal | null {
});
const contextMenuRef = useRef<HTMLElement>(null);

useEffect(() => {
setTargetNode(document.querySelector("#contextMenu"));
}, []);

useEventListener({
target: document.querySelector("#__next"),
type: "click",
Expand All @@ -53,11 +44,7 @@ export default function ContextMenu(): ReactPortal | null {
});
}, [contextMenuData]);

if (targetNode === null) {
throw new Error("ContextMenu needs a target element with id: contextMenu");
}

if (targetNode === undefined || !contextMenuData) {
if (!contextMenuData) {
return null;
}

Expand All @@ -74,36 +61,37 @@ export default function ContextMenu(): ReactPortal | null {
CONTEXT_MENU_SIDE_OFFSET
);

return createPortal(
<section
role="menu"
data-type={contextMenuData.data?.type}
ref={contextMenuRef}
style={{ top, left }}
>
{contextMenuData.data?.type === "track" ||
contextMenuData.data?.type === "episode" ? (
<CardTrackContextMenu track={contextMenuData.data as ITrack} />
) : (
<CardContentContextMenu
data={contextMenuData.data as ICardContentContextMenu["data"]}
/>
)}
<style jsx>{`
section {
max-width: 400px;
width: fit-content;
position: absolute;
margin: 0 auto;
border-radius: 5px;
background-color: #282828;
box-shadow: 0px 2px 9px 0px rgb(0 0 0 / 5%);
padding: 3px;
max-height: 95vh;
z-index: 999999999999;
}
`}</style>
</section>,
targetNode
return (
<PortalTarget targetId="contextMenu">
<section
role="menu"
data-type={contextMenuData.data?.type}
ref={contextMenuRef}
style={{ top, left }}
>
{contextMenuData.data?.type === "track" ||
contextMenuData.data?.type === "episode" ? (
<CardTrackContextMenu track={contextMenuData.data as ITrack} />
) : (
<CardContentContextMenu
data={contextMenuData.data as ICardContentContextMenu["data"]}
/>
)}
<style jsx>{`
section {
max-width: 400px;
width: fit-content;
position: absolute;
margin: 0 auto;
border-radius: 5px;
background-color: #282828;
box-shadow: 0px 2px 9px 0px rgb(0 0 0 / 5%);
padding: 3px;
max-height: 95vh;
z-index: 999999999999;
}
`}</style>
</section>
</PortalTarget>
);
}
102 changes: 63 additions & 39 deletions components/EpisodeCard/EpisodeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
formatTime,
getSiteUrl,
getTimeAgo,
handlePlayCurrentTrackError,
playCurrentTrack,
templateReplace,
ToastMessage,
Expand Down Expand Up @@ -48,6 +49,8 @@ export default function EpisodeCard({
pageDetails,
setCurrentlyPlaying,
setPlaylistPlayingId,
setReconnectionError,
setPlayedSource,
} = useSpotify();
const { user, accessToken, setAccessToken } = useAuth();
const { addToast } = useToast();
Expand All @@ -72,6 +75,65 @@ export default function EpisodeCard({

if (!item) return null;

async function playThisTrack() {
try {
const playlistPlayingId = await playCurrentTrack(
{
album: {
id: show.id,
images: item.images ?? [],
name: show.name,
release_date: item.release_date,
type: "album",
uri: show.uri,
},
artists: [
{
name: show.name,
id: show.id,
type: "artist",
uri: `spotify:show:${show.id}`,
},
],
id: item.id,
name: item.name,
explicit: item.explicit ?? false,
type: "track",
uri: item.uri,
},
{
player,
user,
allTracks,
accessToken,
deviceId,
playlistUri: pageDetails?.uri,
playlistId: pageDetails?.id,
setCurrentlyPlaying,
isSingleTrack: true,
position,
setAccessToken,
}
);

const source = pageDetails?.uri;
const isCollection = source?.split(":")?.[3];
setPlaylistPlayingId(playlistPlayingId);
setPlayedSource(
isCollection && pageDetails?.type && pageDetails?.id
? `spotify:${pageDetails.type}:${pageDetails.id}`
: source ?? item.uri
);
} catch (error) {
handlePlayCurrentTrackError(error, {
addToast,
player: player as Spotify.Player,
setReconnectionError,
translations,
});
}
}

return (
<div
onContextMenu={(e) => {
Expand Down Expand Up @@ -205,45 +267,7 @@ export default function EpisodeCard({
if (isPremium) {
(player as Spotify.Player)?.activateElement();
}
playCurrentTrack(
{
album: {
id: show.id,
images: item.images ?? [],
name: show.name,
release_date: item.release_date,
type: "album",
uri: show.uri,
},
artists: [
{
name: show.name,
id: show.id,
type: "artist",
uri: `spotify:show:${show.id}`,
},
],
id: item.id,
name: item.name,
explicit: item.explicit ?? false,
type: "track",
uri: item.uri,
},
{
player,
user,
allTracks,
accessToken,
deviceId,
playlistUri: pageDetails?.uri,
playlistId: pageDetails?.id,
setCurrentlyPlaying,
setPlaylistPlayingId,
isSingleTrack: true,
position,
setAccessToken,
}
);
playThisTrack();
}}
>
{isThisEpisodePlaying && isPlaying ? <Pause /> : <Play />}
Expand Down
Loading

1 comment on commit 56e6c6f

@vercel
Copy link

@vercel vercel bot commented on 56e6c6f Sep 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.