refactor(dock): implement PollingManager for unread count updates, fixed #3891
- Removed redundant polling logic from DockService and replaced it with a PollingManager class to handle polling operations more efficiently. - Updated the setting-sync provider to utilize the new polling mechanism for managing dock badge updates. - Cleaned up unused setDockBadge method from SettingService. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
20d8590c58
commit
70255af458
|
|
@ -1,36 +1,78 @@
|
|||
import { UNREAD_BACKGROUND_POLLING_INTERVAL } from "../../constants/app"
|
||||
import { apiClient } from "../../lib/api-client"
|
||||
import { setDockCount } from "../../lib/dock"
|
||||
import { sleep } from "../../lib/utils"
|
||||
import type { IpcContext } from "../base"
|
||||
import { IpcMethod, IpcService } from "../base"
|
||||
|
||||
const pollingMap = {
|
||||
unread: false,
|
||||
class PollingManager {
|
||||
private abortController: AbortController | null = null
|
||||
private isPolling = false
|
||||
|
||||
async startPolling(pollingFn: () => Promise<void>, interval: number): Promise<void> {
|
||||
if (this.isPolling) {
|
||||
return // Already polling, prevent duplicate instances
|
||||
}
|
||||
|
||||
this.isPolling = true
|
||||
this.abortController = new AbortController()
|
||||
|
||||
try {
|
||||
while (!this.abortController.signal.aborted) {
|
||||
await pollingFn()
|
||||
|
||||
// Use AbortSignal with sleep for proper cancellation
|
||||
await this.sleepWithAbortSignal(interval, this.abortController.signal)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.name !== "AbortError") {
|
||||
console.error("Polling error:", error)
|
||||
}
|
||||
} finally {
|
||||
this.isPolling = false
|
||||
this.abortController = null
|
||||
}
|
||||
}
|
||||
|
||||
stopPolling(): void {
|
||||
if (this.abortController) {
|
||||
this.abortController.abort()
|
||||
}
|
||||
}
|
||||
|
||||
get active(): boolean {
|
||||
return this.isPolling
|
||||
}
|
||||
|
||||
private async sleepWithAbortSignal(ms: number, signal: AbortSignal): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeoutId = setTimeout(resolve, ms)
|
||||
|
||||
signal.addEventListener("abort", () => {
|
||||
clearTimeout(timeoutId)
|
||||
reject(new DOMException("Aborted", "AbortError"))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class DockService extends IpcService {
|
||||
private unreadPollingManager = new PollingManager()
|
||||
|
||||
constructor() {
|
||||
super("dock")
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async pollingUpdateUnreadCount(): Promise<void> {
|
||||
if (pollingMap.unread) {
|
||||
return
|
||||
}
|
||||
|
||||
pollingMap.unread = true
|
||||
while (pollingMap.unread) {
|
||||
await sleep(UNREAD_BACKGROUND_POLLING_INTERVAL)
|
||||
if (pollingMap.unread) {
|
||||
await this.updateUnreadCount()
|
||||
}
|
||||
}
|
||||
await this.unreadPollingManager.startPolling(
|
||||
() => this.updateUnreadCount(),
|
||||
UNREAD_BACKGROUND_POLLING_INTERVAL,
|
||||
)
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async cancelPollingUpdateUnreadCount(): Promise<void> {
|
||||
pollingMap.unread = false
|
||||
this.unreadPollingManager.stopPolling()
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
|
|
@ -38,4 +80,9 @@ export class DockService extends IpcService {
|
|||
const res = await apiClient.reads["total-count"].$get()
|
||||
setDockCount(res.data.count)
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
setDockBadge(_context: IpcContext, count: number): void {
|
||||
setDockCount(count)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { createRequire } from "node:module"
|
|||
|
||||
import { app, nativeTheme } from "electron"
|
||||
|
||||
import { setDockCount } from "../../lib/dock"
|
||||
import { setProxyConfig, updateProxy } from "../../lib/proxy"
|
||||
import { store } from "../../lib/store"
|
||||
import { getTrayConfig, setTrayConfig } from "../../lib/tray"
|
||||
|
|
@ -65,11 +64,6 @@ export class SettingService extends IpcService {
|
|||
setTrayConfig(minimize)
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
setDockBadge(_context: IpcContext, count: number): void {
|
||||
setDockCount(count)
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
getProxyConfig(_context: IpcContext) {
|
||||
const proxy = store.get("proxy")
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import type { Event } from "electron/main"
|
|||
import { START_IN_TRAY_ARGS } from "./constants/app"
|
||||
import { isMacOS, isWindows, isWindows11 } from "./env"
|
||||
import { filePathToAppUrl, getIconPath } from "./helper"
|
||||
import { services } from "./ipc"
|
||||
import { t } from "./lib/i18n"
|
||||
import { store } from "./lib/store"
|
||||
import { getTrayConfig } from "./lib/tray"
|
||||
|
|
@ -312,23 +311,6 @@ export const createMainWindow = () => {
|
|||
}
|
||||
})
|
||||
|
||||
window.on("show", () => {
|
||||
services.dock.pollingUpdateUnreadCount()
|
||||
|
||||
const caller = callWindowExpose(window)
|
||||
|
||||
caller.onWindowShow()
|
||||
})
|
||||
|
||||
window.on("hide", async () => {
|
||||
const caller = callWindowExpose(window)
|
||||
const settings = await caller.getUISettings()
|
||||
|
||||
if (settings?.showDockBadge) {
|
||||
services.dock.pollingUpdateUnreadCount()
|
||||
}
|
||||
})
|
||||
|
||||
return window
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { isMobile } from "@follow/components/hooks/useMobile.js"
|
||||
import { unreadActions } from "@follow/store/unread/store"
|
||||
import i18next from "i18next"
|
||||
import { useEffect, useInsertionEffect, useLayoutEffect } from "react"
|
||||
|
||||
|
|
@ -38,12 +37,11 @@ const useUISettingSync = () => {
|
|||
|
||||
useEffect(() => {
|
||||
if (setting.showDockBadge) {
|
||||
return unreadActions.subscribeUnreadCount(
|
||||
(count) => ipcServices?.setting.setDockBadge(count),
|
||||
true,
|
||||
)
|
||||
ipcServices?.dock.pollingUpdateUnreadCount()
|
||||
} else {
|
||||
ipcServices?.setting.setDockBadge(0)
|
||||
ipcServices?.dock.cancelPollingUpdateUnreadCount().then(() => {
|
||||
ipcServices?.dock.setDockBadge(0)
|
||||
})
|
||||
}
|
||||
return
|
||||
}, [setting.showDockBadge])
|
||||
|
|
|
|||
Loading…
Reference in New Issue