diff --git a/.prettierrc.json b/.prettierrc.json
index 6a32fd0..84fb09c 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -5,21 +5,5 @@
"printWidth": 80,
"arrowParens": "always",
"importOrderSeparation": true,
- "importOrder": [
- "^next.*",
- "^react$",
- "^react.*",
- "^axios.*",
- "^@emotion/.*",
- "^@mui/material/.*",
- "^@mui/.*",
- "^@src/.*",
- "^@models/.*",
- "^@interfaces/.*",
- "^@utils/.*",
- "^@components/.*",
- ".*sass$",
- ".*css$",
- "^@svg/.*"
- ]
+ "importOrder": ["^next./", "^@nextui-org/."]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..6ea2e9f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "prettier.configPath": ".prettierrc.json"
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 879393a..4aa8d27 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
},
"devDependencies": {
"@tanstack/react-query-devtools": "^5.27.8",
+ "@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/next-pwa": "^5.6.9",
"@types/node": "^20",
"@types/react": "^18",
diff --git a/src/app/(trending)/Trending.tsx b/src/app/(trending)/Trending.tsx
index 066ea95..2147ece 100644
--- a/src/app/(trending)/Trending.tsx
+++ b/src/app/(trending)/Trending.tsx
@@ -3,18 +3,17 @@
import { Component } from "@/typings/component";
import { useClient } from "@/hooks/useClient";
import { useQuery } from "@tanstack/react-query";
-import { Card, CardFooter, CardBody } from "@nextui-org/card";
-import { Image } from "@nextui-org/image";
+
import { Button } from "@nextui-org/button";
import { CircularProgress } from "@nextui-org/progress";
-import { Divider } from "@nextui-org/divider";
-import Link from "next/link";
-import formatNumber from "@/utils/formatNumbers";
+
+import { Spacer } from "@nextui-org/spacer";
+import { VideoCard } from "./VideoCard";
export const Trending: Component = ({}) => {
const client = useClient();
- const { isLoading, error, data } = useQuery({
+ const { isLoading, error, refetch, data } = useQuery({
queryKey: ["trending"],
queryFn: () => client.getTrending("NL")
});
@@ -26,45 +25,24 @@ export const Trending: Component = ({}) => {
)}
+ {error && (
+
+
+
+ An error occurred loading the trending page
+
+ {error.toString()}
+
+
+
+
+ )}
{data && (
{data.map((video) => (
-
-
-
-
-
- 20:41
-
-
-
-
-
-
- {video.title}
-
-
-
- {video.author.name}
-
-
- {video.uploaded.toLocaleDateString()}
-
-
-
- Views: {formatNumber(video.views)}
-
-
-
-
-
-
+
))}
)}
diff --git a/src/app/(trending)/VideoCard.tsx b/src/app/(trending)/VideoCard.tsx
new file mode 100644
index 0000000..8e4d021
--- /dev/null
+++ b/src/app/(trending)/VideoCard.tsx
@@ -0,0 +1,50 @@
+import { TrendingVideo } from "@/client/typings/trending";
+import { Component } from "@/typings/component";
+import { Card, CardFooter, CardBody } from "@nextui-org/card";
+import { Image } from "@nextui-org/image";
+import { Divider } from "@nextui-org/divider";
+import Link from "next/link";
+import formatNumber from "@/utils/formatNumbers";
+
+export const VideoCard: Component<{ data: TrendingVideo }> = ({
+ data: video
+}) => {
+ return (
+
+
+
+
+
+ {video.duration}
+
+
+
+
+
+
+ {video.title}
+
+
+
+ {video.author.name}
+
+
+ {video.uploaded.toLocaleDateString()}
+
+
+
+ Views: {formatNumber(video.views)}
+
+
+
+
+
+
+ );
+};
diff --git a/src/client/adapters/invidious/transformer.ts b/src/client/adapters/invidious/transformer.ts
index 3d7f5f9..4bf506b 100644
--- a/src/client/adapters/invidious/transformer.ts
+++ b/src/client/adapters/invidious/transformer.ts
@@ -1,23 +1,31 @@
import { TrendingVideo } from "@/client/typings/trending";
-import { Thumbnail } from "@/client/typings/thumbnail";
import InvidiousTrending from "./typings/trending";
-import InvidiousThumbnail from "./typings/thumbnail";
export default class Transformer {
- public static thumbnails(data: InvidiousThumbnail[]): Thumbnail[] {
- return data.map((thumbnail) => ({ url: thumbnail.url }));
- }
-
public static trending(data: InvidiousTrending[]): TrendingVideo[] {
- return data.map((video) => ({
- author: { id: video.authorId, name: video.author },
- duration: video.lengthSeconds * 1000,
- id: video.videoId,
- title: video.title,
- thumbnails: Transformer.thumbnails(video.videoThumbnails),
- uploaded: new Date(video.published * 1000 ?? 0),
- views: video.viewCount
- }));
+ return data.map((video) => {
+ const thumbnail = video.videoThumbnails.find(
+ (thumbnail) =>
+ thumbnail.quality == "default" ||
+ thumbnail.quality == "medium" ||
+ thumbnail.quality == "middle"
+ );
+
+ if (thumbnail === undefined)
+ throw new Error(
+ `Invidious: Missing thumbnail for video with id ${video.videoId}`
+ );
+
+ return {
+ author: { id: video.authorId, name: video.author },
+ duration: video.lengthSeconds * 1000,
+ id: video.videoId,
+ title: video.title,
+ thumbnail: thumbnail.url,
+ uploaded: new Date(video.published * 1000 ?? 0),
+ views: video.viewCount
+ };
+ });
}
}
diff --git a/src/client/adapters/invidious/typings/thumbnail.ts b/src/client/adapters/invidious/typings/thumbnail.ts
index bb08c89..730a49d 100644
--- a/src/client/adapters/invidious/typings/thumbnail.ts
+++ b/src/client/adapters/invidious/typings/thumbnail.ts
@@ -1,7 +1,19 @@
import z from "zod";
+const qualityTypes = [
+ "maxres",
+ "maxresdefault",
+ "sddefault",
+ "high",
+ "medium",
+ "default",
+ "start",
+ "middle",
+ "end"
+] as const;
+
export const ThumbnailModel = z.object({
- quality: z.string(),
+ quality: z.enum(qualityTypes),
url: z.string().url(),
width: z.number(),
height: z.number()
diff --git a/src/client/adapters/piped/transformer.ts b/src/client/adapters/piped/transformer.ts
index 833a492..88a2cc3 100644
--- a/src/client/adapters/piped/transformer.ts
+++ b/src/client/adapters/piped/transformer.ts
@@ -26,7 +26,7 @@ export default class Transformer {
views: video.views,
id: videoId,
uploaded: new Date(video.uploaded),
- thumbnails: [{ url: video.thumbnail }],
+ thumbnail: video.thumbnail,
title: video.title,
author: { id: channelId, name: video.uploaderName }
};
diff --git a/src/client/typings/thumbnail.ts b/src/client/typings/thumbnail.ts
deleted file mode 100644
index 0867598..0000000
--- a/src/client/typings/thumbnail.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface Thumbnail {
- url: string;
-}
diff --git a/src/client/typings/trending.ts b/src/client/typings/trending.ts
index 8085205..c9ba2f6 100644
--- a/src/client/typings/trending.ts
+++ b/src/client/typings/trending.ts
@@ -1,8 +1,6 @@
-import { Thumbnail } from "./thumbnail";
-
export interface TrendingVideo {
title: string;
- thumbnails: Thumbnail[];
+ thumbnail: string;
id: string;
author: {
name: string;
diff --git a/yarn.lock b/yarn.lock
index 6387f29..0542599 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -29,7 +29,7 @@
jsonpointer "^5.0.0"
leven "^3.1.0"
-"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.23.5":
+"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5":
version "7.23.5"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==
@@ -63,7 +63,16 @@
json5 "^2.2.3"
semver "^6.3.1"
-"@babel/generator@^7.23.6":
+"@babel/generator@7.17.7":
+ version "7.17.7"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad"
+ integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==
+ dependencies:
+ "@babel/types" "^7.17.0"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
+"@babel/generator@^7.23.0", "@babel/generator@^7.23.6":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e"
integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==
@@ -245,7 +254,7 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83"
integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==
-"@babel/helper-validator-identifier@^7.22.20":
+"@babel/helper-validator-identifier@^7.16.7", "@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
@@ -282,7 +291,7 @@
chalk "^2.4.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.24.0":
+"@babel/parser@^7.20.5", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac"
integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
@@ -947,6 +956,22 @@
"@babel/parser" "^7.24.0"
"@babel/types" "^7.24.0"
+"@babel/traverse@7.23.2":
+ version "7.23.2"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
+ integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
+ dependencies:
+ "@babel/code-frame" "^7.22.13"
+ "@babel/generator" "^7.23.0"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/parser" "^7.23.0"
+ "@babel/types" "^7.23.0"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
"@babel/traverse@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e"
@@ -963,7 +988,15 @@
debug "^4.3.1"
globals "^11.1.0"
-"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4":
+"@babel/types@7.17.0":
+ version "7.17.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b"
+ integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ to-fast-properties "^2.0.0"
+
+"@babel/types@^7.17.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
@@ -2955,6 +2988,18 @@
dependencies:
"@tanstack/query-core" "5.27.5"
+"@trivago/prettier-plugin-sort-imports@^4.3.0":
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz#725f411646b3942193a37041c84e0b2116339789"
+ integrity sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==
+ dependencies:
+ "@babel/generator" "7.17.7"
+ "@babel/parser" "^7.20.5"
+ "@babel/traverse" "7.23.2"
+ "@babel/types" "7.17.0"
+ javascript-natural-sort "0.7.1"
+ lodash "^4.17.21"
+
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@@ -4804,6 +4849,11 @@ jake@^10.8.5:
filelist "^1.0.4"
minimatch "^3.1.2"
+javascript-natural-sort@0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
+ integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==
+
jest-worker@^26.2.1:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
@@ -5032,7 +5082,7 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
-lodash@^4.17.20:
+lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -5932,6 +5982,11 @@ source-map-support@~0.5.20:
buffer-from "^1.0.0"
source-map "^0.6.0"
+source-map@^0.5.0:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
source-map@^0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"