From bd63206790ebe7397ee53d2596234dfd466481c0 Mon Sep 17 00:00:00 2001
From: celine
Date: Wed, 28 Jan 2026 19:41:09 -0500
Subject: [PATCH] add user preference to show/hide recommends
---
.claude/settings.local.json | 3 +-
.../[did]/[publication]/[rkey]/CanvasPage.tsx | 2 +
.../[rkey]/Interactions/Interactions.tsx | 30 +-
.../[rkey]/LinearDocumentPage.tsx | 1 +
.../[rkey]/PostHeader/PostHeader.tsx | 7 +-
.../[did]/[publication]/[rkey]/PostPages.tsx | 2 +
.../dashboard/PublishedPostsLists.tsx | 1 +
.../dashboard/settings/PostOptions.tsx | 22 +-
app/lish/[did]/[publication]/page.tsx | 3 +
app/lish/createPub/CreatePubForm.tsx | 1 +
app/lish/createPub/UpdatePubForm.tsx | 3 +-
app/lish/createPub/createPublication.ts | 32 ++-
app/lish/createPub/updatePublication.ts | 265 +++++++++++-------
components/InteractionsPreview.tsx | 14 +-
components/PostListing.tsx | 3 +
lexicons/api/types/pub/leaflet/publication.ts | 83 +++---
.../api/types/site/standard/publication.ts | 61 ++--
lexicons/pub/leaflet/publication.json | 4 +
lexicons/site/standard/publication.json | 4 +
lexicons/src/normalize.ts | 27 +-
lexicons/src/publication.ts | 1 +
21 files changed, 363 insertions(+), 206 deletions(-)
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 457d562b..9371392c 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -8,7 +8,8 @@
"mcp__primitive__pending_delegations",
"mcp__primitive__claim_delegation",
"mcp__primitive__tasks_update",
- "mcp__primitive__contexts_update"
+ "mcp__primitive__contexts_update",
+ "mcp__primitive__contexts_list"
]
}
}
diff --git a/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx b/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx
index 05c9e1c1..12b30135 100644
--- a/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx
@@ -206,6 +206,7 @@ const CanvasMetadata = (props: {
preferences: {
showComments?: boolean;
showMentions?: boolean;
+ showRecommends?: boolean;
showPrevNext?: boolean;
};
quotesCount: number | undefined;
@@ -221,6 +222,7 @@ const CanvasMetadata = (props: {
recommendsCount={props.recommendsCount}
showComments={props.preferences.showComments !== false}
showMentions={props.preferences.showMentions !== false}
+ showRecommends={props.preferences.showRecommends !== false}
pageId={props.pageId}
/>
{!props.isSubpage && (
diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx b/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx
index 4b90df68..f2645ef9 100644
--- a/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx
@@ -112,6 +112,7 @@ export const Interactions = (props: {
className?: string;
showComments: boolean;
showMentions: boolean;
+ showRecommends: boolean;
pageId?: string;
}) => {
const {
@@ -132,7 +133,8 @@ export const Interactions = (props: {
const tags = normalizedDocument.tags;
const tagCount = tags?.length || 0;
- let interactionsAvailable = props.showComments || props.showMentions;
+ let interactionsAvailable =
+ props.showComments || props.showMentions || props.showRecommends;
return (
{props.quotesCount}
)}
-
+ {props.showRecommends === false ? null : (
+
+ )}
{tagCount > 0 && }
@@ -186,6 +190,7 @@ export const ExpandedInteractions = (props: {
className?: string;
showComments: boolean;
showMentions: boolean;
+ showRecommends: boolean;
pageId?: string;
}) => {
const {
@@ -208,7 +213,8 @@ export const ExpandedInteractions = (props: {
const tags = normalizedDocument.tags;
const tagCount = tags?.length || 0;
- let noInteractions = !props.showComments && !props.showMentions;
+ let noInteractions =
+ !props.showComments && !props.showMentions && !props.showRecommends;
let subscribed =
identity?.atp_did &&
@@ -237,11 +243,13 @@ export const ExpandedInteractions = (props: {
) : (
<>
-
+ {props.showRecommends === false ? null : (
+
+ )}
{props.quotesCount === 0 || !props.showMentions ? null : (
{
diff --git a/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx b/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
index 32ada105..04b9d7d9 100644
--- a/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
@@ -87,6 +87,7 @@ export function LinearDocumentPage({
pageId={pageId}
showComments={preferences.showComments !== false}
showMentions={preferences.showMentions !== false}
+ showRecommends={preferences.showRecommends !== false}
commentsCount={
getCommentCount(document.comments_on_documents, pageId) || 0
}
diff --git a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx
index 8db38856..7a0f8ab0 100644
--- a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx
+++ b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx
@@ -18,7 +18,11 @@ import { ProfilePopover } from "components/ProfilePopover";
export function PostHeader(props: {
data: PostPageData;
profile: ProfileViewDetailed;
- preferences: { showComments?: boolean; showMentions?: boolean };
+ preferences: {
+ showComments?: boolean;
+ showMentions?: boolean;
+ showRecommends?: boolean;
+ };
}) {
let { identity } = useIdentityData();
let document = props.data;
@@ -87,6 +91,7 @@ export function PostHeader(props: {
diff --git a/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
index 076568ef..70ae3d75 100644
--- a/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
+++ b/app/lish/[did]/[publication]/dashboard/settings/PostOptions.tsx
@@ -29,6 +29,11 @@ export const PostOptions = (props: {
? true
: record.preferences.showMentions,
);
+ let [showRecommends, setShowRecommends] = useState(
+ record?.preferences?.showRecommends === undefined
+ ? true
+ : record.preferences.showRecommends,
+ );
let [showPrevNext, setShowPrevNext] = useState(
record?.preferences?.showPrevNext === undefined
? true
@@ -53,6 +58,7 @@ export const PostOptions = (props: {
showComments: showComments,
showMentions: showMentions,
showPrevNext: showPrevNext,
+ showRecommends: showRecommends,
},
});
toast({ type: "success", content: Posts Updated! });
@@ -99,7 +105,21 @@ export const PostOptions = (props: {
Show Mentions
- Display a list of posts on Bluesky that mention your post
+ Display a list Bluesky mentions about your post
+
+
+
+
+ {
+ setShowRecommends(!showRecommends);
+ }}
+ >
+
+
Show Recommends
+
+ Allow readers to recommend/like your post
diff --git a/app/lish/[did]/[publication]/page.tsx b/app/lish/[did]/[publication]/page.tsx
index 4a369f00..457f38b2 100644
--- a/app/lish/[did]/[publication]/page.tsx
+++ b/app/lish/[did]/[publication]/page.tsx
@@ -175,6 +175,9 @@ export default async function Publication(props: {
showMentions={
record?.preferences?.showMentions !== false
}
+ showRecommends={
+ record?.preferences?.showRecommends !== false
+ }
/>
diff --git a/app/lish/createPub/CreatePubForm.tsx b/app/lish/createPub/CreatePubForm.tsx
index 2dbe924e..749b4397 100644
--- a/app/lish/createPub/CreatePubForm.tsx
+++ b/app/lish/createPub/CreatePubForm.tsx
@@ -58,6 +58,7 @@ export const CreatePubForm = () => {
showComments: true,
showMentions: true,
showPrevNext: true,
+ showRecommends: true,
},
});
diff --git a/app/lish/createPub/UpdatePubForm.tsx b/app/lish/createPub/UpdatePubForm.tsx
index 3672c5f8..f9844796 100644
--- a/app/lish/createPub/UpdatePubForm.tsx
+++ b/app/lish/createPub/UpdatePubForm.tsx
@@ -88,6 +88,7 @@ export const EditPubForm = (props: {
showComments: showComments,
showMentions: showMentions,
showPrevNext: showPrevNext,
+ showRecommends: record?.preferences?.showRecommends ?? true,
},
});
toast({ type: "success", content: "Updated!" });
@@ -194,8 +195,6 @@ export const EditPubForm = (props: {
-
-
);
diff --git a/app/lish/createPub/createPublication.ts b/app/lish/createPub/createPublication.ts
index a705a0e6..5adcc7ee 100644
--- a/app/lish/createPub/createPublication.ts
+++ b/app/lish/createPub/createPublication.ts
@@ -5,10 +5,7 @@ import {
PubLeafletPublication,
SiteStandardPublication,
} from "lexicons/api";
-import {
- restoreOAuthSession,
- OAuthSessionError,
-} from "src/atproto-oauth";
+import { restoreOAuthSession, OAuthSessionError } from "src/atproto-oauth";
import { getIdentityData } from "actions/getIdentityData";
import { supabaseServerClient } from "supabase/serverClient";
import { Json } from "supabase/database.types";
@@ -76,7 +73,11 @@ export async function createPublication({
// Build record based on publication type
let record: SiteStandardPublication.Record | PubLeafletPublication.Record;
- let iconBlob: Awaited>["data"]["blob"] | undefined;
+ let iconBlob:
+ | Awaited<
+ ReturnType
+ >["data"]["blob"]
+ | undefined;
// Upload the icon if provided
if (iconFile && iconFile.size > 0) {
@@ -97,16 +98,29 @@ export async function createPublication({
...(iconBlob && { icon: iconBlob }),
basicTheme: {
$type: "site.standard.theme.basic",
- background: { $type: "site.standard.theme.color#rgb", ...PubThemeDefaultsRGB.background },
- foreground: { $type: "site.standard.theme.color#rgb", ...PubThemeDefaultsRGB.foreground },
- accent: { $type: "site.standard.theme.color#rgb", ...PubThemeDefaultsRGB.accent },
- accentForeground: { $type: "site.standard.theme.color#rgb", ...PubThemeDefaultsRGB.accentForeground },
+ background: {
+ $type: "site.standard.theme.color#rgb",
+ ...PubThemeDefaultsRGB.background,
+ },
+ foreground: {
+ $type: "site.standard.theme.color#rgb",
+ ...PubThemeDefaultsRGB.foreground,
+ },
+ accent: {
+ $type: "site.standard.theme.color#rgb",
+ ...PubThemeDefaultsRGB.accent,
+ },
+ accentForeground: {
+ $type: "site.standard.theme.color#rgb",
+ ...PubThemeDefaultsRGB.accentForeground,
+ },
},
preferences: {
showInDiscover: preferences.showInDiscover,
showComments: preferences.showComments,
showMentions: preferences.showMentions,
showPrevNext: preferences.showPrevNext,
+ showRecommends: preferences.showRecommends,
},
} satisfies SiteStandardPublication.Record;
} else {
diff --git a/app/lish/createPub/updatePublication.ts b/app/lish/createPub/updatePublication.ts
index a9bd3e56..350b3f88 100644
--- a/app/lish/createPub/updatePublication.ts
+++ b/app/lish/createPub/updatePublication.ts
@@ -77,7 +77,9 @@ async function withPublicationUpdate(
}
const aturi = new AtUri(existingPub.uri);
- const publicationType = getPublicationType(aturi.collection) as PublicationType;
+ const publicationType = getPublicationType(
+ aturi.collection,
+ ) as PublicationType;
// Normalize existing record
const normalizedPub = normalizePublicationRecord(existingPub.record);
@@ -128,7 +130,11 @@ interface RecordOverrides {
}
/** Merges override with existing value, respecting explicit undefined */
-function resolveField(override: T | undefined, existing: T | undefined, hasOverride: boolean): T | undefined {
+function resolveField(
+ override: T | undefined,
+ existing: T | undefined,
+ hasOverride: boolean,
+): T | undefined {
return hasOverride ? override : existing;
}
@@ -146,17 +152,32 @@ function buildLeafletRecord(
return {
$type: "pub.leaflet.publication",
name: overrides.name ?? normalizedPub?.name ?? "",
- description: resolveField(overrides.description, normalizedPub?.description, "description" in overrides),
- icon: resolveField(overrides.icon, normalizedPub?.icon, "icon" in overrides),
- theme: resolveField(overrides.theme, normalizedPub?.theme, "theme" in overrides),
+ description: resolveField(
+ overrides.description,
+ normalizedPub?.description,
+ "description" in overrides,
+ ),
+ icon: resolveField(
+ overrides.icon,
+ normalizedPub?.icon,
+ "icon" in overrides,
+ ),
+ theme: resolveField(
+ overrides.theme,
+ normalizedPub?.theme,
+ "theme" in overrides,
+ ),
base_path: overrides.basePath ?? existingBasePath,
- preferences: preferences ? {
- $type: "pub.leaflet.publication#preferences",
- showInDiscover: preferences.showInDiscover,
- showComments: preferences.showComments,
- showMentions: preferences.showMentions,
- showPrevNext: preferences.showPrevNext,
- } : undefined,
+ preferences: preferences
+ ? {
+ $type: "pub.leaflet.publication#preferences",
+ showInDiscover: preferences.showInDiscover,
+ showComments: preferences.showComments,
+ showMentions: preferences.showMentions,
+ showPrevNext: preferences.showPrevNext,
+ showRecommends: preferences.showRecommends,
+ }
+ : undefined,
};
}
@@ -175,17 +196,36 @@ function buildStandardRecord(
return {
$type: "site.standard.publication",
name: overrides.name ?? normalizedPub?.name ?? "",
- description: resolveField(overrides.description, normalizedPub?.description, "description" in overrides),
- icon: resolveField(overrides.icon, normalizedPub?.icon, "icon" in overrides),
- theme: resolveField(overrides.theme, normalizedPub?.theme, "theme" in overrides),
- basicTheme: resolveField(overrides.basicTheme, normalizedPub?.basicTheme, "basicTheme" in overrides),
+ description: resolveField(
+ overrides.description,
+ normalizedPub?.description,
+ "description" in overrides,
+ ),
+ icon: resolveField(
+ overrides.icon,
+ normalizedPub?.icon,
+ "icon" in overrides,
+ ),
+ theme: resolveField(
+ overrides.theme,
+ normalizedPub?.theme,
+ "theme" in overrides,
+ ),
+ basicTheme: resolveField(
+ overrides.basicTheme,
+ normalizedPub?.basicTheme,
+ "basicTheme" in overrides,
+ ),
url: basePath ? `https://${basePath}` : normalizedPub?.url || "",
- preferences: preferences ? {
- showInDiscover: preferences.showInDiscover,
- showComments: preferences.showComments,
- showMentions: preferences.showMentions,
- showPrevNext: preferences.showPrevNext,
- } : undefined,
+ preferences: preferences
+ ? {
+ showInDiscover: preferences.showInDiscover,
+ showComments: preferences.showComments,
+ showMentions: preferences.showMentions,
+ showPrevNext: preferences.showPrevNext,
+ showRecommends: preferences.showRecommends,
+ }
+ : undefined,
};
}
@@ -217,27 +257,30 @@ export async function updatePublication({
iconFile?: File | null;
preferences?: Omit;
}): Promise {
- return withPublicationUpdate(uri, async ({ normalizedPub, existingBasePath, publicationType, agent }) => {
- // Upload icon if provided
- let iconBlob = normalizedPub?.icon;
- if (iconFile && iconFile.size > 0) {
- const buffer = await iconFile.arrayBuffer();
- const uploadResult = await agent.com.atproto.repo.uploadBlob(
- new Uint8Array(buffer),
- { encoding: iconFile.type },
- );
- if (uploadResult.data.blob) {
- iconBlob = uploadResult.data.blob;
+ return withPublicationUpdate(
+ uri,
+ async ({ normalizedPub, existingBasePath, publicationType, agent }) => {
+ // Upload icon if provided
+ let iconBlob = normalizedPub?.icon;
+ if (iconFile && iconFile.size > 0) {
+ const buffer = await iconFile.arrayBuffer();
+ const uploadResult = await agent.com.atproto.repo.uploadBlob(
+ new Uint8Array(buffer),
+ { encoding: iconFile.type },
+ );
+ if (uploadResult.data.blob) {
+ iconBlob = uploadResult.data.blob;
+ }
}
- }
- return buildRecord(normalizedPub, existingBasePath, publicationType, {
- name,
- description,
- icon: iconBlob,
- preferences,
- });
- });
+ return buildRecord(normalizedPub, existingBasePath, publicationType, {
+ name,
+ description,
+ icon: iconBlob,
+ preferences,
+ });
+ },
+ );
}
export async function updatePublicationBasePath({
@@ -247,11 +290,14 @@ export async function updatePublicationBasePath({
uri: string;
base_path: string;
}): Promise {
- return withPublicationUpdate(uri, async ({ normalizedPub, existingBasePath, publicationType }) => {
- return buildRecord(normalizedPub, existingBasePath, publicationType, {
- basePath: base_path,
- });
- });
+ return withPublicationUpdate(
+ uri,
+ async ({ normalizedPub, existingBasePath, publicationType }) => {
+ return buildRecord(normalizedPub, existingBasePath, publicationType, {
+ basePath: base_path,
+ });
+ },
+ );
}
type Color =
@@ -275,58 +321,81 @@ export async function updatePublicationTheme({
accentText: Color;
};
}): Promise {
- return withPublicationUpdate(uri, async ({ normalizedPub, existingBasePath, publicationType, agent }) => {
- // Build theme object
- const themeData = {
- $type: "pub.leaflet.publication#theme" as const,
- backgroundImage: theme.backgroundImage
- ? {
- $type: "pub.leaflet.theme.backgroundImage",
- image: (
- await agent.com.atproto.repo.uploadBlob(
- new Uint8Array(await theme.backgroundImage.arrayBuffer()),
- { encoding: theme.backgroundImage.type },
- )
- )?.data.blob,
- width: theme.backgroundRepeat || undefined,
- repeat: !!theme.backgroundRepeat,
- }
- : theme.backgroundImage === null
- ? undefined
- : normalizedPub?.theme?.backgroundImage,
- backgroundColor: theme.backgroundColor
- ? {
- ...theme.backgroundColor,
- }
- : undefined,
- pageWidth: theme.pageWidth,
- primary: {
- ...theme.primary,
- },
- pageBackground: {
- ...theme.pageBackground,
- },
- showPageBackground: theme.showPageBackground,
- accentBackground: {
- ...theme.accentBackground,
- },
- accentText: {
- ...theme.accentText,
- },
- };
+ return withPublicationUpdate(
+ uri,
+ async ({ normalizedPub, existingBasePath, publicationType, agent }) => {
+ // Build theme object
+ const themeData = {
+ $type: "pub.leaflet.publication#theme" as const,
+ backgroundImage: theme.backgroundImage
+ ? {
+ $type: "pub.leaflet.theme.backgroundImage",
+ image: (
+ await agent.com.atproto.repo.uploadBlob(
+ new Uint8Array(await theme.backgroundImage.arrayBuffer()),
+ { encoding: theme.backgroundImage.type },
+ )
+ )?.data.blob,
+ width: theme.backgroundRepeat || undefined,
+ repeat: !!theme.backgroundRepeat,
+ }
+ : theme.backgroundImage === null
+ ? undefined
+ : normalizedPub?.theme?.backgroundImage,
+ backgroundColor: theme.backgroundColor
+ ? {
+ ...theme.backgroundColor,
+ }
+ : undefined,
+ pageWidth: theme.pageWidth,
+ primary: {
+ ...theme.primary,
+ },
+ pageBackground: {
+ ...theme.pageBackground,
+ },
+ showPageBackground: theme.showPageBackground,
+ accentBackground: {
+ ...theme.accentBackground,
+ },
+ accentText: {
+ ...theme.accentText,
+ },
+ };
- // Derive basicTheme from the theme colors for site.standard.publication
- const basicTheme: NormalizedPublication["basicTheme"] = {
- $type: "site.standard.theme.basic",
- background: { $type: "site.standard.theme.color#rgb", r: theme.backgroundColor.r, g: theme.backgroundColor.g, b: theme.backgroundColor.b },
- foreground: { $type: "site.standard.theme.color#rgb", r: theme.primary.r, g: theme.primary.g, b: theme.primary.b },
- accent: { $type: "site.standard.theme.color#rgb", r: theme.accentBackground.r, g: theme.accentBackground.g, b: theme.accentBackground.b },
- accentForeground: { $type: "site.standard.theme.color#rgb", r: theme.accentText.r, g: theme.accentText.g, b: theme.accentText.b },
- };
+ // Derive basicTheme from the theme colors for site.standard.publication
+ const basicTheme: NormalizedPublication["basicTheme"] = {
+ $type: "site.standard.theme.basic",
+ background: {
+ $type: "site.standard.theme.color#rgb",
+ r: theme.backgroundColor.r,
+ g: theme.backgroundColor.g,
+ b: theme.backgroundColor.b,
+ },
+ foreground: {
+ $type: "site.standard.theme.color#rgb",
+ r: theme.primary.r,
+ g: theme.primary.g,
+ b: theme.primary.b,
+ },
+ accent: {
+ $type: "site.standard.theme.color#rgb",
+ r: theme.accentBackground.r,
+ g: theme.accentBackground.g,
+ b: theme.accentBackground.b,
+ },
+ accentForeground: {
+ $type: "site.standard.theme.color#rgb",
+ r: theme.accentText.r,
+ g: theme.accentText.g,
+ b: theme.accentText.b,
+ },
+ };
- return buildRecord(normalizedPub, existingBasePath, publicationType, {
- theme: themeData,
- basicTheme,
- });
- });
+ return buildRecord(normalizedPub, existingBasePath, publicationType, {
+ theme: themeData,
+ basicTheme,
+ });
+ },
+ );
}
diff --git a/components/InteractionsPreview.tsx b/components/InteractionsPreview.tsx
index 46f91183..9f393f86 100644
--- a/components/InteractionsPreview.tsx
+++ b/components/InteractionsPreview.tsx
@@ -18,22 +18,26 @@ export const InteractionPreview = (props: {
postUrl: string;
showComments: boolean;
showMentions: boolean;
+ showRecommends: boolean;
share?: boolean;
}) => {
let smoker = useSmoker();
let interactionsAvailable =
(props.quotesCount > 0 && props.showMentions) ||
- (props.showComments !== false && props.commentsCount > 0);
+ (props.showComments !== false && props.commentsCount > 0) ||
+ (props.showRecommends !== false && props.recommendsCount > 0);
const tagsCount = props.tags?.length || 0;
return (
-
+ {props.showRecommends === false ? null : (
+
+ )}
{!props.showMentions || props.quotesCount === 0 ? null : (
{
tags={tags}
showComments={pubRecord?.preferences?.showComments !== false}
showMentions={pubRecord?.preferences?.showMentions !== false}
+ showRecommends={
+ pubRecord?.preferences?.showRecommends !== false
+ }
share
/>
diff --git a/lexicons/api/types/pub/leaflet/publication.ts b/lexicons/api/types/pub/leaflet/publication.ts
index 88314a28..51143ee0 100644
--- a/lexicons/api/types/pub/leaflet/publication.ts
+++ b/lexicons/api/types/pub/leaflet/publication.ts
@@ -1,89 +1,94 @@
/**
* GENERATED CODE - DO NOT MODIFY
*/
-import { type ValidationResult, BlobRef } from '@atproto/lexicon'
-import { CID } from 'multiformats/cid'
-import { validate as _validate } from '../../../lexicons'
-import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
-import type * as PubLeafletThemeColor from './theme/color'
-import type * as PubLeafletThemeBackgroundImage from './theme/backgroundImage'
+import { type ValidationResult, BlobRef } from "@atproto/lexicon";
+import { CID } from "multiformats/cid";
+import { validate as _validate } from "../../../lexicons";
+import {
+ type $Typed,
+ is$typed as _is$typed,
+ type OmitKey,
+} from "../../../util";
+import type * as PubLeafletThemeColor from "./theme/color";
+import type * as PubLeafletThemeBackgroundImage from "./theme/backgroundImage";
const is$typed = _is$typed,
- validate = _validate
-const id = 'pub.leaflet.publication'
+ validate = _validate;
+const id = "pub.leaflet.publication";
export interface Record {
- $type: 'pub.leaflet.publication'
- name: string
- base_path?: string
- description?: string
- icon?: BlobRef
- theme?: Theme
- preferences?: Preferences
- [k: string]: unknown
+ $type: "pub.leaflet.publication";
+ name: string;
+ base_path?: string;
+ description?: string;
+ icon?: BlobRef;
+ theme?: Theme;
+ preferences?: Preferences;
+ [k: string]: unknown;
}
-const hashRecord = 'main'
+const hashRecord = "main";
export function isRecord(v: V) {
- return is$typed(v, id, hashRecord)
+ return is$typed(v, id, hashRecord);
}
export function validateRecord(v: V) {
- return validate(v, id, hashRecord, true)
+ return validate(v, id, hashRecord, true);
}
export interface Preferences {
- $type?: 'pub.leaflet.publication#preferences'
- showInDiscover: boolean
- showComments: boolean
- showMentions: boolean
- showPrevNext: boolean
+ $type?: "pub.leaflet.publication#preferences";
+ showInDiscover: boolean;
+ showComments: boolean;
+ showMentions: boolean;
+ showPrevNext: boolean;
+ showRecommends: boolean;
}
-const hashPreferences = 'preferences'
+const hashPreferences = "preferences";
export function isPreferences(v: V) {
- return is$typed(v, id, hashPreferences)
+ return is$typed(v, id, hashPreferences);
}
export function validatePreferences(v: V) {
- return validate(v, id, hashPreferences)
+ return validate(v, id, hashPreferences);
}
export interface Theme {
- $type?: 'pub.leaflet.publication#theme'
+ $type?: "pub.leaflet.publication#theme";
backgroundColor?:
| $Typed
| $Typed
- | { $type: string }
- backgroundImage?: PubLeafletThemeBackgroundImage.Main
- pageWidth?: number
+ | { $type: string };
+ backgroundImage?: PubLeafletThemeBackgroundImage.Main;
+ pageWidth?: number;
primary?:
| $Typed
| $Typed
- | { $type: string }
+ | { $type: string };
pageBackground?:
| $Typed
| $Typed
- | { $type: string }
- showPageBackground: boolean
+ | { $type: string };
+ showPageBackground: boolean;
accentBackground?:
| $Typed
| $Typed
- | { $type: string }
+ | { $type: string };
accentText?:
| $Typed
| $Typed
- | { $type: string }
+ | { $type: string };
}
-const hashTheme = 'theme'
+const hashTheme = "theme";
export function isTheme(v: V) {
- return is$typed(v, id, hashTheme)
+ return is$typed(v, id, hashTheme);
}
export function validateTheme(v: V) {
- return validate(v, id, hashTheme)
+ return validate(v, id, hashTheme);
}
diff --git a/lexicons/api/types/site/standard/publication.ts b/lexicons/api/types/site/standard/publication.ts
index 2daf12b6..08f80d9c 100644
--- a/lexicons/api/types/site/standard/publication.ts
+++ b/lexicons/api/types/site/standard/publication.ts
@@ -1,53 +1,58 @@
/**
* GENERATED CODE - DO NOT MODIFY
*/
-import { type ValidationResult, BlobRef } from '@atproto/lexicon'
-import { CID } from 'multiformats/cid'
-import { validate as _validate } from '../../../lexicons'
-import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util'
-import type * as SiteStandardThemeBasic from './theme/basic'
-import type * as PubLeafletPublication from '../../pub/leaflet/publication'
+import { type ValidationResult, BlobRef } from "@atproto/lexicon";
+import { CID } from "multiformats/cid";
+import { validate as _validate } from "../../../lexicons";
+import {
+ type $Typed,
+ is$typed as _is$typed,
+ type OmitKey,
+} from "../../../util";
+import type * as SiteStandardThemeBasic from "./theme/basic";
+import type * as PubLeafletPublication from "../../pub/leaflet/publication";
const is$typed = _is$typed,
- validate = _validate
-const id = 'site.standard.publication'
+ validate = _validate;
+const id = "site.standard.publication";
export interface Record {
- $type: 'site.standard.publication'
- basicTheme?: SiteStandardThemeBasic.Main
- theme?: $Typed | { $type: string }
- description?: string
- icon?: BlobRef
- name: string
- preferences?: Preferences
- url: string
- [k: string]: unknown
+ $type: "site.standard.publication";
+ basicTheme?: SiteStandardThemeBasic.Main;
+ theme?: $Typed | { $type: string };
+ description?: string;
+ icon?: BlobRef;
+ name: string;
+ preferences?: Preferences;
+ url: string;
+ [k: string]: unknown;
}
-const hashRecord = 'main'
+const hashRecord = "main";
export function isRecord(v: V) {
- return is$typed(v, id, hashRecord)
+ return is$typed(v, id, hashRecord);
}
export function validateRecord(v: V) {
- return validate(v, id, hashRecord, true)
+ return validate(v, id, hashRecord, true);
}
export interface Preferences {
- $type?: 'site.standard.publication#preferences'
- showInDiscover: boolean
- showComments: boolean
- showMentions: boolean
- showPrevNext: boolean
+ $type?: "site.standard.publication#preferences";
+ showInDiscover: boolean;
+ showComments: boolean;
+ showMentions: boolean;
+ showPrevNext: boolean;
+ showRecommends: boolean;
}
-const hashPreferences = 'preferences'
+const hashPreferences = "preferences";
export function isPreferences(v: V) {
- return is$typed(v, id, hashPreferences)
+ return is$typed(v, id, hashPreferences);
}
export function validatePreferences(v: V) {
- return validate(v, id, hashPreferences)
+ return validate(v, id, hashPreferences);
}
diff --git a/lexicons/pub/leaflet/publication.json b/lexicons/pub/leaflet/publication.json
index 0627addf..c98b1eb6 100644
--- a/lexicons/pub/leaflet/publication.json
+++ b/lexicons/pub/leaflet/publication.json
@@ -59,6 +59,10 @@
"showPrevNext": {
"type": "boolean",
"default": true
+ },
+ "showRecommends": {
+ "type": "boolean",
+ "default": true
}
}
},
diff --git a/lexicons/site/standard/publication.json b/lexicons/site/standard/publication.json
index b1449052..7fdbcc22 100644
--- a/lexicons/site/standard/publication.json
+++ b/lexicons/site/standard/publication.json
@@ -58,6 +58,10 @@
"showPrevNext": {
"default": false,
"type": "boolean"
+ },
+ "showRecommends": {
+ "default": true,
+ "type": "boolean"
}
},
"type": "object"
diff --git a/lexicons/src/normalize.ts b/lexicons/src/normalize.ts
index d4890e07..4f7294c7 100644
--- a/lexicons/src/normalize.ts
+++ b/lexicons/src/normalize.ts
@@ -50,7 +50,7 @@ export type NormalizedPublication = {
* Checks if the record is a pub.leaflet.document
*/
export function isLeafletDocument(
- record: unknown
+ record: unknown,
): record is PubLeafletDocument.Record {
if (!record || typeof record !== "object") return false;
const r = record as Record;
@@ -65,7 +65,7 @@ export function isLeafletDocument(
* Checks if the record is a site.standard.document
*/
export function isStandardDocument(
- record: unknown
+ record: unknown,
): record is SiteStandardDocument.Record {
if (!record || typeof record !== "object") return false;
const r = record as Record;
@@ -76,7 +76,7 @@ export function isStandardDocument(
* Checks if the record is a pub.leaflet.publication
*/
export function isLeafletPublication(
- record: unknown
+ record: unknown,
): record is PubLeafletPublication.Record {
if (!record || typeof record !== "object") return false;
const r = record as Record;
@@ -91,7 +91,7 @@ export function isLeafletPublication(
* Checks if the record is a site.standard.publication
*/
export function isStandardPublication(
- record: unknown
+ record: unknown,
): record is SiteStandardPublication.Record {
if (!record || typeof record !== "object") return false;
const r = record as Record;
@@ -106,7 +106,7 @@ function extractRgb(
| $Typed
| $Typed
| { $type: string }
- | undefined
+ | undefined,
): { r: number; g: number; b: number } | undefined {
if (!color || typeof color !== "object") return undefined;
const c = color as Record;
@@ -124,12 +124,13 @@ function extractRgb(
* Converts a pub.leaflet theme to a site.standard.theme.basic format
*/
export function leafletThemeToBasicTheme(
- theme: PubLeafletPublication.Theme | undefined
+ theme: PubLeafletPublication.Theme | undefined,
): SiteStandardThemeBasic.Main | undefined {
if (!theme) return undefined;
const background = extractRgb(theme.backgroundColor);
- const accent = extractRgb(theme.accentBackground) || extractRgb(theme.primary);
+ const accent =
+ extractRgb(theme.accentBackground) || extractRgb(theme.primary);
const accentForeground = extractRgb(theme.accentText);
// If we don't have the required colors, return undefined
@@ -160,7 +161,10 @@ export function leafletThemeToBasicTheme(
* @param uri - Optional document URI, used to extract the rkey for the path field when normalizing pub.leaflet records
* @returns A normalized document in site.standard format, or null if invalid/unrecognized
*/
-export function normalizeDocument(record: unknown, uri?: string): NormalizedDocument | null {
+export function normalizeDocument(
+ record: unknown,
+ uri?: string,
+): NormalizedDocument | null {
if (!record || typeof record !== "object") return null;
// Pass through site.standard records directly (theme is already in correct format if present)
@@ -219,7 +223,7 @@ export function normalizeDocument(record: unknown, uri?: string): NormalizedDocu
* @returns A normalized publication in site.standard format, or null if invalid/unrecognized
*/
export function normalizePublication(
- record: unknown
+ record: unknown,
): NormalizedPublication | null {
if (!record || typeof record !== "object") return null;
@@ -268,6 +272,7 @@ export function normalizePublication(
showComments: record.preferences.showComments,
showMentions: record.preferences.showMentions,
showPrevNext: record.preferences.showPrevNext,
+ showRecommends: record.preferences.showRecommends,
}
: undefined;
@@ -290,7 +295,7 @@ export function normalizePublication(
* Type guard to check if a normalized document has leaflet content
*/
export function hasLeafletContent(
- doc: NormalizedDocument
+ doc: NormalizedDocument,
): doc is NormalizedDocument & {
content: $Typed;
} {
@@ -304,7 +309,7 @@ export function hasLeafletContent(
* Gets the pages array from a normalized document, handling both formats
*/
export function getDocumentPages(
- doc: NormalizedDocument
+ doc: NormalizedDocument,
): PubLeafletContent.Main["pages"] | undefined {
if (!doc.content) return undefined;
diff --git a/lexicons/src/publication.ts b/lexicons/src/publication.ts
index 57bbbef9..cf5904d2 100644
--- a/lexicons/src/publication.ts
+++ b/lexicons/src/publication.ts
@@ -29,6 +29,7 @@ export const PubLeafletPublication: LexiconDoc = {
showComments: { type: "boolean", default: true },
showMentions: { type: "boolean", default: true },
showPrevNext: { type: "boolean", default: true },
+ showRecommends: { type: "boolean", default: true },
},
},
theme: {
--
2.51.2