Featured genre support added & CategoryCard was seperated as an independent View

This commit is contained in:
KRTirtho 2021-04-26 22:40:22 +06:00
parent c89c5a975a
commit 0dd41812ee
5 changed files with 90 additions and 58 deletions

View File

@ -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'\""

View File

@ -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>
);
}; };

View File

@ -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) {

View 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;

View File

@ -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",