diff --git a/app/lish/[did]/[publication]/[rkey]/PostSubscribe.tsx b/app/lish/[did]/[publication]/[rkey]/PostSubscribe.tsx
index 90b3a8ac..6ffcd0be 100644
--- a/app/lish/[did]/[publication]/[rkey]/PostSubscribe.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/PostSubscribe.tsx
@@ -1,15 +1,15 @@
"use client";
-import { useContext } from "react";
-import { PostPageContext } from "./PostPageContext";
+import { useDocumentOptional } from "contexts/DocumentContext";
import { useIdentityData } from "components/IdentityProvider";
import { SubscribeWithBluesky } from "app/lish/Subscribe";
import { getPublicationURL } from "app/lish/createPub/getPublicationURL";
export const PostSubscribe = () => {
- const data = useContext(PostPageContext);
+ const data = useDocumentOptional();
let { identity } = useIdentityData();
- let publication = data?.documents_in_publications[0]?.publications;
+ let publication = data?.publication;
+ let normalizedPublication = data?.normalizedPublication;
let subscribed =
identity?.atp_did &&
@@ -20,11 +20,10 @@ export const PostSubscribe = () => {
let isAuthor =
identity &&
- identity.atp_did ===
- data?.documents_in_publications[0]?.publications?.identity_did &&
- data?.leaflets_in_publications[0];
+ identity.atp_did === publication?.identity_did &&
+ data?.leafletId;
- if (!subscribed && !isAuthor && publication && publication.record)
+ if (!subscribed && !isAuthor && publication && normalizedPublication)
return (
@@ -41,5 +40,5 @@ export const PostSubscribe = () => {
);
- else return;
+ else return null;
};
diff --git a/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx b/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx
index beb835e3..7918ab2d 100644
--- a/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/QuoteHandler.tsx
@@ -3,7 +3,7 @@ import { BlueskyLinkTiny } from "components/Icons/BlueskyLinkTiny";
import { CopyTiny } from "components/Icons/CopyTiny";
import { Separator } from "components/Layout";
import { useSmoker } from "components/Toast";
-import { useEffect, useMemo, useState, useContext } from "react";
+import { useEffect, useMemo, useState } from "react";
import {
encodeQuotePosition,
decodeQuotePosition,
@@ -12,8 +12,7 @@ import {
import { useIdentityData } from "components/IdentityProvider";
import { CommentTiny } from "components/Icons/CommentTiny";
import { setInteractionState } from "./Interactions/Interactions";
-import { PostPageContext } from "./PostPageContext";
-import { PubLeafletPublication } from "lexicons/api";
+import { useDocument } from "contexts/DocumentContext";
import { flushSync } from "react-dom";
import { scrollIntoView } from "src/utils/scrollIntoView";
@@ -148,10 +147,7 @@ export function QuoteHandler() {
export const QuoteOptionButtons = (props: { position: string }) => {
let smoker = useSmoker();
let { identity } = useIdentityData();
- const data = useContext(PostPageContext);
- const document_uri = data?.uri;
- if (!document_uri)
- throw new Error("document_uri not available in PostPageContext");
+ const { uri: document_uri, publication } = useDocument();
let [url, position] = useMemo(() => {
let currentUrl = new URL(window.location.href);
let pos = decodeQuotePosition(props.position);
@@ -169,9 +165,7 @@ export const QuoteOptionButtons = (props: { position: string }) => {
currentUrl.hash = `#${fragmentId}`;
return [currentUrl.toString(), pos];
}, [props.position]);
- let pubRecord = data.documents_in_publications[0]?.publications?.record as
- | PubLeafletPublication.Record
- | undefined;
+ let pubRecord = publication?.record;
return (
<>
diff --git a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts
index aa0cc515..9f7f44a2 100644
--- a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts
+++ b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts
@@ -1,9 +1,16 @@
import { supabaseServerClient } from "supabase/serverClient";
import { AtUri } from "@atproto/syntax";
-import { PubLeafletDocument, PubLeafletPublication } from "lexicons/api";
-
-export async function getPostPageData(uri: string) {
- let { data: document } = await supabaseServerClient
+import {
+ normalizeDocumentRecord,
+ normalizePublicationRecord,
+ type NormalizedDocument,
+ type NormalizedPublication,
+} from "src/utils/normalizeRecords";
+import { PubLeafletPublication, SiteStandardPublication } from "lexicons/api";
+import { documentUriFilter } from "src/utils/uriHelpers";
+
+export async function getPostPageData(did: string, rkey: string) {
+ let { data: documents } = await supabaseServerClient
.from("documents")
.select(
`
@@ -18,17 +25,26 @@ export async function getPostPageData(uri: string) {
leaflets_in_publications(*)
`,
)
- .eq("uri", uri)
- .single();
+ .or(documentUriFilter(did, rkey))
+ .order("uri", { ascending: false })
+ .limit(1);
+ let document = documents?.[0];
if (!document) return null;
+ // Normalize the document record - this is the primary way consumers should access document data
+ const normalizedDocument = normalizeDocumentRecord(document.data, document.uri);
+ if (!normalizedDocument) return null;
+
+ // Normalize the publication record - this is the primary way consumers should access publication data
+ const normalizedPublication = normalizePublicationRecord(
+ document.documents_in_publications[0]?.publications?.record
+ );
+
// Fetch constellation backlinks for mentions
- const pubRecord = document.documents_in_publications[0]?.publications
- ?.record as PubLeafletPublication.Record;
- let aturi = new AtUri(uri);
- const postUrl = pubRecord
- ? `https://${pubRecord?.base_path}/${aturi.rkey}`
+ let aturi = new AtUri(document.uri);
+ const postUrl = normalizedPublication
+ ? `${normalizedPublication.url}/${aturi.rkey}`
: `https://leaflet.pub/p/${aturi.host}/${aturi.rkey}`;
const constellationBacklinks = await getConstellationBacklinks(postUrl);
@@ -48,11 +64,7 @@ export async function getPostPageData(uri: string) {
...uniqueBacklinks,
];
- let theme =
- (
- document?.documents_in_publications[0]?.publications
- ?.record as PubLeafletPublication.Record
- )?.theme || (document?.data as PubLeafletDocument.Record)?.theme;
+ let theme = normalizedPublication?.theme || normalizedDocument?.theme;
// Calculate prev/next documents from the fetched publication documents
let prevNext:
@@ -62,8 +74,7 @@ export async function getPostPageData(uri: string) {
}
| undefined;
- const currentPublishedAt = (document.data as PubLeafletDocument.Record)
- ?.publishedAt;
+ const currentPublishedAt = normalizedDocument.publishedAt;
const allDocs =
document.documents_in_publications[0]?.publications
?.documents_in_publications;
@@ -71,13 +82,15 @@ export async function getPostPageData(uri: string) {
if (currentPublishedAt && allDocs) {
// Filter and sort documents by publishedAt
const sortedDocs = allDocs
- .map((dip) => ({
- uri: dip?.documents?.uri,
- title: (dip?.documents?.data as PubLeafletDocument.Record).title,
- publishedAt: (dip?.documents?.data as PubLeafletDocument.Record)
- .publishedAt,
- }))
- .filter((doc) => doc.publishedAt) // Only include docs with publishedAt
+ .map((dip) => {
+ const normalizedData = normalizeDocumentRecord(dip?.documents?.data, dip?.documents?.uri);
+ return {
+ uri: dip?.documents?.uri,
+ title: normalizedData?.title,
+ publishedAt: normalizedData?.publishedAt,
+ };
+ })
+ .filter((doc) => doc.publishedAt && doc.title) // Only include docs with publishedAt and valid data
.sort(
(a, b) =>
new Date(a.publishedAt!).getTime() -
@@ -85,7 +98,7 @@ export async function getPostPageData(uri: string) {
);
// Find current document index
- const currentIndex = sortedDocs.findIndex((doc) => doc.uri === uri);
+ const currentIndex = sortedDocs.findIndex((doc) => doc.uri === document.uri);
if (currentIndex !== -1) {
prevNext = {
@@ -93,25 +106,43 @@ export async function getPostPageData(uri: string) {
currentIndex > 0
? {
uri: sortedDocs[currentIndex - 1].uri || "",
- title: sortedDocs[currentIndex - 1].title,
+ title: sortedDocs[currentIndex - 1].title || "",
}
: undefined,
next:
currentIndex < sortedDocs.length - 1
? {
uri: sortedDocs[currentIndex + 1].uri || "",
- title: sortedDocs[currentIndex + 1].title,
+ title: sortedDocs[currentIndex + 1].title || "",
}
: undefined,
};
}
}
+ // Build explicit publication context for consumers
+ const rawPub = document.documents_in_publications[0]?.publications;
+ const publication = rawPub ? {
+ uri: rawPub.uri,
+ name: rawPub.name,
+ identity_did: rawPub.identity_did,
+ record: rawPub.record as PubLeafletPublication.Record | SiteStandardPublication.Record | null,
+ publication_subscriptions: rawPub.publication_subscriptions || [],
+ } : null;
+
return {
...document,
+ // Pre-normalized data - consumers should use these instead of normalizing themselves
+ normalizedDocument,
+ normalizedPublication,
quotesAndMentions,
theme,
prevNext,
+ // Explicit relational data for DocumentContext
+ publication,
+ comments: document.comments_on_documents,
+ mentions: document.document_mentions_in_bsky,
+ leafletId: document.leaflets_in_publications[0]?.leaflet || null,
};
}
diff --git a/app/lish/[did]/[publication]/[rkey]/opengraph-image.ts b/app/lish/[did]/[publication]/[rkey]/opengraph-image.ts
index d58a9993..2ba3e011 100644
--- a/app/lish/[did]/[publication]/[rkey]/opengraph-image.ts
+++ b/app/lish/[did]/[publication]/[rkey]/opengraph-image.ts
@@ -1,10 +1,9 @@
import { getMicroLinkOgImage } from "src/utils/getMicroLinkOgImage";
import { supabaseServerClient } from "supabase/serverClient";
-import { AtUri } from "@atproto/syntax";
-import { ids } from "lexicons/api/lexicons";
-import { PubLeafletDocument } from "lexicons/api";
import { jsonToLex } from "@atproto/lexicon";
import { fetchAtprotoBlob } from "app/api/atproto_images/route";
+import { normalizeDocumentRecord } from "src/utils/normalizeRecords";
+import { documentUriFilter } from "src/utils/uriHelpers";
export const revalidate = 60;
@@ -15,15 +14,17 @@ export default async function OpenGraphImage(props: {
let did = decodeURIComponent(params.did);
// Try to get the document's cover image
- let { data: document } = await supabaseServerClient
+ let { data: documents } = await supabaseServerClient
.from("documents")
.select("data")
- .eq("uri", AtUri.make(did, ids.PubLeafletDocument, params.rkey).toString())
- .single();
+ .or(documentUriFilter(did, params.rkey))
+ .order("uri", { ascending: false })
+ .limit(1);
+ let document = documents?.[0];
if (document) {
- let docRecord = jsonToLex(document.data) as PubLeafletDocument.Record;
- if (docRecord.coverImage) {
+ const docRecord = normalizeDocumentRecord(jsonToLex(document.data));
+ if (docRecord?.coverImage) {
try {
// Get CID from the blob ref (handle both serialized and hydrated forms)
let cid =
diff --git a/app/lish/[did]/[publication]/[rkey]/page.tsx b/app/lish/[did]/[publication]/[rkey]/page.tsx
index bf1ea7e8..6bab19df 100644
--- a/app/lish/[did]/[publication]/[rkey]/page.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/page.tsx
@@ -1,9 +1,8 @@
import { supabaseServerClient } from "supabase/serverClient";
-import { AtUri } from "@atproto/syntax";
-import { ids } from "lexicons/api/lexicons";
-import { PubLeafletDocument } from "lexicons/api";
import { Metadata } from "next";
import { DocumentPageRenderer } from "./DocumentPageRenderer";
+import { normalizeDocumentRecord } from "src/utils/normalizeRecords";
+import { documentUriFilter } from "src/utils/uriHelpers";
export async function generateMetadata(props: {
params: Promise<{ publication: string; did: string; rkey: string }>;
@@ -12,16 +11,19 @@ export async function generateMetadata(props: {
let did = decodeURIComponent(params.did);
if (!did) return { title: "Publication 404" };
- let [{ data: document }] = await Promise.all([
+ let [{ data: documents }] = await Promise.all([
supabaseServerClient
.from("documents")
.select("*, documents_in_publications(publications(*))")
- .eq("uri", AtUri.make(did, ids.PubLeafletDocument, params.rkey))
- .single(),
+ .or(documentUriFilter(did, params.rkey))
+ .order("uri", { ascending: false })
+ .limit(1),
]);
+ let document = documents?.[0];
if (!document) return { title: "404" };
- let docRecord = document.data as PubLeafletDocument.Record;
+ const docRecord = normalizeDocumentRecord(document.data);
+ if (!docRecord) return { title: "404" };
return {
icons: {
diff --git a/app/lish/[did]/[publication]/[rkey]/useHighlight.tsx b/app/lish/[did]/[publication]/[rkey]/useHighlight.tsx
index ee045aa6..7ccee1ea 100644
--- a/app/lish/[did]/[publication]/[rkey]/useHighlight.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/useHighlight.tsx
@@ -2,8 +2,6 @@
"use client";
import { useParams } from "next/navigation";
-import { useContext } from "react";
-import { PostPageContext } from "./PostPageContext";
import { create } from "zustand";
import { decodeQuotePosition, QuotePosition } from "./quotePosition";
@@ -12,7 +10,6 @@ export const useActiveHighlightState = create(() => ({
}));
export const useHighlight = (pos: number[], pageId?: string) => {
- let doc = useContext(PostPageContext);
let { quote } = useParams();
let activeHighlight = useActiveHighlightState(
(state) => state.activeHighlight,
diff --git a/app/lish/[did]/[publication]/dashboard/DraftList.tsx b/app/lish/[did]/[publication]/dashboard/DraftList.tsx
index 998efcbd..5ef24543 100644
--- a/app/lish/[did]/[publication]/dashboard/DraftList.tsx
+++ b/app/lish/[did]/[publication]/dashboard/DraftList.tsx
@@ -2,7 +2,10 @@
import { NewDraftSecondaryButton } from "./NewDraftButton";
import React from "react";
-import { usePublicationData } from "./PublicationSWRProvider";
+import {
+ usePublicationData,
+ useNormalizedPublicationRecord,
+} from "./PublicationSWRProvider";
import { LeafletList } from "app/(home-pages)/home/HomeLayout";
export function DraftList(props: {
@@ -10,8 +13,14 @@ export function DraftList(props: {
showPageBackground: boolean;
}) {
let { data: pub_data } = usePublicationData();
+ // Normalize the publication record - skip rendering if unrecognized format
+ const normalizedPubRecord = useNormalizedPublicationRecord();
if (!pub_data?.publication) return null;
- let { leaflets_in_publications, ...publication } = pub_data.publication;
+ const { drafts, leaflet_data } = pub_data;
+ const { leaflets_in_publications, ...publication } = pub_data.publication;
+
+ if (!normalizedPubRecord) return null;
+
return (
!l.documents)
- .filter((l) => !l.archived)
- .map((l) => {
- return {
- archived: l.archived,
- added_at: "",
- token: {
- ...l.permission_tokens!,
- leaflets_in_publications: [
- {
- ...l,
- publications: {
- ...publication,
- },
- },
- ],
- },
- };
- })}
- initialFacts={pub_data.leaflet_data.facts || {}}
+ leaflets={drafts
+ .filter((d) => d.permission_tokens)
+ .map((d) => ({
+ archived: (d._raw as { archived?: boolean }).archived,
+ added_at: "",
+ token: {
+ ...d.permission_tokens!,
+ leaflets_in_publications: [
+ {
+ ...d._raw,
+ publications: publication,
+ },
+ ],
+ },
+ }))}
+ initialFacts={leaflet_data.facts || {}}
titles={{
- ...leaflets_in_publications.reduce(
- (acc, leaflet) => {
- if (leaflet.permission_tokens)
- acc[leaflet.permission_tokens.root_entity] =
- leaflet.title || "Untitled";
+ ...drafts.reduce(
+ (acc, draft) => {
+ if (draft.permission_tokens)
+ acc[draft.permission_tokens.root_entity] =
+ draft.title || "Untitled";
return acc;
},
{} as { [l: string]: string },
diff --git a/app/lish/[did]/[publication]/dashboard/PublicationDashboard.tsx b/app/lish/[did]/[publication]/dashboard/PublicationDashboard.tsx
index 28aecd87..184f4e25 100644
--- a/app/lish/[did]/[publication]/dashboard/PublicationDashboard.tsx
+++ b/app/lish/[did]/[publication]/dashboard/PublicationDashboard.tsx
@@ -5,21 +5,19 @@ import { GetPublicationDataReturnType } from "app/api/rpc/[command]/get_publicat
import { Actions } from "./Actions";
import React, { useState } from "react";
import { PublishedPostsList } from "./PublishedPostsLists";
-import { PubLeafletPublication } from "lexicons/api";
import { PublicationSubscribers } from "./PublicationSubscribers";
-import { AtUri } from "@atproto/syntax";
import {
- HomeDashboardControls,
DashboardLayout,
PublicationDashboardControls,
} from "components/PageLayouts/DashboardLayout";
import { useDebouncedEffect } from "src/hooks/useDebouncedEffect";
+import { type NormalizedPublication } from "src/utils/normalizeRecords";
export default function PublicationDashboard({
publication,
record,
}: {
- record: PubLeafletPublication.Record;
+ record: NormalizedPublication;
publication: Exclude<
GetPublicationDataReturnType["result"]["publication"],
null
diff --git a/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx b/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx
index 96f51b9c..4ba0fd87 100644
--- a/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx
+++ b/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx
@@ -2,11 +2,18 @@
import type { GetPublicationDataReturnType } from "app/api/rpc/[command]/get_publication_data";
import { callRPC } from "app/api/rpc/client";
-import { createContext, useContext, useEffect } from "react";
+import { createContext, useContext, useEffect, useMemo } from "react";
import useSWR, { SWRConfig, KeyedMutator, mutate } from "swr";
-import { produce, Draft } from "immer";
+import { produce, Draft as ImmerDraft } from "immer";
+import {
+ normalizePublicationRecord,
+ type NormalizedPublication,
+} from "src/utils/normalizeRecords";
+// Derive all types from the RPC return type
export type PublicationData = GetPublicationDataReturnType["result"];
+export type PublishedDocument = NonNullable["documents"][number];
+export type PublicationDraft = NonNullable["drafts"][number];
const PublicationContext = createContext({ name: "", did: "" });
export function PublicationSWRDataProvider(props: {
@@ -49,9 +56,21 @@ export function usePublicationData() {
return { data, mutate };
}
+/**
+ * Returns the normalized publication record from the publication data.
+ * Use this instead of manually calling normalizePublicationRecord on data.publication.record
+ */
+export function useNormalizedPublicationRecord(): NormalizedPublication | null {
+ const { data } = usePublicationData();
+ return useMemo(
+ () => normalizePublicationRecord(data?.publication?.record),
+ [data?.publication?.record]
+ );
+}
+
export function mutatePublicationData(
mutate: KeyedMutator,
- recipe: (draft: Draft>) => void,
+ recipe: (draft: ImmerDraft>) => void,
) {
mutate(
(data) => {
diff --git a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx
index 29929a5b..69f9735f 100644
--- a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx
+++ b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx
@@ -1,22 +1,16 @@
"use client";
import { AtUri } from "@atproto/syntax";
-import { PubLeafletDocument, PubLeafletPublication } from "lexicons/api";
import { EditTiny } from "components/Icons/EditTiny";
-import { usePublicationData } from "./PublicationSWRProvider";
-import { Fragment, useState } from "react";
+import {
+ usePublicationData,
+ useNormalizedPublicationRecord,
+ type PublishedDocument,
+} from "./PublicationSWRProvider";
+import { Fragment } from "react";
import { useParams } from "next/navigation";
import { getPublicationURL } from "app/lish/createPub/getPublicationURL";
-import { Menu, MenuItem } from "components/Menu";
-import { deletePost } from "./deletePost";
-import { ButtonPrimary } from "components/Buttons";
-import { MoreOptionsVerticalTiny } from "components/Icons/MoreOptionsVerticalTiny";
-import { DeleteSmall } from "components/Icons/DeleteSmall";
-import { ShareSmall } from "components/Icons/ShareSmall";
-import { ShareButton } from "app/[leaflet_id]/actions/ShareOptions";
import { SpeedyLink } from "components/SpeedyLink";
-import { QuoteTiny } from "components/Icons/QuoteTiny";
-import { CommentTiny } from "components/Icons/CommentTiny";
import { InteractionPreview } from "components/InteractionsPreview";
import { useLocalizedDate } from "src/hooks/useLocalizedDate";
import { LeafletOptions } from "app/(home-pages)/home/LeafletList/LeafletOptions";
@@ -27,136 +21,136 @@ export function PublishedPostsList(props: {
showPageBackground: boolean;
}) {
let { data } = usePublicationData();
- let params = useParams();
- let { publication } = data!;
- let pubRecord = publication?.record as PubLeafletPublication.Record;
+ let { publication, documents } = data || {};
+ const pubRecord = useNormalizedPublicationRecord();
if (!publication) return null;
- if (publication.documents_in_publications.length === 0)
+ if (!documents || documents.length === 0)
return (
Nothing's been published yet...
);
+
+ // Sort by publishedAt (most recent first)
+ const sortedDocuments = [...documents].sort((a, b) => {
+ const aDate = a.record.publishedAt
+ ? new Date(a.record.publishedAt)
+ : new Date(0);
+ const bDate = b.record.publishedAt
+ ? new Date(b.record.publishedAt)
+ : new Date(0);
+ return bDate.getTime() - aDate.getTime();
+ });
+
return (
- {publication.documents_in_publications
- .sort((a, b) => {
- let aRecord = a.documents?.data! as PubLeafletDocument.Record;
- let bRecord = b.documents?.data! as PubLeafletDocument.Record;
- const aDate = aRecord.publishedAt
- ? new Date(aRecord.publishedAt)
- : new Date(0);
- const bDate = bRecord.publishedAt
- ? new Date(bRecord.publishedAt)
- : new Date(0);
- return bDate.getTime() - aDate.getTime(); // Sort by most recent first
- })
- .map((doc) => {
- if (!doc.documents) return null;
- let leaflet = publication.leaflets_in_publications.find(
- (l) => doc.documents && l.doc === doc.documents.uri,
- );
- let uri = new AtUri(doc.documents.uri);
- let postRecord = doc.documents.data as PubLeafletDocument.Record;
- let quotes = doc.documents.document_mentions_in_bsky[0]?.count || 0;
- let comments = doc.documents.comments_on_documents[0]?.count || 0;
- let tags = (postRecord?.tags as string[] | undefined) || [];
-
- let postLink = data?.publication
- ? `${getPublicationURL(data?.publication)}/${new AtUri(doc.documents.uri).rkey}`
- : "";
+ {sortedDocuments.map((doc) => (
+
+ ))}
+
+ );
+}
- return (
-
-
-
-
-
-
- {postRecord.title}
-
-
-
- {leaflet && leaflet.permission_tokens && (
- <>
-
-
-
+function PublishedPostItem(props: {
+ doc: PublishedDocument;
+ publication: NonNullable["data"]>["publication"]>;
+ pubRecord: ReturnType;
+ showPageBackground: boolean;
+}) {
+ const { doc, publication, pubRecord, showPageBackground } = props;
+ const uri = new AtUri(doc.uri);
+ const leaflet = publication.leaflets_in_publications.find(
+ (l) => l.doc === doc.uri,
+ );
-
-
-
- >
- )}
-
-
+ return (
+
+
+
+
+
+
+ {doc.record.title}
+
+
+
+ {leaflet && leaflet.permission_tokens && (
+ <>
+
+
+
- {postRecord.description ? (
-
- {postRecord.description}
-
- ) : null}
-
- {postRecord.publishedAt ? (
-
- ) : null}
-
-
-
-
- {!props.showPageBackground && (
-
+
+
+
+ >
)}
-
- );
- })}
-
+
+
+
+ {doc.record.description ? (
+
+ {doc.record.description}
+
+ ) : null}
+
+ {doc.record.publishedAt ? (
+
+ ) : null}
+
+
+
+
+ {!showPageBackground && (
+
+ )}
+
);
}
diff --git a/app/lish/[did]/[publication]/dashboard/deletePost.ts b/app/lish/[did]/[publication]/dashboard/deletePost.ts
index 32b10eba..a976f12f 100644
--- a/app/lish/[did]/[publication]/dashboard/deletePost.ts
+++ b/app/lish/[did]/[publication]/dashboard/deletePost.ts
@@ -39,10 +39,15 @@ export async function deletePost(
}
await Promise.all([
+ // Delete from both PDS collections (document exists in one or the other)
agent.pub.leaflet.document.delete({
repo: credentialSession.did,
rkey: uri.rkey,
- }),
+ }).catch(() => {}),
+ agent.site.standard.document.delete({
+ repo: credentialSession.did,
+ rkey: uri.rkey,
+ }).catch(() => {}),
supabaseServerClient.from("documents").delete().eq("uri", document_uri),
supabaseServerClient
.from("leaflets_in_publications")
@@ -83,10 +88,15 @@ export async function unpublishPost(
}
await Promise.all([
+ // Delete from both PDS collections (document exists in one or the other)
agent.pub.leaflet.document.delete({
repo: credentialSession.did,
rkey: uri.rkey,
- }),
+ }).catch(() => {}),
+ agent.site.standard.document.delete({
+ repo: credentialSession.did,
+ rkey: uri.rkey,
+ }).catch(() => {}),
supabaseServerClient.from("documents").delete().eq("uri", document_uri),
]);
revalidatePath("/lish/[did]/[publication]/dashboard", "layout");
diff --git a/app/lish/[did]/[publication]/dashboard/page.tsx b/app/lish/[did]/[publication]/dashboard/page.tsx
index d124fe8e..6dfd25bb 100644
--- a/app/lish/[did]/[publication]/dashboard/page.tsx
+++ b/app/lish/[did]/[publication]/dashboard/page.tsx
@@ -3,12 +3,11 @@ import { Metadata } from "next";
import { getIdentityData } from "actions/getIdentityData";
import { get_publication_data } from "app/api/rpc/[command]/get_publication_data";
import { PublicationSWRDataProvider } from "./PublicationSWRProvider";
-import { PubLeafletPublication } from "lexicons/api";
import { PublicationThemeProviderDashboard } from "components/ThemeManager/PublicationThemeProvider";
import { AtUri } from "@atproto/syntax";
import { NotFoundLayout } from "components/PageLayouts/NotFoundLayout";
import PublicationDashboard from "./PublicationDashboard";
-import Link from "next/link";
+import { normalizePublicationRecord } from "src/utils/normalizeRecords";
export async function generateMetadata(props: {
params: Promise<{ publication: string; did: string }>;
@@ -24,8 +23,7 @@ export async function generateMetadata(props: {
{ supabase: supabaseServerClient },
);
let { publication } = publication_data;
- let record =
- (publication?.record as PubLeafletPublication.Record) || undefined;
+ const record = normalizePublicationRecord(publication?.record);
if (!publication) return { title: "404 Publication" };
return { title: record?.name || "Untitled Publication" };
}
@@ -56,7 +54,7 @@ export default async function Publication(props: {
{ supabase: supabaseServerClient },
);
let { publication, leaflet_data } = publication_data;
- let record = publication?.record as PubLeafletPublication.Record | null;
+ const record = normalizePublicationRecord(publication?.record);
if (!publication || identity.atp_did !== publication.identity_did || !record)
return
;
diff --git a/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
index d3991fc7..076568ef 100644
--- a/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
+++ b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
@@ -1,5 +1,7 @@
-import { PubLeafletPublication } from "lexicons/api";
-import { usePublicationData } from "../PublicationSWRProvider";
+import {
+ usePublicationData,
+ useNormalizedPublicationRecord,
+} from "../PublicationSWRProvider";
import { PubSettingsHeader } from "./PublicationSettings";
import { useState } from "react";
import { Toggle } from "components/Toggle";
@@ -15,7 +17,7 @@ export const PostOptions = (props: {
let { data } = usePublicationData();
let { publication: pubData } = data || {};
- let record = pubData?.record as PubLeafletPublication.Record;
+ const record = useNormalizedPublicationRecord();
let [showComments, setShowComments] = useState(
record?.preferences?.showComments === undefined
@@ -37,7 +39,7 @@ export const PostOptions = (props: {
return (