Compare commits

...

17 Commits

Author SHA1 Message Date
Ammar Ahmed
bb42a2e1a4 ci: skip testflight 2024-08-08 10:19:10 +05:00
Ammar Ahmed
12c5b6d227 mobile: release v3.0.12 2024-07-29 10:06:21 +05:00
Ammar Ahmed
364ae51e36 mobile: fix backup share button not working 2024-07-29 09:53:20 +05:00
Ammar Ahmed
18947e0c93 mobile: fix missing fonts in share sheet 2024-07-29 09:43:37 +05:00
François Martin
3880db4339 global: clarify explanations for force push and force pull (#6255)
Signed-off-by: François Martin <f.martin@fastmail.com>
2024-07-29 09:38:30 +05:00
Ammar Ahmed
ae5b0b6fcc mobile: fix share sheet not loading on ios 2024-07-29 09:25:46 +05:00
Abdullah Atta
2c729f90cc global: update lockfiles 2024-07-27 13:30:25 +05:00
Ammar Ahmed
800514d769 mobile: fix position of password input 2024-07-27 12:49:57 +05:00
Ammar Ahmed
b03b9482dc mobile: app stuck after unlock 2024-07-27 12:49:57 +05:00
Abdullah Atta
9019490dbd web: bump version to v3.0.13 2024-07-27 11:16:42 +05:00
Abdullah Atta
4a3e23c288 web: fix reminder can't be set in january 2024-07-27 11:16:09 +05:00
Ammar Ahmed
1800ebea2d mobile: fix keyboard blocks continue button on applock 2024-07-27 11:12:09 +05:00
Ammar Ahmed
a708c9e9eb mobile: fix home shortcut not working 2024-07-27 10:56:09 +05:00
Abdullah Atta
2aeb875fec web: fix crash on moving temporary tab 2024-07-27 10:08:38 +05:00
Abdullah Atta
a8164e9f6c web: enter in title should focus editor 2024-07-27 09:46:37 +05:00
Abdullah Atta
0ee8e738e5 web: fix attachments ui in properties 2024-07-27 09:46:23 +05:00
Abdullah Atta
8fdef2ac7d web: fix attachments flicker in editor note properties 2024-07-27 09:46:23 +05:00
36 changed files with 375 additions and 343 deletions

View File

@@ -89,13 +89,13 @@ jobs:
- name: CCache Stats After Build
run: ccache -sv
- name: "Upload app to TestFlight"
uses: apple-actions/upload-testflight-build@v1
with:
app-path: Notesnook.ipa
issuer-id: ${{ secrets.API_KEY_ISSUER_ID }}
api-key-id: ${{ secrets.API_KEY_ID }}
api-private-key: ${{ secrets.API_KEY }}
# - name: "Upload app to TestFlight"
# uses: apple-actions/upload-testflight-build@v1
# with:
# app-path: Notesnook.ipa
# issuer-id: ${{ secrets.API_KEY_ISSUER_ID }}
# api-key-id: ${{ secrets.API_KEY_ID }}
# api-private-key: ${{ secrets.API_KEY }}
- name: Upload Notesnook.ipa to Github
uses: actions/upload-artifact@v4

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/desktop",
"version": "3.0.12",
"version": "3.0.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/desktop",
"version": "3.0.12",
"version": "3.0.13",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.0.12",
"version": "3.0.13",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/index.js",

View File

@@ -25,7 +25,6 @@ import { I18nManager, View } from "react-native";
import "react-native-gesture-handler";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { initializeLogger } from "./common/database/logger";
import AppLockedOverlay from "./components/app-lock-overlay";
import { withErrorBoundry } from "./components/exception-handler";
import GlobalSafeAreaProvider from "./components/globalsafearea";
@@ -41,33 +40,24 @@ import { useUserStore } from "./stores/use-user-store";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
I18nManager.swapLeftAndRightInRTL(false);
const { appLockEnabled, appLockMode } = SettingsService.get();
if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
const App = () => {
const init = useAppEvents();
useAppEvents();
//@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true;
useEffect(() => {
initializeLogger()
.catch((e) => {
console.log(e);
})
.finally(() => {
const { appLockEnabled, appLockMode } = SettingsService.get();
if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
//@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true;
init();
setTimeout(async () => {
SettingsService.onFirstLaunch();
await Notifications.get();
if (SettingsService.get().notifNotes) {
Notifications.pinQuickNote(true);
}
TipManager.init();
}, 100);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
SettingsService.onFirstLaunch();
setTimeout(async () => {
await Notifications.get();
if (SettingsService.get().notifNotes) {
Notifications.pinQuickNote(true);
}
TipManager.init();
}, 100);
}, []);
return (
<View

View File

@@ -23,7 +23,9 @@ import { Platform } from "react-native";
import { setLogger } from ".";
import { RNSqliteDriver } from "./sqlite.kysely";
let loggerLoaded = false;
const initializeLogger = async () => {
if (loggerLoaded) return;
await initialize({
dialect: (name) => ({
createDriver: () => {
@@ -37,6 +39,7 @@ const initializeLogger = async () => {
journalMode: Platform.OS === "ios" ? "DELETE" : "WAL"
});
setLogger();
loggerLoaded = true;
};
export { initializeLogger };

View File

@@ -18,7 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { useCallback, useEffect, useRef } from "react";
import { AppStateStatus, Platform, TextInput, View } from "react-native";
import {
AppStateStatus,
Platform,
TextInput,
useWindowDimensions,
View
} from "react-native";
//@ts-ignore
import { useThemeColors } from "@notesnook/theme";
import { DatabaseLogger } from "../../common/database";
@@ -46,6 +52,7 @@ import Input from "../ui/input";
import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
const getUser = () => {
const user = MMKV.getString("user");
@@ -86,6 +93,7 @@ const AppLockedOverlay = () => {
const appState = useAppState();
const lastAppState = useRef<AppStateStatus>(appState);
const biometricUnlockAwaitingUserInput = useRef(false);
const { height } = useWindowDimensions();
const keyboardType = useSettingStore(
(state) => state.settings.applockKeyboardType
);
@@ -191,15 +199,20 @@ const AppLockedOverlay = () => {
}, [appState, onUnlockAppRequested, appLocked]);
return appLocked ? (
<View
<KeyboardAwareScrollView
style={{
backgroundColor: colors.primary.background,
width: "100%",
height: "100%",
position: "absolute",
zIndex: 999,
justifyContent: "center"
zIndex: 999
}}
contentContainerStyle={{
justifyContent: "center",
minHeight: height
}}
keyboardDismissMode="interactive"
keyboardShouldPersistTaps="handled"
>
<Toast context="local" />
<View
@@ -314,7 +327,7 @@ const AppLockedOverlay = () => {
</View>
</View>
</View>
</View>
</KeyboardAwareScrollView>
) : null;
};

View File

@@ -97,6 +97,7 @@ import {
import { getGithubVersion } from "../utils/github-version";
import { tabBarRef } from "../utils/global-refs";
import { sleep } from "../utils/time";
import { initializeLogger } from "../common/database/logger";
const onCheckSyncStatus = async (type: SyncStatusEvent) => {
const { disableSync, disableAutoSync } = SettingsService.get();
@@ -280,8 +281,108 @@ const onSubscriptionError = async (error: RNIap.PurchaseError) => {
const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium);
const doAppLoadActions = async () => {
if (SettingsService.get().sessionExpired) {
eSendEvent(eLoginSessionExpired);
return;
}
notifee.setBadgeCount(0);
if (!(await db.user.getUser())) {
setLoginMessage();
return;
}
await useMessageStore.getState().setAnnouncement();
if (NewFeature.present()) return;
if (await checkAppUpdateAvailable()) return;
if (await checkForRateAppRequest()) return;
if (await PremiumService.getRemainingTrialDaysStatus()) return;
if (SettingsService.get().introCompleted) {
useMessageStore.subscribe((state) => {
const dialogs = state.dialogs;
if (dialogs.length > 0) {
eSendEvent(eOpenAnnouncementDialog, dialogs[0]);
}
});
}
};
const checkAppUpdateAvailable = async () => {
if (__DEV__ || Config.isTesting === "true" || Config.FDROID_BUILD || BETA)
return;
try {
const version =
Config.GITHUB_RELEASE === "true"
? await getGithubVersion()
: await checkVersion();
if (!version || !version?.needsUpdate) return false;
setUpdateAvailableMessage(version);
return true;
} catch (e) {
return false;
}
};
const checkForRateAppRequest = async () => {
const rateApp = SettingsService.get().rateApp as number;
if (
rateApp &&
rateApp < Date.now() &&
!useMessageStore.getState().message?.visible
) {
setRateAppMessage();
return false;
}
return false;
};
const IsDatabaseMigrationRequired = () => {
if (!db.migrations.required() || useUserStore.getState().appLocked)
return false;
presentSheet({
component: <Migrate />,
onClose: () => {
if (!db.migrations.required()) {
initializeDatabase();
}
},
disableClosing: true
});
return true;
};
const initializeDatabase = async (password?: string) => {
if (useUserStore.getState().appLocked) return;
if (!db.isInitialized) {
RNBootSplash.hide({ fade: true });
DatabaseLogger.info("Initializing database");
try {
await setupDatabase(password);
await db.init();
} catch (e) {
DatabaseLogger.error(e as Error);
ToastManager.error(e as Error, "Error initializing database", "global");
}
}
if (IsDatabaseMigrationRequired()) return;
if (db.isInitialized) {
Notifications.setupReminders(true);
if (SettingsService.get().notifNotes) {
Notifications.pinQuickNote(false);
}
useSettingStore.getState().setAppLoading(false);
DatabaseLogger.info("Database initialized");
}
Walkthrough.init();
};
export const useAppEvents = () => {
const loading = useSettingStore((state) => state.isAppLoading);
const isAppLoading = useSettingStore((state) => state.isAppLoading);
const [setLastSynced, setUser, appLocked, syncing] = useUserStore((state) => [
state.setLastSynced,
state.setUser,
@@ -312,7 +413,7 @@ export const useAppEvents = () => {
}, [setLastSynced]);
useEffect(() => {
if (loading) return;
if (isAppLoading) return;
let subscriptions: EventManagerSubscription[] = [];
const eventManager = db.eventManager;
@@ -327,7 +428,7 @@ export const useAppEvents = () => {
return () => {
subscriptions.forEach((sub) => sub?.unsubscribe?.());
};
}, [loading, onSyncComplete]);
}, [isAppLoading, onSyncComplete]);
const subscribeToPurchaseListeners = useCallback(async () => {
if (Platform.OS === "android") {
@@ -572,7 +673,7 @@ export const useAppEvents = () => {
});
}
let sub: NativeEventSubscription;
if (!loading && !appLocked) {
if (!isAppLoading && !appLocked) {
setTimeout(() => {
sub = AppState.addEventListener("change", onAppStateChanged);
if (
@@ -594,7 +695,7 @@ export const useAppEvents = () => {
sub?.remove();
unsubscribePurchaseListeners();
};
}, [loading, appLocked, checkAutoBackup]);
}, [isAppLoading, appLocked, checkAutoBackup]);
useEffect(() => {
if (!appLocked && !syncing && refValues.current.backupDidWait) {
@@ -643,127 +744,22 @@ export const useAppEvents = () => {
}
useEffect(() => {
if (!loading) {
if (!isAppLoading) {
onUserUpdated();
doAppLoadActions();
}
}, [loading, onUserUpdated]);
const initializeDatabase = useCallback(async (password?: string) => {
const IsDatabaseMigrationRequired = () => {
if (!db.migrations.required() || useUserStore.getState().appLocked)
return false;
presentSheet({
component: <Migrate />,
onClose: () => {
if (!db.migrations.required()) {
initializeDatabase();
}
},
disableClosing: true
});
return true;
};
if (useUserStore.getState().appLocked) return;
if (!db.isInitialized) {
RNBootSplash.hide({ fade: true });
DatabaseLogger.info("Initializing database");
try {
await setupDatabase(password);
await db.init();
} catch (e) {
DatabaseLogger.error(e as Error);
ToastManager.error(e as Error, "Error initializing database", "global");
}
}
if (IsDatabaseMigrationRequired()) return;
if (db.isInitialized) {
Notifications.setupReminders(true);
if (SettingsService.get().notifNotes) {
Notifications.pinQuickNote(false);
}
useSettingStore.getState().setAppLoading(false);
DatabaseLogger.info("Database initialized");
}
Walkthrough.init();
}, []);
}, [isAppLoading, onUserUpdated]);
useEffect(() => {
let sub: () => void;
if (appLocked) {
const sub = useUserStore.subscribe((state) => {
if (!state.appLocked && useSettingStore.getState().isAppLoading) {
console.log("DB initialized");
if (!appLocked && isAppLoading) {
initializeLogger()
.catch((e) => {
console.log(e);
})
.finally(() => {
//@ts-ignore
initializeDatabase();
sub();
}
});
});
}
return () => {
sub?.();
};
}, [appLocked, initializeDatabase]);
return initializeDatabase;
};
const doAppLoadActions = async () => {
if (SettingsService.get().sessionExpired) {
eSendEvent(eLoginSessionExpired);
return;
}
notifee.setBadgeCount(0);
if (!(await db.user.getUser())) {
setLoginMessage();
return;
}
await useMessageStore.getState().setAnnouncement();
if (NewFeature.present()) return;
if (await checkAppUpdateAvailable()) return;
if (await checkForRateAppRequest()) return;
if (await PremiumService.getRemainingTrialDaysStatus()) return;
if (SettingsService.get().introCompleted) {
useMessageStore.subscribe((state) => {
const dialogs = state.dialogs;
if (dialogs.length > 0) {
eSendEvent(eOpenAnnouncementDialog, dialogs[0]);
}
});
}
};
const checkAppUpdateAvailable = async () => {
if (__DEV__ || Config.isTesting === "true" || Config.FDROID_BUILD || BETA)
return;
try {
const version =
Config.GITHUB_RELEASE === "true"
? await getGithubVersion()
: await checkVersion();
if (!version || !version?.needsUpdate) return false;
setUpdateAvailableMessage(version);
return true;
} catch (e) {
return false;
}
};
const checkForRateAppRequest = async () => {
const rateApp = SettingsService.get().rateApp as number;
if (
rateApp &&
rateApp < Date.now() &&
!useMessageStore.getState().message?.visible
) {
setRateAppMessage();
return false;
}
return false;
}, [appLocked, isAppLoading]);
};

View File

@@ -62,7 +62,6 @@ import {
} from "../services/event-manager";
import { useSettingStore } from "../stores/use-setting-store";
import {
eClearEditor,
eCloseFullscreenEditor,
eOnEnterEditor,
eOnExitEditor,
@@ -286,9 +285,10 @@ const _TabsHolder = () => {
break;
case "mobile":
if (
state &&
!state?.movedAway &&
useTabStore.getState().getCurrentNoteId()
(state &&
!state?.movedAway &&
useTabStore.getState().getCurrentNoteId()) ||
editorState().movedAway === false
) {
tabBarRef.current?.goToIndex(2, false);
} else {

View File

@@ -475,7 +475,7 @@ export const settingsGroups: SettingSection[] = [
{
id: "pull-sync",
name: "Force pull changes",
description: `Use this if some changes are not appearing on this device from other devices. This will pull everything from the server and overwrite with whatever is one this device.\n\nThese must only be used for troubleshooting. Using them regularly for sync is not recommended and will lead to unexpected data loss and other issues. If you are having persistent issues with sync, please report them to us at support@streetwriters.co.`,
description: `Use this if changes from other devices are not appearing on this device. This will overwrite the data on this device with the latest data from the server.\n\nThis must only be used for troubleshooting. Using it regularly for sync is not recommended and will lead to unexpected data loss and other issues. If you are having persistent issues with sync, please report them to us at support@streetwriters.co.`,
modifer: () => {
presentDialog({
title: "Force Pull changes",
@@ -497,7 +497,7 @@ export const settingsGroups: SettingSection[] = [
{
id: "push-sync",
name: "Force push changes",
description: `Use this if some changes are not appearing on this device from other devices. This will pull everything from the server and overwrite with whatever is one this device.`,
description: `Use this if changes made on this device are not appearing on other devices. This will overwrite the data on the server with the data from this device.\n\nThis must only be used for troubleshooting. Using it regularly for sync is not recommended and will lead to unexpected data loss and other issues. If you are having persistent issues with sync, please report them to us at support@streetwriters.co.`,
modifer: () => {
presentDialog({
title: "Force Push changes",

View File

@@ -141,7 +141,6 @@ const onBoot = async () => {
}
await Notifications.setupReminders();
SettingsService.init();
if (SettingsService.get().notifNotes) {
Notifications.pinQuickNote(false);
}

View File

@@ -171,7 +171,6 @@ async function run(progress = false, context) {
}
let path;
let backupFilePath;
let backupFileName = "notesnook_backup_" + Date.now();
if (Platform.OS === "ios") {
@@ -236,7 +235,7 @@ async function run(progress = false, context) {
await sleep(300);
if (showBackupCompleteSheet) {
presentBackupCompleteSheet(backupFilePath);
presentBackupCompleteSheet(path);
} else {
progress && eSendEvent(eCloseSheet);
}

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Platform } from "react-native";
import { NativeModules, Platform } from "react-native";
import { enabled } from "react-native-privacy-snapshot";
import { MMKV } from "../common/database/mmkv";
import {
@@ -118,14 +118,18 @@ function setPrivacyScreen(settings: SettingStore["settings"]) {
NotesnookModule.setSecureMode(true);
} else {
enabled(true);
ScreenGuardModule.register({ backgroundColor: "#000000" });
if (NativeModules.ScreenGuard) {
ScreenGuardModule.register({ backgroundColor: "#000000" });
}
}
} else {
if (Platform.OS === "android") {
NotesnookModule.setSecureMode(false);
} else {
enabled(false);
ScreenGuardModule.unregister();
if (NativeModules.ScreenGuard) {
ScreenGuardModule.unregister();
}
}
}
}

View File

@@ -17,8 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Profile } from "@notesnook/core";
import { User } from "@notesnook/core";
import { Profile, User } from "@notesnook/core";
import create, { State } from "zustand";
export enum SyncStatus {
@@ -56,7 +55,9 @@ export const useUserStore = create<UserStore>((set) => ({
set({ syncing: syncing, lastSyncStatus: status });
},
setLastSynced: (lastSynced) => set({ lastSynced: lastSynced }),
lockApp: (appLocked) => set({ appLocked }),
lockApp: (appLocked) => {
set({ appLocked });
},
lastSyncStatus: SyncStatus.Never,
disableAppLockRequests: false,
setDisableAppLockRequests: (disableAppLockRequests) => {

View File

@@ -111,7 +111,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled true
versionCode 3019
versionCode 3020
versionName getNpmVersion()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

View File

@@ -1,5 +1,3 @@
- Fixed realtime sync issues
- Fixed color popups not opening from main toolbar
- Bug fixes and performance improvements
Thank you for using Notesnook!

View File

@@ -21,9 +21,9 @@
6517B7C32B6838EB0079FF37 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
6529A13E279BC4C70048D4A8 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6529A13D279BC4C70048D4A8 /* BootSplash.storyboard */; };
656835812BB29A9800144BAB /* OpenSans-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 656835802BB29A8300144BAB /* OpenSans-Italic.ttf */; };
656DD2AB2B1891DF00A362EA /* BuildFile in Resources */ = {isa = PBXBuildFile; };
656DD2AC2B1891DF00A362EA /* BuildFile in Resources */ = {isa = PBXBuildFile; };
656DD2AD2B1891DF00A362EA /* BuildFile in Resources */ = {isa = PBXBuildFile; };
6569927F2C5754F10041CD41 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
656992802C5754F10041CD41 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */; };
656992812C5754F10041CD41 /* OpenSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */; };
6593E4A3281C345400492C50 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6593E4A2281C345400492C50 /* AppDelegate.mm */; };
659BE46725E11A5100E05671 /* notesnook-text.png in Resources */ = {isa = PBXBuildFile; fileRef = 659BE46625E11A5100E05671 /* notesnook-text.png */; };
65AA857925E6DDEC00772A01 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65AA857825E6DDEC00772A01 /* WidgetKit.framework */; };
@@ -586,9 +586,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
656DD2AB2B1891DF00A362EA /* BuildFile in Resources */,
656DD2AC2B1891DF00A362EA /* BuildFile in Resources */,
656DD2AD2B1891DF00A362EA /* BuildFile in Resources */,
6569927F2C5754F10041CD41 /* OpenSans-Bold.ttf in Resources */,
656992802C5754F10041CD41 /* OpenSans-Regular.ttf in Resources */,
656992812C5754F10041CD41 /* OpenSans-SemiBold.ttf in Resources */,
65C400DF2A80B6B600AA3DF5 /* MaterialCommunityIcons.ttf in Resources */,
65C149872A61151B005C40F1 /* extension.bundle in Resources */,
65B5014725A672B200E2D264 /* MainInterface.storyboard in Resources */,
@@ -1015,7 +1015,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1089,7 +1089,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1120,7 +1120,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1194,7 +1194,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1353,7 +1353,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1365,7 +1365,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1396,7 +1396,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1409,7 +1409,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1439,7 +1439,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1513,7 +1513,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1544,7 +1544,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2108;
CURRENT_PROJECT_VERSION = 2109;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1619,7 +1619,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.11;
MARKETING_VERSION = 3.0.12;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -971,4 +971,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 2b8b28a341b202bf3ca5f231b75bb05893486ed8
COCOAPODS: 1.14.2
COCOAPODS: 1.15.2

View File

@@ -34,7 +34,7 @@
},
"../../packages/common": {
"name": "@notesnook/common",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook/core": "^8.0.0",
@@ -114,7 +114,7 @@
},
"../../packages/core": {
"name": "@notesnook/core",
"version": "8.0.2",
"version": "8.0.8",
"dev": true,
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
@@ -3121,7 +3121,7 @@
},
"../../packages/crypto": {
"name": "@notesnook/crypto",
"version": "2.0.1",
"version": "2.0.7",
"dev": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -3135,7 +3135,7 @@
},
"../../packages/editor": {
"name": "@notesnook/editor",
"version": "2.0.1",
"version": "2.0.7",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -23800,13 +23800,13 @@
},
"../../packages/logger": {
"name": "@notesnook/logger",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"devDependencies": {}
},
"../../packages/sodium": {
"name": "@notesnook/sodium",
"version": "2.0.1",
"version": "2.0.7",
"dev": true,
"license": "GPL-3.0-or-later",
"devDependencies": {
@@ -25178,7 +25178,7 @@
},
"../../packages/theme": {
"name": "@notesnook/theme",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"devDependencies": {
"@emotion/react": "11.11.1",
@@ -26245,7 +26245,7 @@
},
"../../packages/ui": {
"name": "@notesnook/ui",
"version": "2.0.2",
"version": "2.0.8",
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook/theme": "file:../theme"

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.0.11",
"version": "3.0.12",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [

View File

@@ -134,7 +134,7 @@
},
"../../packages/common": {
"name": "@notesnook/common",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook/core": "^8.0.0",
@@ -330,7 +330,7 @@
},
"../../packages/theme": {
"name": "@notesnook/theme",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"devDependencies": {
"@emotion/react": "11.11.1",
@@ -979,7 +979,7 @@
},
"../web": {
"name": "@notesnook/web",
"version": "3.0.10",
"version": "3.0.13",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

View File

@@ -33,7 +33,7 @@
},
"../../packages/crypto": {
"name": "@notesnook/crypto",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook/sodium": "file:../sodium"

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/web",
"version": "3.0.12",
"version": "3.0.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/web",
"version": "3.0.12",
"version": "3.0.13",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -31906,7 +31906,7 @@
},
"../desktop": {
"name": "@notesnook/desktop",
"version": "3.0.11",
"version": "3.0.13",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "@notesnook/web",
"description": "Your private note taking space",
"version": "3.0.12",
"version": "3.0.13",
"private": true,
"main": "./src/app.js",
"homepage": "https://notesnook.com/",

View File

@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect } from "react";
import { useStore } from "./stores/app-store";
import { useStore as useUserStore } from "./stores/user-store";
import { useStore as useAttachmentStore } from "./stores/attachment-store";
import { useEditorStore } from "./stores/editor-store";
import { useStore as useAnnouncementStore } from "./stores/announcement-store";
import { resetNotices, scheduleBackups } from "./common/notices";
@@ -51,7 +50,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
const isFocusMode = useStore((store) => store.isFocusMode);
const initUser = useUserStore((store) => store.init);
const initStore = useStore((store) => store.init);
const initAttachments = useAttachmentStore((store) => store.init);
const setIsVaultCreated = useStore((store) => store.setIsVaultCreated);
const initEditorStore = useEditorStore((store) => store.init);
const dialogAnnouncements = useAnnouncementStore(
@@ -77,7 +75,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
);
initStore();
initAttachments();
initEditorStore();
(async function () {
@@ -102,7 +99,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
[
initEditorStore,
initStore,
initAttachments,
updateLastSynced,
refreshNavItems,
initUser,

View File

@@ -156,8 +156,7 @@ export function Attachment({
<td>
<Flex
sx={{
alignItems: "center",
maxWidth: compact ? 180 : "95%"
alignItems: "center"
}}
>
{status ? (
@@ -209,7 +208,12 @@ export function Attachment({
<Text
as="td"
variant="body"
sx={{ color: status ? "accent" : "paragraph" }}
sx={{
color: status ? "accent" : "paragraph",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis"
}}
>
{status ? (
<>

View File

@@ -281,21 +281,21 @@ function TabStrip() {
items={sessions}
moveItem={(from, to) => {
if (from === to) return;
useEditorStore.setState((state) => {
const isToPinned = state.sessions[to].pinned;
const [fromTab] = state.sessions.splice(from, 1);
const sessions = useEditorStore.getState().sessions.slice();
const isToPinned = sessions[to].pinned;
const [fromTab] = sessions.splice(from, 1);
// if the tab where this tab is being dropped is pinned,
// let's pin our tab too.
if (isToPinned) {
fromTab.pinned = true;
fromTab.preview = false;
}
// unpin the tab if it is moved.
else if (fromTab.pinned) fromTab.pinned = false;
// if the tab where this tab is being dropped is pinned,
// let's pin our tab too.
if (isToPinned) {
fromTab.pinned = true;
fromTab.preview = false;
}
// unpin the tab if it is moved.
else if (fromTab.pinned) fromTab.pinned = false;
state.sessions.splice(to, 0, fromTab);
});
sessions.splice(to, 0, fromTab);
useEditorStore.setState({ sessions });
}}
renderItem={({ item: session, index: i }) => (
<Tab

View File

@@ -23,7 +23,7 @@ import { useEditorStore } from "../../stores/editor-store";
import { debounceWithId } from "@notesnook/common";
import useMobile from "../../hooks/use-mobile";
import useTablet from "../../hooks/use-tablet";
import { useEditorConfig } from "./manager";
import { useEditorConfig, useEditorManager } from "./manager";
import { getFontById } from "@notesnook/editor";
import { replaceDateTime } from "@notesnook/editor/dist/extensions/date-time";
import { useStore as useSettingsStore } from "../../stores/setting-store";
@@ -131,6 +131,13 @@ function TitleBox(props: TitleBoxProps) {
color: "placeholder"
}
}}
onKeyUp={(e) => {
if (e.key === "Enter") {
const context = useEditorManager.getState().getEditor(id);
if (!context) return;
context.editor?.focus({ scrollIntoView: true });
}
}}
onChange={(e) => {
pendingChanges.current = true;
e.target.value = replaceDateTime(

View File

@@ -659,6 +659,7 @@ function Attachments({ noteId }: { noteId: string }) {
estimatedSize={30}
getItemKey={(index) => result.value.key(index)}
items={result.value.placeholders}
style={{ tableLayout: "fixed", width: "100%" }}
header={
<tr>
<th style={{ width: "75%" }} />
@@ -666,7 +667,6 @@ function Attachments({ noteId }: { noteId: string }) {
<th style={{ width: "20%" }} />
</tr>
}
headerSize={0}
renderRow={({ index }) => (
<ResolvedItem index={index} type="attachment" items={result.value}>
{({ item }) => <ListItemWrapper item={item} compact />}

View File

@@ -17,9 +17,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Virtualizer, useVirtualizer } from "@tanstack/react-virtual";
import { Box } from "@theme-ui/components";
import { Virtualizer } from "@tanstack/react-virtual";
import { Flex } from "@theme-ui/components";
import React, { useRef } from "react";
import { TableVirtuoso } from "react-virtuoso";
export type VirtualizedTableRowProps<T, C> = {
item: T;
@@ -36,12 +37,10 @@ type VirtualizedTableProps<T, C> = {
mode?: "fixed" | "dynamic";
items: T[];
estimatedSize: number;
headerSize: number;
getItemKey: (index: number) => string;
scrollElement?: Element | null;
scrollElement?: HTMLElement | null;
context?: C;
renderRow: (props: VirtualizedTableRowProps<T, C>) => JSX.Element | null;
scrollMargin?: number;
header: React.ReactNode;
style?: React.CSSProperties;
};
@@ -50,59 +49,95 @@ export function VirtualizedTable<T, C>(props: VirtualizedTableProps<T, C>) {
items,
getItemKey,
scrollElement,
scrollMargin,
headerSize,
renderRow: Row,
estimatedSize,
mode,
virtualizerRef,
header,
style,
context
context,
style
} = props;
const containerRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
estimateSize: () => estimatedSize,
getItemKey,
getScrollElement: () =>
scrollElement || containerRef.current?.closest(".ms-container") || null,
scrollMargin: scrollMargin || containerRef.current?.offsetTop || 0
});
if (virtualizerRef) virtualizerRef.current = virtualizer;
const virtualItems = virtualizer.getVirtualItems();
return (
<Box
<Flex
ref={containerRef}
sx={{
height: virtualizer.getTotalSize() + headerSize
}}
variant="columnFill"
sx={{ height: estimatedSize * items.length }}
>
<table style={style}>
<thead>{header}</thead>
<tbody>
{virtualItems.map((row, index) => (
<Row
key={row.key}
item={items[row.index]}
index={row.index}
rowRef={mode === "dynamic" ? virtualizer.measureElement : null}
context={context}
style={{
height: mode === "dynamic" ? "unset" : `${row.size}px`,
transform: `translateY(${
row.start -
index * row.size -
virtualizer.options.scrollMargin
}px)`
}}
/>
))}
</tbody>
</table>
</Box>
<TableVirtuoso
data={items}
context={context}
customScrollParent={
scrollElement ||
containerRef.current?.closest(".ms-container") ||
undefined
}
computeItemKey={(index) => getItemKey(index)}
defaultItemHeight={estimatedSize}
fixedHeaderContent={() => <>{header}</>}
fixedItemHeight={mode === "fixed" ? estimatedSize : undefined}
components={{
Table: (props) => (
<table {...props} style={{ ...style, ...props.style }} />
),
TableRow: (props) => {
return (
<Row
index={props["data-item-index"]}
item={props.item}
style={props.style || {}}
context={props.context}
/>
);
}
}}
/>
</Flex>
);
//
// const virtualizer = useVirtualizer({
// count: items.length,
// estimateSize: () => estimatedSize,
// getItemKey,
// getScrollElement: () =>
// scrollElement || containerRef.current?.closest(".ms-container") || null,
// scrollMargin: scrollMargin || containerRef.current?.offsetTop || 0
// });
// if (virtualizerRef) virtualizerRef.current = virtualizer;
// const virtualItems = virtualizer.getVirtualItems();
// return (
// <Box
// ref={containerRef}
// sx={{
// height: virtualizer.getTotalSize() + headerSize
// }}
// >
// <table style={style}>
// <thead>{header}</thead>
// <tbody>
// {virtualItems.map((row, index) => (
// <Row
// key={row.key}
// item={items[row.index]}
// index={row.index}
// rowRef={mode === "dynamic" ? virtualizer.measureElement : null}
// context={context}
// style={{
// height: mode === "dynamic" ? "unset" : `${row.size}px`,
// transform: `translateY(${
// row.start -
// index * row.size -
// virtualizer.options.scrollMargin
// }px)`
// }}
// />
// ))}
// </tbody>
// </table>
// </Box>
// );
}

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { useEffect, useState, memo, useRef } from "react";
import { useEffect, useState, memo, useRef, startTransition } from "react";
import {
Box,
Button,
@@ -29,7 +29,7 @@ import {
Text
} from "@theme-ui/components";
import { store, useStore } from "../stores/attachment-store";
import { ResolvedItem, formatBytes, usePromise } from "@notesnook/common";
import { formatBytes, usePromise, useResolvedItem } from "@notesnook/common";
import Dialog from "../components/dialog";
import {
ChevronDown,
@@ -66,6 +66,7 @@ import { FlexScrollContainer } from "../components/scroll-container";
import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
import { ConfirmDialog } from "./confirm";
import { showToast } from "../utils/toast";
import { Loader } from "../components/loader";
type ToolbarAction = {
title: string;
@@ -107,7 +108,7 @@ type SortOptions = {
type AttachmentsDialogProps = BaseDialogProps<false>;
export const AttachmentsDialog = DialogManager.register(
function AttachmentsDialog({ onClose }: AttachmentsDialogProps) {
const allAttachments = useStore((store) => store.attachments);
const nonce = useStore((store) => store.nonce);
const [attachments, setAttachments] =
useState<VirtualizedGrouping<AttachmentType>>();
const [counts, setCounts] = useState<Record<Route, number>>({
@@ -125,29 +126,20 @@ export const AttachmentsDialog = DialogManager.register(
direction: "asc"
});
const currentRoute = useRef<Route>("all");
const refresh = useStore((store) => store.refresh);
const download = useStore((store) => store.download);
useEffect(() => {
refresh();
}, [refresh]);
filterAttachments(currentRoute.current)
.sorted({
sortBy: sortBy.id,
sortDirection: sortBy.direction
})
.then((value) => startTransition(() => setAttachments(value)));
}, [sortBy, nonce]);
useEffect(() => {
(async function () {
setAttachments(
await filterAttachments(currentRoute.current).sorted({
sortBy: sortBy.id,
sortDirection: sortBy.direction
})
);
})();
}, [sortBy, allAttachments]);
useEffect(() => {
(async function () {
setCounts(await getCounts());
})();
}, [allAttachments]);
getCounts().then((counts) => startTransition(() => setCounts(counts)));
}, [nonce]);
return (
<Dialog
@@ -234,7 +226,7 @@ export const AttachmentsDialog = DialogManager.register(
</Text>
</Button> */}
</Flex>
{attachments && (
{attachments ? (
<VirtualizedTable
style={{
tableLayout: "fixed",
@@ -327,7 +319,6 @@ export const AttachmentsDialog = DialogManager.register(
}
mode="fixed"
estimatedSize={30}
headerSize={40}
getItemKey={(index) => attachments.key(index)}
items={attachments.placeholders}
context={{
@@ -345,6 +336,8 @@ export const AttachmentsDialog = DialogManager.register(
}}
renderRow={AttachmentRow}
/>
) : (
<Loader title="Loading attachments..." />
)}
</FlexScrollContainer>
</Flex>
@@ -364,23 +357,21 @@ function AttachmentRow(
}
>
) {
if (!props.context) return null;
const item = useResolvedItem({
index: props.index,
items: props.context!.attachments,
type: "attachment"
});
if (!item) return null;
return (
<ResolvedItem
index={props.index}
items={props.context.attachments}
type="attachment"
>
{({ item }) => (
<Attachment
rowRef={props.rowRef}
style={props.style}
item={item}
isSelected={props.context?.isSelected(item.id)}
onSelected={() => props.context?.select(item.id)}
/>
)}
</ResolvedItem>
<Attachment
key={item.item.id}
rowRef={props.rowRef}
style={props.style}
item={item?.item}
isSelected={props.context?.isSelected(item.item.id)}
onSelected={() => props.context?.select(item.item.id)}
/>
);
}

View File

@@ -80,10 +80,10 @@ export const SyncSettings: SettingsGroup[] = [
key: "force-sync",
title: "Having problems with sync?",
description: `Force push:
Use this if some changes from this device are not appearing on other devices.This will push everything on this device and overwrite whatever is one the server.
Use this if changes made on this device are not appearing on other devices. This will overwrite the data on the server with the data from this device.
Force pull:
Use this if some changes are not appearing on this device from other devices. This will pull everything from the server and overwrite with whatever is one this device.
Use this if changes from other devices are not appearing on this device. This will overwrite the data on this device with the latest data from the server.
**These must only be used for troubleshooting. Using them regularly for sync is not recommended and will lead to unexpected data loss and other issues. If you are having persistent issues with sync, please report them to us at support@streetwriters.co.**`,
keywords: ["force sync", "sync troubleshoot"],

View File

@@ -27,11 +27,11 @@ import { showToast } from "../utils/toast";
import { AttachmentStream } from "../utils/streams/attachment-stream";
import { createZipStream } from "../utils/streams/zip-stream";
import { createWriteStream } from "../utils/stream-saver";
import { Attachment, VirtualizedGrouping } from "@notesnook/core";
import { Attachment } from "@notesnook/core";
let abortController: AbortController | undefined = undefined;
class AttachmentStore extends BaseStore<AttachmentStore> {
attachments?: VirtualizedGrouping<Attachment>;
nonce = 0;
status?: { current: number; total: number };
processing: Record<
string,
@@ -40,17 +40,10 @@ class AttachmentStore extends BaseStore<AttachmentStore> {
refresh = async () => {
this.set({
attachments: await db.attachments.all.sorted({
sortBy: "dateCreated",
sortDirection: "desc"
})
nonce: this.get().nonce + 1
});
};
init = () => {
this.refresh();
};
download = async (ids: string[]) => {
if (this.get().status)
throw new Error(

View File

@@ -142,12 +142,12 @@ function reminderToCronExpression(reminder: Reminder) {
const dateTime = dayjs(date);
if (mode === "once" || !selectedDays) {
return dateTime.format("ss mm HH DD MM * YYYY");
return dateTime.format("00 mm HH DD MM * YYYY");
} else {
const cron = dateTime.format("ss mm HH").split(" ");
const cron = dateTime.format("00 mm HH").split(" ");
if (recurringMode === "year") {
cron.push(`${dateTime.date()}`); // day of month
cron.push(`${dateTime.month()}`); // month
cron.push(`${dateTime.month() + 1}`); // month
cron.push("*"); // day of week
cron.push("*"); // year
} else if (recurringMode === "week") {

View File

@@ -0,0 +1,3 @@
- Bug fixes and performance improvements
Thank you for using Notesnook!

View File

@@ -22,7 +22,7 @@ export function formatBytes(bytes: number, decimals = 2) {
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];

View File

@@ -35,7 +35,7 @@
},
"../editor": {
"name": "@notesnook/editor",
"version": "2.0.1",
"version": "2.0.7",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -123,7 +123,7 @@
},
"../theme": {
"name": "@notesnook/theme",
"version": "2.0.1",
"version": "2.0.7",
"license": "GPL-3.0-or-later",
"devDependencies": {
"@emotion/react": "11.11.1",