diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/components/FooterMarkItem.tsx b/apps/desktop/layer/renderer/src/modules/entry-column/components/FooterMarkItem.tsx
index fc0cabea8..e8d3c7c7a 100644
--- a/apps/desktop/layer/renderer/src/modules/entry-column/components/FooterMarkItem.tsx
+++ b/apps/desktop/layer/renderer/src/modules/entry-column/components/FooterMarkItem.tsx
@@ -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
+ return
} else if (views[view]!.gridMode) {
- return
+ return
}
- return
+ return
}
-const SocialMediaFooterMarkItem = () => {
+interface FooterMarkItemProps {
+ filter?: {
+ insertedBefore: number
+ }
+}
+
+const SocialMediaFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
return (
{
buttonClassName="w-[645px] mx-auto mb-4 pl-7 py-4"
iconClassName="mr-1 text-lg"
which="above"
+ filter={filter}
/>
)
}
-const GridFooterMarkItem = () => {
+const GridFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
return (
)
}
-const CommonFooterMarkItem = () => {
+const CommonFooterMarkItem = ({ filter }: FooterMarkItemProps) => {
return (
)
}
diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useEntriesByView.ts b/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useEntriesByView.ts
index b373f6479..8cd81de7a 100644
--- a/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useEntriesByView.ts
+++ b/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useEntriesByView.ts
@@ -123,6 +123,7 @@ const useRemoteEntries = (): UseEntriesReturn => {
isFetching: query.isFetching,
hasNextPage: query.hasNextPage,
error: query.isError ? query.error : null,
+ fetchedTime,
}
}
diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useMarkAll.ts b/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useMarkAll.ts
index cfe02bafb..324689bf2 100644
--- a/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useMarkAll.ts
+++ b/apps/desktop/layer/renderer/src/modules/entry-column/hooks/useMarkAll.ts
@@ -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: {
diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/index.tsx b/apps/desktop/layer/renderer/src/modules/entry-column/index.tsx
index 46bbd697a..2aa3f6a88 100644
--- a/apps/desktop/layer/renderer/src/modules/entry-column/index.tsx
+++ b/apps/desktop/layer/renderer/src/modules/entry-column/index.tsx
@@ -165,7 +165,7 @@ function EntryColumnImpl() {
fetchNextPage={fetchNextPage}
refetch={entries.refetch}
groupCounts={groupedCounts}
- Footer={}
+ Footer={}
/>
)}
diff --git a/packages/internal/database/src/services/entry.ts b/packages/internal/database/src/services/entry.ts
index eb8495f87..fabaa337b 100644
--- a/packages/internal/database/src/services/entry.ts
+++ b/packages/internal/database/src/services/entry.ts
@@ -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
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,
),
)
}
diff --git a/packages/internal/shared/src/hono.ts b/packages/internal/shared/src/hono.ts
index ab141adda..3009379e7 100644
--- a/packages/internal/shared/src/hono.ts
+++ b/packages/internal/shared/src/hono.ts
@@ -19498,6 +19498,7 @@ declare const _routes: hono_hono_base.HonoBase()
@@ -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
diff --git a/packages/internal/store/src/entry/types.ts b/packages/internal/store/src/entry/types.ts
index 7a60b5a5e..69d4a85bd 100644
--- a/packages/internal/store/src/entry/types.ts
+++ b/packages/internal/store/src/entry/types.ts
@@ -38,6 +38,7 @@ export type UseEntriesReturn = {
isFetchingNextPage: boolean
hasNextPage: boolean
error: Error | null
+ fetchedTime?: number
}
export type UseEntriesControl = Pick<
diff --git a/packages/internal/store/src/unread/store.ts b/packages/internal/store/src/unread/store.ts
index 2a3044b94..4ef2c44a1 100644
--- a/packages/internal/store/src/unread/store.ts
+++ b/packages/internal/store/src/unread/store.ts
@@ -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
}) {
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 () => {
diff --git a/packages/internal/store/src/unread/types.ts b/packages/internal/store/src/unread/types.ts
index 9bd1214e6..ba1ffacac 100644
--- a/packages/internal/store/src/unread/types.ts
+++ b/packages/internal/store/src/unread/types.ts
@@ -3,6 +3,10 @@ export interface PublishAtTimeRangeFilter {
endTime: number
}
+export interface InsertedBeforeTimeRangeFilter {
+ insertedBefore: number
+}
+
export interface UnreadUpdateOptions {
reset?: boolean
}