diff --git a/apps/feeds/src/algos/rap-metal.ts b/apps/feeds/src/algos/rap-metal.ts index 2179723c..352e22e1 100644 --- a/apps/feeds/src/algos/rap-metal.ts +++ b/apps/feeds/src/algos/rap-metal.ts @@ -10,7 +10,7 @@ const handler = async ( ) => { const { limit = 50, cursor } = params; - const whereConditions = [arrayContains(schema.artists.genres, ["rap-metal"])]; + const whereConditions = [arrayContains(schema.artists.genres, ["rap metal"])]; if (cursor) { const cursorDate = new Date(parseInt(cursor, 10)); diff --git a/apps/web/package.json b/apps/web/package.json index bf402a30..c6652fb4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -57,7 +57,7 @@ "lodash": "^4.17.21", "numeral": "^2.0.6", "posthog-js": "^1.234.6", - "ramda": "^0.30.1", + "ramda": "^0.32.0", "react": "^18.3.1", "react-content-loader": "^7.0.2", "react-dom": "^18.3.1", @@ -85,7 +85,7 @@ "@storybook/test": "^8.5.2", "@tanstack/router-plugin": "^1.125.4", "@types/lodash": "^4.17.15", - "@types/ramda": "^0.30.2", + "@types/ramda": "^0.31.1", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@vitejs/plugin-react-swc": "^3.5.0", diff --git a/apps/web/src/atoms/feed.ts b/apps/web/src/atoms/feed.ts index 2cb1f0e5..3f9d1d43 100644 --- a/apps/web/src/atoms/feed.ts +++ b/apps/web/src/atoms/feed.ts @@ -5,3 +5,7 @@ export const feedAtom = atom("all"); export const feedGeneratorUriAtom = atom( "at://did:plc:vegqomyce4ssoqs7zwqvgqty/app.rocksky.feed.generator/all", ); + +export const feedUrisAtom = atom>({ + all: "at://did:plc:vegqomyce4ssoqs7zwqvgqty/app.rocksky.feed/all", +}); diff --git a/apps/web/src/hooks/useFeed.tsx b/apps/web/src/hooks/useFeed.tsx index 502c1188..3ed07478 100644 --- a/apps/web/src/hooks/useFeed.tsx +++ b/apps/web/src/hooks/useFeed.tsx @@ -3,7 +3,7 @@ import { getFeedByUri, getFeedGenerators, getFeed } from "../api/feed"; export const useFeedQuery = (feed: string, limit = 114, cursor?: string) => useQuery({ - queryKey: ["feed"], + queryKey: ["feed", feed], queryFn: () => getFeed(feed, limit, cursor), }); diff --git a/apps/web/src/pages/home/feed/Feed.tsx b/apps/web/src/pages/home/feed/Feed.tsx index 31d14016..2c1d6bb1 100644 --- a/apps/web/src/pages/home/feed/Feed.tsx +++ b/apps/web/src/pages/home/feed/Feed.tsx @@ -62,7 +62,7 @@ function Feed() { () => message.scrobblesChart, ); - await queryClient.invalidateQueries({ queryKey: ["feed"] }); + await queryClient.invalidateQueries({ queryKey: ["feed", feedUri] }); await queryClient.invalidateQueries({ queryKey: ["now-playings"] }); await queryClient.invalidateQueries({ queryKey: ["scrobblesChart"] }); }; @@ -114,54 +114,47 @@ function Feed() { flexGridColumnGap="scale800" flexGridRowGap="scale1000" > - { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data.map((song: any) => ( - - - ( + + + + +
+
+ - -
-
- -
- {" "}
- - recently played this song + {" "} +
+ + recently played this song + + + + {dayjs(song.date).fromNow()} - - - {dayjs(song.date).fromNow()} - - - - )) - } + + + ))}
)} diff --git a/apps/web/src/pages/home/feed/FeedGenerators/FeedGenerators.tsx b/apps/web/src/pages/home/feed/FeedGenerators/FeedGenerators.tsx index f09a2efa..33dfd433 100644 --- a/apps/web/src/pages/home/feed/FeedGenerators/FeedGenerators.tsx +++ b/apps/web/src/pages/home/feed/FeedGenerators/FeedGenerators.tsx @@ -2,16 +2,41 @@ import { useState, useRef, useEffect } from "react"; import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react"; import { categories } from "./constants"; import { useAtom } from "jotai"; -import { feedAtom } from "../../../../atoms/feed"; +import { + feedAtom, + feedGeneratorUriAtom, + feedUrisAtom, +} from "../../../../atoms/feed"; +import { useFeedGeneratorsQuery } from "../../../../hooks/useFeed"; +import * as R from "ramda"; function FeedGenerators() { const jwt = localStorage.getItem("token"); + const { data: feedGenerators } = useFeedGeneratorsQuery(); + const [feedUris, setFeedUris] = useAtom(feedUrisAtom); + const [, setFeedUri] = useAtom(feedGeneratorUriAtom); const [activeCategory, setActiveCategory] = useAtom(feedAtom); const [showLeftChevron, setShowLeftChevron] = useState(false); const [showRightChevron, setShowRightChevron] = useState(true); const [hasOverflow, setHasOverflow] = useState(false); const scrollContainerRef = useRef(null); + useEffect(() => { + if (!feedGenerators?.feeds) { + return; + } + const feedRegistry = R.indexBy( + R.prop("name"), + feedGenerators.feeds + .map((x) => ({ + ...x, + name: x.name.toLowerCase(), + })) + .filter((x) => categories.includes(x.name)), + ); + setFeedUris(R.map(R.prop("uri"), feedRegistry)); + }, [feedGenerators, setFeedUris]); + // Check scroll position and update chevron visibility const handleScroll = () => { const container = scrollContainerRef.current; @@ -49,6 +74,7 @@ function FeedGenerators() { const handleCategoryClick = (category: string, index: number) => { setActiveCategory(category); + setFeedUri(feedUris[category]); const container = scrollContainerRef.current; if (container) { diff --git a/apps/web/src/pages/home/feed/FeedGenerators/constants.ts b/apps/web/src/pages/home/feed/FeedGenerators/constants.ts index 6b6ffb59..3d2a2733 100644 --- a/apps/web/src/pages/home/feed/FeedGenerators/constants.ts +++ b/apps/web/src/pages/home/feed/FeedGenerators/constants.ts @@ -3,7 +3,6 @@ export const categories = [ "afrobeat", "afrobeats", "alternative metal", - "alternative r&b", "anime", "art pop", "breakcore", diff --git a/bun.lock b/bun.lock index 04b82de4..96ce5866 100644 --- a/bun.lock +++ b/bun.lock @@ -208,7 +208,7 @@ "lodash": "^4.17.21", "numeral": "^2.0.6", "posthog-js": "^1.234.6", - "ramda": "^0.30.1", + "ramda": "^0.32.0", "react": "^18.3.1", "react-content-loader": "^7.0.2", "react-dom": "^18.3.1", @@ -236,7 +236,7 @@ "@storybook/test": "^8.5.2", "@tanstack/router-plugin": "^1.125.4", "@types/lodash": "^4.17.15", - "@types/ramda": "^0.30.2", + "@types/ramda": "^0.31.1", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@vitejs/plugin-react-swc": "^3.5.0", @@ -3054,6 +3054,10 @@ "@rocksky/spotify-proxy/wrangler": ["wrangler@4.42.2", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.7", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20251008.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.21", "workerd": "1.20251008.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20251008.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-1iTnbjB4F12KSP1zbfxQL495xarS+vdrZnulQP2SEcAxDTUGn7N9zk1O2WtFOc+Fhcgl+9/sdz/4AL9pF34Pwg=="], + "@rocksky/web/@types/ramda": ["@types/ramda@0.31.1", "", { "dependencies": { "types-ramda": "^0.31.0" } }, "sha512-Vt6sFXnuRpzaEj+yeutA0q3bcAsK7wdPuASIzR9LXqL4gJPyFw8im9qchlbp4ltuf3kDEIRmPJTD/Fkg60dn7g=="], + + "@rocksky/web/ramda": ["ramda@0.32.0", "", {}, "sha512-GQWAHhxhxWBWA8oIBr1XahFVjQ9Fic6MK9ikijfd4TZHfE2+urfk+irVlR5VOn48uwMgM+loRRBJd6Yjsbc0zQ=="], + "@rocksky/web/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], "@rocksky/web/vitest": ["vitest@3.0.9", "", { "dependencies": { "@vitest/expect": "3.0.9", "@vitest/mocker": "3.0.9", "@vitest/pretty-format": "^3.0.9", "@vitest/runner": "3.0.9", "@vitest/snapshot": "3.0.9", "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.9", "@vitest/ui": "3.0.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ=="], @@ -3502,6 +3506,8 @@ "@rocksky/web-mobile/vitest/vite-node": ["vite-node@3.0.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg=="], + "@rocksky/web/@types/ramda/types-ramda": ["types-ramda@0.31.0", "", { "dependencies": { "ts-toolbelt": "^9.6.0" } }, "sha512-vaoC35CRC3xvL8Z6HkshDbi6KWM1ezK0LHN0YyxXWUn9HKzBNg/T3xSGlJZjCYspnOD3jE7bcizsp0bUXZDxnQ=="], + "@rocksky/web/vitest/@vitest/expect": ["@vitest/expect@3.0.9", "", { "dependencies": { "@vitest/spy": "3.0.9", "@vitest/utils": "3.0.9", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig=="], "@rocksky/web/vitest/@vitest/mocker": ["@vitest/mocker@3.0.9", "", { "dependencies": { "@vitest/spy": "3.0.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA=="],