Something went wrong. Try again.
leaflet fork for copy edit / bug fixes forked from leaflet.pub/leaflet
Something went wrong. Try again.
8.8 kB · 273 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274"use client";import { Avatar } from "components/Avatar";import { ActionButton } from "./ActionButton";import { useIdentityData, clearIdentityData } from "components/IdentityProvider";import { AccountSmall } from "components/Icons/AccountSmall";import { useRecordFromDid } from "src/utils/useRecordFromDid";import { useIsMobile } from "src/hooks/isMobile";import { LogoutSmall } from "components/Icons/LogoutSmall";import { SpeedyLink } from "components/SpeedyLink";import { Popover } from "components/Popover";import { Modal } from "components/Modal";import { InlineUpgradeToPro, UpgradeContent,} from "app/(app)/(published)/lish/[did]/[publication]/UpgradeModal";import { ManageProSubscription } from "app/(app)/(published)/lish/[did]/[publication]/dashboard/settings/ProSettings";import { ManageDomains } from "components/Domains/ManageDomains";import { WebSmall } from "components/Icons/WebSmall";import { useIsPro, useCanSeePro, useCanSeePayments,} from "src/hooks/useEntitlement";import { useState } from "react";import { LeafletPro } from "components/Icons/LeafletPro";import { AnalyticsSmall } from "components/Icons/AnalyticsSmall";import { ConnectPayments } from "components/StripeConnect/ConnectPayments";import { useSidebarStore } from "./Sidebar";import { AccountList, SwitchAccountItem } from "./AccountSwitcher";import { LoginContent } from "components/LoginButton";import { mutateSavedAccounts, readSavedAccountEntries, removeSavedAccountEntry, switchToSavedAccount,} from "src/hooks/useSavedAccounts";
export const ProfileButton = () => { let setSidebarOpen = useSidebarStore((s) => s.setOpen); let { identity } = useIdentityData(); let { data: record } = useRecordFromDid(identity?.atp_did); let isMobile = useIsMobile(); let isPro = useIsPro(); let canSeePro = useCanSeePro(); let canSeePayments = useCanSeePayments(); let [open, setOpen] = useState(false); let [domainsOpen, setDomainsOpen] = useState(false); let [addAccountOpen, setAddAccountOpen] = useState(false); let [showAccounts, setShowAccounts] = useState(false); let [proOpen, setProOpen] = useState(false); let [upgradeOpen, setUpgradeOpen] = useState(false);
// Close the menu but leave the mobile sidebar open: this component (and the // add-account modal's state) is mounted inside the sidebar's Dialog, so // closing the sidebar would unmount the modal right as it opens. let openAddAccount = () => { setOpen(false); setShowAccounts(false); setAddAccountOpen(true); };
return ( <> <Popover asChild open={open} onOpenChange={(o) => { setOpen(o); if (!o) setShowAccounts(false); }} side={isMobile ? "top" : "right"} align={isMobile ? "center" : "start"} className="w-xs py-1! z-[60]!" trigger={ <ActionButton labelOnMobile={false} icon={ record ? ( <Avatar src={record.avatar} displayName={record.displayName || record.handle} /> ) : ( <AccountSmall /> ) } label={ record ? record.displayName || record.handle : identity?.email || "Account" } className={`font-bold`} /> } > {showAccounts ? ( <AccountList onBack={() => setShowAccounts(false)} onAddAccount={openAddAccount} /> ) : ( <div className="flex flex-col gap-0.5"> {record?.handle && ( <> <SpeedyLink className="no-underline! menuItem -mx-[8px]" href={`/p/${record.handle}`} onClick={() => { setOpen(false); }} > <button type="button" className="flex gap-2 "> <AccountSmall /> View Profile </button> </SpeedyLink> </> )}
<button type="button" className="menuItem -mx-[8px] text-left flex items-center gap-2 hover:no-underline!" onClick={() => { setOpen(false); setDomainsOpen(true); }} > <WebSmall /> Domain Settings </button> {identity && ( <SpeedyLink className="no-underline! menuItem -mx-[8px]" href="/memberships" onClick={() => { setOpen(false); }} > <button type="button" className="flex gap-2"> <AnalyticsSmall /> Memberships & Billing </button> </SpeedyLink> )} <hr className="border-border-light border-dashed" />
{canSeePro && isPro && ( <> <button type="button" className="menuItem -mx-[8px] text-left flex items-center gap-2 hover:no-underline!" onClick={() => { setOpen(false); setProOpen(true); }} > <LeafletPro /> Manage Pro Subscription </button> <hr className="border-border-light border-dashed" /> </> )} {identity && canSeePayments && ( <> <Modal trigger={ <div className="menuItem -mx-[8px] "> <AnalyticsSmall /> Payments </div> } > <div className="flex flex-col gap-3 max-w-prose"> <div className="font-bold text-primary text-lg">Payments</div> <ConnectPayments /> </div> </Modal> <hr className="border-border-light border-dashed" /> </> )} <SwitchAccountItem onShowAccounts={() => setShowAccounts(true)} onAddAccount={openAddAccount} /> <button type="button" className="menuItem -mx-[8px] text-left flex items-center gap-2 hover:no-underline!" onClick={async () => { setOpen(false); setSidebarOpen(false); let currentIdentity = identity?.id; // Logging out of this account falls through to the most recent // other saved session. Revoking the old session and installing the // next happens in one request so the open page never sits on a // cleared cookie, which flashed an error before the navigation // landed. let entries = readSavedAccountEntries(); let next = entries.find((e) => e.identity !== currentIdentity); if (next) { let ok = await switchToSavedAccount(next, { logoutCurrent: true, }); if (ok) { if (currentIdentity) removeSavedAccountEntry(currentIdentity); window.location.href = "/home"; return; } // The fallback session was revoked elsewhere — drop it and log // out normally. removeSavedAccountEntry(next.identity); } await fetch("/api/auth/logout"); if (currentIdentity) removeSavedAccountEntry(currentIdentity); mutateSavedAccounts(); clearIdentityData(); }} > <LogoutSmall /> Log Out </button> {canSeePro && !isPro && ( <> {" "} <hr className="border-border-light border-dashed" /> <div className="py-2"> <div className="p-2 accent-container"> <InlineUpgradeToPro compact onClick={() => { setOpen(false); setUpgradeOpen(true); }} /> </div> </div> </> )} </div> )} </Popover> <ManageDomains open={domainsOpen} onOpenChange={setDomainsOpen} /> <Modal open={addAccountOpen} onOpenChange={setAddAccountOpen} className="w-full!" > <LoginContent addAccount open={addAccountOpen} onSuccess={() => setAddAccountOpen(false)} /> </Modal> {canSeePro && isPro && ( <Modal className="w-md max-w-full" open={proOpen} onOpenChange={setProOpen} > <ManageProSubscription /> </Modal> )} {canSeePro && !isPro && ( <Modal className="sm:w-fit w-[90vw]" open={upgradeOpen} onOpenChange={setUpgradeOpen} > <UpgradeContent /> </Modal> )} </> );};