feat: hide from timeline option (#4229)

This commit is contained in:
Stephen Zhou 2025-07-23 18:26:38 +08:00 committed by GitHub
parent b7aedd3809
commit 3a9cec4c64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1025 additions and 14 deletions

View File

@ -46,6 +46,7 @@ const formSchema = z.object({
view: z.string(),
category: z.string().nullable().optional(),
isPrivate: z.boolean().optional(),
hideFromTimeline: z.boolean().optional(),
title: z.string().optional(),
})
export type FeedFormDataValuesType = z.infer<typeof formSchema>
@ -189,6 +190,7 @@ const FeedInnerForm = ({
category?: string | null
isPrivate?: boolean
title?: string | null
hideFromTimeline?: boolean | null
}
feed: FeedModel
entries?: EntryModelSimple[]
@ -217,8 +219,11 @@ const FeedInnerForm = ({
if (subscription) {
form.setValue("view", `${subscription?.view}`)
subscription?.category && form.setValue("category", subscription.category)
form.setValue("isPrivate", subscription?.isPrivate || false)
form.setValue("title", subscription?.title || "")
typeof subscription.isPrivate === "boolean" &&
form.setValue("isPrivate", subscription.isPrivate)
typeof subscription.hideFromTimeline === "boolean" &&
form.setValue("hideFromTimeline", subscription.hideFromTimeline)
subscription?.title && form.setValue("title", subscription.title)
}
}, [subscription])
@ -239,6 +244,7 @@ const FeedInnerForm = ({
view: Number.parseInt(values.view),
category: values.category,
isPrivate: values.isPrivate,
hideFromTimeline: values.hideFromTimeline,
title: values.title,
feedId: feed.id,
}
@ -387,6 +393,29 @@ const FeedInnerForm = ({
</FormItem>
)}
/>
<FormField
control={form.control}
name="hideFromTimeline"
render={({ field }) => (
<FormItem>
<div className="flex items-center justify-between">
<div>
<FormLabel>{t("feed_form.hide_from_timeline")}</FormLabel>
<FormDescription>
{t("feed_form.hide_from_timeline_description")}
</FormDescription>
</div>
<FormControl>
<Switch
className="shrink-0"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="view"

View File

@ -44,6 +44,7 @@ const formSchema = z.object({
view: z.string(),
category: z.string().nullable().optional(),
isPrivate: z.boolean().optional(),
hideFromTimeline: z.boolean().optional(),
title: z.string().optional(),
})
@ -175,6 +176,7 @@ const ListInnerForm = ({
category?: string | null
isPrivate?: boolean
title?: string | null
hideFromTimeline?: boolean | null
}
list: ListModel
analytics?: ListAnalyticsModel
@ -201,8 +203,11 @@ const ListInnerForm = ({
useEffect(() => {
if (subscription) {
form.setValue("view", `${subscription?.view}`)
form.setValue("isPrivate", subscription?.isPrivate || false)
form.setValue("title", subscription?.title || "")
typeof subscription.isPrivate === "boolean" &&
form.setValue("isPrivate", subscription.isPrivate)
subscription?.title && form.setValue("title", subscription.title)
typeof subscription.hideFromTimeline === "boolean" &&
form.setValue("hideFromTimeline", subscription.hideFromTimeline)
}
}, [subscription])
@ -213,6 +218,7 @@ const ListInnerForm = ({
view: Number.parseInt(values.view),
category: values.category,
isPrivate: values.isPrivate,
hideFromTimeline: values.hideFromTimeline,
title: values.title,
TOTPCode: values.TOTPCode,
}
@ -334,6 +340,29 @@ const ListInnerForm = ({
</FormItem>
)}
/>
<FormField
control={form.control}
name="hideFromTimeline"
render={({ field }) => (
<FormItem>
<div className="flex items-center justify-between">
<div>
<FormLabel>{t("feed_form.hide_from_timeline")}</FormLabel>
<FormDescription>
{t("feed_form.hide_from_timeline_description")}
</FormDescription>
</div>
<FormControl>
<Switch
className="shrink-0"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</div>
</FormItem>
)}
/>
{!!list.fee && !isSubscribed && (
<div>
<FormLabel className="flex items-center gap-1">

View File

@ -37,6 +37,7 @@ const formSchema = z.object({
view: z.coerce.number(),
category: z.string().nullable().optional(),
isPrivate: z.boolean().optional(),
hideFromTimeline: z.boolean().optional(),
title: z.string().optional(),
})
@ -93,9 +94,10 @@ function FollowImpl(props: { feedId: string; defaultView?: FeedViewType }) {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
category: subscription?.category ?? "",
isPrivate: subscription?.isPrivate ?? false,
title: subscription?.title ?? "",
category: subscription?.category ?? undefined,
isPrivate: subscription?.isPrivate ?? undefined,
hideFromTimeline: subscription?.hideFromTimeline ?? undefined,
title: subscription?.title ?? undefined,
view: subscription?.view ?? defaultView ?? FeedViewType.Articles,
},
})
@ -121,8 +123,10 @@ function FollowImpl(props: { feedId: string; defaultView?: FeedViewType }) {
view: values.view,
category: values.category ?? "",
isPrivate: values.isPrivate ?? false,
hideFromTimeline: values.hideFromTimeline,
title: values.title ?? "",
feedId: feed?.id,
listId: undefined,
}
if (isSubscribed) {
@ -276,6 +280,22 @@ function FollowImpl(props: { feedId: string; defaultView?: FeedViewType }) {
/>
</View>
<View>
<Controller
name="hideFromTimeline"
control={form.control}
render={({ field: { onChange, value } }) => (
<FormSwitch
size="sm"
value={value}
label={t("subscription_form.hide_from_timeline")}
description={t("subscription_form.hide_from_timeline_description")}
onValueChange={onChange}
/>
)}
/>
</View>
<View className="-mx-3">
<FormLabel className="mb-4 pl-4" label={t("subscription_form.view")} optional />

View File

@ -54,6 +54,7 @@ export const FollowList = (props: { id: string }) => {
const formSchema = z.object({
view: z.number(),
isPrivate: z.boolean(),
hideFromTimeline: z.boolean().optional(),
title: z.string().optional(),
})
@ -71,6 +72,7 @@ const Impl = (props: { id: string }) => {
defaultValues: {
view: list?.view ?? FeedViewType.Articles,
isPrivate: subscription?.isPrivate,
hideFromTimeline: subscription?.hideFromTimeline ?? undefined,
title: subscription?.title ?? undefined,
},
})
@ -89,6 +91,11 @@ const Impl = (props: { id: string }) => {
isPrivate: payload.isPrivate,
title: payload.title,
hideFromTimeline: payload.hideFromTimeline,
url: undefined,
category: undefined,
feedId: undefined,
}
if (isSubscribed) {
@ -220,6 +227,22 @@ const Impl = (props: { id: string }) => {
/>
</View>
<View className="-mx-1">
<Controller
name="hideFromTimeline"
control={form.control}
render={({ field: { onChange, value } }) => (
<FormSwitch
value={value}
label={t("subscription_form.hide_from_timeline")}
description={t("subscription_form.hide_from_timeline_description")}
onValueChange={onChange}
size="sm"
/>
)}
/>
</View>
{!!list.fee && (
<View className="ml-1">
<View className="flex-row">

View File

@ -233,6 +233,8 @@
"feed_form.follow": "Follow",
"feed_form.follow_with_fee": "Follow with {{fee}} Power",
"feed_form.followed": "🎉 Followed.",
"feed_form.hide_from_timeline": "Hide from Timeline",
"feed_form.hide_from_timeline_description": "Whether this subscription's entries are visible on your main view timeline.",
"feed_form.private_follow": "Private Follow",
"feed_form.private_follow_description": "Whether this follow is publicly visible on your profile page.",
"feed_form.retry": "Retry",

View File

@ -63,6 +63,8 @@
"signin.sign_up_to": "Sign up to",
"subscription_form.category": "Category",
"subscription_form.category_description": "By default, your follows will be grouped by website.",
"subscription_form.hide_from_timeline": "Hide from Timeline",
"subscription_form.hide_from_timeline_description": "Whether this subscription's entries are visible on your main view timeline.",
"subscription_form.private_follow": "Private Follow",
"subscription_form.private_follow_description": "Whether this follow is publicly visible on your profile page.",
"subscription_form.title": "Title",

View File

@ -0,0 +1 @@
ALTER TABLE `subscriptions` ADD `hide_from_timeline` integer;

View File

@ -0,0 +1,886 @@
{
"version": "6",
"dialect": "sqlite",
"id": "611bbe39-b8f0-4c81-a067-315ac9b0f8a3",
"prevId": "022f2968-0d86-43b1-a257-1c81d8fd42d4",
"tables": {
"ai_chat_messages": {
"name": "ai_chat_messages",
"columns": {
"room_id": {
"name": "room_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch() * 1000)"
},
"message": {
"name": "message",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"ai_chat_messages_unq": {
"name": "ai_chat_messages_unq",
"columns": ["room_id", "id"],
"isUnique": true
}
},
"foreignKeys": {
"ai_chat_messages_room_id_ai_chat_room_id_fk": {
"name": "ai_chat_messages_room_id_ai_chat_room_id_fk",
"tableFrom": "ai_chat_messages",
"tableTo": "ai_chat",
"columnsFrom": ["room_id"],
"columnsTo": ["room_id"],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"ai_chat": {
"name": "ai_chat",
"columns": {
"room_id": {
"name": "room_id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch() * 1000)"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"collections": {
"name": "collections",
"columns": {
"feed_id": {
"name": "feed_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"entry_id": {
"name": "entry_id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"view": {
"name": "view",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"entries": {
"name": "entries",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"url": {
"name": "url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"source_content": {
"name": "source_content",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"readability_updated_at": {
"name": "readability_updated_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"guid": {
"name": "guid",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"author": {
"name": "author",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"author_url": {
"name": "author_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"author_avatar": {
"name": "author_avatar",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"inserted_at": {
"name": "inserted_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"published_at": {
"name": "published_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"media": {
"name": "media",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"categories": {
"name": "categories",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"attachments": {
"name": "attachments",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"extra": {
"name": "extra",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"language": {
"name": "language",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"feed_id": {
"name": "feed_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"inbox_handle": {
"name": "inbox_handle",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"read": {
"name": "read",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"sources": {
"name": "sources",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"settings": {
"name": "settings",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"feeds": {
"name": "feeds",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"url": {
"name": "url",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"error_at": {
"name": "error_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"site_url": {
"name": "site_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"owner_user_id": {
"name": "owner_user_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"error_message": {
"name": "error_message",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"subscription_count": {
"name": "subscription_count",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"updates_per_week": {
"name": "updates_per_week",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"latest_entry_published_at": {
"name": "latest_entry_published_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"tip_users": {
"name": "tip_users",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"published_at": {
"name": "published_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"images": {
"name": "images",
"columns": {
"url": {
"name": "url",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"colors": {
"name": "colors",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(unixepoch() * 1000)"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"inboxes": {
"name": "inboxes",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"secret": {
"name": "secret",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"lists": {
"name": "lists",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feed_ids": {
"name": "feed_ids",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"view": {
"name": "view",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"fee": {
"name": "fee",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"owner_user_id": {
"name": "owner_user_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"subscription_count": {
"name": "subscription_count",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"purchase_amount": {
"name": "purchase_amount",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"subscriptions": {
"name": "subscriptions",
"columns": {
"feed_id": {
"name": "feed_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"list_id": {
"name": "list_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"inbox_id": {
"name": "inbox_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"view": {
"name": "view",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"is_private": {
"name": "is_private",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"hide_from_timeline": {
"name": "hide_from_timeline",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"summaries": {
"name": "summaries",
"columns": {
"entry_id": {
"name": "entry_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"summary": {
"name": "summary",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"readability_summary": {
"name": "readability_summary",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"language": {
"name": "language",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"unq": {
"name": "unq",
"columns": ["entry_id", "language"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"translations": {
"name": "translations",
"columns": {
"entry_id": {
"name": "entry_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"language": {
"name": "language",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"readability_content": {
"name": "readability_content",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {
"translation-unique-index": {
"name": "translation-unique-index",
"columns": ["entry_id", "language"],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"unread": {
"name": "unread",
"columns": {
"subscription_id": {
"name": "subscription_id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"count": {
"name": "count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"users": {
"name": "users",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"handle": {
"name": "handle",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"is_me": {
"name": "is_me",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"email_verified": {
"name": "email_verified",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bio": {
"name": "bio",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"website": {
"name": "website",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"social_links": {
"name": "social_links",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -225,6 +225,13 @@
"when": 1751640829832,
"tag": "0031_kind_ikaris",
"breakpoints": true
},
{
"idx": 32,
"version": "6",
"when": 1753240775348,
"tag": "0032_orange_prima",
"breakpoints": true
}
]
}

View File

@ -32,6 +32,7 @@ import m0028 from "./0028_chief_cyclops.sql"
import m0029 from "./0029_flaky_gorgon.sql"
import m0030 from "./0030_common_gabe_jones.sql"
import m0031 from "./0031_kind_ikaris.sql"
import m0032 from "./0032_orange_prima.sql"
import journal from "./meta/_journal.json"
export default {
@ -69,5 +70,6 @@ export default {
m0029,
m0030,
m0031,
m0032,
},
}

View File

@ -31,6 +31,7 @@ export const subscriptionsTable = sqliteTable("subscriptions", {
userId: text("user_id").notNull(),
view: integer("view").notNull().$type<FeedViewType>(),
isPrivate: integer("is_private", { mode: "boolean" }).notNull(),
hideFromTimeline: integer("hide_from_timeline", { mode: "boolean" }),
title: text("title"),
category: text("category"),
createdAt: text("created_at"),

View File

@ -91,7 +91,9 @@ class EntryActions implements Hydratable, Resetable {
if (!feedId) return
const subscription = getSubscriptionById(feedId)
const ignore = hidePrivateSubscriptionsInTimeline && subscription?.isPrivate
const ignore =
(hidePrivateSubscriptionsInTimeline && subscription?.isPrivate) ||
subscription?.hideFromTimeline
if (typeof subscription?.view === "number" && !ignore) {
draft.entryIdByView[subscription.view].add(entryId)
@ -100,7 +102,9 @@ class EntryActions implements Hydratable, Resetable {
// lists
for (const s of sources ?? []) {
const subscription = getSubscriptionById(s)
const ignore = hidePrivateSubscriptionsInTimeline && subscription?.isPrivate
const ignore =
(hidePrivateSubscriptionsInTimeline && subscription?.isPrivate) ||
subscription?.hideFromTimeline
if (typeof subscription?.view === "number" && !ignore) {
draft.entryIdByView[subscription.view].add(entryId)

View File

@ -40,6 +40,8 @@ class APIMorph {
userId: item.userId,
view: item.view,
isPrivate: item.isPrivate,
// @ts-expect-error update client sdk
hideFromTimeline: item.hideFromTimeline,
title: item.title,
createdAt: item.createdAt,
} as SubscriptionModel

View File

@ -1,14 +1,17 @@
import type { FeedViewType } from "@follow/constants"
import type { SubscriptionSchema } from "@follow/database/schemas/types"
type Nullable<T> = T | null | undefined
export interface SubscriptionForm {
url?: string
url: string | undefined
view: FeedViewType
category?: string
category: Nullable<string>
isPrivate: boolean
title?: string | null
feedId?: string
listId?: string
hideFromTimeline: Nullable<boolean>
title: Nullable<string>
feedId: Nullable<string>
listId: string | undefined
}
export type SubscriptionModel = Omit<SubscriptionSchema, "id">