diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx index 76a2706..a67d48d 100644 --- a/components/CollectionCard.tsx +++ b/components/CollectionCard.tsx @@ -68,7 +68,7 @@ export default function CollectionCard({ collection, className }: Props) { return ( ); diff --git a/components/Modal/Collection/TeamManagement.tsx b/components/Modal/Collection/TeamManagement.tsx index b163681..07854aa 100644 --- a/components/Modal/Collection/TeamManagement.tsx +++ b/components/Modal/Collection/TeamManagement.tsx @@ -238,7 +238,7 @@ export default function TeamManagement({ )}
@@ -425,7 +425,7 @@ export default function TeamManagement({ >
diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 9f8984f..4a91fb5 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -83,7 +83,7 @@ export default function Navbar() { id="profile-dropdown" > diff --git a/components/ProfilePhoto.tsx b/components/ProfilePhoto.tsx index e2f2b39..7dcb02c 100644 --- a/components/ProfilePhoto.tsx +++ b/components/ProfilePhoto.tsx @@ -2,38 +2,28 @@ import React, { useEffect, useState } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faUser } from "@fortawesome/free-solid-svg-icons"; import Image from "next/image"; -import avatarExists from "@/lib/client/avatarExists"; type Props = { - src: string; + src?: string; className?: string; emptyImage?: boolean; - status?: Function; priority?: boolean; }; -export default function ProfilePhoto({ - src, - className, - emptyImage, - status, - priority, -}: Props) { - const [error, setError] = useState(emptyImage || true); - - const checkAvatarExistence = async () => { - const canPass = await avatarExists(src); - - setError(!canPass); - }; +export default function ProfilePhoto({ src, className, priority }: Props) { + const [image, setImage] = useState(""); useEffect(() => { - if (src) checkAvatarExistence(); + console.log(src); + if (src && !src?.includes("base64")) + setImage(`/api/v1/${src.replace("uploads/", "").replace(".jpg", "")}`); + else if (!src) setImage(""); + else { + setImage(src); + } + }, [src]); - status && status(error || !src); - }, [src, error]); - - return error || !src ? ( + return !image ? (
@@ -42,7 +32,7 @@ export default function ProfilePhoto({ ) : ( = { ...userInfo, whitelistedUsers: newWhitelistedUsernames, - profilePic: `/api/v1/avatar/${userInfo.id}?${Date.now()}`, + image: userInfo.image ? `${userInfo.image}?${Date.now()}` : "", }; return { response, status: 200 }; diff --git a/lib/api/migration/migrateToV2.js b/lib/api/migration/migrateToV2.js index ec2300a..dc4781d 100644 --- a/lib/api/migration/migrateToV2.js +++ b/lib/api/migration/migrateToV2.js @@ -70,7 +70,7 @@ async function migrateToV2() { if (res) { await prisma.user.update({ where: { id: user.id }, - data: { imagePath: path }, + data: { image: path }, }); console.log(`Updated avatar for avatar ${user.id}`); } else { diff --git a/lib/api/storage/readFile.ts b/lib/api/storage/readFile.ts index 0721d9d..bf543cf 100644 --- a/lib/api/storage/readFile.ts +++ b/lib/api/storage/readFile.ts @@ -9,14 +9,12 @@ import s3Client from "./s3Client"; import util from "util"; type ReturnContentTypes = - | "text/html" + | "text/plain" | "image/jpeg" | "image/png" | "application/pdf"; export default async function readFile(filePath: string) { - const isRequestingAvatar = filePath.startsWith("uploads/avatar"); - let contentType: ReturnContentTypes; if (s3Client) { @@ -41,12 +39,12 @@ export default async function readFile(filePath: string) { try { await headObjectAsync(bucketParams); } catch (err) { - contentType = "text/html"; + contentType = "text/plain"; returnObject = { - file: isRequestingAvatar ? "File not found." : fileNotFoundTemplate, + file: "File not found.", contentType, - status: isRequestingAvatar ? 200 : 400, + status: 400, }; } @@ -71,9 +69,9 @@ export default async function readFile(filePath: string) { } catch (err) { console.log("Error:", err); - contentType = "text/html"; + contentType = "text/plain"; return { - file: "An internal occurred, please contact support.", + file: "An internal occurred, please contact the support team.", contentType, }; } @@ -92,9 +90,9 @@ export default async function readFile(filePath: string) { if (!fs.existsSync(creationPath)) return { - file: isRequestingAvatar ? "File not found." : fileNotFoundTemplate, - contentType: "text/html", - status: isRequestingAvatar ? 200 : 400, + file: "File not found.", + contentType: "text/plain", + status: 400, }; else { const file = fs.readFileSync(creationPath); diff --git a/lib/client/addMemberToCollection.ts b/lib/client/addMemberToCollection.ts index af0db51..95f3217 100644 --- a/lib/client/addMemberToCollection.ts +++ b/lib/client/addMemberToCollection.ts @@ -35,6 +35,7 @@ const addMemberToCollection = async ( id: user.id, name: user.name, username: user.username, + image: user.image, }, }); } diff --git a/lib/client/avatarExists.ts b/lib/client/avatarExists.ts deleted file mode 100644 index f81f1e9..0000000 --- a/lib/client/avatarExists.ts +++ /dev/null @@ -1,13 +0,0 @@ -const avatarCache = new Map(); - -export default async function avatarExists(fileUrl: string): Promise { - if (avatarCache.has(fileUrl)) { - return avatarCache.get(fileUrl); - } - - const response = await fetch(fileUrl, { method: "HEAD" }); - const exists = !(response.headers.get("content-type") === "text/html"); - - avatarCache.set(fileUrl, exists); - return exists; -} diff --git a/lib/client/getPublicUserData.ts b/lib/client/getPublicUserData.ts index 20bd1e9..6b3706e 100644 --- a/lib/client/getPublicUserData.ts +++ b/lib/client/getPublicUserData.ts @@ -5,6 +5,8 @@ export default async function getPublicUserData(id: number | string) { const data = await response.json(); + console.log(data); + if (!response.ok) toast.error(data.response); return data.response; diff --git a/next.config.js b/next.config.js index 1c05e95..71cfd8e 100644 --- a/next.config.js +++ b/next.config.js @@ -3,6 +3,7 @@ const nextConfig = { reactStrictMode: true, images: { domains: ["t2.gstatic.com"], + minimumCacheTTL: 10, }, }; diff --git a/pages/api/v1/avatar/[id].ts b/pages/api/v1/avatar/[id].ts index c92b98b..97eeb91 100644 --- a/pages/api/v1/avatar/[id].ts +++ b/pages/api/v1/avatar/[id].ts @@ -13,7 +13,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) { if (!userId || !username) return res - .setHeader("Content-Type", "text/html") + .setHeader("Content-Type", "text/plain") .status(401) .send("You must be logged in."); else if (session?.user?.isSubscriber === false) @@ -24,7 +24,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) { if (!queryId) return res - .setHeader("Content-Type", "text/html") + .setHeader("Content-Type", "text/plain") .status(401) .send("Invalid parameters."); @@ -44,8 +44,9 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) { if (targetUser?.isPrivate && !whitelistedUsernames?.includes(username)) { return res - .setHeader("Content-Type", "text/html") - .send("This profile is private."); + .setHeader("Content-Type", "text/plain") + .status(400) + .send("File not found."); } } diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx index 59a7fc2..f1751aa 100644 --- a/pages/collections/[id].tsx +++ b/pages/collections/[id].tsx @@ -104,7 +104,7 @@ export default function Index() { return ( ); diff --git a/pages/collections/index.tsx b/pages/collections/index.tsx index 1f81285..a06ad6c 100644 --- a/pages/collections/index.tsx +++ b/pages/collections/index.tsx @@ -15,11 +15,8 @@ import useModalStore from "@/store/modals"; import SortDropdown from "@/components/SortDropdown"; import { Sort } from "@/types/global"; import useSort from "@/hooks/useSort"; -import { useTheme } from "next-themes"; export default function Collections() { - const { theme } = useTheme(); - const { collections } = useCollectionStore(); const [expandDropdown, setExpandDropdown] = useState(false); const [sortDropdown, setSortDropdown] = useState(false); diff --git a/pages/settings/account.tsx b/pages/settings/account.tsx index 20434ea..8248006 100644 --- a/pages/settings/account.tsx +++ b/pages/settings/account.tsx @@ -21,13 +21,8 @@ export default function Account() { const emailEnabled = process.env.NEXT_PUBLIC_EMAIL_PROVIDER; - const [profileStatus, setProfileStatus] = useState(true); const [submitLoader, setSubmitLoader] = useState(false); - const handleProfileStatus = (e: boolean) => { - setProfileStatus(!e); - }; - const { account, updateAccount } = useAccountStore(); const [user, setUser] = useState( @@ -40,12 +35,11 @@ export default function Account() { username: "", email: "", emailVerified: null, - image: null, + image: "", isPrivate: true, // @ts-ignore createdAt: null, whitelistedUsers: [], - profilePic: "", } as unknown as AccountSettings) ); @@ -54,6 +48,7 @@ export default function Account() { } useEffect(() => { + console.log(account); if (!objectIsEmpty(account)) setUser({ ...account }); }, [account]); @@ -68,7 +63,7 @@ export default function Account() { ) { const reader = new FileReader(); reader.onload = () => { - setUser({ ...user, profilePic: reader.result as string }); + setUser({ ...user, image: reader.result as string }); }; reader.readAsDataURL(resizedFile); } else { @@ -220,16 +215,15 @@ export default function Account() {
- {profileStatus && ( + {user.image && (
setUser({ ...user, - profilePic: "", + image: "", }) } className="absolute top-1 left-1 w-5 h-5 flex items-center justify-center border p-1 border-slate-200 dark:border-neutral-700 rounded-full bg-white dark:bg-neutral-800 text-center select-none cursor-pointer duration-100 hover:text-red-500" diff --git a/prisma/migrations/20231028041930_rename_image_path_to_image/migration.sql b/prisma/migrations/20231028041930_rename_image_path_to_image/migration.sql new file mode 100644 index 0000000..6833e7b --- /dev/null +++ b/prisma/migrations/20231028041930_rename_image_path_to_image/migration.sql @@ -0,0 +1 @@ +ALTER TABLE "User" RENAME COLUMN "imagePath" TO "image"; \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index dda64fd..d89d2a6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,7 +15,7 @@ model User { email String? @unique emailVerified DateTime? - imagePath String? + image String? password String collections Collection[] diff --git a/store/account.ts b/store/account.ts index c57d71e..c1da399 100644 --- a/store/account.ts +++ b/store/account.ts @@ -19,9 +19,7 @@ const useAccountStore = create()((set) => ({ const data = await response.json(); - const profilePic = `/api/v1/avatar/${data.response.id}?${Date.now()}`; - - if (response.ok) set({ account: { ...data.response, profilePic } }); + if (response.ok) set({ account: { ...data.response } }); }, updateAccount: async (user) => { const response = await fetch(`/api/v1/users/${user.id}`, { diff --git a/types/global.ts b/types/global.ts index 09959c5..4944c83 100644 --- a/types/global.ts +++ b/types/global.ts @@ -35,7 +35,6 @@ export interface CollectionIncludingMembersAndLinkCount } export interface AccountSettings extends User { - profilePic: string; newPassword?: string; whitelistedUsers: string[]; } @@ -79,7 +78,7 @@ interface CollectionIncludingLinks extends Collection { links: LinksIncludingTags[]; } -export interface Backup extends Omit { +export interface Backup extends Omit { collections: CollectionIncludingLinks[]; }