mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
Merge branch 'master' into beta
This commit is contained in:
@@ -125,7 +125,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 3091
|
||||
versionCode 3092
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
- Add notebooks, tags and colors to Home Screen Shortcuts
|
||||
- Change day format and use /day in notes
|
||||
- Add Setting to change default editor line height
|
||||
- Set a custom title for monographs
|
||||
- Add webpage title and date clipped to web clips
|
||||
- Configure Week to start from Sunday or Monday
|
||||
- Change Note's creation date
|
||||
- Set expiry date on notes
|
||||
- Temporarily disable password change and recovery options
|
||||
- Note history now includes note title
|
||||
- Minor bug fixes
|
||||
- Bug fixes and minor improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
|
||||
@@ -167,14 +167,16 @@ const ColorPicker = ({
|
||||
);
|
||||
if (!title.current)
|
||||
return ToastManager.error(
|
||||
new Error(strings.allFieldsRequired())
|
||||
new Error(strings.allFieldsRequired()),
|
||||
"color-picker"
|
||||
);
|
||||
const exists = await db.colors.all.find((v) =>
|
||||
v.and([v(`colorCode`, "==", selectedColor)])
|
||||
);
|
||||
if (exists)
|
||||
return ToastManager.error(
|
||||
new Error(strings.colorExists(selectedColor))
|
||||
new Error(strings.colorExists(selectedColor)),
|
||||
"color-picker"
|
||||
);
|
||||
const id = await db.colors.add({
|
||||
title: title.current,
|
||||
|
||||
@@ -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;
|
||||
@@ -1007,8 +1008,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;
|
||||
@@ -799,7 +814,6 @@ export const useAppEvents = () => {
|
||||
return () => {
|
||||
emitterSubscriptions.forEach((sub) => sub?.remove?.());
|
||||
subscriptions.forEach((sub) => sub?.unsubscribe?.());
|
||||
EV.unsubscribeAll();
|
||||
};
|
||||
}, [onSyncComplete, onUserUpdated]);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,7 +25,8 @@ import React, {
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useLayoutEffect,
|
||||
useRef
|
||||
useRef,
|
||||
useState
|
||||
} from "react";
|
||||
import { Platform, ViewStyle } from "react-native";
|
||||
import WebView from "react-native-webview";
|
||||
@@ -109,17 +110,20 @@ const Editor = React.memo(
|
||||
noToolbar,
|
||||
noHeader
|
||||
});
|
||||
const renderKey = useRef(randId("editor-id") + editorId);
|
||||
const [renderKey, setRenderKey] = useState(
|
||||
randId("editor-id") + editorId
|
||||
);
|
||||
useImperativeHandle(ref, () => ({
|
||||
get: () => editor
|
||||
}));
|
||||
useLockedNoteHandler();
|
||||
|
||||
const onError = useCallback(() => {
|
||||
renderKey.current = randId("editor-id") + editorId;
|
||||
setRenderKey(randId("editor-id") + editorId);
|
||||
editor.state.current.ready = false;
|
||||
editor.state.current.initialLoadCalled = false;
|
||||
editor.setLoading(true);
|
||||
}, [editor, editorId]);
|
||||
}, [editor]);
|
||||
|
||||
useEffect(() => {
|
||||
const sub = [eSubscribeEvent(eEditorReset, onError)];
|
||||
@@ -144,7 +148,7 @@ const Editor = React.memo(
|
||||
<WebView
|
||||
testID={notesnook.editor.id}
|
||||
ref={editor.ref}
|
||||
key={renderKey.current}
|
||||
key={renderKey}
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
KeepLocalCopyResponse,
|
||||
pick as pickFile
|
||||
} from "@react-native-documents/picker";
|
||||
import { basename } from "pathe";
|
||||
import { basename, dirname } from "pathe";
|
||||
import { Platform } from "react-native";
|
||||
import RNFetchBlob from "react-native-blob-util";
|
||||
import { Image, openCamera, openPicker } from "react-native-image-crop-picker";
|
||||
@@ -119,7 +119,9 @@ const file = async (fileOptions: PickerOptions) => {
|
||||
throw new Error("Failed to attach file");
|
||||
}
|
||||
|
||||
await RNFetchBlob.fs.unlink(uri);
|
||||
RNFetchBlob.fs.unlink(dirname(fileCopyUri.localUri)).catch((e) => {
|
||||
console.log(e, "error");
|
||||
});
|
||||
|
||||
if (
|
||||
fileOptions.tabId !== undefined &&
|
||||
@@ -140,6 +142,7 @@ const file = async (fileOptions: PickerOptions) => {
|
||||
throw new Error("Failed to attach file, no tabId is set");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("ERROR OCCURED HERE.", e);
|
||||
ToastManager.show({
|
||||
heading: (e as Error).message,
|
||||
type: "error",
|
||||
@@ -250,7 +253,6 @@ const handleImageResponse = async (
|
||||
for (const image of response) {
|
||||
const isPng = /(png)/g.test(image.mime);
|
||||
const isJpeg = /(jpeg|jpg)/g.test(image.mime);
|
||||
|
||||
if (compress && (isPng || isJpeg)) {
|
||||
image.path = await compressToFile(
|
||||
Platform.OS === "ios" ? "file://" + image.path : image.path,
|
||||
@@ -290,7 +292,7 @@ const handleImageResponse = async (
|
||||
|
||||
if (!(await attachFile(uri, hash, image.mime, fileName, options))) return;
|
||||
|
||||
if (Platform.OS === "ios") await RNFetchBlob.fs.unlink(uri);
|
||||
RNFetchBlob.fs.unlink(uri).catch((e) => {});
|
||||
|
||||
if (
|
||||
options.tabId !== undefined &&
|
||||
@@ -375,9 +377,7 @@ export async function attachFile(
|
||||
return true;
|
||||
} catch (e) {
|
||||
DatabaseLogger.error(e);
|
||||
if (Platform.OS === "ios") {
|
||||
await RNFetchBlob.fs.unlink(uri);
|
||||
}
|
||||
RNFetchBlob.fs.unlink(uri).catch((e) => {});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,8 +684,6 @@ export const useEditor = (
|
||||
lastContentChangeTime.current[item.id] = item.dateEdited;
|
||||
currentNotes.current[item.id] = item;
|
||||
|
||||
if (!currentNotes.current[item.id]) return;
|
||||
|
||||
editorSessionHistory.newSession(item.id);
|
||||
|
||||
await commands.setStatus(
|
||||
@@ -1097,6 +1095,8 @@ export const useEditor = (
|
||||
if (noteId) {
|
||||
const note = await db.notes?.note(noteId);
|
||||
fluidTabsRef.current?.goToPage("editor");
|
||||
loadNoteMutex.cancel();
|
||||
loadNoteMutex.release();
|
||||
if (note) {
|
||||
loadNote({
|
||||
item: note
|
||||
@@ -1104,6 +1104,8 @@ export const useEditor = (
|
||||
}
|
||||
} else {
|
||||
noteId = useTabStore.getState().getCurrentNoteId() || null;
|
||||
loadNoteMutex.cancel();
|
||||
loadNoteMutex.release();
|
||||
if (!noteId) {
|
||||
loadNote({ newNote: true });
|
||||
if (fluidTabsRef.current?.page() === "editor") {
|
||||
|
||||
@@ -193,11 +193,13 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
||||
headerTitle={notebook?.title}
|
||||
loading={loading}
|
||||
CustomLisHeader={
|
||||
<NotebookHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
notebook={notebook!}
|
||||
totalNotes={notes?.placeholders.length || 0}
|
||||
/>
|
||||
notebook ? (
|
||||
<NotebookHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
notebook={notebook}
|
||||
totalNotes={notes?.placeholders.length || 0}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
placeholder={{
|
||||
title: notebook?.title!,
|
||||
|
||||
@@ -1029,7 +1029,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1104,7 +1104,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1135,7 +1135,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1210,7 +1210,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1367,7 +1367,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1379,7 +1379,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1410,7 +1410,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1423,7 +1423,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1453,7 +1453,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1534,7 +1534,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1565,7 +1565,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
CURRENT_PROJECT_VERSION = 2172;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1647,7 +1647,7 @@
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
|
||||
MARKETING_VERSION = 3.3.13;
|
||||
MARKETING_VERSION = 3.3.14;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.3.13",
|
||||
"version": "3.3.14",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -208,4 +208,4 @@
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
13
fastlane/metadata/android/en-US/changelogs/15459.txt
Normal file
13
fastlane/metadata/android/en-US/changelogs/15459.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
- Add notebooks, tags and colors to Home Screen Shortcuts
|
||||
- Change day format and use /day in notes
|
||||
- Add Setting to change default editor line height
|
||||
- Set a custom title for monographs
|
||||
- Add webpage title and date clipped to web clips
|
||||
- Configure Week to start from Sunday or Monday
|
||||
- Change Note's creation date
|
||||
- Set expiry date on notes
|
||||
- Temporarily disable password change and recovery options
|
||||
- Note history now includes note title
|
||||
- Minor bug fixes
|
||||
|
||||
Thank you for using Notesnook!
|
||||
3
fastlane/metadata/android/en-US/changelogs/15464.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/15464.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Bug fixes and minor improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -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,
|
||||
@@ -49,7 +49,7 @@ class Collector {
|
||||
): AsyncGenerator<SyncTransferItem, void, unknown> {
|
||||
const keys = await this.db.user.getDataEncryptionKeys();
|
||||
if (!keys || !keys.length) {
|
||||
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
|
||||
@@ -104,7 +103,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;
|
||||
@@ -177,7 +176,7 @@ export 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;
|
||||
}
|
||||
@@ -207,7 +206,9 @@ export 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();
|
||||
}
|
||||
@@ -454,7 +455,7 @@ export 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 () => {
|
||||
@@ -517,7 +518,7 @@ export class Sync {
|
||||
this.logger.error(
|
||||
new Error("User encryption keys not generated. Please relogin.")
|
||||
);
|
||||
EV.publish(EVENTS.userSessionExpired);
|
||||
this.db.eventManager.publish(EVENTS.userSessionExpired);
|
||||
return false;
|
||||
}
|
||||
await this.processChunk(chunk, keys, options);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ class UserManager {
|
||||
private tokenManager: TokenManager;
|
||||
private keyManager: KeyManager;
|
||||
constructor(private readonly db: Database) {
|
||||
this.tokenManager = new TokenManager(db.kv);
|
||||
this.keyManager = new KeyManager(db);
|
||||
this.tokenManager = new TokenManager(db.kv, db.eventManager);
|
||||
|
||||
EV.subscribe(EVENTS.userUnauthorized, async (url: string) => {
|
||||
if (url.includes("/connect/token") || !(await HealthCheck.auth())) return;
|
||||
|
||||
@@ -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