From 7470d389a7ebbf5a6cf194e8183db3c14dc1f02e Mon Sep 17 00:00:00 2001 From: Matthieu Jacq <67386567+matthieujacq@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:41:08 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=91=A4=20Implement=20gravatar=20(?= =?UTF-8?q?#1268)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ Implement gravatar * ♻️ refact gravatar url generation with a custom hook * review: do not add a default value to the email if undefined --- .../ChatsListItem/components/UserButton.tsx | 13 ++++++-- .../ChatsListItem/hooks/useGravatar.ts | 30 +++++++++++++++++++ frontend/next.config.js | 6 +++- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 frontend/app/chat/components/ChatsList/components/ChatsListItem/hooks/useGravatar.ts diff --git a/frontend/app/chat/components/ChatsList/components/ChatsListItem/components/UserButton.tsx b/frontend/app/chat/components/ChatsList/components/ChatsListItem/components/UserButton.tsx index 2128e8158ed8..f8c9ff243580 100644 --- a/frontend/app/chat/components/ChatsList/components/ChatsListItem/components/UserButton.tsx +++ b/frontend/app/chat/components/ChatsList/components/ChatsListItem/components/UserButton.tsx @@ -1,16 +1,25 @@ +import Image from "next/image"; import Link from "next/link"; -import { MdPerson } from "react-icons/md"; import { useSupabase } from "@/lib/context/SupabaseProvider"; +import { useGravatar } from "../hooks/useGravatar"; import { sidebarLinkStyle } from "../styles/SidebarLinkStyle"; export const UserButton = (): JSX.Element => { const { session } = useSupabase(); + const { gravatarUrl } = useGravatar(); return ( - +
+ gravatar +
{session?.user.email ?? ""} diff --git a/frontend/app/chat/components/ChatsList/components/ChatsListItem/hooks/useGravatar.ts b/frontend/app/chat/components/ChatsList/components/ChatsListItem/hooks/useGravatar.ts new file mode 100644 index 000000000000..ded77c203efb --- /dev/null +++ b/frontend/app/chat/components/ChatsList/components/ChatsListItem/hooks/useGravatar.ts @@ -0,0 +1,30 @@ +import { createHash } from "crypto"; +import { useEffect, useState } from "react"; + +import { useSupabase } from "@/lib/context/SupabaseProvider"; + +// Gravatar images may be requested just like a normal image, using an IMG tag. To get an image specific to a user, you must first calculate their email hash. +// The most basic image request URL looks like this: +// https://www.gravatar.com/avatar/HASH + +const computeGravatarUrl = (email?: string) => { + const hash = createHash("md5") + .update(typeof email === "string" ? email.trim().toLowerCase() : "") + .digest("hex"); + + return `https://www.gravatar.com/avatar/${hash}?d=mp`; +}; + +export const useGravatar = (): { gravatarUrl: string } => { + const { session } = useSupabase(); + const [gravatarUrl, setGravatarUrl] = useState(computeGravatarUrl()); + + const email = session?.user.email; + + useEffect(() => { + const computedUrl = computeGravatarUrl(email); + setGravatarUrl(computedUrl); + }, [email]); + + return { gravatarUrl }; +}; diff --git a/frontend/next.config.js b/frontend/next.config.js index 5c5440d4c3fd..fc3f56345703 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -1,6 +1,10 @@ const nextConfig = { images: { - domains: ["www.quivr.app", "quivr-cms.s3.eu-west-3.amazonaws.com"] + domains: [ + "www.quivr.app", + "quivr-cms.s3.eu-west-3.amazonaws.com", + "www.gravatar.com", + ], }, // eslint-disable-next-line prefer-arrow/prefer-arrow-functions async headers() {