import { usePublicationData, useNormalizedPublicationRecord, } from "app/lish/[did]/[publication]/dashboard/PublicationSWRProvider"; import { useState } from "react"; import { pickers, SectionArrow } from "./ThemeSetter"; import { PubLeafletThemeBackgroundImage } from "lexicons/api"; import { AtUri } from "@atproto/syntax"; import { useLocalPubTheme } from "./PublicationThemeProvider"; import { BaseThemeProvider, CardBorderHiddenContext } from "./ThemeProvider"; import { blobRefToSrc } from "src/utils/blobRefToSrc"; import { updatePublicationTheme } from "app/lish/createPub/updatePublication"; import { PagePickers } from "./PubPickers/PubTextPickers"; import { BackgroundPicker } from "./PubPickers/PubBackgroundPickers"; import { PubAccentPickers } from "./PubPickers/PubAcccentPickers"; import { Separator } from "components/Layout"; import { ColorToRGB, ColorToRGBA } from "./colorToLexicons"; import { useToaster } from "components/Toast"; import { OAuthErrorMessage, isOAuthSessionError } from "components/OAuthError"; import { PubPageWidthSetter } from "./PubPickers/PubPageWidthSetter"; import { FontPicker } from "./Pickers/TextPickers"; import { GoToArrow } from "components/Icons/GoToArrow"; import { ButtonPrimary } from "components/Buttons"; import { PresetThemePicker } from "./PubPickers/PubPresetPicker"; export type ImageState = { src: string; file?: File; repeat: number | null; }; export function usePubThemeEditorState() { let [openPicker, setOpenPicker] = useState("null"); let { data, mutate } = usePublicationData(); let { publication: pub } = data || {}; let record = useNormalizedPublicationRecord(); let [showPageBackground, setShowPageBackground] = useState( !!record?.theme?.showPageBackground, ); let { theme: localPubTheme, setTheme, changes, resetChanges, } = useLocalPubTheme(record?.theme, showPageBackground); let [image, setImage] = useState( PubLeafletThemeBackgroundImage.isMain(record?.theme?.backgroundImage) ? { src: blobRefToSrc( record.theme.backgroundImage.image.ref, pub?.identity_did!, ), repeat: record.theme.backgroundImage.repeat ? record.theme.backgroundImage.width || 500 : null, } : null, ); let [pageWidth, setPageWidth] = useState( record?.theme?.pageWidth || 624, ); let [headingFont, setHeadingFont] = useState( record?.theme?.headingFont, ); let [bodyFont, setBodyFont] = useState( record?.theme?.bodyFont, ); let pubBGImage = image?.src || null; let leafletBGRepeat = image?.repeat || null; let toaster = useToaster(); let submitTheme = async (setLoading: (l: boolean) => void) => { if (!pub) return; setLoading(true); let result = await updatePublicationTheme({ uri: pub.uri, theme: { pageBackground: ColorToRGBA(localPubTheme.bgPage), showPageBackground: showPageBackground, backgroundColor: image ? ColorToRGBA(localPubTheme.bgLeaflet) : ColorToRGB(localPubTheme.bgLeaflet), backgroundRepeat: image?.repeat, backgroundImage: image ? image.file : null, pageWidth: pageWidth, primary: ColorToRGB(localPubTheme.primary), accentBackground: ColorToRGB(localPubTheme.accent1), accentText: ColorToRGB(localPubTheme.accent2), headingFont: headingFont, bodyFont: bodyFont, }, }); if (!result.success) { setLoading(false); if (result.error && isOAuthSessionError(result.error)) { toaster({ content: , type: "error", }); } else { toaster({ content: "Failed to update theme", type: "error", }); } return result; } mutate((pub) => { if (result.publication && pub?.publication) return { ...pub, publication: { ...pub.publication, ...result.publication }, }; return pub; }, false); resetChanges(); setLoading(false); return result; }; return { openPicker, setOpenPicker, pub, record, mutate, showPageBackground, setShowPageBackground, localPubTheme, setTheme, changes, resetChanges, image, setImage, pageWidth, setPageWidth, headingFont, setHeadingFont, bodyFont, setBodyFont, pubBGImage, leafletBGRepeat, toaster, submitTheme, }; } export type PubThemeEditorState = ReturnType; export function PubThemePickerPanel(props: { state: PubThemeEditorState }) { let { openPicker, setOpenPicker, showPageBackground, setShowPageBackground, localPubTheme, setTheme, image, setImage, pageWidth, setPageWidth, headingFont, setHeadingFont, bodyFont, setBodyFont, pubBGImage, leafletBGRepeat, } = props.state; return (

{ setTheme((t) => ({ ...t, bgPage: color })); }} setBackgroundColor={(color) => { setTheme((t) => ({ ...t, bgLeaflet: color })); }} openPicker={openPicker} setOpenPicker={setOpenPicker} hasPageBackground={!!showPageBackground} setHasPageBackground={setShowPageBackground} />
{ setTheme((t) => ({ ...t, bgPage: color })); }} setPrimary={(color) => { setTheme((t) => ({ ...t, primary: color })); }} openPicker={openPicker} setOpenPicker={(pickers) => setOpenPicker(pickers)} hasPageBackground={showPageBackground} />
{ setTheme((t) => ({ ...t, accent1: color })); }} accent2={localPubTheme.accent2} setAccent2={(color) => { setTheme((t) => ({ ...t, accent2: color })); }} openPicker={openPicker} setOpenPicker={(pickers) => setOpenPicker(pickers)} />
); } export const PubThemeSetter = (props: { backToMenu: () => void; loading: boolean; setLoading: (l: boolean) => void; }) => { let [sample, setSample] = useState<"pub" | "post">("pub"); let state = usePubThemeEditorState(); let { localPubTheme, headingFont, bodyFont, image, pageWidth, pubBGImage, leafletBGRepeat, pub, record, showPageBackground, submitTheme, } = state; return (
Preview
{" "}
{ await submitTheme(props.setLoading); }} > {props.loading ? "Saving..." : "Save Theme"}
); };