mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 03:29:21 +02:00
Compare commits
1 Commits
3.4.7-andr
...
mobile-rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
953a1142a3 |
4
apps/desktop/package-lock.json
generated
4
apps/desktop/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.2",
|
||||
"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.4.4",
|
||||
"version": "3.4.2",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/cjs/index.js",
|
||||
|
||||
@@ -140,7 +140,7 @@ android {
|
||||
if (project.hasProperty("prBuildNumber")) {
|
||||
versionCode Integer.parseInt(prBuildNumber())
|
||||
} else {
|
||||
versionCode 3113
|
||||
versionCode 3111
|
||||
}
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
- Add option to clear note version history
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
|
||||
@@ -72,7 +72,6 @@ const MergeConflicts = () => {
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const content = useRef<UnencryptedContentItem>(null);
|
||||
const { height } = useSettingStore((state) => state.dimensions);
|
||||
const keepScreenOn = useSettingStore((state) => state.settings.keepScreenOn);
|
||||
|
||||
const applyChanges = async () => {
|
||||
const contentToSave = selectedContent;
|
||||
@@ -156,9 +155,9 @@ const MergeConflicts = () => {
|
||||
...item.content,
|
||||
conflicted: currentContent?.conflicted
|
||||
? await db.vault.decryptContent(
|
||||
currentContent?.conflicted as EncryptedContentItem,
|
||||
password
|
||||
)
|
||||
currentContent?.conflicted as EncryptedContentItem,
|
||||
password
|
||||
)
|
||||
: undefined
|
||||
} as UnencryptedContentItem;
|
||||
|
||||
@@ -183,9 +182,9 @@ const MergeConflicts = () => {
|
||||
...item.content,
|
||||
conflicted: currentContent?.conflicted
|
||||
? await db.vault.decryptContent(
|
||||
currentContent?.conflicted as EncryptedContentItem,
|
||||
password
|
||||
)
|
||||
currentContent?.conflicted as EncryptedContentItem,
|
||||
password
|
||||
)
|
||||
: undefined
|
||||
} as UnencryptedContentItem;
|
||||
|
||||
@@ -386,7 +385,7 @@ const MergeConflicts = () => {
|
||||
paddingTop: insets.top
|
||||
}}
|
||||
>
|
||||
{keepScreenOn && <KeepAwake />}
|
||||
<KeepAwake />
|
||||
{dialogVisible && (
|
||||
<BaseDialog visible={true}>
|
||||
<DialogContainer>
|
||||
|
||||
@@ -29,7 +29,7 @@ import { ActionSheetRef, ScrollView } from "react-native-actions-sheet";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { db } from "../../common/database";
|
||||
import { useDBItem } from "../../hooks/use-db-item";
|
||||
import { presentSheet, ToastManager } from "../../services/event-manager";
|
||||
import { presentSheet } from "../../services/event-manager";
|
||||
import { openLinkInBrowser } from "../../utils/functions";
|
||||
import { AppFontSize } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
@@ -39,19 +39,15 @@ import { Pressable } from "../ui/pressable";
|
||||
import Seperator from "../ui/seperator";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import NotePreview from "./preview";
|
||||
import { presentDialog } from "../dialog/functions";
|
||||
import { Dialog } from "../dialog";
|
||||
|
||||
const HistoryItem = ({
|
||||
index,
|
||||
items,
|
||||
note,
|
||||
refresh
|
||||
note
|
||||
}: {
|
||||
index: number;
|
||||
items?: VirtualizedGrouping<HistorySession>;
|
||||
note: Note;
|
||||
refresh: () => void;
|
||||
}) => {
|
||||
const [item] = useDBItem(index, "noteHistory", items);
|
||||
const { colors } = useThemeColors();
|
||||
@@ -79,13 +75,12 @@ const HistoryItem = ({
|
||||
}}
|
||||
content={content}
|
||||
note={note}
|
||||
update={refresh}
|
||||
/>
|
||||
),
|
||||
context: "note_history"
|
||||
});
|
||||
},
|
||||
[note, refresh]
|
||||
[note]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -117,8 +112,7 @@ const HistoryItem = ({
|
||||
};
|
||||
|
||||
export default function NoteHistory({
|
||||
note,
|
||||
fwdRef
|
||||
note
|
||||
}: {
|
||||
note: Note;
|
||||
fwdRef: RefObject<ActionSheetRef>;
|
||||
@@ -127,7 +121,7 @@ export default function NoteHistory({
|
||||
const [_loading, setLoading] = useState(true);
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
useEffect(() => {
|
||||
db.noteHistory
|
||||
.get(note.id)
|
||||
.sorted({
|
||||
@@ -143,56 +137,17 @@ export default function NoteHistory({
|
||||
});
|
||||
}, [note.id]);
|
||||
|
||||
useEffect(() => {
|
||||
refresh();
|
||||
}, [refresh]);
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ index }: { index: number }) => (
|
||||
<HistoryItem
|
||||
index={index}
|
||||
items={history}
|
||||
note={note}
|
||||
refresh={refresh}
|
||||
/>
|
||||
<HistoryItem index={index} items={history} note={note} />
|
||||
),
|
||||
[history, note, refresh]
|
||||
[history, note]
|
||||
);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<SheetProvider context="note_history" />
|
||||
<Dialog context="local" />
|
||||
<DialogHeader
|
||||
title={strings.noteHistory()}
|
||||
padding={12}
|
||||
button={
|
||||
history?.placeholders.length
|
||||
? {
|
||||
title: strings.clearHistory(),
|
||||
type: "secondary",
|
||||
onPress: () => {
|
||||
presentDialog({
|
||||
title: strings.clearHistory(),
|
||||
paragraph: strings.clearHistoryConfirmation(),
|
||||
positiveText: strings.clear(),
|
||||
negativeText: strings.cancel(),
|
||||
positiveType: "errorShade",
|
||||
context: "local",
|
||||
positivePress: async () => {
|
||||
await db.noteHistory.clearSessions(note.id);
|
||||
fwdRef.current?.hide();
|
||||
ToastManager.show({
|
||||
heading: strings.historyCleared(),
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<DialogHeader title={strings.noteHistory()} padding={12} />
|
||||
|
||||
<Seperator />
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ import {
|
||||
export default function NotePreview({
|
||||
session,
|
||||
content,
|
||||
note,
|
||||
update
|
||||
note
|
||||
}: {
|
||||
session?: HistorySession & { session: string };
|
||||
content:
|
||||
@@ -65,7 +64,6 @@ export default function NotePreview({
|
||||
>
|
||||
| undefined;
|
||||
note: TrashOrItem<Note>;
|
||||
update?: () => void;
|
||||
}) {
|
||||
const { colors } = useThemeColors();
|
||||
const [locked, setLocked] = useState(false);
|
||||
@@ -109,35 +107,24 @@ export default function NotePreview({
|
||||
}, [note]);
|
||||
|
||||
const deleteNote = async () => {
|
||||
const isSession = !!session;
|
||||
|
||||
presentDialog({
|
||||
title: isSession ? strings.deleteVersion() : strings.deleteNote(),
|
||||
paragraph: isSession
|
||||
? strings.deleteVersionConfirmation()
|
||||
: strings.deleteNoteConfirmation(),
|
||||
title: strings.deleteNote(),
|
||||
paragraph: strings.deleteNoteConfirmation(),
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
context: "preview",
|
||||
context: "local",
|
||||
positivePress: async () => {
|
||||
if (isSession) {
|
||||
await db.noteHistory.remove(session.id);
|
||||
update?.();
|
||||
eSendEvent(eCloseSheet, "note_history");
|
||||
Navigation.queueRoutesForUpdate();
|
||||
} else if (note.type === "trash") {
|
||||
if (note) {
|
||||
await db.trash.delete(note.id);
|
||||
useTrashStore.getState().refresh();
|
||||
useSelectionStore.getState().setSelectionMode();
|
||||
ToastManager.show({
|
||||
heading: strings.noteDeleted(),
|
||||
type: "success",
|
||||
context: "local"
|
||||
});
|
||||
eSendEvent(eCloseSheet);
|
||||
}
|
||||
ToastManager.show({
|
||||
heading: isSession ? strings.versionDeleted() : strings.noteDeleted(),
|
||||
type: "success",
|
||||
context: isSession ? "local" : "global"
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
positiveType: "error"
|
||||
});
|
||||
@@ -150,7 +137,7 @@ export default function NotePreview({
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Dialog context="preview" />
|
||||
<Dialog context="local" />
|
||||
<DialogHeader
|
||||
padding={12}
|
||||
title={content?.title || note.title || session?.session}
|
||||
|
||||
@@ -112,8 +112,7 @@ const PayWall = (props: NavigationProps<"PayWall">) => {
|
||||
}
|
||||
setStep(Steps.buy);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [routeParams.state]);
|
||||
}, [pricingPlans, routeParams.state]);
|
||||
|
||||
useEffect(() => {
|
||||
let listener: NativeEventSubscription;
|
||||
|
||||
@@ -170,147 +170,147 @@ export const SelectionHeader = React.memo(
|
||||
{!selectedItemsList.length
|
||||
? null
|
||||
: (focusedRouteId === "Monographs"
|
||||
? [
|
||||
{
|
||||
title: strings.unpublish(),
|
||||
onPress: () => {
|
||||
presentDialog({
|
||||
title: strings.doActions.unpublish.note(
|
||||
selectedItemsList.length
|
||||
),
|
||||
positiveText: strings.unpublish(),
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: async () => {
|
||||
for (const id of selectedItemsList) {
|
||||
await db.monographs.unpublish(id);
|
||||
}
|
||||
? [
|
||||
{
|
||||
title: strings.unpublish(),
|
||||
onPress: () => {
|
||||
presentDialog({
|
||||
title: strings.doActions.unpublish.note(
|
||||
selectedItemsList.length
|
||||
),
|
||||
positiveText: strings.unpublish(),
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: async () => {
|
||||
for (const id of selectedItemsList) {
|
||||
await db.monographs.unpublish(id);
|
||||
}
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
},
|
||||
positiveType: "errorShade"
|
||||
});
|
||||
},
|
||||
visible: true,
|
||||
icon: "delete"
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
title: strings.manageTags(),
|
||||
onPress: async () => {
|
||||
ManageTags.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "pound"
|
||||
},
|
||||
{
|
||||
title: strings.export(),
|
||||
onPress: async () => {
|
||||
ExportNotesSheet.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "export"
|
||||
},
|
||||
{
|
||||
title: strings.addToNotebook(),
|
||||
onPress: async () => {
|
||||
Navigation.navigate("LinkNotebooks", {
|
||||
noteIds: selectedItemsList
|
||||
});
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "plus"
|
||||
},
|
||||
{
|
||||
title: strings.unlinkNotebook(),
|
||||
onPress: async () => {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(
|
||||
id,
|
||||
...selectedItemsList
|
||||
);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
},
|
||||
positiveType: "errorShade"
|
||||
});
|
||||
},
|
||||
visible: true,
|
||||
icon: "delete"
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
title: strings.manageTags(),
|
||||
onPress: async () => {
|
||||
ManageTags.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "pound"
|
||||
},
|
||||
{
|
||||
title: strings.export(),
|
||||
onPress: async () => {
|
||||
ExportNotesSheet.present(selectedItemsList);
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "export"
|
||||
},
|
||||
{
|
||||
title: strings.addToNotebook(),
|
||||
onPress: async () => {
|
||||
Navigation.navigate("LinkNotebooks", {
|
||||
noteIds: selectedItemsList
|
||||
});
|
||||
},
|
||||
visible: type === "note",
|
||||
icon: "plus"
|
||||
},
|
||||
{
|
||||
title: strings.unlinkNotebook(),
|
||||
onPress: async () => {
|
||||
if (!id) return;
|
||||
await db.notes.removeFromNotebook(
|
||||
id,
|
||||
...selectedItemsList
|
||||
);
|
||||
updateNotebook(id);
|
||||
Navigation.queueRoutesForUpdate();
|
||||
clearSelection();
|
||||
},
|
||||
visible: renderedInRoute === "Notebook",
|
||||
icon: "minus"
|
||||
},
|
||||
{
|
||||
title: strings.unfavorite(),
|
||||
onPress: addToFavorite,
|
||||
visible: focusedRouteId === "Favorites",
|
||||
icon: "star-off"
|
||||
},
|
||||
{
|
||||
title: strings.moveToTrash(),
|
||||
onPress: async () => {
|
||||
const selection = useSelectionStore.getState();
|
||||
if (!selection.selectionMode) return;
|
||||
await deleteItems(
|
||||
selection.selectionMode as ItemType,
|
||||
selection.selectedItemsList
|
||||
);
|
||||
selection.clearSelection();
|
||||
selection.setSelectionMode(undefined);
|
||||
},
|
||||
visible: type === "note" || type === "notebook",
|
||||
icon: "delete"
|
||||
},
|
||||
{
|
||||
title: strings.doActions.delete.unknown(
|
||||
type!,
|
||||
selectedItemsList.length
|
||||
),
|
||||
onPress: async () => {
|
||||
const selection = useSelectionStore.getState();
|
||||
if (!selection.selectionMode) return;
|
||||
await deleteItems(
|
||||
selection.selectionMode as ItemType,
|
||||
selection.selectedItemsList
|
||||
);
|
||||
selection.clearSelection();
|
||||
selection.setSelectionMode(undefined);
|
||||
},
|
||||
visible:
|
||||
type !== "trash" &&
|
||||
type !== "note" &&
|
||||
type !== "notebook",
|
||||
icon: "delete"
|
||||
},
|
||||
{
|
||||
title: strings.restore(),
|
||||
onPress: restoreItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete-restore"
|
||||
},
|
||||
{
|
||||
title: strings.delete(),
|
||||
onPress: deleteItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete"
|
||||
}
|
||||
]
|
||||
).map((item) =>
|
||||
!item.visible ? null : (
|
||||
<IconButton
|
||||
size={AppFontSize.lg}
|
||||
type="plain"
|
||||
tooltipText={item.title}
|
||||
tooltipPosition={NativeTooltip.POSITIONS.TOP}
|
||||
testID={`select-${item.icon}`}
|
||||
name={item.icon}
|
||||
key={item.title}
|
||||
color={colors.primary.icon}
|
||||
onPress={async () => {
|
||||
//@ts-ignore
|
||||
menuRef.current?.hide();
|
||||
if (Platform.OS === "ios") await sleep(300);
|
||||
item.onPress();
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
visible: renderedInRoute === "Notebook",
|
||||
icon: "minus"
|
||||
},
|
||||
{
|
||||
title: strings.unfavorite(),
|
||||
onPress: addToFavorite,
|
||||
visible: focusedRouteId === "Favorites",
|
||||
icon: "star-off"
|
||||
},
|
||||
{
|
||||
title: strings.moveToTrash(),
|
||||
onPress: async () => {
|
||||
const selection = useSelectionStore.getState();
|
||||
if (!selection.selectionMode) return;
|
||||
await deleteItems(
|
||||
selection.selectionMode as ItemType,
|
||||
selection.selectedItemsList
|
||||
);
|
||||
selection.clearSelection();
|
||||
selection.setSelectionMode(undefined);
|
||||
},
|
||||
visible: type === "note" || type === "notebook",
|
||||
icon: "delete"
|
||||
},
|
||||
{
|
||||
title: strings.doActions.delete.unknown(
|
||||
type!,
|
||||
selectedItemsList.length
|
||||
),
|
||||
onPress: async () => {
|
||||
const selection = useSelectionStore.getState();
|
||||
if (!selection.selectionMode) return;
|
||||
await deleteItems(
|
||||
selection.selectionMode as ItemType,
|
||||
selection.selectedItemsList
|
||||
);
|
||||
selection.clearSelection();
|
||||
selection.setSelectionMode(undefined);
|
||||
},
|
||||
visible:
|
||||
type !== "trash" &&
|
||||
type !== "note" &&
|
||||
type !== "notebook",
|
||||
icon: "delete"
|
||||
},
|
||||
{
|
||||
title: strings.restore(),
|
||||
onPress: restoreItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete-restore"
|
||||
},
|
||||
{
|
||||
title: strings.delete(),
|
||||
onPress: deleteItem,
|
||||
visible: type === "trash",
|
||||
icon: "delete"
|
||||
}
|
||||
]
|
||||
).map((item) =>
|
||||
!item.visible ? null : (
|
||||
<IconButton
|
||||
size={AppFontSize.lg}
|
||||
type="plain"
|
||||
tooltipText={item.title}
|
||||
tooltipPosition={NativeTooltip.POSITIONS.TOP}
|
||||
testID={`select-${item.icon}`}
|
||||
name={item.icon}
|
||||
key={item.title}
|
||||
color={colors.primary.icon}
|
||||
onPress={async () => {
|
||||
//@ts-ignore
|
||||
menuRef.current?.hide();
|
||||
if (Platform.OS === "ios") await sleep(300);
|
||||
item.onPress();
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
|
||||
<IconButton
|
||||
|
||||
@@ -28,7 +28,7 @@ import { NativeEvents } from "@notesnook/editor-mobile/src/utils/native-events";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { ActivityIndicator, TextInput, View } from "react-native";
|
||||
import { TextInput, View } from "react-native";
|
||||
import { FlatList } from "react-native-actions-sheet";
|
||||
import { db } from "../../../common/database";
|
||||
import { useDBItem } from "../../../hooks/use-db-item";
|
||||
@@ -40,8 +40,6 @@ import { Button } from "../../ui/button";
|
||||
import Input from "../../ui/input";
|
||||
import { Pressable } from "../../ui/pressable";
|
||||
import Paragraph from "../../ui/typography/paragraph";
|
||||
import Navigation from "../../../services/navigation";
|
||||
import { useUserStore } from "../../../stores/use-user-store";
|
||||
|
||||
const ListNoteItem = ({
|
||||
id,
|
||||
@@ -120,8 +118,8 @@ const ListBlockItem = ({
|
||||
{item?.content.length > 200
|
||||
? item?.content.slice(0, 200) + "..."
|
||||
: !item.content || item.content.trim() === ""
|
||||
? strings.linkNoteEmptyBlock()
|
||||
: item.content}
|
||||
? strings.linkNoteEmptyBlock()
|
||||
: item.content}
|
||||
</Paragraph>
|
||||
|
||||
<View
|
||||
@@ -160,7 +158,6 @@ export default function LinkNote(props: {
|
||||
|
||||
const [selectedNote, setSelectedNote] = useState<Note>();
|
||||
const [selectedNodeId, setSelectedNodeId] = useState<string>();
|
||||
const [blocksLoading, setBlocksLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
db.notes.all.sorted(db.settings.getGroupOptions("notes")).then((notes) => {
|
||||
@@ -209,12 +206,10 @@ export default function LinkNote(props: {
|
||||
|
||||
const onSelectNote = async (note: Note) => {
|
||||
setSelectedNote(note);
|
||||
setBlocksLoading(true);
|
||||
inputRef.current?.clear();
|
||||
setTimeout(async () => {
|
||||
nodesRef.current = await db.notes.contentBlocks(note.id);
|
||||
setNodes(nodesRef.current);
|
||||
setBlocksLoading(false);
|
||||
});
|
||||
// Fetch and set note's nodes.
|
||||
};
|
||||
@@ -229,7 +224,6 @@ export default function LinkNote(props: {
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: DefaultAppStyles.GAP,
|
||||
paddingBottom: DefaultAppStyles.GAP,
|
||||
minHeight: "100%",
|
||||
maxHeight: "100%"
|
||||
}}
|
||||
@@ -336,42 +330,28 @@ export default function LinkNote(props: {
|
||||
windowSize={3}
|
||||
keyExtractor={(item) => item.id}
|
||||
ListEmptyComponent={
|
||||
!blockLinking || blocksLoading ? (
|
||||
<ActivityIndicator size={25} color={colors.primary.accent} />
|
||||
) : !blockLinking.isAllowed ? (
|
||||
<View
|
||||
<View
|
||||
style={{
|
||||
gap: DefaultAppStyles.GAP_VERTICAL,
|
||||
backgroundColor: colors.secondary.background,
|
||||
padding: DefaultAppStyles.GAP,
|
||||
borderRadius: defaultBorderRadius,
|
||||
borderWidth: 0.5,
|
||||
borderColor: colors.secondary.border,
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Paragraph color={colors.secondary.paragraph}>
|
||||
{blockLinking?.error}
|
||||
</Paragraph>
|
||||
<Button
|
||||
title={strings.upgradePlan()}
|
||||
style={{
|
||||
gap: DefaultAppStyles.GAP_VERTICAL,
|
||||
backgroundColor: colors.secondary.background,
|
||||
padding: DefaultAppStyles.GAP,
|
||||
borderRadius: defaultBorderRadius,
|
||||
borderWidth: 0.5,
|
||||
borderColor: colors.secondary.border,
|
||||
alignItems: "center"
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Paragraph color={colors.secondary.paragraph}>
|
||||
{blockLinking?.error}
|
||||
</Paragraph>
|
||||
<Button
|
||||
title={strings.upgradePlan()}
|
||||
style={{
|
||||
width: "100%"
|
||||
}}
|
||||
type="accent"
|
||||
onPress={() => {
|
||||
Navigation.navigate("PayWall", {
|
||||
context: useUserStore.getState().user
|
||||
? "logged-in"
|
||||
: "logged-out",
|
||||
canGoBack: true
|
||||
});
|
||||
|
||||
props.close?.();
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
) : null
|
||||
type="accent"
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
data={blockLinking?.isAllowed ? nodes : []}
|
||||
/>
|
||||
|
||||
@@ -447,9 +447,7 @@ const onChangeTab = async (event: { i: number; from: number }) => {
|
||||
if (event.i === 2) {
|
||||
editorState().movedAway = false;
|
||||
editorState().isFocused = true;
|
||||
if (useSettingStore.getState().settings.keepScreenOn) {
|
||||
activateKeepAwake();
|
||||
}
|
||||
activateKeepAwake();
|
||||
eSendEvent(eOnEnterEditor);
|
||||
|
||||
if (
|
||||
|
||||
@@ -163,20 +163,7 @@ const LinkNotebooks = (props: NavigationProps<"LinkNotebooks">) => {
|
||||
}, [noteIds]);
|
||||
|
||||
const onSave = async () => {
|
||||
const selectionState = useNotebookSelectionStore.getState();
|
||||
const changedNotebooks = { ...selectionState.selection };
|
||||
|
||||
if (!selectionState.multiSelect) {
|
||||
for (const id in selectionState.initialState) {
|
||||
if (
|
||||
selectionState.initialState[id] === "selected" &&
|
||||
changedNotebooks[id] !== "selected"
|
||||
) {
|
||||
changedNotebooks[id] = "deselected";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const changedNotebooks = useNotebookSelectionStore.getState().selection;
|
||||
for (const id in changedNotebooks) {
|
||||
const item = await db.notebooks.notebook(id);
|
||||
if (!item) continue;
|
||||
@@ -220,11 +207,11 @@ const LinkNotebooks = (props: NavigationProps<"LinkNotebooks">) => {
|
||||
rightButton={
|
||||
hasSelection
|
||||
? {
|
||||
name: "restore",
|
||||
onPress: () => {
|
||||
updateInitialSelectionState(noteIds);
|
||||
name: "restore",
|
||||
onPress: () => {
|
||||
updateInitialSelectionState(noteIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -210,7 +210,7 @@ export const settingsGroups: SettingSection[] = [
|
||||
: status === SubscriptionStatus.ACTIVE
|
||||
? strings.subRenewOn(expiryDate)
|
||||
: status === SubscriptionStatus.CANCELED ||
|
||||
status === SubscriptionStatus.PAUSED
|
||||
status === SubscriptionStatus.PAUSED
|
||||
? strings.subEndsOn(expiryDate)
|
||||
: status === SubscriptionStatus.EXPIRED
|
||||
? subscriptionDaysLeft.time < -3
|
||||
@@ -965,14 +965,6 @@ export const settingsGroups: SettingSection[] = [
|
||||
property: "checkForUpdates",
|
||||
icon: "update"
|
||||
},
|
||||
{
|
||||
id: "keep-screen-on",
|
||||
type: "switch",
|
||||
name: strings.keepScreenOn(),
|
||||
description: strings.keepScreenOnDesc(),
|
||||
property: "keepScreenOn",
|
||||
icon: "cellphone-screenshot",
|
||||
},
|
||||
{
|
||||
id: "image-compression",
|
||||
type: "component",
|
||||
|
||||
@@ -35,7 +35,7 @@ import notifee, {
|
||||
import NetInfo from "@react-native-community/netinfo";
|
||||
import dayjs, { Dayjs } from "dayjs";
|
||||
import { encodeNonAsciiHTML } from "entities";
|
||||
import { AppState, Platform } from "react-native";
|
||||
import { Platform } from "react-native";
|
||||
import { db, setupDatabase } from "../common/database";
|
||||
import { MMKV } from "../common/database/mmkv";
|
||||
import { presentDialog } from "../components/dialog/functions";
|
||||
@@ -45,7 +45,7 @@ import { useRelationStore } from "../stores/use-relation-store";
|
||||
import { useReminderStore } from "../stores/use-reminder-store";
|
||||
import { useSettingStore } from "../stores/use-setting-store";
|
||||
import { useUserStore } from "../stores/use-user-store";
|
||||
import { eCloseSimpleDialog, eOnLoadNote } from "../utils/events";
|
||||
import { eOnLoadNote } from "../utils/events";
|
||||
import { fluidTabsRef } from "../utils/global-refs";
|
||||
import { convertNoteToText } from "../utils/note-to-text";
|
||||
import { NotesnookModule } from "../utils/notesnook-module";
|
||||
@@ -577,7 +577,7 @@ async function displayNotification({
|
||||
}
|
||||
|
||||
function openSettingsDialog(context: string) {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
return new Promise((resolve) => {
|
||||
presentDialog({
|
||||
title: strings.notificationsDisabled(),
|
||||
paragraph: strings.notificationsDisabledDesc(),
|
||||
@@ -597,94 +597,49 @@ function openSettingsDialog(context: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function waitForAppFocusAfterSettings(timeoutMs = 120000): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
let didLeaveApp = AppState.currentState !== "active";
|
||||
const timeout = setTimeout(() => {
|
||||
subscription.remove();
|
||||
resolve();
|
||||
}, timeoutMs);
|
||||
|
||||
const subscription = AppState.addEventListener("change", (state) => {
|
||||
if (state !== "active") {
|
||||
didLeaveApp = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (didLeaveApp && state === "active") {
|
||||
clearTimeout(timeout);
|
||||
subscription.remove();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function checkAndRequestPermissions(
|
||||
promptUser?: boolean
|
||||
): Promise<boolean> {
|
||||
let permissionStatus = await notifee.getNotificationSettings();
|
||||
if (Platform.OS === "android") {
|
||||
const hasNotificationPermission =
|
||||
permissionStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED;
|
||||
const hasAlarmPermission = permissionStatus.android.alarm === 1;
|
||||
|
||||
if (hasNotificationPermission && hasAlarmPermission) {
|
||||
if (
|
||||
permissionStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED &&
|
||||
permissionStatus.android.alarm === 1
|
||||
)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (permissionStatus.authorizationStatus === AuthorizationStatus.DENIED) {
|
||||
permissionStatus = await notifee.requestPermission();
|
||||
}
|
||||
|
||||
// Wait for user to return from exact alarm settings
|
||||
if (permissionStatus.android.alarm !== 1) {
|
||||
const waitForAppFocus = waitForAppFocusAfterSettings();
|
||||
|
||||
await notifee.openAlarmPermissionSettings();
|
||||
await waitForAppFocus;
|
||||
}
|
||||
permissionStatus = await notifee.getNotificationSettings();
|
||||
|
||||
const authorized =
|
||||
if (
|
||||
permissionStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED &&
|
||||
permissionStatus.android.alarm === 1;
|
||||
|
||||
if (authorized) {
|
||||
permissionStatus.android.alarm === 1
|
||||
)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (promptUser) {
|
||||
const openSettings = await openSettingsDialog("local");
|
||||
if (openSettings) {
|
||||
const waitForAppFocus = waitForAppFocusAfterSettings();
|
||||
if (await openSettingsDialog("local")) {
|
||||
await notifee.openNotificationSettings();
|
||||
await waitForAppFocus;
|
||||
permissionStatus = await notifee.getNotificationSettings();
|
||||
const finalAuthorized =
|
||||
permissionStatus.authorizationStatus ===
|
||||
AuthorizationStatus.AUTHORIZED &&
|
||||
permissionStatus.android.alarm === 1;
|
||||
if (finalAuthorized) {
|
||||
eSendEvent(eCloseSimpleDialog);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
permissionStatus = await notifee.requestPermission();
|
||||
if (permissionStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED)
|
||||
return true;
|
||||
if (promptUser) {
|
||||
await openSettingsDialog("local");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// iOS
|
||||
permissionStatus = await notifee.requestPermission();
|
||||
if (permissionStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED) {
|
||||
return true;
|
||||
}
|
||||
if (promptUser) {
|
||||
await openSettingsDialog("local");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function getTriggers(
|
||||
reminder: Reminder
|
||||
): Promise<(Trigger & { id: string })[] | undefined> {
|
||||
|
||||
@@ -104,7 +104,6 @@ export type Settings = {
|
||||
checkForUpdates?: boolean;
|
||||
defaultLineHeight: number;
|
||||
imageCompression: "ask-every-time" | "enabled" | "disabled";
|
||||
keepScreenOn?: boolean;
|
||||
};
|
||||
|
||||
type DimensionsType = {
|
||||
@@ -214,8 +213,7 @@ export const defaultSettings: SettingStore["settings"] = {
|
||||
lastFullBackupDate: 0,
|
||||
checkForUpdates: true,
|
||||
defaultLineHeight: EDITOR_LINE_HEIGHT.DEFAULT,
|
||||
imageCompression: "ask-every-time",
|
||||
keepScreenOn: true
|
||||
imageCompression: "ask-every-time"
|
||||
};
|
||||
|
||||
export const useSettingStore = create<SettingStore>((set, get) => ({
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2191
|
||||
IOS_MARKETING_VERSION = 3.4.7
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2191
|
||||
IOS_MARKETING_VERSION = 3.4.7
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Staging iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2191
|
||||
IOS_MARKETING_VERSION = 3.4.7
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
6
apps/mobile/package-lock.json
generated
6
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.5",
|
||||
"version": "3.4.0-beta.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.5",
|
||||
"version": "3.4.0-beta.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
@@ -290,7 +290,7 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook-importer/core": "^2.4.5",
|
||||
"@notesnook-importer/core": "^2.2.5",
|
||||
"@notesnook/common": "file:../common",
|
||||
"@notesnook/intl": "file:../intl",
|
||||
"@notesnook/theme": "file:../theme",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.7",
|
||||
"version": "3.4.5",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/vericrypt",
|
||||
"version": "1.4.0",
|
||||
"version": "1.3.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/platform": "^1.3.6",
|
||||
@@ -43,4 +43,4 @@
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import { PasteEncryptedData, SyncRequestBody } from "./components/step-4";
|
||||
import { StepSeperator } from "./components/step-seperator";
|
||||
import { Footer } from "./components/footer";
|
||||
import { useState } from "react";
|
||||
import { NNCrypto, Cipher } from "@notesnook/crypto";
|
||||
import { NNCrypto } from "@notesnook/crypto";
|
||||
import { Code } from "./components/code";
|
||||
import { Accordion } from "./components/accordion";
|
||||
import { DecryptedResult } from "./components/decrypted-result";
|
||||
@@ -41,7 +41,7 @@ const instructions = [
|
||||
"Go to Notesnook",
|
||||
"Open Settings",
|
||||
<>
|
||||
Click on <Code text="Save data recovery key" />
|
||||
Click on <Code text="Backup data recovery key" />
|
||||
</>,
|
||||
"Enter your account password for verification",
|
||||
"Confirm that your generated encryption key matches"
|
||||
@@ -52,7 +52,6 @@ function App() {
|
||||
const [salt, setSalt] = useState<string>();
|
||||
const [key, setKey] = useState<string>();
|
||||
const [data, setData] = useState<SyncRequestBody | undefined>();
|
||||
const [accountDataKey, setAccountDataKey] = useState<Cipher<"base64"> | null | undefined>();
|
||||
const theme = useTheme({ accent: getDefaultAccentColor(), theme: "light" });
|
||||
|
||||
return (
|
||||
@@ -68,7 +67,7 @@ function App() {
|
||||
>
|
||||
<LoginToNotesnook />
|
||||
<StepSeperator />
|
||||
<GetAccountSalt onSaltSubmitted={setSalt} setAccountDataKey={setAccountDataKey} />
|
||||
<GetAccountSalt onSaltSubmitted={setSalt} />
|
||||
|
||||
{salt && (
|
||||
<>
|
||||
@@ -92,7 +91,7 @@ function App() {
|
||||
return true;
|
||||
}}
|
||||
popup={{
|
||||
title: "Your master encryption key",
|
||||
title: "Your data encryption key",
|
||||
body: key ? (
|
||||
<>
|
||||
<Text
|
||||
@@ -147,13 +146,11 @@ function App() {
|
||||
password={password}
|
||||
salt={salt}
|
||||
data={data}
|
||||
accountKey={accountDataKey}
|
||||
onRestartProcess={() => {
|
||||
setSalt(undefined);
|
||||
setPassword(undefined);
|
||||
setKey(undefined);
|
||||
setData(undefined);
|
||||
setAccountDataKey(undefined);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 181 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 166 KiB |
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { Flex, Button, Text, Link } from "@theme-ui/components";
|
||||
import { StepContainer } from "./step-container";
|
||||
import { SyncRequestBody } from "./step-4";
|
||||
import { NNCrypto, Cipher } from "@notesnook/crypto";
|
||||
import { NNCrypto } from "@notesnook/crypto";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FcDataEncryption } from "react-icons/fc";
|
||||
import { Code } from "./code";
|
||||
@@ -32,7 +32,6 @@ type DecryptedResultProps = {
|
||||
password: string;
|
||||
salt: string;
|
||||
data: SyncRequestBody;
|
||||
accountKey: Cipher<"base64"> | null | undefined;
|
||||
onRestartProcess: () => void;
|
||||
};
|
||||
|
||||
@@ -52,19 +51,10 @@ export function DecryptedResult(props: DecryptedResultProps) {
|
||||
};
|
||||
const crypto = new NNCrypto();
|
||||
const key = await crypto.exportKey(props.password, props.salt);
|
||||
let encryptionKey = undefined;
|
||||
if (props.accountKey != null){
|
||||
// Need to decrypt the account key
|
||||
props.accountKey.format = "base64"; // account keys don't have the format set, but they're base64.
|
||||
const dataEncryptionKey = JSON.parse(await crypto.decrypt(key, props.accountKey, "text"))
|
||||
encryptionKey = dataEncryptionKey;
|
||||
} else {
|
||||
encryptionKey = key;
|
||||
}
|
||||
for (const arrayKey in data) {
|
||||
const array = data[arrayKey];
|
||||
for (const encryptedItem of (props.data as any)[arrayKey]) {
|
||||
const data = await crypto.decrypt(encryptionKey, encryptedItem, "text");
|
||||
const data = await crypto.decrypt(key, encryptedItem, "text");
|
||||
array.push(JSON.parse(data));
|
||||
}
|
||||
}
|
||||
@@ -160,9 +150,19 @@ export function DecryptedResult(props: DecryptedResultProps) {
|
||||
support@streetwriters.co
|
||||
</Link>{" "}
|
||||
or{" "}
|
||||
<Link href="https://go.notesnook.com/discord">join our Discord community</Link>.
|
||||
<Link href="https://discord.gg/">joining our Discord community</Link>.
|
||||
We'll do our best to alleviate all your worries.
|
||||
</Text>
|
||||
<Text as="p" variant="body" sx={{ mx: 2, mt: 2, fontWeight: "bold" }}>
|
||||
What about open sourcing Notesnook?
|
||||
</Text>
|
||||
<Text as="p" variant="body" sx={{ mx: 2, my: 2 }}>
|
||||
Open sourcing is another part of garnering our users' trust. We
|
||||
have <Link href="https://notesnook.com/roadmap">plans</Link> to begin
|
||||
open sourcing in May but open sourcing will not make this tool
|
||||
obsolete. Verifying the integrity of encrypted data at any point in
|
||||
time is very important even if the software is open source.
|
||||
</Text>
|
||||
</Accordion>
|
||||
<Flex sx={{ alignSelf: "center", mt: 4 }}>
|
||||
<Button
|
||||
|
||||
@@ -38,6 +38,11 @@ export function LoginToNotesnook() {
|
||||
>
|
||||
<Text variant="title">Welcome to Vericrypt</Text>
|
||||
<Text as="p" variant="body" sx={{ mt: 1 }}>
|
||||
<del>
|
||||
Trust is a huge problem in closed source end-to-end encrypted
|
||||
applications. How can you be sure that the app is actually encrypting
|
||||
your data?
|
||||
</del>
|
||||
</Text>
|
||||
<Text as="p" variant="body" sx={{ mt: 1 }}>
|
||||
The only way to earn a user's trust is by allowing them to see how
|
||||
@@ -51,10 +56,9 @@ export function LoginToNotesnook() {
|
||||
</Link>
|
||||
</Text>
|
||||
<Text as="p" variant="body" sx={{ mt: 1 }}>
|
||||
Yes, that's right. Notesnook is 100% open source under the
|
||||
GPLv3 license. That includes the app, the encryption library, and
|
||||
everything else. We've even open sourced the server, available under the
|
||||
AGPLv3 license.
|
||||
Yes, that's right. Notesnook is now 100% open source under the
|
||||
GPLv3 license. That includes the app, the encryption library, the
|
||||
backend server, and everything else.
|
||||
</Text>
|
||||
<Text as="p" variant="body" sx={{ mt: 1 }}>
|
||||
However, even with an open source app, how can you be sure that the app
|
||||
@@ -82,7 +86,7 @@ export function LoginToNotesnook() {
|
||||
sx={{ alignSelf: "center", mt: 2 }}
|
||||
onClick={() => window.open("https://app.notesnook.com/login", "_blank")}
|
||||
>
|
||||
Get Started by Logging in
|
||||
Login to Notesnook
|
||||
</Button>
|
||||
</StepContainer>
|
||||
);
|
||||
|
||||
@@ -16,11 +16,11 @@ 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 { Flex, Text, Image, Textarea } from "@theme-ui/components";
|
||||
import { Flex, Text, Image, Input } from "@theme-ui/components";
|
||||
import { StepContainer } from "./step-container";
|
||||
import DevtoolsCopyUsersChrome from "../assets/screenshots/devtools_copy_users.png";
|
||||
import DevtoolsCopySaltChrome from "../assets/screenshots/devtools_copy_salt.png";
|
||||
|
||||
import DevtoolsCopyUsersFirefox from "../assets/screenshots/firefox/firefox_copy_users.png";
|
||||
import DevtoolsCopySaltFirefox from "../assets/screenshots/firefox/firefox_copy_salt.png";
|
||||
|
||||
import { Accordion } from "./accordion";
|
||||
import { getCombo } from "../utils/keycombos";
|
||||
@@ -29,11 +29,9 @@ import { KeyCombo } from "./key-combo";
|
||||
import { Code } from "./code";
|
||||
import { useState } from "react";
|
||||
import { getSourceUrl } from "../utils/links";
|
||||
import { Cipher } from "@notesnook/crypto";
|
||||
|
||||
type GetAccountSaltProps = {
|
||||
onSaltSubmitted: (salt: string) => void;
|
||||
setAccountDataKey: (accountDataKey: Cipher<"base64"> | null) => void;
|
||||
};
|
||||
|
||||
const steps = {
|
||||
@@ -54,10 +52,10 @@ const steps = {
|
||||
</Text>,
|
||||
<Flex key="key-named-salt" sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">Follow the steps as shown in the image:</Text>
|
||||
<Image src={DevtoolsCopyUsersChrome} width={"100%"} sx={{ mt: 1 }} />
|
||||
<Image src={DevtoolsCopySaltChrome} width={"100%"} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<Flex key="copy-salt" sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">Copy everything in the response and paste it below.</Text>
|
||||
<Text as="p">Copy the salt and paste it below.</Text>
|
||||
</Flex>
|
||||
],
|
||||
firefox: [
|
||||
@@ -77,10 +75,10 @@ const steps = {
|
||||
</Text>,
|
||||
<Flex key="key-named-salt" sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">Follow the steps as shown in the image:</Text>
|
||||
<Image src={DevtoolsCopyUsersFirefox} width={"100%"} sx={{ mt: 1 }} />
|
||||
<Image src={DevtoolsCopySaltFirefox} width={"100%"} sx={{ mt: 1 }} />
|
||||
</Flex>,
|
||||
<Flex key="copy-salt" sx={{ flexDirection: "column" }}>
|
||||
<Text as="p">Copy everything in the response and paste it below.</Text>
|
||||
<Text as="p">Copy the salt and paste it below.</Text>
|
||||
</Flex>
|
||||
]
|
||||
};
|
||||
@@ -116,14 +114,14 @@ export function GetAccountSalt(props: GetAccountSaltProps) {
|
||||
sx={{ flexDirection: "column" }}
|
||||
>
|
||||
<Flex sx={{ justifyContent: "space-between", alignItems: "center" }}>
|
||||
<Text variant="title">Account Key Data</Text>
|
||||
<Text variant="title">Account salt</Text>
|
||||
<Code
|
||||
text="src/components/step-2.tsx"
|
||||
href={getSourceUrl("src/components/step-2.tsx")}
|
||||
/>
|
||||
</Flex>
|
||||
<Accordion
|
||||
title="How to get your key data?"
|
||||
title="How to get your account salt?"
|
||||
sx={{
|
||||
border: "1px solid var(--border)",
|
||||
mt: 2,
|
||||
@@ -131,9 +129,9 @@ export function GetAccountSalt(props: GetAccountSaltProps) {
|
||||
}}
|
||||
>
|
||||
<Text variant="body" sx={{ mx: 2 }}>
|
||||
You'll be extracting your account's keys right from
|
||||
We'll be extracting your account's salt right from
|
||||
Notesnook's local database that lives in your web browser. So put
|
||||
on your seat belt and let's retrieve those keys.
|
||||
on your seat belt and let's get some salt!
|
||||
</Text>
|
||||
<Text as="ol" variant="body" sx={{ mb: 2 }}>
|
||||
{instructions?.map((item, index) => (
|
||||
@@ -143,11 +141,12 @@ export function GetAccountSalt(props: GetAccountSaltProps) {
|
||||
))}
|
||||
</Text>
|
||||
</Accordion>
|
||||
<Textarea
|
||||
<Input
|
||||
variant="forms.clean"
|
||||
id="account-data"
|
||||
name="account-data"
|
||||
placeholder="Paste the response here"
|
||||
id="salt"
|
||||
name="salt"
|
||||
type="text"
|
||||
placeholder="Enter your account salt"
|
||||
sx={{
|
||||
mt: 2,
|
||||
fontSize: "subheading",
|
||||
@@ -163,21 +162,13 @@ export function GetAccountSalt(props: GetAccountSaltProps) {
|
||||
spellCheck={false}
|
||||
onChange={(e) => {
|
||||
setIsSaltValid(undefined);
|
||||
/*
|
||||
If there is no dataEncryptionKey, try reading the legacyDataEncryptionKey.
|
||||
If there is a legacyDataEncryptionKey, use this one.
|
||||
If there is no legacyDataEncryptionKey, it is a legacy account (pre DEK update) that has not
|
||||
changed passwords. (Use master key instead.)
|
||||
*/
|
||||
try {
|
||||
const value = JSON.parse(e.target.value);
|
||||
props.setAccountDataKey(value.dataEncryptionKey ?? value.legacyDataEncryptionKey ?? null);
|
||||
const salt = value.salt;
|
||||
const isValid = Buffer.from(salt, "base64").length === 16;
|
||||
const value = e.target.value;
|
||||
const isValid = Buffer.from(value, "base64").length === 16;
|
||||
if (!isValid) setIsSaltValid(false);
|
||||
else {
|
||||
setIsSaltValid(true);
|
||||
props.onSaltSubmitted(salt);
|
||||
props.onSaltSubmitted(value);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
4
apps/web/package-lock.json
generated
4
apps/web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.4.4",
|
||||
"version": "3.4.2",
|
||||
"private": true,
|
||||
"main": "./src/app.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
|
||||
@@ -684,12 +684,6 @@ function TiptapWrapper(
|
||||
}
|
||||
}, [props.spellcheck]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editorContainerRef.current) {
|
||||
editorContainerRef.current.style.fontSize = `${editorConfig.fontSize}px`;
|
||||
}
|
||||
}, [editorConfig.fontSize]);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
ref={containerRef}
|
||||
|
||||
@@ -97,7 +97,34 @@ const features: Record<FeatureKeys, Feature> = {
|
||||
)
|
||||
}
|
||||
]
|
||||
: [],
|
||||
: [
|
||||
{
|
||||
icon: Inbox,
|
||||
title: "Inbox API",
|
||||
subtitle: "A new API to send data to Notesnook from other apps."
|
||||
},
|
||||
{
|
||||
icon: LinkedTo,
|
||||
title: "Deep links on Desktop",
|
||||
subtitle: "Reference Notesnook notes from other apps."
|
||||
},
|
||||
{
|
||||
icon: Plus,
|
||||
title: "More features, bug fixes, and security improvments",
|
||||
subtitle: (
|
||||
<>
|
||||
This release contains much much more.{" "}
|
||||
<Link
|
||||
href="https://blog.notesnook.com/notesnook-desktop-v3.4.0"
|
||||
target="_blank"
|
||||
title="Read the full release notes"
|
||||
>
|
||||
Read the full release notes
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
}
|
||||
],
|
||||
cta: {
|
||||
title: strings.gotIt(),
|
||||
icon: Checkmark,
|
||||
|
||||
@@ -21,7 +21,7 @@ On all three platforms we use the same exact library for all cryptographic funct
|
||||
|
||||
> info Fun story
|
||||
>
|
||||
> When we first added encryption, we used AES-GCM-256 across platforms but the cross-platform compatibility was abyssmal. That is when I found out about the great libsodium. Written in C, wrappers available for all platforms...what more could I want?
|
||||
> When we first added encryption, we used AES-GCM-256 across platforms but the cross-platform compatbility was abyssmal. That is when I found out about the great libsodium. Written in C, wrappers available for all platforms...what more could I want?
|
||||
|
||||
## Process
|
||||
|
||||
@@ -41,7 +41,13 @@ This process is repeated every time you sign in.
|
||||
|
||||
### 2. Key generation
|
||||
|
||||
When you first sign up for an account, your client generates two encryption keys. One is a unique data encryption key that encrypts all your notes and other data. The second is your master encryption key, this is derived by your password and predictable salt. This key protects all your encryption keys, like the aforementioned data encryption key. If you change your password, your client will re-encrypt your existing data encryption key with your new master key.
|
||||
After you are signed in, the app requests your user data which includes, among other things, your salt.
|
||||
|
||||
> info Salt generation
|
||||
>
|
||||
> When you create an account, the server generates a cryptographically secure random salt for you. This salt is used for key generation.
|
||||
|
||||
You password & salt is then used to derive a strong irreversible key using Argon2 as the password key derivation function (PKDF).
|
||||
|
||||
### 3. Encryption key storage
|
||||
|
||||
@@ -49,7 +55,7 @@ When you first sign up for an account, your client generates two encryption keys
|
||||
|
||||
Instead of storing the key as plain text (and allowing anyone to copy/move it), we use browser's `IndexedDB` to store the key as a `CryptoKey`.
|
||||
|
||||
`CryptoKey` is stored securely by the browser and cannot be exported, viewed, or copied except by the app & browser.
|
||||
`CryptoKey` is stored securely by the browser and cannot be exported, viewed, copied except by the app & browser.
|
||||
|
||||
# [Mobile](#/tab/mobile)
|
||||
|
||||
@@ -59,12 +65,12 @@ On iOS and Android, the encryption key is stored in the phone's keychain.
|
||||
|
||||
### 4. Data encryption
|
||||
|
||||
Encryption only takes place when you sync. Each item in the database is encrypted separately using XChaCha-Poly1305-IETF.
|
||||
Encryption only takes place when you sync. Each item in the database is encrypted seperately using XChaCha-Poly1305-IETF.
|
||||
|
||||
#### How it works
|
||||
|
||||
1. The item is read from the database as JSON object and stringified (i.e. converted to a string).
|
||||
2. The string is encrypted using the data encryption key generated earlier.
|
||||
2. The string is encrypted using the encryption key generated earlier.
|
||||
3. The result is a JSON object which contains:
|
||||
1. A base64 encoded `cipher`
|
||||
2. A 192-bit nonce (`iv`)
|
||||
@@ -77,9 +83,3 @@ Encryption only takes place when you sync. Each item in the database is encrypte
|
||||
> See the whole process in action [here.](https://vericrypt.notesnook.com/)
|
||||
|
||||
This object is then sent to the server for storage. The server performs no further operation on this data (because it can't).
|
||||
|
||||
## Faqs
|
||||
|
||||
### I am an old user of Notesnook, I don't have a data encryption key.
|
||||
|
||||
Your data encryption key will be created when you change your password.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> error This feature is Android only.
|
||||
|
||||
A simple, quick and convenient way to take notes on your phone from notifications. This works the same way as a messaging/chat app allows you to reply to messages from notifications.
|
||||
A simple, quick and convinient way to take notes on your phone from notifications. This works the same way as a messaging/chat app allows you to reply to messages from notifications.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Basic web clipping support is available on both Android & iOS apps via share extensions.
|
||||
|
||||
We are going to use browser app as an example to demonstrate how you can clip information from webpages and other apps on your iPhone.
|
||||
We are going to use browser app as an example to demonstarte how you can clip information from webpages and other apps on your iPhone.
|
||||
|
||||
1. Select some text on a webpage then Tap on "Share" on the context menu.
|
||||
|
||||
@@ -40,7 +40,7 @@ We are going to use browser app as an example to demonstrate how you can clip in
|
||||
|
||||
> info
|
||||
>
|
||||
> Share extension will save the note you selected so in future web clips, it will be selected by default until you reset it.
|
||||
> Share exenstion will save the note you selected so in future web clips, it will be selected by default until you reset it.
|
||||
|
||||
## Clipping full webpage content
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ The first step to recovering your account consists of requesting an account reco
|
||||
5. On the next page, your email should be prefilled. If it isn't, fill it out.
|
||||

|
||||
6. Click on `Send recovery email`
|
||||
7. If everything goes well, you should receive an email from Notesnook in your inbox:
|
||||
7. If everything goes well, you should recieve an email from Notesnook in your inbox:
|
||||

|
||||
> info What if I didn't receive an email?
|
||||
>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -1,4 +0,0 @@
|
||||
- Add option to clear note version history
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -437,7 +437,6 @@ export class Notes implements ICollection {
|
||||
const duplicateId = await this.db.notes.add({
|
||||
...clone(note),
|
||||
id: undefined,
|
||||
pinned: false,
|
||||
isGeneratedTitle: false,
|
||||
contentId: undefined,
|
||||
title: note.title + " (Copy)",
|
||||
|
||||
2
packages/editor-mobile/package-lock.json
generated
2
packages/editor-mobile/package-lock.json
generated
@@ -63,7 +63,7 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook-importer/core": "^2.4.5",
|
||||
"@notesnook-importer/core": "^2.2.5",
|
||||
"@notesnook/common": "file:../common",
|
||||
"@notesnook/intl": "file:../intl",
|
||||
"@notesnook/theme": "file:../theme",
|
||||
|
||||
@@ -138,7 +138,7 @@ msgstr "{count, plural, one {Are you sure you want to download all attachments o
|
||||
msgid "{count, plural, one {Are you sure you want to move this notebook to {selectedNotebookTitle}?} other {Are you sure you want to move these # notebooks {selectedNotebookTitle}?}}"
|
||||
msgstr "{count, plural, one {Are you sure you want to move this notebook to {selectedNotebookTitle}?} other {Are you sure you want to move these # notebooks {selectedNotebookTitle}?}}"
|
||||
|
||||
#: generated/action-confirmations.ts:82
|
||||
#: generated/action-confirmations.ts:76
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this item?} other {Are you sure you to permanently delete these items?}}"
|
||||
msgstr "{count, plural, one {Are you sure you want to permanently delete this item?} other {Are you sure you to permanently delete these items?}}"
|
||||
|
||||
@@ -150,10 +150,6 @@ msgstr "{count, plural, one {Are you sure you want to permanently delete this no
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this notebook?} other {Are you sure you to permanently delete these notebooks?}}"
|
||||
msgstr "{count, plural, one {Are you sure you want to permanently delete this notebook?} other {Are you sure you to permanently delete these notebooks?}}"
|
||||
|
||||
#: generated/action-confirmations.ts:69
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this version?} other {Are you sure you to permanently delete these versions?}}"
|
||||
msgstr "{count, plural, one {Are you sure you want to permanently delete this version?} other {Are you sure you to permanently delete these versions?}}"
|
||||
|
||||
#: src/strings.ts:135
|
||||
msgid "{count, plural, one {Attach image} other {Attach # images}}"
|
||||
msgstr "{count, plural, one {Attach image} other {Attach # images}}"
|
||||
@@ -166,7 +162,7 @@ msgstr "{count, plural, one {Attachment deleted} other {# attachments deleted}}"
|
||||
msgid "{count, plural, one {Attachment downloaded at {path}} other {#/{total} attachments downloaded as a zip file at {path}}}"
|
||||
msgstr "{count, plural, one {Attachment downloaded at {path}} other {#/{total} attachments downloaded as a zip file at {path}}}"
|
||||
|
||||
#: generated/actions.ts:222
|
||||
#: generated/actions.ts:216
|
||||
msgid "{count, plural, one {Color renamed} other {# colors renamed}}"
|
||||
msgstr "{count, plural, one {Color renamed} other {# colors renamed}}"
|
||||
|
||||
@@ -179,7 +175,7 @@ msgid "{count, plural, one {Delete color} other {Delete # colors}}"
|
||||
msgstr "{count, plural, one {Delete color} other {Delete # colors}}"
|
||||
|
||||
#: generated/do-actions.ts:12
|
||||
#: generated/do-actions.ts:59
|
||||
#: generated/do-actions.ts:53
|
||||
msgid "{count, plural, one {Delete item} other {Delete # items}}"
|
||||
msgstr "{count, plural, one {Delete item} other {Delete # items}}"
|
||||
|
||||
@@ -199,10 +195,6 @@ msgstr "{count, plural, one {Delete reminder} other {Delete # reminders}}"
|
||||
msgid "{count, plural, one {Delete tag} other {Delete # tags}}"
|
||||
msgstr "{count, plural, one {Delete tag} other {Delete # tags}}"
|
||||
|
||||
#: generated/do-actions.ts:36
|
||||
msgid "{count, plural, one {Delete version} other {Delete # versions}}"
|
||||
msgstr "{count, plural, one {Delete version} other {Delete # versions}}"
|
||||
|
||||
#: generated/in-progress-actions.ts:16
|
||||
msgid "{count, plural, one {Deleting attachment...} other {Deleting # attachments...}}"
|
||||
msgstr "{count, plural, one {Deleting attachment...} other {Deleting # attachments...}}"
|
||||
@@ -227,27 +219,27 @@ msgstr "{count, plural, one {Deleting reminder...} other {Deleting # reminders..
|
||||
msgid "{count, plural, one {Deleting tag...} other {Deleting # tags...}}"
|
||||
msgstr "{count, plural, one {Deleting tag...} other {Deleting # tags...}}"
|
||||
|
||||
#: generated/do-actions.ts:280
|
||||
#: generated/do-actions.ts:274
|
||||
msgid "{count, plural, one {Download attachment} other {Download # attachments}}"
|
||||
msgstr "{count, plural, one {Download attachment} other {Download # attachments}}"
|
||||
|
||||
#: generated/do-actions.ts:289
|
||||
#: generated/do-actions.ts:283
|
||||
msgid "{count, plural, one {Download item} other {Download # items}}"
|
||||
msgstr "{count, plural, one {Download item} other {Download # items}}"
|
||||
|
||||
#: generated/do-actions.ts:214
|
||||
#: generated/do-actions.ts:208
|
||||
msgid "{count, plural, one {Edit item} other {Edit # items}}"
|
||||
msgstr "{count, plural, one {Edit item} other {Edit # items}}"
|
||||
|
||||
#: generated/do-actions.ts:197
|
||||
#: generated/do-actions.ts:191
|
||||
msgid "{count, plural, one {Edit notebook} other {Edit # notebooks}}"
|
||||
msgstr "{count, plural, one {Edit notebook} other {Edit # notebooks}}"
|
||||
|
||||
#: generated/do-actions.ts:201
|
||||
#: generated/do-actions.ts:195
|
||||
msgid "{count, plural, one {Edit reminder} other {Edit # reminders}}"
|
||||
msgstr "{count, plural, one {Edit reminder} other {Edit # reminders}}"
|
||||
|
||||
#: generated/do-actions.ts:193
|
||||
#: generated/do-actions.ts:187
|
||||
msgid "{count, plural, one {Edit tag} other {Edit # tags}}"
|
||||
msgstr "{count, plural, one {Edit tag} other {Edit # tags}}"
|
||||
|
||||
@@ -263,41 +255,41 @@ msgstr "{count, plural, one {Item could not be published} other {# items could n
|
||||
msgid "{count, plural, one {Item could not be unpublished} other {# items could not be unpublished}}"
|
||||
msgstr "{count, plural, one {Item could not be unpublished} other {# items could not be unpublished}}"
|
||||
|
||||
#: generated/actions.ts:214
|
||||
#: generated/actions.ts:208
|
||||
msgid "{count, plural, one {Item created} other {# items created}}"
|
||||
msgstr "{count, plural, one {Item created} other {# items created}}"
|
||||
|
||||
#: generated/actions.ts:47
|
||||
#: generated/actions.ts:41
|
||||
msgid "{count, plural, one {Item deleted} other {# items deleted}}"
|
||||
msgstr "{count, plural, one {Item deleted} other {# items deleted}}"
|
||||
|
||||
#: generated/actions.ts:185
|
||||
#: generated/actions.ts:179
|
||||
msgid "{count, plural, one {Item edited} other {# items edited}}"
|
||||
msgstr "{count, plural, one {Item edited} other {# items edited}}"
|
||||
|
||||
#: generated/actions.ts:70
|
||||
#: generated/actions.ts:64
|
||||
msgid "{count, plural, one {Item moved to trash} other {# items moved to trash}}"
|
||||
msgstr "{count, plural, one {Item moved to trash} other {# items moved to trash}}"
|
||||
|
||||
#: generated/actions.ts:86
|
||||
#: generated/actions.ts:99
|
||||
#: generated/actions.ts:80
|
||||
#: generated/actions.ts:93
|
||||
msgid "{count, plural, one {Item permanently deleted} other {# items permanently deleted}}"
|
||||
msgstr "{count, plural, one {Item permanently deleted} other {# items permanently deleted}}"
|
||||
|
||||
#: generated/actions.ts:116
|
||||
#: generated/actions.ts:110
|
||||
msgid "{count, plural, one {Item published} other {# items published}}"
|
||||
msgstr "{count, plural, one {Item published} other {# items published}}"
|
||||
|
||||
#: generated/actions.ts:231
|
||||
#: generated/actions.ts:225
|
||||
msgid "{count, plural, one {Item renamed} other {# items renamed}}"
|
||||
msgstr "{count, plural, one {Item renamed} other {# items renamed}}"
|
||||
|
||||
#: generated/actions.ts:149
|
||||
#: generated/actions.ts:162
|
||||
#: generated/actions.ts:143
|
||||
#: generated/actions.ts:156
|
||||
msgid "{count, plural, one {Item restored} other {# items restored}}"
|
||||
msgstr "{count, plural, one {Item restored} other {# items restored}}"
|
||||
|
||||
#: generated/actions.ts:133
|
||||
#: generated/actions.ts:127
|
||||
msgid "{count, plural, one {Item unpublished} other {# items unpublished}}"
|
||||
msgstr "{count, plural, one {Item unpublished} other {# items unpublished}}"
|
||||
|
||||
@@ -329,23 +321,23 @@ msgstr "{count, plural, one {Note deleted} other {# notes deleted}}"
|
||||
msgid "{count, plural, one {Note exported} other {# notes exported}}"
|
||||
msgstr "{count, plural, one {Note exported} other {# notes exported}}"
|
||||
|
||||
#: generated/actions.ts:55
|
||||
#: generated/actions.ts:49
|
||||
msgid "{count, plural, one {Note moved to trash} other {# notes moved to trash}}"
|
||||
msgstr "{count, plural, one {Note moved to trash} other {# notes moved to trash}}"
|
||||
|
||||
#: generated/actions.ts:78
|
||||
#: generated/actions.ts:72
|
||||
msgid "{count, plural, one {Note permanently deleted} other {# notes permanently deleted}}"
|
||||
msgstr "{count, plural, one {Note permanently deleted} other {# notes permanently deleted}}"
|
||||
|
||||
#: generated/actions.ts:107
|
||||
#: generated/actions.ts:101
|
||||
msgid "{count, plural, one {Note published} other {# notes published}}"
|
||||
msgstr "{count, plural, one {Note published} other {# notes published}}"
|
||||
|
||||
#: generated/actions.ts:141
|
||||
#: generated/actions.ts:135
|
||||
msgid "{count, plural, one {Note restored} other {# notes restored}}"
|
||||
msgstr "{count, plural, one {Note restored} other {# notes restored}}"
|
||||
|
||||
#: generated/actions.ts:124
|
||||
#: generated/actions.ts:118
|
||||
msgid "{count, plural, one {Note unpublished} other {# notes unpublished}}"
|
||||
msgstr "{count, plural, one {Note unpublished} other {# notes unpublished}}"
|
||||
|
||||
@@ -353,7 +345,7 @@ msgstr "{count, plural, one {Note unpublished} other {# notes unpublished}}"
|
||||
msgid "{count, plural, one {Note will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?} other {# notes will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?}}"
|
||||
msgstr "{count, plural, one {Note will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?} other {# notes will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?}}"
|
||||
|
||||
#: generated/actions.ts:193
|
||||
#: generated/actions.ts:187
|
||||
msgid "{count, plural, one {Notebook created} other {# notebooks created}}"
|
||||
msgstr "{count, plural, one {Notebook created} other {# notebooks created}}"
|
||||
|
||||
@@ -361,28 +353,28 @@ msgstr "{count, plural, one {Notebook created} other {# notebooks created}}"
|
||||
msgid "{count, plural, one {Notebook deleted} other {# notebooks deleted}}"
|
||||
msgstr "{count, plural, one {Notebook deleted} other {# notebooks deleted}}"
|
||||
|
||||
#: generated/actions.ts:174
|
||||
#: generated/actions.ts:168
|
||||
msgid "{count, plural, one {Notebook edited} other {# notebooks edited}}"
|
||||
msgstr "{count, plural, one {Notebook edited} other {# notebooks edited}}"
|
||||
|
||||
#: generated/actions.ts:59
|
||||
#: generated/actions.ts:53
|
||||
msgid "{count, plural, one {Notebook moved to trash} other {# notebooks moved to trash}}"
|
||||
msgstr "{count, plural, one {Notebook moved to trash} other {# notebooks moved to trash}}"
|
||||
|
||||
#: generated/actions.ts:82
|
||||
#: generated/actions.ts:76
|
||||
msgid "{count, plural, one {Notebook permanently deleted} other {# notebooks permanently deleted}}"
|
||||
msgstr "{count, plural, one {Notebook permanently deleted} other {# notebooks permanently deleted}}"
|
||||
|
||||
#: generated/actions.ts:145
|
||||
#: generated/actions.ts:139
|
||||
msgid "{count, plural, one {Notebook restored} other {# notebooks restored}}"
|
||||
msgstr "{count, plural, one {Notebook restored} other {# notebooks restored}}"
|
||||
|
||||
#: generated/do-actions.ts:147
|
||||
#: generated/do-actions.ts:141
|
||||
msgid "{count, plural, one {Permanently delete attachment} other {Permanently delete # attachments}}"
|
||||
msgstr "{count, plural, one {Permanently delete attachment} other {Permanently delete # attachments}}"
|
||||
|
||||
#: generated/do-actions.ts:151
|
||||
#: generated/do-actions.ts:162
|
||||
#: generated/do-actions.ts:145
|
||||
#: generated/do-actions.ts:156
|
||||
msgid "{count, plural, one {Permanently delete item} other {Permanently delete # items}}"
|
||||
msgstr "{count, plural, one {Permanently delete item} other {Permanently delete # items}}"
|
||||
|
||||
@@ -391,15 +383,15 @@ msgstr "{count, plural, one {Permanently delete item} other {Permanently delete
|
||||
msgid "{count, plural, one {permanently deleting item...} other {permanently deleting # items...}}"
|
||||
msgstr "{count, plural, one {permanently deleting item...} other {permanently deleting # items...}}"
|
||||
|
||||
#: generated/do-actions.ts:105
|
||||
#: generated/do-actions.ts:99
|
||||
msgid "{count, plural, one {Pin item} other {Pin # items}}"
|
||||
msgstr "{count, plural, one {Pin item} other {Pin # items}}"
|
||||
|
||||
#: generated/do-actions.ts:90
|
||||
#: generated/do-actions.ts:84
|
||||
msgid "{count, plural, one {Pin note} other {Pin # notes}}"
|
||||
msgstr "{count, plural, one {Pin note} other {Pin # notes}}"
|
||||
|
||||
#: generated/do-actions.ts:94
|
||||
#: generated/do-actions.ts:88
|
||||
msgid "{count, plural, one {Pin notebook} other {Pin # notebooks}}"
|
||||
msgstr "{count, plural, one {Pin notebook} other {Pin # notebooks}}"
|
||||
|
||||
@@ -407,11 +399,11 @@ msgstr "{count, plural, one {Pin notebook} other {Pin # notebooks}}"
|
||||
msgid "{count, plural, one {Prevent note from syncing} other {Prevent # notes from syncing}}"
|
||||
msgstr "{count, plural, one {Prevent note from syncing} other {Prevent # notes from syncing}}"
|
||||
|
||||
#: generated/do-actions.ts:139
|
||||
#: generated/do-actions.ts:133
|
||||
msgid "{count, plural, one {Publish item} other {Publish # items}}"
|
||||
msgstr "{count, plural, one {Publish item} other {Publish # items}}"
|
||||
|
||||
#: generated/do-actions.ts:130
|
||||
#: generated/do-actions.ts:124
|
||||
msgid "{count, plural, one {Publish note} other {Publish # notes}}"
|
||||
msgstr "{count, plural, one {Publish note} other {Publish # notes}}"
|
||||
|
||||
@@ -419,47 +411,47 @@ msgstr "{count, plural, one {Publish note} other {Publish # notes}}"
|
||||
msgid "{count, plural, one {Reminder deleted} other {# reminders deleted}}"
|
||||
msgstr "{count, plural, one {Reminder deleted} other {# reminders deleted}}"
|
||||
|
||||
#: generated/do-actions.ts:259
|
||||
#: generated/do-actions.ts:253
|
||||
msgid "{count, plural, one {Remove attachment} other {Remove # attachments}}"
|
||||
msgstr "{count, plural, one {Remove attachment} other {Remove # attachments}}"
|
||||
|
||||
#: generated/do-actions.ts:255
|
||||
#: generated/do-actions.ts:249
|
||||
msgid "{count, plural, one {Remove color} other {Remove # colors}}"
|
||||
msgstr "{count, plural, one {Remove color} other {Remove # colors}}"
|
||||
|
||||
#: generated/do-actions.ts:272
|
||||
#: generated/do-actions.ts:266
|
||||
msgid "{count, plural, one {Remove item} other {Remove # items}}"
|
||||
msgstr "{count, plural, one {Remove item} other {Remove # items}}"
|
||||
|
||||
#: generated/do-actions.ts:251
|
||||
#: generated/do-actions.ts:245
|
||||
msgid "{count, plural, one {Remove shortcut} other {Remove # shortcuts}}"
|
||||
msgstr "{count, plural, one {Remove shortcut} other {Remove # shortcuts}}"
|
||||
|
||||
#: generated/do-actions.ts:222
|
||||
#: generated/do-actions.ts:216
|
||||
msgid "{count, plural, one {Rename attachment} other {Rename # attachments}}"
|
||||
msgstr "{count, plural, one {Rename attachment} other {Rename # attachments}}"
|
||||
|
||||
#: generated/do-actions.ts:226
|
||||
#: generated/do-actions.ts:220
|
||||
msgid "{count, plural, one {Rename color} other {Rename # colors}}"
|
||||
msgstr "{count, plural, one {Rename color} other {Rename # colors}}"
|
||||
|
||||
#: generated/do-actions.ts:243
|
||||
#: generated/do-actions.ts:237
|
||||
msgid "{count, plural, one {Rename item} other {Rename # items}}"
|
||||
msgstr "{count, plural, one {Rename item} other {Rename # items}}"
|
||||
|
||||
#: generated/do-actions.ts:230
|
||||
#: generated/do-actions.ts:224
|
||||
msgid "{count, plural, one {Rename tag} other {Rename # tags}}"
|
||||
msgstr "{count, plural, one {Rename tag} other {Rename # tags}}"
|
||||
|
||||
#: generated/do-actions.ts:185
|
||||
#: generated/do-actions.ts:179
|
||||
msgid "{count, plural, one {Restore item} other {Restore # items}}"
|
||||
msgstr "{count, plural, one {Restore item} other {Restore # items}}"
|
||||
|
||||
#: generated/do-actions.ts:170
|
||||
#: generated/do-actions.ts:164
|
||||
msgid "{count, plural, one {Restore note} other {Restore # notes}}"
|
||||
msgstr "{count, plural, one {Restore note} other {Restore # notes}}"
|
||||
|
||||
#: generated/do-actions.ts:174
|
||||
#: generated/do-actions.ts:168
|
||||
msgid "{count, plural, one {Restore notebook} other {Restore # notebooks}}"
|
||||
msgstr "{count, plural, one {Restore notebook} other {Restore # notebooks}}"
|
||||
|
||||
@@ -468,11 +460,11 @@ msgstr "{count, plural, one {Restore notebook} other {Restore # notebooks}}"
|
||||
msgid "{count, plural, one {Restoring item...} other {Restoring # items...}}"
|
||||
msgstr "{count, plural, one {Restoring item...} other {Restoring # items...}}"
|
||||
|
||||
#: generated/actions.ts:201
|
||||
#: generated/actions.ts:195
|
||||
msgid "{count, plural, one {Shortcut created} other {# shortcuts created}}"
|
||||
msgstr "{count, plural, one {Shortcut created} other {# shortcuts created}}"
|
||||
|
||||
#: generated/actions.ts:197
|
||||
#: generated/actions.ts:191
|
||||
msgid "{count, plural, one {Tag created} other {# tags created}}"
|
||||
msgstr "{count, plural, one {Tag created} other {# tags created}}"
|
||||
|
||||
@@ -480,34 +472,30 @@ msgstr "{count, plural, one {Tag created} other {# tags created}}"
|
||||
msgid "{count, plural, one {Tag deleted} other {# tags deleted}}"
|
||||
msgstr "{count, plural, one {Tag deleted} other {# tags deleted}}"
|
||||
|
||||
#: generated/actions.ts:170
|
||||
#: generated/actions.ts:164
|
||||
msgid "{count, plural, one {Tag edited} other {# tags edited}}"
|
||||
msgstr "{count, plural, one {Tag edited} other {# tags edited}}"
|
||||
|
||||
#: generated/do-actions.ts:82
|
||||
#: generated/do-actions.ts:76
|
||||
msgid "{count, plural, one {Unpin item} other {Unpin # items}}"
|
||||
msgstr "{count, plural, one {Unpin item} other {Unpin # items}}"
|
||||
|
||||
#: generated/do-actions.ts:67
|
||||
#: generated/do-actions.ts:61
|
||||
msgid "{count, plural, one {Unpin note} other {Unpin # notes}}"
|
||||
msgstr "{count, plural, one {Unpin note} other {Unpin # notes}}"
|
||||
|
||||
#: generated/do-actions.ts:71
|
||||
#: generated/do-actions.ts:65
|
||||
msgid "{count, plural, one {Unpin notebook} other {Unpin # notebooks}}"
|
||||
msgstr "{count, plural, one {Unpin notebook} other {Unpin # notebooks}}"
|
||||
|
||||
#: generated/do-actions.ts:122
|
||||
#: generated/do-actions.ts:116
|
||||
msgid "{count, plural, one {Unpublish item} other {Unpublish # items}}"
|
||||
msgstr "{count, plural, one {Unpublish item} other {Unpublish # items}}"
|
||||
|
||||
#: generated/do-actions.ts:113
|
||||
#: generated/do-actions.ts:107
|
||||
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
msgstr "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
|
||||
#: generated/actions.ts:28
|
||||
msgid "{count, plural, one {Version deleted} other {# versions deleted}}"
|
||||
msgstr "{count, plural, one {Version deleted} other {# versions deleted}}"
|
||||
|
||||
#: src/strings.ts:2510
|
||||
msgid "{count} characters"
|
||||
msgstr "{count} characters"
|
||||
@@ -1659,10 +1647,6 @@ msgstr "Clear data & reset account"
|
||||
msgid "Clear default notebook"
|
||||
msgstr "Clear default notebook"
|
||||
|
||||
#: src/strings.ts:2800
|
||||
msgid "Clear history"
|
||||
msgstr "Clear history"
|
||||
|
||||
#: src/strings.ts:1015
|
||||
msgid "Clear logs"
|
||||
msgstr "Clear logs"
|
||||
@@ -2311,10 +2295,6 @@ msgstr "Delete account"
|
||||
msgid "Delete all"
|
||||
msgstr "Delete all"
|
||||
|
||||
#: src/strings.ts:2802
|
||||
msgid "Delete all version history for this note?"
|
||||
msgstr "Delete all version history for this note?"
|
||||
|
||||
#: src/strings.ts:2732
|
||||
msgid "Delete attachment"
|
||||
msgstr "Delete attachment"
|
||||
@@ -3841,10 +3821,6 @@ msgstr "Keep"
|
||||
msgid "Keep open"
|
||||
msgstr "Keep open"
|
||||
|
||||
#: src/strings.ts:2800
|
||||
msgid "Keep screen on"
|
||||
msgstr "Keep screen on"
|
||||
|
||||
#: src/strings.ts:1361
|
||||
msgid "Keep your data safe"
|
||||
msgstr "Keep your data safe"
|
||||
@@ -5215,10 +5191,6 @@ msgstr "Pressing \"X\" will hide the app in your system tray."
|
||||
msgid "Prevent note title from appearing in tab/window title."
|
||||
msgstr "Prevent note title from appearing in tab/window title."
|
||||
|
||||
#: src/strings.ts:2802
|
||||
msgid "Prevent the screen from turning off while the editor is focused."
|
||||
msgstr "Prevent the screen from turning off while the editor is focused."
|
||||
|
||||
#: src/strings.ts:2325
|
||||
msgid "Preview attachment"
|
||||
msgstr "Preview attachment"
|
||||
@@ -7553,10 +7525,6 @@ msgstr "Verifying your email"
|
||||
msgid "Version"
|
||||
msgstr "Version"
|
||||
|
||||
#: src/strings.ts:2801
|
||||
msgid "Version history cleared"
|
||||
msgstr "Version history cleared"
|
||||
|
||||
#: src/strings.ts:50
|
||||
msgid "Vibrate"
|
||||
msgstr "Vibrate"
|
||||
|
||||
@@ -138,7 +138,7 @@ msgstr ""
|
||||
msgid "{count, plural, one {Are you sure you want to move this notebook to {selectedNotebookTitle}?} other {Are you sure you want to move these # notebooks {selectedNotebookTitle}?}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/action-confirmations.ts:82
|
||||
#: generated/action-confirmations.ts:76
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this item?} other {Are you sure you to permanently delete these items?}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -150,10 +150,6 @@ msgstr ""
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this notebook?} other {Are you sure you to permanently delete these notebooks?}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/action-confirmations.ts:69
|
||||
msgid "{count, plural, one {Are you sure you want to permanently delete this version?} other {Are you sure you to permanently delete these versions?}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:135
|
||||
msgid "{count, plural, one {Attach image} other {Attach # images}}"
|
||||
msgstr ""
|
||||
@@ -166,7 +162,7 @@ msgstr ""
|
||||
msgid "{count, plural, one {Attachment downloaded at {path}} other {#/{total} attachments downloaded as a zip file at {path}}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:222
|
||||
#: generated/actions.ts:216
|
||||
msgid "{count, plural, one {Color renamed} other {# colors renamed}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -179,7 +175,7 @@ msgid "{count, plural, one {Delete color} other {Delete # colors}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:12
|
||||
#: generated/do-actions.ts:59
|
||||
#: generated/do-actions.ts:53
|
||||
msgid "{count, plural, one {Delete item} other {Delete # items}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -199,10 +195,6 @@ msgstr ""
|
||||
msgid "{count, plural, one {Delete tag} other {Delete # tags}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:36
|
||||
msgid "{count, plural, one {Delete version} other {Delete # versions}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/in-progress-actions.ts:16
|
||||
msgid "{count, plural, one {Deleting attachment...} other {Deleting # attachments...}}"
|
||||
msgstr ""
|
||||
@@ -227,27 +219,27 @@ msgstr ""
|
||||
msgid "{count, plural, one {Deleting tag...} other {Deleting # tags...}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:280
|
||||
#: generated/do-actions.ts:274
|
||||
msgid "{count, plural, one {Download attachment} other {Download # attachments}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:289
|
||||
#: generated/do-actions.ts:283
|
||||
msgid "{count, plural, one {Download item} other {Download # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:214
|
||||
#: generated/do-actions.ts:208
|
||||
msgid "{count, plural, one {Edit item} other {Edit # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:197
|
||||
#: generated/do-actions.ts:191
|
||||
msgid "{count, plural, one {Edit notebook} other {Edit # notebooks}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:201
|
||||
#: generated/do-actions.ts:195
|
||||
msgid "{count, plural, one {Edit reminder} other {Edit # reminders}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:193
|
||||
#: generated/do-actions.ts:187
|
||||
msgid "{count, plural, one {Edit tag} other {Edit # tags}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -263,41 +255,41 @@ msgstr ""
|
||||
msgid "{count, plural, one {Item could not be unpublished} other {# items could not be unpublished}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:214
|
||||
#: generated/actions.ts:208
|
||||
msgid "{count, plural, one {Item created} other {# items created}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:47
|
||||
#: generated/actions.ts:41
|
||||
msgid "{count, plural, one {Item deleted} other {# items deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:185
|
||||
#: generated/actions.ts:179
|
||||
msgid "{count, plural, one {Item edited} other {# items edited}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:70
|
||||
#: generated/actions.ts:64
|
||||
msgid "{count, plural, one {Item moved to trash} other {# items moved to trash}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:86
|
||||
#: generated/actions.ts:99
|
||||
#: generated/actions.ts:80
|
||||
#: generated/actions.ts:93
|
||||
msgid "{count, plural, one {Item permanently deleted} other {# items permanently deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:116
|
||||
#: generated/actions.ts:110
|
||||
msgid "{count, plural, one {Item published} other {# items published}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:231
|
||||
#: generated/actions.ts:225
|
||||
msgid "{count, plural, one {Item renamed} other {# items renamed}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:149
|
||||
#: generated/actions.ts:162
|
||||
#: generated/actions.ts:143
|
||||
#: generated/actions.ts:156
|
||||
msgid "{count, plural, one {Item restored} other {# items restored}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:133
|
||||
#: generated/actions.ts:127
|
||||
msgid "{count, plural, one {Item unpublished} other {# items unpublished}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -329,23 +321,23 @@ msgstr ""
|
||||
msgid "{count, plural, one {Note exported} other {# notes exported}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:55
|
||||
#: generated/actions.ts:49
|
||||
msgid "{count, plural, one {Note moved to trash} other {# notes moved to trash}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:78
|
||||
#: generated/actions.ts:72
|
||||
msgid "{count, plural, one {Note permanently deleted} other {# notes permanently deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:107
|
||||
#: generated/actions.ts:101
|
||||
msgid "{count, plural, one {Note published} other {# notes published}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:141
|
||||
#: generated/actions.ts:135
|
||||
msgid "{count, plural, one {Note restored} other {# notes restored}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:124
|
||||
#: generated/actions.ts:118
|
||||
msgid "{count, plural, one {Note unpublished} other {# notes unpublished}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -353,7 +345,7 @@ msgstr ""
|
||||
msgid "{count, plural, one {Note will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?} other {# notes will be automatically deleted from all other devices & any future changes won't get synced. Are you sure you want to continue?}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:193
|
||||
#: generated/actions.ts:187
|
||||
msgid "{count, plural, one {Notebook created} other {# notebooks created}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -361,28 +353,28 @@ msgstr ""
|
||||
msgid "{count, plural, one {Notebook deleted} other {# notebooks deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:174
|
||||
#: generated/actions.ts:168
|
||||
msgid "{count, plural, one {Notebook edited} other {# notebooks edited}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:59
|
||||
#: generated/actions.ts:53
|
||||
msgid "{count, plural, one {Notebook moved to trash} other {# notebooks moved to trash}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:82
|
||||
#: generated/actions.ts:76
|
||||
msgid "{count, plural, one {Notebook permanently deleted} other {# notebooks permanently deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:145
|
||||
#: generated/actions.ts:139
|
||||
msgid "{count, plural, one {Notebook restored} other {# notebooks restored}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:147
|
||||
#: generated/do-actions.ts:141
|
||||
msgid "{count, plural, one {Permanently delete attachment} other {Permanently delete # attachments}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:151
|
||||
#: generated/do-actions.ts:162
|
||||
#: generated/do-actions.ts:145
|
||||
#: generated/do-actions.ts:156
|
||||
msgid "{count, plural, one {Permanently delete item} other {Permanently delete # items}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -391,15 +383,15 @@ msgstr ""
|
||||
msgid "{count, plural, one {permanently deleting item...} other {permanently deleting # items...}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:105
|
||||
#: generated/do-actions.ts:99
|
||||
msgid "{count, plural, one {Pin item} other {Pin # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:90
|
||||
#: generated/do-actions.ts:84
|
||||
msgid "{count, plural, one {Pin note} other {Pin # notes}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:94
|
||||
#: generated/do-actions.ts:88
|
||||
msgid "{count, plural, one {Pin notebook} other {Pin # notebooks}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -407,11 +399,11 @@ msgstr ""
|
||||
msgid "{count, plural, one {Prevent note from syncing} other {Prevent # notes from syncing}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:139
|
||||
#: generated/do-actions.ts:133
|
||||
msgid "{count, plural, one {Publish item} other {Publish # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:130
|
||||
#: generated/do-actions.ts:124
|
||||
msgid "{count, plural, one {Publish note} other {Publish # notes}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -419,47 +411,47 @@ msgstr ""
|
||||
msgid "{count, plural, one {Reminder deleted} other {# reminders deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:259
|
||||
#: generated/do-actions.ts:253
|
||||
msgid "{count, plural, one {Remove attachment} other {Remove # attachments}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:255
|
||||
#: generated/do-actions.ts:249
|
||||
msgid "{count, plural, one {Remove color} other {Remove # colors}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:272
|
||||
#: generated/do-actions.ts:266
|
||||
msgid "{count, plural, one {Remove item} other {Remove # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:251
|
||||
#: generated/do-actions.ts:245
|
||||
msgid "{count, plural, one {Remove shortcut} other {Remove # shortcuts}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:222
|
||||
#: generated/do-actions.ts:216
|
||||
msgid "{count, plural, one {Rename attachment} other {Rename # attachments}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:226
|
||||
#: generated/do-actions.ts:220
|
||||
msgid "{count, plural, one {Rename color} other {Rename # colors}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:243
|
||||
#: generated/do-actions.ts:237
|
||||
msgid "{count, plural, one {Rename item} other {Rename # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:230
|
||||
#: generated/do-actions.ts:224
|
||||
msgid "{count, plural, one {Rename tag} other {Rename # tags}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:185
|
||||
#: generated/do-actions.ts:179
|
||||
msgid "{count, plural, one {Restore item} other {Restore # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:170
|
||||
#: generated/do-actions.ts:164
|
||||
msgid "{count, plural, one {Restore note} other {Restore # notes}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:174
|
||||
#: generated/do-actions.ts:168
|
||||
msgid "{count, plural, one {Restore notebook} other {Restore # notebooks}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -468,11 +460,11 @@ msgstr ""
|
||||
msgid "{count, plural, one {Restoring item...} other {Restoring # items...}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:201
|
||||
#: generated/actions.ts:195
|
||||
msgid "{count, plural, one {Shortcut created} other {# shortcuts created}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:197
|
||||
#: generated/actions.ts:191
|
||||
msgid "{count, plural, one {Tag created} other {# tags created}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -480,34 +472,30 @@ msgstr ""
|
||||
msgid "{count, plural, one {Tag deleted} other {# tags deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:170
|
||||
#: generated/actions.ts:164
|
||||
msgid "{count, plural, one {Tag edited} other {# tags edited}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:82
|
||||
#: generated/do-actions.ts:76
|
||||
msgid "{count, plural, one {Unpin item} other {Unpin # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:67
|
||||
#: generated/do-actions.ts:61
|
||||
msgid "{count, plural, one {Unpin note} other {Unpin # notes}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:71
|
||||
#: generated/do-actions.ts:65
|
||||
msgid "{count, plural, one {Unpin notebook} other {Unpin # notebooks}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:122
|
||||
#: generated/do-actions.ts:116
|
||||
msgid "{count, plural, one {Unpublish item} other {Unpublish # items}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/do-actions.ts:113
|
||||
#: generated/do-actions.ts:107
|
||||
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
msgstr ""
|
||||
|
||||
#: generated/actions.ts:28
|
||||
msgid "{count, plural, one {Version deleted} other {# versions deleted}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2510
|
||||
msgid "{count} characters"
|
||||
msgstr ""
|
||||
@@ -1659,10 +1647,6 @@ msgstr ""
|
||||
msgid "Clear default notebook"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2800
|
||||
msgid "Clear history"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:1015
|
||||
msgid "Clear logs"
|
||||
msgstr ""
|
||||
@@ -2300,10 +2284,6 @@ msgstr ""
|
||||
msgid "Delete all"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2802
|
||||
msgid "Delete all version history for this note?"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2732
|
||||
msgid "Delete attachment"
|
||||
msgstr ""
|
||||
@@ -3821,10 +3801,6 @@ msgstr ""
|
||||
msgid "Keep open"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2800
|
||||
msgid "Keep screen on"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:1361
|
||||
msgid "Keep your data safe"
|
||||
msgstr ""
|
||||
@@ -5189,10 +5165,6 @@ msgstr ""
|
||||
msgid "Prevent note title from appearing in tab/window title."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2802
|
||||
msgid "Prevent the screen from turning off while the editor is focused."
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2325
|
||||
msgid "Preview attachment"
|
||||
msgstr ""
|
||||
@@ -7503,10 +7475,6 @@ msgstr ""
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2801
|
||||
msgid "Version history cleared"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:50
|
||||
msgid "Vibrate"
|
||||
msgstr ""
|
||||
|
||||
@@ -30,8 +30,7 @@ const DO_ACTIONS = [
|
||||
"notebook",
|
||||
"tag",
|
||||
"color",
|
||||
"attachment",
|
||||
"version"
|
||||
"attachment"
|
||||
]
|
||||
},
|
||||
{ action: "unpin", label: "Unpin", dataTypes: ["note", "notebook"] },
|
||||
@@ -74,7 +73,7 @@ const ACTIONS = [
|
||||
{
|
||||
action: "deleted",
|
||||
label: "deleted",
|
||||
dataTypes: ["attachment", "reminder", "tag", "note", "notebook", "version"]
|
||||
dataTypes: ["attachment", "reminder", "tag", "note", "notebook"]
|
||||
},
|
||||
{
|
||||
action: "movedToTrash",
|
||||
@@ -122,12 +121,12 @@ const ACTION_CONFIRMATIONS = [
|
||||
"tag",
|
||||
"color",
|
||||
"attachment"
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
action: "permanentlyDelete",
|
||||
label: "permanently delete",
|
||||
dataTypes: ["note", "notebook", "version"]
|
||||
dataTypes: ["note", "notebook"]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -210,12 +209,6 @@ const DATA_TYPES = {
|
||||
singularCamelCase: `Shortcut`,
|
||||
plural: `shortcuts`,
|
||||
pluralCamelCase: `Shortcuts`
|
||||
},
|
||||
version: {
|
||||
singular: `version`,
|
||||
singularCamelCase: `Version`,
|
||||
plural: `versions`,
|
||||
pluralCamelCase: `Versions`
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2796,15 +2796,5 @@ Continue without attachments?`,
|
||||
t`Colornote password for ${filename}`,
|
||||
colorNotPasswordForDesc: () =>
|
||||
t`The password for decrypting the Colornote backup file.`,
|
||||
deleteItem: () => t`Delete item`,
|
||||
keepScreenOn: () => t`Keep screen on`,
|
||||
keepScreenOnDesc: () =>
|
||||
t`Prevent the screen from turning off while the editor is focused.`,
|
||||
clearHistory: () => t`Clear history`,
|
||||
historyCleared: () => t`Version history cleared`,
|
||||
clearHistoryConfirmation: () => t`Delete all version history for this note?`,
|
||||
deleteVersion: () => doActions.delete.version(1),
|
||||
deleteVersionConfirmation: () =>
|
||||
actionConfirmations.permanentlyDelete.version(1),
|
||||
versionDeleted: () => actions.deleted.version(1)
|
||||
deleteItem: () => t`Delete item`
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user