diff --git a/components/LoginButton.tsx b/components/LoginButton.tsx index 35ec9f27..0f61a3dd 100644 --- a/components/LoginButton.tsx +++ b/components/LoginButton.tsx @@ -1,23 +1,26 @@ "use client"; import { useIdentityData } from "./IdentityProvider"; import { Popover } from "./Popover"; +import { Modal } from "./Modal"; import LoginForm from "app/login/LoginForm"; import { ButtonPrimary } from "./Buttons"; import { ActionButton } from "./ActionBar/ActionButton"; import { AccountSmall } from "./Icons/AccountSmall"; -import { useIsMobile } from "src/hooks/isMobile"; import { AtmosphericHandleInfo } from "./Subscribe/HandleSubscribe"; import { HandleInput } from "./Subscribe/HandleInput"; import { EmailInput, EmailConfirm } from "./Subscribe/EmailSubscribe"; import { useState } from "react"; import { GoToArrow } from "./Icons/GoToArrow"; import { ToggleGroup } from "./ToggleGroup"; -import { Modal } from "./Modal"; import { useToaster } from "./Toast"; -import { InfoSmall } from "./Icons/InfoSmall"; -import { HelpSmall } from "./Icons/HelpSmall"; -import { HelpTiny } from "./Icons/HelpTiny"; import { BlueskyTiny } from "./Icons/BlueskyTiny"; +import { + requestAuthEmailToken, + confirmEmailAuthToken, +} from "actions/emailAuth"; +import { loginWithEmailToken } from "actions/login"; +import { getHomeDocs } from "app/(home-pages)/home/storage"; +import { mutate } from "swr"; export function LoginButton() { let identityData = useIdentityData(); @@ -39,24 +42,55 @@ export function LoginButton() { export function LoginActionButton() { let identityData = useIdentityData(); if (identityData.identity) return null; - let isMobile = useIsMobile(); - let [state, setState] = useState<"log in" | "sign up" | "email log in">( - "log in", - ); + let [state, setState] = useState< + "log in" | "sign up" | "email log in" | "email confirm" + >("log in"); let [loginEmail, setLoginEmail] = useState(""); + let [tokenId, setTokenId] = useState(null); let toaster = useToaster(); + + const handleEmailSubmit = async () => { + const id = await requestAuthEmailToken(loginEmail); + setTokenId(id); + setState("email confirm"); + }; + + const handleCodeSubmit = async (code: string) => { + if (!tokenId) return; + const confirmedToken = await confirmEmailAuthToken(tokenId, code); + if (!confirmedToken) { + toaster({ + content:
Incorrect code!
, + type: "error", + }); + } else { + const localLeaflets = getHomeDocs(); + await loginWithEmailToken(localLeaflets.filter((l) => !l.hidden)); + mutate("identity"); + toaster({ + content:
Welcome back!
, + type: "success", + }); + } + }; return ( - } label="Sign In" /> + } + label="Log In/Sign Up" + /> } > +
{state === "log in" ? ( <> -
-

Log into the Atmosphere

+
+

+ Log in with
+ Atmosphere account +

@@ -80,6 +117,9 @@ export function LoginActionButton() { } + onSubmit={(handle) => { + window.location.href = `/api/oauth/login?handle=${encodeURIComponent(handle)}&redirect_url=/`; + }} />
} />
- + + ) : state === "email confirm" ? ( + ) : (

Leaflet is part of
the Atmosphere.

-
+
Create an Atmosphere account on Bluesky to get started!
@@ -146,7 +174,7 @@ export function LoginActionButton() {
)}
- {/**/} - +
+ ); } diff --git a/components/Subscribe/EmailSubscribe.tsx b/components/Subscribe/EmailSubscribe.tsx index 18fc7319..b63d3542 100644 --- a/components/Subscribe/EmailSubscribe.tsx +++ b/components/Subscribe/EmailSubscribe.tsx @@ -33,19 +33,19 @@ export const EmailInput = (props: { export const EmailConfirm = (props: { emailValue: string; - onSubmit: () => void; + onSubmit: (code: string) => void; }) => { let inputClassName = "input-with-border text-2xl w-8 h-12 text-center"; return ( -
+

Confirm your email

- Enter the confirmation code sent to
+ Enter the code sent to
{props.emailValue}
{ - props.onSubmit(); + onAutoSubmit={(value) => { + props.onSubmit(value); }} >
diff --git a/components/Subscribe/HandleInput.tsx b/components/Subscribe/HandleInput.tsx index 119943a1..c0743273 100644 --- a/components/Subscribe/HandleInput.tsx +++ b/components/Subscribe/HandleInput.tsx @@ -17,6 +17,7 @@ export const HandleInput = (props: { action?: React.ReactNode; className?: string; large?: boolean; + onSubmit?: (handle: string) => void; }) => { let [handleValue, setHandleValue] = useState(""); let [suggestions, setSuggestions] = useState([]); @@ -53,19 +54,26 @@ export const HandleInput = (props: { setHandleValue(selected); setDropdownOpen(false); setSuggestions([]); + props.onSubmit?.(selected); }; const handleKeyDown = (e: React.KeyboardEvent) => { - if (!dropdownOpen) return; if (e.key === "ArrowDown") { + if (!dropdownOpen) return; e.preventDefault(); setSelectedIndex((i) => Math.min(i + 1, suggestions.length - 1)); } else if (e.key === "ArrowUp") { + if (!dropdownOpen) return; e.preventDefault(); setSelectedIndex((i) => Math.max(i - 1, 0)); - } else if (e.key === "Enter" && suggestions[selectedIndex]) { - e.preventDefault(); - handleSelect(suggestions[selectedIndex].handle); + } else if (e.key === "Enter") { + if (dropdownOpen && suggestions[selectedIndex]) { + e.preventDefault(); + handleSelect(suggestions[selectedIndex].handle); + } else if (!dropdownOpen && handleValue) { + e.preventDefault(); + props.onSubmit?.(handleValue); + } } else if (e.key === "Escape") { setDropdownOpen(false); } @@ -90,7 +98,17 @@ export const HandleInput = (props: { onKeyDown={handleKeyDown} autoComplete="off" /> - {props.action} + {props.onSubmit ? ( + + ) : ( + props.action + )}
diff --git a/components/Subscribe/Logos.tsx b/components/Subscribe/Logos.tsx index 7ecc90af..385bcb6a 100644 --- a/components/Subscribe/Logos.tsx +++ b/components/Subscribe/Logos.tsx @@ -8,14 +8,14 @@ export const LogoLeaflet = () => { xmlns="http://www.w3.org/2000/svg" >