feat: allow hide private subscription in view timeline (#3773)
This commit is contained in:
parent
2ba2948693
commit
f85f2f5fbb
|
|
@ -12,7 +12,10 @@ export type DefinedQuery<TQueryKey extends QueryKey, TData> = Readonly<{
|
|||
cancel: (key?: (key: TQueryKey) => QueryKey) => Promise<void>
|
||||
remove: (key?: (key: TQueryKey) => QueryKey) => Promise<void>
|
||||
|
||||
invalidate: (key?: (key: TQueryKey) => QueryKey) => Promise<void>
|
||||
invalidate: (options?: {
|
||||
keyExtractor?: (key: TQueryKey) => QueryKey
|
||||
exact?: boolean
|
||||
}) => Promise<void>
|
||||
invalidateRoot: () => void
|
||||
|
||||
refetch: () => Promise<TData | undefined>
|
||||
|
|
@ -107,12 +110,14 @@ export function defineQuery<
|
|||
const queryKey = typeof keyExtactor === "function" ? keyExtactor(key) : key
|
||||
queryClient.removeQueries({ queryKey })
|
||||
},
|
||||
invalidate: async (keyExtactor) => {
|
||||
const queryKey = typeof keyExtactor === "function" ? keyExtactor(key) : key
|
||||
invalidate: async (args) => {
|
||||
const { keyExtractor, exact } = args || {}
|
||||
const queryKey = typeof keyExtractor === "function" ? keyExtractor(key) : key
|
||||
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey,
|
||||
refetchType: "all",
|
||||
exact,
|
||||
})
|
||||
options?.onInvalidate?.()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { useTranslation } from "react-i18next"
|
|||
import { toast } from "sonner"
|
||||
import { z } from "zod"
|
||||
|
||||
import { getGeneralSettings } from "~/atoms/settings/general"
|
||||
import { Autocomplete } from "~/components/ui/auto-completion"
|
||||
import { useCurrentModal, useIsInModal } from "~/components/ui/modal/stacked/hooks"
|
||||
import { getRouteParams } from "~/hooks/biz/useRouteParams"
|
||||
|
|
@ -32,6 +33,7 @@ import { useAuthQuery, useI18n } from "~/hooks/common"
|
|||
import { apiClient } from "~/lib/api-fetch"
|
||||
import { tipcClient } from "~/lib/client"
|
||||
import { toastFetchError } from "~/lib/error-parser"
|
||||
import { entries as entriesQuery } from "~/queries/entries"
|
||||
import { feed as feedQuery, useFeedQuery } from "~/queries/feed"
|
||||
import { subscription as subscriptionQuery } from "~/queries/subscriptions"
|
||||
import { useFeedByIdOrUrl } from "~/store/feed"
|
||||
|
|
@ -245,6 +247,16 @@ const FeedInnerForm = ({
|
|||
})
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
if (getGeneralSettings().hidePrivateSubscriptionsInTimeline) {
|
||||
entriesQuery
|
||||
.entries({
|
||||
feedId: "all",
|
||||
view: Number(variables.view),
|
||||
excludePrivate: true,
|
||||
})
|
||||
.invalidate({ exact: true })
|
||||
}
|
||||
|
||||
if (isSubscribed && variables.view !== `${subscription?.view}`) {
|
||||
feedUnreadActions.fetchUnreadByView(subscription?.view)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { useTranslation } from "react-i18next"
|
|||
import { toast } from "sonner"
|
||||
import { z } from "zod"
|
||||
|
||||
import { getGeneralSettings } from "~/atoms/settings/general"
|
||||
import { useCurrentModal } from "~/components/ui/modal/stacked/hooks"
|
||||
import { useI18n } from "~/hooks/common"
|
||||
import { apiClient } from "~/lib/api-fetch"
|
||||
|
|
@ -31,6 +32,7 @@ import { tipcClient } from "~/lib/client"
|
|||
import { getFetchErrorMessage, toastFetchError } from "~/lib/error-parser"
|
||||
import { getNewIssueUrl } from "~/lib/issues"
|
||||
import { FollowSummary } from "~/modules/feed/feed-summary"
|
||||
import { entries as entriesQuery } from "~/queries/entries"
|
||||
import { lists as listsQuery, useList } from "~/queries/lists"
|
||||
import { subscription as subscriptionQuery } from "~/queries/subscriptions"
|
||||
import { useListById } from "~/store/list"
|
||||
|
|
@ -219,6 +221,16 @@ const ListInnerForm = ({
|
|||
})
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
if (getGeneralSettings().hidePrivateSubscriptionsInTimeline) {
|
||||
entriesQuery
|
||||
.entries({
|
||||
feedId: "all",
|
||||
view: Number(variables.view),
|
||||
excludePrivate: true,
|
||||
})
|
||||
.invalidate({ exact: true })
|
||||
}
|
||||
|
||||
if (isSubscribed && variables.view !== `${subscription?.view}`) {
|
||||
feedUnreadActions.fetchUnreadByView(subscription?.view)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ const useRemoteEntries = (): UseEntriesReturn => {
|
|||
const isPreview = useIsPreviewFeed()
|
||||
|
||||
const unreadOnly = useGeneralSettingKey("unreadOnly")
|
||||
const hidePrivateSubscriptionsInTimeline = useGeneralSettingKey(
|
||||
"hidePrivateSubscriptionsInTimeline",
|
||||
)
|
||||
|
||||
const folderIds = useFolderFeedsByFeedId({
|
||||
feedId,
|
||||
|
|
@ -64,6 +67,7 @@ const useRemoteEntries = (): UseEntriesReturn => {
|
|||
listId,
|
||||
view,
|
||||
...(unreadOnly === true && !isPreview && { read: false }),
|
||||
...(hidePrivateSubscriptionsInTimeline === true && { excludePrivate: true }),
|
||||
}
|
||||
|
||||
if (feedId && listId && isBizId(feedId)) {
|
||||
|
|
@ -71,7 +75,16 @@ const useRemoteEntries = (): UseEntriesReturn => {
|
|||
}
|
||||
|
||||
return params
|
||||
}, [feedId, folderIds, inboxId, listId, unreadOnly, view, isPreview])
|
||||
}, [
|
||||
feedId,
|
||||
folderIds,
|
||||
inboxId,
|
||||
listId,
|
||||
unreadOnly,
|
||||
isPreview,
|
||||
view,
|
||||
hidePrivateSubscriptionsInTimeline,
|
||||
])
|
||||
const query = useEntries(entriesOptions)
|
||||
|
||||
const [fetchedTime, setFetchedTime] = useState<number>()
|
||||
|
|
@ -134,6 +147,9 @@ const useLocalEntries = (): UseEntriesReturn => {
|
|||
const { feedId, view, inboxId, listId, isAllFeeds } = useRouteParams()
|
||||
|
||||
const unreadOnly = useGeneralSettingKey("unreadOnly")
|
||||
const hidePrivateSubscriptionsInTimeline = useGeneralSettingKey(
|
||||
"hidePrivateSubscriptionsInTimeline",
|
||||
)
|
||||
|
||||
const folderIds = useFolderFeedsByFeedId({
|
||||
feedId,
|
||||
|
|
@ -145,6 +161,7 @@ const useLocalEntries = (): UseEntriesReturn => {
|
|||
{
|
||||
unread: unreadOnly,
|
||||
view,
|
||||
excludePrivate: hidePrivateSubscriptionsInTimeline,
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { getGeneralSettings } from "~/atoms/settings/general"
|
||||
import { getRouteParams } from "~/hooks/biz/useRouteParams"
|
||||
import { getFolderFeedsByFeedId, subscriptionActions } from "~/store/subscription"
|
||||
|
||||
|
|
@ -17,7 +18,12 @@ export const markAllByRoute = async (filter?: MarkAllFilter) => {
|
|||
if (!routerParams) return
|
||||
|
||||
if (typeof routerParams.feedId === "number" || routerParams.isAllFeeds) {
|
||||
subscriptionActions.markReadByView(view, filter)
|
||||
const { hidePrivateSubscriptionsInTimeline } = getGeneralSettings()
|
||||
subscriptionActions.markReadByView({
|
||||
view,
|
||||
filter,
|
||||
excludePrivate: hidePrivateSubscriptionsInTimeline,
|
||||
})
|
||||
} else if (inboxId) {
|
||||
subscriptionActions.markReadByFeedIds({
|
||||
inboxId,
|
||||
|
|
|
|||
|
|
@ -103,11 +103,14 @@ export const SettingGeneral = () => {
|
|||
label: t("general.auto_group.label"),
|
||||
description: t("general.auto_group.description"),
|
||||
}),
|
||||
|
||||
defineSettingItem("hideAllReadSubscriptions", {
|
||||
label: t("general.hide_all_read_subscriptions.label"),
|
||||
description: t("general.hide_all_read_subscriptions.description"),
|
||||
}),
|
||||
defineSettingItem("hidePrivateSubscriptionsInTimeline", {
|
||||
label: t("general.hide_private_subscriptions_in_timeline.label"),
|
||||
description: t("general.hide_private_subscriptions_in_timeline.description"),
|
||||
}),
|
||||
|
||||
{
|
||||
type: "title",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export const entries = {
|
|||
listId,
|
||||
view,
|
||||
read,
|
||||
excludePrivate,
|
||||
limit,
|
||||
}: {
|
||||
feedId?: number | string
|
||||
|
|
@ -20,10 +21,11 @@ export const entries = {
|
|||
listId?: number | string
|
||||
view?: number
|
||||
read?: boolean
|
||||
excludePrivate?: boolean
|
||||
limit?: number
|
||||
}) =>
|
||||
defineQuery(
|
||||
["entries", inboxId || listId || feedId, view, read, limit],
|
||||
["entries", inboxId || listId || feedId, view, read, excludePrivate, limit],
|
||||
async ({ pageParam }) =>
|
||||
entryActions.fetchEntries({
|
||||
feedId,
|
||||
|
|
@ -31,6 +33,7 @@ export const entries = {
|
|||
listId,
|
||||
view,
|
||||
read,
|
||||
excludePrivate,
|
||||
limit,
|
||||
pageParam: pageParam as string,
|
||||
}),
|
||||
|
|
@ -130,30 +133,35 @@ export const useEntries = ({
|
|||
listId,
|
||||
view,
|
||||
read,
|
||||
excludePrivate,
|
||||
}: {
|
||||
feedId?: number | string
|
||||
inboxId?: number | string
|
||||
listId?: number | string
|
||||
view?: number
|
||||
read?: boolean
|
||||
excludePrivate?: boolean
|
||||
}) => {
|
||||
const fetchUnread = read === false
|
||||
const feedUnreadDirty = useFeedUnreadIsDirty((feedId as string) || "")
|
||||
|
||||
return useAuthInfiniteQuery(entries.entries({ feedId, inboxId, listId, view, read }), {
|
||||
enabled: feedId !== undefined || inboxId !== undefined || listId !== undefined,
|
||||
getNextPageParam: (lastPage) => lastPage.data?.at(-1)?.entries.publishedAt,
|
||||
initialPageParam: undefined,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
// DON'T refetch when the router is pop to previous page
|
||||
refetchOnMount: fetchUnread && feedUnreadDirty && !history.isPop ? "always" : false,
|
||||
return useAuthInfiniteQuery(
|
||||
entries.entries({ feedId, inboxId, listId, view, read, excludePrivate }),
|
||||
{
|
||||
enabled: feedId !== undefined || inboxId !== undefined || listId !== undefined,
|
||||
getNextPageParam: (lastPage) => lastPage.data?.at(-1)?.entries.publishedAt,
|
||||
initialPageParam: undefined,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
// DON'T refetch when the router is pop to previous page
|
||||
refetchOnMount: fetchUnread && feedUnreadDirty && !history.isPop ? "always" : false,
|
||||
|
||||
staleTime:
|
||||
// Force refetch unread entries when feed is dirty
|
||||
// HACK: disable refetch when the router is pop to previous page
|
||||
history.isPop ? Infinity : fetchUnread && feedUnreadDirty ? 0 : defaultStaleTime,
|
||||
})
|
||||
staleTime:
|
||||
// Force refetch unread entries when feed is dirty
|
||||
// HACK: disable refetch when the router is pop to previous page
|
||||
history.isPop ? Infinity : fetchUnread && feedUnreadDirty ? 0 : defaultStaleTime,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export const useEntriesPreview = ({ id }: { id?: string }) =>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useCallback } from "react"
|
|||
import { FEED_COLLECTION_LIST, ROUTE_FEED_IN_FOLDER } from "~/constants"
|
||||
|
||||
import { useListsFeedIds } from "../list"
|
||||
import { useFeedIdByView } from "../subscription"
|
||||
import { useFeedIdByView, useNonPrivateSubscriptionIds } from "../subscription"
|
||||
import { getEntryIsInView, getFilteredFeedIds } from "./helper"
|
||||
import { useEntryStore } from "./store"
|
||||
import type { EntryFilter, FlatEntryModel } from "./types"
|
||||
|
|
@ -82,12 +82,15 @@ export const useEntryIdsByFeedId = (feedId: string, filter?: EntryFilter) =>
|
|||
|
||||
export const useEntryIdsByView = (view: FeedViewType, filter?: EntryFilter) => {
|
||||
const feedIds = useFeedIdByView(view)
|
||||
const listFeedIds = useListsFeedIds(feedIds)
|
||||
const nonPrivateFeedIds = useNonPrivateSubscriptionIds(feedIds)
|
||||
const finalFeedIds = filter?.excludePrivate ? nonPrivateFeedIds : feedIds
|
||||
const listFeedIds = useListsFeedIds(finalFeedIds)
|
||||
|
||||
return useEntryStore(
|
||||
useCallback(
|
||||
() => getFilteredFeedIds(Array.from(new Set([...feedIds, ...listFeedIds])), filter) || [],
|
||||
[feedIds, listFeedIds, filter],
|
||||
() =>
|
||||
getFilteredFeedIds(Array.from(new Set([...finalFeedIds, ...listFeedIds])), filter) || [],
|
||||
[finalFeedIds, listFeedIds, filter],
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ class EntryActions {
|
|||
listId,
|
||||
view,
|
||||
read,
|
||||
excludePrivate,
|
||||
limit,
|
||||
pageParam,
|
||||
}: {
|
||||
|
|
@ -121,6 +122,7 @@ class EntryActions {
|
|||
listId?: number | string
|
||||
view?: number
|
||||
read?: boolean
|
||||
excludePrivate?: boolean
|
||||
limit?: number
|
||||
pageParam?: string
|
||||
}) {
|
||||
|
|
@ -163,6 +165,7 @@ class EntryActions {
|
|||
publishedAfter: pageParam,
|
||||
read,
|
||||
limit,
|
||||
excludePrivate,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -31,4 +31,5 @@ export interface EntryState {
|
|||
export interface EntryFilter {
|
||||
unread?: boolean
|
||||
view?: FeedViewType
|
||||
excludePrivate?: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,3 +211,9 @@ export const useInboxesGroupedData = (view: FeedViewType) => {
|
|||
|
||||
export const useIsSubscribed = (feedId: string) =>
|
||||
useSubscriptionStore(useCallback((state) => isSubscribedSelector(feedId)(state), [feedId]))
|
||||
|
||||
export const useNonPrivateSubscriptionIds = (ids: string[]) => {
|
||||
const subscriptions = useSubscriptionsByFeedIds(ids)
|
||||
const nonPrivateSubscriptions = subscriptions.filter((s) => !!s).filter((s) => !s?.isPrivate)
|
||||
return nonPrivateSubscriptions.map((s) => s.listId || s.feedId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,13 +238,22 @@ class SubscriptionActions {
|
|||
})
|
||||
}
|
||||
|
||||
async markReadByView(view: FeedViewType, filter?: MarkReadFilter) {
|
||||
async markReadByView({
|
||||
view,
|
||||
excludePrivate,
|
||||
filter,
|
||||
}: {
|
||||
view: FeedViewType
|
||||
excludePrivate?: boolean
|
||||
filter?: MarkReadFilter
|
||||
}) {
|
||||
const tx = createTransaction()
|
||||
|
||||
tx.execute(async () => {
|
||||
await apiClient.reads.all.$post({
|
||||
json: {
|
||||
view,
|
||||
excludePrivate,
|
||||
...filter,
|
||||
},
|
||||
})
|
||||
|
|
@ -257,6 +266,9 @@ class SubscriptionActions {
|
|||
tx.optimistic(async () => {
|
||||
const state = get()
|
||||
for (const feedId in state.data) {
|
||||
if (excludePrivate && state.data[feedId]?.isPrivate) {
|
||||
return
|
||||
}
|
||||
if (state.data[feedId]!.view === view) {
|
||||
if (state.data[feedId]?.listId) {
|
||||
const listFeedIds = getListById(state.data[feedId].listId)?.feedIds
|
||||
|
|
|
|||
|
|
@ -111,6 +111,9 @@ export const GeneralScreen: NavigationControllerView = () => {
|
|||
const summary = useGeneralSettingKey("summary")
|
||||
const autoGroup = useGeneralSettingKey("autoGroup")
|
||||
const hideAllReadSubscriptions = useGeneralSettingKey("hideAllReadSubscriptions")
|
||||
const hidePrivateSubscriptionsInTimeline = useGeneralSettingKey(
|
||||
"hidePrivateSubscriptionsInTimeline",
|
||||
)
|
||||
const showUnreadOnLaunch = useGeneralSettingKey("unreadOnly")
|
||||
// const groupByDate = useGeneralSettingKey("groupByDate")
|
||||
const expandLongSocialMedia = useGeneralSettingKey("autoExpandLongSocialMedia")
|
||||
|
|
@ -184,6 +187,19 @@ export const GeneralScreen: NavigationControllerView = () => {
|
|||
}}
|
||||
/>
|
||||
</GroupedInsetListCell>
|
||||
|
||||
<GroupedInsetListCell
|
||||
label={t("general.hide_private_subscriptions_in_timeline.label")}
|
||||
description={t("general.hide_private_subscriptions_in_timeline.description")}
|
||||
>
|
||||
<Switch
|
||||
size="sm"
|
||||
value={hidePrivateSubscriptionsInTimeline}
|
||||
onValueChange={(value) => {
|
||||
setGeneralSetting("hidePrivateSubscriptionsInTimeline", value)
|
||||
}}
|
||||
/>
|
||||
</GroupedInsetListCell>
|
||||
</GroupedInsetListCard>
|
||||
|
||||
{/* Timeline */}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,28 @@ import type { EntryModel, FetchEntriesProps } from "./types"
|
|||
export const usePrefetchEntries = (props: Omit<FetchEntriesProps, "pageParam" | "read"> | null) => {
|
||||
const { feedId, inboxId, listId, view, limit, feedIdList } = props || {}
|
||||
const unreadOnly = useGeneralSettingKey("unreadOnly")
|
||||
const hidePrivateSubscriptionsInTimeline = useGeneralSettingKey(
|
||||
"hidePrivateSubscriptionsInTimeline",
|
||||
)
|
||||
return useInfiniteQuery({
|
||||
queryKey: ["entries", feedId, inboxId, listId, view, unreadOnly, limit, feedIdList],
|
||||
queryKey: [
|
||||
"entries",
|
||||
feedId,
|
||||
inboxId,
|
||||
listId,
|
||||
view,
|
||||
unreadOnly,
|
||||
limit,
|
||||
feedIdList,
|
||||
hidePrivateSubscriptionsInTimeline,
|
||||
],
|
||||
queryFn: ({ pageParam }) =>
|
||||
entrySyncServices.fetchEntries({ ...props, pageParam, read: unreadOnly ? false : undefined }),
|
||||
entrySyncServices.fetchEntries({
|
||||
...props,
|
||||
pageParam,
|
||||
read: unreadOnly ? false : undefined,
|
||||
excludePrivate: hidePrivateSubscriptionsInTimeline,
|
||||
}),
|
||||
getNextPageParam: (lastPage) => lastPage.data?.at(-1)?.entries.publishedAt,
|
||||
initialPageParam: undefined as undefined | string,
|
||||
refetchOnWindowFocus: false,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { FeedViewType } from "@follow/constants"
|
|||
import { debounce } from "es-toolkit/compat"
|
||||
import { fetch as expoFetch } from "expo/fetch"
|
||||
|
||||
import { getGeneralSettings } from "@/src/atoms/settings/general"
|
||||
import { apiClient } from "@/src/lib/api-fetch"
|
||||
import { getCookie } from "@/src/lib/auth"
|
||||
import { honoMorph } from "@/src/morph/hono"
|
||||
|
|
@ -68,16 +69,21 @@ class EntryActions {
|
|||
sources?: string[] | null
|
||||
}) {
|
||||
if (!feedId) return
|
||||
|
||||
const subscription = getSubscription(feedId)
|
||||
if (typeof subscription?.view === "number") {
|
||||
const { hidePrivateSubscriptionsInTimeline } = getGeneralSettings()
|
||||
const ignore = hidePrivateSubscriptionsInTimeline && subscription?.isPrivate
|
||||
|
||||
if (typeof subscription?.view === "number" && !ignore) {
|
||||
draft.entryIdByView[subscription.view].add(entryId)
|
||||
}
|
||||
|
||||
// lists
|
||||
for (const s of sources ?? []) {
|
||||
const subscription = getSubscription(s)
|
||||
const ignore = hidePrivateSubscriptionsInTimeline && subscription?.isPrivate
|
||||
|
||||
if (typeof subscription?.view === "number") {
|
||||
if (typeof subscription?.view === "number" && !ignore) {
|
||||
draft.entryIdByView[subscription.view].add(entryId)
|
||||
}
|
||||
}
|
||||
|
|
@ -363,8 +369,18 @@ class EntryActions {
|
|||
|
||||
class EntrySyncServices {
|
||||
async fetchEntries(props: FetchEntriesProps) {
|
||||
const { feedId, inboxId, listId, view, read, limit, pageParam, isCollection, feedIdList } =
|
||||
props
|
||||
const {
|
||||
feedId,
|
||||
inboxId,
|
||||
listId,
|
||||
view,
|
||||
read,
|
||||
limit,
|
||||
pageParam,
|
||||
isCollection,
|
||||
feedIdList,
|
||||
excludePrivate,
|
||||
} = props
|
||||
const params = getEntriesParams({
|
||||
feedId,
|
||||
inboxId,
|
||||
|
|
@ -389,6 +405,7 @@ class EntrySyncServices {
|
|||
read,
|
||||
limit,
|
||||
isCollection,
|
||||
excludePrivate,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ export type FetchEntriesProps = {
|
|||
limit?: number
|
||||
pageParam?: string
|
||||
isCollection?: boolean
|
||||
excludePrivate?: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { FeedViewType } from "@follow/constants"
|
||||
|
||||
import { getGeneralSettings } from "@/src/atoms/settings/general"
|
||||
import type { UnreadSchema } from "@/src/database/schemas/types"
|
||||
import { apiClient } from "@/src/lib/api-fetch"
|
||||
import { setBadgeCountAsyncWithPermission } from "@/src/lib/permission"
|
||||
|
|
@ -68,9 +69,11 @@ class UnreadSyncService {
|
|||
} | null
|
||||
time?: PublishAtTimeRangeFilter
|
||||
}) {
|
||||
const { hidePrivateSubscriptionsInTimeline } = getGeneralSettings()
|
||||
await apiClient.reads.all.$post({
|
||||
json: {
|
||||
view,
|
||||
excludePrivate: hidePrivateSubscriptionsInTimeline,
|
||||
...filter,
|
||||
...time,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@
|
|||
"general.group_by_date.label": "Group by date",
|
||||
"general.hide_all_read_subscriptions.description": "Hide subscriptions without unread entries in the subscription list.",
|
||||
"general.hide_all_read_subscriptions.label": "Hide read",
|
||||
"general.hide_private_subscriptions_in_timeline.description": "Hide private subscriptions in the View Timeline.",
|
||||
"general.hide_private_subscriptions_in_timeline.label": "Hide private",
|
||||
"general.language": "Language",
|
||||
"general.launch_at_login": "Launch at login",
|
||||
"general.log_file.button": "Reveal",
|
||||
|
|
|
|||
|
|
@ -185,6 +185,8 @@
|
|||
"general.group_by_date.label": "按日期分组",
|
||||
"general.hide_all_read_subscriptions.description": "在订阅列表中隐藏没有未读条目的订阅。",
|
||||
"general.hide_all_read_subscriptions.label": "隐藏已读",
|
||||
"general.hide_private_subscriptions_in_timeline.description": "在视图时间线中隐藏私密订阅。",
|
||||
"general.hide_private_subscriptions_in_timeline.label": "隐藏私密",
|
||||
"general.language": "语言",
|
||||
"general.launch_at_login": "开机时启动",
|
||||
"general.log_file.button": "显示",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const defaultGeneralSettings: GeneralSettings = {
|
|||
// subscription
|
||||
autoGroup: true,
|
||||
hideAllReadSubscriptions: false,
|
||||
hidePrivateSubscriptionsInTimeline: false,
|
||||
|
||||
// view
|
||||
unreadOnly: true,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ export interface GeneralSettings {
|
|||
// subscription
|
||||
autoGroup: boolean
|
||||
hideAllReadSubscriptions: boolean
|
||||
hidePrivateSubscriptionsInTimeline: boolean
|
||||
|
||||
/**
|
||||
* Top timeline for mobile
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue