mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Featured genre support added & CategoryCard was seperated as an independent View
This commit is contained in:
parent
c89c5a975a
commit
0dd41812ee
@ -10,9 +10,11 @@
|
|||||||
"dev": "cross-env TSC_WATCHFILE=UseFsEvents webpack --mode=development",
|
"dev": "cross-env TSC_WATCHFILE=UseFsEvents webpack --mode=development",
|
||||||
"start": "qode ./dist/index.js",
|
"start": "qode ./dist/index.js",
|
||||||
"start:watch": "nodemon -e node -w ./*.babelrc -x \"npm start\"",
|
"start:watch": "nodemon -e node -w ./*.babelrc -x \"npm start\"",
|
||||||
"start-dev": "concurrently -n \"webpack,spotube\" -p \"{name}-{pid}\" -c \"bgBlue,bgGreen\" -i --default-input-target spotube \"npm run dev\" \"npm run start:watch\"",
|
"start-dev": "concurrently -n \"webpack,spotube\" -p \"{name}-{pid}\" -c \"bgBlue.black.bold,bgGreen.black.bold\" -i --default-input-target spotube \"npm run dev\" \"npm run start:watch\"",
|
||||||
|
"debug-dev": "concurrently -n \"webpack,spotube\" -p \"{name}-{pid}\" -c \"bgBlue.black.bold,bgGreen.black.bold\" -i --default-input-target spotube \"npm run dev\" \"npm run debug:watch\"",
|
||||||
"start:trace": "qode ./dist/index.js --trace",
|
"start:trace": "qode ./dist/index.js --trace",
|
||||||
"debug": "qode --inspect ./dist/index.js",
|
"debug": "qode --inspect ./dist/index.js",
|
||||||
|
"debug:watch": "nodemon -e node -w ./*.babelrc -x \"npm run debug\"",
|
||||||
"pack": "nodegui-packer -p ./dist",
|
"pack": "nodegui-packer -p ./dist",
|
||||||
"pack-deb": "node scripts/build-deb.js",
|
"pack-deb": "node scripts/build-deb.js",
|
||||||
"pack-win32": "powershell.exe -ExecutionPolicy Unrestricted -Command \". '.\\scripts\\build-win32.ps1'\""
|
"pack-win32": "powershell.exe -ExecutionPolicy Unrestricted -Command \". '.\\scripts\\build-win32.ps1'\""
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import { Button, ScrollArea, View } from "@nodegui/react-nodegui";
|
import { Button, ScrollArea, View } from "@nodegui/react-nodegui";
|
||||||
import { useHistory } from "react-router";
|
|
||||||
import { CursorShape, QMouseEvent } from "@nodegui/nodegui";
|
|
||||||
import { QueryCacheKeys } from "../conf";
|
import { QueryCacheKeys } from "../conf";
|
||||||
import useSpotifyQuery from "../hooks/useSpotifyQuery";
|
import useSpotifyQuery from "../hooks/useSpotifyQuery";
|
||||||
import PlaceholderApplet from "./shared/PlaceholderApplet";
|
import PlaceholderApplet from "./shared/PlaceholderApplet";
|
||||||
import PlaylistCard from "./shared/PlaylistCard";
|
|
||||||
import useSpotifyInfiniteQuery from "../hooks/useSpotifyInfiniteQuery";
|
import useSpotifyInfiniteQuery from "../hooks/useSpotifyInfiniteQuery";
|
||||||
|
import CategoryCardView from "./shared/CategoryCardView";
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
const { data: pagedCategories, isError, refetch, isLoading, hasNextPage, isFetchingNextPage, fetchNextPage } = useSpotifyInfiniteQuery<SpotifyApi.PagingObject<SpotifyApi.CategoryObject>>(
|
const { data: pagedCategories, isError, refetch, isLoading, hasNextPage, isFetchingNextPage, fetchNextPage } = useSpotifyInfiniteQuery<SpotifyApi.PagingObject<SpotifyApi.CategoryObject>>(
|
||||||
@ -25,7 +23,7 @@ function Home() {
|
|||||||
.map((page) => page.items)
|
.map((page) => page.items)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.flat(1);
|
.flat(1);
|
||||||
|
categories?.unshift({ href: "", icons: [], id: "featured", name: "Featured" });
|
||||||
return (
|
return (
|
||||||
<ScrollArea style={`flex-grow: 1; border: none;`}>
|
<ScrollArea style={`flex-grow: 1; border: none;`}>
|
||||||
<View style={`flex-direction: 'column'; align-items: 'center'; flex: 1;`}>
|
<View style={`flex-direction: 'column'; align-items: 'center'; flex: 1;`}>
|
||||||
@ -33,12 +31,7 @@ function Home() {
|
|||||||
{categories?.map((category, index) => {
|
{categories?.map((category, index) => {
|
||||||
return <CategoryCard key={index + category.id} id={category.id} name={category.name} />;
|
return <CategoryCard key={index + category.id} id={category.id} name={category.name} />;
|
||||||
})}
|
})}
|
||||||
{hasNextPage &&
|
{hasNextPage && <Button on={{ clicked: () => fetchNextPage() }} text="Load More" enabled={!isFetchingNextPage} />}
|
||||||
<Button
|
|
||||||
on={{ clicked: () => fetchNextPage() }}
|
|
||||||
text="Load More"
|
|
||||||
enabled={!isFetchingNextPage}
|
|
||||||
/>}
|
|
||||||
</View>
|
</View>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
);
|
);
|
||||||
@ -51,55 +44,21 @@ interface CategoryCardProps {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const categoryStylesheet = `
|
|
||||||
#container{
|
|
||||||
flex: 1;
|
|
||||||
flex-direction: 'column';
|
|
||||||
justify-content: 'center';
|
|
||||||
}
|
|
||||||
#anchor-heading{
|
|
||||||
background: transparent;
|
|
||||||
padding: 10px;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
align-self: flex-start;
|
|
||||||
}
|
|
||||||
#child-view{
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
#anchor-heading:hover{
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const CategoryCard = ({ id, name }: CategoryCardProps) => {
|
const CategoryCard = ({ id, name }: CategoryCardProps) => {
|
||||||
const history = useHistory();
|
|
||||||
const { data: playlists, isError } = useSpotifyQuery<SpotifyApi.PlaylistObjectSimplified[]>(
|
const { data: playlists, isError } = useSpotifyQuery<SpotifyApi.PlaylistObjectSimplified[]>(
|
||||||
[QueryCacheKeys.categoryPlaylists, id],
|
[QueryCacheKeys.categoryPlaylists, id],
|
||||||
(spotifyApi) => spotifyApi.getPlaylistsForCategory(id, { limit: 4 }).then((playlistsRes) => playlistsRes.body.playlists.items),
|
async (spotifyApi) => {
|
||||||
|
const option = { limit: 4 };
|
||||||
|
let res;
|
||||||
|
if (id === "featured") {
|
||||||
|
res = await spotifyApi.getFeaturedPlaylists(option);
|
||||||
|
} else {
|
||||||
|
res = await spotifyApi.getPlaylistsForCategory(id, option);
|
||||||
|
}
|
||||||
|
return res.body.playlists.items;
|
||||||
|
},
|
||||||
{ initialData: [] }
|
{ initialData: [] }
|
||||||
);
|
);
|
||||||
|
|
||||||
function goToGenre(native: any) {
|
return <CategoryCardView url={`/genre/playlists/${id}`} isError={isError} name={name} playlists={playlists ?? []} />;
|
||||||
const mouse = new QMouseEvent(native);
|
|
||||||
if (mouse.button() === 1) {
|
|
||||||
history.push(`/genre/playlists/${id}`, { name });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isError) {
|
|
||||||
return <></>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<View id="container" styleSheet={categoryStylesheet}>
|
|
||||||
<Button id="anchor-heading" cursor={CursorShape.PointingHandCursor} on={{ MouseButtonRelease: goToGenre }} text={name} />
|
|
||||||
<View id="child-view">
|
|
||||||
{playlists?.map((playlist, index) => {
|
|
||||||
return <PlaylistCard key={index + playlist.id} playlist={playlist} />;
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,16 @@ function PlaylistGenreView() {
|
|||||||
const location = useLocation<{ name: string }>();
|
const location = useLocation<{ name: string }>();
|
||||||
const { data: pagedPlaylists, isError, isLoading, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = useSpotifyInfiniteQuery<SpotifyApi.PagingObject<SpotifyApi.PlaylistObjectSimplified>>(
|
const { data: pagedPlaylists, isError, isLoading, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = useSpotifyInfiniteQuery<SpotifyApi.PagingObject<SpotifyApi.PlaylistObjectSimplified>>(
|
||||||
[QueryCacheKeys.genrePlaylists, id],
|
[QueryCacheKeys.genrePlaylists, id],
|
||||||
(spotifyApi, { pageParam }) => spotifyApi.getPlaylistsForCategory(id, { limit: 20, offset: pageParam }).then((playlistsRes) => playlistsRes.body.playlists),
|
async (spotifyApi, { pageParam }) => {
|
||||||
|
const option = { limit: 20, offset: pageParam };
|
||||||
|
let res;
|
||||||
|
if (id === "featured") {
|
||||||
|
res = await spotifyApi.getFeaturedPlaylists(option);
|
||||||
|
} else {
|
||||||
|
res = await spotifyApi.getPlaylistsForCategory(id, option);
|
||||||
|
}
|
||||||
|
return res.body.playlists;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
getNextPageParam(lastPage) {
|
getNextPageParam(lastPage) {
|
||||||
if (lastPage.next) {
|
if (lastPage.next) {
|
||||||
|
61
src/components/shared/CategoryCardView.tsx
Normal file
61
src/components/shared/CategoryCardView.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { QMouseEvent, CursorShape } from "@nodegui/nodegui";
|
||||||
|
import { View, Button } from "@nodegui/react-nodegui";
|
||||||
|
import React, { FC } from "react";
|
||||||
|
import { useHistory } from "react-router";
|
||||||
|
import PlaylistCard from "./PlaylistCard";
|
||||||
|
|
||||||
|
interface CategoryCardProps {
|
||||||
|
url: string;
|
||||||
|
name: string;
|
||||||
|
isError: boolean;
|
||||||
|
playlists: SpotifyApi.PlaylistObjectSimplified[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const categoryStylesheet = `
|
||||||
|
#container{
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: 'column';
|
||||||
|
justify-content: 'center';
|
||||||
|
}
|
||||||
|
#anchor-heading{
|
||||||
|
background: transparent;
|
||||||
|
padding: 10px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
#child-view{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
#anchor-heading:hover{
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const CategoryCard: FC<CategoryCardProps> = ({ name, isError, playlists, url }) => {
|
||||||
|
const history = useHistory();
|
||||||
|
function goToGenre(native: any) {
|
||||||
|
const mouse = new QMouseEvent(native);
|
||||||
|
if (mouse.button() === 1) {
|
||||||
|
history.push(url, { name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isError) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<View id="container" styleSheet={categoryStylesheet}>
|
||||||
|
<Button id="anchor-heading" cursor={CursorShape.PointingHandCursor} on={{ MouseButtonRelease: goToGenre }} text={name} />
|
||||||
|
<View id="child-view">
|
||||||
|
{playlists.map((playlist, index) => {
|
||||||
|
return <PlaylistCard key={index + playlist.id} playlist={playlist} />;
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CategoryCard;
|
@ -12,6 +12,7 @@ export const cacheDir = join(homedir(), ".cache", "spotube")
|
|||||||
export enum QueryCacheKeys{
|
export enum QueryCacheKeys{
|
||||||
categories="categories",
|
categories="categories",
|
||||||
categoryPlaylists = "categoryPlaylists",
|
categoryPlaylists = "categoryPlaylists",
|
||||||
|
featuredPlaylists = "featuredPlaylists",
|
||||||
genrePlaylists="genrePlaylists",
|
genrePlaylists="genrePlaylists",
|
||||||
playlistTracks="playlistTracks",
|
playlistTracks="playlistTracks",
|
||||||
userPlaylists = "user-palylists",
|
userPlaylists = "user-palylists",
|
||||||
|
Loading…
Reference in New Issue
Block a user