diff --git a/components/Icons/EmailTiny.tsx b/components/Icons/EmailTiny.tsx
new file mode 100644
index 00000000..b6f448f7
--- /dev/null
+++ b/components/Icons/EmailTiny.tsx
@@ -0,0 +1,20 @@
+import { Props } from "./Props";
+export const EmailTiny = (props: Props) => {
+ return (
+
+ );
+};
diff --git a/components/Subscribe/EmailSubscribe.tsx b/components/Subscribe/EmailSubscribe.tsx
index 5eeedbcd..8fb9fa08 100644
--- a/components/Subscribe/EmailSubscribe.tsx
+++ b/components/Subscribe/EmailSubscribe.tsx
@@ -7,6 +7,7 @@ import { theme } from "tailwind.config";
export const EmailInput = (props: {
action: React.ReactNode;
+ leading?: React.ReactNode;
autoFocus?: boolean;
large?: boolean;
value: string;
@@ -29,6 +30,11 @@ export const EmailInput = (props: {
}
}
>
+ {props.leading && (
+
+ {props.leading}
+
+ )}
void;
+ onAtSuccess?: () => void;
+ leading?: React.ReactNode;
user: {
loggedIn: boolean;
email: string | undefined;
@@ -78,50 +80,57 @@ export const SubscribeWithHandle = (props: {
if (props.user.loggedIn && props.user.handle) {
return (
-
{
- if (subscribing) return;
- setSubscribing(true);
- setOauthError(null);
- let url = new URL(window.location.href);
- url.searchParams.set("refreshAuth", "");
- let result = await subscribeToPublication(
- props.publicationUri,
- url.toString(),
- );
- if (!result.success) {
- if (isOAuthSessionError(result.error))
- setOauthError(result.error);
+
+ {props.leading}
+
{
+ if (subscribing) return;
+ setSubscribing(true);
+ setOauthError(null);
+ let url = new URL(window.location.href);
+ url.searchParams.set("refreshAuth", "");
+ let result = await subscribeToPublication(
+ props.publicationUri,
+ url.toString(),
+ );
+ if (!result.success) {
+ if (isOAuthSessionError(result.error))
+ setOauthError(result.error);
+ setSubscribing(false);
+ return;
+ }
+ if (props.onAtSuccess) {
+ props.onAtSuccess();
+ } else {
+ toaster({
+ content: You're Subscribed!
,
+ type: "success",
+ });
+ }
+ props.onSubscribed?.();
setSubscribing(false);
- return;
- }
- toaster({
- content: You're Subscribed!
,
- type: "success",
- });
- props.onSubscribed?.();
- setSubscribing(false);
- }}
- >
- {subscribing ? (
-
- ) : (
- <>
- Subscribe as
-
-
+ }}
+ >
+ {subscribing ? (
+
+ ) : (
+ <>
+ Subscribe as
+
+
- {props.user.handle}
-
- >
- )}
-
+
{props.user.handle}
+
+ >
+ )}
+
+
{oauthError && (
{
let trimmed = handle.trim();
if (!trimmed) return;
diff --git a/components/Subscribe/SubscribeButton.tsx b/components/Subscribe/SubscribeButton.tsx
index f4c5bfce..52df92f4 100644
--- a/components/Subscribe/SubscribeButton.tsx
+++ b/components/Subscribe/SubscribeButton.tsx
@@ -1,7 +1,7 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
-import { SubscribeWithHandle } from "./HandleSubscribe";
+import { SubscribeWithHandle, AtSubscribeSuccess } from "./HandleSubscribe";
import { EmailInput, EmailConfirm } from "./EmailSubscribe";
import { EmailSubscribeSuccess } from "./EmailSubscribeSuccess";
import { LinkIdentityModal } from "./LinkIdentityModal";
@@ -10,6 +10,9 @@ import { ButtonPrimary } from "components/Buttons";
import { ManageSubscription } from "./ManageSubscribe";
import { useToaster } from "components/Toast";
import { useIdentityData } from "components/IdentityProvider";
+import { AtmosphereAccount } from "components/Icons/AtmosphereAccount";
+import { EmailTiny } from "components/Icons/EmailTiny";
+import { Menu, RadioMenuGroup, RadioMenuItem } from "components/Menu";
import {
requestPublicationEmailSubscription,
confirmPublicationEmailSubscription,
@@ -17,6 +20,8 @@ import {
import { useViewerSubscription } from "./viewerSubscription";
+type SubscribeMode = "email" | "atproto";
+
export type SubscribeProps = {
autoFocus?: boolean;
publicationUri: string;
@@ -78,7 +83,7 @@ export const SubscribeInput = (props: SubscribeProps) => {
let toaster = useToaster();
let router = useRouter();
const user = useViewerSubscription(props.publicationUri);
- const { identity } = useIdentityData();
+ const { identity, mutate: mutateIdentity } = useIdentityData();
let [email, setEmail] = useState(user.email ?? "");
let [confirmState, setConfirmState] = useState<"confirm" | "success">(
"confirm",
@@ -88,6 +93,8 @@ export const SubscribeInput = (props: SubscribeProps) => {
let [confirming, setConfirming] = useState(false);
let [locallySubscribed, setLocallySubscribed] = useState(false);
let [linkModalOpen, setLinkModalOpen] = useState(false);
+ let [subscribeMode, setSubscribeMode] = useState("email");
+ let [atSuccessOpen, setAtSuccessOpen] = useState(false);
// Tracks that the user passed through LinkIdentityModal — when they enter
// the confirmation code we attach the email to their current atp identity
// (or merge from any existing email-only identity) instead of creating a
@@ -125,6 +132,9 @@ export const SubscribeInput = (props: SubscribeProps) => {
? user.emailSubscribed
: user.atprotoSubscribed;
const isSubscribed = showManage || locallySubscribed;
+ const modeMenu = (
+
+ );
return (
<>
@@ -180,30 +190,40 @@ export const SubscribeInput = (props: SubscribeProps) => {
>
) : props.newsletterMode ? (
- {
- if (requesting) return;
- if (needsLinkConfirmation) {
- setLinkModalOpen(true);
- return;
- }
- await sendRequest(false);
- }}
- >
- Subscribe
-
- }
- />
+ {subscribeMode === "email" ? (
+ {
+ if (!email || requesting) return;
+ if (needsLinkConfirmation) {
+ setLinkModalOpen(true);
+ return;
+ }
+ await sendRequest(false);
+ }}
+ >
+ Subscribe
+
+ }
+ />
+ ) : (
+ setAtSuccessOpen(true)}
+ leading={modeMenu}
+ />
+ )}
) : (
{
/>
)}
{props.newsletterMode && (
- {
- setConfirmOpen(open);
- if (!open) {
- if (confirmState === "success") setLocallySubscribed(true);
- setConfirmState("confirm");
- setLinkToCurrent(false);
- }
- }}
- >
- {confirmState === "success" ? (
+ <>
+ {
+ setAtSuccessOpen(open);
+ if (!open) {
+ setLocallySubscribed(true);
+ mutateIdentity();
+ router.refresh();
+ }
+ }}
+ >
+
+
+ {
+ setConfirmOpen(open);
+ if (!open) {
+ if (confirmState === "success") setLocallySubscribed(true);
+ setConfirmState("confirm");
+ setLinkToCurrent(false);
+ }
+ }}
+ >
+ {confirmState === "success" ? (
) : (
{
}}
/>
)}
-
+
+ >
)}
>
);
};
+const SubscribeModeMenu = (props: {
+ mode: SubscribeMode;
+ onChange: (mode: SubscribeMode) => void;
+}) => {
+ return (
+
+ );
+};
+
type SubscribeError =
| "invalid_email"
| "newsletter_disabled"