Merge branch 'develop' into settings

This commit is contained in:
Ammar Ahmed
2022-04-19 23:15:54 +05:00
committed by GitHub
19 changed files with 3630 additions and 121 deletions

View File

@@ -1,10 +1,4 @@
- Sync over web-sockets - Improvements to sync performance
- Optionally disable section headers in lists - Added sort by title option in sort menu
- Formatting support for notification notes
- Fix bold text in editor
- Fix session-expired dialog does not hide after login
- Fix login issues when 2FA enabled
- Fix a race condition causing note to be empty in editor
- Fix pin to notifications not working
Thank you for using Notesnook! Thank you for using Notesnook!

View File

@@ -1,12 +1,3 @@
import { FeatureType } from './src/components/sheets/new-feature'; import { FeatureType } from './src/components/sheets/new-feature';
export const features: FeatureType[] = [ export const features: FeatureType[] = [];
{
title: 'Sync over web-sockets',
body: 'We have moved from SSE to web-sockets! Enjoy instant, fast and reliable sync with progress.'
},
{
title: 'Disable section headers',
body: 'Now you can disable section headers in lists by changing grouping to "none"'
}
];

View File

@@ -1118,7 +1118,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@@ -1191,7 +1191,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
@@ -1219,7 +1219,7 @@
CODE_SIGN_ENTITLEMENTS = Notesnook/Notesnook.entitlements; CODE_SIGN_ENTITLEMENTS = Notesnook/Notesnook.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
@@ -1291,7 +1291,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
@@ -1449,7 +1449,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -1460,7 +1460,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1490,7 +1490,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -1501,7 +1501,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1530,7 +1530,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements"; CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -1603,7 +1603,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1633,7 +1633,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1807; CURRENT_PROJECT_VERSION = 1809;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -1706,7 +1706,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.8.7; MARKETING_VERSION = 1.8.9;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,4 @@
- Sync over web-sockets - Improvements to sync performance
- Disable section headers in lists by changing grouping to "none" - Added sort by title option in sort menu
- Fix padding-left on bold text in editor
- Fix session-expired dialog does not hide after login
- Fix login issues when 2FA enabled on some devices
- Fix a race condition causing note to be empty in editor
- Fix pin to notifications not working for some notes
Thank you for using Notesnook! Thank you for using Notesnook!

View File

@@ -1,13 +1,4 @@
# What's new - Improvements to sync performance
- Sync over web-sockets - Added sort by title option in sort menu
- Optionally Disable section headers in lists by changing grouping to "none"
- Formatting support for notification notes
# What's fixed
- Fix padding-left on bold text in editor
- Fix session-expired dialog does not hide after login
- Fix login issues when 2FA enabled on some devices
- Fix a race condition causing note to be empty in editor
- Fix pin to notifications not working for some notes
Thank you for using Notesnook! Thank you for using Notesnook!

View File

