diff --git a/apps/mobile/app/components/paywall/index.tsx b/apps/mobile/app/components/paywall/index.tsx index 8a7d7b624..90f046c88 100644 --- a/apps/mobile/app/components/paywall/index.tsx +++ b/apps/mobile/app/components/paywall/index.tsx @@ -76,6 +76,7 @@ import { IconButton } from "../ui/icon-button"; import { SvgView } from "../ui/svg"; import Heading from "../ui/typography/heading"; import Paragraph from "../ui/typography/paragraph"; +import { db } from "../../common/database"; const Steps = { select: 1, @@ -139,7 +140,7 @@ const PayWall = (props: NavigationProps<"PayWall">) => { }, [isFocused, step]); useEffect(() => { - const sub = EV.subscribe( + const sub = db.eventManager.subscribe( EVENTS.userSubscriptionUpdated, (sub: User["subscription"]) => { if (sub.plan === SubscriptionPlan.FREE) return; @@ -1006,8 +1007,8 @@ const PricingPlanCard = ({ : "monthly" }` : pricingPlans.isGithubRelease - ? (WebPlan?.period as string) - : (product?.productId as string) + ? (WebPlan?.period as string) + : (product?.productId as string) ); setStep(Steps.buy); }} diff --git a/apps/mobile/app/hooks/use-app-events.tsx b/apps/mobile/app/hooks/use-app-events.tsx index 4dba33602..8ef5be143 100644 --- a/apps/mobile/app/hooks/use-app-events.tsx +++ b/apps/mobile/app/hooks/use-app-events.tsx @@ -722,24 +722,39 @@ export const useAppEvents = () => { useEffect(() => { const subscriptions = [ - EV.subscribe(EVENTS.syncCheckStatus, onCheckSyncStatus), - EV.subscribe(EVENTS.syncAborted, onSyncAborted), - EV.subscribe(EVENTS.appRefreshRequested, onSyncComplete), + db.eventManager.subscribe(EVENTS.syncCheckStatus, onCheckSyncStatus), + db.eventManager.subscribe(EVENTS.syncAborted, onSyncAborted), + db.eventManager.subscribe(EVENTS.appRefreshRequested, onSyncComplete), db.eventManager.subscribe(EVENTS.userLoggedOut, onLogout), db.eventManager.subscribe(EVENTS.userEmailConfirmed, onUserEmailVerified), - EV.subscribe(EVENTS.userSessionExpired, onUserSessionExpired), + db.eventManager.subscribe( + EVENTS.userSessionExpired, + onUserSessionExpired + ), db.eventManager.subscribe( EVENTS.userSubscriptionUpdated, onUserSubscriptionStatusChanged ), - EV.subscribe(EVENTS.fileDownload, onDownloadingAttachmentProgress), - EV.subscribe(EVENTS.fileUpload, onUploadingAttachmentProgress), - EV.subscribe(EVENTS.fileDownloaded, onDownloadedAttachmentProgress), - EV.subscribe(EVENTS.fileUploaded, onUploadedAttachmentProgress), - EV.subscribe(EVENTS.downloadCanceled, (data) => { + db.eventManager.subscribe( + EVENTS.fileDownload, + onDownloadingAttachmentProgress + ), + db.eventManager.subscribe( + EVENTS.fileUpload, + onUploadingAttachmentProgress + ), + db.eventManager.subscribe( + EVENTS.fileDownloaded, + onDownloadedAttachmentProgress + ), + db.eventManager.subscribe( + EVENTS.fileUploaded, + onUploadedAttachmentProgress + ), + db.eventManager.subscribe(EVENTS.downloadCanceled, (data) => { useAttachmentStore.getState().setDownloading(data); }), - EV.subscribe(EVENTS.uploadCanceled, (data) => { + db.eventManager.subscribe(EVENTS.uploadCanceled, (data) => { useAttachmentStore.getState().setUploading(data); }), EV.subscribe(EVENTS.migrationStarted, (name) => { @@ -765,7 +780,7 @@ export const useAppEvents = () => { return; endProgress(); }), - EV.subscribe(EVENTS.vaultLocked, async () => { + db.eventManager.subscribe(EVENTS.vaultLocked, async () => { // Lock all notes in all tabs... for (const tab of useTabStore.getState().tabs) { const noteId = useTabStore.getState().getTab(tab.id)?.session?.noteId; @@ -797,7 +812,6 @@ export const useAppEvents = () => { return () => { emitterSubscriptions.forEach((sub) => sub?.remove?.()); subscriptions.forEach((sub) => sub?.unsubscribe?.()); - EV.unsubscribeAll(); }; }, [onSyncComplete, onUserUpdated]); diff --git a/apps/mobile/app/hooks/use-sync-progress.ts b/apps/mobile/app/hooks/use-sync-progress.ts index 79e22fdaf..948fd212b 100644 --- a/apps/mobile/app/hooks/use-sync-progress.ts +++ b/apps/mobile/app/hooks/use-sync-progress.ts @@ -29,7 +29,6 @@ export type SyncProgressEventType = { const useSyncProgress = () => { const [progress, setProgress] = useState(); - const EV = db.eventManager; const onProgress = useCallback( ({ type, current, total }: SyncProgressEventType) => { @@ -42,13 +41,13 @@ const useSyncProgress = () => { setProgress(undefined); }; useEffect(() => { - EV?.subscribe(EVENTS.syncProgress, onProgress); - EV?.subscribe(EVENTS.syncCompleted, onSyncComplete); + db.eventManager.subscribe(EVENTS.syncProgress, onProgress); + db.eventManager.subscribe(EVENTS.syncCompleted, onSyncComplete); return () => { - EV?.unsubscribe(EVENTS.syncProgress, onProgress); - EV?.unsubscribe(EVENTS.syncCompleted, onSyncComplete); + db.eventManager.unsubscribe(EVENTS.syncProgress, onProgress); + db.eventManager.unsubscribe(EVENTS.syncCompleted, onSyncComplete); }; - }, [EV, onProgress]); + }, [onProgress]); return { progress diff --git a/apps/web/src/app-effects.tsx b/apps/web/src/app-effects.tsx index faeafac5e..95cb29922 100644 --- a/apps/web/src/app-effects.tsx +++ b/apps/web/src/app-effects.tsx @@ -31,7 +31,7 @@ import { } from "./common"; import { AppEventManager, AppEvents } from "./common/app-events"; import { db } from "./common/db"; -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; import { registerKeyMap } from "./common/key-map"; import { updateStatus, removeStatus, getStatus } from "./hooks/use-status"; import { hashNavigate } from "./navigation"; @@ -113,7 +113,7 @@ export default function AppEffects() { } } - const fileDownloadEvents = EV.subscribeMulti( + const fileDownloadEvents = db.eventManager.subscribeMulti( [EVENTS.fileDownloaded, EVENTS.fileDownload], ({ total, current }: { total: number; current: number }) => { handleDownloadUploadProgress("download", total, current); @@ -121,7 +121,7 @@ export default function AppEffects() { null ); - const fileUploadEvents = EV.subscribeMulti( + const fileUploadEvents = db.eventManager.subscribeMulti( [EVENTS.fileUploaded, EVENTS.fileUpload], ({ total, current }: { total: number; current: number }) => { handleDownloadUploadProgress("upload", total, current); diff --git a/apps/web/src/components/editor/tiptap.tsx b/apps/web/src/components/editor/tiptap.tsx index 8dee809a6..3c0abc1b2 100644 --- a/apps/web/src/components/editor/tiptap.tsx +++ b/apps/web/src/components/editor/tiptap.tsx @@ -68,7 +68,6 @@ import { showFeatureNotAllowedToast } from "../../common/toasts"; import { UpgradeDialog } from "../../dialogs/buy-dialog/upgrade-dialog"; import { ConfirmDialog } from "../../dialogs/confirm"; import { strings } from "@notesnook/intl"; -import { AppEventManager, AppEvents } from "../../common/app-events"; export type OnChangeHandler = ( content: () => string, diff --git a/apps/web/src/components/publish-view/index.tsx b/apps/web/src/components/publish-view/index.tsx index bd7bc8610..605df4a26 100644 --- a/apps/web/src/components/publish-view/index.tsx +++ b/apps/web/src/components/publish-view/index.tsx @@ -23,7 +23,7 @@ import { Loading, Refresh } from "../icons"; import { db } from "../../common/db"; import { writeText } from "clipboard-polyfill"; import { showToast } from "../../utils/toast"; -import { EV, EVENTS, hosts, MonographAnalytics } from "@notesnook/core"; +import { EVENTS, hosts } from "@notesnook/core"; import { useStore } from "../../stores/monograph-store"; import { Note } from "@notesnook/core"; import { strings } from "@notesnook/intl"; @@ -67,7 +67,7 @@ function PublishView(props: PublishViewProps) { }, [monograph?.id, monographAnalytics]); useEffect(() => { - const fileDownloadedEvent = EV.subscribe( + const fileDownloadedEvent = db.eventManager.subscribe( EVENTS.fileDownloaded, ({ total, current, groupId }) => { if (!groupId || !groupId.includes(note.id)) return; diff --git a/apps/web/src/hooks/use-vault.ts b/apps/web/src/hooks/use-vault.ts index f18292c63..b3656b687 100644 --- a/apps/web/src/hooks/use-vault.ts +++ b/apps/web/src/hooks/use-vault.ts @@ -1,4 +1,4 @@ -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; import { useEffect, useState } from "react"; import Vault from "../common/vault"; import { db } from "../common/db"; @@ -7,8 +7,8 @@ export function useVault() { const [isLocked, setIsLocked] = useState(!db.vault.unlocked); useEffect(() => { - EV.subscribe(EVENTS.vaultLocked, () => setIsLocked(true)); - EV.subscribe(EVENTS.vaultUnlocked, () => setIsLocked(false)); + db.eventManager.subscribe(EVENTS.vaultLocked, () => setIsLocked(true)); + db.eventManager.subscribe(EVENTS.vaultUnlocked, () => setIsLocked(false)); }, []); return { diff --git a/apps/web/src/stores/app-store.ts b/apps/web/src/stores/app-store.ts index 48ae8a2a4..68139afd9 100644 --- a/apps/web/src/stores/app-store.ts +++ b/apps/web/src/stores/app-store.ts @@ -30,7 +30,7 @@ import { store as settingStore } from "./setting-store"; import BaseStore from "./index"; import { showToast } from "../utils/toast"; import { Notice } from "../common/notices"; -import { EV, EVENTS, SYNC_CHECK_IDS, SyncOptions } from "@notesnook/core"; +import { EVENTS, SYNC_CHECK_IDS, SyncOptions } from "@notesnook/core"; import { logger } from "../utils/logger"; import Config from "../utils/config"; import { @@ -92,7 +92,7 @@ class AppStore extends BaseStore { }); this.get().sync({ type: "full" }); - EV.subscribe(EVENTS.appRefreshRequested, () => this.refresh()); + db.eventManager.subscribe(EVENTS.appRefreshRequested, () => this.refresh()); db.eventManager.subscribe(EVENTS.syncCompleted, () => this.refresh()); db.eventManager.subscribe(EVENTS.syncProgress, ({ type, current }) => { @@ -105,7 +105,7 @@ class AppStore extends BaseStore { }); }); - EV.subscribe(EVENTS.syncCheckStatus, async (type) => { + db.eventManager.subscribe(EVENTS.syncCheckStatus, async (type) => { const { isAutoSyncEnabled, isSyncEnabled } = this.get(); switch (type) { case SYNC_CHECK_IDS.sync: diff --git a/apps/web/src/stores/editor-store.ts b/apps/web/src/stores/editor-store.ts index 445e7ab9c..cdc8fcc06 100644 --- a/apps/web/src/stores/editor-store.ts +++ b/apps/web/src/stores/editor-store.ts @@ -23,7 +23,7 @@ import { store as appStore } from "./app-store"; import { useStore as useSettingStore } from "./setting-store"; import { db } from "../common/db"; import BaseStore from "."; -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; import { logger } from "../utils/logger"; import Config from "../utils/config"; import { setDocumentTitle } from "../utils/dom"; @@ -255,7 +255,7 @@ class EditorStore extends BaseStore { closeTabs(...tabs.map((s) => s.id)); }); - EV.subscribe(EVENTS.vaultLocked, () => { + db.eventManager.subscribe(EVENTS.vaultLocked, () => { this.set((state) => { state.sessions = state.sessions.map((session) => { if (isLockedSession(session)) { diff --git a/apps/web/src/stores/user-store.ts b/apps/web/src/stores/user-store.ts index 9b85b8557..8c4d3a070 100644 --- a/apps/web/src/stores/user-store.ts +++ b/apps/web/src/stores/user-store.ts @@ -20,7 +20,7 @@ along with this program. If not, see . import createStore from "../common/store"; import { db } from "../common/db"; import BaseStore from "./index"; -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; import Config from "../utils/config"; import { hashNavigate } from "../navigation"; import { AuthenticatorType, User } from "@notesnook/core"; @@ -39,7 +39,7 @@ class UserStore extends BaseStore { counter = 0; init = () => { - EV.subscribe(EVENTS.userSessionExpired, async () => { + db.eventManager.subscribe(EVENTS.userSessionExpired, async () => { Config.set("sessionExpired", true); window.location.replace("/sessionexpired"); }); @@ -53,7 +53,8 @@ class UserStore extends BaseStore { user, isLoggedIn: true }); - if (Config.get("sessionExpired")) EV.publish(EVENTS.userSessionExpired); + if (Config.get("sessionExpired")) + db.eventManager.publish(EVENTS.userSessionExpired); }); if (Config.get("sessionExpired")) return; diff --git a/apps/web/src/views/checkout.tsx b/apps/web/src/views/checkout.tsx index d1afb2f09..826a960ed 100644 --- a/apps/web/src/views/checkout.tsx +++ b/apps/web/src/views/checkout.tsx @@ -20,7 +20,7 @@ along with this program. If not, see . import "../app.css"; import { useEffect, useState } from "react"; import { Box, Button, Flex, Text } from "@theme-ui/components"; -import { hardNavigate, hashNavigate, useQueryParams } from "../navigation"; +import { hardNavigate, useQueryParams } from "../navigation"; import { Support } from "../components/icons"; import { HeadlessAuth } from "./auth"; import { @@ -39,7 +39,8 @@ import { isUserSubscribed } from "../hooks/use-is-user-premium"; import { PLAN_METADATA } from "../dialogs/buy-dialog/plans"; import { planToAvailability } from "@notesnook/common"; import { FeatureCaption } from "../dialogs/buy-dialog/feature-caption"; -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; +import { db } from "../common/db"; export type Plan = z.infer; @@ -119,9 +120,12 @@ function Checkout() { useEffect(() => { if (currentStep === 2) { - const event = EV.subscribe(EVENTS.userSubscriptionUpdated, () => { - hardNavigate("/notes#/welcome"); - }); + const event = db.eventManager.subscribe( + EVENTS.userSubscriptionUpdated, + () => { + hardNavigate("/notes#/welcome"); + } + ); return () => { event.unsubscribe(); }; diff --git a/packages/common/src/hooks/use-is-feature-available.ts b/packages/common/src/hooks/use-is-feature-available.ts index e0949b82c..db2150860 100644 --- a/packages/common/src/hooks/use-is-feature-available.ts +++ b/packages/common/src/hooks/use-is-feature-available.ts @@ -24,7 +24,8 @@ import { FeatureResult, isFeatureAvailable } from "../utils/index.js"; -import { EV, EVENTS } from "@notesnook/core"; +import { EVENTS } from "@notesnook/core"; +import { database } from "../database.js"; export function useIsFeatureAvailable( id: TId | undefined, @@ -36,7 +37,7 @@ export function useIsFeatureAvailable( if (!id) return; isFeatureAvailable(id, value).then((result) => setResult(result)); - const userSubscriptionUpdated = EV.subscribe( + const userSubscriptionUpdated = database.eventManager.subscribe( EVENTS.userSubscriptionUpdated, () => { isFeatureAvailable(id, value).then((result) => setResult(result)); @@ -59,7 +60,7 @@ export function useAreFeaturesAvailable( useEffect(() => { areFeaturesAvailable(ids, values).then((result) => setResult(result)); - const userSubscriptionUpdated = EV.subscribe( + const userSubscriptionUpdated = database.eventManager.subscribe( EVENTS.userSubscriptionUpdated, () => { areFeaturesAvailable(ids, values).then((result) => setResult(result)); diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts index 176d41d2b..979a2f0ee 100644 --- a/packages/core/src/api/index.ts +++ b/packages/core/src/api/index.ts @@ -30,7 +30,7 @@ import Lookup from "./lookup.js"; import { Content } from "../collections/content.js"; import Backup from "../database/backup.js"; import Hosts from "../utils/constants.js"; -import { EV, EVENTS } from "../common.js"; +import { EVENTS } from "../common.js"; import { LegacySettings } from "../collections/legacy-settings.js"; import Migrations from "./migrations.js"; import UserManager from "./user-manager.js"; @@ -126,7 +126,11 @@ class Database { ); return ( this._fs || - (this._fs = new FileStorage(this.options.fs, this.tokenManager)) + (this._fs = new FileStorage( + this.options.fs, + this.tokenManager, + this.eventManager + )) ); }; @@ -191,7 +195,7 @@ class Database { options!: Options; eventSource?: EventSource | null; - tokenManager = new TokenManager(this.kv); + tokenManager = new TokenManager(this.kv, this.eventManager); mfa = new MFAManager(this.tokenManager); subscriptions = new Subscriptions(this); circle = new Circle(this); @@ -293,10 +297,13 @@ class Database { this.connectSSE, this ); - EV.subscribe(EVENTS.tokenRefreshed, () => this.connectSSE()); - EV.subscribe(EVENTS.attachmentDeleted, async (attachment: Attachment) => { - await this.fs().cancel(attachment.hash); - }); + this.eventManager.subscribe(EVENTS.tokenRefreshed, () => this.connectSSE()); + this.eventManager.subscribe( + EVENTS.attachmentDeleted, + async (attachment: Attachment) => { + await this.fs().cancel(attachment.hash); + } + ); this.eventManager.subscribe(EVENTS.userLoggedOut, async () => { await this.monographs.clear(); await this.fs().clear(); diff --git a/packages/core/src/api/sync/collector.ts b/packages/core/src/api/sync/collector.ts index 2fcfc9dd4..ca2ffe590 100644 --- a/packages/core/src/api/sync/collector.ts +++ b/packages/core/src/api/sync/collector.ts @@ -19,7 +19,7 @@ along with this program. If not, see . import { Cipher } from "@notesnook/crypto"; import Database from "../index.js"; -import { CURRENT_DATABASE_VERSION, EV, EVENTS } from "../../common.js"; +import { CURRENT_DATABASE_VERSION, EVENTS } from "../../common.js"; import { logger } from "../../logger.js"; import { SyncItem, @@ -48,7 +48,7 @@ class Collector { ): AsyncGenerator { const key = await this.db.user.getEncryptionKey(); if (!key || !key.key || !key.salt) { - EV.publish(EVENTS.userSessionExpired); + this.db.eventManager.publish(EVENTS.userSessionExpired); throw new Error("User encryption key not generated. Please relogin."); } diff --git a/packages/core/src/api/sync/index.ts b/packages/core/src/api/sync/index.ts index 53e595cb9..f35a89bd3 100644 --- a/packages/core/src/api/sync/index.ts +++ b/packages/core/src/api/sync/index.ts @@ -20,7 +20,6 @@ along with this program. If not, see . import { checkSyncStatus, CURRENT_DATABASE_VERSION, - EV, EVENTS, sendSyncProgressEvent, SYNC_CHECK_IDS @@ -55,7 +54,6 @@ import { import { DownloadableFile } from "../../database/fs.js"; import { SyncDevices } from "./devices.js"; import { DefaultColors } from "../../collections/colors.js"; -import { Monographs } from "../monographs.js"; enum LogLevel { /** Log level for very low severity diagnostic messages. */ @@ -103,7 +101,7 @@ export default class SyncManager { async start(options: SyncOptions) { try { - if (await checkSyncStatus(SYNC_CHECK_IDS.autoSync)) + if (await checkSyncStatus(this.db.eventManager, SYNC_CHECK_IDS.autoSync)) await this.sync.autoSync.start(); await this.sync.start(options); return true; @@ -176,7 +174,7 @@ class Sync { await this.createConnection(options); if (!this.connection) return; - if (!(await checkSyncStatus(SYNC_CHECK_IDS.sync))) { + if (!(await checkSyncStatus(this.db.eventManager, SYNC_CHECK_IDS.sync))) { await this.connection.stop(); return; } @@ -206,7 +204,9 @@ class Sync { await this.stop(options); - if (!(await checkSyncStatus(SYNC_CHECK_IDS.autoSync))) { + if ( + !(await checkSyncStatus(this.db.eventManager, SYNC_CHECK_IDS.autoSync)) + ) { await this.connection.stop(); this.autoSync.stop(); } @@ -418,7 +418,7 @@ class Sync { const { HubConnectionBuilder, HttpTransportType, JsonHubProtocol } = await import("@microsoft/signalr"); - const tokenManager = new TokenManager(this.db.kv); + const tokenManager = new TokenManager(this.db.kv, this.db.eventManager); this.connection = new HubConnectionBuilder() .withUrl(`${Constants.API_HOST}/hubs/sync/v2`, { accessTokenFactory: async () => { @@ -519,7 +519,7 @@ class Sync { this.logger.error( new Error("User encryption key not generated. Please relogin.") ); - EV.publish(EVENTS.userSessionExpired); + this.db.eventManager.publish(EVENTS.userSessionExpired); return; } return key; diff --git a/packages/core/src/api/token-manager.ts b/packages/core/src/api/token-manager.ts index b0a29ff8f..f105cb9ef 100644 --- a/packages/core/src/api/token-manager.ts +++ b/packages/core/src/api/token-manager.ts @@ -19,10 +19,11 @@ along with this program. If not, see . import http from "../utils/http.js"; import constants from "../utils/constants.js"; -import { EV, EVENTS } from "../common.js"; +import { EVENTS } from "../common.js"; import { withTimeout, Mutex } from "async-mutex"; import { logger } from "../logger.js"; import { KVStorageAccessor } from "../interfaces.js"; +import EventManager from "../utils/event-manager.js"; export type Token = { access_token: string; @@ -55,7 +56,10 @@ class TokenManager { new Error("Timed out while refreshing access token.") ); - constructor(private readonly storage: KVStorageAccessor) {} + constructor( + private readonly storage: KVStorageAccessor, + private readonly eventManager: EventManager + ) {} async getToken(renew = true, forceRenew = false): Promise { const token = await this.storage().read("token"); @@ -92,12 +96,16 @@ class TokenManager { scopes: Scope[] = ["notesnook.sync", "IdentityServerApi"], forceRenew = false ) { - return await getSafeToken(async () => { - const token = await this.getToken(true, forceRenew); - if (!token || !token.scope) return; - if (!scopes.some((s) => token.scope.includes(s))) return; - return token.access_token; - }, "Error getting access token:"); + return await getSafeToken( + async () => { + const token = await this.getToken(true, forceRenew); + if (!token || !token.scope) return; + if (!scopes.some((s) => token.scope.includes(s))) return; + return token.access_token; + }, + "Error getting access token:", + this.eventManager + ); } async _refreshToken(forceRenew = false) { @@ -112,7 +120,7 @@ class TokenManager { const { refresh_token, scope } = token; if (!refresh_token || !scope) { - EV.publish(EVENTS.userSessionExpired); + this.eventManager.publish(EVENTS.userSessionExpired); this.logger.error(new Error("Token not found.")); return; } @@ -127,7 +135,7 @@ class TokenManager { } ); await this.saveToken(refreshTokenResponse); - EV.publish(EVENTS.tokenRefreshed); + this.eventManager.publish(EVENTS.tokenRefreshed); }); } @@ -163,7 +171,11 @@ class TokenManager { } export default TokenManager; -async function getSafeToken(action: () => Promise, errorMessage: string) { +async function getSafeToken( + action: () => Promise, + errorMessage: string, + eventManager: EventManager +) { try { return await action(); } catch (e) { @@ -172,7 +184,7 @@ async function getSafeToken(action: () => Promise, errorMessage: string) { e instanceof Error && (e.message === "invalid_grant" || e.message === "invalid_client") ) { - EV.publish(EVENTS.userSessionExpired); + eventManager.publish(EVENTS.userSessionExpired); } throw e; } diff --git a/packages/core/src/api/user-manager.ts b/packages/core/src/api/user-manager.ts index 53040af2a..0ae623e17 100644 --- a/packages/core/src/api/user-manager.ts +++ b/packages/core/src/api/user-manager.ts @@ -46,7 +46,7 @@ class UserManager { private cachedMonographPasswordsKey?: SerializedKey; private cachedInboxKeys?: SerializedKeyPair; constructor(private readonly db: Database) { - this.tokenManager = new TokenManager(this.db.kv); + this.tokenManager = new TokenManager(db.kv, db.eventManager); EV.subscribe(EVENTS.userUnauthorized, async (url: string) => { if (url.includes("/connect/token") || !(await HealthCheck.auth())) return; @@ -80,7 +80,7 @@ class UserManager { password: hashedPassword, client_id: "notesnook" }); - EV.publish(EVENTS.userSignedUp); + this.db.eventManager.publish(EVENTS.userSignedUp); return await this._login({ email, password, hashedPassword }); } diff --git a/packages/core/src/api/vault.ts b/packages/core/src/api/vault.ts index da700e794..0489f6e12 100644 --- a/packages/core/src/api/vault.ts +++ b/packages/core/src/api/vault.ts @@ -19,7 +19,7 @@ along with this program. If not, see . import { Cipher } from "@notesnook/crypto"; import Database from "./index.js"; -import { EV, EVENTS } from "../common.js"; +import { EVENTS } from "../common.js"; import { isCipher } from "../utils/crypto.js"; import { Note, NoteContent } from "../types.js"; import { logger } from "../logger.js"; @@ -48,7 +48,7 @@ export default class Vault { } private startEraser() { - EV.publish(EVENTS.vaultUnlocked); + this.db.eventManager.publish(EVENTS.vaultUnlocked); clearTimeout(this.erasureTimeout); this.erasureTimeout = setTimeout(() => { this.lock(); @@ -80,7 +80,7 @@ export default class Vault { async lock() { this.password = undefined; - EV.publish(EVENTS.vaultLocked); + this.db.eventManager.publish(EVENTS.vaultLocked); return true; } diff --git a/packages/core/src/collections/attachments.ts b/packages/core/src/collections/attachments.ts index 0a966ccf5..bc17ba535 100644 --- a/packages/core/src/collections/attachments.ts +++ b/packages/core/src/collections/attachments.ts @@ -19,7 +19,7 @@ along with this program. If not, see . import { ICollection } from "./collection.js"; import { getId } from "../utils/id.js"; -import { EV, EVENTS } from "../common.js"; +import { EVENTS } from "../common.js"; import dataurl from "../utils/dataurl.js"; import dayjs from "dayjs"; import { @@ -48,7 +48,7 @@ export class Attachments implements ICollection { db.sanitizer ); - EV.subscribe( + db.eventManager.subscribe( EVENTS.fileDownloaded, async ({ success, @@ -68,7 +68,7 @@ export class Attachments implements ICollection { const src = await this.read(filename, getOutputType(attachment)); if (!src) return; - EV.publish(EVENTS.mediaAttachmentDownloaded, { + this.db.eventManager.publish(EVENTS.mediaAttachmentDownloaded, { groupId, hash: attachment.hash, attachmentType: getAttachmentType(attachment), @@ -77,7 +77,7 @@ export class Attachments implements ICollection { } ); - EV.subscribe( + db.eventManager.subscribe( EVENTS.fileUploaded, async ({ success, diff --git a/packages/core/src/common.ts b/packages/core/src/common.ts index e640f8ccf..a0dbdcb9d 100644 --- a/packages/core/src/common.ts +++ b/packages/core/src/common.ts @@ -28,11 +28,14 @@ export const SYNC_CHECK_IDS = { export type SyncStatusEvent = keyof typeof SYNC_CHECK_IDS; -export async function checkSyncStatus(type: string) { - const results = await EV.publishWithResult<{ type: string; result: boolean }>( - EVENTS.syncCheckStatus, - type - ); +export async function checkSyncStatus( + eventManager: EventManager, + type: string +) { + const results = await eventManager.publishWithResult<{ + type: string; + result: boolean; + }>(EVENTS.syncCheckStatus, type); if (typeof results === "boolean") return results; else if (typeof results === "undefined") return true; return results.some((r) => r.type === type && r.result === true); @@ -44,23 +47,23 @@ export type SyncProgressEvent = { }; export function sendSyncProgressEvent( - EV: EventManager, + eventManager: EventManager, type: string, current: number ) { - EV.publish(EVENTS.syncProgress, { + eventManager.publish(EVENTS.syncProgress, { type, current } as SyncProgressEvent); } export function sendMigrationProgressEvent( - EV: EventManager, + eventManager: EventManager, collection: string, total: number, current?: number ) { - EV.publish(EVENTS.migrationProgress, { + eventManager.publish(EVENTS.migrationProgress, { collection, total, current: current === undefined ? total : current diff --git a/packages/core/src/database/fs.ts b/packages/core/src/database/fs.ts index 1ae799d52..8bfe8bf25 100644 --- a/packages/core/src/database/fs.ts +++ b/packages/core/src/database/fs.ts @@ -24,8 +24,9 @@ import { IFileStorage } from "../interfaces.js"; import { DataFormat, SerializedKey } from "@notesnook/crypto"; -import { EV, EVENTS } from "../common.js"; +import { EVENTS } from "../common.js"; import { logger } from "../logger.js"; +import EventManager from "../utils/event-manager.js"; export type FileStorageAccessor = () => FileStorage; export type DownloadableFile = { @@ -48,7 +49,8 @@ export class FileStorage { constructor( private readonly fs: IFileStorage, - private readonly tokenManager: TokenManager + private readonly tokenManager: TokenManager, + private readonly eventManager: EventManager ) {} async queueDownloads( @@ -70,7 +72,7 @@ export class FileStorage { for (const file of files as QueueItem[]) { current++; if (!group.has(file.filename)) { - EV.publish(EVENTS.fileDownloaded, { + this.eventManager.publish(EVENTS.fileDownloaded, { success: false, groupId, filename: file.filename, @@ -93,7 +95,7 @@ export class FileStorage { const { filename, chunkSize } = file; if (await this.exists(filename)) { - EV.publish(EVENTS.fileDownloaded, { + this.eventManager.publish(EVENTS.fileDownloaded, { success: true, groupId, filename, @@ -104,7 +106,7 @@ export class FileStorage { continue; } - EV.publish(EVENTS.fileDownload, { + this.eventManager.publish(EVENTS.fileDownload, { total, current, groupId, @@ -128,7 +130,7 @@ export class FileStorage { this.downloads.set(filename, file); const result = await file.operation; if (eventData) - EV.publish(EVENTS.fileDownloaded, { + this.eventManager.publish(EVENTS.fileDownloaded, { success: result, total, current, @@ -180,7 +182,7 @@ export class FileStorage { group.delete(filename); }); - EV.publish(EVENTS.fileUpload, { + this.eventManager.publish(EVENTS.fileUpload, { total, current, groupId, @@ -189,7 +191,7 @@ export class FileStorage { this.uploads.set(filename, file); const result = await file.operation; - EV.publish(EVENTS.fileUploaded, { + this.eventManager.publish(EVENTS.fileUploaded, { error, success: result, total, @@ -256,10 +258,16 @@ export class FileStorage { if (queue.type === "download") { this.groups.downloads.delete(groupId); - EV.publish(EVENTS.downloadCanceled, { groupId, canceled: true }); + this.eventManager.publish(EVENTS.downloadCanceled, { + groupId, + canceled: true + }); } else if (queue.type === "upload") { this.groups.uploads.delete(groupId); - EV.publish(EVENTS.uploadCanceled, { groupId, canceled: true }); + this.eventManager.publish(EVENTS.uploadCanceled, { + groupId, + canceled: true + }); } } }