Compare commits

..

1 Commits

Author SHA1 Message Date
Ammar Ahmed
15c27ed273 mobile: fix sync on iOS 2024-11-20 12:35:16 +05:00
111 changed files with 3200 additions and 3752 deletions

View File

@@ -10,7 +10,7 @@ const authors = readFileSync("AUTHORS", "utf-8");
const isAuthor = authors.includes(`<${authorEmail}>`);
const SCOPES = [
// for full list of scopes + details see: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md#commit-guidelines
// for full list of scopes + details see: https://github.com/streetwriters/notesnook-private/blob/master/CONTRIBUTING.md#commit-guidelines
"mobile",
"web",
@@ -36,8 +36,7 @@ const SCOPES = [
"global",
"docs",
"themebuilder",
"intl",
"webclipper"
"intl"
];
module.exports = {

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/desktop",
"version": "3.0.22",
"version": "3.0.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/desktop",
"version": "3.0.22",
"version": "3.0.21",
"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.22",
"version": "3.0.21",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",

View File

@@ -18,17 +18,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import path from "path";
import fs from "fs/promises";
import { existsSync } from "fs";
import fs, { readFile, writeFile } from "fs/promises";
import { existsSync, readFileSync } from "fs";
import yargs from "yargs-parser";
import os from "os";
import * as childProcess from "child_process";
import { fileURLToPath } from "url";
import { patchBetterSQLite3 } from "./patch-better-sqlite3.mjs";
const args = yargs(process.argv);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const packageJson = JSON.parse(
readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")
);
const webAppPath = path.resolve(path.join(__dirname, "..", "..", "web"));
@@ -44,6 +46,12 @@ if (args.rebuild || !existsSync(path.join(webAppPath, "build"))) {
// temporary until there's support for prebuilt binaries for linux ARM
if (os.platform() === "linux") await patchBetterSQLite3();
// if (os.platform() === "win32")
// await exec(
// `npx prebuildify --arch=arm64 --strip -t electron@${packageJson.devDependencies.electron}`,
// path.join(__dirname, "..", "node_modules", "sodium-native")
// );
await fs.cp(path.join(webAppPath, "build"), "build", {
recursive: true,
force: true
@@ -75,3 +83,21 @@ async function exec(cmd, cwd) {
cwd: cwd || process.cwd()
});
}
async function patchBetterSQLite3() {
const jsonPath = path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"package.json"
);
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
json.version = "11.5.1";
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
json.repository.url =
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
await writeFile(jsonPath, JSON.stringify(json));
}

View File

@@ -1,48 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 { readFile, writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export async function patchBetterSQLite3() {
const jsonPath = path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"package.json"
);
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
json.version = "11.5.1";
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
json.repository.url =
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
await writeFile(jsonPath, JSON.stringify(json));
}
if (process.argv[1] === __filename) {
console.log("Patching better-sqlite3");
patchBetterSQLite3();
}

View File

@@ -224,13 +224,6 @@ export default async function downloadAttachment(
}
try {
useAttachmentStore.getState().setDownloading({
groupId: options.groupId || attachment.hash,
current: 0,
total: 1,
filename: attachment.filename
});
await db
.fs()
.downloadFile(
@@ -238,15 +231,6 @@ export default async function downloadAttachment(
attachment.hash,
attachment.chunkSize
);
useAttachmentStore.getState().setDownloading({
groupId: options.groupId || attachment.hash,
current: 1,
total: 1,
filename: attachment.filename,
success: true
});
if (!(await exists(attachment.hash))) {
DatabaseLogger.log("Attachment does not exist after download.");
return;
@@ -317,14 +301,6 @@ export default async function downloadAttachment(
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}_dcache`)
.catch(console.log);
}
useAttachmentStore.getState().setDownloading({
groupId: options.groupId || attachment.hash,
current: 0,
total: 0,
filename: attachment.filename,
success: false
});
DatabaseLogger.error(e);
useAttachmentStore.getState().remove(attachment.hash);
if (options.throwError) {

View File

@@ -63,11 +63,9 @@ const Actions = ({
attachment,
close,
setAttachments,
fwdRef,
context
fwdRef
}: {
attachment: Attachment;
context: string;
setAttachments: (attachments?: VirtualizedGrouping<Attachment>) => void;
close?: () => void;
fwdRef: RefObject<ActionSheetRef>;
@@ -81,6 +79,7 @@ const Actions = ({
const [loading, setLoading] = useState<{
name?: string;
}>({});
const actions = [
{
name: strings.network.download(),
@@ -89,7 +88,7 @@ const Actions = ({
await db.fs().cancel(attachment.hash);
useAttachmentStore.getState().remove(attachment.hash);
}
downloadAttachment(attachment.hash, context === "global");
downloadAttachment(attachment.hash, false);
fwdRef.current?.hide();
},
icon: "download"
@@ -376,7 +375,6 @@ Actions.present = (
setAttachments={set}
close={close}
attachment={attachment}
context={context || "global"}
/>
)
});

View File

@@ -31,7 +31,6 @@ import { ProgressCircleComponent } from "../ui/svg/lazy";
import Paragraph from "../ui/typography/paragraph";
import Actions from "./actions";
import { strings } from "@notesnook/intl";
import { Pressable } from "../ui/pressable";
function getFileExtension(filename: string) {
const ext = /^.+\.([^.]+)$/.exec(filename);
@@ -70,7 +69,8 @@ export const AttachmentItem = ({
};
return errorOnly && attachment && !attachment?.failed ? null : (
<Pressable
<TouchableOpacity
activeOpacity={0.9}
onPress={onPress}
style={{
flexDirection: "row",
@@ -186,6 +186,6 @@ export const AttachmentItem = ({
)}
</>
)}
</Pressable>
</TouchableOpacity>
);
};

View File

@@ -206,7 +206,7 @@ export const AttachmentDialog = ({
errorOnly={currentFilter === "errors"}
attachments={attachments}
id={index}
context={!isSheet ? "global" : "attachments-list"}
context="global"
/>
);

View File

@@ -188,7 +188,7 @@ const PDFPreview = () => {
}}
color={colors.static.white}
>
{strings.loadingWithProgress(progress?.percent)}
{strings.loadingWithProgress(progress.percent)}
</Paragraph>
</Animated.View>
) : (

View File

@@ -19,8 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useRef } from "react";
import { Platform, StyleSheet, View } from "react-native";
//@ts-ignore
import { useThemeColors } from "@notesnook/theme";
import { Menu } from "react-native-material-menu";
import Menu from "react-native-reanimated-material-menu";
import { notesnook } from "../../../e2e/test.ids";
import {
HeaderRightButton,
@@ -96,16 +97,14 @@ export const RightMenus = ({
style={{
borderRadius: 5,
backgroundColor: contextMenuColors.primary.background,
marginTop: 35
marginTop: -40
}}
onRequestClose={() => {
//@ts-ignore
menuRef.current?.hide();
}}
anchor={
<IconButton
onPress={() => {
//@ts-ignore
menuRef.current?.show();
}}
name="dots-vertical"
@@ -117,10 +116,9 @@ export const RightMenus = ({
{headerRightButtons.map((item) => (
<Button
style={{
width: 150,
justifyContent: "flex-start",
borderRadius: 0,
alignSelf: "flex-start",
width: "100%"
borderRadius: 0
}}
type="plain"
buttonType={{
@@ -129,7 +127,6 @@ export const RightMenus = ({
key={item.title}
title={item.title}
onPress={async () => {
//@ts-ignore
menuRef.current?.hide();
if (Platform.OS === "ios") await sleep(300);
item.onPress();

View File

@@ -81,8 +81,7 @@ const ReminderItem = React.memo(
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
marginTop: 5
flexWrap: "wrap"
}}
>
{item.disabled ? (
@@ -150,8 +149,10 @@ const ReminderItem = React.memo(
fontSize={SIZE.xs}
style={{
justifyContent: "flex-start",
height: 25,
alignSelf: "flex-start"
borderWidth: 0,
height: 30,
alignSelf: "flex-start",
marginTop: 5
}}
/>
</View>

View File

@@ -70,7 +70,6 @@ const SelectionWrapper = ({
}
const onLongPress = () => {
if (isSheet) return;
if (useSelectionStore.getState().selectionMode !== item.type) {
useSelectionStore.getState().setSelectionMode(item.type);
}
@@ -79,7 +78,7 @@ const SelectionWrapper = ({
return (
<Pressable
customColor={isSheet ? colors.secondary.background : "transparent"}
customColor={isSheet ? colors.primary.hover : "transparent"}
testID={testID}
onLongPress={onLongPress}
onPress={onPress}

View File

@@ -26,7 +26,7 @@ import {
Platform,
View
} from "react-native";
import { Menu } from "react-native-material-menu";
import Menu from "react-native-reanimated-material-menu/src/Menu";
import { db } from "../../common/database";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { ToastManager } from "../../services/event-manager";
@@ -101,14 +101,11 @@ export const SelectionHeader = React.memo(
};
const deleteItem = async () => {
if (!type) return;
presentDialog({
title: strings.doActions.delete[
type as keyof typeof strings.doActions.delete
](selectedItemsList.length),
paragraph: strings.actionConfirmations.delete[
type as keyof typeof strings.doActions.delete
](selectedItemsList.length),
title: strings.doActions.delete[type](selectedItemsList.length),
paragraph: strings.actionConfirmations.delete[type](
selectedItemsList.length
),
positiveText: strings.delete(),
negativeText: strings.cancel(),
positivePress: async () => {
@@ -221,16 +218,14 @@ export const SelectionHeader = React.memo(
style={{
borderRadius: 5,
backgroundColor: contextMenuColors.primary.background,
marginTop: 35
marginTop: -20
}}
onRequestClose={() => {
//@ts-ignore
menuRef.current?.hide();
}}
anchor={
<IconButton
onPress={() => {
//@ts-ignore
menuRef.current?.show();
}}
name="dots-vertical"
@@ -324,10 +319,9 @@ export const SelectionHeader = React.memo(
!item.visible ? null : (
<Button
style={{
width: 150,
justifyContent: "flex-start",
borderRadius: 0,
alignSelf: "flex-start",
width: "100%"
borderRadius: 0
}}
type="plain"
buttonType={{
@@ -337,7 +331,6 @@ export const SelectionHeader = React.memo(
key={item.title}
title={item.title}
onPress={async () => {
//@ts-ignore
menuRef.current?.hide();
if (Platform.OS === "ios") await sleep(300);
item.onPress();

View File

@@ -88,14 +88,14 @@ export const RelationsList = ({
sortDirection: "desc"
})
.then((grouped) => {
setTimeout(() => {
setItems(grouped);
}, 300);
setItems(grouped);
});
}, [relationType, referenceType, item?.id, item?.type, updater]);
}, [relationType, referenceType, item?.id, item?.type]);
return (
<View style={{ paddingHorizontal: 12, height: "100%" }}>
<View
style={{ paddingHorizontal: 12, height: hasNoRelations ? 300 : "100%" }}
>
<SheetProvider context="local" />
<DialogHeader
title={title}

View File

@@ -68,19 +68,19 @@ export default function ReminderNotify({
const QuickActions = [
{
title: `5 ${strings.timeShort.minute()}`,
title: `5 ${strings.timeShort.minute}`,
time: 5
},
{
title: `15 ${strings.timeShort.minute()}`,
title: `15 ${strings.timeShort.minute}`,
time: 15
},
{
title: `30 ${strings.timeShort.minute()}`,
title: `30 ${strings.timeShort.minute}`,
time: 30
},
{
title: `1 ${strings.timeShort.hour()}`,
title: `1 ${strings.timeShort.hour}`,
time: 60
}
];

View File

@@ -124,11 +124,9 @@ export default function ReminderSheet({
const referencedItem = reference ? (reference as Note) : null;
const title = useRef<string | undefined>(
!reminder ? referencedItem?.title : reminder?.title
);
const details = useRef<string | undefined>(
!reminder ? referencedItem?.headline : reminder?.description
reminder?.title || referencedItem?.title
);
const details = useRef<string | undefined>(reminder?.description);
const titleRef = useRef<TextInput>(null);
const timer = useRef<NodeJS.Timeout>();
@@ -545,7 +543,7 @@ export default function ReminderSheet({
/>
{reminderMode === ReminderModes.Permanent ? null : (
<RNScrollView
<ScrollView
style={{
flexDirection: "row",
marginTop: 12,
@@ -590,7 +588,7 @@ export default function ReminderSheet({
}}
/>
))}
</RNScrollView>
</ScrollView>
)}
</ScrollView>

View File

@@ -51,6 +51,7 @@ export const ReminderTime = ({
<Button
title={time}
key={reminder.id}
height={20}
icon="bell"
fontSize={SIZE.xs}
iconSize={SIZE.sm}
@@ -66,10 +67,12 @@ export const ReminderTime = ({
marginRight: 0
}}
style={{
height: "auto",
borderRadius: 5,
marginRight: 5,
borderWidth: 0.5,
borderColor: colors.primary.border,
paddingHorizontal: 6,
marginBottom: 5,
...(style as ViewStyle)
}}
{...props}

View File

@@ -33,17 +33,17 @@
"@readme/data-urls": "3.0.0",
"react-native-wheel-color-picker": "^1.3.1",
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@tanstack/react-query": "^4.36.1",
"@trpc/client": "10.45.2",
"@trpc/react-query": "10.45.2",
"@trpc/server": "10.45.2",
"@streetwriters/kysely": "^0.27.4",
"pathe": "1.1.2",
"react-native-format-currency": "0.0.5",
"@lingui/react": "4.11.2",
"@lingui/core": "4.11.2",
"react-native-check-version": "^1.3.0",
"react-native-material-menu": "^2.0.0",
"@trpc/client": "^10.45.2",
"@trpc/react-query": "^10.45.2",
"@trpc/server": "^10.45.2",
"@tanstack/react-query": "^4.36.1"
"react-native-reanimated-material-menu": "github:ammarahm-ed/react-native-reanimated-material-menu"
},
"sideEffects": false
}

View File

@@ -34,7 +34,6 @@ import { EditorEvents } from "./tiptap/utils";
import { useThemeColors } from "@notesnook/theme";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { db } from "../../common/database";
import { i18n } from "@lingui/core";
const onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
if (request.url.includes("https")) {
@@ -144,17 +143,10 @@ export function ReadonlyEditor(props: {
ref={editorRef}
key={"readonly-editor:" + props.editorId}
nestedScrollEnabled
injectedJavaScript={`
globalThis.__DEV__ = ${__DEV__}
globalThis.readonlyEditor=true;
globalThis.LINGUI_LOCALE = "${i18n.locale}";
globalThis.LINGUI_LOCALE_DATA = ${JSON.stringify({
[i18n.locale]: i18n.messages
})};
globalThis.loadApp();`}
injectedJavaScriptBeforeContentLoaded={`globalThis.readonlyEditor=true;`}
injectedJavaScript="globalThis.readonlyEditor=true;"
useSharedProcessPool={false}
javaScriptEnabled={true}
webviewDebuggingEnabled={__DEV__}
focusable={true}
setSupportMultipleWindows={false}
overScrollMode="never"

View File

@@ -37,7 +37,6 @@ export type EditorState = {
scrollPosition: number;
overlay?: boolean;
initialLoadCalled?: boolean;
editorStateRestored?: boolean;
};
export type Settings = {

View File

@@ -861,13 +861,9 @@ export const useEditor = (
state.current.currentlyEditing = true;
state.current.movedAway = false;
if (!state.current.editorStateRestored) {
state.current.isRestoringState = true;
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1, false);
}
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1, false);
}
clearAppState();
state.current.isRestoringState = false;
}, []);

View File

@@ -29,7 +29,6 @@ import { useAttachmentProgress } from "../../hooks/use-attachment-progress";
import { useDBItem } from "../../hooks/use-db-item";
import { useAttachmentStore } from "../../stores/use-attachment-store";
import { SIZE } from "../../utils/size";
import { strings } from "@notesnook/intl";
export const AttachmentGroupProgress = (props: { groupId?: string }) => {
const { colors } = useThemeColors();
@@ -91,12 +90,11 @@ export const AttachmentGroupProgress = (props: { groupId?: string }) => {
}}
numberOfLines={1}
>
{strings.downloading()} {file?.filename}{" "}
{formatBytes(file?.size || 0)}{" "}
Downloading {file?.filename} {formatBytes(file?.size || 0)}{" "}
{fileProgress?.percent ? `(${fileProgress.percent})` : ""}
</Paragraph>
<Paragraph size={10} color={colors.secondary.paragraph}>
{strings.group()}: {props.groupId}
Group: {props.groupId}
</Paragraph>
</View>
{props.groupId === "offline-mode" ? null : (

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { Menu, MenuItem } from "react-native-material-menu";
import Menu, { MenuItem } from "react-native-reanimated-material-menu";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { Dialog } from "../../../components/dialog";
import { Pressable } from "../../../components/ui/pressable";
@@ -146,7 +146,7 @@ export function SettingsPicker<T>({
onChange(item);
}
}}
pressColor={colors.primary.hover}
underlayColor={colors.primary.hover}
style={{
backgroundColor: compareValue(currentValue, item)
? colors.selected.background

View File

@@ -1166,9 +1166,7 @@ export const settingsGroups: SettingSection[] = [
type: "component",
hidden: () => !useUserStore.getState().user,
name: strings.automaticBackupsWithAttachments(),
description: [
...strings.automaticBackupsWithAttachmentsDesc()
].join("\n"),
description: strings.automaticBackupsWithAttachmentsDesc(),
component: "autobackupsattachments"
},
{

View File

@@ -123,7 +123,6 @@ export type PresentSheetOptions = {
};
export function presentSheet(data: Partial<PresentSheetOptions>) {
console.log("PRESENTING...");
eSendEvent(eOpenSheet, data);
}

View File

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

View File

@@ -1063,7 +1063,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1137,7 +1137,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1168,7 +1168,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1242,7 +1242,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1401,7 +1401,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1413,7 +1413,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1444,7 +1444,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1457,7 +1457,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1487,7 +1487,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1561,7 +1561,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1592,7 +1592,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2120;
CURRENT_PROJECT_VERSION = 2118;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1667,7 +1667,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.23;
MARKETING_VERSION = 3.0.21;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -217,7 +217,7 @@ module.exports = (env) => {
/node_modules(.*[/\\])+@tanstack[/\\]react-query/,
/node_modules(.*[/\\])+@trpc[/\\]react-query/,
/node_modules(.*[/\\])+katex/,
/node_modules(.*[/\\])+react-native-material-menu/,
/node_modules(.*[/\\])+mime/,
/node_modules(.*[/\\])+@notesnook[/\\]core/,
/node_modules(.*[/\\])+whatwg-url-without-unicode/,
/node_modules(.*[/\\])+whatwg-url/,

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/mobile",
"version": "3.0.22",
"version": "3.0.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/mobile",
"version": "3.0.22",
"version": "3.0.21",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -14,6 +14,7 @@
"app/"
],
"dependencies": {
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
"@notesnook/common": "file:../../packages/common",
"@notesnook/core": "file:../../packages/core",
"@notesnook/editor": "file:../../packages/editor",
@@ -24,7 +25,8 @@
"@notesnook/themes-server": "file:../../servers/themes",
"diffblazer": "^1.0.1",
"react": "18.2.0",
"react-native": "0.74.5"
"react-native": "0.74.5",
"react-native-actions-sheet": "^0.9.7"
},
"devDependencies": {
"fonteditor-core": "^2.1.11",
@@ -1045,7 +1047,6 @@
"@readme/data-urls": "^3.0.0",
"@streetwriters/kysely": "^0.27.4",
"@streetwriters/showdown": "^3.0.9-alpha",
"@types/mime-db": "^1.43.5",
"async-mutex": "^0.3.2",
"dayjs": "1.11.9",
"dom-serializer": "^2.0.0",
@@ -1058,7 +1059,7 @@
"katex": "0.16.2",
"linkedom": "^0.14.17",
"liqe": "^1.13.0",
"mime-db": "^1.53.0",
"mime": "^4.0.4",
"prismjs": "^1.29.0",
"qclone": "^1.2.0",
"rfdc": "^1.3.0",
@@ -7734,7 +7735,7 @@
},
"../../packages/editor-mobile/node_modules/@types/prop-types": {
"version": "15.7.11",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"../../packages/editor-mobile/node_modules/@types/q": {
@@ -7754,7 +7755,7 @@
},
"../../packages/editor-mobile/node_modules/@types/react": {
"version": "18.2.39",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -7785,7 +7786,7 @@
},
"../../packages/editor-mobile/node_modules/@types/scheduler": {
"version": "0.16.8",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"../../packages/editor-mobile/node_modules/@types/semver": {
@@ -12610,7 +12611,7 @@
},
"../../packages/editor-mobile/node_modules/immer": {
"version": "9.0.21",
"dev": true,
"devOptional": true,
"license": "MIT",
"funding": {
"type": "opencollective",
@@ -23082,7 +23083,6 @@
},
"../../packages/editor/node_modules/js-tokens": {
"version": "4.0.0",
"dev": true,
"license": "MIT"
},
"../../packages/editor/node_modules/jsesc": {
@@ -23133,7 +23133,6 @@
},
"../../packages/editor/node_modules/loose-envify": {
"version": "1.4.0",
"dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -23645,7 +23644,6 @@
},
"../../packages/editor/node_modules/react": {
"version": "18.3.1",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
@@ -23664,7 +23662,6 @@
},
"../../packages/editor/node_modules/react-dom": {
"version": "18.3.1",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
@@ -23803,7 +23800,6 @@
},
"../../packages/editor/node_modules/scheduler": {
"version": "0.23.2",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
@@ -28896,9 +28892,9 @@
"@streetwriters/kysely": "^0.27.4",
"@streetwriters/showdown": "^3.0.1-alpha.2",
"@tanstack/react-query": "^4.36.1",
"@trpc/client": "^10.45.2",
"@trpc/react-query": "^10.45.2",
"@trpc/server": "^10.45.2",
"@trpc/client": "10.45.2",
"@trpc/react-query": "10.45.2",
"@trpc/server": "10.45.2",
"absolutify": "^0.1.0",
"buffer": "^6.0.3",
"dayjs": "^1.10.4",
@@ -28916,9 +28912,9 @@
"react-native-format-currency": "0.0.5",
"react-native-image-zoom-viewer": "^3.0.1",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-material-menu": "^2.0.0",
"react-native-progress": "^5.0.0",
"react-native-qrcode-svg": "^6.0.6",
"react-native-reanimated-material-menu": "github:ammarahm-ed/react-native-reanimated-material-menu",
"react-native-reanimated-progress-bar": "1.0.1",
"react-native-swiper-flatlist": "3.2.2",
"react-native-wheel-color-picker": "^1.3.1",
@@ -28929,6 +28925,70 @@
"zustand": "^3.6.0"
}
},
"app/node_modules/@tanstack/query-core": {
"version": "4.36.1",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"app/node_modules/@tanstack/react-query": {
"version": "4.36.1",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "4.36.1",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-native": "*"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"app/node_modules/@trpc/client": {
"version": "10.45.2",
"funding": [
"https://trpc.io/sponsor"
],
"license": "MIT",
"peerDependencies": {
"@trpc/server": "10.45.2"
}
},
"app/node_modules/@trpc/react-query": {
"version": "10.45.2",
"funding": [
"https://trpc.io/sponsor"
],
"license": "MIT",
"peerDependencies": {
"@tanstack/react-query": "^4.18.0",
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"app/node_modules/@trpc/server": {
"version": "10.45.2",
"funding": [
"https://trpc.io/sponsor"
],
"license": "MIT"
},
"native": {
"name": "@notesnook/mobile-native",
"version": "1.0.0",
@@ -28937,7 +28997,6 @@
"@ammarahmed/notifee-react-native": "7.4.7",
"@ammarahmed/react-native-background-fetch": "^4.2.2",
"@ammarahmed/react-native-eventsource": "1.1.0",
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
"@ammarahmed/react-native-share-extension": "^2.6.0",
"@ammarahmed/react-native-sodium": "1.5.6",
"@bam.tech/react-native-image-resizer": "3.0.5",
@@ -29214,7 +29273,6 @@
},
"node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.22.5"
@@ -29334,7 +29392,6 @@
},
"node_modules/@babel/helper-hoist-variables": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.22.5"
@@ -29594,7 +29651,6 @@
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
"integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
},
@@ -29609,7 +29665,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz",
"integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
@@ -29758,7 +29813,6 @@
"version": "7.21.0-placeholder-for-preset-env.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
"integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
"dev": true,
"engines": {
"node": ">=6.9.0"
},
@@ -29771,7 +29825,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
"integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -29806,7 +29859,6 @@
},
"node_modules/@babel/plugin-syntax-class-properties": {
"version": "7.12.13",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.12.13"
@@ -29819,7 +29871,6 @@
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
"integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.14.5"
},
@@ -29857,7 +29908,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.3"
},
@@ -29882,7 +29932,6 @@
"version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz",
"integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -29897,7 +29946,6 @@
"version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz",
"integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -29912,7 +29960,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
"integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4"
},
@@ -29924,7 +29971,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -30024,7 +30070,6 @@
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.14.5"
},
@@ -30052,7 +30097,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
"integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -30081,7 +30125,6 @@
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz",
"integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
@@ -30112,7 +30155,6 @@
},
"node_modules/@babel/plugin-transform-block-scoped-functions": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30141,7 +30183,6 @@
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz",
"integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==",
"dev": true,
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30157,7 +30198,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz",
"integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==",
"dev": true,
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5",
@@ -30222,7 +30262,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
"integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30238,7 +30277,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
"integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -30253,7 +30291,6 @@
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
"integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
},
@@ -30266,7 +30303,6 @@
},
"node_modules/@babel/plugin-transform-exponentiation-operator": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
@@ -30283,7 +30319,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz",
"integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
@@ -30311,7 +30346,6 @@
},
"node_modules/@babel/plugin-transform-for-of": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30342,7 +30376,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz",
"integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-json-strings": "^7.8.3"
@@ -30371,7 +30404,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz",
"integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
@@ -30385,7 +30417,6 @@
},
"node_modules/@babel/plugin-transform-member-expression-literals": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30401,7 +30432,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
"integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
"dev": true,
"dependencies": {
"@babel/helper-module-transforms": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30432,7 +30462,6 @@
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz",
"integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==",
"dev": true,
"dependencies": {
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-module-transforms": "^7.22.5",
@@ -30450,7 +30479,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
"integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
"dev": true,
"dependencies": {
"@babel/helper-module-transforms": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30480,7 +30508,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
"integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -30510,7 +30537,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz",
"integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
@@ -30526,7 +30552,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz",
"integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
@@ -30543,7 +30568,6 @@
},
"node_modules/@babel/plugin-transform-object-super": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
@@ -30560,7 +30584,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz",
"integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
@@ -30634,7 +30657,6 @@
},
"node_modules/@babel/plugin-transform-property-literals": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30704,7 +30726,6 @@
},
"node_modules/@babel/plugin-transform-regenerator": {
"version": "7.22.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
@@ -30721,7 +30742,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
"integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -30814,7 +30834,6 @@
"version": "7.24.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz",
"integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -30845,7 +30864,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
"integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
@@ -30860,7 +30878,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz",
"integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30890,7 +30907,6 @@
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz",
"integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
"@babel/helper-plugin-utils": "^7.22.5"
@@ -30906,7 +30922,6 @@
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz",
"integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.22.5",
"@babel/helper-compilation-targets": "^7.22.5",
@@ -31000,7 +31015,6 @@
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
"integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
@@ -31016,7 +31030,6 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -34176,79 +34189,10 @@
"url": "https://www.paypal.me/tiviesantos"
}
},
"node_modules/@tanstack/query-core": {
"version": "4.36.1",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.36.1.tgz",
"integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "4.36.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.36.1.tgz",
"integrity": "sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==",
"dependencies": {
"@tanstack/query-core": "4.36.1",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-native": "*"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/@tokenizer/token": {
"version": "0.3.0",
"license": "MIT"
},
"node_modules/@trpc/client": {
"version": "10.45.2",
"resolved": "https://registry.npmjs.org/@trpc/client/-/client-10.45.2.tgz",
"integrity": "sha512-ykALM5kYWTLn1zYuUOZ2cPWlVfrXhc18HzBDyRhoPYN0jey4iQHEFSEowfnhg1RvYnrAVjNBgHNeSAXjrDbGwg==",
"funding": [
"https://trpc.io/sponsor"
],
"peerDependencies": {
"@trpc/server": "10.45.2"
}
},
"node_modules/@trpc/react-query": {
"version": "10.45.2",
"resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-10.45.2.tgz",
"integrity": "sha512-BAqb9bGZIscroradlNx+Cc9522R+idY3BOSf5z0jHUtkxdMbjeGKxSSMxxu7JzoLqSIEC+LVzL3VvF8sdDWaZQ==",
"funding": [
"https://trpc.io/sponsor"
],
"peerDependencies": {
"@tanstack/react-query": "^4.18.0",
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@trpc/server": {
"version": "10.45.2",
"resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.45.2.tgz",
"integrity": "sha512-wOrSThNNE4HUnuhJG6PfDRp4L2009KDVxsd+2VYH8ro6o/7/jwYZ8Uu5j+VaW+mOmc8EHerHzGcdbGNQSAUPgg==",
"funding": [
"https://trpc.io/sponsor"
]
},
"node_modules/@tsconfig/react-native": {
"version": "3.0.2",
"dev": true,
@@ -34294,8 +34238,7 @@
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/graceful-fs": {
"version": "4.1.6",
@@ -34401,12 +34344,12 @@
},
"node_modules/@types/prop-types": {
"version": "15.7.5",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.2.13",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -34449,7 +34392,7 @@
},
"node_modules/@types/scheduler": {
"version": "0.16.3",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/@types/semver": {
@@ -34762,7 +34705,6 @@
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
"dev": true,
"dependencies": {
"@webassemblyjs/helper-numbers": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
@@ -34771,26 +34713,22 @@
"node_modules/@webassemblyjs/floating-point-hex-parser": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
"dev": true
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
},
"node_modules/@webassemblyjs/helper-api-error": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
"dev": true
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
"dev": true
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw=="
},
"node_modules/@webassemblyjs/helper-numbers": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
"dev": true,
"dependencies": {
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
@@ -34800,14 +34738,12 @@
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
"dev": true
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -34819,7 +34755,6 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
"dev": true,
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
@@ -34828,7 +34763,6 @@
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
"dev": true,
"dependencies": {
"@xtuc/long": "4.2.2"
}
@@ -34836,14 +34770,12 @@
"node_modules/@webassemblyjs/utf8": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
"dev": true
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -34859,7 +34791,6 @@
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
@@ -34872,7 +34803,6 @@
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
@@ -34884,7 +34814,6 @@
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
@@ -34898,7 +34827,6 @@
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
"dev": true,
"dependencies": {
"@webassemblyjs/ast": "1.11.6",
"@xtuc/long": "4.2.2"
@@ -34956,14 +34884,12 @@
"node_modules/@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
"dev": true
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
},
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
@@ -35942,7 +35868,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
"dev": true,
"engines": {
"node": ">=6.0"
}
@@ -36373,7 +36298,7 @@
},
"node_modules/csstype": {
"version": "3.1.2",
"dev": true,
"devOptional": true,
"license": "MIT"
},
"node_modules/date-fns": {
@@ -36959,7 +36884,6 @@
"version": "5.17.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -37082,8 +37006,7 @@
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"dev": true
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw=="
},
"node_modules/es-set-tostringtag": {
"version": "2.0.1",
@@ -37417,7 +37340,6 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
@@ -37430,7 +37352,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
@@ -37594,7 +37515,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -37606,7 +37526,6 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
@@ -37615,7 +37534,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -38369,8 +38287,7 @@
"node_modules/glob-to-regexp": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"dev": true
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
},
"node_modules/global": {
"version": "4.4.0",
@@ -40456,8 +40373,7 @@
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"dev": true
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
"node_modules/json-schema-ref-resolver": {
"version": "1.0.1",
@@ -40933,7 +40849,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
"dev": true,
"engines": {
"node": ">=6.11.5"
}
@@ -41764,8 +41679,7 @@
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
@@ -43154,7 +43068,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
@@ -43562,15 +43475,6 @@
"version": "4.0.5",
"license": "MIT"
},
"node_modules/react-native-material-menu": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-native-material-menu/-/react-native-material-menu-2.0.0.tgz",
"integrity": "sha512-SmO9PLE3E469EPbVWZqvdu6JGPPZIm7YjqDcWs2PPoY0k7w2V9tFo3BmmLXNzNZDCVCAi+PPSsL7h/5WkfHcSg==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-mmkv-storage": {
"version": "0.10.2",
"license": "MIT",
@@ -43686,6 +43590,14 @@
"react-native": "*"
}
},
"node_modules/react-native-reanimated-material-menu": {
"version": "2.0.0",
"resolved": "git+ssh://git@github.com/ammarahm-ed/react-native-reanimated-material-menu.git#b1b19ba9e87333c76eb8abc3dc8377fe3ddd8bfc",
"peerDependencies": {
"react": ">= 16.3.0",
"react-native": ">= 0.54.0"
}
},
"node_modules/react-native-reanimated-progress-bar": {
"version": "1.0.1",
"license": "MIT",
@@ -44089,7 +44001,6 @@
},
"node_modules/regenerator-transform": {
"version": "0.15.1",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.8.4"
@@ -44442,7 +44353,6 @@
},
"node_modules/serialize-javascript": {
"version": "6.0.1",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"randombytes": "^2.1.0"
@@ -45100,7 +45010,6 @@
},
"node_modules/tapable": {
"version": "2.2.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -45178,7 +45087,6 @@
"version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.17",
"jest-worker": "^27.4.5",
@@ -45212,7 +45120,6 @@
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
"dev": true,
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
@@ -45226,7 +45133,6 @@
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -45802,7 +45708,6 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"dev": true,
"dependencies": {
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.1.2"
@@ -45826,7 +45731,6 @@
"version": "5.94.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"dev": true,
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@@ -45942,7 +45846,6 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"dev": true,
"engines": {
"node": ">=10.13.0"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.0.23",
"version": "3.0.21",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -45,6 +45,7 @@
"@notesnook/themes-server": "file:../../servers/themes",
"diffblazer": "^1.0.1",
"react": "18.2.0",
"react-native": "0.74.5"
"react-native": "0.74.5",
"react-native-actions-sheet": "^0.9.7"
}
}
}

View File

@@ -1,19 +0,0 @@
diff --git a/node_modules/react-native-material-menu/dist/Menu.js b/node_modules/react-native-material-menu/dist/Menu.js
index 64fbf13..c7fcee0 100644
--- a/node_modules/react-native-material-menu/dist/Menu.js
+++ b/node_modules/react-native-material-menu/dist/Menu.js
@@ -132,10 +132,13 @@ class Menu extends react_1.default.Component {
else if (left < SCREEN_INDENT) {
left = SCREEN_INDENT;
}
+ console.log(top, windowHeight - menuHeight - SCREEN_INDENT);
// Flip by Y axis if menu hits bottom screen border
if (top > windowHeight - menuHeight - SCREEN_INDENT) {
+ const diff = top - (windowHeight - menuHeight - SCREEN_INDENT);
+ const fraction = (diff / menuHeight);
transforms.push({
- translateY: react_native_1.Animated.multiply(menuSizeAnimation.y, -1),
+ translateY: react_native_1.Animated.multiply(menuSizeAnimation.y, -(fraction + 1)),
});
top = windowHeight - SCREEN_INDENT;
top = Math.min(windowHeight - SCREEN_INDENT, top + buttonHeight);

View File

@@ -0,0 +1,600 @@
diff --git a/node_modules/react-native-reanimated-material-menu/src/Menu.js b/node_modules/react-native-reanimated-material-menu/src/Menu.js
deleted file mode 100644
index 69065f0..0000000
--- a/node_modules/react-native-reanimated-material-menu/src/Menu.js
+++ /dev/null
@@ -1,268 +0,0 @@
-import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
-import {
- Dimensions, I18nManager, Modal,
- Platform,
- StatusBar,
- StyleSheet,
- TouchableWithoutFeedback,
- View
-} from 'react-native';
-import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated";
-
-const STATES = {
- HIDDEN: 'HIDDEN',
- ANIMATING: 'ANIMATING',
- SHOWN: 'SHOWN',
-};
-
-const EASING = Easing.bezier(0.4, 0, 0.2, 1);
-const SCREEN_INDENT = 8;
-
-const Menu = ({ animationDuration = 300, ...props }, ref) => {
- const container = useRef();
- const [state, setState] = useState({
- menuState: STATES.HIDDEN,
-
- top: 0,
- left: 0,
-
- menuWidth: 0,
- menuHeight: 0,
-
- buttonWidth: 0,
- buttonHeight: 0,
- });
- const menuSizeXAnimation = useSharedValue(0);
- const menuSizeYAnimation = useSharedValue(0);
- const opacityAnimation = useSharedValue(0);
-
- const _onMenuLayout = e => {
- if (state.menuState === STATES.ANIMATING) {
- return;
- }
- const { width, height } = e.nativeEvent.layout;
- setState(state => {
- return {
- ...state,
- menuState: STATES.ANIMATING,
- menuWidth: width,
- menuHeight: height,
- }
- }
-
- );
- };
-
- useEffect(() => {
- if (menuState === STATES.ANIMATING) {
-
- menuSizeXAnimation.value = withTiming(state.menuWidth, {
- duration: animationDuration * 2,
- easing: EASING
- })
- menuSizeYAnimation.value = withTiming(state.menuHeight, {
- duration: animationDuration,
- easing: EASING
- })
- opacityAnimation.value = withTiming(1, {
- duration: animationDuration + 25,
- easing: EASING
- })
- }
- }, [state])
-
- const _onDismiss = () => {
- if (props.onHidden) {
- props.onHidden();
- }
- };
- useImperativeHandle(ref, () => {
- return {
- show: () => {
- container.current.measureInWindow((left, top, buttonWidth, buttonHeight) => {
-
- setState(state => {
-
- return {
- ...state,
- buttonHeight,
- buttonWidth,
- left,
- menuState: STATES.SHOWN,
- top,
- }
- });
- });
- },
-
- hide: hide
- }
-
- }, [hide, container])
-
- const hide = onHidden => {
- opacityAnimation.value = withTiming(0, {
- duration: animationDuration,
- easing: EASING
- });
- setTimeout(() => {
- setState(
- state => {
- return {
- ...state,
- menuState: STATES.HIDDEN,
- }
- }
- );
- menuSizeXAnimation.value = 0;
- menuSizeYAnimation.value = 0;
- opacityAnimation.value = 0;
-
- onHidden && onHidden();
- if (Platform.OS !== 'ios' && props.onHidden) {
- props.onHidden();
- }
- }, props.animationDuration)
-
- };
-
- // @@ TODO: Rework this
- const _hide = () => {
- hide();
- };
-
-
- const menuSize = useAnimatedStyle(() => {
- return {
- width: menuSizeXAnimation.value,
- height: menuSizeYAnimation.value,
- }
- });
- const shadowMenuContainerStyle = useAnimatedStyle(() => {
- return {
- opacity: opacityAnimation.value,
- };
- }, [state])
-
- const { isRTL } = I18nManager;
- const dimensions = Dimensions.get('window');
- const { width: windowWidth } = dimensions;
- const windowHeight = dimensions.height - (StatusBar.currentHeight || 0);
- const {
- menuWidth,
- menuHeight,
- buttonWidth,
- buttonHeight,
- } = state;
-
- // Adjust position of menu
- let { left, top } = state;
- const transforms = [];
- if (
- (isRTL && left + buttonWidth - menuWidth > SCREEN_INDENT) ||
- (!isRTL && left + menuWidth > windowWidth - SCREEN_INDENT)
- ) {
- transforms.push({
- translateX: menuSizeXAnimation.value * -1,
- });
-
- left = Math.min(windowWidth - SCREEN_INDENT, left + buttonWidth);
- } else if (left < SCREEN_INDENT) {
- left = SCREEN_INDENT;
- }
-
-
- // Flip by Y axis if menu hits bottom screen border
- if (top > windowHeight - menuHeight - SCREEN_INDENT) {
- transforms.push({
- translateY: menuSizeYAnimation.value * -1,
- });
-
- top = windowHeight - SCREEN_INDENT;
- top = Math.min(windowHeight - SCREEN_INDENT, top + buttonHeight);
- } else if (top < SCREEN_INDENT) {
- top = SCREEN_INDENT;
- }
-
- const extraStyles = {
- transform: transforms,
- top,
-
- // Switch left to right for rtl devices
- ...(isRTL ? { right: left } : { left }),
- }
-
- const { menuState } = state;
- const animationStarted = menuState === STATES.ANIMATING;
- const modalVisible = menuState === STATES.SHOWN || animationStarted;
-
- const { testID, button, style, children } = props;
-
- return <View ref={container} collapsable={false} testID={testID}>
- <View>{button}</View>
-
- <Modal
- visible={modalVisible}
- onRequestClose={_hide}
- supportedOrientations={[
- 'portrait',
- 'portrait-upside-down',
- 'landscape',
- 'landscape-left',
- 'landscape-right',
- ]}
- transparent
- onDismiss={_onDismiss}
- >
- <TouchableWithoutFeedback onPress={_hide} accessible={false}>
- <View style={StyleSheet.absoluteFill}>
- <Animated.View
- onLayout={_onMenuLayout}
- style={[
- styles.shadowMenuContainer,
- shadowMenuContainerStyle,
- extraStyles,
- style,
- ]}
- >
- <Animated.View
- style={[styles.menuContainer, animationStarted && menuSize]}
- >
- {children}
- </Animated.View>
- </Animated.View>
- </View>
- </TouchableWithoutFeedback>
- </Modal>
- </View>
-
-}
-
-
-const styles = StyleSheet.create({
- shadowMenuContainer: {
- position: 'absolute',
- backgroundColor: 'white',
- borderRadius: 4,
- opacity: 0,
- overflow: "hidden",
-
- // Shadow
- ...Platform.select({
- ios: {
- shadowColor: 'black',
- shadowOffset: { width: 0.3 * 5, height: 0.5 * 5 },
- shadowOpacity: 0.2,
- shadowRadius: 0.7 * 5,
- },
- android: {
- elevation: 8,
- },
- }),
- },
- menuContainer: {
- overflow: 'hidden',
- },
-});
-
-export default forwardRef(Menu);
diff --git a/node_modules/react-native-reanimated-material-menu/src/Menu.tsx b/node_modules/react-native-reanimated-material-menu/src/Menu.tsx
new file mode 100644
index 0000000..c3bc1c9
--- /dev/null
+++ b/node_modules/react-native-reanimated-material-menu/src/Menu.tsx
@@ -0,0 +1,303 @@
+import React from 'react';
+
+import {
+ Animated,
+ Dimensions,
+ Easing,
+ I18nManager,
+ LayoutChangeEvent,
+ Modal,
+ Platform,
+ ScrollView,
+ StatusBar,
+ StyleSheet,
+ TouchableWithoutFeedback,
+ View,
+ ViewStyle,
+} from 'react-native';
+
+export interface MenuProps {
+ children?: React.ReactNode;
+ anchor?: React.ReactNode;
+ style?: ViewStyle;
+ onRequestClose?(): void;
+ animationDuration?: number;
+ testID?: string;
+ visible?: boolean;
+}
+
+enum States {
+ Hidden,
+ Animating,
+ Shown,
+}
+
+interface State {
+ buttonHeight: number;
+ buttonWidth: number;
+ left: number;
+ menuHeight: number;
+ menuSizeAnimation: Animated.ValueXY;
+ menuState: States;
+ menuWidth: number;
+ opacityAnimation: Animated.Value;
+ top: number;
+}
+
+const EASING = Easing.bezier(0.4, 0, 0.2, 1);
+const SCREEN_INDENT = 8;
+const SCREEN_INDENT_VERTICAL = 80;
+
+class Menu extends React.Component<MenuProps, State> {
+ _container: View | null = null;
+
+ static defaultProps = {
+ animationDuration: 300,
+ };
+
+ constructor(props: MenuProps) {
+ super(props);
+
+ this.state = {
+ menuState: States.Hidden,
+
+ top: 0,
+ left: 0,
+
+ menuWidth: 0,
+ menuHeight: 0,
+
+ buttonWidth: 0,
+ buttonHeight: 0,
+
+ menuSizeAnimation: new Animated.ValueXY({ x: 0, y: 0 }),
+ opacityAnimation: new Animated.Value(0),
+ };
+ }
+
+ componentDidMount() {
+ if (!this.props.visible) {
+ return;
+ }
+
+ this.show();
+ }
+
+ componentDidUpdate(prevProps: MenuProps) {
+ if (prevProps.visible === this.props.visible) {
+ return;
+ }
+
+ if (this.props.visible) {
+ this.show();
+ } else {
+ this.hide();
+ }
+ }
+
+ private setContainerRef = (ref: View) => {
+ this._container = ref;
+ };
+
+ // Start menu animation
+ private onMenuLayout = (e: LayoutChangeEvent) => {
+ if (this.state.menuState === States.Animating) {
+ return;
+ }
+
+ const { width, height } = e.nativeEvent.layout;
+ let timeout:any = 0;
+ this.setState(
+ {
+ menuState: States.Animating,
+ menuWidth: width,
+ menuHeight: height,
+ },
+ () => {
+ Animated.parallel([
+ Animated.timing(this.state.menuSizeAnimation, {
+ toValue: { x: width, y: height },
+ duration: this.props.animationDuration,
+ easing: EASING,
+ useNativeDriver: false,
+ }),
+ Animated.timing(this.state.opacityAnimation, {
+ toValue: 1,
+ duration: this.props.animationDuration,
+ easing: EASING,
+ useNativeDriver: false,
+ }),
+ ]).start(({finished}) => {
+ if (finished) {
+ clearTimeout(timeout);
+ timeout = setTimeout(() => {
+ this.setState({
+ menuState: States.Shown
+ })
+ },20)
+
+ }
+ });
+ },
+ );
+ };
+
+ show = () => {
+ this._container?.measureInWindow((left, top, buttonWidth, buttonHeight) => {
+ this.setState({
+ buttonHeight,
+ buttonWidth,
+ left,
+ menuState: States.Shown,
+ top,
+ });
+ });
+ };
+
+ hide = () => {
+ Animated.timing(this.state.opacityAnimation, {
+ toValue: 0,
+ duration: this.props.animationDuration,
+ easing: EASING,
+ useNativeDriver: false,
+ }).start(() => {
+ // Reset state
+ this.setState({
+ menuState: States.Hidden,
+ menuSizeAnimation: new Animated.ValueXY({ x: 0, y: 0 }),
+ opacityAnimation: new Animated.Value(0),
+ });
+ });
+ };
+
+ private onRequestClose = () => {
+ this.props.onRequestClose?.();
+ };
+
+ render() {
+ const { isRTL } = I18nManager;
+
+ const dimensions = Dimensions.get('window');
+ const { width: windowWidth } = dimensions;
+ const windowHeight = dimensions.height - (StatusBar.currentHeight || 0);
+
+ const {
+ menuSizeAnimation,
+ menuWidth,
+ menuHeight,
+ buttonWidth,
+ buttonHeight,
+ opacityAnimation,
+ } = this.state;
+ const menuSize = {
+ width: menuSizeAnimation.x,
+ height: menuSizeAnimation.y,
+ };
+
+ // Adjust position of menu
+ let { left, top } = this.state;
+ const transforms:any[] = [];
+
+ if (
+ (isRTL && left + buttonWidth - menuWidth > SCREEN_INDENT) ||
+ (!isRTL && left + menuWidth > windowWidth - SCREEN_INDENT)
+ ) {
+ transforms.push({
+ translateX: Animated.multiply(menuSizeAnimation.x, -1),
+ } as never);
+
+ left = Math.min(windowWidth - SCREEN_INDENT, left + buttonWidth);
+ } else if (left < SCREEN_INDENT) {
+ left = SCREEN_INDENT;
+ }
+
+ // Flip by Y axis if menu hits bottom screen border
+ if (top > windowHeight - menuHeight - SCREEN_INDENT_VERTICAL) {
+ transforms.push({
+ translateY: Animated.multiply(menuSizeAnimation.y, -1),
+ } as never);
+
+ top = windowHeight - SCREEN_INDENT_VERTICAL;
+ top = Math.min(windowHeight - SCREEN_INDENT_VERTICAL, top + buttonHeight);
+ } else if (top < SCREEN_INDENT_VERTICAL) {
+ top = SCREEN_INDENT_VERTICAL;
+ }
+
+ const shadowMenuContainerStyle = {
+ opacity: opacityAnimation,
+ transform: transforms,
+ maxHeight: 500,
+ top,
+
+ // Switch left to right for rtl devices
+ ...(isRTL ? { right: left } : { left }),
+ };
+ const { menuState } = this.state;
+ const animationStarted = menuState === States.Animating;
+ const modalVisible = menuState === States.Shown || animationStarted;
+
+ const { testID, anchor, style, children } = this.props;
+
+ return (
+ <View ref={this.setContainerRef} collapsable={false} testID={testID}>
+ {anchor}
+
+ <Modal
+ visible={modalVisible}
+ onRequestClose={this.onRequestClose}
+ supportedOrientations={[
+ 'portrait',
+ 'portrait-upside-down',
+ 'landscape',
+ 'landscape-left',
+ 'landscape-right',
+ ]}
+ transparent
+ >
+ <TouchableWithoutFeedback onPress={this.onRequestClose} accessible={false}>
+ <View style={StyleSheet.absoluteFill}>
+ <Animated.View
+ onLayout={this.onMenuLayout}
+ style={[styles.shadowMenuContainer, shadowMenuContainerStyle, style]}
+ >
+ <Animated.View style={[styles.menuContainer, animationStarted && menuSize]}>
+ <ScrollView showsVerticalScrollIndicator={menuState !== States.Animating} >
+ {children}
+ </ScrollView>
+ </Animated.View>
+ </Animated.View>
+ </View>
+ </TouchableWithoutFeedback>
+ </Modal>
+ </View>
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ shadowMenuContainer: {
+ position: 'absolute',
+ backgroundColor: 'white',
+ borderRadius: 4,
+ opacity: 0,
+
+ // Shadow
+ ...Platform.select({
+ ios: {
+ shadowColor: 'black',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.14,
+ shadowRadius: 2,
+ },
+ android: {
+ elevation: 8,
+ },
+ }),
+ },
+ menuContainer: {
+ overflow: 'hidden',
+ },
+});
+
+
+export default Menu
\ No newline at end of file
diff --git a/node_modules/react-native-reanimated-material-menu/src/MenuItem.js b/node_modules/react-native-reanimated-material-menu/src/MenuItem.js
index 120a870..d6459c0 100644
--- a/node_modules/react-native-reanimated-material-menu/src/MenuItem.js
+++ b/node_modules/react-native-reanimated-material-menu/src/MenuItem.js
@@ -14,6 +14,11 @@ const Touchable =
? TouchableNativeFeedback
: TouchableHighlight;
+/**
+ *
+ * @param {any} param0
+ * @returns
+ */
function MenuItem({
children,
disabled,

View File

@@ -6,5 +6,3 @@ node_modules
.dev.vars
.wrangler
/output
/fonts

View File

@@ -1,14 +1,18 @@
FROM --platform=$BUILDPLATFORM oven/bun:1.1.36-alpine
FROM --platform=$BUILDPLATFORM node:20-alpine
RUN mkdir -p /home/bun/app && chown -R bun:bun /home/bun/app
RUN mkdir -p /home/node/app && chown -R node:node /home/node/app
WORKDIR /home/bun/app
WORKDIR /home/node/app
USER bun
USER node
COPY --chown=bun:bun output .
COPY --chown=node:node build ./build
RUN bun install
RUN mv build/package.json .
CMD [ "bun", "run", "start" ]
RUN npm install
RUN ls
CMD [ "npm", "run", "start" ]

View File

@@ -21,10 +21,9 @@ import { mdiTimerOutline } from "@mdi/js";
import { Icon } from "@notesnook/ui";
import { Flex, Image, Link, Text } from "@theme-ui/components";
import { SxProp } from "@theme-ui/core";
import { PUBLIC_URL } from "../utils/env";
type Props = SxProp & { publicUrl: string };
export function MonographChat({ sx, publicUrl }: Props) {
export function MonographChat({ sx }: SxProp) {
return (
<Flex
sx={{
@@ -63,7 +62,7 @@ export function MonographChat({ sx, publicUrl }: Props) {
borderRadius: 10,
width: "100%"
}}
src={`${publicUrl}/api/og.jpg?title=Open+sourcing&description=VGhpcyBtb25vZ3JhcGggaXMgZW5jcnlwdGVkLiBFbnRlciBwYXNzd29yZCB0byB2aWV3IGNvbnRlbnRzLg%3D%3D&date=Saturday%2C+February+18%2C+2023`}
src={`${PUBLIC_URL}/api/og.png?title=Open+sourcing&description=VGhpcyBtb25vZ3JhcGggaXMgZW5jcnlwdGVkLiBFbnRlciBwYXNzd29yZCB0byB2aWV3IGNvbnRlbnRzLg%3D%3D&date=Saturday%2C+February+18%2C+2023`}
/>
<Text
mt="12px"
@@ -77,10 +76,10 @@ export function MonographChat({ sx, publicUrl }: Props) {
color: "accent",
overflowWrap: "anywhere"
}}
href={`${publicUrl}/62db75572020209c36f9f9fb`}
href={`${PUBLIC_URL}/62db75572020209c36f9f9fb`}
target="_blank"
>
{publicUrl}/62db75572020209c36f9f9fb
{PUBLIC_URL}/62db75572020209c36f9f9fb
</Link>
</Text>
<Timer time={"5m ago"} sx={{ mb: 1, mr: 1, alignSelf: "end" }} />

View File

@@ -73,11 +73,6 @@ function generateTableOfContents() {
let currentHeading = 0;
for (const heading of headings) {
const isCalloutHeading = heading.closest(".callout");
if (isCalloutHeading) {
continue;
}
const text = heading.textContent || "<empty>";
const nodeName = heading.nodeName;
const headingLevel = levelsMap[nodeName];

View File

@@ -60,7 +60,7 @@ export default function handleRequest(
const styles = constructStyleTagsFromChunks(extractCriticalToChunks(body));
const html = `<!DOCTYPE html><html><head><!--start head-->${head}${styles}<!--end head--></head><body><div id="root">${body}</div></body></html>`;
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
responseHeaders.set("Content-Type", "text/html");
return new Response(html, {
status: responseStatusCode,

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import type { MetaFunction, LoaderFunctionArgs } from "@remix-run/node";
import { Cipher } from "@notesnook/crypto";
import { convert } from "html-to-text";
import { Flex, Text } from "@theme-ui/components";
import { useLoaderData } from "@remix-run/react";
import { MonographPage } from "../components/monographpost";
@@ -45,13 +46,12 @@ type Monograph = {
type MonographResponse = Omit<Monograph, "content"> & { content: string };
export const meta: MetaFunction<typeof loader> = ({ data }) => {
if (!data || !data.metadata || !data.monograph) return [];
const imageUrl = `${PUBLIC_URL}/api/og.jpg?${new URLSearchParams({
const imageUrl = `${PUBLIC_URL}/api/og.png?${new URLSearchParams({
title: data?.metadata?.title || "",
description: data?.metadata?.fullDescription
? Buffer.from(data.metadata.fullDescription, "utf-8").toString("base64")
: "",
description: Buffer.from(
data?.metadata?.fullDescription || "",
"utf-8"
).toString("base64"),
date: data?.metadata?.datePublished || ""
}).toString()}`;
@@ -88,7 +88,7 @@ export async function loader({ params }: LoaderFunctionArgs) {
metadata
};
} catch (e) {
// console.error(e);
console.error(e);
return {
monograph: null,
metadata: {
@@ -134,6 +134,15 @@ export default function MonographPost() {
);
}
const extractParagraph = (html: string) => {
if (!html) return "";
return convert(html, {
wordwrap: false,
preserveNewlines: false,
decodeEntities: true
});
};
type Metadata = {
title: string;
fullDescription: string;
@@ -141,21 +150,6 @@ type Metadata = {
datePublished: string;
};
function extractFirstWords(html: string, numWords = 30): string {
// Strip HTML tags and normalize whitespace
const plainText = html
.replace(/<[^>]*>/g, " ")
.replace(/\s+/g, " ")
.trim();
// Split into words and take first N
const words = plainText.split(" ").slice(0, numWords);
// Add ellipsis if text was truncated
const excerpt = words.join(" ");
return words.length < plainText.split(" ").length ? excerpt + "..." : excerpt;
}
function trimDescription(
str: string,
length: number,
@@ -180,12 +174,12 @@ function addPeriod(str: string) {
return str + "...";
}
function getMonographMetadata(monograph: Monograph): Metadata {
function getMonographMetadata(monograph?: Monograph): Metadata {
const title = monograph?.title || "Not found";
const text = monograph?.encryptedContent
? "This monograph is encrypted. Enter password to view contents."
: monograph?.content
? extractFirstWords(monograph?.content.data, 100)
? extractParagraph(monograph?.content.data)
: "";
const shortDescription = trimDescription(text, 150, true);
const fullDescription = trimDescription(text, 300, true);

View File

@@ -38,7 +38,6 @@ import { Footer } from "../components/footer";
import { Header } from "../components/header";
import { ForwardRef } from "@theme-ui/components/dist/declarations/src/types";
import { PUBLIC_URL } from "../utils/env";
import { useLoaderData } from "@remix-run/react";
export const meta: MetaFunction = () => {
return generateMetaDescriptors({
@@ -52,10 +51,6 @@ export const meta: MetaFunction = () => {
});
};
export async function loader() {
return { publicUrl: PUBLIC_URL };
}
const ButtonLink = Button as ForwardRef<
HTMLButtonElement,
ButtonProps & LinkProps
@@ -79,8 +74,6 @@ const features = [
}
];
export default function Monograph() {
const { publicUrl } = useLoaderData<typeof loader>();
return (
<Flex
sx={{
@@ -153,7 +146,6 @@ export default function Monograph() {
border: "1px solid var(--border)",
boxShadow: "0px -5px 15px 0px rgba(0,0,0,0.05)"
}}
publicUrl={publicUrl}
/>
</Flex>
<Box

View File

@@ -21,6 +21,6 @@ import { LoaderFunctionArgs } from "@remix-run/node";
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
url.pathname += ".jpg";
url.pathname += ".png";
return Response.redirect(url, 308);
}

View File

@@ -1,52 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 { LoaderFunctionArgs } from "@remix-run/node";
import { makeImage } from "../utils/generate-og-image.server";
import { formatDate } from "@notesnook/core";
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const title = url.searchParams.get("title") || "Not found";
const description = url.searchParams.get("description") || "";
const date =
url.searchParams.get("date") ||
formatDate(new Date(), {
type: "date-time",
dateFormat: "YYYY-MM-DD",
timeFormat: "24-hour"
});
return new Response(
await makeImage(
{
date,
description,
title
},
url.search
),
{
status: 200,
headers: {
"Content-Type": "image/jpeg"
}
}
);
}

View File

@@ -18,9 +18,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { LoaderFunctionArgs } from "@remix-run/node";
import { makeImage } from "../utils/generate-og-image.server";
import { formatDate } from "@notesnook/core";
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
url.pathname = url.pathname.replace(/.png/, ".jpg");
return Response.redirect(url, 308);
const title = url.searchParams.get("title") || "Not found";
const description = url.searchParams.get("description") || "";
const date =
url.searchParams.get("date") ||
formatDate(new Date(), {
type: "date-time",
dateFormat: "YYYY-MM-DD",
timeFormat: "24-hour"
});
return new Response(
await makeImage({
date,
description,
title
}),
{
status: 200,
headers: {
"Content-Type": "image/png"
}
}
);
}

View File

@@ -17,15 +17,12 @@ 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 { json, LoaderFunctionArgs } from "@remix-run/node";
import { cors } from "remix-utils/cors";
import { COMPATIBILITY_VERSION, INSTANCE_NAME } from "../utils/env";
export async function loader({ request }: LoaderFunctionArgs) {
const response = json({
export async function loader() {
return Response.json({
version: COMPATIBILITY_VERSION,
id: "monograph",
instance: INSTANCE_NAME
});
return cors(request, response);
}

View File

@@ -17,12 +17,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const p = "process" in globalThis ? globalThis.process : ({ env: {} } as any);
export const API_HOST =
import.meta.env.API_HOST || p.env.API_HOST || `https://api.notesnook.com`;
import.meta.env.API_HOST ||
process.env.API_HOST ||
`https://api.notesnook.com`;
export const PUBLIC_URL =
import.meta.env.PUBLIC_URL ||
p.env.PUBLIC_URL ||
`http://localhost:${import.meta.env.PORT || p.env.PORT || 5173}`;
process.env.PUBLIC_URL ||
`http://localhost:${import.meta.env.PORT || process.env.PORT || 5017}`;
export const COMPATIBILITY_VERSION = 1;
export const INSTANCE_NAME = p.env.INSTANCE_NAME || "default";
export const INSTANCE_NAME = process.env.INSTANCE_NAME || "default";

View File

@@ -1,174 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 { createCanvas, GlobalFonts, loadImage } from "@napi-rs/canvas";
import { LRUCache } from "lru-cache";
import { ThemeDark } from "@notesnook/theme";
import path from "path";
import { fileURLToPath } from "url";
import { split } from "canvas-hypertxt";
import { readFile } from "fs/promises";
export type OGMetadata = { title: string; description: string; date: string };
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const ROOT = path.join(__dirname, "../../");
const fontMap = JSON.parse(
await readFile(path.join(ROOT, "fonts", "fonts.json"), "utf-8")
);
// Register fonts
const OpenSans = path.join(
__dirname,
import.meta.env.DEV ? "../assets/fonts/" : "../../assets/fonts/",
"open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf"
);
const OpenSansBold = path.join(
__dirname,
import.meta.env.DEV ? "../assets/fonts/" : "../../assets/fonts/",
"open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf"
);
console.log("OpenSans", GlobalFonts.registerFromPath(OpenSans, "OpenSans"));
console.log(
"registering",
"OpenSansBold",
GlobalFonts.registerFromPath(OpenSansBold, "OpenSansBold")
);
const fontFamilies = {
regular: ["OpenSans"],
bold: ["OpenSansBold"]
};
for (const font of fontMap) {
const id = (font.name + font.weight).replace(/ /g, "");
const result = GlobalFonts.registerFromPath(
path.resolve(ROOT, font.path),
id
);
if (!result)
throw new Error(
`Failed to register font: ${id} at ${path.resolve(ROOT, font.path)}`
);
if (font.weight === "600") fontFamilies.bold.push(id);
else fontFamilies.regular.push(id);
console.log("registering", id, result);
}
const cache = new LRUCache<string, Buffer>({
ttl: 1000 * 60 * 60 * 24,
ttlAutopurge: true
});
const WIDTH = 1200;
const HEIGHT = 630;
const PADDING = 50;
const QUALITY = 80;
const logo = loadImage(
import.meta.env.DEV
? path.resolve(__dirname, "../../public/logo.svg")
: path.resolve(__dirname, "../../client/logo.svg")
);
const boldFontFamily = fontFamilies.bold.join(",");
const regularFontFamily = fontFamilies.regular.join(",");
export async function makeImage(metadata: OGMetadata, cacheKey: string) {
if (cache.has(cacheKey)) {
return cache.get(cacheKey)!;
}
console.time("canvas");
const theme = ThemeDark.scopes.base;
const canvas = createCanvas(WIDTH, HEIGHT);
const ctx = canvas.getContext("2d");
// Background
ctx.fillStyle = theme.primary.background;
ctx.fillRect(0, 0, WIDTH, HEIGHT);
// Bottom border
ctx.fillStyle = "#008837";
ctx.fillRect(0, HEIGHT - 10, WIDTH, 10);
// Draw logo
ctx.drawImage(await logo, PADDING, HEIGHT - PADDING - 85, 80, 80);
// Draw bottom text
ctx.fillStyle = theme.primary.heading;
ctx.font = "600 32px OpenSansBold";
ctx.fillText("Notesnook Monograph", PADDING + 95, HEIGHT - PADDING - 55);
ctx.fillStyle = theme.secondary.paragraph;
ctx.font = "25px OpenSans";
ctx.fillText(
"Anonymous, secure, and encrypted note sharing with password protection.",
PADDING + 95,
HEIGHT - PADDING - 19
);
// Draw date
ctx.fillStyle = theme.secondary.paragraph;
ctx.font = "25px OpenSans";
ctx.fillText(metadata.date, PADDING, PADDING + 25);
// Draw title
ctx.fillStyle = theme.primary.heading;
ctx.font = `600 64px ${boldFontFamily}`;
let y = PADDING + 105;
const titleLines = split(
ctx as any,
metadata.title,
`600 64px ${boldFontFamily}`,
WIDTH - PADDING * 2,
true
);
for (const line of titleLines) {
ctx.fillText(line, PADDING, y);
y += 60;
}
// Draw description
ctx.fillStyle = theme.primary.paragraph;
ctx.font = `30px ${regularFontFamily}`;
const description = Buffer.from(
metadata.description || "",
"base64"
).toString("utf-8");
const descLines = split(
ctx as any,
description,
`30px ${regularFontFamily}`,
WIDTH - PADDING * 2,
true
).slice(0, 4);
for (const line of descLines) {
ctx.fillText(line, PADDING, y);
y += 40;
}
const buffer = canvas.toBuffer("image/jpeg", QUALITY);
console.timeEnd("canvas");
cache.set(cacheKey, buffer);
return buffer;
}

View File

@@ -0,0 +1,148 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 satori from "satori";
import { ThemeDark } from "@notesnook/theme";
import { svg2png, initialize } from "svg2png-wasm";
import svg2pngWasm from "svg2png-wasm/svg2png_wasm_bg.wasm?arraybuffer";
import fontRegular from "../assets/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf?arraybuffer";
import fontBold from "../assets/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf?arraybuffer";
export type OGMetadata = { title: string; description: string; date: string };
await initialize(svg2pngWasm);
export async function makeImage(metadata: OGMetadata) {
const theme = ThemeDark.scopes.base;
const svg = await satori(
<div
style={{
flexDirection: "column",
display: "flex",
justifyContent: "space-between",
height: "100%",
borderBottom: "10px solid #008837",
width: "100%",
padding: 50,
margin: 0
}}
>
<div style={{ display: "flex", flexDirection: "column" }}>
<p
style={{ fontSize: 25, margin: 0, color: theme.secondary.paragraph }}
>
{metadata.date}
</p>
<h1
style={{
margin: 0,
marginTop: 5,
fontSize: 64,
fontWeight: 600,
color: theme.primary.heading
}}
>
{metadata.title}
</h1>
<p
style={{
margin: 0,
marginTop: 5,
fontSize: 30,
color: theme.primary.paragraph
}}
>
{Buffer.from(metadata.description || "", "base64").toString("utf-8")}
</p>
</div>
<div style={{ display: "flex", flexDirection: "row", flexShrink: 0 }}>
<svg
width="80"
height="80"
viewBox="0 0 1024 1024"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_25_12)">
<path d="M1024 0H0V1024H1024V0Z" fill="white" />
<path
d="M736.652 699.667C719.397 750.078 684.817 792.732 639.064 820.039C593.311 847.346 539.354 857.535 486.794 848.792C434.234 840.049 386.481 812.942 352.032 772.294C317.583 731.646 298.673 680.095 298.667 626.812V516.562L377.788 549.615V626.767C377.78 647.546 382.221 668.085 390.812 687.005C399.402 705.924 411.943 722.785 427.592 736.455C430.562 739.042 433.644 741.562 436.828 743.914C460.184 761.302 488.23 771.266 517.322 772.511C518.312 772.511 519.268 772.59 520.247 772.612C521.225 772.635 522.497 772.612 523.622 772.612C524.747 772.612 525.872 772.612 526.997 772.612C528.122 772.612 528.932 772.612 529.922 772.511C559.002 771.263 587.038 761.308 610.393 743.936C613.565 741.585 616.648 739.076 619.629 736.489C640.186 718.51 655.286 695.123 663.212 668.989L736.652 699.667Z"
fill="black"
/>
<path
d="M748.667 430.748V626.813C748.667 629.344 748.667 631.887 748.509 634.418L669.545 601.399V430.748C669.533 393.064 654.939 356.847 628.82 329.682C602.702 302.518 567.086 286.514 529.431 285.022C491.777 283.53 455.006 296.666 426.82 321.679C398.634 346.692 381.221 381.641 378.227 419.206C377.945 423.008 377.788 426.867 377.788 430.748V479.461L298.667 446.386V205.748H523.667C583.34 205.748 640.57 229.453 682.766 271.649C724.961 313.845 748.667 371.074 748.667 430.748Z"
fill="black"
/>
</g>
<defs>
<clipPath id="clip0_25_12">
<rect width="1024" height="1024" rx="200" fill="white" />
</clipPath>
</defs>
</svg>
<div
style={{ display: "flex", flexDirection: "column", marginLeft: 15 }}
>
<p
style={{
margin: 0,
fontSize: 32,
fontWeight: 600,
color: theme.primary.heading
}}
>
Notesnook Monograph
</p>
<p
style={{
fontSize: 25,
margin: 0,
color: theme.secondary.paragraph
}}
>
Anonymous, secure, and encrypted note sharing with password
protection.
</p>
</div>
</div>
</div>,
{
width: 1200,
height: 630,
fonts: [
{
name: "Open Sans",
data: fontRegular!,
weight: 400,
style: "normal"
},
{
name: "Open Sans",
data: fontBold!,
weight: 600,
style: "normal"
}
]
}
);
return await svg2png(svg, {
backgroundColor: "black"
});
}

View File

@@ -74,7 +74,7 @@ export async function isSpam(monograph: Monograph) {
}
return isSpam;
} catch (e) {
// console.error(e);
console.error(e);
return false;
}
}

View File

@@ -23,7 +23,7 @@ export async function read<T>(key: string, fallback: T): Promise<T> {
try {
return (JSON.parse(await readFile(key, "utf-8")) as T) || fallback;
} catch (e) {
// console.error(e);
console.error(e);
return fallback;
}
}

View File

@@ -28,11 +28,11 @@ const cache: Record<
export async function read<T>(key: string, fallback: T) {
const cached = cache[key];
if (cached && cached.ttl > Date.now() - cached.cachedAt) {
return cached.value as T;
return cached.value;
}
const value = (await provider).read<T>(key, fallback);
cache[key] = {
ttl: 60 * 60 * 1000,
ttl: 5 * 60000,
value,
cachedAt: Date.now()
};
@@ -40,10 +40,6 @@ export async function read<T>(key: string, fallback: T) {
}
export async function write<T>(key: string, data: T) {
if (cache[key]) {
cache[key].value = data;
cache[key].cachedAt = Date.now();
}
return (await provider).write<T>(key, data);
}

View File

@@ -40,7 +40,7 @@ export async function read<T>(key: string, fallback: T): Promise<T> {
key
});
if (typeof response === "object" && !response.success) {
// console.error("failed:", response.errors);
console.error("failed:", response.errors);
return fallback;
}
return (
@@ -48,7 +48,7 @@ export async function read<T>(key: string, fallback: T): Promise<T> {
fallback
);
} catch (e) {
// console.error(e);
console.error(e);
return fallback;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,22 @@
{
"name": "@notesnook/monograph",
"version": "1.2.2",
"version": "1.1.0",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "npm run fonts && remix vite:build",
"build": "remix vite:build",
"dev": "remix vite:dev",
"typecheck": "tsc",
"fonts": "node scripts/font-loader.mjs",
"start": "bun server.ts"
"start": "remix-serve ./build/server/index.js"
},
"dependencies": {
"@emotion/cache": "11.11.0",
"@emotion/react": "11.11.1",
"@emotion/server": "11.11.0",
"@mdi/js": "^7.4.47",
"@lingui/core": "4.11.4",
"@lingui/react": "4.11.4",
"@mdi/js": "^7.4.47",
"@napi-rs/canvas": "0.1.59",
"@notesnook/core": "file:../../packages/core",
"@notesnook/crypto": "file:../../packages/crypto",
"@notesnook/editor": "file:../../packages/editor",
@@ -30,12 +28,11 @@
"@sagi.io/workers-kv": "^0.0.14",
"@theme-ui/components": "^0.16.2",
"@theme-ui/core": "^0.16.2",
"canvas-hypertxt": "^1.0.3",
"buffer": "^6.0.3",
"comlink": "^4.4.1",
"date-fns": "^4.1.0",
"html-to-text": "^9.0.5",
"isbot": "^5.1.17",
"lru-cache": "^11.0.2",
"mac-scrollbar": "^0.13.6",
"nanoid": "^5.0.7",
"react": "18.3.1",
@@ -44,24 +41,24 @@
"react-turnstile": "^1.1.4",
"refractor": "^4.8.1",
"remix-utils": "^7.7.0",
"satori": "^0.11.1",
"slugify": "^1.6.6",
"svg2png-wasm": "^1.4.1",
"zustand": "^4.5.5"
},
"devDependencies": {
"@remix-run/dev": "^2.12.1",
"@remix-run/serve": "^2.12.1",
"@remix-run/server-runtime": "^2.15.0",
"@types/bun": "^1.1.13",
"@types/bun": "^1.1.10",
"@types/html-to-text": "^9.0.4",
"@types/react": "^18.3.9",
"@types/react-dom": "^18.3.0",
"@types/react-modal": "^3.16.3",
"autoprefixer": "^10.4.20",
"google-fonts-helper": "^3.6.0",
"postcss": "^8.4.47",
"vite": "^5.4.8",
"vite-plugin-arraybuffer": "^0.0.8",
"vite-plugin-static-copy": "^2.1.0",
"vite-plugin-wasm": "^3.3.0",
"vite-tsconfig-paths": "^5.0.1",
"wrangler": "3.78.11"
},

View File

@@ -1,32 +0,0 @@
<svg
width="80"
height="80"
viewBox="0 0 1024 1024"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_25_12)">
<rect
x="0"
y="0"
width="1024"
height="1024"
rx="130"
ry="130"
fill="white"
/>
<path
d="M736.652 699.667C719.397 750.078 684.817 792.732 639.064 820.039C593.311 847.346 539.354 857.535 486.794 848.792C434.234 840.049 386.481 812.942 352.032 772.294C317.583 731.646 298.673 680.095 298.667 626.812V516.562L377.788 549.615V626.767C377.78 647.546 382.221 668.085 390.812 687.005C399.402 705.924 411.943 722.785 427.592 736.455C430.562 739.042 433.644 741.562 436.828 743.914C460.184 761.302 488.23 771.266 517.322 772.511C518.312 772.511 519.268 772.59 520.247 772.612C521.225 772.635 522.497 772.612 523.622 772.612C524.747 772.612 525.872 772.612 526.997 772.612C528.122 772.612 528.932 772.612 529.922 772.511C559.002 771.263 587.038 761.308 610.393 743.936C613.565 741.585 616.648 739.076 619.629 736.489C640.186 718.51 655.286 695.123 663.212 668.989L736.652 699.667Z"
fill="black"
/>
<path
d="M748.667 430.748V626.813C748.667 629.344 748.667 631.887 748.509 634.418L669.545 601.399V430.748C669.533 393.064 654.939 356.847 628.82 329.682C602.702 302.518 567.086 286.514 529.431 285.022C491.777 283.53 455.006 296.666 426.82 321.679C398.634 346.692 381.221 381.641 378.227 419.206C377.945 423.008 377.788 426.867 377.788 430.748V479.461L298.667 446.386V205.748H523.667C583.34 205.748 640.57 229.453 682.766 271.649C724.961 313.845 748.667 371.074 748.667 430.748Z"
fill="black"
/>
</g>
<defs>
<clipPath id="clip0_25_12">
<rect width="1024" height="1024" rx="200" fill="white" />
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,121 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 { createWriteStream, existsSync, writeFileSync } from "fs";
import { constructURL } from "google-fonts-helper";
import { Writable } from "stream";
import { mkdir } from "fs/promises";
const FONTS = [
{ locale: "ja-JP", slug: "Noto+Sans+JP", name: "Noto Sans JP" },
{ locale: "ko-KR", slug: "Noto+Sans+KR", name: "Noto Sans KR" },
{ locale: "zh-CN", slug: "Noto+Sans+SC", name: "Noto Sans SC" },
{ locale: "zh-TW", slug: "Noto+Sans+TC", name: "Noto Sans TC" },
{ locale: "zh-HK", slug: "Noto+Sans+HK", name: "Noto Sans HK" },
{ locale: "th-TH", slug: "Noto+Sans+Thai", name: "Noto Sans Thai" },
{ locale: "bn-IN", slug: "Noto+Sans+Bengali", name: "Noto Sans Bengali" },
{ locale: "ar-AR", slug: "Noto+Sans+Arabic", name: "Noto Sans Arabic" },
{ locale: "ta-IN", slug: "Noto+Sans+Tamil", name: "Noto Sans Tamil" },
{ locale: "ml-IN", slug: "Noto+Sans+Malayalam", name: "Noto Sans Malayalam" },
{ locale: "he-IL", slug: "Noto+Sans+Hebrew", name: "Noto Sans Hebrew" },
{ locale: "te-IN", slug: "Noto+Sans+Telugu", name: "Noto Sans Telugu" },
{
locale: "devanagari",
slug: "Noto+Sans+Devanagari",
name: "Noto Sans Devanagari"
},
{ locale: "kannada", slug: "Noto+Sans+Kannada", name: "Noto Sans Kannada" }
// { locale: "symbol", slug: "Noto+Sans+Symbols", name: "Noto Sans Symbols" },
// {
// locale: "symbol",
// slug: "Noto+Sans+Symbols+2",
// name: "Noto Sans Symbols 2"
// },
// { locale: "math", slug: "Noto+Sans+Math", name: "Noto Sans Math" }
];
async function loadFonts(dir) {
const families = {};
for (const font of FONTS) {
families[font.name] = [400, 600];
}
const css = await (
await fetch(constructURL({ families }), {
headers: {
// Make sure it returns TTF.
"User-Agent":
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
}
})
).text();
const fontFaces = css
.split("@font-face")
.filter(Boolean)
.map((fontFace) => {
const src = fontFace.match(
/src: url\((.+)\) format\('(opentype|truetype)'\)/
);
const family = fontFace.match(/font-family: '(.+)'/);
const weight = fontFace.match(/font-weight: (\d+)/);
const style = fontFace.match(/font-style: (\w+)/);
return {
src: src[1],
family: family[1],
weight: weight[1],
style: style[1]
};
});
await mkdir("fonts", { recursive: true });
const fontMap = [];
for (const face of fontFaces) {
console.log("Downloading", face.family, face.weight);
const font = FONTS.find((font) => font.name === face.family);
if (!font) continue;
const fileName = `${font.slug}+${face.weight}.ttf`;
const path = `fonts/${fileName}`;
if (existsSync(path)) continue;
const fileStream = Writable.toWeb(
createWriteStream(path, {
autoClose: true,
emitClose: true,
flush: true
})
);
await (await fetch(face.src)).body.pipeTo(fileStream);
fontMap.push({
name: font.name,
locale: font.locale,
weight: face.weight,
path
});
}
writeFileSync("fonts/fonts.json", JSON.stringify(fontMap, null, 2));
console.log("Done");
}
loadFonts();

View File

@@ -1,48 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// This server file is used to serve the Remix app in production using Bun.
// run it like so: npm run build; cd output; bun install; bun run start
// Running it directly will give an error.
import type { ServerBuild } from "@remix-run/server-runtime";
import { createRequestHandler } from "@remix-run/server-runtime";
import { resolve } from "node:path";
// @ts-expect-error server is not built yet
import * as build from "./build/server/index";
import { type Serve } from "bun";
const remix = createRequestHandler(
build as unknown as ServerBuild,
Bun.env.NODE_ENV
);
process.env.PORT = process.env.PORT || "3000";
export default {
port: process.env.PORT,
async fetch(request) {
// First we need to send handle static files
const { pathname } = new URL(request.url);
const file = Bun.file(
resolve(__dirname, "./build/client/", `.${pathname}`)
);
if (await file.exists()) return new Response(file);
// Only if a file doesn't exists we send the request to the Remix request handler
return remix(request);
}
} satisfies Serve;

View File

@@ -9,7 +9,7 @@
],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["vite/client", "vite-plugin-arraybuffer/types", "bun"],
"types": ["vite/client", "vite-plugin-arraybuffer/types"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",

View File

@@ -20,11 +20,11 @@ import { vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import arraybuffer from "vite-plugin-arraybuffer";
import ThemeDark from "@notesnook/theme/theme-engine/themes/default-dark.json" with {type:"json"};
import wasm from "vite-plugin-wasm";
import { ThemeDark } from "@notesnook/theme";
import type { Plugin, ResolvedConfig } from "vite";
import { writeFile } from "fs/promises";
import path from "path";
import { viteStaticCopy } from "vite-plugin-static-copy";
import * as pkg from "./package.json";
const DEDUPE = [
@@ -44,19 +44,17 @@ const DEFAULT_THEME_KEY =
export default defineConfig(({ isSsrBuild }) => ({
plugins: [
writePlugin({
"../package.json": JSON.stringify({
"package.json": JSON.stringify({
name: pkg.name,
version: pkg.version,
type: "module",
scripts: { start: pkg.scripts.start },
dependencies: {
"@napi-rs/canvas": pkg.dependencies["@napi-rs/canvas"],
"@remix-run/server-runtime": pkg.devDependencies["@remix-run/server-runtime"],
},
"@remix-run/serve": pkg.devDependencies["@remix-run/serve"]
}
})
}),
remix({
buildDirectory: "output/build",
future: {
v3_fetcherPersist: true,
v3_relativeSplatPath: true,
@@ -65,13 +63,7 @@ export default defineConfig(({ isSsrBuild }) => ({
}),
tsconfigPaths(),
arraybuffer(),
isSsrBuild ? viteStaticCopy({
targets: [
{ src: "./server.ts", dest: "../../" },
{ src: "./app/assets", dest: "../" },
{ src: "./fonts", dest: "../" }
]
}) : undefined
wasm()
],
worker: {
format: "es",
@@ -82,15 +74,13 @@ export default defineConfig(({ isSsrBuild }) => ({
}
},
ssr: {
...(process.env.NODE_ENV === "development"
? {}
: { noExternal: true, external: ["@napi-rs/canvas"] }),
...(process.env.NODE_ENV === "development" ? {} : { noExternal: true }),
target: "node"
},
build: {
target: isSsrBuild ? "node20" : undefined,
rollupOptions: {
external: ["@napi-rs/canvas"]
external: ["svg2png-wasm/svg2png_wasm_bg.wasm"]
}
},
define: {

View File

@@ -1,4 +1,4 @@
Subtotal: ₹300
Sales tax: ₹200
Discount: -₹300
Total: ₹300
Total: ₹300/mo

View File

@@ -1,4 +1,4 @@
Subtotal: ₹300
Sales tax: ₹200
Discount: -₹300
Total: ₹300
Total: ₹300/mo

View File

@@ -1,4 +1,4 @@
Subtotal: ₹300
Sales tax: ₹200
Discount: -₹300
Total: ₹300
Total: ₹300/mo

View File

@@ -1,4 +1,4 @@
Subtotal: $100
Sales tax: $0
Discount: -$100
Total: $100
Total: $100/mo

View File

@@ -1,4 +1,4 @@
Subtotal: $100
Sales tax: $0
Discount: -$100
Total: $100
Total: $100/mo

View File

@@ -1,4 +1,4 @@
Subtotal: $100
Sales tax: $0
Discount: -$100
Total: $100
Total: $100/mo

View File

@@ -231,23 +231,6 @@ test("add tags to note", async ({ page }) => {
expect(noteTags.every((t, i) => t === tags[i])).toBe(true);
});
test("add tags to locked note", async ({ page }) => {
const tags = ["incognito", "secret-stuff"];
const app = new AppModel(page);
await app.goto();
const notes = await app.goToNotes();
const note = await notes.createNote(NOTE);
await note?.contextMenu.lock(PASSWORD);
await note?.openLockedNote(PASSWORD);
await notes.editor.setTags(tags);
await page.waitForTimeout(200);
const noteTags = await notes.editor.getTags();
expect(noteTags).toHaveLength(tags.length);
expect(noteTags.every((t, i) => t === tags[i])).toBe(true);
});
for (const format of ["html", "txt", "md"] as const) {
test(`export note as ${format}`, async ({ page }) => {
const app = new AppModel(page);

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/web",
"version": "3.0.22",
"version": "3.0.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/web",
"version": "3.0.22",
"version": "3.0.21",
"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.22",
"version": "3.0.21",
"private": true,
"main": "./src/app.js",
"homepage": "https://notesnook.com/",

View File

@@ -20,10 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { getCurrentHash, getCurrentPath, makeURL } from "./navigation";
import Config from "./utils/config";
import type { AuthProps } from "./views/auth";
import {
initializeFeatureChecks,
isFeatureSupported
} from "./utils/feature-check";
import { initializeFeatureChecks } from "./utils/feature-check";
import { initializeLogger } from "./utils/logger";
type Route<TProps = null> = {
@@ -145,24 +142,9 @@ function isSessionExpired(path: Routes): RouteWithPath<AuthProps> | null {
return null;
}
function checkPrerequisites() {
if (!window.isSecureContext)
throw new Error("Please run Notesnook in a secure (https) context.");
if (!navigator.locks)
throw new Error("Your browser does not support the Web Locks API.");
if (!crypto.subtle)
throw new Error("Your browser does not support the SubtleCrypto API.");
if (!window.indexedDB && !isFeatureSupported("opfs"))
throw new Error("Your browser does not support IndexedDB or OPFS.");
if (!window.WebAssembly)
throw new Error("Your browser does not support WebAssembly.");
}
export async function init() {
await initializeFeatureChecks();
checkPrerequisites();
const { path, route } = getRoute();
const [{ default: Component }] = await Promise.all([

View File

@@ -118,7 +118,7 @@ class _SQLiteWorker {
} else this.retryCounter[sql] = 0;
if (ex instanceof Error || ex instanceof SQLiteError)
ex.message += ` (error preparing query: ${sql})`;
ex.message += ` (query: ${sql})`;
throw ex;
}
}
@@ -146,7 +146,7 @@ class _SQLiteWorker {
return rows;
} catch (e) {
if (e instanceof Error || e instanceof SQLiteError)
e.message += ` (error exec query: ${sql})`;
e.message += ` (query: ${sql})`;
throw e;
} finally {
await this.sqlite
@@ -201,16 +201,16 @@ class _SQLiteWorker {
this.initialized = false;
}
async export(name: string, options: SQLiteOptions) {
const vfs = await this.getVFS(name, options.async);
const stream = new ReadableStream(new DatabaseSource(vfs, name));
async export() {
const vfs = await this.getVFS(this.name, this.async);
const stream = new ReadableStream(new DatabaseSource(vfs, this.name));
return transfer(stream, [stream]);
}
async delete(name: string, options: SQLiteOptions) {
async delete() {
await this.close();
if (this.vfs) await this.vfs.delete();
else await (await this.getVFS(name, options.async)).delete();
else await (await this.getVFS(this.name, this.async)).delete();
}
async getVFS(dbName: string, async: boolean) {

View File

@@ -76,10 +76,7 @@ export class WaSqliteWorkerMultipleTabDriver implements Driver {
activated: true,
closed: false
});
this.connection = new WaSqliteWorkerConnection(
service.proxy,
this.config.async
);
this.connection = new WaSqliteWorkerConnection(service.proxy);
}
return;
}
@@ -125,10 +122,7 @@ export class WaSqliteWorkerMultipleTabDriver implements Driver {
await service.getProviderPort();
console.timeEnd("waiting for provider port");
this.connection = new WaSqliteWorkerConnection(
service.proxy,
this.config.async
);
this.connection = new WaSqliteWorkerConnection(service.proxy);
servicePool.set(this.serviceName, {
service,
@@ -208,22 +202,12 @@ export class WaSqliteWorkerMultipleTabDriver implements Driver {
async delete() {
const service = servicePool.get(this.serviceName);
if (!service || !service.service) return;
await service.service?.proxy?.delete(this.config.dbName, {
async: this.config.async,
encrypted: this.config.encrypted,
url: this.config.async ? SQLiteAsyncURI : SQLiteSyncURI
});
await service.service?.proxy?.delete();
service.closed = true;
}
async export() {
return servicePool
.get(this.serviceName)
?.service?.proxy?.export(this.config.dbName, {
async: this.config.async,
encrypted: this.config.encrypted,
url: this.config.async ? SQLiteAsyncURI : SQLiteSyncURI
});
return servicePool.get(this.serviceName)?.service?.proxy?.export();
}
}
@@ -244,10 +228,7 @@ export class WaSqliteWorkerSingleTabDriver implements Driver {
encrypted: this.config.encrypted,
url: this.config.async ? SQLiteAsyncURI : SQLiteSyncURI
});
this.connection = new WaSqliteWorkerConnection(
this.worker,
this.config.async
);
this.connection = new WaSqliteWorkerConnection(this.worker);
}
async acquireConnection(): Promise<DatabaseConnection> {
@@ -281,28 +262,16 @@ export class WaSqliteWorkerSingleTabDriver implements Driver {
}
async delete() {
await this.worker.delete(this.config.dbName, {
async: this.config.async,
encrypted: this.config.encrypted,
url: this.config.async ? SQLiteAsyncURI : SQLiteSyncURI
});
await this.worker.delete();
}
async export() {
return await this.worker.export(this.config.dbName, {
async: this.config.async,
encrypted: this.config.encrypted,
url: this.config.async ? SQLiteAsyncURI : SQLiteSyncURI
});
return await this.worker.export();
}
}
class WaSqliteWorkerConnection implements DatabaseConnection {
#queryMutex = new Mutex();
constructor(
private readonly worker: SQLiteWorker | Remote<SQLiteWorker>,
private readonly sequential = false
) {}
constructor(private readonly worker: SQLiteWorker | Remote<SQLiteWorker>) {}
streamQuery<R>(): AsyncIterableIterator<QueryResult<R>> {
throw new Error("wasqlite driver doesn't support streaming");
@@ -310,17 +279,6 @@ class WaSqliteWorkerConnection implements DatabaseConnection {
async executeQuery<R>(
compiledQuery: CompiledQuery<unknown>
): Promise<QueryResult<R>> {
if (this.sequential) {
return this.#queryMutex.runExclusive(async () =>
this.#_executeQuery(compiledQuery)
);
}
return this.#_executeQuery(compiledQuery);
}
#_executeQuery<R>(
compiledQuery: CompiledQuery<unknown>
): Promise<QueryResult<R>> {
const { parameters, sql, query } = compiledQuery;
const mode =

View File

@@ -834,7 +834,6 @@ function UnlockNoteView(props: UnlockNoteViewProps) {
if (!note || !note.content)
throw new Error("note with this id does not exist.");
const tags = await db.notes.tags(note.id);
useEditorStore.getState().addSession({
type: session.note.readonly ? "readonly" : "default",
locked: true,
@@ -842,7 +841,6 @@ function UnlockNoteView(props: UnlockNoteViewProps) {
note: session.note,
saveState: SaveState.Saved,
sessionId: `${Date.now()}`,
tags,
pinned: session.pinned,
preview: session.preview,
content: note.content

View File

@@ -449,18 +449,12 @@ function TiptapWrapper(
const handleWheel = (e: WheelEvent) => {
if (e.ctrlKey) {
if (e.deltaY === 0) return;
e.preventDefault();
const delta =
(e.deltaY > 0 && e.deltaY < 10) || (e.deltaY > -10 && e.deltaY < 0)
? -e.deltaY
: e.deltaY > 0
? -EDITOR_ZOOM.STEP
: EDITOR_ZOOM.STEP;
Math.ceil(-e.deltaY / 10 / EDITOR_ZOOM.STEP) * EDITOR_ZOOM.STEP;
const zoom = Math.min(
EDITOR_ZOOM.MAX,
Math.max(EDITOR_ZOOM.MIN, Math.round(editorConfig.zoom + delta))
Math.max(EDITOR_ZOOM.MIN, editorConfig.zoom + delta)
);
setEditorConfig({ zoom });
}

View File

@@ -17,7 +17,13 @@ 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 { forwardRef, useEffect, useRef, useState } from "react";
import {
forwardRef,
useEffect,
useLayoutEffect,
useRef,
useState
} from "react";
import { Flex, Button } from "@theme-ui/components";
import { Plus } from "../icons";
import {
@@ -44,6 +50,7 @@ import {
} from "react-virtuoso";
import { getRandom, useResolvedItem } from "@notesnook/common";
import { Context } from "./types";
import { AppEventManager, AppEvents } from "../../common/app-events";
export const CustomScrollbarsVirtualList = forwardRef<
HTMLDivElement,
@@ -89,7 +96,7 @@ function ListContainer(props: ListContainerProps) {
const listRef = useRef<VirtuosoHandle>(null);
const listContainerRef = useRef(null);
// const activeItem = useRef<{ focus: boolean; id: string }>();
const activeItem = useRef<{ focus: boolean; id: string }>();
useEffect(() => {
return () => {
@@ -97,6 +104,42 @@ function ListContainer(props: ListContainerProps) {
};
}, []);
useLayoutEffect(() => {
if (activeItem.current) {
items
.ids()
.then(
(ids) =>
listRef.current &&
activeItem.current &&
revealItemInList(
listRef.current,
activeItem.current.id,
ids,
activeItem.current.focus
)
);
}
const event = AppEventManager.subscribe(
AppEvents.revealItemInList,
(id, focus) => {
if (activeItem.current?.id === id) return;
activeItem.current = { id, focus };
items
.ids()
.then(
(ids) =>
listRef.current &&
revealItemInList(listRef.current, id, ids, focus)
);
}
);
return () => {
event.unsubscribe();
};
}, [items]);
const { onMouseUp, onKeyDown } = useKeyboardListNavigation({
length: items.length,
reset: () => toggleSelection(false),
@@ -399,3 +442,20 @@ export function waitForElement(
}
});
}
function revealItemInList(
list: VirtuosoHandle,
itemId: string,
ids: string[],
focus: boolean
) {
const index = ids.indexOf(itemId);
if (index === -1) return;
waitForElement(
list,
index,
`id_${itemId}`,
(element) => focus && element.focus(),
{ align: "center" }
);
}

View File

@@ -172,9 +172,7 @@ export function PaddleCheckout(props: PaddleCheckoutProps) {
items: [
{
prices: checkout.prices.customer.items,
recurring: {
prices: [checkout.recurring_prices.customer.items[0].recurring]
}
recurring: { prices: checkout.recurring_prices.customer.items }
}
]
});

View File

@@ -74,7 +74,6 @@ export function PlansList(props: PlansListProps) {
// }
onClick={() => onPlanSelected(plan)}
sx={{
flexShrink: 0,
flex: 1,
textAlign: "start",
alignItems: "center",

View File

@@ -202,8 +202,6 @@ export interface CheckoutPrices {
unit_price: CheckoutPrice;
// line_price: CheckoutPrice;
discounts: CheckoutDiscount[];
recurring: CheckoutPrices;
// tax_rate: number;
}

View File

@@ -127,19 +127,12 @@ export const IssueDialog = DialogManager.register(function IssueDialog(
<Link
href="https://github.com/streetwriters/notesnook/issues"
title="github.com/streetwriters/notesnook/issues"
target="_blank"
>
github.com/streetwriters/notesnook/issues
</Link>
/>{" "}
{strings.issueNotice[1]()}{" "}
<Link
href="https://discord.gg/zQBK97EE22"
title={strings.issueNotice[2]()}
target="_blank"
>
{strings.issueNotice[2]()}
</Link>
/
/>
</Text>
<Text variant="subBody" mt={1}>
{getDeviceInfo([`Pro: ${isUserPremium()}`])

View File

@@ -28,9 +28,6 @@ import { useStore as useUserStore } from "../../stores/user-store";
import { desktop } from "../../common/desktop-bridge";
import { PATHS } from "@notesnook/desktop";
const getDesktopBackupsDirectoryPath = () =>
useSettingStore.getState().backupStorageLocation || PATHS.backupsDirectory;
export const BackupExportSettings: SettingsGroup[] = [
{
key: "backup",
@@ -167,10 +164,7 @@ export const BackupExportSettings: SettingsGroup[] = [
{
key: "backup-directory",
title: strings.selectBackupDir(),
description: () =>
strings
.selectBackupDirDesc(getDesktopBackupsDirectoryPath())
.join("\n\n"),
description: strings.selectBackupDirDesc(),
isHidden: () => !IS_DESKTOP_APP,
components: [
{
@@ -182,7 +176,9 @@ export const BackupExportSettings: SettingsGroup[] = [
(await verifyAccount());
if (!verified) return;
const backupStorageLocation = getDesktopBackupsDirectoryPath();
const backupStorageLocation =
useSettingStore.getState().backupStorageLocation ||
PATHS.backupsDirectory;
const location = await desktop?.integration.selectDirectory.query(
{
title: strings.selectBackupDir(),

View File

@@ -166,11 +166,7 @@ export function Importer() {
<Box as="ol" sx={{ my: 1 }}>
<Text as="li" variant="body">
Go to{" "}
<Link
href="https://importer.notesnook.com/"
target="_blank"
sx={{ color: "accent" }}
>
<Link href="https://importer.notesnook.com/" target="_blank">
https://importer.notesnook.com/
</Link>
</Text>

View File

@@ -466,7 +466,7 @@ function SettingItem(props: { item: Setting }) {
gap: 4
}}
>
<Flex sx={{ flexDirection: "column", flex: 1 }}>
<Flex sx={{ flexDirection: "column", flexShrink: 0 }}>
<Text variant={"subtitle"}>{item.title}</Text>
{item.description && (
<Text
@@ -485,8 +485,7 @@ function SettingItem(props: { item: Setting }) {
alignItems: "center",
justifyContent: "end",
gap: 2,
"& > label": { width: "auto" },
"& > *": { flexShrink: 0 }
"& > label": { width: "auto" }
}}
>
{components.map((component, index) => {

View File

@@ -371,8 +371,8 @@ class KeyStore extends BaseStore<KeyStore> {
};
clear = async () => {
await this.#metadataStore?.clear();
await this.#secretStore?.clear();
await this.#metadataStore.clear();
await this.#secretStore.clear();
this.#key = undefined;
this.set({ credentials: [], secrets: {}, isLocked: false });
};

View File

@@ -421,7 +421,7 @@ class EditorStore extends BaseStore<EditorStore> {
continue;
updateSession(session.id, undefined, {
tags: await db.notes.tags(session.note.id)
tags: await getTags(session.note.id)
});
}
} else if (
@@ -432,7 +432,7 @@ class EditorStore extends BaseStore<EditorStore> {
event.item.toType === "note"
) {
updateSession(event.item.toId, undefined, {
tags: await db.notes.tags(event.item.toId)
tags: await getTags(event.item.toId)
});
}
} else if (event.collection === "tags") {
@@ -445,7 +445,7 @@ class EditorStore extends BaseStore<EditorStore> {
continue;
console.log("UDPATE");
updateSession(session.id, undefined, {
tags: await db.notes.tags(session.note.id)
tags: await getTags(session.note.id)
});
}
}
@@ -671,7 +671,7 @@ class EditorStore extends BaseStore<EditorStore> {
const attachmentsLength = await db.attachments
.ofNote(note.id, "all")
.count();
const tags = await db.notes.tags(note.id);
const tags = await getTags(note.id);
const colors = await db.relations.to(note, "color").get();
if (note.readonly) {
this.addSession(
@@ -871,19 +871,12 @@ class EditorStore extends BaseStore<EditorStore> {
};
newSession = () => {
const state = useEditorStore.getState();
const session = state.sessions.find((session) => session.type === "new");
if (session) {
session.context = useNoteStore.getState().context;
this.activateSession(session.id);
} else {
this.addSession({
type: "new",
id: getId(),
context: useNoteStore.getState().context,
saveState: SaveState.NotSaved
});
}
this.addSession({
type: "new",
id: getId(),
context: useNoteStore.getState().context,
saveState: SaveState.NotSaved
});
};
closeSessions = (...ids: string[]) => {
@@ -1027,3 +1020,12 @@ async function waitForSync() {
db.eventManager.subscribe(EVENTS.syncCompleted, resolve, true);
});
}
async function getTags(noteId: string) {
return await db.relations
.to({ id: noteId, type: "note" }, "tag")
.selector.items(undefined, {
sortBy: "dateCreated",
sortDirection: "asc"
});
}

View File

@@ -19,22 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import snarkdown from "snarkdown";
function addAttributes(
html: string,
tag: keyof HTMLElementTagNameMap,
attributes: Record<string, string>
) {
const temp = document.createElement("div");
temp.innerHTML = html;
const elements = temp.querySelectorAll(tag);
elements.forEach((element) => {
Object.entries(attributes).forEach(([key, value]) => {
element.setAttribute(key, value);
});
});
return temp.innerHTML;
}
export function mdToHtml(markdown: string) {
return addAttributes(snarkdown(markdown), "a", { target: "_blank" });
return snarkdown(markdown);
}

View File

@@ -985,14 +985,7 @@ export function AuthField(props: FieldProps) {
p: "12px",
borderRadius: "default",
bg: "background",
boxShadow: "0px 0px 5px 0px #00000019",
"::-moz-appearance": "textfield",
"::-webkit-inner-spin-button": {
"-webkit-appearance": "none"
},
"::-webkit-outer-spin-button": {
"-webkit-appearance": "none"
}
boxShadow: "0px 0px 5px 0px #00000019"
}
}}
/>

View File

@@ -1,30 +0,0 @@
# Contributing guidelines
Please read the [contributing guidelines](../../CONTRIBUTING.md) beforehand.
### Setting web clipper locally
#### Running the web clipper
1. Install packages and setup the repo. Run this command in the repository root:
```sh
npm install
```
1. Run the Notesnook webapp:
```sh
npm run start:web
```
1. Navigate to the web clipper folder:
```sh
cd extensions/web-clipper
```
1. Run the web clipper:
```sh
npm run dev:chrome
```
#### Viewing the web clipper
1. Open chrome and go to `chrome://extensions`.
1. Turn on "Developer Mode".
1. Click on "Load unpacked" and select the `extensions/web-clipper/build` folder.

View File

@@ -75,8 +75,6 @@ function attachMessagePort() {
height: document.body.clientHeight,
width: document.body.clientWidth
};
default:
return false;
}
});
}

View File

@@ -1,9 +0,0 @@
- Added full support for localization in Notesnook
- Improved search experience
- Allow user to cancel logging in
- Fixed scrolling focused line into view
- Support self hosted monograph server
- Fixed markdown link pasting in editor
- Many other bug fixes and improvements
Thank you for using Notesnook!

View File

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

View File

@@ -197,15 +197,6 @@ test("update note", () =>
expect(note?.favorite).toBe(true);
}));
test("get note tags", () =>
noteTest({
...TEST_NOTE
}).then(async ({ db, id }) => {
const tag = await db.tags.add({ title: "hello" });
await db.relations.add({ type: "tag", id: tag }, { type: "note", id });
expect(await db.notes.tags(id)).toEqual([await db.tags.tag(tag)]);
}));
test("get favorite notes", () =>
noteTest({
...TEST_NOTE,

View File

@@ -16,7 +16,6 @@
"@readme/data-urls": "^3.0.0",
"@streetwriters/kysely": "^0.27.4",
"@streetwriters/showdown": "^3.0.9-alpha",
"@types/mime-db": "^1.43.5",
"async-mutex": "^0.3.2",
"dayjs": "1.11.9",
"dom-serializer": "^2.0.0",
@@ -29,7 +28,7 @@
"katex": "0.16.2",
"linkedom": "^0.14.17",
"liqe": "^1.13.0",
"mime-db": "^1.53.0",
"mime": "^4.0.4",
"prismjs": "^1.29.0",
"qclone": "^1.2.0",
"rfdc": "^1.3.0",
@@ -2267,11 +2266,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/mime-db": {
"version": "1.43.5",
"resolved": "https://registry.npmjs.org/@types/mime-db/-/mime-db-1.43.5.tgz",
"integrity": "sha512-/bfTiIUTNPUBnwnYvUxXAre5MhD88jgagLEQiQtIASjU+bwxd8kS/ASDA4a8ufd8m0Lheu6eeMJHEUpLHoJ28A=="
},
"node_modules/@types/node": {
"version": "18.11.9",
"dev": true,
@@ -3453,12 +3447,19 @@
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
"node_modules/mime-db": {
"version": "1.53.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz",
"integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==",
"node_modules/mime": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz",
"integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==",
"funding": [
"https://github.com/sponsors/broofa"
],
"license": "MIT",
"bin": {
"mime": "bin/cli.js"
},
"engines": {
"node": ">= 0.6"
"node": ">=16"
}
},
"node_modules/mimic-fn": {

View File

@@ -68,7 +68,6 @@
"@readme/data-urls": "^3.0.0",
"@streetwriters/kysely": "^0.27.4",
"@streetwriters/showdown": "^3.0.9-alpha",
"@types/mime-db": "^1.43.5",
"async-mutex": "^0.3.2",
"dayjs": "1.11.9",
"dom-serializer": "^2.0.0",
@@ -81,7 +80,7 @@
"katex": "0.16.2",
"linkedom": "^0.14.17",
"liqe": "^1.13.0",
"mime-db": "^1.53.0",
"mime": "^4.0.4",
"prismjs": "^1.29.0",
"qclone": "^1.2.0",
"rfdc": "^1.3.0",

View File

@@ -79,7 +79,6 @@ import { Sanitizer } from "../database/sanitizer.js";
import { createTriggers, dropTriggers } from "../database/triggers.js";
import { NNMigrationProvider } from "../database/migrations.js";
import { ConfigStorage } from "../database/config.js";
import { LazyPromise } from "../utils/lazy-promise.js";
type EventSourceConstructor = new (
uri: string,
@@ -102,9 +101,6 @@ class Database {
sseMutex = new Mutex();
_fs?: FileStorage;
_compressor?: Promise<ICompressor>;
private databaseReady = new LazyPromise<
Kysely<DatabaseSchema> | Transaction<DatabaseSchema>
>();
storage: StorageAccessor = () => {
if (!this.options?.storage)
@@ -152,12 +148,11 @@ class Database {
return this._sql;
};
private _kv = new KVStorage(this.databaseReady.promise);
kv: KVStorageAccessor = () => this._kv;
private _config: ConfigStorage = new ConfigStorage(
this.databaseReady.promise
);
config: ConfigStorageAccessor = () => this._config;
private _kv?: KVStorage;
kv: KVStorageAccessor = () => this._kv || new KVStorage(this.sql);
private _config?: ConfigStorage;
config: ConfigStorageAccessor = () =>
this._config || new ConfigStorage(this.sql);
private _transaction?: QueueValue<Transaction<DatabaseSchema>>;
transaction = async (
@@ -296,7 +291,6 @@ class Database {
migrationProvider: new NNMigrationProvider(),
onInit: (db) => this.onInit(db)
})) as unknown as Kysely<DatabaseSchema>;
this.databaseReady.resolve(this._sql);
await this.sanitizer.init();

View File

@@ -176,15 +176,6 @@ export class Notes implements ICollection {
return note;
}
async tags(id: string) {
return this.db.relations
.to({ id, type: "note" }, "tag")
.selector.items(undefined, {
sortBy: "dateCreated",
sortDirection: "asc"
});
}
// note(idOrNote: string | Note) {
// if (!idOrNote) return;
// const note =

View File

@@ -17,47 +17,41 @@ 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 { LazyDatabaseAccessor, RawDatabaseSchema } from "./index.js";
import { DatabaseAccessor, RawDatabaseSchema } from "./index.js";
export class ConfigStorage {
private readonly db: LazyDatabaseAccessor<RawDatabaseSchema>;
constructor(db: LazyDatabaseAccessor) {
this.db = db as unknown as LazyDatabaseAccessor<RawDatabaseSchema>;
private readonly db: DatabaseAccessor<RawDatabaseSchema>;
constructor(db: DatabaseAccessor) {
this.db = db as unknown as DatabaseAccessor<RawDatabaseSchema>;
}
async getItem(name: string): Promise<unknown | undefined> {
const result = await this.db.then((db) =>
db
.selectFrom("config")
.where("name", "==", name)
.select("value")
.limit(1)
.executeTakeFirst()
);
const result = await this.db()
.selectFrom("config")
.where("name", "==", name)
.select("value")
.limit(1)
.executeTakeFirst();
if (!result?.value) return;
return JSON.parse(result.value);
}
async setItem(name: string, value: unknown) {
await this.db.then((db) =>
db
.replaceInto("config")
.values({
name,
value: JSON.stringify(value),
dateModified: Date.now()
})
.execute()
);
await this.db()
.replaceInto("config")
.values({
name,
value: JSON.stringify(value),
dateModified: Date.now()
})
.execute();
}
async removeItem(name: string) {
await this.db.then((db) =>
db.deleteFrom("config").where("name", "==", name).execute()
);
await this.db().deleteFrom("config").where("name", "==", name).execute();
}
async clear() {
await this.db.then((db) => db.deleteFrom("config").execute());
await this.db().deleteFrom("config").execute();
}
}

View File

@@ -198,10 +198,6 @@ export type DatabaseAccessor<TSchema = DatabaseSchema> = () =>
| Kysely<TSchema>
| Transaction<TSchema>;
export type LazyDatabaseAccessor<TSchema = DatabaseSchema> = Promise<
Kysely<TSchema> | Transaction<TSchema>
>;
type FilterBooleanProperties<T, Type> = keyof {
[K in keyof T as T[K] extends Type ? K : never]: T[K];
};

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 { LazyDatabaseAccessor, RawDatabaseSchema } from "./index.js";
import { DatabaseAccessor, RawDatabaseSchema } from "./index.js";
import { Token } from "../api/token-manager.js";
import { User } from "../types.js";
@@ -44,44 +44,38 @@ export const KEYS: (keyof KV)[] = [
];
export class KVStorage {
private readonly db: LazyDatabaseAccessor<RawDatabaseSchema>;
constructor(db: LazyDatabaseAccessor) {
this.db = db as unknown as LazyDatabaseAccessor<RawDatabaseSchema>;
private readonly db: DatabaseAccessor<RawDatabaseSchema>;
constructor(db: DatabaseAccessor) {
this.db = db as unknown as DatabaseAccessor<RawDatabaseSchema>;
}
async read<T extends keyof KV>(key: T): Promise<KV[T] | undefined> {
const result = await this.db.then((db) =>
db
.selectFrom("kv")
.where("key", "==", key)
.select("value")
.limit(1)
.executeTakeFirst()
);
const result = await this.db()
.selectFrom("kv")
.where("key", "==", key)
.select("value")
.limit(1)
.executeTakeFirst();
if (!result?.value) return;
return JSON.parse(result.value) as KV[T];
}
async write<T extends keyof KV>(key: T, value: KV[T]) {
await this.db.then((db) =>
db
.replaceInto("kv")
.values({
key,
value: JSON.stringify(value),
dateModified: Date.now()
})
.execute()
);
await this.db()
.replaceInto("kv")
.values({
key,
value: JSON.stringify(value),
dateModified: Date.now()
})
.execute();
}
async delete<T extends keyof KV>(key: T) {
await this.db.then((db) =>
db.deleteFrom("kv").where("key", "==", key).execute()
);
await this.db().deleteFrom("kv").where("key", "==", key).execute();
}
async clear() {
await this.db.then((db) => db.deleteFrom("kv").execute());
await this.db().deleteFrom("kv").execute();
}
}

View File

@@ -1,50 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 { describe, expect, it } from "vitest";
import { parseInternalLink } from "../internal-link";
describe("parseInternalLink", () => {
const invalidInternalLinks = [
"",
"invalid-url",
"http://google.com",
"https://google.com"
];
invalidInternalLinks.forEach((url) => {
it(`should return undefined when not internal link: ${url}`, () => {
expect(parseInternalLink(url)).toBeUndefined();
});
});
const validInternalLinks = [
{
url: "nn://note/123",
expected: { type: "note", id: "123", params: {} }
},
{
url: "nn://note/123?blockId=456",
expected: { type: "note", id: "123", params: { blockId: "456" } }
}
];
validInternalLinks.forEach(({ url, expected }) => {
it(`should parse internal link: ${url}`, () => {
expect(parseInternalLink(url)).toEqual(expected);
});
});
});

View File

@@ -23,11 +23,11 @@ export async function getFileNameWithExtension(
): Promise<string> {
if (!mime || mime === "application/octet-stream") return filename;
const { default: mimeDB } = await import("mime-db");
const { default: mimeDB } = await import("mime");
const { extensions } = mimeDB[mime] || {};
const extensions = mimeDB.getAllExtensions(mime);
if (!extensions || extensions.length === 0) return filename;
if (!extensions || extensions.size === 0) return filename;
for (const ext of extensions) {
if (filename.endsWith(ext)) return filename;

View File

@@ -52,12 +52,7 @@ export function createInternalLink<T extends InternalLinkType>(
}
export function parseInternalLink(link: string): InternalLink | undefined {
let url;
try {
url = new URL(link);
} catch (e) {
return;
}
const url = new URL(link);
if (url.protocol !== "nn:") return;
const [type, id] = url.href.split("?")[0].split("/").slice(2);

View File

@@ -1,34 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export class LazyPromise<T> {
private _promise: Promise<T>;
private _resolve?: (result: T) => void;
constructor() {
this._promise = new Promise((resolve) => (this._resolve = resolve));
}
resolve(result: T) {
this._resolve?.(result);
}
get promise() {
return this._promise;
}
}

Some files were not shown because too many files have changed in this diff Show More