Compare commits

..

8 Commits

Author SHA1 Message Date
ammarahm-ed
c1708260b8 mobile: fix tag not updated on list item on rename 2023-04-07 14:45:30 +05:00
ammarahm-ed
45ebf0670f mobile: show error when note is locked 2023-04-07 02:22:49 +05:00
ammarahm-ed
9cfaa90232 mobile: use text exporter from core 2023-04-07 02:22:49 +05:00
ammarahm-ed
edf4a248ed web: remove unnecessary param passed to export 2023-04-07 02:22:49 +05:00
ammarahm-ed
14d7ec6b4e core: allow exports with custom content 2023-04-07 02:22:49 +05:00
Ammar Ahmed
cd2ca94c3d mobile: Fix crash when leaving note after search (#2289) 2023-04-07 01:10:52 +05:00
Abdullah Atta
f1609aaa46 editor: do not convert \n characters to paragraphs 2023-04-06 01:40:55 +05:00
ammarahm-ed
851364c0bf mobile: release 2.4.11 2023-04-05 02:45:02 +05:00
26 changed files with 179 additions and 166 deletions

View File

@@ -81,10 +81,20 @@ function getNotebook(item) {
return items;
}
function getTags(item) {
const noteTags = item.tags?.slice(0, 3) || [];
const tags = [];
for (const tagName of noteTags) {
const tag = db.tags.tag(tagName);
if (!tag) continue;
tags.push(tag);
}
return tags;
}
const NoteItem = ({
item,
isTrash,
tags,
dateBy = "dateCreated",
noOpen = false
}) => {
@@ -100,6 +110,7 @@ const NoteItem = ({
const reminders = db.relations.from(item, "reminder");
const reminder = getUpcomingReminder(reminders);
const noteColor = COLORS_NOTE[item.color?.toLowerCase()];
const tags = getTags(item);
return (
<>
<View

View File

@@ -100,7 +100,7 @@ export const openNote = async (item, isTrash, setSelectedItem, isSheet) => {
};
export const NoteWrapper = React.memo(
function NoteWrapper({ item, index, tags, dateBy, isSheet }) {
function NoteWrapper({ item, index, dateBy, isSheet }) {
const isTrash = item.type === "trash";
const setSelectedItem = useSelectionStore((state) => state.setSelectedItem);
@@ -113,7 +113,7 @@ export const NoteWrapper = React.memo(
isSheet={isSheet}
item={item}
>
<NoteItem item={item} dateBy={dateBy} tags={tags} isTrash={isTrash} />
<NoteItem item={item} dateBy={dateBy} isTrash={isTrash} />
</SelectionWrapper>
);
},
@@ -125,10 +125,6 @@ export const NoteWrapper = React.memo(
return false;
}
if (JSON.stringify(prev.tags) !== JSON.stringify(next.tags)) {
return false;
}
if (prev.item !== next.item) {
return false;
}

View File

@@ -57,25 +57,10 @@ const RenderItem = ({ item, index, type, ...restArgs }) => {
const dateBy =
groupOptions.sortBy !== "title" ? groupOptions.sortBy : "dateEdited";
const totalNotes = getTotalNotes(item);
const tags =
item.tags
?.slice(0, 3)
?.map((item) => {
let tag = db.tags.tag(item);
if (!tag) return null;
return {
title: tag.title,
id: tag.id,
alias: tag.alias
};
})
.filter((t) => t !== null) || [];
return (
<Item
item={item}
tags={tags}
dateBy={dateBy}
index={index}
type={type}
@@ -168,7 +153,6 @@ const List = ({
minWidth: 1
};
const _keyExtractor = (item) => item.id || item.title;
const ListView = ScrollComponent ? ScrollComponent : FlashList;
return (
<>

View File

@@ -170,9 +170,17 @@ export const useActions = ({ close = () => null, item }) => {
checkNotifPinned();
return;
}
if (item.locked) return;
let html = await db.notes.note(item.id).content();
let text = await toTXT(item);
if (item.locked) {
ToastEvent.show({
heading: "Note is locked",
type: "error",
message: "Locked notes cannot be pinned to notifications",
context: "local"
});
return;
}
let text = await toTXT(item, false);
let html = text.replace(/\n/g, "<br />");
Notifications.displayNotification({
title: item.title,
message: item.headline || text,
@@ -373,9 +381,11 @@ export const useActions = ({ close = () => null, item }) => {
positivePress: async (value) => {
if (!value || value === "" || value.trimStart().length == 0) return;
await db.tags.rename(item.id, db.tags.sanitize(value));
useTagStore.getState().setTags();
useMenuStore.getState().setMenuPins();
Navigation.queueRoutesForUpdate();
setImmediate(() => {
useTagStore.getState().setTags();
useMenuStore.getState().setMenuPins();
Navigation.queueRoutesForUpdate();
});
},
input: true,
defaultValue: alias,
@@ -418,24 +428,16 @@ export const useActions = ({ close = () => null, item }) => {
? "This reminder will be removed"
: "This tag will be removed from all notes.",
positivePress: async () => {
const routes = [];
routes.push(
"TaggedNotes",
"ColoredNotes",
"Notes",
"NotesPage",
"Reminders",
"Favorites"
);
if (item.type === "reminder") {
await db.reminders.remove(item.id);
} else {
await db.tags.remove(item.id);
useTagStore.getState().setTags();
routes.push("Tags");
}
Navigation.queueRoutesForUpdate();
useRelationStore.getState().update();
setImmediate(() => {
useTagStore.getState().setTags();
Navigation.queueRoutesForUpdate();
useRelationStore.getState().update();
});
},
positiveText: "Delete",
positiveType: "errorShade"
@@ -497,12 +499,14 @@ export const useActions = ({ close = () => null, item }) => {
negativeText: "Cancel",
positivePress: async () => {
await db.trash.delete(item.id);
Navigation.queueRoutesForUpdate();
useSelectionStore.getState().setSelectionMode(false);
ToastEvent.show({
heading: "Permanantly deleted items",
type: "success",
context: "local"
setImmediate(() => {
Navigation.queueRoutesForUpdate();
useSelectionStore.getState().setSelectionMode(false);
ToastEvent.show({
heading: "Permanantly deleted items",
type: "success",
context: "local"
});
});
},
positiveType: "errorShade"
@@ -520,6 +524,15 @@ export const useActions = ({ close = () => null, item }) => {
}
async function exportNote() {
if (item.locked) {
ToastEvent.show({
heading: "Note is locked",
type: "error",
message: "Locked notes cannot be exported",
context: "local"
});
return;
}
ExportNotesSheet.present([item]);
}
@@ -623,7 +636,7 @@ export const useActions = ({ close = () => null, item }) => {
id: "pin-to-notifications",
title:
notifPinned !== null
? "Unpin from Notifications"
? "Unpin from notifications"
: "Pin to notifications",
icon: "message-badge-outline",
on: notifPinned !== null,

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import React, { useEffect, useState } from "react";
import { View } from "react-native";
import Animated, { FadeInDown, FadeOutDown } from "react-native-reanimated";
import Animated, { FadeInDown } from "react-native-reanimated";
import DelayLayout from "../../components/delay-layout";
import BaseDialog from "../../components/dialog/base-dialog";
import { ProgressBarComponent } from "../../components/ui/svg/lazy";
@@ -75,57 +75,55 @@ const Home = ({
return (
<DelayLayout delay={300} type="settings">
<View>
{loading && (
//@ts-ignore // Migrate to typescript required.
<BaseDialog animated={false} bounce={false} visible={true}>
{loading && (
//@ts-ignore // Migrate to typescript required.
<BaseDialog animated={false} bounce={false} visible={true}>
<View
style={{
width: "100%",
height: "100%",
backgroundColor: colors.bg,
justifyContent: "center",
alignItems: "center"
}}
>
<Heading color={colors.pri} size={SIZE.lg}>
Logging out
</Heading>
<Paragraph color={colors.icon}>
Please wait while we log out and clear app data.
</Paragraph>
<View
style={{
width: "100%",
height: "100%",
backgroundColor: colors.bg,
justifyContent: "center",
alignItems: "center"
flexDirection: "row",
width: 100,
marginTop: 15
}}
>
<Heading color={colors.pri} size={SIZE.lg}>
Logging out
</Heading>
<Paragraph color={colors.icon}>
Please wait while we log out and clear app data.
</Paragraph>
<View
style={{
flexDirection: "row",
width: 100,
marginTop: 15
}}
>
<ProgressBarComponent
height={5}
width={100}
animated={true}
useNativeDriver
indeterminate
indeterminateAnimationDuration={2000}
unfilledColor={colors.nav}
color={colors.accent}
borderWidth={0}
/>
</View>
<ProgressBarComponent
height={5}
width={100}
animated={true}
useNativeDriver
indeterminate
indeterminateAnimationDuration={2000}
unfilledColor={colors.nav}
color={colors.accent}
borderWidth={0}
/>
</View>
</BaseDialog>
)}
</View>
</BaseDialog>
)}
<Animated.FlatList
entering={FadeInDown}
exiting={FadeOutDown}
data={settingsGroups}
keyExtractor={keyExtractor}
ListFooterComponent={<View style={{ height: 200 }} />}
renderItem={renderItem}
/>
</View>
<Animated.FlatList
entering={FadeInDown}
data={settingsGroups}
windowSize={1}
keyExtractor={keyExtractor}
ListFooterComponent={<View style={{ height: 200 }} />}
renderItem={renderItem}
/>
</DelayLayout>
);
};

View File

@@ -42,12 +42,12 @@ export const SectionGroup = ({ item }: { item: SettingSection }) => {
color={colors.accent}
size={SIZE.xs}
>
{item.name.toUpperCase()}
{(item.name as string).toUpperCase()}
</Heading>
) : null}
{item.sections?.map((item) => (
<SectionItem key={item.name} item={item} />
<SectionItem key={item.name as string} item={item} />
))}
</View>
);

View File

@@ -87,7 +87,7 @@ export const TrashIntervalSelector = () => {
>
{[-1, 7, 30, 365].map((item) => (
<MenuItem
key={item.name}
key={item.toString()}
onPress={async () => {
if (item === -1) {
await PremiumService.verify(() => {

View File

@@ -35,6 +35,7 @@ import { eOnNewTopicAdded } from "../utils/events";
import { rootNavigatorRef, tabBarRef } from "../utils/global-refs";
import { eSendEvent } from "./event-manager";
import SettingsService from "./settings";
import SearchService from "./search";
/**
* Routes that should be updated on focus
@@ -86,7 +87,8 @@ const routeUpdateFunctions: {
ColoredNotes: (params) => eSendEvent("ColoredNotes", params),
TopicNotes: (params) => eSendEvent("TopicNotes", params),
Monographs: (params) => eSendEvent("Monographs", params),
Reminders: () => useReminderStore.getState().setReminders()
Reminders: () => useReminderStore.getState().setReminders(),
Search: () => SearchService.updateAndSearch()
};
function clearRouteFromQueue(routeName: RouteName) {
@@ -113,7 +115,7 @@ function queueRoutesForUpdate(...routesToUpdate: RouteName[]) {
: (Object.keys(routeNames) as (keyof RouteParams)[]);
const currentScreen = useNavigationStore.getState().currentScreen;
if (routes.indexOf(currentScreen.name) > -1) {
routeUpdateFunctions[currentScreen.name]();
routeUpdateFunctions[currentScreen.name]?.();
clearRouteFromQueue(currentScreen.name);
// Remove focused screen from queue
routes.splice(routes.indexOf(currentScreen.name), 1);
@@ -129,7 +131,7 @@ function navigate<T extends RouteName>(
useNavigationStore.getState().update(screen, !!params?.canGoBack);
if (screen.name === "Notebook") routeUpdateFunctions["Notebook"](params);
if (screen.name.endsWith("Notes") && screen.name !== "Notes")
routeUpdateFunctions[screen.name](params);
routeUpdateFunctions[screen.name]?.(params);
//@ts-ignore Not sure how to fix this for now ignore it.
rootNavigatorRef.current?.navigate<RouteName>(screen.name, params);
}

View File

@@ -26,7 +26,7 @@ let searchInformation = {
placeholder: "Search in all notes",
data: [],
type: "notes",
get: () => null
get: () => []
};
let keyword = null;

View File

@@ -145,19 +145,12 @@ export function getTotalNotes(item) {
return db.notebooks.notebook(item.id)?.totalNotes || 0;
}
export async function toTXT(note, notitle) {
export async function toTXT(note, template = true) {
let text;
if (note.locked) {
text = note.content.data;
text = await db.notes.note(note.id).export("txt", note.content, template);
} else {
text = await db.notes.note(note.id).content();
}
htmlToText = htmlToText || require("html-to-text");
text = htmlToText.convert(text, {
selectors: [{ selector: "img", format: "skip" }]
});
if (!notitle) {
text = `${note.title}\n \n ${text}`;
text = await db.notes.note(note.id).export("txt", undefined, template);
}
return text;
}

View File

@@ -55,12 +55,13 @@ describe("NOTE TESTS", () => {
await prepare();
let note = await createNote();
await tapById(notesnook.listitem.menu);
await tapById("icon-Favorite");
await tapById("icon-favorite");
await visibleById("icon-star");
await navigate("Favorites");
await visibleByText(note.body);
await sleep(500);
await tapById(notesnook.listitem.menu);
await tapById("icon-Favorite");
await tapById("icon-favorite");
await expect(element(by.text(note.body))).not.toBeVisible();
await navigate("Notes");
});
@@ -69,11 +70,11 @@ describe("NOTE TESTS", () => {
await prepare();
await createNote();
await tapById(notesnook.listitem.menu);
await tapById("icon-Pin");
await tapById("icon-pin");
await visibleByText("Pinned");
await visibleById("icon-pinned");
await tapById(notesnook.listitem.menu);
await tapById("icon-Pin");
await tapById("icon-pin");
expect(element(by.id("icon-pinned"))).not.toBeVisible();
});
@@ -81,11 +82,12 @@ describe("NOTE TESTS", () => {
await prepare();
await createNote();
await tapById(notesnook.listitem.menu);
await tapById("icon-PinToNotif");
await visibleByText("Unpin from Notifications");
await tapById("icon-pin-to-notifications");
await visibleByText("Unpin from notifications");
await sleep(500);
await tapById("icon-PinToNotif");
await visibleByText("Pin to Notifications");
await tapById("icon-pin-to-notifications");
await sleep(500);
await visibleByText("Pin to notifications");
});
// it("Copy note", async () => {
@@ -100,7 +102,7 @@ describe("NOTE TESTS", () => {
await prepare();
await createNote();
await tapById(notesnook.listitem.menu);
await tapById("icon-Export");
await tapById("icon-export");
await visibleByText("PDF");
});
@@ -122,7 +124,7 @@ describe("NOTE TESTS", () => {
await prepare();
await createNote();
await tapById(notesnook.listitem.menu);
await tapById("icon-Delete");
await tapById("icon-delete");
await navigate("Trash");
await tapById(notesnook.listitem.menu);
await tapByText("Restore note");

View File

@@ -17,13 +17,15 @@ 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 { notesnook } from "../test.ids";
import {
tapById,
visibleByText,
createNote,
prepare,
elementById,
sleep
sleep,
tapByText
} from "./utils";
describe("Search", () => {
@@ -34,6 +36,10 @@ describe("Search", () => {
await sleep(300);
await elementById("search-input").typeText("n");
await sleep(1000);
await tapByText(note.body);
await sleep(1000);
await device.pressBack();
await device.pressBack();
await visibleByText(note.body);
});
});

View File

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

View File

@@ -1,7 +1,7 @@
- Added support for sorting topics in topics sheet
- Navigation Bar in app now follows app theme
- Splashscreen logo quality in dark mode has been improved
- Fix topic title goes into multiple lines if long
- Fix reminder date picker not allowing to pick a date from past
- New and improved share extension with support for organizing notes
with tags & notebooks!
- Improved UX for topics sheet in Notebooks
- Improved editor performance
- Many bug fixes and minor improvements
Thank you for using Notesnook!

View File

@@ -993,7 +993,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2033;
CURRENT_PROJECT_VERSION = 2034;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1067,7 +1067,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 2.4.10;
MARKETING_VERSION = 2.4.11;
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 = 2033;
CURRENT_PROJECT_VERSION = 2034;
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.10;
MARKETING_VERSION = 2.4.11;
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 = 2033;
CURRENT_PROJECT_VERSION = 2034;
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.10;
MARKETING_VERSION = 2.4.11;
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 = 2033;
CURRENT_PROJECT_VERSION = 2034;
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.10;
MARKETING_VERSION = 2.4.11;
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 = 2033;
CURRENT_PROJECT_VERSION = 2034;
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.10;
MARKETING_VERSION = 2.4.11;
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 = 2033;
CURRENT_PROJECT_VERSION = 2034;
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.10;
MARKETING_VERSION = 2.4.11;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -1,6 +1,7 @@
- Added support for sorting topics in topics sheet
- Fixed topics sheet is hard to swipe up from bottom
- Fix topic title goes into multiple lines if long
- Fix reminder date picker not allowing to pick a date from past
- New and improved share extension with support for organizing notes
with tags & notebooks!
- Improved UX for Topics sheet in Notebooks
- Improved editor performance
- Many bug fixes and minor improvements
Thank you for using Notesnook!

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "2.4.10",
"version": "2.4.11",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -34,4 +34,4 @@
"@notesnook/editor": "*",
"@notesnook/editor-mobile": "*"
}
}
}

View File

@@ -57,7 +57,7 @@ export async function exportNotes(
if (format === "pdf") {
const note = db.notes?.note(noteIds[0]);
if (!note) return false;
const html = await note.export("html", null);
const html = await note.export("html");
if (!html) return false;
return await exportToPDF(note.title, html);
}
@@ -73,7 +73,7 @@ export async function exportNotes(
text: `Exporting "${note.title}"...`
});
const content = await note.export(format, null).catch((e: Error) => {
const content = await note.export(format).catch((e: Error) => {
showToast("error", e.message);
});
if (!content) continue;

View File

@@ -162,7 +162,6 @@ function TipTap(props: TipTapProps) {
isMobile: isMobile || false,
element: editorContainer,
editable: !readonly,
parseOptions: { preserveWhitespace: "full" },
content,
autofocus: "start",
onFocus,
@@ -383,7 +382,7 @@ function toIEditor(editor: Editor): IEditor {
tr.setMeta("preventSave", true);
return true;
})
.setContent(content, true, { preserveWhitespace: "full" })
.setContent(content, true, { preserveWhitespace: true })
.setTextSelection({
from,
to

View File

@@ -79,10 +79,12 @@ export default class Note {
/**
*
* @param {"html"|"md"|"txt"} format - Format to export into
* @param {string?} rawContent - Use this raw content instead of generating itself
* @param {string} [contentItem=undefined]
* @param {boolean} [template=true]
* @param {string} [rawHTML=undefined] rawHTML - Use this raw content instead of generating itself
* @returns {Promise<string | false | undefined>}
*/
async export(to = "html", rawContent) {
async export(to = "html", contentItem, template = true, rawHTML) {
if (to !== "txt" && !(await checkIsUserPremium(CHECK_IDS.noteExport)))
return false;
@@ -94,7 +96,8 @@ export default class Note {
createdOn: formatDate(this.data.dateCreated),
tags: this.tags.join(", ")
};
const contentItem = await this._db.content.raw(this._note.contentId);
contentItem =
contentItem || (await this._db.content.raw(this._note.contentId));
if (!contentItem) return false;
const { data, type } = await this._db.content.downloadMedia(
`export-${this.id}`,
@@ -105,14 +108,20 @@ export default class Note {
switch (to) {
case "html":
templateData.content = rawContent || content.toHTML();
return HTMLBuilder.buildHTML(templateData);
templateData.content = rawHTML || content.toHTML();
return template
? HTMLBuilder.buildHTML(templateData)
: templateData.content;
case "txt":
templateData.content = rawContent || content.toTXT();
return TextBuilder.buildText(templateData);
templateData.content = rawHTML || content.toTXT();
return template
? TextBuilder.buildText(templateData)
: templateData.content;
case "md":
templateData.content = rawContent || content.toMD();
return MarkdownBuilder.buildMarkdown(templateData);
templateData.content = rawHTML || content.toMD();
return template
? MarkdownBuilder.buildMarkdown(templateData)
: templateData.content;
default:
throw new Error("Export format not supported.");
}

View File

@@ -102,7 +102,6 @@ const Tiptap = ({
editorProps: {
editable: () => !settings.readonly
},
parseOptions: { preserveWhitespace: "full" },
content: global.editorController?.content?.current,
isMobile: true,
isKeyboardOpen: settings.keyboardShown,

View File

@@ -118,7 +118,7 @@ export function useEditorController(update: () => void): EditorController {
if (!editor) break;
const { from, to } = editor.state.selection;
editor?.commands.setContent(htmlContentRef.current, false, {
preserveWhitespace: "full"
preserveWhitespace: true
});
editor.commands.setTextSelection({
from,

View File

@@ -630,7 +630,7 @@ function indentOnEnter(editor: Editor, $from: ResolvedPos, options: Indent) {
return editor
.chain()
.insertContent(`${newline}${indentation}`, {
parseOptions: { preserveWhitespace: "full" }
parseOptions: { preserveWhitespace: true }
})
.focus()
.run();

View File

@@ -57,7 +57,7 @@ test("codeblocks should get highlighted after pasting", async () => {
});
editor.commands.setContent(CODEBLOCKS_HTML, true, {
preserveWhitespace: "full"
preserveWhitespace: true
});
await new Promise((resolve) => setTimeout(resolve, 100));

View File

@@ -241,7 +241,8 @@ const useTiptap = (
editor.storage.portalProviderAPI = PortalProviderAPI;
if (onBeforeCreate) onBeforeCreate({ editor });
},
injectCSS: false
injectCSS: false,
parseOptions: { preserveWhitespace: true }
}),
[
onPreviewAttachment,

View File

@@ -39,7 +39,6 @@ export function createEditor<TNodes extends string>(
const editor = new Editor({
element,
content: initialContent,
parseOptions: { preserveWhitespace: "full" },
extensions: [
StarterKit.configure({
bulletList: false,