mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
core: use db eventmanager for events
This commit is contained in:
@@ -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);
|
||||
}}
|
||||
|
||||
@@ -724,24 +724,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) => {
|
||||
@@ -767,7 +782,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;
|
||||
|
||||
@@ -29,7 +29,6 @@ export type SyncProgressEventType = {
|
||||
|
||||
const useSyncProgress = () => {
|
||||
const [progress, setProgress] = useState<SyncProgressEventType>();
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<AppStore> {
|
||||
});
|
||||
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<AppStore> {
|
||||
});
|
||||
});
|
||||
|
||||
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:
|
||||
|
||||
@@ -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<EditorStore> {
|
||||
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)) {
|
||||
|
||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
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<UserStore> {
|
||||
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<UserStore> {
|
||||
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;
|
||||
|
||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
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<typeof PlanSchema>;
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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<TId extends FeatureId>(
|
||||
id: TId | undefined,
|
||||
@@ -36,7 +37,7 @@ export function useIsFeatureAvailable<TId extends FeatureId>(
|
||||
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<TIds extends FeatureId[]>(
|
||||
|
||||
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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<SyncTransferItem, void, unknown> {
|
||||
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.");
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
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;
|
||||
|
||||
@@ -19,10 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<Token | undefined> {
|
||||
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<T>(action: () => Promise<T>, errorMessage: string) {
|
||||
async function getSafeToken<T>(
|
||||
action: () => Promise<T>,
|
||||
errorMessage: string,
|
||||
eventManager: EventManager
|
||||
) {
|
||||
try {
|
||||
return await action();
|
||||
} catch (e) {
|
||||
@@ -172,7 +184,7 @@ async function getSafeToken<T>(action: () => Promise<T>, errorMessage: string) {
|
||||
e instanceof Error &&
|
||||
(e.message === "invalid_grant" || e.message === "invalid_client")
|
||||
) {
|
||||
EV.publish(EVENTS.userSessionExpired);
|
||||
eventManager.publish(EVENTS.userSessionExpired);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user