mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 11:47:54 +01:00
mobile: finalize note linking
This commit is contained in:
committed by
Abdullah Atta
parent
ef6c4bb6fb
commit
09f37ae872
@@ -74,6 +74,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
maxHeight: "100%"
|
maxHeight: "100%"
|
||||||
}}
|
}}
|
||||||
nestedScrollEnabled
|
nestedScrollEnabled
|
||||||
|
bounces={false}
|
||||||
data={[0]}
|
data={[0]}
|
||||||
keyExtractor={() => "properties-scroll-item"}
|
keyExtractor={() => "properties-scroll-item"}
|
||||||
renderItem={() => (
|
renderItem={() => (
|
||||||
@@ -215,6 +216,8 @@ Properties.present = async (item, buttons = [], isSheet) => {
|
|||||||
"reminders",
|
"reminders",
|
||||||
"local-only",
|
"local-only",
|
||||||
"duplicate",
|
"duplicate",
|
||||||
|
"copy-link",
|
||||||
|
"references",
|
||||||
...android,
|
...android,
|
||||||
...buttons
|
...buttons
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ export const Items = ({ item, buttons, close }) => {
|
|||||||
|
|
||||||
const _renderRowItem = ({ item }) => (
|
const _renderRowItem = ({ item }) => (
|
||||||
<View
|
<View
|
||||||
onPress={item.func}
|
|
||||||
key={item.id}
|
key={item.id}
|
||||||
testID={"icon-" + item.id}
|
testID={"icon-" + item.id}
|
||||||
style={{
|
style={{
|
||||||
@@ -117,7 +116,6 @@ export const Items = ({ item, buttons, close }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderTopBarItem = (item, index) => {
|
const renderTopBarItem = (item, index) => {
|
||||||
const isLast = index === topBarItems.length;
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={item.func}
|
onPress={item.func}
|
||||||
@@ -126,7 +124,6 @@ export const Items = ({ item, buttons, close }) => {
|
|||||||
activeOpacity={1}
|
activeOpacity={1}
|
||||||
style={{
|
style={{
|
||||||
alignSelf: "flex-start",
|
alignSelf: "flex-start",
|
||||||
marginRight: isLast ? 0 : 10,
|
|
||||||
paddingHorizontal: 0,
|
paddingHorizontal: 0,
|
||||||
width: topBarItemWidth
|
width: topBarItemWidth
|
||||||
}}
|
}}
|
||||||
@@ -194,6 +191,8 @@ export const Items = ({ item, buttons, close }) => {
|
|||||||
"history",
|
"history",
|
||||||
"reminders",
|
"reminders",
|
||||||
"attachments",
|
"attachments",
|
||||||
|
"references",
|
||||||
|
"copy-link",
|
||||||
"trash"
|
"trash"
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -227,6 +226,9 @@ export const Items = ({ item, buttons, close }) => {
|
|||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
marginTop: 6
|
marginTop: 6
|
||||||
}}
|
}}
|
||||||
|
contentContainerStyle={{
|
||||||
|
gap: 10
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{topBarItems.map(renderTopBarItem)}
|
{topBarItems.map(renderTopBarItem)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { ContentBlock, Note, VirtualizedGrouping } from "@notesnook/core";
|
import {
|
||||||
|
ContentBlock,
|
||||||
|
Note,
|
||||||
|
VirtualizedGrouping,
|
||||||
|
createInternalLink
|
||||||
|
} from "@notesnook/core";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { TextInput, View } from "react-native";
|
import { TextInput, View } from "react-native";
|
||||||
@@ -25,10 +30,12 @@ import { db } from "../../../common/database";
|
|||||||
import { useDBItem } from "../../../hooks/use-db-item";
|
import { useDBItem } from "../../../hooks/use-db-item";
|
||||||
import { presentSheet } from "../../../services/event-manager";
|
import { presentSheet } from "../../../services/event-manager";
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
|
import { Button } from "../../ui/button";
|
||||||
import Input from "../../ui/input";
|
import Input from "../../ui/input";
|
||||||
import { PressableButton } from "../../ui/pressable";
|
import { PressableButton } from "../../ui/pressable";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
import { Button } from "../../ui/button";
|
import type { LinkAttributes } from "@notesnook/editor/dist/extensions/link";
|
||||||
|
import { editorController } from "../../../screens/editor/tiptap/utils";
|
||||||
|
|
||||||
const ListNoteItem = ({
|
const ListNoteItem = ({
|
||||||
id,
|
id,
|
||||||
@@ -91,10 +98,25 @@ const ListBlockItem = ({
|
|||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
justifyContent: "space-between",
|
columnGap: 10,
|
||||||
alignItems: "center"
|
alignItems: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderRadius: 5,
|
||||||
|
backgroundColor: colors.secondary.background,
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
|
||||||
|
{item.type.toUpperCase()}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
|
||||||
<Paragraph
|
<Paragraph
|
||||||
style={{
|
style={{
|
||||||
flexShrink: 1
|
flexShrink: 1
|
||||||
@@ -104,27 +126,17 @@ const ListBlockItem = ({
|
|||||||
? item?.content.slice(0, 200) + "..."
|
? item?.content.slice(0, 200) + "..."
|
||||||
: item.content}
|
: item.content}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
borderRadius: 5,
|
|
||||||
backgroundColor: colors.secondary.background,
|
|
||||||
width: 30,
|
|
||||||
height: 30,
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
|
|
||||||
{item.type.toUpperCase()}
|
|
||||||
</Paragraph>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
</PressableButton>
|
</PressableButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LinkNote() {
|
export default function LinkNote(props: {
|
||||||
|
attributes: LinkAttributes;
|
||||||
|
resolverId: string;
|
||||||
|
onLinkCreated: () => void;
|
||||||
|
close?: (ctx?: string) => void;
|
||||||
|
}) {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const query = useRef<string>();
|
const query = useRef<string>();
|
||||||
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
|
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
|
||||||
@@ -141,6 +153,7 @@ export default function LinkNote() {
|
|||||||
setNotes(notes);
|
setNotes(notes);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
console.log(new URL("https://google.com").protocol);
|
||||||
|
|
||||||
const onChange = async (value: string) => {
|
const onChange = async (value: string) => {
|
||||||
query.current = value;
|
query.current = value;
|
||||||
@@ -161,6 +174,26 @@ export default function LinkNote() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onCreateLink = (blockId?: string) => {
|
||||||
|
if (!selectedNote) return;
|
||||||
|
const link = createInternalLink(
|
||||||
|
"note",
|
||||||
|
selectedNote.id,
|
||||||
|
blockId
|
||||||
|
? {
|
||||||
|
blockId: blockId
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
editorController.current.commands.createInternalLink(
|
||||||
|
{
|
||||||
|
href: link,
|
||||||
|
title: selectedNote.title
|
||||||
|
},
|
||||||
|
props.resolverId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const onSelectNote = async (note: Note) => {
|
const onSelectNote = async (note: Note) => {
|
||||||
setSelectedNote(note);
|
setSelectedNote(note);
|
||||||
inputRef.current?.clear();
|
inputRef.current?.clear();
|
||||||
@@ -172,17 +205,16 @@ export default function LinkNote() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSelectBlock = (block: ContentBlock) => {
|
const onSelectBlock = (block: ContentBlock) => {
|
||||||
setSelectedNodeId(block.id);
|
onCreateLink(block.id);
|
||||||
|
props.onLinkCreated();
|
||||||
|
props.close?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
height: "100%",
|
minHeight: 400
|
||||||
flexShrink: 1,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: "red"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
@@ -270,6 +302,9 @@ export default function LinkNote() {
|
|||||||
renderItem={({ item, index }) => (
|
renderItem={({ item, index }) => (
|
||||||
<ListBlockItem item={item} onSelectBlock={onSelectBlock} />
|
<ListBlockItem item={item} onSelectBlock={onSelectBlock} />
|
||||||
)}
|
)}
|
||||||
|
style={{
|
||||||
|
marginTop: 10
|
||||||
|
}}
|
||||||
keyExtractor={(item) => item.id}
|
keyExtractor={(item) => item.id}
|
||||||
data={nodes}
|
data={nodes}
|
||||||
/>
|
/>
|
||||||
@@ -282,6 +317,9 @@ export default function LinkNote() {
|
|||||||
onSelectNote={onSelectNote}
|
onSelectNote={onSelectNote}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
style={{
|
||||||
|
marginTop: 10
|
||||||
|
}}
|
||||||
data={notes?.placeholders}
|
data={notes?.placeholders}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -294,14 +332,36 @@ export default function LinkNote() {
|
|||||||
title="Create link"
|
title="Create link"
|
||||||
type="accent"
|
type="accent"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
onPress={() => {
|
||||||
|
onCreateLink();
|
||||||
|
props.onLinkCreated();
|
||||||
|
props.close?.();
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkNote.present = () => {
|
LinkNote.present = (attributes: LinkAttributes, resolverId: string) => {
|
||||||
|
let didCreateLink = false;
|
||||||
presentSheet({
|
presentSheet({
|
||||||
component: () => <LinkNote />
|
component: (ref, close) => (
|
||||||
|
<LinkNote
|
||||||
|
attributes={attributes}
|
||||||
|
resolverId={resolverId}
|
||||||
|
onLinkCreated={() => {
|
||||||
|
didCreateLink = true;
|
||||||
|
}}
|
||||||
|
close={close}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
onClose: () => {
|
||||||
|
if (!didCreateLink) {
|
||||||
|
editorController?.current.commands.dismissCreateInternalLinkRequest(
|
||||||
|
resolverId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
521
apps/mobile/app/components/sheets/references/index.tsx
Normal file
521
apps/mobile/app/components/sheets/references/index.tsx
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
/*
|
||||||
|
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 {
|
||||||
|
InternalLink,
|
||||||
|
TextSlice,
|
||||||
|
VirtualizedGrouping,
|
||||||
|
createInternalLink,
|
||||||
|
highlightInternalLinks
|
||||||
|
} from "@notesnook/core";
|
||||||
|
import { ContentBlock, ItemReference, Note } from "@notesnook/core/dist/types";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
|
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||||
|
import { ActivityIndicator, View } from "react-native";
|
||||||
|
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
|
||||||
|
import create from "zustand";
|
||||||
|
import { db } from "../../../common/database";
|
||||||
|
import { useDBItem } from "../../../hooks/use-db-item";
|
||||||
|
import { eSendEvent, presentSheet } from "../../../services/event-manager";
|
||||||
|
import { useRelationStore } from "../../../stores/use-relation-store";
|
||||||
|
import { eOnLoadNote } from "../../../utils/events";
|
||||||
|
import { tabBarRef } from "../../../utils/global-refs";
|
||||||
|
import { SIZE } from "../../../utils/size";
|
||||||
|
import SheetProvider from "../../sheet-provider";
|
||||||
|
import { Button } from "../../ui/button";
|
||||||
|
import { IconButton } from "../../ui/icon-button";
|
||||||
|
import { PressableButton } from "../../ui/pressable";
|
||||||
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
|
|
||||||
|
export const useExpandedStore = create<{
|
||||||
|
expanded: {
|
||||||
|
[id: string]: boolean;
|
||||||
|
};
|
||||||
|
setExpanded: (id: string) => void;
|
||||||
|
}>((set, get) => ({
|
||||||
|
expanded: {},
|
||||||
|
setExpanded(id: string) {
|
||||||
|
set({
|
||||||
|
expanded: {
|
||||||
|
...get().expanded,
|
||||||
|
[id]: !get().expanded[id]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const ListBlockItem = ({
|
||||||
|
item,
|
||||||
|
onSelectBlock
|
||||||
|
}: {
|
||||||
|
item: ContentBlock;
|
||||||
|
onSelectBlock: () => void;
|
||||||
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
return (
|
||||||
|
<PressableButton
|
||||||
|
onPress={() => {
|
||||||
|
onSelectBlock();
|
||||||
|
}}
|
||||||
|
type={"transparent"}
|
||||||
|
customStyle={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
paddingLeft: 35,
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
minHeight: 45,
|
||||||
|
paddingHorizontal: 12
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
columnGap: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderRadius: 5,
|
||||||
|
backgroundColor: colors.secondary.background,
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
|
||||||
|
{item.type.toUpperCase()}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
flexShrink: 1,
|
||||||
|
marginTop: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item?.content.length > 200
|
||||||
|
? item?.content.slice(0, 200) + "..."
|
||||||
|
: item.content}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
</PressableButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListNoteInternalLink = ({
|
||||||
|
link,
|
||||||
|
onSelect
|
||||||
|
}: {
|
||||||
|
link: {
|
||||||
|
blockId: string;
|
||||||
|
highlightedText: [TextSlice, TextSlice, TextSlice][];
|
||||||
|
};
|
||||||
|
onSelect: () => void;
|
||||||
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
return (
|
||||||
|
<PressableButton
|
||||||
|
onPress={() => {
|
||||||
|
onSelect();
|
||||||
|
}}
|
||||||
|
type={"transparent"}
|
||||||
|
customStyle={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
paddingLeft: 35,
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
minHeight: 45
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
rowGap: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{link.highlightedText.map((text) => (
|
||||||
|
<Paragraph
|
||||||
|
key={`root_${text[0].text}`}
|
||||||
|
style={{
|
||||||
|
flexShrink: 1,
|
||||||
|
marginTop: 2,
|
||||||
|
flexWrap: "wrap"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text.map((slice) =>
|
||||||
|
!slice.highlighted ? (
|
||||||
|
slice.text
|
||||||
|
) : (
|
||||||
|
<Paragraph
|
||||||
|
key={slice.text}
|
||||||
|
color={colors.selected.accent}
|
||||||
|
style={{
|
||||||
|
textDecorationLine: "underline",
|
||||||
|
textDecorationColor: colors.selected.accent
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{slice.text}
|
||||||
|
</Paragraph>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Paragraph>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</PressableButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListNoteItem = ({
|
||||||
|
id,
|
||||||
|
items,
|
||||||
|
onSelect,
|
||||||
|
reference,
|
||||||
|
internalLinks,
|
||||||
|
listType
|
||||||
|
}: {
|
||||||
|
id: number;
|
||||||
|
items: VirtualizedGrouping<Note> | undefined;
|
||||||
|
onSelect: (item: Note, blockId?: string) => void;
|
||||||
|
reference: Note;
|
||||||
|
internalLinks: MutableRefObject<InternalLink<"note">[] | undefined>;
|
||||||
|
listType: "linkedNotes" | "referencedIn";
|
||||||
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const [item] = useDBItem(id, "note", items);
|
||||||
|
const expanded = useExpandedStore((state) =>
|
||||||
|
!item ? false : state.expanded[item.id]
|
||||||
|
);
|
||||||
|
const [linkedBlocks, setLinkedBlocks] = useState<ContentBlock[]>([]);
|
||||||
|
const [noteInternalLinks, setNoteInternalLinks] = useState<
|
||||||
|
{
|
||||||
|
blockId: string;
|
||||||
|
highlightedText: [TextSlice, TextSlice, TextSlice][];
|
||||||
|
}[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (item?.id && expanded) {
|
||||||
|
(async () => {
|
||||||
|
if (listType === "linkedNotes") {
|
||||||
|
if (linkedBlocks.length) return;
|
||||||
|
setLoading(true);
|
||||||
|
if (!internalLinks.current) {
|
||||||
|
internalLinks.current = await db.notes.internalLinks(reference.id);
|
||||||
|
}
|
||||||
|
const noteLinks = internalLinks.current.filter(
|
||||||
|
(link) => link.id === item.id && link.params?.blockId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (noteLinks.length) {
|
||||||
|
const blocks = await db.notes.contentBlocks(item.id);
|
||||||
|
|
||||||
|
setLinkedBlocks(
|
||||||
|
blocks.filter((block) =>
|
||||||
|
noteLinks.find((link) => block.id === link.params?.blockId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (noteInternalLinks.length) return;
|
||||||
|
setLoading(true);
|
||||||
|
const blocks = await db.notes.contentBlocks(item.id);
|
||||||
|
|
||||||
|
setNoteInternalLinks(
|
||||||
|
blocks
|
||||||
|
.filter((block) =>
|
||||||
|
block.content.includes(createInternalLink("note", reference.id))
|
||||||
|
)
|
||||||
|
.map((block) => {
|
||||||
|
return {
|
||||||
|
blockId: block?.id as string,
|
||||||
|
highlightedText: highlightInternalLinks(
|
||||||
|
block as ContentBlock,
|
||||||
|
reference.id
|
||||||
|
)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
item?.id,
|
||||||
|
expanded,
|
||||||
|
linkedBlocks.length,
|
||||||
|
internalLinks,
|
||||||
|
reference.id,
|
||||||
|
listType,
|
||||||
|
noteInternalLinks.length
|
||||||
|
]);
|
||||||
|
|
||||||
|
const renderBlock = React.useCallback(
|
||||||
|
(block: ContentBlock) => (
|
||||||
|
<ListBlockItem
|
||||||
|
item={block}
|
||||||
|
onSelectBlock={() => {
|
||||||
|
if (!item) return;
|
||||||
|
onSelect(item, block.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[item, onSelect]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderInternalLink = React.useCallback(
|
||||||
|
(link: {
|
||||||
|
blockId: string;
|
||||||
|
highlightedText: [TextSlice, TextSlice, TextSlice][];
|
||||||
|
}) => (
|
||||||
|
<ListNoteInternalLink
|
||||||
|
link={link}
|
||||||
|
onSelect={() => {
|
||||||
|
if (!item) return;
|
||||||
|
onSelect(item, link.blockId);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[item, onSelect]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PressableButton
|
||||||
|
type={"gray"}
|
||||||
|
onPress={() => {
|
||||||
|
if (!item) return;
|
||||||
|
onSelect(item as Note);
|
||||||
|
}}
|
||||||
|
customStyle={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
width: "100%",
|
||||||
|
height: 45
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
size={SIZE.xl}
|
||||||
|
onPress={() => {
|
||||||
|
if (!item?.id) return;
|
||||||
|
useExpandedStore.getState().setExpanded(item?.id);
|
||||||
|
}}
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
bottom={0}
|
||||||
|
right={0}
|
||||||
|
customStyle={{
|
||||||
|
width: 35,
|
||||||
|
height: 35
|
||||||
|
}}
|
||||||
|
name={expanded ? "chevron-down" : "chevron-right"}
|
||||||
|
/>
|
||||||
|
<Paragraph numberOfLines={1}>{item?.title}</Paragraph>
|
||||||
|
</PressableButton>
|
||||||
|
|
||||||
|
{expanded && !item?.locked ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<ActivityIndicator color={colors.primary.accent} size={SIZE.lg} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{listType === "linkedNotes" ? (
|
||||||
|
<>
|
||||||
|
{linkedBlocks.length === 0 ? (
|
||||||
|
<Paragraph color={colors.secondary.paragraph}>
|
||||||
|
No blocks linked
|
||||||
|
</Paragraph>
|
||||||
|
) : (
|
||||||
|
linkedBlocks.map(renderBlock)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{noteInternalLinks.length === 0 ? (
|
||||||
|
<Paragraph color={colors.secondary.paragraph}>
|
||||||
|
No references found of this note
|
||||||
|
</Paragraph>
|
||||||
|
) : (
|
||||||
|
noteInternalLinks.map(renderInternalLink)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type ReferencesListProps = {
|
||||||
|
item: { id: string; type: string };
|
||||||
|
close?: (ctx?: any) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ReferencesList = ({ item, close }: ReferencesListProps) => {
|
||||||
|
const [tab, setTab] = useState(0);
|
||||||
|
const updater = useRelationStore((state) => state.updater);
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const [items, setItems] = useState<VirtualizedGrouping<Note>>();
|
||||||
|
const hasNoRelations = !items || items?.placeholders?.length === 0;
|
||||||
|
const internalLinks = useRef<InternalLink<"note">[]>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
db.relations?.[tab === 0 ? "from" : "to"]?.(
|
||||||
|
{ id: item?.id, type: item?.type } as ItemReference,
|
||||||
|
"note"
|
||||||
|
)
|
||||||
|
.selector.sorted({
|
||||||
|
sortBy: "dateEdited",
|
||||||
|
sortDirection: "desc"
|
||||||
|
})
|
||||||
|
.then((items) => {
|
||||||
|
setItems(items);
|
||||||
|
});
|
||||||
|
}, [item?.id, item?.type, tab]);
|
||||||
|
|
||||||
|
const renderNote = React.useCallback(
|
||||||
|
({ index }: any) => (
|
||||||
|
<ListNoteItem
|
||||||
|
id={index}
|
||||||
|
items={items}
|
||||||
|
onSelect={(note, blockId) => {
|
||||||
|
console.log(note.id, blockId);
|
||||||
|
eSendEvent(eOnLoadNote, {
|
||||||
|
item: note,
|
||||||
|
blockId: blockId
|
||||||
|
});
|
||||||
|
tabBarRef.current?.goToPage(1);
|
||||||
|
close?.();
|
||||||
|
}}
|
||||||
|
reference={item as Note}
|
||||||
|
internalLinks={internalLinks}
|
||||||
|
listType={tab === 0 ? "linkedNotes" : "referencedIn"}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[items, item, tab, close]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ height: "100%" }}>
|
||||||
|
<SheetProvider context="local" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: colors.primary.border
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type={"gray"}
|
||||||
|
title="Linked notes"
|
||||||
|
style={{
|
||||||
|
borderRadius: 0,
|
||||||
|
borderBottomWidth: 3,
|
||||||
|
borderColor: tab === 0 ? colors.primary.accent : "transparent",
|
||||||
|
height: 40,
|
||||||
|
width: "50%"
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
setTab(0);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type={"gray"}
|
||||||
|
title="Referenced in"
|
||||||
|
style={{
|
||||||
|
width: "50%",
|
||||||
|
borderRadius: 0,
|
||||||
|
borderBottomWidth: 3,
|
||||||
|
borderColor: tab === 1 ? colors.primary.accent : "transparent",
|
||||||
|
height: 40
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
setTab(1);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{hasNoRelations ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
height: "85%",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paragraph color={colors.secondary.paragraph}>
|
||||||
|
{tab === 1
|
||||||
|
? "This note is not referenced in other notes."
|
||||||
|
: "This note does not link to other notes."}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
flex: 1,
|
||||||
|
marginTop: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FlashList
|
||||||
|
bounces={false}
|
||||||
|
data={items.placeholders}
|
||||||
|
renderItem={renderNote}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ReferencesList.present = ({
|
||||||
|
reference
|
||||||
|
}: {
|
||||||
|
reference: { id: string; type: string };
|
||||||
|
}) => {
|
||||||
|
presentSheet({
|
||||||
|
component: (ref, close, update) => (
|
||||||
|
<ReferencesList item={reference} close={close} />
|
||||||
|
),
|
||||||
|
onClose: () => {
|
||||||
|
useExpandedStore.setState({
|
||||||
|
expanded: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import { VAULT_ERRORS } from "@notesnook/core/dist/api/vault";
|
import { VAULT_ERRORS } from "@notesnook/core/dist/api/vault";
|
||||||
import {
|
import {
|
||||||
Color,
|
Color,
|
||||||
|
ItemReference,
|
||||||
Note,
|
Note,
|
||||||
Notebook,
|
Notebook,
|
||||||
Reminder,
|
Reminder,
|
||||||
@@ -64,6 +65,7 @@ import { eOpenLoginDialog } from "../utils/events";
|
|||||||
import { deleteItems } from "../utils/functions";
|
import { deleteItems } from "../utils/functions";
|
||||||
import { convertNoteToText } from "../utils/note-to-text";
|
import { convertNoteToText } from "../utils/note-to-text";
|
||||||
import { sleep } from "../utils/time";
|
import { sleep } from "../utils/time";
|
||||||
|
import { ReferencesList } from "../components/sheets/references";
|
||||||
|
|
||||||
export const useActions = ({
|
export const useActions = ({
|
||||||
close,
|
close,
|
||||||
@@ -801,7 +803,20 @@ export const useActions = ({
|
|||||||
icon: "history",
|
icon: "history",
|
||||||
func: openHistory
|
func: openHistory
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "copy-link",
|
||||||
|
title: "Copy link",
|
||||||
|
icon: "link",
|
||||||
|
func: () => {
|
||||||
|
Clipboard.setString(`nn://note/${item.id}`);
|
||||||
|
ToastManager.show({
|
||||||
|
heading: "Note link copied",
|
||||||
|
message: `nn://note/${item.id}`,
|
||||||
|
context: "local",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "reminders",
|
id: "reminders",
|
||||||
title: "Reminders",
|
title: "Reminders",
|
||||||
@@ -909,6 +924,16 @@ export const useActions = ({
|
|||||||
title: "Add tags",
|
title: "Add tags",
|
||||||
icon: "pound",
|
icon: "pound",
|
||||||
func: addTo
|
func: addTo
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "references",
|
||||||
|
title: "References",
|
||||||
|
icon: "vector-link",
|
||||||
|
func: () => {
|
||||||
|
ReferencesList.present({
|
||||||
|
reference: item as ItemReference
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,5 @@ const EditorMobileSourceUrl =
|
|||||||
* The url should be something like this: http://192.168.100.126:3000/index.html
|
* The url should be something like this: http://192.168.100.126:3000/index.html
|
||||||
*/
|
*/
|
||||||
export const EDITOR_URI = __DEV__
|
export const EDITOR_URI = __DEV__
|
||||||
? "http://192.168.43.252:3000/index.html"
|
? EditorMobileSourceUrl
|
||||||
: EditorMobileSourceUrl;
|
: EditorMobileSourceUrl;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { Settings } from "./types";
|
|||||||
import { getResponse, randId, textInput } from "./utils";
|
import { getResponse, randId, textInput } from "./utils";
|
||||||
import { Note } from "@notesnook/core/dist/types";
|
import { Note } from "@notesnook/core/dist/types";
|
||||||
import { useTabStore } from "./use-tab-store";
|
import { useTabStore } from "./use-tab-store";
|
||||||
|
import type { LinkAttributes } from "@notesnook/editor/dist/extensions/link";
|
||||||
|
|
||||||
type Action = { job: string; id: string };
|
type Action = { job: string; id: string };
|
||||||
|
|
||||||
@@ -322,6 +323,28 @@ const image = toBlobURL("${image.dataurl}", "${image.hash}");
|
|||||||
`);
|
`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
createInternalLink = async (
|
||||||
|
attributes: LinkAttributes,
|
||||||
|
resolverId: string
|
||||||
|
) => {
|
||||||
|
if (!resolverId) return;
|
||||||
|
return this.doAsync(`
|
||||||
|
if (globalThis.pendingResolvers["${resolverId}"]) {
|
||||||
|
globalThis.pendingResolvers["${resolverId}"](${JSON.stringify(
|
||||||
|
attributes
|
||||||
|
)});
|
||||||
|
}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
dismissCreateInternalLinkRequest = async (resolverId: string) => {
|
||||||
|
if (!resolverId) return;
|
||||||
|
return this.doAsync(`
|
||||||
|
if (globalThis.pendingResolvers["${resolverId}"]) {
|
||||||
|
globalThis.pendingResolvers["${resolverId}"](undefined);
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
};
|
||||||
|
|
||||||
scrollIntoViewById = async (id: string) => {
|
scrollIntoViewById = async (id: string) => {
|
||||||
const tabId = useTabStore.getState().currentTab;
|
const tabId = useTabStore.getState().currentTab;
|
||||||
return this.doAsync(`
|
return this.doAsync(`
|
||||||
|
|||||||
@@ -41,5 +41,6 @@ export const EventTypes = {
|
|||||||
tabsChanged: "editor-events:tabs-changed",
|
tabsChanged: "editor-events:tabs-changed",
|
||||||
showTabs: "editor-events:show-tabs",
|
showTabs: "editor-events:show-tabs",
|
||||||
tabFocused: "editor-events:tab-focused",
|
tabFocused: "editor-events:tab-focused",
|
||||||
toc: "editor-events:toc"
|
toc: "editor-events:toc",
|
||||||
|
createInternalLink: "editor-events:create-internal-link"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ import { EditorMessage, EditorProps, useEditorType } from "./types";
|
|||||||
import { useTabStore } from "./use-tab-store";
|
import { useTabStore } from "./use-tab-store";
|
||||||
import { EditorEvents, editorState } from "./utils";
|
import { EditorEvents, editorState } from "./utils";
|
||||||
import TableOfContents from "../../../components/sheets/toc";
|
import TableOfContents from "../../../components/sheets/toc";
|
||||||
|
import LinkNote from "../../../components/sheets/link-note";
|
||||||
|
import { parseInternalLink } from "@notesnook/core";
|
||||||
|
|
||||||
const publishNote = async () => {
|
const publishNote = async () => {
|
||||||
const user = useUserStore.getState().user;
|
const user = useUserStore.getState().user;
|
||||||
@@ -504,7 +506,35 @@ export const useEditorEvents = (
|
|||||||
eSendEvent(eOpenFullscreenEditor);
|
eSendEvent(eOpenFullscreenEditor);
|
||||||
break;
|
break;
|
||||||
case EventTypes.link:
|
case EventTypes.link:
|
||||||
openLinkInBrowser(editorMessage.value as string);
|
if (editorMessage.value.startsWith("nn://")) {
|
||||||
|
const data = parseInternalLink(editorMessage.value);
|
||||||
|
if (!data?.id) break;
|
||||||
|
if (
|
||||||
|
data.id ===
|
||||||
|
useTabStore
|
||||||
|
.getState()
|
||||||
|
.getNoteIdForTab(useTabStore.getState().currentTab)
|
||||||
|
) {
|
||||||
|
if (data.params?.blockId) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!data.params?.blockId) return;
|
||||||
|
editor.commands.scrollIntoViewById(data.params.blockId);
|
||||||
|
}, 150);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eSendEvent(eOnLoadNote, {
|
||||||
|
item: await db.notes.note(data?.id),
|
||||||
|
blockId: data.params?.blockId
|
||||||
|
});
|
||||||
|
console.log(
|
||||||
|
"Opening note from internal link:",
|
||||||
|
editorMessage.value
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
openLinkInBrowser(editorMessage.value as string);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventTypes.previewAttachment: {
|
case EventTypes.previewAttachment: {
|
||||||
@@ -576,6 +606,13 @@ export const useEditorEvents = (
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EventTypes.createInternalLink: {
|
||||||
|
LinkNote.present(
|
||||||
|
editorMessage.value.attributes,
|
||||||
|
editorMessage.value.resolverId
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ export const useEditor = (
|
|||||||
const currentLoadingNoteId = useRef<string>();
|
const currentLoadingNoteId = useRef<string>();
|
||||||
const loadingState = useRef<string>();
|
const loadingState = useRef<string>();
|
||||||
const lastTabFocused = useRef(0);
|
const lastTabFocused = useRef(0);
|
||||||
|
const blockIdRef = useRef<string>();
|
||||||
const postMessage = useCallback(
|
const postMessage = useCallback(
|
||||||
async <T>(type: string, data: T, tabId?: number, waitFor = 300) =>
|
async <T>(type: string, data: T, tabId?: number, waitFor = 300) =>
|
||||||
await post(
|
await post(
|
||||||
@@ -382,7 +383,9 @@ export const useEditor = (
|
|||||||
forced?: boolean;
|
forced?: boolean;
|
||||||
newNote?: boolean;
|
newNote?: boolean;
|
||||||
tabId?: number;
|
tabId?: number;
|
||||||
|
blockId?: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
blockIdRef.current = event.blockId;
|
||||||
state.current.currentlyEditing = true;
|
state.current.currentlyEditing = true;
|
||||||
if (
|
if (
|
||||||
!state.current.ready &&
|
!state.current.ready &&
|
||||||
@@ -495,6 +498,13 @@ export const useEditor = (
|
|||||||
10000
|
10000
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (blockIdRef.current) {
|
||||||
|
commands.scrollIntoViewById(blockIdRef.current);
|
||||||
|
blockIdRef.current = undefined;
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
|
||||||
loadingState.current = undefined;
|
loadingState.current = undefined;
|
||||||
await commands.setTags(item);
|
await commands.setTags(item);
|
||||||
commands.setSettings();
|
commands.setSettings();
|
||||||
@@ -743,7 +753,7 @@ export const useEditor = (
|
|||||||
restoreTabNote();
|
restoreTabNote();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}, 500);
|
||||||
}, [
|
}, [
|
||||||
onReady,
|
onReady,
|
||||||
postMessage,
|
postMessage,
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import SettingsService from "../../services/settings";
|
|||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
import { useNotes } from "../../stores/use-notes-store";
|
import { useNotes } from "../../stores/use-notes-store";
|
||||||
import { openEditor } from "../notes/common";
|
import { openEditor } from "../notes/common";
|
||||||
|
import LinkNote from "../../components/sheets/link-note";
|
||||||
|
|
||||||
export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||||
const [notes, loading] = useNotes();
|
const [notes, loading] = useNotes();
|
||||||
@@ -79,7 +80,12 @@ export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
|||||||
loading: "Loading your notes"
|
loading: "Loading your notes"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<FloatingButton title="Create a new note" onPress={openEditor} />
|
<FloatingButton
|
||||||
|
title="Create a new note"
|
||||||
|
onPress={() => {
|
||||||
|
LinkNote.present();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</DelayLayout>
|
</DelayLayout>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
import 'react-native-url-polyfill/auto';
|
||||||
import "./polyfills/console-time.js"
|
import "./polyfills/console-time.js"
|
||||||
global.Buffer = require('buffer').Buffer;
|
global.Buffer = require('buffer').Buffer;
|
||||||
import '../app/common/logger/index';
|
import '../app/common/logger/index';
|
||||||
|
|||||||
@@ -66,7 +66,8 @@
|
|||||||
"react-native-quick-sqlite": "^8.0.6",
|
"react-native-quick-sqlite": "^8.0.6",
|
||||||
"react-native-theme-switch-animation": "^0.6.0",
|
"react-native-theme-switch-animation": "^0.6.0",
|
||||||
"@ammarahmed/react-native-background-fetch": "^4.2.2",
|
"@ammarahmed/react-native-background-fetch": "^4.2.2",
|
||||||
"react-native-image-crop-picker": "^0.40.2"
|
"react-native-image-crop-picker": "^0.40.2",
|
||||||
|
"react-native-url-polyfill": "^2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
|
|||||||
52361
apps/mobile/package-lock.json
generated
52361
apps/mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@
|
|||||||
"@notesnook/editor": "file:../../packages/editor",
|
"@notesnook/editor": "file:../../packages/editor",
|
||||||
"@notesnook/editor-mobile": "file:../../packages/editor-mobile",
|
"@notesnook/editor-mobile": "file:../../packages/editor-mobile",
|
||||||
"@notesnook/logger": "file:../../packages/logger",
|
"@notesnook/logger": "file:../../packages/logger",
|
||||||
|
"@notesnook/theme": "file:../../packages/theme",
|
||||||
"@notesnook/themes-server": "file:../../servers/themes",
|
"@notesnook/themes-server": "file:../../servers/themes",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.72.0"
|
"react-native": "0.72.0"
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ const EXTRA_ICON_NAMES = [
|
|||||||
"cloud",
|
"cloud",
|
||||||
"restore",
|
"restore",
|
||||||
"keyboard",
|
"keyboard",
|
||||||
"numeric"
|
"numeric",
|
||||||
|
"vector-link"
|
||||||
];
|
];
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
|||||||
7
apps/theme-builder/package-lock.json
generated
7
apps/theme-builder/package-lock.json
generated
@@ -977,7 +977,7 @@
|
|||||||
},
|
},
|
||||||
"../web": {
|
"../web": {
|
||||||
"name": "@notesnook/web",
|
"name": "@notesnook/web",
|
||||||
"version": "3.0.2-beta",
|
"version": "3.0.6-beta",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1020,6 +1020,7 @@
|
|||||||
"cronosjs": "^1.7.1",
|
"cronosjs": "^1.7.1",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
|
"diffblazer": "^1.0.1",
|
||||||
"electron-trpc": "0.5.2",
|
"electron-trpc": "0.5.2",
|
||||||
"event-source-polyfill": "^1.0.25",
|
"event-source-polyfill": "^1.0.25",
|
||||||
"fflate": "^0.8.0",
|
"fflate": "^0.8.0",
|
||||||
@@ -1038,11 +1039,13 @@
|
|||||||
"platform": "^1.3.6",
|
"platform": "^1.3.6",
|
||||||
"qclone": "^1.2.0",
|
"qclone": "^1.2.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
"react-avatar-editor": "^13.0.2",
|
||||||
"react-complex-tree": "^2.2.4",
|
"react-complex-tree": "^2.2.4",
|
||||||
"react-day-picker": "^8.9.1",
|
"react-day-picker": "^8.9.1",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-error-boundary": "^4.0.12",
|
"react-error-boundary": "^4.0.12",
|
||||||
|
"react-freeze": "^1.0.3",
|
||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.4.1",
|
||||||
"react-loading-skeleton": "^3.3.1",
|
"react-loading-skeleton": "^3.3.1",
|
||||||
"react-modal": "3.16.1",
|
"react-modal": "3.16.1",
|
||||||
@@ -1068,8 +1071,10 @@
|
|||||||
"@types/node-fetch": "^2.5.10",
|
"@types/node-fetch": "^2.5.10",
|
||||||
"@types/platform": "^1.3.4",
|
"@types/platform": "^1.3.4",
|
||||||
"@types/react": "^18.2.39",
|
"@types/react": "^18.2.39",
|
||||||
|
"@types/react-avatar-editor": "^13.0.2",
|
||||||
"@types/react-dom": "^18.2.17",
|
"@types/react-dom": "^18.2.17",
|
||||||
"@types/react-modal": "3.16.3",
|
"@types/react-modal": "3.16.3",
|
||||||
|
"@types/react-scroll-sync": "^0.9.0",
|
||||||
"@types/tinycolor2": "^1.4.3",
|
"@types/tinycolor2": "^1.4.3",
|
||||||
"@types/wicg-file-system-access": "^2020.9.6",
|
"@types/wicg-file-system-access": "^2020.9.6",
|
||||||
"@vitejs/plugin-react-swc": "3.3.2",
|
"@vitejs/plugin-react-swc": "3.3.2",
|
||||||
|
|||||||
6
packages/common/package-lock.json
generated
6
packages/common/package-lock.json
generated
@@ -36,6 +36,9 @@
|
|||||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.1.0",
|
||||||
"entities": "^4.3.1",
|
"entities": "^4.3.1",
|
||||||
"fuzzyjs": "^5.0.1",
|
"fuzzyjs": "^5.0.1",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
@@ -176,6 +179,9 @@
|
|||||||
"bson-objectid": "^2.0.4",
|
"bson-objectid": "^2.0.4",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.1.0",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"entities": "^4.3.1",
|
"entities": "^4.3.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import {
|
|||||||
useTabStore
|
useTabStore
|
||||||
} from "../hooks/useTabStore";
|
} from "../hooks/useTabStore";
|
||||||
import { EmotionEditorToolbarTheme } from "../theme-factory";
|
import { EmotionEditorToolbarTheme } from "../theme-factory";
|
||||||
import { EventTypes, Settings } from "../utils";
|
import { EventTypes, randId, Settings } from "../utils";
|
||||||
import Header from "./header";
|
import Header from "./header";
|
||||||
import StatusBar from "./statusbar";
|
import StatusBar from "./statusbar";
|
||||||
import Tags from "./tags";
|
import Tags from "./tags";
|
||||||
@@ -82,15 +82,15 @@ const Tiptap = ({
|
|||||||
transaction.getMeta("ignoreEdit")
|
transaction.getMeta("ignoreEdit")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onOpenAttachmentPicker: (editor, type) => {
|
openAttachmentPicker: (type) => {
|
||||||
globalThis.editorControllers[tab.id]?.openFilePicker(type);
|
globalThis.editorControllers[tab.id]?.openFilePicker(type);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onDownloadAttachment: (editor, attachment) => {
|
downloadAttachment: (attachment) => {
|
||||||
globalThis.editorControllers[tab.id]?.downloadAttachment(attachment);
|
globalThis.editorControllers[tab.id]?.downloadAttachment(attachment);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onPreviewAttachment(editor, attachment) {
|
previewAttachment(attachment) {
|
||||||
globalThis.editorControllers[tab.id]?.previewAttachment(attachment);
|
globalThis.editorControllers[tab.id]?.previewAttachment(attachment);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@@ -99,6 +99,23 @@ const Tiptap = ({
|
|||||||
attachment
|
attachment
|
||||||
) as Promise<string | undefined>;
|
) as Promise<string | undefined>;
|
||||||
},
|
},
|
||||||
|
createInternalLink(attributes) {
|
||||||
|
logger("info", "create internal link");
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const id = randId("createInternalLink");
|
||||||
|
|
||||||
|
globalThis.pendingResolvers[id] = (value) => {
|
||||||
|
delete globalThis.pendingResolvers[id];
|
||||||
|
resolve(value);
|
||||||
|
logger("info", "resolved create link request:", id);
|
||||||
|
};
|
||||||
|
|
||||||
|
post("editor-events:create-internal-link", {
|
||||||
|
attributes: attributes,
|
||||||
|
resolverId: id
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
element: getContentDiv(),
|
element: getContentDiv(),
|
||||||
editable: !settings.readonly,
|
editable: !settings.readonly,
|
||||||
editorProps: {
|
editorProps: {
|
||||||
@@ -107,7 +124,7 @@ const Tiptap = ({
|
|||||||
content: globalThis.editorControllers[tab.id]?.content?.current,
|
content: globalThis.editorControllers[tab.id]?.content?.current,
|
||||||
isMobile: true,
|
isMobile: true,
|
||||||
doubleSpacedLines: settings.doubleSpacedLines,
|
doubleSpacedLines: settings.doubleSpacedLines,
|
||||||
onOpenLink: (url) => {
|
openLink: (url) => {
|
||||||
return globalThis.editorControllers[tab.id]?.openLink(url) || true;
|
return globalThis.editorControllers[tab.id]?.openLink(url) || true;
|
||||||
},
|
},
|
||||||
copyToClipboard: (text) => {
|
copyToClipboard: (text) => {
|
||||||
|
|||||||
@@ -17,13 +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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { ControlledMenu, MenuItem as MenuItemInner } from "@szhsin/react-menu";
|
||||||
ControlledMenu,
|
|
||||||
// applyStatics
|
|
||||||
MenuItem as MenuItemInner,
|
|
||||||
SubMenu as SubMenuInner,
|
|
||||||
MenuDivider
|
|
||||||
} from "@szhsin/react-menu";
|
|
||||||
import ArrowBackIcon from "mdi-react/ArrowBackIcon";
|
import ArrowBackIcon from "mdi-react/ArrowBackIcon";
|
||||||
import ArrowULeftTopIcon from "mdi-react/ArrowULeftTopIcon";
|
import ArrowULeftTopIcon from "mdi-react/ArrowULeftTopIcon";
|
||||||
import ArrowURightTopIcon from "mdi-react/ArrowURightTopIcon";
|
import ArrowURightTopIcon from "mdi-react/ArrowURightTopIcon";
|
||||||
@@ -32,12 +26,13 @@ import DotsHorizontalIcon from "mdi-react/DotsHorizontalIcon";
|
|||||||
import DotsVerticalIcon from "mdi-react/DotsVerticalIcon";
|
import DotsVerticalIcon from "mdi-react/DotsVerticalIcon";
|
||||||
import FullscreenIcon from "mdi-react/FullscreenIcon";
|
import FullscreenIcon from "mdi-react/FullscreenIcon";
|
||||||
import MagnifyIcon from "mdi-react/MagnifyIcon";
|
import MagnifyIcon from "mdi-react/MagnifyIcon";
|
||||||
|
import TableOfContentsIcon from "mdi-react/TableOfContentsIcon";
|
||||||
import React, { useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { useSafeArea } from "../hooks/useSafeArea";
|
import { useSafeArea } from "../hooks/useSafeArea";
|
||||||
import { useTabContext, useTabStore } from "../hooks/useTabStore";
|
import { useTabContext, useTabStore } from "../hooks/useTabStore";
|
||||||
import { EventTypes, Settings } from "../utils";
|
import { EventTypes, Settings } from "../utils";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import TableOfContentsIcon from "mdi-react/TableOfContentsIcon";
|
|
||||||
const menuClassName = ({ state }: any) =>
|
const menuClassName = ({ state }: any) =>
|
||||||
state === "opening"
|
state === "opening"
|
||||||
? styles.menuOpening
|
? styles.menuOpening
|
||||||
@@ -52,22 +47,10 @@ const menuItemClassName = ({ hover, disabled }: any) =>
|
|||||||
? styles.menuItemHover
|
? styles.menuItemHover
|
||||||
: styles.menuItem;
|
: styles.menuItem;
|
||||||
|
|
||||||
const submenuItemClassName = (modifiers: any) =>
|
|
||||||
`${styles.submenuItem} ${menuItemClassName(modifiers)}`;
|
|
||||||
|
|
||||||
const MenuItem = (props: any) => (
|
const MenuItem = (props: any) => (
|
||||||
<MenuItemInner {...props} className={menuItemClassName} />
|
<MenuItemInner {...props} className={menuItemClassName} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const SubMenu = (props: any) => (
|
|
||||||
<SubMenuInner
|
|
||||||
{...props}
|
|
||||||
menuClassName={menuClassName}
|
|
||||||
itemProps={{ className: submenuItemClassName }}
|
|
||||||
offsetY={-7}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const Button = ({
|
const Button = ({
|
||||||
onPress,
|
onPress,
|
||||||
children,
|
children,
|
||||||
@@ -178,65 +161,6 @@ function Header({
|
|||||||
flexDirection: "row"
|
flexDirection: "row"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
|
||||||
onPress={() => {
|
|
||||||
editor?.commands.undo();
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
borderWidth: 0,
|
|
||||||
borderRadius: 100,
|
|
||||||
color: "var(--nn_primary_icon)",
|
|
||||||
marginRight: 10,
|
|
||||||
width: 39,
|
|
||||||
height: 39,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
position: "relative"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ArrowULeftTopIcon
|
|
||||||
color={
|
|
||||||
!hasUndo
|
|
||||||
? "var(--nn_secondary_background)"
|
|
||||||
: "var(--nn_primary_paragraph)"
|
|
||||||
}
|
|
||||||
size={25 * settings.fontScale}
|
|
||||||
style={{
|
|
||||||
position: "absolute"
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
onPress={() => {
|
|
||||||
editor?.commands.redo();
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
borderWidth: 0,
|
|
||||||
borderRadius: 100,
|
|
||||||
color: "var(--nn_primary_icon)",
|
|
||||||
marginRight: 10,
|
|
||||||
width: 39,
|
|
||||||
height: 39,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
position: "relative"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ArrowURightTopIcon
|
|
||||||
color={
|
|
||||||
!hasRedo
|
|
||||||
? "var(--nn_secondary_background)"
|
|
||||||
: "var(--nn_primary_paragraph)"
|
|
||||||
}
|
|
||||||
size={25 * settings.fontScale}
|
|
||||||
style={{
|
|
||||||
position: "absolute"
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
{!settings.premium && (
|
{!settings.premium && (
|
||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
@@ -266,32 +190,6 @@ function Header({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
|
||||||
onPress={() => {
|
|
||||||
editor?.commands.startSearch();
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
borderWidth: 0,
|
|
||||||
borderRadius: 100,
|
|
||||||
color: "var(--nn_primary_icon)",
|
|
||||||
marginRight: 10,
|
|
||||||
width: 39,
|
|
||||||
height: 39,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
position: "relative"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MagnifyIcon
|
|
||||||
size={28 * settings.fontScale}
|
|
||||||
style={{
|
|
||||||
position: "absolute"
|
|
||||||
}}
|
|
||||||
color="var(--nn_primary_paragraph)"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{settings.deviceMode !== "mobile" && !settings.fullscreen ? (
|
{settings.deviceMode !== "mobile" && !settings.fullscreen ? (
|
||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
@@ -342,8 +240,9 @@ function Header({
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: "2.5px solid var(--nn_primary_icon)",
|
border: "2.5px solid var(--nn_primary_icon)",
|
||||||
width: 20 * settings.fontScale,
|
width: 19 * settings.fontScale,
|
||||||
height: 20 * settings.fontScale,
|
height: 19 * settings.fontScale,
|
||||||
|
minWidth: 19 * settings.fontScale,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
@@ -417,6 +316,102 @@ function Header({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
editor?.commands.undo();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 100,
|
||||||
|
color: "var(--nn_primary_icon)",
|
||||||
|
marginRight: 10,
|
||||||
|
width: 39,
|
||||||
|
height: 39,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
position: "relative"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ArrowULeftTopIcon
|
||||||
|
color={
|
||||||
|
!hasUndo
|
||||||
|
? "var(--nn_secondary_border)"
|
||||||
|
: "var(--nn_primary_paragraph)"
|
||||||
|
}
|
||||||
|
size={25 * settings.fontScale}
|
||||||
|
style={{
|
||||||
|
position: "absolute"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
editor?.commands.redo();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 100,
|
||||||
|
color: "var(--nn_primary_icon)",
|
||||||
|
marginRight: 10,
|
||||||
|
width: 39,
|
||||||
|
height: 39,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
position: "relative"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ArrowURightTopIcon
|
||||||
|
color={
|
||||||
|
!hasRedo
|
||||||
|
? "var(--nn_secondary_border)"
|
||||||
|
: "var(--nn_primary_paragraph)"
|
||||||
|
}
|
||||||
|
size={25 * settings.fontScale}
|
||||||
|
style={{
|
||||||
|
position: "absolute"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
editor?.commands.startSearch();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderWidth: 0,
|
||||||
|
borderRadius: 100,
|
||||||
|
color: "var(--nn_primary_icon)",
|
||||||
|
marginRight: 10,
|
||||||
|
width: 39,
|
||||||
|
height: 39,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
position: "relative"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MagnifyIcon
|
||||||
|
size={28 * settings.fontScale}
|
||||||
|
style={{
|
||||||
|
position: "absolute"
|
||||||
|
}}
|
||||||
|
color="var(--nn_primary_paragraph)"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
value="toc"
|
value="toc"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -271,8 +271,8 @@ export function useEditorController({
|
|||||||
case "native:status":
|
case "native:status":
|
||||||
break;
|
break;
|
||||||
case "native:keyboardShown":
|
case "native:keyboardShown":
|
||||||
if (editor?.current) {
|
if (editor) {
|
||||||
scrollIntoView(editor?.current as any);
|
scrollIntoView(editor as any);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "native:attachment-data":
|
case "native:attachment-data":
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { Dispatch, MutableRefObject, RefObject, SetStateAction } from "react";
|
|||||||
import { EditorController } from "../hooks/useEditorController";
|
import { EditorController } from "../hooks/useEditorController";
|
||||||
|
|
||||||
globalThis.sessionId = "notesnook-editor";
|
globalThis.sessionId = "notesnook-editor";
|
||||||
|
globalThis.pendingResolvers = {};
|
||||||
|
|
||||||
globalThis.pendingResolvers = {};
|
globalThis.pendingResolvers = {};
|
||||||
export function randId(prefix: string) {
|
export function randId(prefix: string) {
|
||||||
@@ -80,6 +81,7 @@ declare global {
|
|||||||
var noToolbar: boolean;
|
var noToolbar: boolean;
|
||||||
var noHeader: boolean;
|
var noHeader: boolean;
|
||||||
function toBlobURL(dataurl: string, id?: string): string | undefined;
|
function toBlobURL(dataurl: string, id?: string): string | undefined;
|
||||||
|
var pendingResolvers: { [name: string]: (value: any) => void };
|
||||||
/**
|
/**
|
||||||
* Id of current session
|
* Id of current session
|
||||||
*/
|
*/
|
||||||
@@ -187,9 +189,16 @@ export const EventTypes = {
|
|||||||
tabsChanged: "editor-events:tabs-changed",
|
tabsChanged: "editor-events:tabs-changed",
|
||||||
showTabs: "editor-events:show-tabs",
|
showTabs: "editor-events:show-tabs",
|
||||||
tabFocused: "editor-events:tab-focused",
|
tabFocused: "editor-events:tab-focused",
|
||||||
toc: "editor-events:toc"
|
toc: "editor-events:toc",
|
||||||
|
createInternalLink: "editor-events:create-internal-link"
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export function randId(prefix: string) {
|
||||||
|
return Math.random()
|
||||||
|
.toString(36)
|
||||||
|
.replace("0.", prefix || "");
|
||||||
|
}
|
||||||
|
|
||||||
export function isReactNative(): boolean {
|
export function isReactNative(): boolean {
|
||||||
return !!window.ReactNativeWebView;
|
return !!window.ReactNativeWebView;
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/editor/package-lock.json
generated
3
packages/editor/package-lock.json
generated
@@ -105,6 +105,9 @@
|
|||||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||||
"async-mutex": "^0.3.2",
|
"async-mutex": "^0.3.2",
|
||||||
"dayjs": "1.11.9",
|
"dayjs": "1.11.9",
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.1.0",
|
||||||
"entities": "^4.3.1",
|
"entities": "^4.3.1",
|
||||||
"fuzzyjs": "^5.0.1",
|
"fuzzyjs": "^5.0.1",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
|
|||||||
Reference in New Issue
Block a user