Skip to content

Commit

Permalink
feat: feed unread persist to db (#106)
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei authored Jul 3, 2024
1 parent 9da2365 commit 781c174
Show file tree
Hide file tree
Showing 26 changed files with 183 additions and 106 deletions.
41 changes: 25 additions & 16 deletions src/renderer/src/database/db.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import type { Transaction } from "dexie"
import Dexie from "dexie"

import { LOCAL_DB_NAME } from "./constants"
import {
dbSchemaV1,
} from "./db_schema"
import type { DB_Entry } from "./schemas/entry"
import { dbSchemaV1, dbSchemaV2 } from "./db_schema"
import type { DB_Base } from "./schemas/base"
import type { DB_FeedId } from "./schemas/feed"
import type { DBModel } from "./types"

export interface LobeDBSchemaMap {

entries: DB_Entry
// TODO - Add more schemas here
feeds: DB_Entry
subscriptions: DB_Entry
entryRelated: DB_Entry
feedEntries: DB_Entry
export interface LocalDBSchemaMap {
entries: DB_Base
feeds: DB_Base
subscriptions: DB_Base
entryRelated: DB_Base
feedEntries: DB_FeedId
feedUnreads: DB_FeedId
}

// Define a local DB
Expand All @@ -24,16 +23,25 @@ export class BrowserDB extends Dexie {
public subscriptions: BrowserDBTable<"subscriptions">
public entryRelated: BrowserDBTable<"entryRelated">
public feedEntries: BrowserDBTable<"feedEntries">
public feedUnreads: BrowserDBTable<"feedUnreads">

constructor() {
super(LOCAL_DB_NAME)
this.version(1).stores(dbSchemaV1)
this.version(2).stores(dbSchemaV2)
.upgrade(this.upgradeToV2)

this.entries = this.table("entries")
this.feeds = this.table("feeds")
this.subscriptions = this.table("subscriptions")
this.entryRelated = this.table("entryRelated")
this.feedEntries = this.table("feedEntries")
this.feedUnreads = this.table("feedUnreads")
}

async upgradeToV2(trans: Transaction) {
const session = trans.table("feedUnreads")
session.delete("feedId")
}
}

Expand All @@ -47,9 +55,10 @@ export const browserDB = new BrowserDB()

// types helper
export type BrowserDBSchema = {
[t in keyof LobeDBSchemaMap]: {
model: LobeDBSchemaMap[t]
table: Dexie.Table<DBModel<LobeDBSchemaMap[t]>, string>
[t in keyof LocalDBSchemaMap]: {
model: LocalDBSchemaMap[t]
table: Dexie.Table<DBModel<LocalDBSchemaMap[t]>, string>
};
}
type BrowserDBTable<T extends keyof LobeDBSchemaMap> = BrowserDBSchema[T]["table"]
type BrowserDBTable<T extends keyof LocalDBSchemaMap> =
BrowserDBSchema[T]["table"]
6 changes: 6 additions & 0 deletions src/renderer/src/database/db_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ export const dbSchemaV1 = {
subscriptions: "&id",
entryRelated: "&id",
feedEntries: "&feedId",
feedUnreads: "&id",
}

export const dbSchemaV2 = {
...dbSchemaV1,
subscriptions: "&id, userId, feedId",
}
4 changes: 2 additions & 2 deletions src/renderer/src/database/models/entry-related.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BaseModel } from "../model"
import { DB_EntrySchema } from "../schemas"
import { DB_BaseSchema } from "../schemas"

class ModelStatic extends BaseModel<"entryRelated"> {
constructor() {
super("entryRelated", DB_EntrySchema)
super("entryRelated", DB_BaseSchema)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/database/models/entry.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BaseModel } from "../model"
import { DB_EntrySchema } from "../schemas"
import { DB_BaseSchema } from "../schemas"

class EntryModelStatic extends BaseModel<"entries"> {
constructor() {
super("entries", DB_EntrySchema)
super("entries", DB_BaseSchema)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/database/models/feed-entry.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BaseModel } from "../model"
import { DB_EntrySchema } from "../schemas"
import { DB_BaseSchema } from "../schemas"

class ModelStatic extends BaseModel<"feedEntries"> {
constructor() {
super("feedEntries", DB_EntrySchema)
super("feedEntries", DB_BaseSchema)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/database/models/feed.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BaseModel } from "../model"
import { DB_EntrySchema } from "../schemas"
import { DB_BaseSchema } from "../schemas"

class ModelStatic extends BaseModel<"feeds"> {
constructor() {
super("feeds", DB_EntrySchema)
super("feeds", DB_BaseSchema)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/database/models/subscription.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BaseModel } from "../model"
import { DB_EntrySchema } from "../schemas"
import { DB_BaseSchema } from "../schemas"

class ModelStatic extends BaseModel<"subscriptions"> {
constructor() {
super("subscriptions", DB_EntrySchema)
super("subscriptions", DB_BaseSchema)
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/renderer/src/database/models/unread.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BaseModel } from "../model"
import { DB_BaseSchema } from "../schemas"

class ModelStatic extends BaseModel<"feedUnreads"> {
constructor() {
super("feedUnreads", DB_BaseSchema)
}
}

export const feedUnreadModel = new ModelStatic()
7 changes: 7 additions & 0 deletions src/renderer/src/database/schemas/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { z } from "zod"

export const DB_BaseSchema = z.object({
id: z.string(),
})

export type DB_Base = z.infer<typeof DB_BaseSchema>
7 changes: 0 additions & 7 deletions src/renderer/src/database/schemas/entry.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/renderer/src/database/schemas/feed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { z } from "zod"

export const DB_FeedIdSchema = z.object({
feedId: z.string(),
})

export type DB_FeedId = z.infer<typeof DB_FeedIdSchema>
3 changes: 2 additions & 1 deletion src/renderer/src/database/schemas/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./entry"
export * from "./base"
export * from "./feed"
6 changes: 3 additions & 3 deletions src/renderer/src/hooks/biz/useSubscriptionActions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { apiClient } from "@renderer/lib/api-fetch"
import { Queries } from "@renderer/queries"
import type { SubscriptionPlainModel } from "@renderer/store"
import { getFeedById, unreadActions } from "@renderer/store"
import { feedUnreadActions, getFeedById } from "@renderer/store"
import { useMutation } from "@tanstack/react-query"
import { toast } from "sonner"

Expand All @@ -19,7 +19,7 @@ export const useDeleteSubscription = ({

onSuccess: (_, variables) => {
Queries.subscription.byView(variables.view).invalidate()
unreadActions.updateByFeedId(variables.feedId, 0)
feedUnreadActions.updateByFeedId(variables.feedId, 0)

const feed = getFeedById(variables.feedId)

Expand Down Expand Up @@ -48,7 +48,7 @@ export const useDeleteSubscription = ({
})

Queries.subscription.byView(variables.view).invalidate()
unreadActions.fetchUnreadByView(variables.view)
feedUnreadActions.fetchUnreadByView(variables.view)
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/modules/discover/feed-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { FeedViewType } from "@renderer/lib/enum"
import { cn } from "@renderer/lib/utils"
import { Queries } from "@renderer/queries"
import { useFeed } from "@renderer/queries/feed"
import { unreadActions } from "@renderer/store"
import { feedUnreadActions } from "@renderer/store"
import { useMutation } from "@tanstack/react-query"
import { useEffect, useRef } from "react"
import { useForm } from "react-hook-form"
Expand Down Expand Up @@ -106,13 +106,13 @@ export const FeedForm: Component<{
tipcClient?.invalidateQuery(
Queries.subscription.byView(feed.data?.subscription?.view).key,
)
unreadActions.fetchUnreadByView(feed.data?.subscription?.view)
feedUnreadActions.fetchUnreadByView(feed.data?.subscription?.view)
}
Queries.subscription.byView(Number.parseInt(variables.view)).invalidate()
tipcClient?.invalidateQuery(
Queries.subscription.byView(Number.parseInt(variables.view)).key,
)
unreadActions.fetchUnreadByView(Number.parseInt(variables.view))
feedUnreadActions.fetchUnreadByView(Number.parseInt(variables.view))

const feedId = feed.data?.feed.id
if (feedId) {
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/modules/feed-column/category.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { stopPropagation } from "@renderer/lib/dom"
import { showNativeMenu } from "@renderer/lib/native-menu"
import { cn } from "@renderer/lib/utils"
import type { FeedListModel } from "@renderer/models"
import { useUnreadStore } from "@renderer/store"
import { useFeedUnreadStore } from "@renderer/store"
import { AnimatePresence, m } from "framer-motion"
import { memo, useEffect, useState } from "react"

Expand Down Expand Up @@ -56,11 +56,11 @@ function FeedCategoryImpl({
}
}

const unread = useUnreadStore((state) =>
const unread = useFeedUnreadStore((state) =>
data.list.reduce((acc, cur) => (state.data[cur.feedId] || 0) + acc, 0),
)

const sortByUnreadFeedList = useUnreadStore((state) =>
const sortByUnreadFeedList = useFeedUnreadStore((state) =>
data.list.sort(
(a, b) => (state.data[b.feedId] || 0) - (state.data[a.feedId] || 0),
),
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/modules/feed-column/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { nextFrame } from "@renderer/lib/dom"
import { showNativeMenu } from "@renderer/lib/native-menu"
import { cn } from "@renderer/lib/utils"
import type { SubscriptionPlainModel } from "@renderer/store"
import { getFeedById, useFeedById, useUnreadStore } from "@renderer/store"
import { getFeedById, useFeedById, useFeedUnreadStore } from "@renderer/store"
import { WEB_URL } from "@shared/constants"
import { memo, useCallback } from "react"

Expand Down Expand Up @@ -60,7 +60,7 @@ const FeedItemImpl = ({

const deleteSubscription = useDeleteSubscription({})

const feedUnread = useUnreadStore(
const feedUnread = useFeedUnreadStore(
(state) => state.data[subscription.feedId] || 0,
)
const { present } = useModalStack()
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/modules/feed-column/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { Queries } from "@renderer/queries"
import type { SubscriptionPlainModel } from "@renderer/store"
import {
getFeedById,
useFeedUnreadStore,
useSubscriptionByView,
useUnreadStore,
} from "@renderer/store"
import { useMemo, useState } from "react"
import { Link } from "react-router-dom"
Expand Down Expand Up @@ -103,7 +103,7 @@ export function FeedList({

useAuthQuery(Queries.subscription.unreadAll())

const totalUnread = useUnreadStore((state) => {
const totalUnread = useFeedUnreadStore((state) => {
let unread = 0
data?.list.forEach((a) => {
a.list.forEach((b) => {
Expand All @@ -113,7 +113,7 @@ export function FeedList({
return unread
})

const sortedByUnread = useUnreadStore((state) =>
const sortedByUnread = useFeedUnreadStore((state) =>
data?.list?.sort(
(a, b) =>
b.list.reduce((acc, cur) => (state.data[cur.feedId] || 0) + acc, 0) -
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/providers/ui-setting-Initialize.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { initializeDefaultUISettings, useUISettingValue } from "@renderer/atoms"
import { tipcClient } from "@renderer/lib/client"
import { unreadActions } from "@renderer/store"
import { feedUnreadActions } from "@renderer/store"
import { useEffect, useInsertionEffect } from "react"

initializeDefaultUISettings()
Expand All @@ -14,7 +14,7 @@ export const UISettingInitialize = () => {

useEffect(() => {
if (state.showDockBadge) {
return unreadActions.subscribeUnreadCount((count) => tipcClient?.setMacOSBadge(count), true)
return feedUnreadActions.subscribeUnreadCount((count) => tipcClient?.setMacOSBadge(count), true)
} else {
tipcClient?.setMacOSBadge(0)
}
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/queries/subscriptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { apiClient } from "@renderer/lib/api-fetch"
import { defineQuery } from "@renderer/lib/defineQuery"
import type { FeedViewType } from "@renderer/lib/enum"
import { subscriptionActions, unreadActions } from "@renderer/store"
import { feedUnreadActions, subscriptionActions } from "@renderer/store"

export const subscription = {
byView: (view?: FeedViewType) =>
Expand All @@ -22,5 +22,5 @@ export const subscription = {
}),

unreadAll: () =>
defineQuery(["unread-all"], async () => unreadActions.fetchUnreadAll()),
defineQuery(["unread-all"], async () => feedUnreadActions.fetchUnreadAll()),
}
24 changes: 24 additions & 0 deletions src/renderer/src/services/feed-unread.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { feedUnreadModel } from "@renderer/database/models/unread"

class ServiceStatic {
updateFeedUnread(list: [string, number][]) {
return feedUnreadModel.table.bulkPut(
list.map(([feedId, count]) => ({ id: feedId, count })),
)
}

getAll() {
return feedUnreadModel.table.toArray() as Promise<
{
id: string
count: number
}[]
>
}

clear() {
return feedUnreadModel.table.clear()
}
}

export const FeedUnreadService = new ServiceStatic()
1 change: 1 addition & 0 deletions src/renderer/src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from "./entry"
export * from "./entry-related"
export * from "./feed"
export * from "./feed-entry"
export * from "./feed-unread"
export * from "./subscription"
6 changes: 3 additions & 3 deletions src/renderer/src/store/entry/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { produce } from "immer"
import { merge, omit } from "lodash-es"

import { feedActions } from "../feed"
import { unreadActions } from "../unread"
import { feedUnreadActions } from "../unread"
import { createZustandStore, getStoreActions } from "../utils/helper"
import { isHydrated } from "../utils/hydrate"
import type { EntryActions, EntryState } from "./types"
Expand Down Expand Up @@ -187,7 +187,7 @@ export const useEntryStore = createZustandStore<EntryState & EntryActions>(
},

markRead: (feedId: string, entryId: string, read: boolean) => {
unreadActions.incrementByFeedId(feedId, read ? -1 : 1)
feedUnreadActions.incrementByFeedId(feedId, read ? -1 : 1)
entryActions.patch(entryId, {
read,
})
Expand All @@ -198,7 +198,7 @@ export const useEntryStore = createZustandStore<EntryState & EntryActions>(
entries.forEach((entryId) => {
entryActions.markRead(feedId, entryId, true)
})
unreadActions.updateByFeedId(feedId, 0)
feedUnreadActions.updateByFeedId(feedId, 0)
},

markStar: (entryId, star) => {
Expand Down
Loading

0 comments on commit 781c174

Please sign in to comment.