diff --git a/package.json b/package.json index 16787e4..05c95cf 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "react-image-crop": "^11.0.10", "redis": "^5.11.0", "satori": "^0.26.0", - "seedrandom": "^3.0.5", "sharp": "^0.34.5", "sjcl-with-all": "1.0.8", "swr": "^2.4.1", @@ -46,7 +45,6 @@ "@types/node": "^25.6.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "@types/seedrandom": "^3.0.8", "@types/sjcl": "^1.0.34", "eslint": "^10.2.0", "eslint-config-next": "16.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13b6320..26a202f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,9 +71,6 @@ importers: satori: specifier: ^0.26.0 version: 0.26.0 - seedrandom: - specifier: ^3.0.5 - version: 3.0.5 sharp: specifier: ^0.34.5 version: 0.34.5 @@ -108,9 +105,6 @@ importers: '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.14) - '@types/seedrandom': - specifier: ^3.0.8 - version: 3.0.8 '@types/sjcl': specifier: ^1.0.34 version: 1.0.34 @@ -797,9 +791,6 @@ packages: '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - '@types/seedrandom@3.0.8': - resolution: {integrity: sha512-TY1eezMU2zH2ozQoAFAQFOPpvP15g+ZgSfTZt31AUUH/Rxtnz3H+A/Sv1Snw2/amp//omibc+AEkTaA8KUeOLQ==} - '@types/sjcl@1.0.34': resolution: {integrity: sha512-bQHEeK5DTQRunIfQeUMgtpPsNNCcZyQ9MJuAfW1I7iN0LDunTc78Fu17STbLMd7KiEY/g2zHVApippa70h6HoQ==} @@ -2252,9 +2243,6 @@ packages: schema-dts@2.0.0: resolution: {integrity: sha512-t7NoCy3Rn5GHGx6p7s1qIYK/AeIb8ZxJNR9WUNFkwMv2CiiGZBmqqYWc2FlZVm5ZbiHMY4OvBWhj7QtyrFO2Jw==} - seedrandom@3.0.5: - resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3111,8 +3099,6 @@ snapshots: dependencies: csstype: 3.2.3 - '@types/seedrandom@3.0.8': {} - '@types/sjcl@1.0.34': {} '@types/use-sync-external-store@0.0.6': {} @@ -4701,8 +4687,6 @@ snapshots: transitivePeerDependencies: - typescript - seedrandom@3.0.5: {} - semver@6.3.1: {} semver@7.7.4: {} diff --git a/src/components/mii/list/index.tsx b/src/components/mii/list/index.tsx index 8fb5afa..b4c2dd8 100644 --- a/src/components/mii/list/index.tsx +++ b/src/components/mii/list/index.tsx @@ -1,7 +1,6 @@ import { Prisma } from "@prisma/client"; import crypto from "crypto"; -import seedrandom from "seedrandom"; import { searchSchema } from "@/lib/schemas"; import { auth } from "@/lib/auth"; @@ -23,7 +22,7 @@ export default async function MiiList({ searchParams, userId, parentPage }: Prop const parsed = searchSchema.safeParse(searchParams); if (!parsed.success) return

{parsed.error.issues[0].message}

; - const { q: query, sort, tags, exclude, platform, gender, makeup, allowCopying, quarantined, page = 1, limit = 24, seed } = parsed.data; + const { q: query, sort, tags, exclude, platform, gender, makeup, allowCopying, quarantined, page = 1, limit = 24 } = parsed.data; // My Likes page let miiIdsLiked: number[] | undefined = undefined; @@ -110,61 +109,29 @@ export default async function MiiList({ searchParams, userId, parentPage }: Prop let totalCount: number; let miis: Prisma.MiiGetPayload<{ select: typeof select }>[]; - if (sort === "random") { - // Get all IDs that match the where conditions - const matchingIds = await prisma.mii.findMany({ - where, - select: { id: true }, - }); + // Sorting by likes, newest, or oldest + let orderBy: Prisma.MiiOrderByWithRelationInput[]; - totalCount = matchingIds.length; - - if (matchingIds.length === 0) return; - - // Use seed for consistent random results - const randomSeed = seed || crypto.randomInt(0, 1_000_000_000); - const rng = seedrandom(randomSeed.toString()); - - // Randomize all IDs using the Durstenfeld algorithm - for (let i = matchingIds.length - 1; i > 0; i--) { - const j = Math.floor(rng() * (i + 1)); - [matchingIds[i], matchingIds[j]] = [matchingIds[j], matchingIds[i]]; - } - - // Convert to number[] array - const selectedIds = matchingIds.slice(skip, skip + limit).map((i) => i.id); - - miis = await prisma.mii.findMany({ - where: { - id: { in: selectedIds }, - }, - select, - }); + if (sort === "likes") { + orderBy = [{ likedBy: { _count: "desc" } }, { name: "asc" }]; + } else if (sort === "oldest") { + orderBy = [{ createdAt: "asc" }, { name: "asc" }]; } else { - // Sorting by likes, newest, or oldest - let orderBy: Prisma.MiiOrderByWithRelationInput[]; - - if (sort === "likes") { - orderBy = [{ likedBy: { _count: "desc" } }, { name: "asc" }]; - } else if (sort === "oldest") { - orderBy = [{ createdAt: "asc" }, { name: "asc" }]; - } else { - // default to newest - orderBy = [{ createdAt: "desc" }, { name: "asc" }]; - } - - [totalCount, miis] = await Promise.all([ - prisma.mii.count({ where: { ...where, userId } }), - prisma.mii.findMany({ - where, - orderBy, - select, - skip, - take: limit, - }), - ]); + // default to newest + orderBy = [{ createdAt: "desc" }, { name: "asc" }]; } + [totalCount, miis] = await Promise.all([ + prisma.mii.count({ where: { ...where, userId } }), + prisma.mii.findMany({ + where, + orderBy, + select, + skip, + take: limit, + }), + ]); + const lastPage = Math.ceil(totalCount / limit); return ( diff --git a/src/components/mii/list/sort-select.tsx b/src/components/mii/list/sort-select.tsx index e62ed01..654e796 100644 --- a/src/components/mii/list/sort-select.tsx +++ b/src/components/mii/list/sort-select.tsx @@ -5,9 +5,9 @@ import { useTransition } from "react"; import { useSelect } from "downshift"; import { Icon } from "@iconify/react"; -type Sort = "likes" | "newest" | "oldest" | "random"; +type Sort = "likes" | "newest" | "oldest"; -const items = ["likes", "newest", "oldest", "random"]; +const items = ["likes", "newest", "oldest"]; export default function SortSelect() { const router = useRouter(); @@ -26,10 +26,6 @@ export default function SortSelect() { params.set("page", "1"); params.set("sort", selectedItem); - if (selectedItem == "random") { - params.set("seed", Math.floor(Math.random() * 1_000_000_000).toString()); - } - startTransition(() => { router.push(`?${params.toString()}`, { scroll: false }); }); diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts index 5e4ae4e..490cc5f 100644 --- a/src/lib/schemas.ts +++ b/src/lib/schemas.ts @@ -39,7 +39,7 @@ export const idSchema = z.coerce.number({ error: "ID must be a number" }).int({ export const searchSchema = z.object({ q: querySchema.optional(), - sort: z.enum(["likes", "newest", "oldest", "random"], { error: "Sort must be either 'likes', 'newest', 'oldest', or 'random'" }).default("newest"), + sort: z.enum(["likes", "newest", "oldest"], { error: "Sort must be either 'likes', 'newest', or 'oldest'" }).default("newest"), tags: z .string() .optional() @@ -72,8 +72,6 @@ export const searchSchema = z.object({ .max(100, { error: "Limit cannot be more than 100" }) .optional(), page: z.coerce.number({ error: "Page must be a number" }).int({ error: "Page must be an integer" }).min(1, { error: "Page must be at least 1" }).optional(), - // Random sort - seed: z.coerce.number({ error: "Seed must be a number" }).int({ error: "Seed must be an integer" }).optional(), }); export const userNameSchema = z