@@ -1,6 +1,7 @@
import Clipboard from '@react-native-clipboard/clipboard'; import Clipboard from '@react-native-clipboard/clipboard';
import { getLinkPreview } from 'link-preview-js'; import { getLinkPreview } from 'link-preview-js';
import { HTMLRootElement } from 'node-html-parser/dist/nodes/html'; import { HTMLRootElement } from 'node-html-parser/dist/nodes/html';
import { parseHTML } from 'notes-core/utils/htmlparser';
import React, { Fragment, useEffect, useRef, useState } from 'react'; import React, { Fragment, useEffect, useRef, useState } from 'react';
import { import {
ActivityIndicator, ActivityIndicator,
@@ -8,18 +9,16 @@ import {
Keyboard, Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
Modal, Modal,
NativeModules,
Platform, Platform,
SafeAreaView, SafeAreaView,
ScrollView, ScrollView,
StatusBar, StatusBar,
Text, Text,
TouchableOpacity, TouchableOpacity,
UIManager,
useWindowDimensions, useWindowDimensions,
View View
} from 'react-native'; } from 'react-native';
import Animated, { acc, Easing, timing, useValue } from 'react-native-reanimated'; import Animated, { Easing, timing, useValue } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import WebView from 'react-native-webview'; import WebView from 'react-native-webview';
@@ -32,7 +31,6 @@ import Storage from '../src/utils/database/storage';
import { sleep } from '../src/utils/time'; import { sleep } from '../src/utils/time';
import { Search } from './search'; import { Search } from './search';
import { useShareStore } from './store'; import { useShareStore } from './store';
const AnimatedKAV = Animated.createAnimatedComponent(KeyboardAvoidingView); const AnimatedKAV = Animated.createAnimatedComponent(KeyboardAvoidingView);
const AnimatedSAV = Animated.createAnimatedComponent(SafeAreaView); const AnimatedSAV = Animated.createAnimatedComponent(SafeAreaView);
async function sanitizeHtml(site) { async function sanitizeHtml(site) {
@@ -114,8 +112,6 @@ function removeInvalidElements(document) {
* @param {HTMLRootElement} document * @param {HTMLRootElement} document
*/ */
function replaceSrcWithAbsoluteUrls(document, baseUrl) { function replaceSrcWithAbsoluteUrls(document, baseUrl) {
console.log('parsing:', document);
let images = document.querySelectorAll('img'); let images = document.querySelectorAll('img');
console.log(images.length); console.log(images.length);
for (var i = 0; i < images.length; i++) { for (var i = 0; i < images.length; i++) {
@@ -145,7 +141,7 @@ function replaceSrcWithAbsoluteUrls(document, baseUrl) {
*/ */
function fixCodeBlocks(document) { function fixCodeBlocks(document) {
let elements = document.querySelectorAll('code,pre'); let elements = document.querySelectorAll('code,pre');
console.log(elements.length);
for (let element of elements) { for (let element of elements) {
element.classList.add('.hljs'); element.classList.add('.hljs');
} }
@@ -153,13 +149,11 @@ function fixCodeBlocks(document) {
} }
function sanitize(html, baseUrl) { function sanitize(html, baseUrl) {
let { parse } = require('node-html-parser'); let parser = parseHTML(html);
let parser = parse(html);
parser = wrapTablesWithDiv(parser); parser = wrapTablesWithDiv(parser);
parser = removeInvalidElements(parser); parser = removeInvalidElements(parser);
parser = replaceSrcWithAbsoluteUrls(parser, baseUrl); parser = replaceSrcWithAbsoluteUrls(parser, baseUrl);
parser = fixCodeBlocks(parser); parser = fixCodeBlocks(parser);
let htmlString = parser.outerHTML; let htmlString = parser.outerHTML;
htmlString = htmlString + `<hr>${makeHtmlFromUrl(baseUrl)}`; htmlString = htmlString + `<hr>${makeHtmlFromUrl(baseUrl)}`;

View File

@@ -77,6 +77,7 @@ NewFeature.present = () => {
SettingsService.set({ SettingsService.set({
version: APP_VERSION version: APP_VERSION
}); });
if (features.length === 0) return;
presentSheet({ presentSheet({
component: <NewFeature features={features} /> component: <NewFeature features={features} />
}); });

View File

@@ -64,10 +64,10 @@ const Sort = ({ type, screen }) => {
<Button <Button
title={ title={
groupOptions.sortDirection === 'asc' groupOptions.sortDirection === 'asc'
? groupOptions.groupBy === 'abc' ? groupOptions.groupBy === 'abc' || groupOptions.sortBy === 'title'
? 'A - Z' ? 'A - Z'
: 'Old - New' : 'Old - New'
: groupOptions.groupBy === 'abc' : groupOptions.groupBy === 'abc' || groupOptions.sortBy === 'title'
? 'Z - A' ? 'Z - A'
: 'New - Old' : 'New - Old'
} }
@@ -114,32 +114,34 @@ const Sort = ({ type, screen }) => {
iconSize={SIZE.md} iconSize={SIZE.md}
/> />
) : ( ) : (
Object.keys(SORT).map((item, index) => ( Object.keys(SORT).map((item, index) =>
<Button item === 'title' && groupOptions.groupBy !== 'none' ? null : (
key={item} <Button
type={groupOptions.sortBy === item ? 'grayBg' : 'gray'} key={item}
title={SORT[item]} type={groupOptions.sortBy === item ? 'grayBg' : 'gray'}
height={40} title={SORT[item]}
iconPosition="left" height={40}
icon={groupOptions.sortBy === item ? 'check' : null} iconPosition="left"
style={{ icon={groupOptions.sortBy === item ? 'check' : null}
marginRight: 10, style={{
paddingHorizontal: 8 marginRight: 10,
}} paddingHorizontal: 8
buttonType={{ }}
text: groupOptions.sortBy === item ? colors.accent : colors.icon buttonType={{
}} text: groupOptions.sortBy === item ? colors.accent : colors.icon
fontSize={SIZE.sm} }}
onPress={async () => { fontSize={SIZE.sm}
let _groupOptions = { onPress={async () => {
...groupOptions, let _groupOptions = {
sortBy: type === 'trash' ? 'dateDeleted' : item ...groupOptions,
}; sortBy: type === 'trash' ? 'dateDeleted' : item
await updateGroupOptions(_groupOptions); };
}} await updateGroupOptions(_groupOptions);
iconSize={SIZE.md} }}
/> iconSize={SIZE.md}
)) />
)
)
)} )}
</View> </View>

View File

@@ -746,7 +746,8 @@ async function addToCollection(id) {
break; break;
} }
case 'color': { case 'color': {
await db.notes.note(id).color(editing.actionAfterFirstSave.id); console.log('after save action:', editing.actionAfterFirstSave.name);
await db.notes.note(id).color(editing.actionAfterFirstSave.color);
editing.actionAfterFirstSave = { editing.actionAfterFirstSave = {
type: null type: null
}; };

View File

@@ -10,6 +10,7 @@ import PremiumService from '../../../../services/premium';
import { editing } from '../../../../utils'; import { editing } from '../../../../utils';
import { db } from '../../../../utils/database'; import { db } from '../../../../utils/database';
import { eCloseProgressDialog } from '../../../../utils/events'; import { eCloseProgressDialog } from '../../../../utils/events';
import filesystem from '../../../../utils/filesystem';
import { sleep } from '../../../../utils/time'; import { sleep } from '../../../../utils/time';
import { EditorWebView, getNote } from '../../Functions'; import { EditorWebView, getNote } from '../../Functions';
import tiny, { safeKeyboardDismiss } from '../tiny'; import tiny, { safeKeyboardDismiss } from '../tiny';
@@ -321,7 +322,9 @@ async function attachFile(uri, hash, type, filename, options) {
return false; return false;
} }
if (!exists || options?.reupload) { let fileCheck = exists && (await filesystem.checkAttachment(hash));
if (!exists || options?.reupload || !fileCheck?.success) {
let key = await db.attachments.generateKey(); let key = await db.attachments.generateKey();
encryptionInfo = await Sodium.encryptFile(key, { encryptionInfo = await Sodium.encryptFile(key, {
uri: uri, uri: uri,

View File

@@ -98,10 +98,12 @@ export const Notes = ({ route, navigation }) => {
const setActionAfterFirstSave = () => { const setActionAfterFirstSave = () => {
if (params.current?.get === 'monographs') return; if (params.current?.get === 'monographs') return;
console.log(params.current);
editing.actionAfterFirstSave = { editing.actionAfterFirstSave = {
type: params.current?.type, type: params.current?.type,
id: params.current?.id, id: params.current?.id,
notebook: params.current?.notebookId notebook: params.current?.notebookId,
color: params.current.title
}; };
}; };

View File

@@ -380,7 +380,7 @@ async function saveToMarkdown(note) {
path = file.uri; path = file.uri;
} }
let markdown = await db.notes.note(note.id).export('md', markdown); let markdown = await db.notes.note(note.id).export('md');
let fileName = sanitizeFilename(note.title + Date.now(), { replacement: '_' }); let fileName = sanitizeFilename(note.title + Date.now(), { replacement: '_' });
let fileUri; let fileUri;

View File

@@ -19,8 +19,8 @@ export const GROUP = {
export const SORT = { export const SORT = {
dateEdited: 'Date edited', dateEdited: 'Date edited',
dateCreated: 'Date created' dateCreated: 'Date created',
//title:"Title", title: 'Title'
}; };
export const itemSkus = [ export const itemSkus = [

View File

@@ -10,6 +10,7 @@ import { db } from '../database';
import Storage from '../database/storage'; import Storage from '../database/storage';
import { cacheDir, fileCheck } from './utils'; import { cacheDir, fileCheck } from './utils';
import hosts from 'notes-core/utils/constants'; import hosts from 'notes-core/utils/constants';
import NetInfo from '@react-native-community/netinfo';
export async function downloadFile(filename, data, cancelToken) { export async function downloadFile(filename, data, cancelToken) {
if (!data) return false; if (!data) return false;
@@ -163,6 +164,9 @@ export async function getUploadedFileSize(hash) {
} }
export async function checkAttachment(hash) { export async function checkAttachment(hash) {
const internetState = await NetInfo.fetch();
const isInternetReachable = internetState.isConnected && internetState.isInternetReachable;
if (!isInternetReachable) return { success: true };
const attachment = db.attachments.attachment(hash); const attachment = db.attachments.attachment(hash);
if (!attachment) return { failed: 'Attachment not found.' }; if (!attachment) return { failed: 'Attachment not found.' };
@@ -170,7 +174,7 @@ export async function checkAttachment(hash) {
const size = await getUploadedFileSize(hash); const size = await getUploadedFileSize(hash);
if (size <= 0) return { failed: 'File length is 0.' }; if (size <= 0) return { failed: 'File length is 0.' };
} catch (e) { } catch (e) {
return { failed: e.message }; return { failed: e?.message };
} }
return { success: true }; return { success: true };
} }

View File

@@ -1,12 +1,11 @@
import { Linking } from 'react-native'; import { Linking } from 'react-native';
import { InAppBrowser } from 'react-native-inappbrowser-reborn';
import { history } from '.'; import { history } from '.';
import { useMenuStore, useSelectionStore } from '../stores/stores';
import { eSendEvent, ToastEvent } from '../services/event-manager'; import { eSendEvent, ToastEvent } from '../services/event-manager';
import Navigation from '../services/navigation'; import Navigation from '../services/navigation';
import SearchService from '../services/search';
import { useMenuStore, useSelectionStore } from '../stores/stores';
import { db } from './database'; import { db } from './database';
import { eClearEditor } from './events'; import { eClearEditor } from './events';
import SearchService from '../services/search';
export const deleteItems = async item => { export const deleteItems = async item => {
if (item && db.monographs.isPublished(item.id)) { if (item && db.monographs.isPublished(item.id)) {
@@ -118,27 +117,7 @@ export const deleteItems = async item => {
export const openLinkInBrowser = async (link, colors) => { export const openLinkInBrowser = async (link, colors) => {
try { try {
const url = link; const url = link;
if (await InAppBrowser.isAvailable()) { Linking.openURL(url);
await InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'cancel',
preferredBarTintColor: colors.accent,
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalPresentationStyle: 'fullScreen',
modalTransitionStyle: 'coverVertical',
modalEnabled: true,
enableBarCollapsing: false,
// Android Properties
showTitle: true,
toolbarColor: colors.accent,
secondaryToolbarColor: 'black',
enableUrlBarHiding: true,
enableDefaultShare: true,
forceCloseOnRedirection: false
});
} else Linking.openURL(url);
} catch (error) { } catch (error) {
console.log(error.message); console.log(error.message);
} }

View File

@@ -11,7 +11,7 @@ import {
} from 'react-native'; } from 'react-native';
import * as RNIap from 'react-native-iap'; import * as RNIap from 'react-native-iap';
import { enabled } from 'react-native-privacy-snapshot'; import { enabled } from 'react-native-privacy-snapshot';
import { doInBackground, editing } from '..'; import { editing } from '..';
import { Walkthrough } from '../../components/walkthroughs'; import { Walkthrough } from '../../components/walkthroughs';
import { import {
EditorWebView, EditorWebView,
@@ -37,7 +37,7 @@ import {
} from '../../services/message'; } from '../../services/message';
import PremiumService from '../../services/premium'; import PremiumService from '../../services/premium';
import SettingsService from '../../services/settings'; import SettingsService from '../../services/settings';
import Sync, { ignoredMessages } from '../../services/sync'; import Sync from '../../services/sync';
import { import {
clearAllStores, clearAllStores,
initialize, initialize,

View File

@@ -111,12 +111,15 @@ export function setWidthHeight(size) {
} }
export function getTotalNotes(notebook) { export function getTotalNotes(notebook) {
if (!notebook || notebook.type === 'header') return 0;
if (notebook.type === 'topic') { if (notebook.type === 'topic') {
if (!notebook.notes) return 0;
return notebook.notes.length; return notebook.notes.length;
} }
if (!notebook.topics) return 0; if (!notebook.topics) return 0;
return notebook.topics.reduce((sum, topic) => { return notebook.topics.reduce((sum, topic) => {
return sum + topic.notes.length; let length = topic?.notes ? topic.notes.length : 0;
return sum + length;
}, 0); }, 0);
} }

View File

@@ -1 +1 @@
export const APP_VERSION=1807; export const APP_VERSION=1809;