feat: use insertedBefore for mark above read
This commit is contained in:
parent
3488390afc
commit
a17db88b60
|
|
@ -2,16 +2,34 @@ import { FeedViewType, views } from "@follow/constants"
|
|||
|
||||
import { FlatMarkAllReadButton } from "./mark-all-button"
|
||||
|
||||
export const FooterMarkItem = ({ view }: { view: FeedViewType }) => {
|
||||
export const FooterMarkItem = ({
|
||||
view,
|
||||
fetchedTime,
|
||||
}: {
|
||||
view: FeedViewType
|
||||
fetchedTime?: number
|
||||
}) => {
|
||||
const filter = fetchedTime
|
||||
? {
|
||||
insertedBefore: fetchedTime,
|
||||
}
|
||||
: undefined
|
||||
|
||||
if (view === FeedViewType.SocialMedia) {
|
||||
return <SocialMediaFooterMarkItem />
|
||||
return <SocialMediaFooterMarkItem filter={filter} />
|
||||
} else if (views[view]!.gridMode) {
|
||||
return <GridFooterMarkItem />
|
||||
return <GridFooterMarkItem filter={filter} />
|
||||
}
|
||||
return <CommonFooterMarkItem />
|
||||
return <CommonFooterMarkItem filter={filter} />
|
||||
}
|
||||
|
||||
const SocialMediaFooterMarkItem = () => {
|
||||
interface FooterMarkItemProps {
|
||||
filter?: {
|
||||
insertedBefore: number
|
||||
}
|
||||
}
|
||||
|
||||
const SocialMediaFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
|
||||
return (
|
||||
<div className="relative flex w-full">
|
||||
<FlatMarkAllReadButton
|
||||
|
|
@ -19,30 +37,33 @@ const SocialMediaFooterMarkItem = () => {
|
|||
buttonClassName="w-[645px] mx-auto mb-4 pl-7 py-4"
|
||||
iconClassName="mr-1 text-lg"
|
||||
which="above"
|
||||
filter={filter}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const GridFooterMarkItem = () => {
|
||||
const GridFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
|
||||
return (
|
||||
<div className="relative flex w-full">
|
||||
<FlatMarkAllReadButton
|
||||
buttonClassName="w-full py-4"
|
||||
iconClassName="mr-1 text-base"
|
||||
which="above"
|
||||
filter={filter}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const CommonFooterMarkItem = () => {
|
||||
const CommonFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
|
||||
return (
|
||||
<FlatMarkAllReadButton
|
||||
className="justify-start"
|
||||
buttonClassName="w-full rounded-none px-6 py-4"
|
||||
iconClassName="mr-1 text-base"
|
||||
which="above"
|
||||
filter={filter}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ const useRemoteEntries = (): UseEntriesReturn => {
|
|||
isFetching: query.isFetching,
|
||||
hasNextPage: query.hasNextPage,
|
||||
error: query.isError ? query.error : null,
|
||||
fetchedTime,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,14 @@ import { unreadSyncService } from "@follow/store/unread/store"
|
|||
|
||||
import { getGeneralSettings } from "~/atoms/settings/general"
|
||||
|
||||
export interface MarkAllFilter {
|
||||
startTime: number
|
||||
endTime: number
|
||||
}
|
||||
export type MarkAllFilter =
|
||||
| {
|
||||
startTime: number
|
||||
endTime: number
|
||||
}
|
||||
| {
|
||||
insertedBefore: number
|
||||
}
|
||||
|
||||
export const markAllByRoute = async (
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ function EntryColumnImpl() {
|
|||
fetchNextPage={fetchNextPage}
|
||||
refetch={entries.refetch}
|
||||
groupCounts={groupedCounts}
|
||||
Footer={<FooterMarkItem view={view} />}
|
||||
Footer={<FooterMarkItem view={view} fetchedTime={entries.fetchedTime} />}
|
||||
/>
|
||||
)}
|
||||
</EntryColumnWrapper>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { and, between, eq, inArray, or } from "drizzle-orm"
|
||||
import { and, between, eq, inArray, lt, or } from "drizzle-orm"
|
||||
|
||||
import { db } from "../db"
|
||||
import { entriesTable } from "../schemas"
|
||||
|
|
@ -11,6 +11,10 @@ interface PublishAtTimeRangeFilter {
|
|||
endTime: number
|
||||
}
|
||||
|
||||
interface InsertedBeforeTimeRangeFilter {
|
||||
insertedBefore: number
|
||||
}
|
||||
|
||||
class EntryServiceStatic implements Resetable {
|
||||
async reset() {
|
||||
await db.delete(entriesTable).execute()
|
||||
|
|
@ -40,7 +44,7 @@ class EntryServiceStatic implements Resetable {
|
|||
entry: Partial<EntrySchema>
|
||||
entryIds?: string[]
|
||||
feedIds?: string[]
|
||||
time?: PublishAtTimeRangeFilter
|
||||
time?: PublishAtTimeRangeFilter | InsertedBeforeTimeRangeFilter
|
||||
}) {
|
||||
if (!entryIds && !feedIds) return
|
||||
await db
|
||||
|
|
@ -49,9 +53,12 @@ class EntryServiceStatic implements Resetable {
|
|||
.where(
|
||||
and(
|
||||
or(inArray(entriesTable.id, entryIds ?? []), inArray(entriesTable.feedId, feedIds ?? [])),
|
||||
time
|
||||
time && "startTime" in time
|
||||
? between(entriesTable.publishedAt, new Date(time.startTime), new Date(time.endTime))
|
||||
: undefined,
|
||||
time && "insertedBefore" in time
|
||||
? lt(entriesTable.insertedAt, new Date(time.insertedBefore))
|
||||
: undefined,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19498,6 +19498,7 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
excludePrivate?: boolean | undefined;
|
||||
startTime?: number | undefined;
|
||||
endTime?: number | undefined;
|
||||
insertedBefore?: number | undefined;
|
||||
};
|
||||
};
|
||||
output: {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ import { honoMorph } from "../morph/hono"
|
|||
import { storeDbMorph } from "../morph/store-db"
|
||||
import { getSubscriptionById } from "../subscription/getter"
|
||||
import { getDefaultCategory } from "../subscription/utils"
|
||||
import type { FeedIdOrInboxHandle, PublishAtTimeRangeFilter } from "../unread/types"
|
||||
import type {
|
||||
FeedIdOrInboxHandle,
|
||||
InsertedBeforeTimeRangeFilter,
|
||||
PublishAtTimeRangeFilter,
|
||||
} from "../unread/types"
|
||||
import { whoami } from "../user/getters"
|
||||
import { userActions } from "../user/store"
|
||||
import { getEntry } from "./getter"
|
||||
|
|
@ -311,7 +315,7 @@ class EntryActions implements Hydratable, Resetable {
|
|||
entryIds?: EntryId[]
|
||||
ids?: FeedIdOrInboxHandle[]
|
||||
read: boolean
|
||||
time?: PublishAtTimeRangeFilter
|
||||
time?: PublishAtTimeRangeFilter | InsertedBeforeTimeRangeFilter
|
||||
}) {
|
||||
const affectedEntryIds = new Set<EntryId>()
|
||||
|
||||
|
|
@ -325,11 +329,19 @@ class EntryActions implements Hydratable, Resetable {
|
|||
|
||||
if (
|
||||
time &&
|
||||
"startTime" in time &&
|
||||
(+new Date(entry.publishedAt) < time.startTime ||
|
||||
+new Date(entry.publishedAt) > time.endTime)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
time &&
|
||||
"insertedBefore" in time &&
|
||||
+new Date(entry.insertedAt) >= time.insertedBefore
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (entry.read !== read) {
|
||||
entry.read = read
|
||||
|
|
@ -351,11 +363,19 @@ class EntryActions implements Hydratable, Resetable {
|
|||
for (const entry of entries) {
|
||||
if (
|
||||
time &&
|
||||
"startTime" in time &&
|
||||
(+new Date(entry.publishedAt) < time.startTime ||
|
||||
+new Date(entry.publishedAt) > time.endTime)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
time &&
|
||||
"insertedBefore" in time &&
|
||||
+new Date(entry.insertedAt) >= time.insertedBefore
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (entry.read !== read) {
|
||||
entry.read = read
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export type UseEntriesReturn = {
|
|||
isFetchingNextPage: boolean
|
||||
hasNextPage: boolean
|
||||
error: Error | null
|
||||
fetchedTime?: number
|
||||
}
|
||||
|
||||
export type UseEntriesControl = Pick<
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { getListFeedIds } from "../list/getters"
|
|||
import { getSubscribedFeedIdAndInboxHandlesByView } from "../subscription/getter"
|
||||
import type {
|
||||
FeedIdOrInboxHandle,
|
||||
InsertedBeforeTimeRangeFilter,
|
||||
PublishAtTimeRangeFilter,
|
||||
UnreadState,
|
||||
UnreadStoreModel,
|
||||
|
|
@ -43,7 +44,7 @@ class UnreadSyncService {
|
|||
request,
|
||||
}: {
|
||||
ids: FeedIdOrInboxHandle[]
|
||||
time?: PublishAtTimeRangeFilter
|
||||
time?: PublishAtTimeRangeFilter | InsertedBeforeTimeRangeFilter
|
||||
request: () => Promise<UnreadStoreModel>
|
||||
}) {
|
||||
if (!ids || ids.length === 0) return
|
||||
|
|
@ -116,7 +117,7 @@ class UnreadSyncService {
|
|||
feedIdList?: string[]
|
||||
inboxId?: string
|
||||
} | null
|
||||
time?: PublishAtTimeRangeFilter
|
||||
time?: PublishAtTimeRangeFilter | InsertedBeforeTimeRangeFilter
|
||||
excludePrivate: boolean
|
||||
}) {
|
||||
const request = async () => {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ export interface PublishAtTimeRangeFilter {
|
|||
endTime: number
|
||||
}
|
||||
|
||||
export interface InsertedBeforeTimeRangeFilter {
|
||||
insertedBefore: number
|
||||
}
|
||||
|
||||
export interface UnreadUpdateOptions {
|
||||
reset?: boolean
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue