feat(dependencies): refactor ipc decorator

- Updated the version of electron-ipc-decorator in package.json files for both main and renderer processes to 0.2.0, ensuring compatibility with the latest features and improvements.
- Adjusted pnpm-lock.yaml to reflect the new version and its integrity hash.
- Refactored IPC service classes to utilize the new version, enhancing code organization and functionality.
- Removed deprecated constructor calls in IPC service classes, simplifying the implementation.

These changes improve dependency management and enhance the overall architecture of the IPC system.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-08-23 18:32:42 +08:00
parent 23664e6ceb
commit 0ede6fb2cd
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
17 changed files with 57 additions and 78 deletions

View File

@ -1,5 +1,2 @@
// Export types for renderer to use
export type { IpcServices } from "./src/ipc"
// Export services for potential main process use
export { services } from "./src/ipc"

View File

@ -30,7 +30,7 @@
"@sentry/electron": "6.8.0",
"builder-util-runtime": "9.3.1",
"electron-context-menu": "4.0.5",
"electron-ipc-decorator": "0.1.3",
"electron-ipc-decorator": "0.2.0",
"electron-log": "5.4.1",
"electron-squirrel-startup": "1.0.1",
"electron-store": "10.1.0",

View File

@ -1,4 +1,5 @@
import type { MergeIpcService } from "electron-ipc-decorator"
import { createServices } from "electron-ipc-decorator"
import { AppService } from "./services/app"
import { AuthService } from "./services/auth"
@ -10,17 +11,16 @@ import { ReaderService } from "./services/reader"
import { SettingService } from "./services/setting"
// Initialize all services
export const services = {
app: new AppService(),
auth: new AuthService(),
debug: new DebugService(),
dock: new DockService(),
menu: new MenuService(),
reader: new ReaderService(),
setting: new SettingService(),
integration: new IntegrationService(),
} as const
const services = createServices([
AppService,
AuthService,
DebugService,
DockService,
MenuService,
ReaderService,
SettingService,
IntegrationService,
])
// Extract method types automatically from services
export type IpcServices = MergeIpcService<typeof services>
@ -28,4 +28,5 @@ export type IpcServices = MergeIpcService<typeof services>
export function initializeIpcServices() {
// Services are already initialized in the services constant above
console.info("IPC services initialized")
void services
}

View File

@ -8,6 +8,7 @@ import type { IpcContext } from "electron-ipc-decorator"
import { IpcMethod, IpcService } from "electron-ipc-decorator"
import path from "pathe"
import { START_IN_TRAY_ARGS } from "~/constants/app"
import { getCacheSize } from "~/lib/cleaner"
import { i18n } from "~/lib/i18n"
import { store, StoreKey } from "~/lib/store"
@ -34,9 +35,7 @@ interface Sender extends Electron.WebContents {
}
export class AppService extends IpcService {
constructor() {
super("app")
}
static override readonly groupName = "app"
@IpcMethod()
getAppVersion(): string {
@ -183,6 +182,16 @@ export class AppService extends IpcService {
return path.join(app.getAppPath(), input)
}
@IpcMethod()
readyToShowMainWindow(_context: IpcContext) {
const shouldShowWindow =
!app.getLoginItemSettings().wasOpenedAsHidden && !process.argv.includes(START_IN_TRAY_ARGS)
if (shouldShowWindow) {
const window = WindowManager.getMainWindow()
if (window) window.show()
}
}
@IpcMethod()
openCacheFolder(_context: IpcContext): void {
const dir = path.join(app.getPath("userData"), "cache")
@ -217,22 +226,6 @@ export class AppService extends IpcService {
})
}
// getCacheLimit: t.procedure.action(async () => {
// return store.get(StoreKey.CacheSizeLimit)
// }),
// clearCache: t.procedure.action(async () => {
// }),
// limitCacheSize: t.procedure.input<number>().action(async ({ input }) => {
// logger.info("set limitCacheSize", input)
// if (input === 0) {
// store.delete(StoreKey.CacheSizeLimit)
// } else {
// store.set(StoreKey.CacheSizeLimit, input)
// }
// }),
@IpcMethod()
limitCacheSize(_context: IpcContext, input: number): void {
if (input === 0) {

View File

@ -4,9 +4,7 @@ import { IpcMethod, IpcService } from "electron-ipc-decorator"
import { deleteNotificationsToken, updateNotificationsToken } from "../../lib/user"
export class AuthService extends IpcService {
constructor() {
super("auth")
}
static override readonly groupName = "auth"
@IpcMethod()
async sessionChanged(_context: IpcContext): Promise<void> {

View File

@ -7,9 +7,7 @@ interface InspectElementInput {
}
export class DebugService extends IpcService {
constructor() {
super("debug")
}
static override readonly groupName = "debug"
@IpcMethod()
inspectElement(context: IpcContext, input: InspectElementInput): void {

View File

@ -59,9 +59,7 @@ class PollingManager {
export class DockService extends IpcService {
private unreadPollingManager = new PollingManager()
constructor() {
super("dock")
}
static override readonly groupName = "dock"
@IpcMethod()
async pollingUpdateUnreadCount(): Promise<void> {

View File

@ -54,9 +54,7 @@ interface CustomFetchInput {
}
export class IntegrationService extends IpcService {
constructor() {
super("integration")
}
static override readonly groupName = "integration"
@IpcMethod()
async saveToObsidian(

View File

@ -18,9 +18,7 @@ interface ShowConfirmDialogInput {
}
export class MenuService extends IpcService {
constructor() {
super("menu")
}
static override readonly groupName = "menu"
private normalizeMenuItems(
items: SerializableMenuItem[],

View File

@ -29,9 +29,7 @@ interface DetectCodeStringLanguageInput {
}
export class ReaderService extends IpcService {
constructor() {
super("reader")
}
static override readonly groupName = "reader"
@IpcMethod()
async readability(_context: IpcContext, input: ReadabilityInput) {

View File

@ -20,9 +20,7 @@ interface SetLoginItemSettingsInput {
}
export class SettingService extends IpcService {
constructor() {
super("setting")
}
static override readonly groupName = "setting"
@IpcMethod()
getLoginItemSettings(_context: IpcContext): Electron.LoginItemSettings {

View File

@ -5,11 +5,10 @@ import { LEGACY_APP_PROTOCOL } from "@follow/shared"
import { callWindowExpose, WindowState } from "@follow/shared/bridge"
import { APP_PROTOCOL, DEV } from "@follow/shared/constants"
import type { BrowserWindowConstructorOptions } from "electron"
import { app, BrowserWindow, screen, shell } from "electron"
import { BrowserWindow, screen, shell } from "electron"
import type { Event } from "electron/main"
import path from "pathe"
import { START_IN_TRAY_ARGS } from "~/constants/app"
import { isMacOS, isWindows, isWindows11 } from "~/env"
import { filePathToAppUrl, getIconPath } from "~/helper"
import { t } from "~/lib/i18n"
@ -83,12 +82,6 @@ class WindowManagerStatic {
refreshBound(window, this.config.refreshBoundDelay)
})
window.on("ready-to-show", () => {
const shouldShowWindow =
!app.getLoginItemSettings().wasOpenedAsHidden && !process.argv.includes(START_IN_TRAY_ARGS)
if (shouldShowWindow) window.show()
})
window.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: "deny" }

View File

@ -59,7 +59,7 @@
"cookie-es": "2.0.0",
"dayjs": "1.11.13",
"dnum": "2.15.0",
"electron-ipc-decorator": "0.1.3",
"electron-ipc-decorator": "0.2.0",
"embla-carousel-react": "8.6.0",
"embla-carousel-wheel-gestures": "8.0.2",
"es-toolkit": "1.39.6",

View File

@ -1,14 +1,16 @@
import { isMobile } from "@follow/components/hooks/useMobile.js"
import { IN_ELECTRON } from "@follow/shared/constants"
import { tracker } from "@follow/tracker"
import { nextFrame } from "@follow/utils"
import { cn, getOS } from "@follow/utils/utils"
import { useEffect } from "react"
import { useEffect, useLayoutEffect, useRef } from "react"
import { Outlet } from "react-router"
import { useAppIsReady } from "./atoms/app"
import { useUISettingKey } from "./atoms/settings/ui"
import { applyAfterReadyCallbacks } from "./initialize/queue"
import { removeAppSkeleton } from "./lib/app"
import { ipcServices } from "./lib/client"
import { appLog } from "./lib/log"
import { Titlebar } from "./modules/app/Titlebar"
import { RootProviders } from "./providers/root-providers"
@ -37,13 +39,19 @@ function App() {
const AppLayer = () => {
const appIsReady = useAppIsReady()
useEffect(() => {
removeAppSkeleton()
const onceReady = useRef(false)
useLayoutEffect(() => {
if (appIsReady && !onceReady.current) {
onceReady.current = true
ipcServices?.app.readyToShowMainWindow()
nextFrame(removeAppSkeleton)
}
}, [appIsReady])
useEffect(() => {
const doneTime = Math.trunc(performance.now())
tracker.uiRenderInit(doneTime)
appLog("App is ready", `${doneTime}ms`)
applyAfterReadyCallbacks()
if (isMobile()) {

View File

@ -79,8 +79,7 @@ export const loadLanguageAndApply = async (lang: string) => {
if (IN_ELECTRON) {
importFilePath =
(await (ipcServices as any)?.app.resolveAppAsarPath(`dist/renderer/locales/${lang}.js`)) ||
""
(await ipcServices?.app.resolveAppAsarPath(`dist/renderer/locales/${lang}.js`)) || ""
} else {
importFilePath = `/locales/${lang}.js`
}

View File

@ -11,6 +11,7 @@ import {
} from "@follow/store/context"
import { getOS } from "@follow/utils/utils"
import * as React from "react"
import { flushSync } from "react-dom"
import ReactDOM from "react-dom/client"
import { RouterProvider } from "react-router/dom"
@ -37,7 +38,8 @@ initializeApp().finally(() => {
}
})
setAppIsReady(true)
// eslint-disable-next-line @eslint-react/dom/no-flush-sync
flushSync(() => setAppIsReady(true))
})
const $container = document.querySelector("#root") as HTMLElement

View File

@ -373,8 +373,8 @@ importers:
specifier: 4.0.5
version: 4.0.5(patch_hash=15ed04a0d246eb9e701f47314b91328c64a8a7374914ad58b4053a3f84075fab)
electron-ipc-decorator:
specifier: 0.1.3
version: 0.1.3(electron@37.2.0)
specifier: 0.2.0
version: 0.2.0(electron@37.2.0)
electron-log:
specifier: 5.4.1
version: 5.4.1
@ -596,8 +596,8 @@ importers:
specifier: 2.15.0
version: 2.15.0
electron-ipc-decorator:
specifier: 0.1.3
version: 0.1.3(electron@37.2.0)
specifier: 0.2.0
version: 0.2.0(electron@37.2.0)
embla-carousel-react:
specifier: 8.6.0
version: 8.6.0(react@19.0.0)
@ -8757,8 +8757,8 @@ packages:
engines: {node: '>= 16'}
hasBin: true
electron-ipc-decorator@0.1.3:
resolution: {integrity: sha512-rMmWUc6OFuIXw+e5DEAIsgU0leC+kJ2ibVEwzRDEjxuQvAqsaZJztFrbtUS44kDdIQriRId0lFKYlDJAMm3yhQ==}
electron-ipc-decorator@0.2.0:
resolution: {integrity: sha512-7020pQ/8qdm+CkVQRQG1A0zhWERI4OFyCnULtcPFv4JJRE1rwfBKrKwWIxsoeFpjBEGEV1M7Ms5FGt2jLrMY5g==}
engines: {node: '>=18.0.0'}
peerDependencies:
electron: '>=32.0.0'
@ -24728,7 +24728,7 @@ snapshots:
- supports-color
optional: true
electron-ipc-decorator@0.1.3(electron@37.2.0):
electron-ipc-decorator@0.2.0(electron@37.2.0):
dependencies:
electron: 37.2.0