-
Notifications
You must be signed in to change notification settings - Fork 702
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,946 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
OPENAI_API_KEY= | ||
OPENAI_API_KEY=sk-xxx | ||
BILIBILI_SESSION_TOKEN= | ||
UPSTASH_REDIS_REST_URL= | ||
UPSTASH_REDIS_REST_TOKEN= | ||
UPSTASH_RATE_REDIS_REST_URL= | ||
UPSTASH_RATE_REDIS_REST_TOKEN= | ||
LEMON_API_KEY= | ||
SUPABASE_HOSTNAME="xxxx.supabase.co" | ||
NEXT_PUBLIC_SUPABASE_URL="https://${SUPABASE_HOSTNAME}" | ||
NEXT_PUBLIC_SUPABASE_ANON_KEY="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { useUser } from "@supabase/auth-helpers-react"; | ||
import { AnimatePresence, motion } from "framer-motion"; | ||
import { useSignInModal } from "~/components/sign-in-modal"; | ||
import UserDropdown from "~/components/user-dropdown"; | ||
import { FADE_IN_ANIMATION_SETTINGS } from "~/utils/constants"; | ||
|
||
export default function SignIn() { | ||
const user = useUser(); | ||
console.log("========user========", user); | ||
const { SignInModal, setShowSignInModal } = useSignInModal(); | ||
/*useEffect(() => { | ||
async function loadData() { | ||
const { data } = await supabaseClient.from('test').select('*') | ||
setData(data) | ||
} | ||
// Only run query once user is logged in. | ||
if (user) loadData() | ||
}, [user])*/ | ||
return ( | ||
<div> | ||
<SignInModal /> | ||
|
||
<AnimatePresence> | ||
{user ? ( | ||
<UserDropdown /> | ||
) : ( | ||
<motion.button | ||
className="rounded-full border border-black bg-black p-1.5 px-4 text-sm text-white transition-all hover:bg-white hover:text-black" | ||
onClick={() => setShowSignInModal(true)} | ||
{...FADE_IN_ANIMATION_SETTINGS} | ||
> | ||
Sign In | ||
</motion.button> | ||
)} | ||
</AnimatePresence> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { useEffect, useRef, ReactNode, Dispatch, SetStateAction } from "react"; | ||
import { AnimatePresence, motion, useAnimation } from "framer-motion"; | ||
|
||
export default function Leaflet({ | ||
setShow, | ||
children, | ||
}: { | ||
setShow: Dispatch<SetStateAction<boolean>>; | ||
children: ReactNode; | ||
}) { | ||
const leafletRef = useRef<HTMLDivElement>(null); | ||
const controls = useAnimation(); | ||
const transitionProps = { type: "spring", stiffness: 500, damping: 30 }; | ||
useEffect(() => { | ||
controls.start({ | ||
y: 20, | ||
transition: transitionProps, | ||
}); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
|
||
async function handleDragEnd(_: any, info: any) { | ||
const offset = info.offset.y; | ||
const velocity = info.velocity.y; | ||
const height = leafletRef.current?.getBoundingClientRect().height || 0; | ||
if (offset > height / 2 || velocity > 800) { | ||
await controls.start({ y: "100%", transition: transitionProps }); | ||
setShow(false); | ||
} else { | ||
controls.start({ y: 0, transition: transitionProps }); | ||
} | ||
} | ||
|
||
return ( | ||
<AnimatePresence> | ||
<motion.div | ||
ref={leafletRef} | ||
key="leaflet" | ||
className="group fixed inset-x-0 bottom-0 z-40 w-screen cursor-grab bg-white pb-5 active:cursor-grabbing sm:hidden" | ||
initial={{ y: "100%" }} | ||
animate={controls} | ||
exit={{ y: "100%" }} | ||
transition={transitionProps} | ||
drag="y" | ||
dragDirectionLock | ||
onDragEnd={handleDragEnd} | ||
dragElastic={{ top: 0, bottom: 1 }} | ||
dragConstraints={{ top: 0, bottom: 0 }} | ||
> | ||
<div | ||
className={`rounded-t-4xl -mb-1 flex h-7 w-full items-center justify-center border-t border-gray-200`} | ||
> | ||
<div className="-mr-1 h-1 w-6 rounded-full bg-gray-300 transition-all group-active:rotate-12" /> | ||
<div className="h-1 w-6 rounded-full bg-gray-300 transition-all group-active:-rotate-12" /> | ||
</div> | ||
{children} | ||
</motion.div> | ||
<motion.div | ||
key="leaflet-backdrop" | ||
className="fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur" | ||
initial={{ opacity: 0 }} | ||
animate={{ opacity: 1 }} | ||
exit={{ opacity: 0 }} | ||
onClick={() => setShow(false)} | ||
/> | ||
</AnimatePresence> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { | ||
Dispatch, | ||
SetStateAction, | ||
useCallback, | ||
useEffect, | ||
useRef, | ||
} from "react"; | ||
import FocusTrap from "focus-trap-react"; | ||
import { AnimatePresence, motion } from "framer-motion"; | ||
import Leaflet from "./leaflet"; | ||
import useWindowSize from "~/lib/hooks/use-window-size"; | ||
|
||
export default function Modal({ | ||
children, | ||
showModal, | ||
setShowModal, | ||
}: { | ||
children: React.ReactNode; | ||
showModal: boolean; | ||
setShowModal: Dispatch<SetStateAction<boolean>>; | ||
}) { | ||
const desktopModalRef = useRef(null); | ||
|
||
const onKeyDown = useCallback( | ||
(e: KeyboardEvent) => { | ||
if (e.key === "Escape") { | ||
setShowModal(false); | ||
} | ||
}, | ||
[setShowModal], | ||
); | ||
|
||
useEffect(() => { | ||
document.addEventListener("keydown", onKeyDown); | ||
return () => document.removeEventListener("keydown", onKeyDown); | ||
}, [onKeyDown]); | ||
|
||
const { isMobile, isDesktop } = useWindowSize(); | ||
|
||
return ( | ||
<AnimatePresence> | ||
{showModal && ( | ||
<> | ||
{isMobile && <Leaflet setShow={setShowModal}>{children}</Leaflet>} | ||
{isDesktop && ( | ||
<> | ||
<FocusTrap focusTrapOptions={{ initialFocus: false }}> | ||
<motion.div | ||
ref={desktopModalRef} | ||
key="desktop-modal" | ||
className="fixed inset-0 z-40 hidden min-h-screen items-center justify-center md:flex" | ||
initial={{ scale: 0.95 }} | ||
animate={{ scale: 1 }} | ||
exit={{ scale: 0.95 }} | ||
onMouseDown={(e) => { | ||
if (desktopModalRef.current === e.target) { | ||
setShowModal(false); | ||
} | ||
}} | ||
> | ||
{children} | ||
</motion.div> | ||
</FocusTrap> | ||
<motion.div | ||
key="desktop-backdrop" | ||
className="fixed inset-0 z-30 bg-gray-100 bg-opacity-10 backdrop-blur" | ||
initial={{ opacity: 0 }} | ||
animate={{ opacity: 1 }} | ||
exit={{ opacity: 0 }} | ||
onClick={() => setShowModal(false)} | ||
/> | ||
</> | ||
)} | ||
</> | ||
)} | ||
</AnimatePresence> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Dispatch, SetStateAction, ReactNode, useRef } from "react"; | ||
import * as PopoverPrimitive from "@radix-ui/react-popover"; | ||
import useWindowSize from "~/lib/hooks/use-window-size"; | ||
import Leaflet from "./leaflet"; | ||
|
||
export default function Popover({ | ||
children, | ||
content, | ||
align = "center", | ||
openPopover, | ||
setOpenPopover, | ||
}: { | ||
children: ReactNode; | ||
content: ReactNode | string; | ||
align?: "center" | "start" | "end"; | ||
openPopover: boolean; | ||
setOpenPopover: Dispatch<SetStateAction<boolean>>; | ||
}) { | ||
const { isMobile, isDesktop } = useWindowSize(); | ||
return ( | ||
<> | ||
{isMobile && children} | ||
{openPopover && isMobile && ( | ||
<Leaflet setShow={setOpenPopover}>{content}</Leaflet> | ||
)} | ||
{isDesktop && ( | ||
<PopoverPrimitive.Root> | ||
<PopoverPrimitive.Trigger className="inline-flex" asChild> | ||
{children} | ||
</PopoverPrimitive.Trigger> | ||
<PopoverPrimitive.Content | ||
sideOffset={4} | ||
align={align} | ||
className="z-20 animate-slide-up-fade items-center rounded-md border border-gray-200 bg-white drop-shadow-lg" | ||
> | ||
{content} | ||
</PopoverPrimitive.Content> | ||
</PopoverPrimitive.Root> | ||
)} | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { useSupabaseClient } from "@supabase/auth-helpers-react"; | ||
import { Auth } from "@supabase/auth-ui-react"; | ||
import { ThemeSupa } from "@supabase/auth-ui-shared"; | ||
import React, { | ||
Dispatch, | ||
SetStateAction, | ||
useCallback, | ||
useMemo, | ||
useState, | ||
} from "react"; | ||
import Modal from "~/components/shared/modal"; | ||
import Image from "next/image"; | ||
import { BASE_DOMAIN } from "~/utils/constants"; | ||
|
||
const SignInModal = ({ | ||
showSignInModal, | ||
setShowSignInModal, | ||
}: { | ||
showSignInModal: boolean; | ||
setShowSignInModal: Dispatch<SetStateAction<boolean>>; | ||
}) => { | ||
const supabaseClient = useSupabaseClient(); | ||
return ( | ||
<Modal showModal={showSignInModal} setShowModal={setShowSignInModal}> | ||
<div className="w-full overflow-hidden shadow-xl md:max-w-md md:rounded-2xl md:border md:border-gray-200"> | ||
<div className="flex flex-col items-center justify-center space-y-3 border-b border-gray-200 bg-white px-4 py-6 pt-8 text-center md:px-16"> | ||
<a href={BASE_DOMAIN}> | ||
<Image | ||
src="/tv-logo.png" | ||
alt="Logo" | ||
className="h-10 w-10 rounded-full" | ||
width={20} | ||
height={20} | ||
/> | ||
</a> | ||
<h3 className="font-display text-2xl font-bold">登录</h3> | ||
<p className="text-sm text-pink-400">Prompt, Publish, Profit</p> | ||
</div> | ||
|
||
<div className="flex flex-col space-y-4 bg-gray-50 px-4 py-8 md:px-16"> | ||
<Auth | ||
supabaseClient={supabaseClient} | ||
providers={[ | ||
"notion", | ||
"github", | ||
// "google", "facebook", | ||
// "twitter", | ||
]} | ||
appearance={{ | ||
theme: ThemeSupa, | ||
variables: { | ||
default: { | ||
colors: { | ||
brand: "#F17EB8", | ||
brandAccent: "#f88dbf", | ||
// brandButtonText: "white", | ||
}, | ||
}, | ||
}, | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
</Modal> | ||
); | ||
}; | ||
|
||
export function useSignInModal() { | ||
const [showSignInModal, setShowSignInModal] = useState(false); | ||
|
||
const SignInModalCallback = useCallback(() => { | ||
return ( | ||
<SignInModal | ||
showSignInModal={showSignInModal} | ||
setShowSignInModal={setShowSignInModal} | ||
/> | ||
); | ||
}, [showSignInModal, setShowSignInModal]); | ||
|
||
return useMemo( | ||
() => ({ setShowSignInModal, SignInModal: SignInModalCallback }), | ||
[setShowSignInModal, SignInModalCallback] | ||
); | ||
} |
Oops, something went wrong.