mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 18:19:38 +02:00
Compare commits
47 Commits
fix/text-e
...
fix/sync-q
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2febd09613 | ||
|
|
91138f4911 | ||
|
|
f9bcfe2f7a | ||
|
|
3621f95dbc | ||
|
|
536dead44d | ||
|
|
39d74e80a9 | ||
|
|
46e03dd248 | ||
|
|
152fee2c29 | ||
|
|
492a4d16b2 | ||
|
|
3d7c1fa1e7 | ||
|
|
8a138d960d | ||
|
|
69bb0e3656 | ||
|
|
4875cfa108 | ||
|
|
a28beb62c6 | ||
|
|
21c8960146 | ||
|
|
59442b9107 | ||
|
|
2ba638b123 | ||
|
|
8548940cb9 | ||
|
|
909bdfa0cf | ||
|
|
bfb3c56abe | ||
|
|
e06836f701 | ||
|
|
bc16cb79f2 | ||
|
|
176c46e3f2 | ||
|
|
af65055ce9 | ||
|
|
ad23ff19de | ||
|
|
cf65fc4f57 | ||
|
|
9ab83e7fbb | ||
|
|
1acf2aadba | ||
|
|
06833bcac9 | ||
|
|
3bf6b5293a | ||
|
|
c40d33df37 | ||
|
|
fe609f8275 | ||
|
|
3566f47f2d | ||
|
|
4b5526dffd | ||
|
|
4977390394 | ||
|
|
87804de452 | ||
|
|
bc55d2b476 | ||
|
|
734e79604f | ||
|
|
a1640175e5 | ||
|
|
7cf61570ef | ||
|
|
83762c668e | ||
|
|
ecd4a08b1c | ||
|
|
9744679550 | ||
|
|
9cdc502ce5 | ||
|
|
300a104949 | ||
|
|
df94f31998 | ||
|
|
aec1d601a3 |
@@ -8,9 +8,9 @@ Thank you so much for considering to contribute to Notesnook! If you have no ide
|
||||
|
||||
Ugh! Bugs!
|
||||
|
||||
> A bug is when software behaves in a way that you didn't expect, and the developer didn't intend.
|
||||
> A bug is when software behaves in a way you didn't expect, which the developer didn't intend.
|
||||
|
||||
To help us understand what's going on, we first want to **make sure you're using the latest version of Notesnook**.
|
||||
To help us understand what's happening, we first want to **make sure you're using the latest version of Notesnook**.
|
||||
|
||||
Once you've **confirmed that the bug still exists in the latest version**, you'll want to check to make sure it's not something we already know about in the [opened GitHub issues](https://github.com/streetwriters/notesnook/issues).
|
||||
|
||||
@@ -30,7 +30,7 @@ Before you open a new feature request, please make sure it's not a duplicate. **
|
||||
|
||||
### Helping out in the issue tracker
|
||||
|
||||
There are always new issues getting opened that need to be triaged, sorted & organized, so the developers can easily find the most critical and/or relevant bugs to fix. Any help in this regard is appreciated.
|
||||
New issues are always opened that need to be triaged, sorted & organized, so the developers can easily find the most critical and/or relevant bugs to fix. Any help in this regard is appreciated.
|
||||
|
||||
In addition to this, you can help out in the following ways:
|
||||
|
||||
@@ -62,7 +62,7 @@ Once you are done, [open a new pull request](https://docs.github.com/en/pull-req
|
||||
|
||||
1. Fork [the repository](https://github.com/streetwriters/notesnook) and create your branch from `master` (you can name your branch anything).
|
||||
2. Run `npm run bootstrap` in the repository root.
|
||||
3. If you’ve fixed a bug or added code that should be tested, add tests!
|
||||
3. If you've fixed a bug or added code that should be tested, add tests!
|
||||
4. Ensure the test suite passes (`npm run test`).
|
||||
5. Format your code with prettier (`npm run prettier`).
|
||||
6. Make sure your code lints (`npm run lint`). Tip: `npm run linc` to only check changed files.
|
||||
@@ -131,11 +131,11 @@ We use an automatic code formatter called [Prettier](https://prettier.io/). Run
|
||||
|
||||
Then, our linter will catch most issues that may exist in your code. You can check the status of your code styling by simply running `npm run lint`.
|
||||
|
||||
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb’s Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
|
||||
However, there are still some styles that the linter cannot pick up. If you are unsure about something, looking at [Airbnb's Style Guide](https://github.com/airbnb/javascript) will guide you in the right direction.
|
||||
|
||||
## Git Branch Organization
|
||||
|
||||
Submit all changes directly to the [`master branch`](https://github.com/streetwriters/notesnook). We don’t use separate branches for development or for upcoming releases. This requires us to always keep the `master` branch in a deployable state which means:
|
||||
Submit all changes directly to the [`master branch`](https://github.com/streetwriters/notesnook). We don't use separate branches for development or for upcoming releases. This requires us to always keep the `master` branch in a deployable state which means:
|
||||
|
||||
1. All tests must be passing at all times
|
||||
2. There should be as few breaking changes as possible
|
||||
|
||||
@@ -36,7 +36,11 @@ function getFileExtension(filename) {
|
||||
var ext = /^.+\.([^.]+)$/.exec(filename);
|
||||
return ext == null ? "" : ext[1];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} param0
|
||||
* @returns
|
||||
*/
|
||||
export const AttachmentItem = ({ attachment, encryption, setAttachments }) => {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const [currentProgress, setCurrentProgress] = useAttachmentProgress(
|
||||
|
||||
@@ -44,8 +44,10 @@ import Paragraph from "../ui/typography/paragraph";
|
||||
import { LoginSteps, useLogin } from "./use-login";
|
||||
|
||||
function getObfuscatedEmail(email) {
|
||||
if (!email) return null;
|
||||
return email.replace(/(.{2})(.*)(?=@)/, function (gp1, gp2, gp3) {
|
||||
if (!email) return "";
|
||||
const [username, provider] = email.split("@");
|
||||
if (username.length === 1) return `****@${provider}`;
|
||||
return email.replace(/(.{1})(.*)(?=@)/, function (gp1, gp2, gp3) {
|
||||
for (let i = 0; i < gp3.length; i++) {
|
||||
gp2 += "*";
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import { useNoteStore } from "../../stores/use-notes-store";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { useUserStore } from "../../stores/use-user-store";
|
||||
import { AndroidModule } from "../../utils";
|
||||
import { eOpenAnnouncementDialog } from "../../utils/events";
|
||||
import { getGithubVersion } from "../../utils/github-version";
|
||||
import { SIZE } from "../../utils/size";
|
||||
@@ -192,6 +193,11 @@ const Launcher = React.memo(
|
||||
|
||||
const onUnlockBiometrics = useCallback(async () => {
|
||||
if (!(await BiometricService.isBiometryAvailable())) return;
|
||||
if (Platform.OS === "android") {
|
||||
const activityName = await AndroidModule.getActivityName();
|
||||
if (activityName !== "MainActivity") return;
|
||||
}
|
||||
|
||||
let verified = await BiometricService.validateUser(
|
||||
"Unlock to access your notes",
|
||||
""
|
||||
|
||||
@@ -116,11 +116,11 @@ export const Items = ({ item, buttons, close }) => {
|
||||
key={item.id}
|
||||
testID={"icon-" + item.id}
|
||||
customStyle={{
|
||||
alignItems: "center",
|
||||
alignSelf: "flex-start",
|
||||
width: topBarItemWidth,
|
||||
marginBottom: 10,
|
||||
marginRight: isLast ? 0 : 10,
|
||||
backgroundColor: "transparent"
|
||||
backgroundColor: "transparent",
|
||||
paddingHorizontal: 0
|
||||
}}
|
||||
>
|
||||
<PressableButton
|
||||
@@ -150,11 +150,7 @@ export const Items = ({ item, buttons, close }) => {
|
||||
/>
|
||||
</PressableButton>
|
||||
|
||||
<Paragraph
|
||||
size={SIZE.xxs + 1}
|
||||
style={{ textAlign: "center" }}
|
||||
textBreakStrategy="simple"
|
||||
>
|
||||
<Paragraph size={SIZE.xxs + 1} style={{ textAlign: "center" }}>
|
||||
{item.title}
|
||||
</Paragraph>
|
||||
</PressableButton>
|
||||
|
||||
@@ -200,7 +200,8 @@ export default function ReminderSheet({
|
||||
|
||||
if (!_reminder) {
|
||||
ToastEvent.show({
|
||||
heading: "Failed to add a new reminder"
|
||||
heading: "Failed to add a new reminder",
|
||||
context: "local"
|
||||
});
|
||||
}
|
||||
if (reference) {
|
||||
@@ -214,7 +215,7 @@ export default function ReminderSheet({
|
||||
useRelationStore.getState().update();
|
||||
close?.();
|
||||
} catch (e) {
|
||||
ToastEvent.error(e as Error);
|
||||
ToastEvent.error(e as Error, undefined, "local");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +310,16 @@ export default function ReminderSheet({
|
||||
mode as keyof typeof ReminderModes
|
||||
] as Reminder["mode"]
|
||||
);
|
||||
if (mode === "Repeat") {
|
||||
setSelectedDays((days) => {
|
||||
if (days.length > 0) return days;
|
||||
if (days.indexOf(date.getDay()) > -1) {
|
||||
return days;
|
||||
}
|
||||
days.push(date.getDay());
|
||||
return [...days];
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -25,7 +25,6 @@ import Navigation from "../../../services/navigation";
|
||||
import { useThemeStore } from "../../../stores/use-theme-store";
|
||||
import { GROUP, SORT } from "../../../utils/constants";
|
||||
import { refreshNotesPage } from "../../../utils/events";
|
||||
import layoutmanager from "../../../utils/layout-manager";
|
||||
import { SIZE } from "../../../utils/size";
|
||||
import { Button } from "../../ui/button";
|
||||
import Seperator from "../../ui/seperator";
|
||||
@@ -39,7 +38,6 @@ const Sort = ({ type, screen }) => {
|
||||
const updateGroupOptions = async (_groupOptions) => {
|
||||
await db.settings.setGroupOptions(type, _groupOptions);
|
||||
|
||||
layoutmanager.withSpringAnimation(600);
|
||||
setGroupOptions(_groupOptions);
|
||||
setTimeout(() => {
|
||||
if (screen !== "TopicSheet") Navigation.queueRoutesForUpdate(screen);
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { Keyboard, TouchableOpacity, View } from "react-native";
|
||||
import { TouchableOpacity, View } from "react-native";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { notesnook } from "../../../e2e/test.ids";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
@@ -34,24 +34,25 @@ import { SIZE } from "../../utils/size";
|
||||
import { Button } from "../ui/button";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
let toastMessages = [];
|
||||
export const Toast = ({ context = "global" }) => {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const [keyboard, setKeyboard] = useState(false);
|
||||
const [data, setData] = useState({});
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const hideTimeout = useRef();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const toastMessages = useRef([]);
|
||||
|
||||
const showToastFunc = useCallback(
|
||||
const show = useCallback(
|
||||
async (data) => {
|
||||
if (!data) return;
|
||||
if (data.context !== context) return;
|
||||
if (toastMessages.findIndex((m) => m.message === data.message) >= 0) {
|
||||
if (
|
||||
toastMessages.current.findIndex((m) => m.message === data.message) >= 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
toastMessages.push(data);
|
||||
if (toastMessages?.length > 1) return;
|
||||
toastMessages.current.push(data);
|
||||
if (toastMessages.current?.length > 1) return;
|
||||
setData(data);
|
||||
|
||||
setVisible(true);
|
||||
@@ -59,16 +60,16 @@ export const Toast = ({ context = "global" }) => {
|
||||
clearTimeout(hideTimeout.current);
|
||||
}
|
||||
hideTimeout.current = setTimeout(() => {
|
||||
hideToastFunc();
|
||||
hide();
|
||||
}, data.duration);
|
||||
},
|
||||
[context, hideToastFunc]
|
||||
[context, hide]
|
||||
);
|
||||
|
||||
const showNext = useCallback(
|
||||
const next = useCallback(
|
||||
(data) => {
|
||||
if (!data) {
|
||||
hideToastFunc();
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
setData(data);
|
||||
@@ -76,27 +77,28 @@ export const Toast = ({ context = "global" }) => {
|
||||
clearTimeout(hideTimeout.current);
|
||||
}
|
||||
hideTimeout.current = setTimeout(() => {
|
||||
hideToastFunc();
|
||||
hide();
|
||||
}, data?.duration);
|
||||
},
|
||||
[hideToastFunc]
|
||||
[hide]
|
||||
);
|
||||
|
||||
const hideToastFunc = useCallback(() => {
|
||||
const hide = useCallback(() => {
|
||||
if (hideTimeout.current) {
|
||||
clearTimeout(hideTimeout.current);
|
||||
}
|
||||
let msg = toastMessages.length > 1 ? toastMessages.shift() : null;
|
||||
let msg =
|
||||
toastMessages.current.length > 1 ? toastMessages.current.shift() : null;
|
||||
|
||||
if (msg) {
|
||||
setVisible(false);
|
||||
showNext(msg);
|
||||
next(msg);
|
||||
setTimeout(() => {
|
||||
setVisible(true);
|
||||
}, 300);
|
||||
} else {
|
||||
setVisible(false);
|
||||
toastMessages.shift();
|
||||
toastMessages.current.shift();
|
||||
setTimeout(() => {
|
||||
setData({});
|
||||
if (hideTimeout.current) {
|
||||
@@ -104,44 +106,22 @@ export const Toast = ({ context = "global" }) => {
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}, [showNext]);
|
||||
|
||||
const _onKeyboardShow = () => {
|
||||
setKeyboard(true);
|
||||
};
|
||||
|
||||
const _onKeyboardHide = () => {
|
||||
setKeyboard(false);
|
||||
};
|
||||
}, [next]);
|
||||
|
||||
useEffect(() => {
|
||||
toastMessages = [];
|
||||
let sub1 = Keyboard.addListener("keyboardDidShow", _onKeyboardShow);
|
||||
let sub2 = Keyboard.addListener("keyboardDidHide", _onKeyboardHide);
|
||||
eSubscribeEvent(eShowToast, showToastFunc);
|
||||
eSubscribeEvent(eHideToast, hideToastFunc);
|
||||
eSubscribeEvent(eShowToast, show);
|
||||
eSubscribeEvent(eHideToast, hide);
|
||||
return () => {
|
||||
if (hideTimeout.current) {
|
||||
clearTimeout(hideTimeout.current);
|
||||
}
|
||||
|
||||
toastMessages = [];
|
||||
sub1?.remove();
|
||||
sub2?.remove();
|
||||
eUnSubscribeEvent(eShowToast, showToastFunc);
|
||||
eUnSubscribeEvent(eHideToast, hideToastFunc);
|
||||
toastMessages.current = [];
|
||||
eUnSubscribeEvent(eShowToast, show);
|
||||
eUnSubscribeEvent(eHideToast, hide);
|
||||
};
|
||||
}, [hideToastFunc, keyboard, showToastFunc]);
|
||||
}, [hide, show]);
|
||||
|
||||
return (
|
||||
visible && (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
if (hideTimeout.current) {
|
||||
clearTimeout(hideTimeout.current);
|
||||
}
|
||||
hideToastFunc();
|
||||
}}
|
||||
onPress={hide}
|
||||
activeOpacity={1}
|
||||
style={{
|
||||
width: DDS.isTab ? 400 : "100%",
|
||||
@@ -209,7 +189,7 @@ export const Toast = ({ context = "global" }) => {
|
||||
color={colors.pri}
|
||||
size={SIZE.md}
|
||||
onPress={() => {
|
||||
hideToastFunc();
|
||||
hide();
|
||||
}}
|
||||
>
|
||||
{data.heading}
|
||||
@@ -224,7 +204,7 @@ export const Toast = ({ context = "global" }) => {
|
||||
paddingRight: 10
|
||||
}}
|
||||
onPress={() => {
|
||||
hideToastFunc();
|
||||
hide();
|
||||
}}
|
||||
>
|
||||
{data.message}
|
||||
|
||||
@@ -19,4 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { FeatureType } from "./components/sheets/new-feature";
|
||||
|
||||
export const features: FeatureType[] = [];
|
||||
export const features: FeatureType[] = [
|
||||
{
|
||||
title: "Default font size & font family",
|
||||
body: "Now you can set default font size and font family in editor that will be used across all your new and old notes."
|
||||
}
|
||||
];
|
||||
|
||||
@@ -613,7 +613,7 @@ export const useActions = ({ close = () => null, item }) => {
|
||||
},
|
||||
{
|
||||
id: "pin",
|
||||
title: item.pinned ? "Unpin" : "Pin",
|
||||
title: "Pin",
|
||||
icon: item.pinned ? "pin-off-outline" : "pin-outline",
|
||||
func: pinItem,
|
||||
close: false,
|
||||
@@ -623,7 +623,7 @@ export const useActions = ({ close = () => null, item }) => {
|
||||
},
|
||||
{
|
||||
id: "favorite",
|
||||
title: !item.favorite ? "Favorite" : "Unfavorite",
|
||||
title: "Favorite",
|
||||
icon: item.favorite ? "star-off" : "star-outline",
|
||||
func: addToFavorites,
|
||||
close: false,
|
||||
|
||||
@@ -571,8 +571,8 @@ export const useAppEvents = () => {
|
||||
if (notesAddedFromIntent || shareExtensionOpened) {
|
||||
let id = useEditorStore.getState().currentEditingNote;
|
||||
let note = id && db.notes.note(id).data;
|
||||
eSendEvent("loadingNote", note);
|
||||
eSendEvent("webview_reset");
|
||||
setTimeout(() => eSendEvent("loadingNote", note), 1);
|
||||
MMKV.removeItem("shareExtensionOpened");
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -17,35 +17,46 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useAttachmentStore } from "../stores/use-attachment-store";
|
||||
|
||||
export const useAttachmentProgress = (attachment, encryption) => {
|
||||
type AttachmentProgress = {
|
||||
type: string;
|
||||
value?: number;
|
||||
percent?: string;
|
||||
};
|
||||
|
||||
export const useAttachmentProgress = (
|
||||
attachment: any,
|
||||
encryption?: boolean
|
||||
) => {
|
||||
const progress = useAttachmentStore((state) => state.progress);
|
||||
const [currentProgress, setCurrentProgress] = useState(
|
||||
const [currentProgress, setCurrentProgress] = useState<
|
||||
AttachmentProgress | undefined
|
||||
>(
|
||||
encryption
|
||||
? {
|
||||
type: "encrypt"
|
||||
}
|
||||
: null
|
||||
: undefined
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
let prog = progress[attachment.metadata.hash];
|
||||
if (prog) {
|
||||
let type = prog.type;
|
||||
let loaded = prog.type === "download" ? prog.recieved : prog.sent;
|
||||
prog = loaded / prog.total;
|
||||
prog = (prog * 100).toFixed(0);
|
||||
setCurrentProgress({
|
||||
value: prog,
|
||||
percent: prog + "%",
|
||||
type: type
|
||||
});
|
||||
} else {
|
||||
setCurrentProgress(null);
|
||||
}
|
||||
}, [attachment.metadata.hash, progress]);
|
||||
const attachmentProgress = progress?.[attachment.metadata.hash];
|
||||
if (attachmentProgress) {
|
||||
const type = attachmentProgress.type;
|
||||
const loaded =
|
||||
attachmentProgress.type === "download"
|
||||
? attachmentProgress.recieved
|
||||
: attachmentProgress.sent;
|
||||
const value = loaded / attachmentProgress.total;
|
||||
setCurrentProgress({
|
||||
value: value * 100,
|
||||
percent: (value * 100).toFixed(0) + "%",
|
||||
type: type
|
||||
});
|
||||
} else {
|
||||
setCurrentProgress(undefined);
|
||||
}
|
||||
|
||||
return [currentProgress, setCurrentProgress];
|
||||
};
|
||||
@@ -1,61 +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 React, { useCallback, useEffect } from "react";
|
||||
import BiometicService from "../services/biometrics";
|
||||
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
||||
import { db } from "../common/database";
|
||||
|
||||
const VaultStatusCache = {
|
||||
exists: false,
|
||||
biometryEnrolled: false,
|
||||
isBiometryAvailable: false
|
||||
};
|
||||
|
||||
export const useVaultStatus = () => {
|
||||
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusCache);
|
||||
|
||||
const checkVaultStatus = useCallback(() => {
|
||||
db.vault.exists().then(async (exists) => {
|
||||
let available = await BiometicService.isBiometryAvailable();
|
||||
let fingerprint = await BiometicService.hasInternetCredentials();
|
||||
if (
|
||||
VaultStatusCache.exists === exists &&
|
||||
VaultStatusCache.biometryEnrolled === fingerprint &&
|
||||
VaultStatusCache.isBiometryAvailable === available
|
||||
)
|
||||
return;
|
||||
setVaultStatus({
|
||||
exists: exists,
|
||||
biometryEnrolled: fingerprint,
|
||||
isBiometryAvailable: available ? true : false
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
checkVaultStatus();
|
||||
eSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
||||
return () => {
|
||||
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
|
||||
};
|
||||
}, [checkVaultStatus]);
|
||||
|
||||
return vaultStatus;
|
||||
};
|
||||
@@ -10,7 +10,7 @@
|
||||
"buffer": "^6.0.3",
|
||||
"dayjs": "^1.10.4",
|
||||
"entities": "^3.0.1",
|
||||
"html-to-text": "8.1.0",
|
||||
"html-to-text": "9.0.5",
|
||||
"phone": "^3.1.14",
|
||||
"qclone": "^1.2.0",
|
||||
"react-native-actions-sheet": "0.9.0-alpha.18",
|
||||
|
||||
@@ -24,6 +24,7 @@ import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState
|
||||
} from "react";
|
||||
import { Platform, ViewStyle } from "react-native";
|
||||
@@ -89,7 +90,7 @@ const Editor = React.memo(
|
||||
noToolbar,
|
||||
noHeader
|
||||
});
|
||||
|
||||
const renderKey = useRef(`editor-0`);
|
||||
useImperativeHandle(ref, () => ({
|
||||
get: () => editor
|
||||
}));
|
||||
@@ -124,6 +125,8 @@ const Editor = React.memo(
|
||||
);
|
||||
|
||||
const onError = useCallback(() => {
|
||||
renderKey.current =
|
||||
renderKey.current === `editor-0` ? `editor-1` : `editor-0`;
|
||||
editor.setLoading(true);
|
||||
setTimeout(() => editor.setLoading(false), 10);
|
||||
}, [editor]);
|
||||
@@ -152,6 +155,7 @@ const Editor = React.memo(
|
||||
testID={notesnook.editor.id}
|
||||
ref={editor.ref}
|
||||
onLoad={editor.onLoad}
|
||||
key={renderKey.current}
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
|
||||
@@ -106,6 +106,7 @@ typeof globalThis.editorTitle !== "undefined" && editorTitle.current && editorTi
|
||||
if (editorController.content) editorController.content.current = null;
|
||||
editorController.onUpdate();
|
||||
editorController.setTitle(null);
|
||||
editorController.countWords(0);
|
||||
typeof globalThis.statusBar !== "undefined" && statusBar.current.set({date:"",saved:""});
|
||||
`
|
||||
);
|
||||
|
||||
@@ -48,6 +48,8 @@ export type Settings = {
|
||||
keyboardShown?: boolean;
|
||||
doubleSpacedLines?: boolean;
|
||||
corsProxy: string;
|
||||
fontSize: string;
|
||||
fontFamily: string;
|
||||
};
|
||||
|
||||
export type EditorProps = {
|
||||
|
||||
@@ -136,6 +136,13 @@ export const useEditorEvents = (
|
||||
const doubleSpacedLines = useSettingStore(
|
||||
(state) => state.settings?.doubleSpacedLines
|
||||
);
|
||||
const defaultFontSize = useSettingStore(
|
||||
(state) => state.settings.defaultFontSize
|
||||
);
|
||||
const defaultFontFamily = useSettingStore(
|
||||
(state) => state.settings.defaultFontFamily
|
||||
);
|
||||
|
||||
const tools = useDragState((state) => state.data);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -164,7 +171,9 @@ export const useEditorEvents = (
|
||||
noHeader: noHeader,
|
||||
noToolbar: readonly || editorPropReadonly || noToolbar,
|
||||
doubleSpacedLines: doubleSpacedLines,
|
||||
corsProxy: corsProxy
|
||||
corsProxy: corsProxy,
|
||||
fontSize: defaultFontSize,
|
||||
fontFamily: defaultFontFamily
|
||||
});
|
||||
}, [
|
||||
fullscreen,
|
||||
@@ -179,7 +188,9 @@ export const useEditorEvents = (
|
||||
editorPropReadonly,
|
||||
noHeader,
|
||||
noToolbar,
|
||||
corsProxy
|
||||
corsProxy,
|
||||
defaultFontSize,
|
||||
defaultFontFamily
|
||||
]);
|
||||
|
||||
const onBackPress = useCallback(async () => {
|
||||
|
||||
@@ -580,22 +580,21 @@ export const useEditor = (
|
||||
|
||||
const onReady = useCallback(async () => {
|
||||
if (!(await isEditorLoaded(editorRef, sessionIdRef.current))) {
|
||||
overlay(true);
|
||||
setLoading(true);
|
||||
eSendEvent("webview_reset");
|
||||
} else {
|
||||
isDefaultEditor && restoreEditorState();
|
||||
}
|
||||
}, [overlay, isDefaultEditor, restoreEditorState]);
|
||||
}, [isDefaultEditor, restoreEditorState]);
|
||||
|
||||
useEffect(() => {
|
||||
state.current.saveCount = 0;
|
||||
async () => {
|
||||
(async () => {
|
||||
await commands.setSessionId(sessionIdRef.current);
|
||||
if (sessionIdRef.current) {
|
||||
if (!state.current?.ready) return;
|
||||
await onReady();
|
||||
}
|
||||
};
|
||||
})();
|
||||
}, [sessionId, loading, commands, onReady]);
|
||||
|
||||
const onLoad = useCallback(async () => {
|
||||
@@ -636,6 +635,7 @@ export const useEditor = (
|
||||
saveContent,
|
||||
onContentChanged,
|
||||
editorId: editorId,
|
||||
markImageLoaded
|
||||
markImageLoaded,
|
||||
overlay
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,6 +51,7 @@ export const EditorWrapper = ({ width }) => {
|
||||
if (editorState().movedAway) return;
|
||||
if (state === "active") {
|
||||
editorController.current.onReady();
|
||||
editorController.current.overlay(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import { Licenses } from "./licenses";
|
||||
import SoundPicker from "./sound-picker";
|
||||
import { Subscription } from "./subscription";
|
||||
import { TrashIntervalSelector } from "./trash-interval-selector";
|
||||
import { FontSelector } from "./font-selector";
|
||||
export const components: { [name: string]: ReactElement } = {
|
||||
colorpicker: <AccentColorPicker />,
|
||||
homeselector: <HomagePageSelector />,
|
||||
@@ -35,5 +36,6 @@ export const components: { [name: string]: ReactElement } = {
|
||||
"debug-logs": <DebugLogs />,
|
||||
"sound-picker": <SoundPicker />,
|
||||
licenses: <Licenses />,
|
||||
"trash-interval-selector": <TrashIntervalSelector />
|
||||
"trash-interval-selector": <TrashIntervalSelector />,
|
||||
"font-selector": <FontSelector />
|
||||
};
|
||||
|
||||
@@ -20,8 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { ToolId } from "@notesnook/editor/dist/toolbar";
|
||||
import React, { RefObject } from "react";
|
||||
import { View } from "react-native";
|
||||
import ActionSheet from "react-native-actions-sheet";
|
||||
import { ScrollView } from "react-native-gesture-handler";
|
||||
import { PressableButton } from "../../../components/ui/pressable";
|
||||
import { SvgView } from "../../../components/ui/svg";
|
||||
import Paragraph from "../../../components/ui/typography/paragraph";
|
||||
@@ -34,13 +32,14 @@ import {
|
||||
getToolIcon,
|
||||
getUngroupedTools
|
||||
} from "./toolbar-definition";
|
||||
import { ActionSheetRef, ScrollView } from "react-native-actions-sheet";
|
||||
|
||||
export default function ToolSheet({
|
||||
group,
|
||||
fwdRef
|
||||
}: {
|
||||
group: DraggableItem;
|
||||
fwdRef: RefObject<ActionSheet>;
|
||||
fwdRef: RefObject<ActionSheetRef>;
|
||||
}) {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const data = useDragState((state) => state.data);
|
||||
@@ -50,6 +49,7 @@ export default function ToolSheet({
|
||||
(item: ToolId) => {
|
||||
const tool = findToolById(item);
|
||||
const iconSvgString = tool ? getToolIcon(tool.icon as ToolId) : null;
|
||||
if (item === "none") return;
|
||||
return (
|
||||
<PressableButton
|
||||
key={item}
|
||||
@@ -109,12 +109,7 @@ export default function ToolSheet({
|
||||
padding: 12
|
||||
}}
|
||||
>
|
||||
<ScrollView
|
||||
onMomentumScrollEnd={() => {
|
||||
fwdRef.current?.handleChildScrollEnd();
|
||||
}}
|
||||
nestedScrollEnabled={true}
|
||||
>
|
||||
<ScrollView nestedScrollEnabled={true}>
|
||||
{!ungrouped || ungrouped.length === 0 ? (
|
||||
<Paragraph
|
||||
style={{
|
||||
|
||||
110
apps/mobile/app/screens/settings/font-selector.jsx
Normal file
110
apps/mobile/app/screens/settings/font-selector.jsx
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
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 React, { useRef, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import Menu, { MenuItem } from "react-native-reanimated-material-menu";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { PressableButton } from "../../components/ui/pressable";
|
||||
import Paragraph from "../../components/ui/typography/paragraph";
|
||||
import SettingsService from "../../services/settings";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import { getFontById, getFonts } from "@notesnook/editor/dist/utils/font";
|
||||
|
||||
export const FontSelector = () => {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
const defaultFontFamily = useSettingStore(
|
||||
(state) => state.settings.defaultFontFamily
|
||||
);
|
||||
const menuRef = useRef();
|
||||
const [width, setWidth] = useState(0);
|
||||
|
||||
const onChange = (item) => {
|
||||
menuRef.current?.hide();
|
||||
SettingsService.set({
|
||||
defaultFontFamily: item
|
||||
});
|
||||
};
|
||||
return (
|
||||
<View
|
||||
onLayout={(event) => {
|
||||
setWidth(event.nativeEvent.layout.width);
|
||||
}}
|
||||
style={{
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
animationDuration={200}
|
||||
style={{
|
||||
borderRadius: 5,
|
||||
backgroundColor: colors.bg,
|
||||
width: width,
|
||||
marginTop: 60
|
||||
}}
|
||||
onRequestClose={() => {
|
||||
menuRef.current?.hide();
|
||||
}}
|
||||
anchor={
|
||||
<PressableButton
|
||||
onPress={async () => {
|
||||
menuRef.current?.show();
|
||||
}}
|
||||
type="grayBg"
|
||||
customStyle={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 10,
|
||||
width: "100%",
|
||||
justifyContent: "space-between",
|
||||
padding: 12
|
||||
}}
|
||||
>
|
||||
<Paragraph>{getFontById(defaultFontFamily).title}</Paragraph>
|
||||
<Icon color={colors.icon} name="menu-down" size={SIZE.md} />
|
||||
</PressableButton>
|
||||
}
|
||||
>
|
||||
{getFonts().map((item) => (
|
||||
<MenuItem
|
||||
key={item.id}
|
||||
onPress={async () => {
|
||||
onChange(item.id);
|
||||
}}
|
||||
style={{
|
||||
backgroundColor:
|
||||
defaultFontFamily === item.id ? colors.nav : "transparent",
|
||||
width: "100%",
|
||||
maxWidth: width
|
||||
}}
|
||||
textStyle={{
|
||||
fontSize: SIZE.md,
|
||||
color: defaultFontFamily === item.id ? colors.accent : colors.pri
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -37,6 +37,7 @@ import { useThemeStore } from "../../stores/use-theme-store";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import { components } from "./components";
|
||||
import { RouteParams, SettingSection } from "./types";
|
||||
import { IconButton } from "../../components/ui/icon-button";
|
||||
|
||||
const _SectionItem = ({ item }: { item: SettingSection }) => {
|
||||
const colors = useThemeStore((state) => state.colors);
|
||||
@@ -64,6 +65,12 @@ const _SectionItem = ({ item }: { item: SettingSection }) => {
|
||||
backgroundColor: colors.errorBg
|
||||
}
|
||||
: {};
|
||||
|
||||
const updateInput = (value: any) => {
|
||||
inputRef?.current?.setNativeProps({
|
||||
text: value + ""
|
||||
});
|
||||
};
|
||||
return isHidden ? null : (
|
||||
<PressableButton
|
||||
disabled={item.type === "component"}
|
||||
@@ -190,6 +197,95 @@ const _SectionItem = ({ item }: { item: SettingSection }) => {
|
||||
defaultValue={item.inputProperties?.defaultValue}
|
||||
/>
|
||||
)}
|
||||
|
||||
{item.type === "input-selector" && (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 12
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
name="minus"
|
||||
color={colors.pri}
|
||||
onPress={() => {
|
||||
const rawValue = SettingsService.get()[
|
||||
item.property as keyof SettingStore["settings"]
|
||||
] as string;
|
||||
if (rawValue) {
|
||||
const currentValue = parseInt(rawValue);
|
||||
if (currentValue <= 0) return;
|
||||
const nextValue = currentValue - 1;
|
||||
SettingsService.set({
|
||||
[item.property as string]: nextValue
|
||||
});
|
||||
updateInput(nextValue);
|
||||
}
|
||||
}}
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
<Input
|
||||
{...item.inputProperties}
|
||||
onSubmit={(e) => {
|
||||
if (e.nativeEvent.text) {
|
||||
SettingsService.set({
|
||||
[item.property as string]: e.nativeEvent.text
|
||||
});
|
||||
}
|
||||
item.inputProperties?.onSubmitEditing?.(e);
|
||||
}}
|
||||
onChangeText={(text) => {
|
||||
if (text) {
|
||||
if (item.minInputValue) {
|
||||
text =
|
||||
parseInt(text) < item.minInputValue
|
||||
? item.minInputValue + ""
|
||||
: text;
|
||||
}
|
||||
SettingsService.set({
|
||||
[item.property as string]: text
|
||||
});
|
||||
}
|
||||
item.inputProperties?.onSubmitEditing?.(text as any);
|
||||
}}
|
||||
keyboardType="decimal-pad"
|
||||
containerStyle={{
|
||||
width: 45
|
||||
}}
|
||||
wrapperStyle={{
|
||||
maxWidth: 45,
|
||||
marginBottom: 0,
|
||||
marginHorizontal: 6
|
||||
}}
|
||||
fwdRef={inputRef}
|
||||
onLayout={() => {
|
||||
if (item.property) {
|
||||
updateInput(SettingsService.get()[item.property]);
|
||||
}
|
||||
}}
|
||||
defaultValue={item.inputProperties?.defaultValue}
|
||||
/>
|
||||
<IconButton
|
||||
name="plus"
|
||||
color={colors.pri}
|
||||
onPress={() => {
|
||||
const rawValue = SettingsService.get()[
|
||||
item.property as keyof SettingStore["settings"]
|
||||
] as string;
|
||||
if (rawValue) {
|
||||
const currentValue = parseInt(rawValue);
|
||||
const nextValue = currentValue + 1;
|
||||
SettingsService.set({
|
||||
[item.property as string]: nextValue
|
||||
});
|
||||
updateInput(nextValue);
|
||||
}
|
||||
}}
|
||||
size={SIZE.xl}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import notifee from "@notifee/react-native";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import React from "react";
|
||||
import { Linking, Platform } from "react-native";
|
||||
@@ -450,13 +451,13 @@ export const settingsGroups: SettingSection[] = [
|
||||
},
|
||||
{
|
||||
id: "customize",
|
||||
name: "Customize",
|
||||
name: "Customization",
|
||||
sections: [
|
||||
{
|
||||
id: "personalization",
|
||||
type: "screen",
|
||||
name: "Theme",
|
||||
description: "Change app look and feel",
|
||||
description: "Change app look and feel with color themes",
|
||||
icon: "shape",
|
||||
sections: [
|
||||
{
|
||||
@@ -514,7 +515,7 @@ export const settingsGroups: SettingSection[] = [
|
||||
id: "behaviour",
|
||||
type: "screen",
|
||||
name: "Behaviour",
|
||||
description: "Change app homepage",
|
||||
description: "Change how the app behaves in different situations",
|
||||
sections: [
|
||||
{
|
||||
id: "default-home",
|
||||
@@ -532,6 +533,63 @@ export const settingsGroups: SettingSection[] = [
|
||||
component: "trash-interval-selector"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "editor",
|
||||
name: "Editor",
|
||||
type: "screen",
|
||||
icon: "note-edit-outline",
|
||||
description: "Customize the editor to fit your needs",
|
||||
sections: [
|
||||
{
|
||||
id: "configure-toolbar",
|
||||
type: "screen",
|
||||
name: "Configure toolbar",
|
||||
description: "Make the toolbar adaptable to your needs.",
|
||||
component: "configuretoolbar"
|
||||
},
|
||||
{
|
||||
id: "reset-toolbar",
|
||||
name: "Reset toolbar",
|
||||
description: "Reset toolbar configuration to default",
|
||||
modifer: () => {
|
||||
useDragState.getState().setPreset("default");
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "double-spaced-lines",
|
||||
name: "Use double spaced lines",
|
||||
description:
|
||||
"New lines will be double spaced (old ones won't be affected).",
|
||||
type: "switch",
|
||||
property: "doubleSpacedLines",
|
||||
icon: "format-line-spacing",
|
||||
onChange: () => {
|
||||
ToastEvent.show({
|
||||
heading: "Line spacing changed",
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "default-font-size",
|
||||
name: "Default font size",
|
||||
description: "Set the default font size in editor",
|
||||
type: "input-selector",
|
||||
minInputValue: 8,
|
||||
icon: "format-size",
|
||||
property: "defaultFontSize"
|
||||
},
|
||||
{
|
||||
id: "default-font-family",
|
||||
name: "Default font family",
|
||||
description: "Set the default font family in editor",
|
||||
type: "component",
|
||||
icon: "format-font",
|
||||
property: "defaultFontFamily",
|
||||
component: "font-selector"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -928,42 +986,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "editor",
|
||||
name: "Editor",
|
||||
sections: [
|
||||
{
|
||||
id: "configure-toolbar",
|
||||
type: "screen",
|
||||
name: "Configure toolbar",
|
||||
description: "Make the toolbar adaptable to your needs.",
|
||||
component: "configuretoolbar"
|
||||
},
|
||||
{
|
||||
id: "reset-toolbar",
|
||||
name: "Reset toolbar",
|
||||
description: "Reset toolbar configuration to default",
|
||||
modifer: () => {
|
||||
useDragState.getState().setPreset("default");
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "double-spaced-lines",
|
||||
name: "Use double spaced lines",
|
||||
description:
|
||||
"New lines will be double spaced (old ones won't be affected).",
|
||||
type: "switch",
|
||||
property: "doubleSpacedLines",
|
||||
icon: "format-line-spacing",
|
||||
onChange: () => {
|
||||
ToastEvent.show({
|
||||
heading: "Line spacing changed",
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "help-support",
|
||||
name: "Help and support",
|
||||
|
||||
@@ -22,7 +22,14 @@ import { Settings } from "../../stores/use-setting-store";
|
||||
|
||||
export type SettingSection = {
|
||||
id: string;
|
||||
type?: "screen" | "switch" | "component" | "danger" | "input";
|
||||
type?:
|
||||
| "screen"
|
||||
| "switch"
|
||||
| "component"
|
||||
| "danger"
|
||||
| "input"
|
||||
| "input-selector"
|
||||
| "dropdown-selector";
|
||||
name?: string | ((current?: unknown) => string);
|
||||
description?: string | ((current: unknown) => string);
|
||||
icon?: string;
|
||||
@@ -35,6 +42,8 @@ export type SettingSection = {
|
||||
hidden?: (current: unknown) => boolean;
|
||||
onChange?: (property: boolean) => void;
|
||||
inputProperties?: TextInput["props"];
|
||||
options?: any[];
|
||||
minInputValue?: number;
|
||||
};
|
||||
|
||||
export type SettingsGroup = {
|
||||
|
||||
@@ -86,8 +86,9 @@ async function getNextMonthlyReminderDate(
|
||||
}
|
||||
|
||||
async function initDatabase(notes = true) {
|
||||
if (db.isInitialized) return;
|
||||
await db.initCollections();
|
||||
if (!db.isInitialized) {
|
||||
await db.initCollections();
|
||||
}
|
||||
if (notes) {
|
||||
await db.notes?.init();
|
||||
}
|
||||
@@ -202,14 +203,15 @@ const onEvent = async ({ type, detail }: Event) => {
|
||||
reply_button_text: "Take note",
|
||||
reply_placeholder_text: "Write something..."
|
||||
});
|
||||
await initDatabase(false);
|
||||
if (!db.isInitialized) await db.init();
|
||||
await db.notes?.init();
|
||||
await db.notes?.add({
|
||||
content: {
|
||||
type: "tiptap",
|
||||
data: `<p>${input} </p>`
|
||||
}
|
||||
});
|
||||
await db.notes?.init();
|
||||
await db.sync(false, false);
|
||||
useNoteStore.getState().setNotes();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,14 +27,6 @@ import { DatabaseLogger } from "../common/database/index";
|
||||
import { ToastEvent } from "./event-manager";
|
||||
import SettingsService from "./settings";
|
||||
|
||||
NetInfo.configure({
|
||||
reachabilityUrl: "https://notesnook.com",
|
||||
reachabilityTest: (response) => {
|
||||
if (!response) return false;
|
||||
return response?.status >= 200 && response?.status < 300;
|
||||
}
|
||||
});
|
||||
|
||||
export const ignoredMessages = [
|
||||
"Sync already running",
|
||||
"Not allowed to start service intent",
|
||||
|
||||
@@ -24,7 +24,6 @@ import { db } from "../common/database";
|
||||
import { MMKV } from "../common/database/mmkv";
|
||||
import PremiumService from "../services/premium";
|
||||
import { SUBSCRIPTION_STATUS } from "../utils/constants";
|
||||
import layoutmanager from "../utils/layout-manager";
|
||||
export interface MessageStore extends State {
|
||||
message: Message;
|
||||
setMessage: (message: Message) => void;
|
||||
@@ -96,13 +95,7 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
icon: "account-outline"
|
||||
},
|
||||
setMessage: (message) => {
|
||||
setTimeout(() => {
|
||||
if (get().message.visible || message.visible) {
|
||||
layoutmanager.withAnimation();
|
||||
}
|
||||
|
||||
set({ message: { ...message } });
|
||||
}, 1);
|
||||
set({ message: { ...message } });
|
||||
},
|
||||
announcements: [],
|
||||
remove: async (id) => {
|
||||
|
||||
@@ -69,6 +69,7 @@ export type RouteParams = {
|
||||
AppLock: AppLockRouteParams;
|
||||
Auth: AuthParams;
|
||||
Reminders: GenericRouteParam;
|
||||
SettingsGroup: GenericRouteParam;
|
||||
};
|
||||
|
||||
export type RouteName = keyof RouteParams;
|
||||
|
||||
@@ -73,6 +73,8 @@ export type Settings = {
|
||||
corsProxy: string;
|
||||
disableRealtimeSync?: boolean;
|
||||
notificationSound?: Sound & { platform: PlatformOSType };
|
||||
defaultFontSize: string;
|
||||
defaultFontFamily: string;
|
||||
};
|
||||
|
||||
type DimensionsType = {
|
||||
@@ -149,7 +151,9 @@ export const useSettingStore = create<SettingStore>((set) => ({
|
||||
defaultSnoozeTime: "5",
|
||||
corsProxy: "https://cors.notesnook.com",
|
||||
reminderNotificationMode: "urgent",
|
||||
notificationSound: undefined
|
||||
notificationSound: undefined,
|
||||
defaultFontFamily: "sans-serif",
|
||||
defaultFontSize: "16"
|
||||
},
|
||||
sheetKeyboardHandler: true,
|
||||
fullscreen: false,
|
||||
|
||||
@@ -27,7 +27,6 @@ import { db } from "../common/database";
|
||||
import { tabBarRef } from "./global-refs";
|
||||
|
||||
let prevTarget = null;
|
||||
let htmlToText;
|
||||
|
||||
export const TOOLTIP_POSITIONS = {
|
||||
LEFT: 1,
|
||||
@@ -171,3 +170,8 @@ export function showTooltip(event, text, position = 2) {
|
||||
clickToHide: true
|
||||
});
|
||||
}
|
||||
|
||||
export function toTitleCase(value) {
|
||||
if (!value) return;
|
||||
return value.slice(0, 1).toUpperCase() + value.slice(1);
|
||||
}
|
||||
|
||||
@@ -46,18 +46,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* @return {String} Sanitized filename
|
||||
*/
|
||||
|
||||
var illegalRe = /[/?<>\\:*|"]/g;
|
||||
const illegalRe = /[/?<>\\:*|"]/g;
|
||||
//var controlRe = /[x00-x1f\x80-\x9f]/g;
|
||||
var reservedRe = /^\.+$/;
|
||||
var windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
|
||||
var windowsTrailingRe = /[. ]+$/;
|
||||
var whitespace = /\s+/g;
|
||||
const reservedRe = /^\.+$/;
|
||||
const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
|
||||
const windowsTrailingRe = /[. ]+$/;
|
||||
const whitespace = /\s+/g;
|
||||
|
||||
function sanitize(input, replacement) {
|
||||
function sanitize(input: string, replacement: string) {
|
||||
if (typeof input !== "string") {
|
||||
throw new Error("Input must be string");
|
||||
}
|
||||
var sanitized = input
|
||||
const sanitized = input
|
||||
.replace(whitespace, replacement)
|
||||
.replace(illegalRe, replacement)
|
||||
.replace(reservedRe, replacement)
|
||||
@@ -67,7 +67,10 @@ function sanitize(input, replacement) {
|
||||
return sanitized.slice(0, 254).toLowerCase();
|
||||
}
|
||||
|
||||
export function sanitizeFilename(input, options) {
|
||||
var replacement = (options && options.replacement) || "";
|
||||
export function sanitizeFilename(
|
||||
input: string,
|
||||
options: { replacement: string }
|
||||
) {
|
||||
const replacement = (options && options.replacement) || "";
|
||||
return sanitize(input, replacement);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ describe("NOTE TESTS", () => {
|
||||
await prepare();
|
||||
let note = await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await visibleByText(note.body);
|
||||
await visibleByText("Created at:");
|
||||
});
|
||||
|
||||
it("Favorite and unfavorite a note", async () => {
|
||||
@@ -124,8 +124,9 @@ describe("NOTE TESTS", () => {
|
||||
await prepare();
|
||||
await createNote();
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapById("icon-delete");
|
||||
await tapById("icon-trash");
|
||||
await navigate("Trash");
|
||||
await sleep(500);
|
||||
await tapById(notesnook.listitem.menu);
|
||||
await tapByText("Restore note");
|
||||
await device.pressBack();
|
||||
|
||||
@@ -56,7 +56,7 @@ async function createNotebook(
|
||||
await tapById("topic-add-button");
|
||||
}
|
||||
}
|
||||
await tapByText("Create notebook");
|
||||
await tapByText("Save");
|
||||
await sleep(500);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ describe("NOTEBOOKS", () => {
|
||||
await visibleByText(note.body);
|
||||
});
|
||||
|
||||
it("Add new topic to notebook", async () => {
|
||||
it.only("Add new topic to notebook", async () => {
|
||||
await prepare();
|
||||
await navigate("Notebooks");
|
||||
await sleep(500);
|
||||
@@ -133,7 +133,7 @@ describe("NOTEBOOKS", () => {
|
||||
await elementById("input-title").typeText("Topic");
|
||||
await tapByText("Add");
|
||||
await sleep(500);
|
||||
await visibleById("topic-sheet-item-0");
|
||||
await tapByText("Topic");
|
||||
});
|
||||
|
||||
it("Edit topic", async () => {
|
||||
@@ -146,7 +146,6 @@ describe("NOTEBOOKS", () => {
|
||||
await sleep(500);
|
||||
await tapByText("Notebook 1");
|
||||
await sleep(300);
|
||||
await visibleById("topic-sheet-item-0");
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Edit topic");
|
||||
await elementById("input-title").typeText(" (edited)");
|
||||
@@ -254,7 +253,7 @@ describe("NOTEBOOKS", () => {
|
||||
"Topic 2"
|
||||
);
|
||||
await tapById("topic-add-button");
|
||||
await tapByText("Save changes");
|
||||
await tapByText("Save");
|
||||
await sleep(500);
|
||||
await visibleByText("Notebook 1 (Edited)");
|
||||
await visibleByText("Description of Notebook 1 (Edited)");
|
||||
@@ -274,7 +273,7 @@ describe("NOTEBOOKS", () => {
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Move to trash");
|
||||
await sleep(2000);
|
||||
await tapByText("No");
|
||||
await tapByText("Delete");
|
||||
await sleep(4000);
|
||||
await navigate("Trash");
|
||||
await visibleByText("Notebook 1");
|
||||
@@ -296,7 +295,9 @@ describe("NOTEBOOKS", () => {
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Move to trash");
|
||||
await sleep(2000);
|
||||
await tapByText("Yes");
|
||||
await tapByText("Move all notes in this notebook to trash");
|
||||
await sleep(500);
|
||||
await tapByText("Delete");
|
||||
await sleep(4000);
|
||||
await navigate("Trash");
|
||||
await visibleByText("Notebook 1");
|
||||
@@ -319,7 +320,9 @@ describe("NOTEBOOKS", () => {
|
||||
await tapById(notesnook.ids.notebook.menu);
|
||||
await tapByText("Delete topic");
|
||||
await sleep(2000);
|
||||
await tapByText("Yes");
|
||||
await tapByText("Move all notes in this topic to trash");
|
||||
await sleep(500);
|
||||
await tapByText("Delete");
|
||||
await device.pressBack();
|
||||
await sleep(4000);
|
||||
await navigate("Trash");
|
||||
|
||||
@@ -164,7 +164,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 2043
|
||||
versionCode 2044
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.streetwriters.notesnook;
|
||||
import android.graphics.Color;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
@@ -36,6 +37,16 @@ public class RCTNNativeModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getActivityName(Promise promise) {
|
||||
try {
|
||||
promise.resolve(getCurrentActivity().getClass().getSimpleName());
|
||||
} catch (Exception e) {
|
||||
promise.resolve(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void setSecureMode(final boolean mode) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
- Fixed text exports not following line spacing settings
|
||||
- Fixed tags are not updated in list after renaming
|
||||
- Fixed a sync issue where notes marked as local only would get deleted sometimes
|
||||
- Fixed a bug where opening a note from search then closing it would cause a crash
|
||||
- Added default font size & font family settings
|
||||
- Redesign reminder/notebook sheets to improve UX
|
||||
- Fixed an issue causing sync to fail
|
||||
- Fix tag suggestions in share extension
|
||||
- Fix app font sizes too small in some places
|
||||
- Improved mobile editor performance on low-end devices
|
||||
- Fix pin to notifications not working
|
||||
- Bug fixes and performance improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -993,7 +993,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1067,7 +1067,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1097,7 +1097,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Notesnook/Notesnook.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
@@ -1170,7 +1170,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1328,7 +1328,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1340,7 +1340,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1370,7 +1370,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1382,7 +1382,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1411,7 +1411,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1485,7 +1485,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1515,7 +1515,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2035;
|
||||
CURRENT_PROJECT_VERSION = 2036;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1589,7 +1589,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.4.12;
|
||||
MARKETING_VERSION = 2.4.13;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
- Fixed text exports not following line spacing settings
|
||||
- Fixed tags are not updated in list after renaming
|
||||
- Fixed a sync issue where notes marked as local only would get deleted sometimes
|
||||
- Fixed a bug where opening a note from search then closing it would cause a crash
|
||||
- Added default font size & font family settings
|
||||
- Redesign reminder/notebook sheets to improve UX
|
||||
- Fixed an issue causing sync to fail
|
||||
- Fix tag suggestions in share extension
|
||||
- Fix app font sizes too small in some places
|
||||
- Improved mobile editor performance on low-end devices
|
||||
- Fix pin to notifications not working
|
||||
- Bug fixes and performance improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -86,7 +86,17 @@ module.exports = (env) => {
|
||||
"@notesnook": path.join(__dirname, "../../../packages"),
|
||||
"@streetwriters/showdown": path.join(__dirname, "../node_modules/@streetwriters/showdown"),
|
||||
"qclone": path.join(__dirname, "../node_modules/qclone"),
|
||||
"@notifee/react-native": path.join(__dirname, "../node_modules/@ammarahmed/notifee-react-native")
|
||||
"@notifee/react-native": path.join(__dirname, "../node_modules/@ammarahmed/notifee-react-native"),
|
||||
"html-to-text": path.join(__dirname, "../node_modules/html-to-text"),
|
||||
"leac": path.join(__dirname, "../node_modules/leac"),
|
||||
"parseley": path.join(__dirname, "../node_modules/parseley"),
|
||||
"htmlparser2": path.join(__dirname, "../node_modules/htmlparser2"),
|
||||
"selderee": path.join(__dirname, "../node_modules/selderee"),
|
||||
"minimist": path.join(__dirname, "../node_modules/minimist"),
|
||||
"entities": path.join(__dirname, "../node_modules/entities"),
|
||||
"deepmerge": path.join(__dirname, "../node_modules/deepmerge"),
|
||||
"@selderee/plugin-htmlparser2": path.join(__dirname, "../node_modules/@selderee/plugin-htmlparser2"),
|
||||
"peberminta": path.join(__dirname, "../node_modules/peberminta"),
|
||||
},
|
||||
},
|
||||
/**
|
||||
|
||||
460
apps/mobile/package-lock.json
generated
460
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.12",
|
||||
"version": "2.4.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.12",
|
||||
"version": "2.4.13",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
"native/",
|
||||
@@ -35,7 +35,7 @@
|
||||
"dayjs": "^1.10.4",
|
||||
"entities": "^3.0.1",
|
||||
"fflate": "^0.7.3",
|
||||
"html-to-text": "8.1.0",
|
||||
"html-to-text": "9.0.5",
|
||||
"phone": "^3.1.14",
|
||||
"qclone": "^1.2.0",
|
||||
"react-native-actions-sheet": "0.9.0-alpha.18",
|
||||
@@ -5620,12 +5620,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@selderee/plugin-htmlparser2": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz",
|
||||
"integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==",
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
|
||||
"dependencies": {
|
||||
"domhandler": "^4.2.0",
|
||||
"selderee": "^0.6.0"
|
||||
"domhandler": "^5.0.3",
|
||||
"selderee": "^0.11.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
@@ -8142,57 +8142,6 @@
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select/node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select/node_modules/domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select/node_modules/domutils": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
|
||||
"integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select/node_modules/entities": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
|
||||
"integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
|
||||
@@ -8288,9 +8237,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -8573,11 +8522,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/discontinuous-range": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
|
||||
},
|
||||
"node_modules/doctrine": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
@@ -8591,22 +8535,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer/node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
@@ -8628,11 +8575,11 @@
|
||||
]
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@@ -8642,13 +8589,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
|
||||
"integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
@@ -10967,14 +10914,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"bin": {
|
||||
"he": "bin/he"
|
||||
}
|
||||
},
|
||||
"node_modules/hermes-engine": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
||||
@@ -11024,28 +10963,24 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/html-to-text": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.1.0.tgz",
|
||||
"integrity": "sha512-Z9iYAqYK2c18GswSbnxJSeMs7lyJgwR2oIkDOyOHGBbYsPsG4HvT379jj3Lcbfko8A5ceyyMHAfkmp/BiXA9/Q==",
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
|
||||
"dependencies": {
|
||||
"@selderee/plugin-htmlparser2": "^0.6.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"he": "^1.2.0",
|
||||
"htmlparser2": "^6.1.0",
|
||||
"minimist": "^1.2.5",
|
||||
"selderee": "^0.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"html-to-text": "bin/cli.js"
|
||||
"@selderee/plugin-htmlparser2": "^0.11.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"htmlparser2": "^8.0.2",
|
||||
"selderee": "^0.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.23.2"
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
@@ -11054,16 +10989,19 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2/node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
@@ -14377,6 +14315,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/leac": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
||||
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
@@ -16188,11 +16134,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
|
||||
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@@ -16298,27 +16239,6 @@
|
||||
"ncp": "bin/ncp"
|
||||
}
|
||||
},
|
||||
"node_modules/nearley": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
|
||||
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
|
||||
"dependencies": {
|
||||
"commander": "^2.19.0",
|
||||
"moo": "^0.5.0",
|
||||
"railroad-diagrams": "^1.0.0",
|
||||
"randexp": "0.4.6"
|
||||
},
|
||||
"bin": {
|
||||
"nearley-railroad": "bin/nearley-railroad.js",
|
||||
"nearley-test": "bin/nearley-test.js",
|
||||
"nearley-unparse": "bin/nearley-unparse.js",
|
||||
"nearleyc": "bin/nearleyc.js"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://nearley.js.org/#give-to-nearley"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -16977,12 +16897,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parseley": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz",
|
||||
"integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==",
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.0.tgz",
|
||||
"integrity": "sha512-uLqDm6IQVb6m50a3dIxF66hI8VWr7wFDYUULtHa1ITRh9mwYIXzFpPTkPM66Cm5V0t+bMyeSHgUCGzoXTV96LQ==",
|
||||
"dependencies": {
|
||||
"moo": "^0.5.1",
|
||||
"nearley": "^2.20.1"
|
||||
"leac": "^0.6.0",
|
||||
"peberminta": "^0.9.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
@@ -17069,6 +16989,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/peberminta": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
|
||||
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
}
|
||||
},
|
||||
"node_modules/phin": {
|
||||
"version": "2.9.3",
|
||||
"resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz",
|
||||
@@ -17807,31 +17735,6 @@
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
|
||||
},
|
||||
"node_modules/railroad-diagrams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
|
||||
},
|
||||
"node_modules/randexp": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
|
||||
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||
"dependencies": {
|
||||
"discontinuous-range": "1.0.0",
|
||||
"ret": "~0.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/randexp/node_modules/ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -19159,11 +19062,11 @@
|
||||
"integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w=="
|
||||
},
|
||||
"node_modules/selderee": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz",
|
||||
"integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==",
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
|
||||
"dependencies": {
|
||||
"parseley": "^0.7.0"
|
||||
"parseley": "^0.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/killymxi"
|
||||
@@ -24311,7 +24214,7 @@
|
||||
"dayjs": "^1.10.4",
|
||||
"entities": "^3.0.1",
|
||||
"fflate": "^0.7.3",
|
||||
"html-to-text": "8.1.0",
|
||||
"html-to-text": "9.0.5",
|
||||
"phone": "^3.1.14",
|
||||
"qclone": "^1.2.0",
|
||||
"react-native-actions-sheet": "0.9.0-alpha.18",
|
||||
@@ -25573,12 +25476,12 @@
|
||||
"integrity": "sha512-1k57PXJIfhZrjA4ZQr+goTEYer8MBhe1At6XjVYJq1oBuhG/CIu0gX1EH9fU9exC65e5uDs/zAwjl6Ps+3lCgg=="
|
||||
},
|
||||
"@selderee/plugin-htmlparser2": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz",
|
||||
"integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==",
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
|
||||
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
|
||||
"requires": {
|
||||
"domhandler": "^4.2.0",
|
||||
"selderee": "^0.6.0"
|
||||
"domhandler": "^5.0.3",
|
||||
"selderee": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"@shopify/flash-list": {
|
||||
@@ -27520,41 +27423,6 @@
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
|
||||
"integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
|
||||
"requires": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
|
||||
"integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-tree": {
|
||||
@@ -27627,9 +27495,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"deepmerge": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
|
||||
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="
|
||||
},
|
||||
"defaults": {
|
||||
"version": "1.0.4",
|
||||
@@ -27823,11 +27691,6 @@
|
||||
"path-type": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"discontinuous-range": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
@@ -27838,19 +27701,19 @@
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -27865,21 +27728,21 @@
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
"domelementtype": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
|
||||
"integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"dooboolab-welcome": {
|
||||
@@ -29594,11 +29457,6 @@
|
||||
"type-fest": "^0.8.0"
|
||||
}
|
||||
},
|
||||
"he": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"hermes-engine": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/hermes-engine/-/hermes-engine-0.11.0.tgz",
|
||||
@@ -29645,33 +29503,32 @@
|
||||
"dev": true
|
||||
},
|
||||
"html-to-text": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.1.0.tgz",
|
||||
"integrity": "sha512-Z9iYAqYK2c18GswSbnxJSeMs7lyJgwR2oIkDOyOHGBbYsPsG4HvT379jj3Lcbfko8A5ceyyMHAfkmp/BiXA9/Q==",
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
|
||||
"requires": {
|
||||
"@selderee/plugin-htmlparser2": "^0.6.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"he": "^1.2.0",
|
||||
"htmlparser2": "^6.1.0",
|
||||
"minimist": "^1.2.5",
|
||||
"selderee": "^0.6.0"
|
||||
"@selderee/plugin-htmlparser2": "^0.11.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"htmlparser2": "^8.0.2",
|
||||
"selderee": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -32133,6 +31990,11 @@
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="
|
||||
},
|
||||
"leac": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
|
||||
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="
|
||||
},
|
||||
"leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
@@ -33541,11 +33403,6 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
|
||||
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@@ -33632,17 +33489,6 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nearley": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
|
||||
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
|
||||
"requires": {
|
||||
"commander": "^2.19.0",
|
||||
"moo": "^0.5.0",
|
||||
"railroad-diagrams": "^1.0.0",
|
||||
"randexp": "0.4.6"
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -34119,12 +33965,12 @@
|
||||
}
|
||||
},
|
||||
"parseley": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz",
|
||||
"integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==",
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.0.tgz",
|
||||
"integrity": "sha512-uLqDm6IQVb6m50a3dIxF66hI8VWr7wFDYUULtHa1ITRh9mwYIXzFpPTkPM66Cm5V0t+bMyeSHgUCGzoXTV96LQ==",
|
||||
"requires": {
|
||||
"moo": "^0.5.1",
|
||||
"nearley": "^2.20.1"
|
||||
"leac": "^0.6.0",
|
||||
"peberminta": "^0.9.0"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
@@ -34184,6 +34030,11 @@
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"peberminta": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
|
||||
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="
|
||||
},
|
||||
"phin": {
|
||||
"version": "2.9.3",
|
||||
"resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz",
|
||||
@@ -34734,27 +34585,6 @@
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
|
||||
},
|
||||
"railroad-diagrams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
|
||||
},
|
||||
"randexp": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
|
||||
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||
"requires": {
|
||||
"discontinuous-range": "1.0.0",
|
||||
"ret": "~0.1.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -35710,11 +35540,11 @@
|
||||
"integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w=="
|
||||
},
|
||||
"selderee": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz",
|
||||
"integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==",
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
|
||||
"requires": {
|
||||
"parseley": "^0.7.0"
|
||||
"parseley": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.4.12",
|
||||
"version": "2.4.13",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
diff --git a/node_modules/html-to-text/lib/formatter.js b/node_modules/html-to-text/lib/formatter.js
|
||||
index d6cb1e6..68d0337 100644
|
||||
--- a/node_modules/html-to-text/lib/formatter.js
|
||||
+++ b/node_modules/html-to-text/lib/formatter.js
|
||||
@@ -1,4 +1,4 @@
|
||||
-const he = require('he');
|
||||
+const {decode} = require('entities');
|
||||
|
||||
const { get, numberToLetterSequence, numberToRoman, splitClassesAndIds, trimCharacter } = require('./helper');
|
||||
|
||||
@@ -146,7 +146,7 @@ function withBrackets (str, brackets) {
|
||||
function formatImage (elem, walk, builder, formatOptions) {
|
||||
const attribs = elem.attribs || {};
|
||||
const alt = (attribs.alt)
|
||||
- ? he.decode(attribs.alt, builder.options.decodeOptions)
|
||||
+ ? decode(attribs.alt, builder.options.decodeOptions)
|
||||
: '';
|
||||
const src = (!attribs.src)
|
||||
? ''
|
||||
@@ -176,7 +176,7 @@ function formatAnchor (elem, walk, builder, formatOptions) {
|
||||
href = (formatOptions.baseUrl && href[0] === '/')
|
||||
? formatOptions.baseUrl + href
|
||||
: href;
|
||||
- return he.decode(href, builder.options.decodeOptions);
|
||||
+ return decode(href, builder.options.decodeOptions);
|
||||
}
|
||||
const href = getHref();
|
||||
if (!href) {
|
||||
diff --git a/node_modules/html-to-text/lib/html-to-text.js b/node_modules/html-to-text/lib/html-to-text.js
|
||||
index 9ebda73..8c5345f 100644
|
||||
--- a/node_modules/html-to-text/lib/html-to-text.js
|
||||
+++ b/node_modules/html-to-text/lib/html-to-text.js
|
||||
@@ -1,6 +1,6 @@
|
||||
const { hp2Builder } = require('@selderee/plugin-htmlparser2');
|
||||
const merge = require('deepmerge');
|
||||
-const he = require('he');
|
||||
+const {decode, EntityLevel} = require("entities");
|
||||
const htmlparser = require('htmlparser2');
|
||||
const selderee = require('selderee');
|
||||
|
||||
@@ -27,8 +27,7 @@ const DEFAULT_OPTIONS = {
|
||||
returnDomByDefault: true
|
||||
},
|
||||
decodeOptions: {
|
||||
- isAttributeValue: false,
|
||||
- strict: false
|
||||
+ level:EntityLevel.HTML
|
||||
},
|
||||
formatters: {},
|
||||
limits: {
|
||||
@@ -377,7 +376,7 @@ function recursiveWalk (walk, dom, builder) {
|
||||
for (const elem of dom) {
|
||||
switch (elem.type) {
|
||||
case 'text': {
|
||||
- builder.addInline(he.decode(elem.data, options.decodeOptions));
|
||||
+ builder.addInline(decode(elem.data, options.decodeOptions));
|
||||
break;
|
||||
}
|
||||
case 'tag': {
|
||||
89
apps/mobile/patches/leac+0.6.0.patch
Normal file
89
apps/mobile/patches/leac+0.6.0.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
diff --git a/node_modules/leac/lib/leac.cjs b/node_modules/leac/lib/leac.cjs
|
||||
index 13123da..9d490e2 100644
|
||||
--- a/node_modules/leac/lib/leac.cjs
|
||||
+++ b/node_modules/leac/lib/leac.cjs
|
||||
@@ -1 +1,83 @@
|
||||
-"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e=/\n/g;function t(t){const o=[...t.matchAll(e)].map((e=>e.index||0));o.unshift(-1);const s=n(o,0,o.length);return e=>r(s,e)}function n(e,t,r){if(r-t==1)return{offset:e[t],index:t+1};const o=Math.ceil((t+r)/2),s=n(e,t,o),l=n(e,o,r);return{offset:s.offset,low:s,high:l}}function r(e,t){return function(e){return Object.prototype.hasOwnProperty.call(e,"index")}(e)?{line:e.index,column:t-e.offset}:r(e.high.offset<t?e.high:e.low,t)}function o(e,t){return{...e,regex:s(e,t)}}function s(e,t){if(0===e.name.length)throw new Error(`Rule #${t} has empty name, which is not allowed.`);if(function(e){return Object.prototype.hasOwnProperty.call(e,"regex")}(e))return function(e){if(e.global)throw new Error(`Regular expression /${e.source}/${e.flags} contains the global flag, which is not allowed.`);return e.sticky?e:new RegExp(e.source,e.flags+"y")}(e.regex);if(function(e){return Object.prototype.hasOwnProperty.call(e,"str")}(e)){if(0===e.str.length)throw new Error(`Rule #${t} ("${e.name}") has empty "str" property, which is not allowed.`);return new RegExp(l(e.str),"y")}return new RegExp(l(e.name),"y")}function l(e){return e.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g,"\\$&")}exports.createLexer=function(e,n="",r={}){const s="string"!=typeof n?n:r,l="string"==typeof n?n:"",c=e.map(o),i=!!s.lineNumbers;return function(e,n=0){const r=i?t(e):()=>({line:0,column:0});let o=n;const s=[];e:for(;o<e.length;){let t=!1;for(const n of c){n.regex.lastIndex=o;const c=n.regex.exec(e);if(c&&c[0].length>0){if(!n.discard){const e=r(o),t="string"==typeof n.replace?c[0].replace(new RegExp(n.regex.source,n.regex.flags),n.replace):c[0];s.push({state:l,name:n.name,text:t,offset:o,len:c[0].length,line:e.line,column:e.column})}if(o=n.regex.lastIndex,t=!0,n.push){const t=n.push(e,o);s.push(...t.tokens),o=t.offset}if(n.pop)break e;break}}if(!t)break}return{tokens:s,offset:o,complete:e.length<=o}}};
|
||||
+"use strict";
|
||||
+Object.defineProperty(exports, "__esModule", { value: !0 });
|
||||
+const e = /\n/g;
|
||||
+function t(t) {
|
||||
+ const o = [...t.matchAll(e)].map((e) => e.index || 0);
|
||||
+ o.unshift(-1);
|
||||
+ const s = n(o, 0, o.length);
|
||||
+ return (e) => r(s, e);
|
||||
+}
|
||||
+function n(e, t, r) {
|
||||
+ if (r - t == 1) return { offset: e[t], index: t + 1 };
|
||||
+ const o = Math.ceil((t + r) / 2),
|
||||
+ s = n(e, t, o),
|
||||
+ l = n(e, o, r);
|
||||
+ return { offset: s.offset, low: s, high: l };
|
||||
+}
|
||||
+function r(e, t) {
|
||||
+ return (function (e) {
|
||||
+ return Object.prototype.hasOwnProperty.call(e, "index");
|
||||
+ })(e)
|
||||
+ ? { line: e.index, column: t - e.offset }
|
||||
+ : r(e.high.offset < t ? e.high : e.low, t);
|
||||
+}
|
||||
+function _o(e, t) {
|
||||
+ return { ...e, regex: s(e, t) };
|
||||
+}
|
||||
+function s(e, t) {
|
||||
+ if (0 === e.name.length) throw new Error(`Rule #${t} has empty name, which is not allowed.`);
|
||||
+ if (
|
||||
+ (function (e) {
|
||||
+ return Object.prototype.hasOwnProperty.call(e, "regex");
|
||||
+ })(e)
|
||||
+ )
|
||||
+ return (function (e) {
|
||||
+ if (e.global) throw new Error(`Regular expression /${e.source}/${e.flags} contains the global flag, which is not allowed.`);
|
||||
+ return e.sticky ? e : new RegExp(e.source, e.flags + "y");
|
||||
+ })(e.regex);
|
||||
+ if (
|
||||
+ (function (e) {
|
||||
+ return Object.prototype.hasOwnProperty.call(e, "str");
|
||||
+ })(e)
|
||||
+ ) {
|
||||
+ if (0 === e.str.length) throw new Error(`Rule #${t} ("${e.name}") has empty "str" property, which is not allowed.`);
|
||||
+ return new RegExp(l(e.str), "y");
|
||||
+ }
|
||||
+ return new RegExp(l(e.name), "y");
|
||||
+}
|
||||
+function l(e) {
|
||||
+ return e.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g, "\\$&");
|
||||
+}
|
||||
+exports.createLexer = function (_e, n = "", r = {}) {
|
||||
+ const s = "string" != typeof n ? n : r,
|
||||
+ l = "string" == typeof n ? n : "",
|
||||
+ i = !!s.lineNumbers;
|
||||
+ return function (e, n = 0) {
|
||||
+ const r = i ? t(e) : () => ({ line: 0, column: 0 });
|
||||
+ let o = n;
|
||||
+ const s = [];
|
||||
+ e: for (; o < e.length; ) {
|
||||
+ let t = !1;
|
||||
+ let z = _e.map(_o);
|
||||
+ for (const n of z) {
|
||||
+ n.regex.lastIndex = o;
|
||||
+ const c = n.regex.exec(e);
|
||||
+ if (c && c[0].length > 0) {
|
||||
+ if (!n.discard) {
|
||||
+ const e = r(o),
|
||||
+ t = "string" == typeof n.replace ? c[0].replace(new RegExp(n.regex.source, n.regex.flags), n.replace) : c[0];
|
||||
+ s.push({ state: l, name: n.name, text: t, offset: o, len: c[0].length, line: e.line, column: e.column });
|
||||
+ }
|
||||
+ if (((o = n.regex.lastIndex), (t = !0), n.push)) {
|
||||
+ const t = n.push(e, o);
|
||||
+ s.push(...t.tokens), (o = t.offset);
|
||||
+ }
|
||||
+ if (n.pop) break e;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (!t) break;
|
||||
+ }
|
||||
+ return { tokens: s, offset: o, complete: true };
|
||||
+ };
|
||||
+};
|
||||
@@ -26,12 +26,12 @@ import {
|
||||
Keyboard,
|
||||
Platform,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
useWindowDimensions,
|
||||
View,
|
||||
ScrollView
|
||||
useWindowDimensions
|
||||
} from "react-native";
|
||||
import {
|
||||
SafeAreaProvider,
|
||||
@@ -45,10 +45,9 @@ import Storage from "../app/common/database/storage";
|
||||
import { eSendEvent } from "../app/services/event-manager";
|
||||
import { getElevation } from "../app/utils";
|
||||
import { eOnLoadNote } from "../app/utils/events";
|
||||
import { sleep } from "../app/utils/time";
|
||||
import { Editor } from "./editor";
|
||||
import { Search } from "./search";
|
||||
import { initDatabase, useShareStore } from "./store";
|
||||
import { Editor } from "./editor";
|
||||
const getLinkPreview = (url) => {
|
||||
return getPreviewData(url, 5000);
|
||||
};
|
||||
@@ -315,7 +314,6 @@ const ShareView = ({ quicknote = false }) => {
|
||||
const onPress = async () => {
|
||||
setLoading(true);
|
||||
await initDatabase();
|
||||
await sleep(1500);
|
||||
if (!noteContent.current) return;
|
||||
if (appendNote && !db.notes.note(appendNote.id)) {
|
||||
useShareStore.getState().setAppendNote(null);
|
||||
@@ -358,6 +356,7 @@ const ShareView = ({ quicknote = false }) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
await db.sync(false, false);
|
||||
await Storage.write("notesAddedFromIntent", "added");
|
||||
close();
|
||||
setLoading(false);
|
||||
|
||||
@@ -29,10 +29,9 @@ import { db } from "../app/common/database";
|
||||
|
||||
export async function initDatabase() {
|
||||
if (!db.isInitialized) {
|
||||
// Only load collections in database.
|
||||
await db.initCollections();
|
||||
await db.notes.init();
|
||||
await db.init();
|
||||
}
|
||||
await db.notes.init();
|
||||
}
|
||||
|
||||
const StorageKeys = {
|
||||
|
||||
4
apps/web/desktop/package-lock.json
generated
4
apps/web/desktop/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"dependencies": {
|
||||
"diary": "^0.3.1",
|
||||
"electron-updater": "^5.3.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./build/electron.js",
|
||||
|
||||
4
apps/web/package-lock.json
generated
4
apps/web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@aws-sdk/util-base64-browser": "^3.208.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"description": "Your private note taking space",
|
||||
"version": "2.4.7",
|
||||
"version": "2.4.8",
|
||||
"private": true,
|
||||
"main": "./src/app.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
|
||||
@@ -138,11 +138,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
@keyframes fadeUp {
|
||||
0% {
|
||||
transform: translateY(500px);
|
||||
|
||||
@@ -90,7 +90,13 @@ const features: Record<FeatureKeys, Feature> = {
|
||||
}
|
||||
]
|
||||
: isDesktop()
|
||||
? []
|
||||
? [
|
||||
{
|
||||
title: "Default font size & font family",
|
||||
subtitle:
|
||||
"You can now change the default font family and size used by the editor across all your older & newer notes. Go into Settings > Editor settings to change these settings."
|
||||
}
|
||||
]
|
||||
: [],
|
||||
cta: {
|
||||
title: "Got it",
|
||||
|
||||
@@ -21,14 +21,19 @@ import { Button, Flex } from "@theme-ui/components";
|
||||
import { useMenuTrigger } from "../../hooks/use-menu";
|
||||
import { ChevronDown } from "../icons";
|
||||
|
||||
export default function DropdownButton({ title, options }) {
|
||||
export default function DropdownButton(props) {
|
||||
const { openMenu } = useMenuTrigger();
|
||||
const { options, title, sx, buttonStyle, chevronStyle } = props;
|
||||
|
||||
if (!options || !options.length) return null;
|
||||
return (
|
||||
<Flex>
|
||||
<Flex sx={sx}>
|
||||
<Button
|
||||
sx={{ borderTopRightRadius: 0, borderBottomRightRadius: 0 }}
|
||||
sx={{
|
||||
borderTopRightRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
...buttonStyle
|
||||
}}
|
||||
onClick={options[0].onClick}
|
||||
>
|
||||
{options[0].title()}
|
||||
@@ -38,7 +43,8 @@ export default function DropdownButton({ title, options }) {
|
||||
px={1}
|
||||
sx={{
|
||||
borderBottomLeftRadius: 0,
|
||||
borderTopLeftRadius: 0
|
||||
borderTopLeftRadius: 0,
|
||||
...chevronStyle
|
||||
}}
|
||||
onClick={() => openMenu(options.slice(1), { title })}
|
||||
>
|
||||
|
||||
@@ -24,17 +24,26 @@ import BaseStore from "../../stores";
|
||||
import { UseBoundStore } from "zustand";
|
||||
import shallow from "zustand/shallow";
|
||||
import type { ToolbarDefinition } from "@notesnook/editor";
|
||||
import Config from "../../utils/config";
|
||||
|
||||
type EditorConfig = { fontFamily: string; fontSize: number };
|
||||
type EditorSubState = {
|
||||
editor?: IEditor;
|
||||
canUndo?: boolean;
|
||||
canRedo?: boolean;
|
||||
searching?: boolean;
|
||||
toolbarConfig?: ToolbarDefinition;
|
||||
editorConfig: EditorConfig;
|
||||
statistics?: NoteStatistics;
|
||||
};
|
||||
|
||||
class EditorContext extends BaseStore {
|
||||
subState: EditorSubState = {};
|
||||
subState: EditorSubState = {
|
||||
editorConfig: Config.get("editorConfig", {
|
||||
fontFamily: "sans-serif",
|
||||
fontSize: 16
|
||||
})
|
||||
};
|
||||
|
||||
configure = (
|
||||
partial:
|
||||
@@ -116,3 +125,27 @@ export function useNoteStatistics(): NoteStatistics {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function useEditorConfig() {
|
||||
const editorConfig = useEditorContext((store) => store.subState.editorConfig);
|
||||
const configure = useEditorContext((store) => store.configure);
|
||||
const setEditorConfig = useCallback(
|
||||
(config: Partial<EditorConfig>) => {
|
||||
if (editorConfig)
|
||||
Config.set("editorConfig", {
|
||||
...editorConfig,
|
||||
...config
|
||||
});
|
||||
|
||||
configure({
|
||||
editorConfig: {
|
||||
...editorConfig,
|
||||
...config
|
||||
}
|
||||
});
|
||||
},
|
||||
[editorConfig, configure]
|
||||
);
|
||||
|
||||
return { editorConfig, setEditorConfig };
|
||||
}
|
||||
|
||||
@@ -33,9 +33,10 @@ import {
|
||||
usePermissionHandler,
|
||||
getHTMLFromFragment,
|
||||
Fragment,
|
||||
type DownloadOptions,
|
||||
getTotalWords,
|
||||
countWords,
|
||||
type DownloadOptions
|
||||
getFontById
|
||||
} from "@notesnook/editor";
|
||||
import { Box, Flex } from "@theme-ui/components";
|
||||
import { PropsWithChildren, useEffect, useRef, useState } from "react";
|
||||
@@ -45,7 +46,8 @@ import {
|
||||
useConfigureEditor,
|
||||
useSearch,
|
||||
useToolbarConfig,
|
||||
configureEditor
|
||||
configureEditor,
|
||||
useEditorConfig
|
||||
} from "./context";
|
||||
import { createPortal } from "react-dom";
|
||||
import { getCurrentPreset } from "../../common/toolbar-config";
|
||||
@@ -71,6 +73,8 @@ type TipTapProps = {
|
||||
theme: Theme;
|
||||
isMobile?: boolean;
|
||||
downloadOptions?: DownloadOptions;
|
||||
fontSize: number;
|
||||
fontFamily: string;
|
||||
};
|
||||
|
||||
const SAVE_INTERVAL = process.env.REACT_APP_TEST ? 100 : 300;
|
||||
@@ -115,7 +119,9 @@ function TipTap(props: TipTapProps) {
|
||||
nonce,
|
||||
theme,
|
||||
isMobile,
|
||||
downloadOptions
|
||||
downloadOptions,
|
||||
fontSize,
|
||||
fontFamily
|
||||
} = props;
|
||||
|
||||
const isUserPremium = useIsUserPremium();
|
||||
@@ -301,7 +307,6 @@ function TipTap(props: TipTapProps) {
|
||||
}, [editor, editorContainer]);
|
||||
|
||||
if (!toolbarContainerId) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Portal containerId={toolbarContainerId}>
|
||||
@@ -310,16 +315,24 @@ function TipTap(props: TipTapProps) {
|
||||
theme={theme}
|
||||
location={isMobile ? "bottom" : "top"}
|
||||
tools={toolbarConfig}
|
||||
defaultFontFamily={fontFamily}
|
||||
defaultFontSize={fontSize}
|
||||
/>
|
||||
</Portal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function TiptapWrapper(props: Omit<TipTapProps, "editorContainer" | "theme">) {
|
||||
function TiptapWrapper(
|
||||
props: Omit<
|
||||
TipTapProps,
|
||||
"editorContainer" | "theme" | "fontSize" | "fontFamily"
|
||||
>
|
||||
) {
|
||||
const theme = useTheme() as Theme;
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const editorContainerRef = useRef<HTMLDivElement>(null);
|
||||
const { editorConfig } = useEditorConfig();
|
||||
useEffect(() => {
|
||||
setIsReady(true);
|
||||
}, []);
|
||||
@@ -332,6 +345,8 @@ function TiptapWrapper(props: Omit<TipTapProps, "editorContainer" | "theme">) {
|
||||
{...props}
|
||||
editorContainer={editorContainerRef.current}
|
||||
theme={theme}
|
||||
fontFamily={editorConfig.fontFamily}
|
||||
fontSize={editorConfig.fontSize}
|
||||
/>
|
||||
) : null}
|
||||
<Box
|
||||
@@ -341,7 +356,9 @@ function TiptapWrapper(props: Omit<TipTapProps, "editorContainer" | "theme">) {
|
||||
flex: 1,
|
||||
cursor: "text",
|
||||
color: theme.colors.text, // TODO!
|
||||
paddingBottom: 150
|
||||
paddingBottom: 150,
|
||||
fontSize: editorConfig.fontSize,
|
||||
fontFamily: getFontById(editorConfig.fontFamily)?.font
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
@@ -23,6 +23,8 @@ import { useStore, store } from "../../stores/editor-store";
|
||||
import { debounceWithId } from "../../utils/debounce";
|
||||
import useMobile from "../../hooks/use-mobile";
|
||||
import useTablet from "../../hooks/use-tablet";
|
||||
import { useEditorConfig } from "./context";
|
||||
import { getFontById } from "@notesnook/editor";
|
||||
|
||||
type TitleBoxProps = {
|
||||
readonly: boolean;
|
||||
@@ -35,6 +37,7 @@ function TitleBox(props: TitleBoxProps) {
|
||||
const id = useStore((store) => store.session.id);
|
||||
const isMobile = useMobile();
|
||||
const isTablet = useTablet();
|
||||
const { editorConfig } = useEditorConfig();
|
||||
|
||||
const MAX_FONT_SIZE = useMemo(() => {
|
||||
return isMobile || isTablet ? 1.625 : 2.625;
|
||||
@@ -66,7 +69,7 @@ function TitleBox(props: TitleBoxProps) {
|
||||
readOnly={readonly}
|
||||
sx={{
|
||||
p: 0,
|
||||
fontFamily: "heading",
|
||||
fontFamily: getFontById(editorConfig.fontFamily)?.font || "heading",
|
||||
fontSize: ["1.625em", "1.625em", "2.625em"],
|
||||
fontWeight: "heading",
|
||||
width: "100%"
|
||||
|
||||
@@ -92,6 +92,7 @@ function Field(props) {
|
||||
sx={{
|
||||
fontSize: "subtitle",
|
||||
fontWeight: "bold",
|
||||
fontFamily: "body",
|
||||
color: "icon",
|
||||
flexDirection: "column",
|
||||
...styles.label
|
||||
|
||||
@@ -1019,13 +1019,14 @@ function openURL(url: string, force?: boolean) {
|
||||
|
||||
function maskEmail(email: string) {
|
||||
if (!email) return "";
|
||||
const [username, domain] = email.split("@");
|
||||
const maskChars = "*".repeat(
|
||||
username.substring(2, username.length - 2).length
|
||||
);
|
||||
return `${username.substring(0, 2)}${maskChars}${username.substring(
|
||||
username.length - 2
|
||||
)}@${domain}`;
|
||||
const [username, provider] = email.split("@");
|
||||
if (username.length === 1) return `****@${provider}`;
|
||||
return email.replace(/(.{1})(.*)(?=@)/, function (gp1, gp2, gp3) {
|
||||
for (let i = 0; i < gp3.length; i++) {
|
||||
gp2 += "*";
|
||||
}
|
||||
return gp2;
|
||||
});
|
||||
}
|
||||
|
||||
function isSessionExpired() {
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Button, Flex, Text } from "@theme-ui/components";
|
||||
import { Button, Flex, Input, Text } from "@theme-ui/components";
|
||||
import * as Icon from "../components/icons";
|
||||
import { useStore as useUserStore } from "../stores/user-store";
|
||||
import { useStore as useNoteStore } from "../stores/note-store";
|
||||
@@ -81,6 +81,8 @@ import { useTelemetry } from "../hooks/use-telemetry";
|
||||
import useSpellChecker from "../hooks/use-spell-checker";
|
||||
import useDesktopIntegration from "../hooks/use-desktop-integration";
|
||||
import { writeText } from "clipboard-polyfill";
|
||||
import { useEditorConfig } from "../components/editor/context";
|
||||
import { getFonts } from "@notesnook/editor";
|
||||
|
||||
function subscriptionStatusToString(user) {
|
||||
const status = user?.subscription?.type;
|
||||
@@ -219,6 +221,7 @@ function Settings() {
|
||||
"corsProxy",
|
||||
"https://cors.notesnook.com"
|
||||
);
|
||||
const { editorConfig, setEditorConfig } = useEditorConfig();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@@ -622,6 +625,51 @@ function Settings() {
|
||||
/>
|
||||
{groups.editor && (
|
||||
<>
|
||||
<OptionsItem
|
||||
title={"Default font family"}
|
||||
tip={"Set default font family"}
|
||||
selectedOption={editorConfig.fontFamily}
|
||||
options={getFonts().map((font) => ({
|
||||
value: font.id,
|
||||
title: font.title
|
||||
}))}
|
||||
onSelectionChanged={(option) => {
|
||||
setEditorConfig({ fontFamily: option.value });
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
py={2}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
borderBottom: "1px solid",
|
||||
borderBottomColor: "border",
|
||||
":hover": { borderBottomColor: "primary" },
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Tip
|
||||
text="Default font size"
|
||||
tip="Set default font size"
|
||||
sx={{ flex: 1 }}
|
||||
/>
|
||||
<Input
|
||||
type="number"
|
||||
min={8}
|
||||
sx={{ width: 70 }}
|
||||
defaultValue={editorConfig.fontSize}
|
||||
onChange={(e) => {
|
||||
setEditorConfig({ fontSize: e.currentTarget.valueAsNumber });
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
{/* <Counter
|
||||
value={editorConfig.fontSize}
|
||||
onDecrease={() => {}}
|
||||
onIncrease={() => {}}
|
||||
title="Set default font size"
|
||||
onReset={() => setEditorConfig({ fontFamily: "16px" })}
|
||||
/> */}
|
||||
{/* <DefaultFont /> */}
|
||||
<Toggle
|
||||
title="Use double spaced lines"
|
||||
onTip="New lines will be double spaced (old ones won't be affected)."
|
||||
|
||||
@@ -29,13 +29,13 @@ export default class Subscriptions {
|
||||
}
|
||||
|
||||
async cancel() {
|
||||
const token = this._tokenManager.getAccessToken();
|
||||
const token = await this._tokenManager.getAccessToken();
|
||||
if (!token) return;
|
||||
await http.delete(`${hosts.SUBSCRIPTIONS_HOST}/subscriptions`, token);
|
||||
}
|
||||
|
||||
async updateUrl() {
|
||||
const token = this._tokenManager.getAccessToken();
|
||||
const token = await this._tokenManager.getAccessToken();
|
||||
if (!token) return;
|
||||
return await http.get(
|
||||
`${hosts.SUBSCRIPTIONS_HOST}/subscriptions/update_url`,
|
||||
|
||||
@@ -50,7 +50,8 @@ export class Tiptap {
|
||||
preserveNewlines: true,
|
||||
selectors: [
|
||||
{ selector: "table", format: "dataTable" },
|
||||
{ selector: "ul.checklist", format: "taskList" }
|
||||
{ selector: "ul.checklist", format: "taskList" },
|
||||
{ selector: "p", format: "paragraph" }
|
||||
],
|
||||
formatters: {
|
||||
taskList: (elem, walk, builder, formatOptions) => {
|
||||
|
||||
@@ -24,6 +24,7 @@ import { getContentFromData } from "../content-types";
|
||||
import { CHECK_IDS, checkIsUserPremium } from "../common";
|
||||
import { addItem, deleteItem } from "../utils/array";
|
||||
import { formatDate } from "../utils/date";
|
||||
import qclone from "qclone";
|
||||
|
||||
export default class Note {
|
||||
/**
|
||||
@@ -135,12 +136,14 @@ export default class Note {
|
||||
async duplicate() {
|
||||
const content = await this._db.content.raw(this._note.contentId);
|
||||
return await this._db.notes.add({
|
||||
...this._note,
|
||||
...qclone(this._note),
|
||||
id: undefined,
|
||||
content: {
|
||||
type: content.type,
|
||||
data: content.data
|
||||
},
|
||||
content: content
|
||||
? {
|
||||
type: content.type,
|
||||
data: content.data
|
||||
}
|
||||
: undefined,
|
||||
readonly: false,
|
||||
favorite: false,
|
||||
pinned: false,
|
||||
|
||||
9
packages/core/package-lock.json
generated
9
packages/core/package-lock.json
generated
@@ -15261,8 +15261,7 @@
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
|
||||
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"jest-regex-util": {
|
||||
"version": "28.0.2",
|
||||
@@ -15936,8 +15935,7 @@
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -17197,8 +17195,7 @@
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@@ -33,16 +33,6 @@
|
||||
color: var(--nn_placeholder) !important;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "Open Sans";
|
||||
color: var(--nn_heading);
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import {
|
||||
Editor,
|
||||
getFontById,
|
||||
PortalProvider,
|
||||
Toolbar,
|
||||
usePermissionHandler,
|
||||
@@ -227,6 +228,7 @@ const Tiptap = ({
|
||||
readonly={settings.readonly}
|
||||
controller={controllerRef}
|
||||
title={controller.title}
|
||||
fontFamily={settings.fontFamily}
|
||||
/>
|
||||
<StatusBar container={containerRef} />
|
||||
</>
|
||||
@@ -234,6 +236,8 @@ const Tiptap = ({
|
||||
|
||||
<ContentDiv
|
||||
padding={settings.doubleSpacedLines ? 0 : 6}
|
||||
fontSize={settings.fontSize}
|
||||
fontFamily={settings.fontFamily}
|
||||
ref={contentRef}
|
||||
/>
|
||||
|
||||
@@ -254,6 +258,8 @@ const Tiptap = ({
|
||||
editor={_editor}
|
||||
location="bottom"
|
||||
tools={[...settings.tools]}
|
||||
defaultFontFamily={settings.fontFamily}
|
||||
defaultFontSize={settings.fontSize}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -262,7 +268,10 @@ const Tiptap = ({
|
||||
};
|
||||
|
||||
const ContentDiv = memo(
|
||||
forwardRef<HTMLDivElement, { padding: number }>((props, ref) => {
|
||||
forwardRef<
|
||||
HTMLDivElement,
|
||||
{ padding: number; fontSize: number; fontFamily: string }
|
||||
>((props, ref) => {
|
||||
const theme = useEditorThemeStore((state) => state.colors);
|
||||
return (
|
||||
<div
|
||||
@@ -272,12 +281,18 @@ const ContentDiv = memo(
|
||||
paddingTop: props.padding,
|
||||
color: theme.pri,
|
||||
marginTop: -12,
|
||||
caretColor: theme.accent
|
||||
caretColor: theme.accent,
|
||||
fontSize: props.fontSize,
|
||||
fontFamily: getFontById(props.fontFamily)?.font
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
() => true
|
||||
(prev, next) => {
|
||||
if (prev.fontSize !== next.fontSize || prev.fontFamily !== next.fontFamily)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
const modifyToolbarTheme = (toolbarTheme: Theme) => {
|
||||
|
||||
@@ -17,20 +17,22 @@ 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 React from "react";
|
||||
import { RefObject, useEffect, useRef } from "react";
|
||||
import { getFontById } from "@notesnook/editor";
|
||||
import React, { RefObject, useEffect, useRef } from "react";
|
||||
import { EditorController } from "../hooks/useEditorController";
|
||||
import styles from "./styles.module.css";
|
||||
function Title({
|
||||
controller,
|
||||
title,
|
||||
titlePlaceholder,
|
||||
readonly
|
||||
readonly,
|
||||
fontFamily
|
||||
}: {
|
||||
controller: RefObject<EditorController>;
|
||||
title: string;
|
||||
titlePlaceholder: string;
|
||||
readonly: boolean;
|
||||
fontFamily: string;
|
||||
}) {
|
||||
const titleRef = useRef<HTMLInputElement>(null);
|
||||
const emitUpdate = useRef(true);
|
||||
@@ -59,7 +61,7 @@ function Title({
|
||||
paddingRight: 12,
|
||||
paddingLeft: 12,
|
||||
fontWeight: 600,
|
||||
fontFamily: "Open Sans",
|
||||
fontFamily: getFontById(fontFamily)?.font || "Open Sans",
|
||||
backgroundColor: "transparent",
|
||||
color: "var(--nn_heading)",
|
||||
caretColor: "var(--nn_accent)",
|
||||
@@ -76,8 +78,13 @@ function Title({
|
||||
}
|
||||
|
||||
export default React.memo(Title, (prev, next) => {
|
||||
if (prev.title !== next.title) return false;
|
||||
if (prev.titlePlaceholder !== next.titlePlaceholder) return false;
|
||||
if (prev.readonly !== next.readonly) return false;
|
||||
if (
|
||||
prev.title !== next.title ||
|
||||
prev.titlePlaceholder !== next.titlePlaceholder ||
|
||||
prev.readonly !== next.readonly ||
|
||||
prev.fontFamily !== next.fontFamily
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -65,6 +65,7 @@ export type EditorController = {
|
||||
titlePlaceholder: string;
|
||||
openLink: (url: string) => boolean;
|
||||
setTitlePlaceholder: React.Dispatch<React.SetStateAction<string>>;
|
||||
countWords: (ms: number) => void;
|
||||
};
|
||||
|
||||
export function useEditorController(update: () => void): EditorController {
|
||||
@@ -84,21 +85,34 @@ export function useEditorController(update: () => void): EditorController {
|
||||
post(EventTypes.title, title);
|
||||
}, []);
|
||||
|
||||
const contentChange = useCallback((editor: Editor) => {
|
||||
const currentSessionId = globalThis.sessionId;
|
||||
post(EventTypes.contentchange);
|
||||
if (!editor) return;
|
||||
if (typeof timers.current.change === "number") {
|
||||
clearTimeout(timers.current?.change);
|
||||
}
|
||||
timers.current.change = setTimeout(() => {
|
||||
htmlContentRef.current = editor.getHTML();
|
||||
post(EventTypes.content, htmlContentRef.current, currentSessionId);
|
||||
}, 300);
|
||||
|
||||
countWords(5000);
|
||||
const countWords = useCallback((ms = 300) => {
|
||||
if (typeof timers.current.wordCounter === "number")
|
||||
clearTimeout(timers.current.wordCounter);
|
||||
timers.current.wordCounter = setTimeout(() => {
|
||||
console.time("wordCounter");
|
||||
statusBar?.current?.updateWords();
|
||||
console.timeEnd("wordCounter");
|
||||
}, ms);
|
||||
}, []);
|
||||
|
||||
const contentChange = useCallback(
|
||||
(editor: Editor) => {
|
||||
const currentSessionId = globalThis.sessionId;
|
||||
post(EventTypes.contentchange);
|
||||
if (!editor) return;
|
||||
if (typeof timers.current.change === "number") {
|
||||
clearTimeout(timers.current?.change);
|
||||
}
|
||||
timers.current.change = setTimeout(() => {
|
||||
htmlContentRef.current = editor.getHTML();
|
||||
post(EventTypes.content, htmlContentRef.current, currentSessionId);
|
||||
}, 300);
|
||||
|
||||
countWords(5000);
|
||||
},
|
||||
[countWords]
|
||||
);
|
||||
|
||||
const scroll = useCallback(
|
||||
(_event: React.UIEvent<HTMLDivElement, UIEvent>) => {},
|
||||
[]
|
||||
@@ -152,19 +166,9 @@ export function useEditorController(update: () => void): EditorController {
|
||||
}
|
||||
post(type); // Notify that message was delivered successfully.
|
||||
},
|
||||
[update]
|
||||
[update, countWords]
|
||||
);
|
||||
|
||||
function countWords(ms = 300) {
|
||||
if (typeof timers.current.wordCounter === "number")
|
||||
clearTimeout(timers.current.wordCounter);
|
||||
timers.current.wordCounter = setTimeout(() => {
|
||||
console.time("wordCounter");
|
||||
statusBar?.current?.updateWords();
|
||||
console.timeEnd("wordCounter");
|
||||
}, ms);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isReactNative()) return; // Subscribe only in react native webview.
|
||||
const isSafari = navigator.vendor.match(/apple/i);
|
||||
@@ -208,6 +212,7 @@ export function useEditorController(update: () => void): EditorController {
|
||||
previewAttachment,
|
||||
content: htmlContentRef,
|
||||
openLink,
|
||||
onUpdate: onUpdate
|
||||
onUpdate: onUpdate,
|
||||
countWords
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ const initialState = {
|
||||
noToolbar: globalThis.noToolbar,
|
||||
noHeader: globalThis.noHeader,
|
||||
readonly: globalThis.readonly,
|
||||
doubleSpacedLines: true
|
||||
doubleSpacedLines: true,
|
||||
fontFamily: "sans-serif",
|
||||
fontSize: "16px"
|
||||
};
|
||||
|
||||
global.settingsController = {
|
||||
|
||||
@@ -39,6 +39,8 @@ export type Settings = {
|
||||
noHeader?: boolean;
|
||||
doubleSpacedLines?: boolean;
|
||||
corsProxy: string;
|
||||
fontSize: number;
|
||||
fontFamily: string;
|
||||
};
|
||||
|
||||
/* eslint-disable no-var */
|
||||
|
||||
@@ -17,8 +17,8 @@ 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 "@tiptap/extension-text-style";
|
||||
import { getFontConfig } from "@notesnook/theme/dist/theme/font";
|
||||
import { Extension } from "@tiptap/core";
|
||||
import { getFontById } from "../../utils/font";
|
||||
|
||||
export type FontFamilyOptions = {
|
||||
types: string[];
|
||||
@@ -39,12 +39,6 @@ declare module "@tiptap/core" {
|
||||
}
|
||||
}
|
||||
|
||||
const FONTS: Record<string, string> = {
|
||||
monospace: getFontConfig().fonts.monospace,
|
||||
"sans-serif": getFontConfig().fonts.body,
|
||||
serif: `Noto Serif, Times New Roman, serif`
|
||||
};
|
||||
|
||||
export const FontFamily = Extension.create<FontFamilyOptions>({
|
||||
name: "fontFamily",
|
||||
|
||||
@@ -70,7 +64,8 @@ export const FontFamily = Extension.create<FontFamilyOptions>({
|
||||
|
||||
const realFontFamily =
|
||||
attributes["data-font-family"] || attributes.fontFamily;
|
||||
const font = FONTS[realFontFamily] || attributes.fontFamily;
|
||||
const font =
|
||||
getFontById(realFontFamily)?.font || attributes.fontFamily;
|
||||
return {
|
||||
"data-font-family": realFontFamily,
|
||||
style: `font-family: ${font}`
|
||||
|
||||
@@ -22,7 +22,6 @@ import "@tiptap/extension-text-style";
|
||||
|
||||
type FontSizeOptions = {
|
||||
types: string[];
|
||||
defaultFontSize: number;
|
||||
};
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
@@ -44,8 +43,7 @@ export const FontSize = Extension.create<FontSizeOptions>({
|
||||
name: "fontSize",
|
||||
|
||||
defaultOptions: {
|
||||
types: ["textStyle"],
|
||||
defaultFontSize: 16
|
||||
types: ["textStyle"]
|
||||
},
|
||||
|
||||
addGlobalAttributes() {
|
||||
@@ -54,7 +52,6 @@ export const FontSize = Extension.create<FontSizeOptions>({
|
||||
types: this.options.types,
|
||||
attributes: {
|
||||
fontSize: {
|
||||
default: `${this.options.defaultFontSize}px`,
|
||||
parseHTML: (element) => element.style.fontSize,
|
||||
renderHTML: (attributes) => {
|
||||
if (!attributes.fontSize) {
|
||||
|
||||
@@ -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 { Flex, Text } from "@theme-ui/components";
|
||||
import { Box, Flex } from "@theme-ui/components";
|
||||
import { ReactNodeViewProps } from "../react";
|
||||
import { Icon } from "../../toolbar/components/icon";
|
||||
import { Icons } from "../../toolbar/icons";
|
||||
@@ -89,10 +89,10 @@ export function TaskItemComponent(
|
||||
".icon:hover path": {
|
||||
fill: "var(--checked) !important"
|
||||
},
|
||||
mt: "1px",
|
||||
mx: 1
|
||||
mx: 1,
|
||||
fontFamily: "inherit"
|
||||
}}
|
||||
size={isMobile ? 24 : 20}
|
||||
size={isMobile ? "2.46ch" : "2.22ch"}
|
||||
/>
|
||||
)}
|
||||
<Icon
|
||||
@@ -106,7 +106,6 @@ export function TaskItemComponent(
|
||||
borderRadius: "default",
|
||||
alignSelf: "start",
|
||||
p: "1px",
|
||||
mt: "2px",
|
||||
mr: 1,
|
||||
cursor: editor.isEditable ? "pointer" : "unset",
|
||||
":hover": {
|
||||
@@ -114,7 +113,8 @@ export function TaskItemComponent(
|
||||
},
|
||||
":hover .icon path": {
|
||||
fill: "var(--checked) !important"
|
||||
}
|
||||
},
|
||||
fontFamily: "inherit"
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
if (globalThis["keyboardShown"]) {
|
||||
@@ -129,11 +129,10 @@ export function TaskItemComponent(
|
||||
}
|
||||
}}
|
||||
color={checked ? "checked" : "icon"}
|
||||
size={isMobile ? 16 : 14}
|
||||
size={isMobile ? "1.66ch" : "1.46ch"}
|
||||
/>
|
||||
|
||||
<Text
|
||||
as="div"
|
||||
<Box
|
||||
ref={forwardRef}
|
||||
sx={{
|
||||
"> .taskitem-content-wrapper > p": {
|
||||
|
||||
@@ -76,7 +76,7 @@ export function TaskListComponent(
|
||||
sx={{
|
||||
position: "relative",
|
||||
bg: "bgSecondary",
|
||||
py: 1,
|
||||
py: "5px",
|
||||
borderRadius: "default",
|
||||
mb: 2,
|
||||
alignItems: "center",
|
||||
@@ -108,7 +108,8 @@ export function TaskListComponent(
|
||||
px: 2,
|
||||
zIndex: 1,
|
||||
color: "fontTertiary",
|
||||
fontSize: "title"
|
||||
fontSize: "inherit",
|
||||
fontFamily: "inherit"
|
||||
}}
|
||||
placeholder="Untitled"
|
||||
onChange={(e) => {
|
||||
@@ -168,15 +169,15 @@ export function TaskListComponent(
|
||||
mr: 2,
|
||||
color: "fontTertiary",
|
||||
flexShrink: 0,
|
||||
zIndex: 1
|
||||
zIndex: 1,
|
||||
fontFamily: "inherit"
|
||||
}}
|
||||
>
|
||||
{stats.checked}/{stats.total}
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
<Text
|
||||
as={"div"}
|
||||
<Box
|
||||
ref={forwardRef}
|
||||
dir={textDirection}
|
||||
sx={{
|
||||
|
||||
@@ -273,6 +273,7 @@ export * from "./extensions/react";
|
||||
export * from "./toolbar";
|
||||
export * from "./types";
|
||||
export * from "./utils/word-counter";
|
||||
export * from "./utils/font";
|
||||
export {
|
||||
useTiptap,
|
||||
Toolbar,
|
||||
|
||||
@@ -64,6 +64,7 @@ export function Dropdown(props: DropdownProps) {
|
||||
m: 0,
|
||||
bg: isPopupOpen ? "hover" : "transparent",
|
||||
mr: 1,
|
||||
flexShrink: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
":hover": { bg: "hover" },
|
||||
@@ -75,7 +76,9 @@ export function Dropdown(props: DropdownProps) {
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
>
|
||||
{typeof selectedItem === "string" ? (
|
||||
<Text sx={{ fontSize: "subBody", mr: 1, color: "text" }}>
|
||||
<Text
|
||||
sx={{ fontSize: "subBody", mr: 1, color: "text", flexShrink: 0 }}
|
||||
>
|
||||
{selectedItem}
|
||||
</Text>
|
||||
) : (
|
||||
|
||||
@@ -34,7 +34,7 @@ function isSchemeColor(
|
||||
type IconProps = {
|
||||
title?: string;
|
||||
path: string;
|
||||
size?: keyof Theme["iconSizes"] | number;
|
||||
size?: keyof Theme["iconSizes"] | number | string;
|
||||
color?: keyof SchemeColors | string;
|
||||
stroke?: string;
|
||||
rotate?: boolean;
|
||||
@@ -60,8 +60,10 @@ function MDIIconWrapper({
|
||||
title={title}
|
||||
path={path}
|
||||
size={
|
||||
typeof size === "string"
|
||||
? `${theme?.iconSizes[size] || 24}px`
|
||||
theme && typeof size === "string" && size in theme.iconSizes
|
||||
? `${(theme?.iconSizes as any)[size] || 24}px`
|
||||
: typeof size === "string"
|
||||
? size
|
||||
: `${size}px`
|
||||
}
|
||||
style={{
|
||||
|
||||
@@ -39,7 +39,8 @@ function _SplitButton(props: PropsWithChildren<SplitButtonProps>) {
|
||||
<Flex
|
||||
ref={ref}
|
||||
sx={{
|
||||
borderRadius: "default"
|
||||
borderRadius: "default",
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<ToolButton
|
||||
|
||||
@@ -39,6 +39,10 @@ interface ToolbarState {
|
||||
closePopup: (popupId: string) => void;
|
||||
closePopupGroup: (groupId: string, excluded: string[]) => void;
|
||||
closeAllPopups: () => void;
|
||||
fontFamily: string;
|
||||
setFontFamily: (fontFamily: string) => void;
|
||||
fontSize: number;
|
||||
setFontSize: (fontSize: number) => void;
|
||||
}
|
||||
|
||||
export const useToolbarStore = create<ToolbarState>((set, get) => ({
|
||||
@@ -92,6 +96,16 @@ export const useToolbarStore = create<ToolbarState>((set, get) => ({
|
||||
for (const key in state.openedPopups) {
|
||||
state.openedPopups[key] = undefined;
|
||||
}
|
||||
}),
|
||||
fontFamily: "sans-serif",
|
||||
setFontFamily: (fontFamily) =>
|
||||
set((state) => {
|
||||
state.fontFamily = fontFamily;
|
||||
}),
|
||||
fontSize: 16,
|
||||
setFontSize: (fontSize) =>
|
||||
set((state) => {
|
||||
state.fontSize = fontSize;
|
||||
})
|
||||
}));
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ type ToolbarProps = FlexProps & {
|
||||
editor: Editor | null;
|
||||
location: ToolbarLocation;
|
||||
tools?: ToolbarDefinition;
|
||||
defaultFontFamily: string;
|
||||
defaultFontSize: number;
|
||||
};
|
||||
|
||||
export function Toolbar(props: ToolbarProps) {
|
||||
@@ -49,10 +51,11 @@ export function Toolbar(props: ToolbarProps) {
|
||||
theme,
|
||||
location,
|
||||
tools = getDefaultPresets().default,
|
||||
defaultFontFamily,
|
||||
defaultFontSize,
|
||||
sx,
|
||||
...flexProps
|
||||
} = props;
|
||||
|
||||
const toolbarTools = useMemo(
|
||||
() => [...STATIC_TOOLBAR_GROUPS, ...tools],
|
||||
[tools]
|
||||
@@ -63,11 +66,23 @@ export function Toolbar(props: ToolbarProps) {
|
||||
const setToolbarLocation = useToolbarStore(
|
||||
(store) => store.setToolbarLocation
|
||||
);
|
||||
const setDefaultFontFamily = useToolbarStore((store) => store.setFontFamily);
|
||||
const setDefaultFontSize = useToolbarStore((store) => store.setFontSize);
|
||||
|
||||
useEffect(() => {
|
||||
setToolbarLocation(location);
|
||||
}, [location, setToolbarLocation]);
|
||||
|
||||
useEffect(() => {
|
||||
setDefaultFontFamily(defaultFontFamily);
|
||||
setDefaultFontSize(defaultFontSize);
|
||||
}, [
|
||||
defaultFontFamily,
|
||||
defaultFontSize,
|
||||
setDefaultFontFamily,
|
||||
setDefaultFontSize
|
||||
]);
|
||||
|
||||
if (!editor) return null;
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
|
||||
@@ -24,12 +24,16 @@ import { MenuItem } from "../../components/menu/types";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { Counter } from "../components/counter";
|
||||
import { useRefValue } from "../../hooks/use-ref-value";
|
||||
import { useToolbarStore } from "../stores/toolbar-store";
|
||||
import { getFontById, getFontIds, getFonts } from "../../utils/font";
|
||||
|
||||
export function FontSize(props: ToolProps) {
|
||||
const { editor } = props;
|
||||
const { fontSize: _fontSize } = editor.getAttributes("textStyle");
|
||||
const fontSize = _fontSize || "16px";
|
||||
const fontSizeAsNumber = useRefValue(parseInt(fontSize.replace("px", "")));
|
||||
const defaultFontSize = useToolbarStore((store) => store.fontSize);
|
||||
const { fontSize } = editor.getAttributes("textStyle");
|
||||
const fontSizeAsNumber = useRefValue(
|
||||
fontSize ? parseInt(fontSize.replace("px", "")) : defaultFontSize
|
||||
);
|
||||
|
||||
const decreaseFontSize = useCallback(() => {
|
||||
return Math.max(8, fontSizeAsNumber.current - 1);
|
||||
@@ -56,27 +60,26 @@ export function FontSize(props: ToolProps) {
|
||||
.setFontSize(`${increaseFontSize()}px`)
|
||||
.run();
|
||||
}}
|
||||
onReset={() => editor.current?.chain().focus().setFontSize("16px").run()}
|
||||
value={fontSize}
|
||||
onReset={() =>
|
||||
editor.current
|
||||
?.chain()
|
||||
.focus()
|
||||
.setFontSize(`${defaultFontSize}px`)
|
||||
.run()
|
||||
}
|
||||
value={fontSize || `${defaultFontSize}px`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const fontFamilies = {
|
||||
"Sans-serif": "Open Sans",
|
||||
Serif: "serif",
|
||||
Monospace: "monospace"
|
||||
};
|
||||
export function FontFamily(props: ToolProps) {
|
||||
const { editor } = props;
|
||||
|
||||
const defaultFontFamily = useToolbarStore((store) => store.fontFamily);
|
||||
const currentFontFamily =
|
||||
Object.entries(fontFamilies)
|
||||
.find(([_key, value]) =>
|
||||
editor.isActive("textStyle", { fontFamily: value })
|
||||
)
|
||||
?.map((a) => a)
|
||||
?.at(0) || "Sans-serif";
|
||||
getFontIds().find((id) =>
|
||||
editor.isActive("textStyle", { fontFamily: id })
|
||||
) || defaultFontFamily;
|
||||
|
||||
const items = useMemo(
|
||||
() => toMenuItems(editor, currentFontFamily),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -87,7 +90,7 @@ export function FontFamily(props: ToolProps) {
|
||||
<Dropdown
|
||||
id="fontFamily"
|
||||
group="font"
|
||||
selectedItem={currentFontFamily}
|
||||
selectedItem={getFontById(currentFontFamily)?.title || defaultFontFamily}
|
||||
items={items}
|
||||
menuWidth={130}
|
||||
/>
|
||||
@@ -96,16 +99,16 @@ export function FontFamily(props: ToolProps) {
|
||||
|
||||
function toMenuItems(editor: Editor, currentFontFamily: string): MenuItem[] {
|
||||
const menuItems: MenuItem[] = [];
|
||||
for (const key in fontFamilies) {
|
||||
const value = fontFamilies[key as keyof typeof fontFamilies];
|
||||
for (const font of getFonts()) {
|
||||
menuItems.push({
|
||||
key,
|
||||
key: font.id,
|
||||
type: "button",
|
||||
title: key,
|
||||
isChecked: key === currentFontFamily,
|
||||
onClick: () => editor.current?.chain().focus().setFontFamily(value).run(),
|
||||
title: font.title,
|
||||
isChecked: font.id === currentFontFamily,
|
||||
onClick: () =>
|
||||
editor.current?.chain().focus().setFontFamily(font.id).run(),
|
||||
styles: {
|
||||
fontFamily: value
|
||||
fontFamily: font.font
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,15 +17,34 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function withAnimation(_duration = 300) {
|
||||
return;
|
||||
import { getFontConfig } from "@notesnook/theme/dist/theme/font";
|
||||
|
||||
const FONTS = [
|
||||
{
|
||||
title: "Monospace",
|
||||
id: "monospace",
|
||||
font: getFontConfig().fonts.monospace
|
||||
},
|
||||
{
|
||||
title: "Sans-serif",
|
||||
id: "sans-serif",
|
||||
font: getFontConfig().fonts.body
|
||||
},
|
||||
{
|
||||
title: "Serif",
|
||||
id: "serif",
|
||||
font: `Noto Serif, Times New Roman, serif`
|
||||
}
|
||||
];
|
||||
|
||||
export function getFonts() {
|
||||
return FONTS;
|
||||
}
|
||||
|
||||
function withSpringAnimation(_duration = 300) {
|
||||
return;
|
||||
export function getFontById(id: string) {
|
||||
return FONTS.find((a) => a.id === id);
|
||||
}
|
||||
|
||||
export default {
|
||||
withAnimation,
|
||||
withSpringAnimation
|
||||
};
|
||||
export function getFontIds() {
|
||||
return FONTS.map((a) => a.id);
|
||||
}
|
||||
@@ -1,7 +1,13 @@
|
||||
|
||||
|
||||
.ProseMirror span * {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.ProseMirror {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.ProseMirror p.is-editor-empty:first-child::before {
|
||||
color: var(--placeholder);
|
||||
content: attr(data-placeholder);
|
||||
@@ -87,6 +93,7 @@
|
||||
|
||||
.ProseMirror p {
|
||||
margin-bottom: 0px;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.ProseMirror > p[data-spacing="double"] {
|
||||
@@ -502,7 +509,7 @@ p > *::selection {
|
||||
|
||||
.outline-list li > p::before {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
top: 15%;
|
||||
cursor: pointer;
|
||||
content: "";
|
||||
background-size: 18px;
|
||||
|
||||
Reference in New Issue
Block a user