mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 18:19:38 +02:00
Compare commits
24 Commits
web/defaul
...
fix-loadin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d9df5030c | ||
|
|
af014cf8c1 | ||
|
|
1ddd7b1e6e | ||
|
|
9ef0179566 | ||
|
|
38690d18d4 | ||
|
|
c07f5393f6 | ||
|
|
406c63721d | ||
|
|
97f3e02f59 | ||
|
|
5c6564f00b | ||
|
|
605e75efb3 | ||
|
|
496f9ba340 | ||
|
|
f98283f2dd | ||
|
|
2d32e85a64 | ||
|
|
1a56a22a33 | ||
|
|
c85204d0c1 | ||
|
|
1d8a958eaf | ||
|
|
b52f70d57d | ||
|
|
12687dae7b | ||
|
|
c53c3167d8 | ||
|
|
60df472d53 | ||
|
|
67fe25bc8b | ||
|
|
44a7aed308 | ||
|
|
f22937e1eb | ||
|
|
c816f8b15b |
@@ -113,7 +113,7 @@ jobs:
|
||||
keyStorePassword: ${{ secrets.KEY_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "36.0.0"
|
||||
|
||||
- name: Build apks for Github release
|
||||
run: yarn release:android
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
keyStorePassword: ${{ secrets.PUBLIC_KEY_PASSWORD }}
|
||||
keyPassword: ${{ secrets.PUBLIC_KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "36.0.0"
|
||||
|
||||
- name: Rename apk files
|
||||
run: |
|
||||
|
||||
4
.github/workflows/android.publish.yml
vendored
4
.github/workflows/android.publish.yml
vendored
@@ -113,7 +113,7 @@ jobs:
|
||||
keyStorePassword: ${{ secrets.KEY_PASSWORD }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "36.0.0"
|
||||
|
||||
- name: Build apks for Github release
|
||||
run: yarn release:android
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
keyStorePassword: ${{ secrets.PUBLIC_KEY_PASSWORD }}
|
||||
keyPassword: ${{ secrets.PUBLIC_KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "36.0.0"
|
||||
|
||||
- name: Rename apk files
|
||||
run: |
|
||||
|
||||
4
apps/desktop/package-lock.json
generated
4
apps/desktop/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/cjs/index.js",
|
||||
|
||||
@@ -125,7 +125,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 3090
|
||||
versionCode 3091
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
- Add title and date clipped to web clips
|
||||
- Add notebooks, tags and colors to Home Screen Shortcuts
|
||||
- Change day format and use /day in notes
|
||||
- Add Setting to change default editor line height
|
||||
- Set a custom title for monographs
|
||||
- Add webpage title and date clipped to web clips
|
||||
- Configure Week to start from Sunday or Monday
|
||||
- Change Note's creation date from properties
|
||||
- Set expiry date for notes for auto-deletion
|
||||
- Fix tag and notebook properties cannot be accessed from shortcuts
|
||||
- Fix editor features remain locked after login
|
||||
- Temporarily disable password changing and forgot password features
|
||||
- Note history now includes note title changes
|
||||
- Other minor bug fixes and improvements
|
||||
- Change Note's creation date
|
||||
- Set expiry date on notes
|
||||
- Temporarily disable password change and recovery options
|
||||
- Note history now includes note title
|
||||
- Minor bug fixes
|
||||
|
||||
Thank you for using Notesnook!
|
||||
|
||||
@@ -167,14 +167,16 @@ const ColorPicker = ({
|
||||
);
|
||||
if (!title.current)
|
||||
return ToastManager.error(
|
||||
new Error(strings.allFieldsRequired())
|
||||
new Error(strings.allFieldsRequired()),
|
||||
"color-picker"
|
||||
);
|
||||
const exists = await db.colors.all.find((v) =>
|
||||
v.and([v(`colorCode`, "==", selectedColor)])
|
||||
);
|
||||
if (exists)
|
||||
return ToastManager.error(
|
||||
new Error(strings.colorExists(selectedColor))
|
||||
new Error(strings.colorExists(selectedColor)),
|
||||
"color-picker"
|
||||
);
|
||||
const id = await db.colors.add({
|
||||
title: title.current,
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function NotePreview({
|
||||
content,
|
||||
note
|
||||
}: {
|
||||
session: HistorySession & { session: string };
|
||||
session?: HistorySession & { session: string };
|
||||
content:
|
||||
| Partial<
|
||||
NoteContent<boolean> & {
|
||||
@@ -81,24 +81,26 @@ export default function NotePreview({
|
||||
eSendEvent(eCloseSheet);
|
||||
return;
|
||||
}
|
||||
await db.noteHistory.restore(session.id);
|
||||
if (useTabStore.getState().hasTabForNote(session?.noteId)) {
|
||||
const note = editorController.current.note.current[session?.noteId];
|
||||
if (note) {
|
||||
eSendEvent(eOnLoadNote, {
|
||||
item: note,
|
||||
forced: true
|
||||
});
|
||||
if (session) {
|
||||
await db.noteHistory.restore(session.id);
|
||||
if (useTabStore.getState().hasTabForNote(session?.noteId)) {
|
||||
const note = editorController.current.note.current[session?.noteId];
|
||||
if (note) {
|
||||
eSendEvent(eOnLoadNote, {
|
||||
item: note,
|
||||
forced: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
eSendEvent(eCloseSheet, "note_history");
|
||||
eSendEvent(eCloseSheet);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
eSendEvent(eCloseSheet, "note_history");
|
||||
eSendEvent(eCloseSheet);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
|
||||
ToastManager.show({
|
||||
heading: strings.noteRestoredFromHistory(),
|
||||
type: "success"
|
||||
});
|
||||
ToastManager.show({
|
||||
heading: strings.noteRestoredFromHistory(),
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -166,7 +168,7 @@ export default function NotePreview({
|
||||
currentContent?.data || "<p></p>",
|
||||
content.data as string
|
||||
),
|
||||
id: session?.noteId
|
||||
id: session?.noteId || note.id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,7 +1169,7 @@ export const useActions = ({
|
||||
id: "expiry-date",
|
||||
title: item.expiryDate ? strings.unsetExpiry() : strings.setExpiry(),
|
||||
icon: item.expiryDate ? "bomb-off" : "bomb",
|
||||
locked: features?.expiringNotes?.isAllowed,
|
||||
locked: !features?.expiringNotes?.isAllowed,
|
||||
onPress: async () => {
|
||||
if (item.expiryDate) {
|
||||
await db.notes.setExpiryDate(null, item.id);
|
||||
|
||||
@@ -73,15 +73,6 @@ const RecurringModes = {
|
||||
const WeekDays = [0, 1, 2, 3, 4, 5, 6];
|
||||
const WeekDaysMon = [1, 2, 3, 4, 5, 6, 0];
|
||||
const MonthDays = new Array(31).fill(true);
|
||||
const WeekDayNames = {
|
||||
0: "Sunday",
|
||||
1: "Monday",
|
||||
2: "Tuesday",
|
||||
3: "Wednesday",
|
||||
4: "Thursday",
|
||||
5: "Friday",
|
||||
6: "Saturday"
|
||||
};
|
||||
|
||||
const ReminderNotificationModes = {
|
||||
Silent: "silent",
|
||||
@@ -153,7 +144,8 @@ export default function AddReminder(props: NavigationProps<"AddReminder">) {
|
||||
const isSecondLast = index === selectedDays.length - 2;
|
||||
const joinWith = isSecondLast ? " & " : isLast ? "" : ", ";
|
||||
return recurringMode === RecurringModes.Week
|
||||
? strings.weekDayNames[day as keyof typeof WeekDayNames]() + joinWith
|
||||
? strings.weekDayNames[day as keyof typeof strings.weekDayNames]() +
|
||||
joinWith
|
||||
: `${day}${nth(day)} ${joinWith}`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
@@ -25,7 +25,8 @@ import React, {
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useLayoutEffect,
|
||||
useRef
|
||||
useRef,
|
||||
useState
|
||||
} from "react";
|
||||
import { Platform, ViewStyle } from "react-native";
|
||||
import WebView from "react-native-webview";
|
||||
@@ -109,17 +110,20 @@ const Editor = React.memo(
|
||||
noToolbar,
|
||||
noHeader
|
||||
});
|
||||
const renderKey = useRef(randId("editor-id") + editorId);
|
||||
const [renderKey, setRenderKey] = useState(
|
||||
randId("editor-id") + editorId
|
||||
);
|
||||
useImperativeHandle(ref, () => ({
|
||||
get: () => editor
|
||||
}));
|
||||
useLockedNoteHandler();
|
||||
|
||||
const onError = useCallback(() => {
|
||||
renderKey.current = randId("editor-id") + editorId;
|
||||
setRenderKey(randId("editor-id") + editorId);
|
||||
editor.state.current.ready = false;
|
||||
editor.state.current.initialLoadCalled = false;
|
||||
editor.setLoading(true);
|
||||
}, [editor, editorId]);
|
||||
}, [editor]);
|
||||
|
||||
useEffect(() => {
|
||||
const sub = [eSubscribeEvent(eEditorReset, onError)];
|
||||
@@ -144,7 +148,7 @@ const Editor = React.memo(
|
||||
<WebView
|
||||
testID={notesnook.editor.id}
|
||||
ref={editor.ref}
|
||||
key={renderKey.current}
|
||||
key={renderKey}
|
||||
onRenderProcessGone={onError}
|
||||
nestedScrollEnabled
|
||||
onError={onError}
|
||||
|
||||
@@ -684,8 +684,6 @@ export const useEditor = (
|
||||
lastContentChangeTime.current[item.id] = item.dateEdited;
|
||||
currentNotes.current[item.id] = item;
|
||||
|
||||
if (!currentNotes.current[item.id]) return;
|
||||
|
||||
editorSessionHistory.newSession(item.id);
|
||||
|
||||
await commands.setStatus(
|
||||
@@ -1104,6 +1102,8 @@ export const useEditor = (
|
||||
if (noteId) {
|
||||
const note = await db.notes?.note(noteId);
|
||||
fluidTabsRef.current?.goToPage("editor");
|
||||
loadNoteMutex.cancel();
|
||||
loadNoteMutex.release();
|
||||
if (note) {
|
||||
loadNote({
|
||||
item: note
|
||||
@@ -1111,6 +1111,8 @@ export const useEditor = (
|
||||
}
|
||||
} else {
|
||||
noteId = useTabStore.getState().getCurrentNoteId() || null;
|
||||
loadNoteMutex.cancel();
|
||||
loadNoteMutex.release();
|
||||
if (!noteId) {
|
||||
loadNote({ newNote: true });
|
||||
if (fluidTabsRef.current?.page() === "editor") {
|
||||
|
||||
@@ -193,11 +193,13 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
||||
headerTitle={notebook?.title}
|
||||
loading={loading}
|
||||
CustomLisHeader={
|
||||
<NotebookHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
notebook={notebook!}
|
||||
totalNotes={notes?.placeholders.length || 0}
|
||||
/>
|
||||
notebook ? (
|
||||
<NotebookHeader
|
||||
breadcrumbs={breadcrumbs}
|
||||
notebook={notebook}
|
||||
totalNotes={notes?.placeholders.length || 0}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
placeholder={{
|
||||
title: notebook?.title!,
|
||||
|
||||
@@ -929,7 +929,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
hidden: (current) => (current as VaultStatusType)?.exists,
|
||||
modifer: () => {
|
||||
openVault({
|
||||
item: {},
|
||||
novault: false,
|
||||
title: strings.createVault()
|
||||
});
|
||||
@@ -943,7 +942,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
hidden: (current) => !(current as VaultStatusType)?.exists,
|
||||
modifer: () =>
|
||||
openVault({
|
||||
item: {},
|
||||
changePassword: true,
|
||||
novault: true,
|
||||
title: strings.changeVaultPassword()
|
||||
@@ -957,7 +955,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
hidden: (current) => !(current as VaultStatusType)?.exists,
|
||||
modifer: () => {
|
||||
openVault({
|
||||
item: {},
|
||||
clearVault: true,
|
||||
novault: true,
|
||||
title: strings.clearVault() + "?"
|
||||
@@ -972,7 +969,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
hidden: (current) => !(current as VaultStatusType)?.exists,
|
||||
modifer: () => {
|
||||
openVault({
|
||||
item: {},
|
||||
deleteVault: true,
|
||||
novault: true,
|
||||
title: strings.deleteVault() + "?"
|
||||
@@ -994,7 +990,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
modifer: (current) => {
|
||||
const _current = current as VaultStatusType;
|
||||
openVault({
|
||||
item: {},
|
||||
fingerprintAccess: !_current.biometryEnrolled,
|
||||
revokeFingerprintAccess: _current.biometryEnrolled,
|
||||
novault: true,
|
||||
|
||||
@@ -134,7 +134,7 @@ describe("NOTE TESTS", () => {
|
||||
.run();
|
||||
});
|
||||
|
||||
it.only("Assign colors to a note", async () => {
|
||||
it("Assign colors to a note", async () => {
|
||||
await TestBuilder.create()
|
||||
.prepare()
|
||||
.createNote()
|
||||
|
||||
@@ -21,7 +21,7 @@ import { notesnook } from "../test.ids";
|
||||
import { TestBuilder } from "./utils";
|
||||
|
||||
describe("Sort & filter", () => {
|
||||
it("Sort by date-edited/date-created", async () => {
|
||||
it.only("Sort by date-edited/date-created", async () => {
|
||||
await TestBuilder.create()
|
||||
.prepare()
|
||||
.createNote("Note 1", "Note 1")
|
||||
@@ -34,7 +34,7 @@ describe("Sort & filter", () => {
|
||||
.element(by.web.className("ProseMirror"))
|
||||
.typeText("Edited ", true);
|
||||
})
|
||||
.pressBack(2)
|
||||
.pressBack(1)
|
||||
.waitAndTapById("icon-sort")
|
||||
.wait(500)
|
||||
.waitAndTapByText("Date created")
|
||||
|
||||
@@ -1029,7 +1029,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1135,7 +1135,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1367,7 +1367,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1410,7 +1410,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1453,7 +1453,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1565,7 +1565,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2170;
|
||||
CURRENT_PROJECT_VERSION = 2171;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
|
||||
4
apps/mobile/package-lock.json
generated
4
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.3.13-beta.0",
|
||||
"version": "3.3.13-beta.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.3.13-beta.0",
|
||||
"version": "3.3.13-beta.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.3.13-beta.1",
|
||||
"version": "3.3.13",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
|
||||
2
apps/theme-builder/package-lock.json
generated
2
apps/theme-builder/package-lock.json
generated
@@ -987,7 +987,7 @@
|
||||
},
|
||||
"../web": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.3.8-beta.0",
|
||||
"version": "3.3.8-beta.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
6
apps/web/package-lock.json
generated
6
apps/web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
@@ -507,7 +507,7 @@
|
||||
},
|
||||
"../desktop": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.3.8-beta.0",
|
||||
"version": "3.3.8-beta.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.3.8-beta.1",
|
||||
"version": "3.3.8",
|
||||
"private": true,
|
||||
"main": "./src/app.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
|
||||
@@ -509,7 +509,7 @@ export const AddReminderDialog = DialogManager.register(
|
||||
</Text>
|
||||
) : (
|
||||
<Text variant="subBody" sx={{ mt: 1 }}>
|
||||
{strings.reminderStarts(date.toString(), date.format(timeFormat()))}
|
||||
{strings.reminderStarts(date.format(db.settings.getDateFormat()), date.format(timeFormat()))}
|
||||
</Text>
|
||||
)}
|
||||
</Dialog>
|
||||
|
||||
@@ -22,8 +22,6 @@ import Dialog from "../components/dialog";
|
||||
import { getHomeRoute, hardNavigate } from "../navigation";
|
||||
import { appVersion } from "../utils/version";
|
||||
import Config from "../utils/config";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { ArrowRight, Checkmark, Icon, Warn } from "../components/icons";
|
||||
import { BaseDialogProps, DialogManager } from "../common/dialog-manager";
|
||||
import { strings } from "@notesnook/intl";
|
||||
@@ -93,23 +91,34 @@ const features: Record<FeatureKeys, Feature> = {
|
||||
]
|
||||
: [
|
||||
{
|
||||
title: "Wrapped 2025",
|
||||
title: "Import/export tables as CSV",
|
||||
subtitle:
|
||||
"Notesnook Wrapped 2025 is your personal recap of the year you spent with Notesnook. Available throughout December and accessible from the sidebar, it highlights your activity, stats and how you used Notesnook this year."
|
||||
"You can now import and export CSV files as tables directly in the editor."
|
||||
},
|
||||
{
|
||||
title: "Monograph analytics",
|
||||
title: "Customizable monograph title",
|
||||
subtitle:
|
||||
"Pro users can now see view count analytics for monographs."
|
||||
"You can now set a custom title for your monographs different from the note title."
|
||||
},
|
||||
{
|
||||
title: "Twitter/X embed support",
|
||||
subtitle: "Simply paste the post URL in the Insert Embed dialog."
|
||||
title: "Expiring notes",
|
||||
subtitle:
|
||||
"Set an expiration date for your notes after which they will be automatically moved to trash."
|
||||
},
|
||||
{
|
||||
title: "New keyboard shortcuts",
|
||||
title: "Change note's created date",
|
||||
subtitle:
|
||||
"Use Ctrl/Cmd + Alt/Option + F to open search/replace in the editor. We have also added Ctrl/Cmd + Alt/Option + C for toggling text color."
|
||||
"You can now change a note's created date from the note properties panel."
|
||||
},
|
||||
{
|
||||
title: "Customizable line height",
|
||||
subtitle:
|
||||
"You can now customize the line height in the editor from Settings > Editor."
|
||||
},
|
||||
{
|
||||
title: "Change week starting day",
|
||||
subtitle:
|
||||
"You can now change the starting day of the week from Settings > Behaviour."
|
||||
}
|
||||
],
|
||||
cta: {
|
||||
|
||||
@@ -22,7 +22,7 @@ The following keyboard shortcuts will help you navigate Notesnook faster.
|
||||
| --- | --- | --- | --- |
|
||||
| Next tab | Ctrl Alt → / Ctrl Alt ⇧ → | Ctrl tab | ⌘ tab |
|
||||
| Previous tab | Ctrl Alt ← / Ctrl Alt ⇧ ← | Ctrl ⇧ tab | ⌘ ⇧ tab |
|
||||
| Command palette | Ctrl ⇧ P / Ctrl ⇧ : | Ctrl ⇧ P | ⌘ ⇧ P |
|
||||
| Command palette | Ctrl ⇧ P / Ctrl ⇧ : | Ctrl ⇧ P / Ctrl ⇧ : | ⌘ ⇧ P / ⌘ ⇧ : |
|
||||
| Quick open | Ctrl P | Ctrl P | ⌘ P |
|
||||
| New tab | - | Ctrl T | ⌘ T |
|
||||
| Close active tab | - | Ctrl W | ⌘ W |
|
||||
|
||||
@@ -96,10 +96,7 @@ export const hotkeys = {
|
||||
type: "hotkeys"
|
||||
},
|
||||
openCommandPalette: {
|
||||
keys: normalizeKeys({
|
||||
desktop: ["ctrl+shift+p"],
|
||||
web: ["ctrl+shift+p", "ctrl+shift+:"]
|
||||
}),
|
||||
keys: normalizeKeys(["ctrl+shift+p", "ctrl+shift+:"]),
|
||||
description: "Command palette",
|
||||
category: "Navigation",
|
||||
type: "hotkeys"
|
||||
|
||||
@@ -94,7 +94,7 @@ test(
|
||||
await login(db);
|
||||
await db.monographs.refresh();
|
||||
|
||||
await db.monographs.publish(id);
|
||||
await db.monographs.publish(id, "mono");
|
||||
expect(await db.monographs.all.has(id)).toBeTruthy();
|
||||
|
||||
await db.monographs.unpublish(id);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { databaseTest, delay } from "../__tests__/utils/index.ts";
|
||||
import http from "../src/utils/http.ts";
|
||||
import Constants from "../src/utils/constants.ts";
|
||||
import { writeFileSync } from "node:fs";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const TEST_TIMEOUT = 60 * 1000;
|
||||
const testOptions = { concurrent: true, timeout: TEST_TIMEOUT };
|
||||
@@ -560,7 +561,10 @@ test(
|
||||
});
|
||||
|
||||
// publish on device A
|
||||
const monographId = await deviceA.monographs.publish(noteId);
|
||||
const monographId = await deviceA.monographs.publish(
|
||||
noteId,
|
||||
"Monograph note"
|
||||
);
|
||||
expect(monographId).toBeTruthy();
|
||||
|
||||
// deviceB fetches the monograph
|
||||
@@ -595,9 +599,13 @@ test(
|
||||
});
|
||||
|
||||
// publish with selfDestruct
|
||||
const monographId = await deviceA.monographs.publish(noteId, {
|
||||
selfDestruct: true
|
||||
});
|
||||
const monographId = await deviceA.monographs.publish(
|
||||
noteId,
|
||||
"Self destruct monograph",
|
||||
{
|
||||
selfDestruct: true
|
||||
}
|
||||
);
|
||||
expect(monographId).toBeTruthy();
|
||||
|
||||
// ensure all devices know it's published
|
||||
@@ -649,10 +657,14 @@ test(
|
||||
});
|
||||
|
||||
// publish with password and selfDestruct on device A
|
||||
const monographId = await deviceA.monographs.publish(noteId, {
|
||||
password,
|
||||
selfDestruct: true
|
||||
});
|
||||
const monographId = await deviceA.monographs.publish(
|
||||
noteId,
|
||||
"Protected monograph",
|
||||
{
|
||||
password,
|
||||
selfDestruct: true
|
||||
}
|
||||
);
|
||||
expect(monographId).toBeTruthy();
|
||||
|
||||
// deviceB fetches the monograph
|
||||
|
||||
@@ -314,7 +314,7 @@ test("restoring an old session should replace note's content and title", () =>
|
||||
}
|
||||
));
|
||||
|
||||
test.only("note history item has consistent note and title data between sessions", () =>
|
||||
test("note history item has consistent note and title data between sessions", () =>
|
||||
noteTest({
|
||||
...TEST_NOTE,
|
||||
title: "Test note",
|
||||
|
||||
@@ -28,8 +28,11 @@ import MockDate from "mockdate";
|
||||
import { describe, afterAll, beforeEach, test, expect } from "vitest";
|
||||
import { databaseTest } from "./utils/index.ts";
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc.js";
|
||||
import assert from "assert";
|
||||
|
||||
dayjs.extend(utc);
|
||||
|
||||
describe("format reminder time", () => {
|
||||
afterAll(() => {
|
||||
MockDate.reset();
|
||||
@@ -371,10 +374,10 @@ async function compareReminder(reminder) {
|
||||
.sql()
|
||||
.selectFrom("reminders")
|
||||
.select([
|
||||
createUpcomingReminderTimeQuery(dayjs().format("YYYY-MM-DDTHH:mm")).as(
|
||||
"dueDate"
|
||||
),
|
||||
createIsReminderActiveQuery(dayjs().format("YYYY-MM-DDTHH:mm")).as(
|
||||
createUpcomingReminderTimeQuery(
|
||||
dayjs().utc().format("YYYY-MM-DDTHH:mm")
|
||||
).as("dueDate"),
|
||||
createIsReminderActiveQuery(dayjs.utc().format("YYYY-MM-DDTHH:mm")).as(
|
||||
"isActive"
|
||||
),
|
||||
"id"
|
||||
|
||||
@@ -278,9 +278,9 @@ export function isReminderActive(reminder: Reminder) {
|
||||
|
||||
export function createUpcomingReminderTimeQuery(unix = "now") {
|
||||
const time = sql`time(date / 1000, 'unixepoch', 'localtime')`;
|
||||
const dateNow = sql`date(${unix})`;
|
||||
const dateNow = sql`date(${unix}, 'localtime')`;
|
||||
const dateTime = sql`datetime(${dateNow} || ${time})`;
|
||||
const dateTimeNow = sql`datetime(${unix})`;
|
||||
const dateTimeNow = sql`datetime(${unix}, 'localtime')`;
|
||||
const weekDayNow = sql`CAST(strftime('%w', ${dateNow}) AS INTEGER)`;
|
||||
const monthDayNow = sql`CAST(strftime('%d', ${dateNow}) AS INTEGER)`;
|
||||
const lastSelectedDay = sql`(SELECT MAX(value) FROM json_each(selectedDays))`;
|
||||
@@ -326,8 +326,8 @@ export function createIsReminderActiveQuery(now = "now") {
|
||||
return sql`IIF(
|
||||
(disabled IS NULL OR disabled = 0)
|
||||
AND (mode != 'once'
|
||||
OR datetime(date / 1000, 'unixepoch', 'localtime') > datetime(${now})
|
||||
OR datetime(date / 1000, 'unixepoch', 'localtime') > datetime(${now}, 'localtime')
|
||||
OR (snoozeUntil IS NOT NULL
|
||||
AND datetime(snoozeUntil / 1000, 'unixepoch', 'localtime') > datetime(${now}))
|
||||
AND datetime(snoozeUntil / 1000, 'unixepoch', 'localtime') > datetime(${now}, 'localtime'))
|
||||
), 1, 0)`.$castTo<boolean>();
|
||||
}
|
||||
|
||||
4562
packages/editor/package-lock.json
generated
4562
packages/editor/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -294,7 +294,9 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
tr.mapping.map(to)
|
||||
)
|
||||
);
|
||||
scrollIntoView();
|
||||
|
||||
const domNode = this.editor.view.domAtPos(from).node;
|
||||
scrollIntoView(domNode);
|
||||
|
||||
this.storage.selectedIndex = nextIndex;
|
||||
tr.setMeta("selectedIndex", nextIndex);
|
||||
@@ -319,7 +321,9 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
tr.mapping.map(to)
|
||||
)
|
||||
);
|
||||
scrollIntoView();
|
||||
|
||||
const domNode = this.editor.view.domAtPos(from).node;
|
||||
scrollIntoView(domNode);
|
||||
|
||||
this.storage.selectedIndex = prevIndex;
|
||||
tr.setMeta("selectedIndex", prevIndex);
|
||||
@@ -472,14 +476,13 @@ export const SearchReplace = Extension.create<SearchOptions, SearchStorage>({
|
||||
}
|
||||
});
|
||||
|
||||
function scrollIntoView() {
|
||||
function scrollIntoView(domNode: Node) {
|
||||
setTimeout(() => {
|
||||
const domNode = document.querySelector(".search-result.selected");
|
||||
if (!(domNode instanceof HTMLElement)) return;
|
||||
|
||||
domNode.scrollIntoView({
|
||||
behavior: "instant",
|
||||
block: "center"
|
||||
});
|
||||
if ("scrollIntoView" in domNode) {
|
||||
(domNode as Element).scrollIntoView({
|
||||
behavior: "instant",
|
||||
block: "center"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { DependencyList, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Editor } from "../types.js";
|
||||
import { useToolbarStore } from "../toolbar/stores/toolbar-store.js";
|
||||
import { EditorView } from "@tiptap/pm/view";
|
||||
import { useEditorSearchStore } from "../toolbar/stores/search-store.js";
|
||||
|
||||
function useForceUpdate() {
|
||||
const [, setValue] = useState(0);
|
||||
@@ -57,6 +58,13 @@ export const useEditor = (
|
||||
if (oldIsFocused && !editor.isFocused) editor.commands.focus();
|
||||
options.onCreate?.({ editor: editor });
|
||||
|
||||
const { searchTerm, ...searchOptions } = useEditorSearchStore.getState();
|
||||
if (!searchOptions.isSearching) {
|
||||
editor.commands.endSearch();
|
||||
} else {
|
||||
editor.commands.search(searchTerm, searchOptions);
|
||||
}
|
||||
|
||||
function onTransaction({ editor }: { editor: TiptapEditor }) {
|
||||
editorRef.current = editor;
|
||||
clearTimeout(updateTimeout);
|
||||
|
||||
@@ -17,7 +17,6 @@ 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 { useLayoutEffect } from "react";
|
||||
import { FloatingMenuProps } from "./types.js";
|
||||
import { SearchReplacePopup } from "../popups/search-replace.js";
|
||||
import { ResponsivePresenter } from "../../components/responsive/index.js";
|
||||
@@ -28,12 +27,6 @@ export function SearchReplaceFloatingMenu(props: FloatingMenuProps) {
|
||||
const { editor } = props;
|
||||
const isSearching = useEditorSearchStore((store) => store.isSearching);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const { searchTerm, ...options } = useEditorSearchStore.getState();
|
||||
if (!options.isSearching) editor.commands.endSearch();
|
||||
else editor.commands.search(searchTerm, options);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ResponsivePresenter
|
||||
mobile="sheet"
|
||||
|
||||
@@ -749,7 +749,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:975
|
||||
msgid "Add your first notebook"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2617
|
||||
msgid "Adjust the line height of the editor"
|
||||
@@ -1603,7 +1603,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2392
|
||||
msgid "Click to reset {title}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2615
|
||||
msgid "Click to save"
|
||||
@@ -2591,7 +2591,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:120
|
||||
msgid "Enter the recovery code to continue logging in"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2618
|
||||
msgid "Enter title"
|
||||
@@ -3556,7 +3556,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:2356
|
||||
msgid "Line {line}, Column {column}"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2616
|
||||
msgid "Line height"
|
||||
@@ -7488,7 +7488,7 @@ msgstr ""
|
||||
|
||||
#: src/strings.ts:1403
|
||||
msgid "Your free trial is ending soon"
|
||||
msgstr "<<<<<<< HEAD"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2622
|
||||
msgid "Your free trial is on-going. Your subscription will start on {trialExpiryDate}"
|
||||
|
||||
Reference in New Issue
Block a user