From bfd1a9b64dc239f0c4080347de27a1166e7c30a1 Mon Sep 17 00:00:00 2001 From: ammarahm-ed Date: Fri, 20 May 2022 14:49:38 +0500 Subject: [PATCH] fix: errors in imports --- .../src/components/attachments/actions.js | 2 +- .../components/container/floatingbutton.js | 5 +- .../src/components/dialogprovider/index.js | 18 +- .../src/components/dialogs/vault/index.js | 9 +- .../src/components/mergeconflicts/index.js | 20 +- .../src/components/notehistory/preview.js | 3 +- .../src/components/premium/premiumtoast.js | 8 +- .../src/components/sheetprovider/index.js | 13 +- apps/mobile/src/navigation/tabsholder.js | 4 +- apps/mobile/src/screens/editor/header.js | 21 +- apps/mobile/src/screens/editor/historyview.js | 9 +- apps/mobile/src/screens/editor/index.js | 7 +- .../src/screens/editor/tiptap/picker.js | 351 ++++++++++++++++++ .../src/screens/editor/tiptap/useEditor.ts | 24 +- apps/mobile/src/screens/editor/title.js | 19 +- apps/mobile/src/services/sync.js | 5 +- apps/mobile/src/stores/useAttachmentStore.ts | 42 +-- apps/mobile/src/stores/useEditorStore.ts | 23 +- apps/mobile/src/utils/hooks/useActions.js | 10 +- apps/mobile/src/utils/hooks/useEditorTags.ts | 20 +- 20 files changed, 459 insertions(+), 154 deletions(-) create mode 100644 apps/mobile/src/screens/editor/tiptap/picker.js diff --git a/apps/mobile/src/components/attachments/actions.js b/apps/mobile/src/components/attachments/actions.js index 749a348ff..ea9567ab8 100644 --- a/apps/mobile/src/components/attachments/actions.js +++ b/apps/mobile/src/components/attachments/actions.js @@ -2,7 +2,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; import React, { useEffect, useState } from 'react'; import { View } from 'react-native'; import { ScrollView } from 'react-native-gesture-handler'; -import picker from '../../screens/editor/tiny/toolbar/picker'; +import picker from '../../screens/editor/tiptap/picker'; import { eSendEvent, presentSheet, ToastEvent } from '../../services/event-manager'; import PremiumService from '../../services/premium'; import { useAttachmentStore } from '../../stores/use-attachment-store'; diff --git a/apps/mobile/src/components/container/floatingbutton.js b/apps/mobile/src/components/container/floatingbutton.js index 43f4678cc..3998afc72 100644 --- a/apps/mobile/src/components/container/floatingbutton.js +++ b/apps/mobile/src/components/container/floatingbutton.js @@ -10,8 +10,9 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import { notesnook } from '../../../e2e/test.ids'; import { editorState } from '../../screens/editor/tiptap/utils'; -import { useSelectionStore, useSettingStore } from '../../stores/stores'; -import { editing, getElevation, showTooltip, TOOLTIP_POSITIONS } from '../../utils'; +import { useSelectionStore } from '../../stores/use-selection-store'; +import { useSettingStore } from '../../stores/use-setting-store'; +import { getElevation, showTooltip, TOOLTIP_POSITIONS } from '../../utils'; import { normalize, SIZE } from '../../utils/size'; import { PressableButton } from '../ui/pressable'; diff --git a/apps/mobile/src/components/dialogprovider/index.js b/apps/mobile/src/components/dialogprovider/index.js index 1a6a7861a..3b5192ed3 100644 --- a/apps/mobile/src/components/dialogprovider/index.js +++ b/apps/mobile/src/components/dialogprovider/index.js @@ -1,27 +1,26 @@ import React from 'react'; import { useThemeStore } from '../../stores/use-theme-store'; -import { EditorSettings } from '../../screens/editor/EditorSettings'; -import { AddNotebookSheet } from '../sheets/add-notebook'; -import { AddTopicDialog } from '../dialogs/add-topic'; import { AnnouncementDialog } from '../announcements'; import { AttachmentDialog } from '../attachments'; import Auth from '../auth'; import { SessionExpired } from '../auth/session-expired'; import { Dialog } from '../dialog'; -import ExportNotesSheet from '../sheets/export-notes'; +import { AddTopicDialog } from '../dialogs/add-topic'; +import ResultDialog from '../dialogs/result'; +import { VaultDialog } from '../dialogs/vault'; import ImagePreview from '../image-preview'; import MergeConflicts from '../merge-conflicts'; -import AddToNotebookSheet from '../sheets/add-to'; import PremiumDialog from '../premium'; import { Expiring } from '../premium/expiring'; +import SheetProvider from '../sheet-provider'; +import { AddNotebookSheet } from '../sheets/add-notebook'; +import AddToNotebookSheet from '../sheets/add-to'; +import ExportNotesSheet from '../sheets/export-notes'; +import ManageTagsSheet from '../sheets/manage-tags'; import PublishNoteSheet from '../sheets/publish-note'; import RateAppSheet from '../sheets/rate-app'; import RecoveryKeySheet from '../sheets/recovery-key'; import RestoreDataSheet from '../sheets/restore-data'; -import ResultDialog from '../dialogs/result'; -import SheetProvider from '../sheet-provider'; -import ManageTagsSheet from '../sheets/manage-tags'; -import { VaultDialog } from '../dialogs/vault'; const DialogProvider = React.memo( () => { @@ -45,7 +44,6 @@ const DialogProvider = React.memo( - diff --git a/apps/mobile/src/components/dialogs/vault/index.js b/apps/mobile/src/components/dialogs/vault/index.js index 3246e2b04..6cbebbf5a 100644 --- a/apps/mobile/src/components/dialogs/vault/index.js +++ b/apps/mobile/src/components/dialogs/vault/index.js @@ -3,6 +3,7 @@ import React, { Component, createRef } from 'react'; import { InteractionManager, View } from 'react-native'; import Share from 'react-native-share'; import { notesnook } from '../../../../e2e/test.ids'; +import { editorController } from '../../../screens/editor/tiptap/utils'; import BiometricService from '../../../services/biometrics'; import { DDS } from '../../../services/device-detection'; import { @@ -12,6 +13,7 @@ import { ToastEvent } from '../../../services/event-manager'; import Navigation from '../../../services/navigation'; +import SearchService from '../../../services/search'; import { getElevation, toTXT } from '../../../utils'; import { db } from '../../../utils/database'; import { @@ -24,17 +26,14 @@ import { import { deleteItems } from '../../../utils/functions'; import { tabBarRef } from '../../../utils/global-refs'; import { sleep } from '../../../utils/time'; -import { getNote } from '../../../screens/editor/Functions'; -import { Button } from '../../ui/button'; import BaseDialog from '../../dialog/base-dialog'; import DialogButtons from '../../dialog/dialog-buttons'; import DialogHeader from '../../dialog/dialog-header'; +import { Toast } from '../../toast'; +import { Button } from '../../ui/button'; import Input from '../../ui/input'; import Seperator from '../../ui/seperator'; -import { Toast } from '../../toast'; import Paragraph from '../../ui/typography/paragraph'; -import SearchService from '../../../services/search'; -import { editorController } from '../../../screens/editor/tiptap/utils'; let Keychain; const passInputRef = createRef(); diff --git a/apps/mobile/src/components/mergeconflicts/index.js b/apps/mobile/src/components/mergeconflicts/index.js index 9d072e35a..6457336e1 100644 --- a/apps/mobile/src/components/mergeconflicts/index.js +++ b/apps/mobile/src/components/mergeconflicts/index.js @@ -5,32 +5,28 @@ import { Modal, Platform, SafeAreaView, Text, View } from 'react-native'; import Animated from 'react-native-reanimated'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import WebView from 'react-native-webview'; -import { useThemeStore } from '../../stores/use-theme-store'; +import { editorController } from '../../screens/editor/tiptap/utils'; import { DDS } from '../../services/device-detection'; -import { - eSendEvent, - eSubscribeEvent, - eUnSubscribeEvent, - ToastEvent -} from '../../services/event-manager'; +import { eSubscribeEvent, eUnSubscribeEvent, ToastEvent } from '../../services/event-manager'; import Navigation from '../../services/navigation'; import Sync from '../../services/sync'; +import { useThemeStore } from '../../stores/use-theme-store'; import { dHeight } from '../../utils'; import { db } from '../../utils/database'; -import { eApplyChanges, eShowMergeDialog, refreshNotesPage } from '../../utils/events'; +import { eApplyChanges, eShowMergeDialog } from '../../utils/events'; import { openLinkInBrowser } from '../../utils/functions'; import { normalize, SIZE } from '../../utils/size'; import { timeConverter } from '../../utils/time'; -import { getNote, sourceUri, updateNoteInEditor } from '../../screens/editor/Functions'; -import { IconButton } from '../ui/icon-button'; -import { Button } from '../ui/button'; import BaseDialog from '../dialog/base-dialog'; import DialogButtons from '../dialog/dialog-buttons'; import DialogContainer from '../dialog/dialog-container'; import DialogHeader from '../dialog/dialog-header'; +import { Button } from '../ui/button'; +import { IconButton } from '../ui/icon-button'; import Seperator from '../ui/seperator'; import Paragraph from '../ui/typography/paragraph'; -import { editorController } from '../../screens/editor/tiptap/utils'; + +const sourceUri = ''; const primaryWebView = createRef(); const secondaryWebView = createRef(); diff --git a/apps/mobile/src/components/notehistory/preview.js b/apps/mobile/src/components/notehistory/preview.js index 29223044e..a64f27711 100644 --- a/apps/mobile/src/components/notehistory/preview.js +++ b/apps/mobile/src/components/notehistory/preview.js @@ -1,7 +1,6 @@ import React, { useRef } from 'react'; import { Platform, View } from 'react-native'; import WebView from 'react-native-webview'; -import { sourceUri } from '../../screens/editor/Functions'; import { editorController } from '../../screens/editor/tiptap/utils'; import { eSendEvent, ToastEvent } from '../../services/event-manager'; import Navigation from '../../services/navigation'; @@ -15,6 +14,8 @@ import DialogHeader from '../dialog/dialog-header'; import { Button } from '../ui/button'; import Paragraph from '../ui/typography/paragraph'; +const sourceUri = ''; + export default function NotePreview({ session, content }) { const colors = useThemeStore(state => state.colors); const webviewRef = useRef(); diff --git a/apps/mobile/src/components/premium/premiumtoast.js b/apps/mobile/src/components/premium/premiumtoast.js index cd3dccad0..04fbd81cb 100644 --- a/apps/mobile/src/components/premium/premiumtoast.js +++ b/apps/mobile/src/components/premium/premiumtoast.js @@ -1,19 +1,17 @@ import React, { useEffect, useRef, useState } from 'react'; import { View } from 'react-native'; import Animated, { FadeInUp, FadeOutUp } from 'react-native-reanimated'; -import { EditorWebView } from '../../screens/editor/Functions'; -import tiny from '../../screens/editor/tiny/tiny'; +import { editorState } from '../../screens/editor/tiptap/utils'; import { DDS } from '../../services/device-detection'; import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; import { useThemeStore } from '../../stores/use-theme-store'; -import { editing, getElevation } from '../../utils'; +import { getElevation } from '../../utils'; import { eCloseActionSheet, eOpenPremiumDialog, eShowGetPremium } from '../../utils/events'; import { SIZE } from '../../utils/size'; import { sleep } from '../../utils/time'; import { Button } from '../ui/button'; import Heading from '../ui/typography/heading'; import Paragraph from '../ui/typography/paragraph'; -import { editorState } from '../../screens/editor/tiptap/utils'; export const PremiumToast = ({ close, context = 'global', offset = 0 }) => { const colors = useThemeStore(state => state.colors); @@ -52,7 +50,7 @@ export const PremiumToast = ({ close, context = 'global', offset = 0 }) => { open(null); eSendEvent(eCloseActionSheet); if (editorState().isFocused) { - tiny.call(EditorWebView, tiny.blur); + //tiny.call(EditorWebView, tiny.blur); } await sleep(300); eSendEvent(eOpenPremiumDialog); diff --git a/apps/mobile/src/components/sheetprovider/index.js b/apps/mobile/src/components/sheetprovider/index.js index 8c6035ef1..dc9107b54 100644 --- a/apps/mobile/src/components/sheetprovider/index.js +++ b/apps/mobile/src/components/sheetprovider/index.js @@ -1,20 +1,16 @@ import React, { useEffect, useRef, useState } from 'react'; import { ActivityIndicator, View } from 'react-native'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; -import { useThemeStore } from '../../stores/use-theme-store'; +import { editorState } from '../../screens/editor/tiptap/utils'; import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; -import { editing } from '../../utils'; +import { useThemeStore } from '../../stores/use-theme-store'; import { eCloseProgressDialog, eOpenProgressDialog } from '../../utils/events'; import { SIZE } from '../../utils/size'; import { sleep } from '../../utils/time'; -import { EditorWebView } from '../../screens/editor/Functions'; -import tiny from '../../screens/editor/tiny/tiny'; -import { reFocusEditor } from '../../screens/editor/tiny/toolbar/constants'; import { Button } from '../ui/button'; import SheetWrapper from '../ui/sheet'; import Heading from '../ui/typography/heading'; import Paragraph from '../ui/typography/paragraph'; -import { editorState } from '../../screens/editor/tiptap/utils'; const SheetProvider = ({ context = 'global' }) => { const colors = useThemeStore(state => state.colors); @@ -47,7 +43,7 @@ const SheetProvider = ({ context = 'global' }) => { if (data.editor) { editor.current.refocus = false; if (editorState().keyboardState) { - tiny.call(EditorWebView, tiny.cacheRange + tiny.blur); + // tiny.call(EditorWebView, tiny.cacheRange + tiny.blur); editor.current.refocus = true; } } @@ -62,8 +58,7 @@ const SheetProvider = ({ context = 'global' }) => { } else { if (editor.current?.refocus) { editorState().isFocused = true; - await reFocusEditor(); - tiny.call(EditorWebView, tiny.restoreRange + tiny.clearRange); + // tiny.call(EditorWebView, tiny.restoreRange + tiny.clearRange); editor.current.refocus = false; } } diff --git a/apps/mobile/src/navigation/tabsholder.js b/apps/mobile/src/navigation/tabsholder.js index 13c2c0c1f..cf410d37a 100644 --- a/apps/mobile/src/navigation/tabsholder.js +++ b/apps/mobile/src/navigation/tabsholder.js @@ -320,7 +320,7 @@ export const TabsHolder = React.memo( let layoutTimer = null; const onChangeTab = async obj => { - if (obj.i === 1) { + if (obj.i === 2) { editorState().movedAway = false; editorState().isFocused = true; activateKeepAwake(); @@ -328,7 +328,7 @@ const onChangeTab = async obj => { eSendEvent(eOnLoadNote, { type: 'new' }); } } else { - if (obj.from === 1) { + if (obj.from === 2) { deactivateKeepAwake(); editorState().movedAway = true; editorState().isFocused = false; diff --git a/apps/mobile/src/screens/editor/header.js b/apps/mobile/src/screens/editor/header.js index 987a3c6c1..bc3606a07 100644 --- a/apps/mobile/src/screens/editor/header.js +++ b/apps/mobile/src/screens/editor/header.js @@ -4,10 +4,7 @@ import { BackHandler, InteractionManager, Platform, Vibration, View } from 'reac import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { notesnook } from '../../../e2e/test.ids'; import { Properties } from '../../components/properties'; -import { useThemeStore } from '../../stores/use-theme-store'; -import { useUserStore } from '../../stores/use-user-store'; -import { useEditorStore } from '../../stores/use-editor-store'; -import { useSettingStore } from '../../stores/use-setting-store'; +import { IconButton } from '../../components/ui/icon-button'; import { DDS } from '../../services/device-detection'; import { eSendEvent, @@ -16,6 +13,10 @@ import { ToastEvent } from '../../services/event-manager'; import Navigation from '../../services/navigation'; +import { useEditorStore } from '../../stores/use-editor-store'; +import { useSettingStore } from '../../stores/use-setting-store'; +import { useThemeStore } from '../../stores/use-theme-store'; +import { useUserStore } from '../../stores/use-user-store'; import umami from '../../utils/analytics'; import { SUBSCRIPTION_STATUS } from '../../utils/constants'; import { db } from '../../utils/database'; @@ -29,13 +30,10 @@ import { eOpenPublishNoteDialog } from '../../utils/events'; import { tabBarRef } from '../../utils/global-refs'; -import { EditorTitle } from './title'; import { ProgressCircle } from './progress'; -import { safeKeyboardDismiss } from './tiny/tiny'; -import { endSearch } from './tiny/toolbar/commands'; -import picker from './tiny/toolbar/picker'; +import picker from './tiptap/picker'; import { editorController, editorState } from './tiptap/utils'; -import { IconButton } from '../../components/ui/icon-button'; +import { EditorTitle } from './title'; const EditorHeader = ({ editor }) => { const colors = useThemeStore(state => state.colors); @@ -113,7 +111,6 @@ const EditorHeader = ({ editor }) => { return; } if (editorState().isFocused) { - safeKeyboardDismiss(); editorState().isFocused = true; } eSendEvent(eOpenPublishNoteDialog, note); @@ -133,7 +130,6 @@ const EditorHeader = ({ editor }) => { } if (editorState().isFocused || editorState().keyboardState) { - safeKeyboardDismiss(); editorState().isFocused = true; } @@ -271,7 +267,6 @@ const EditorHeader = ({ editor }) => { top={50} onPress={async () => { if (editorState().isFocused) { - safeKeyboardDismiss(); editorState().isFocused = true; } umami.pageView('/pro-screen', '/editor'); @@ -290,7 +285,7 @@ const EditorHeader = ({ editor }) => { buttom={10} onLongPress={() => { if (searchReplace) { - endSearch(); + //endSearch(); Vibration.vibrate(5, false); } }} diff --git a/apps/mobile/src/screens/editor/historyview.js b/apps/mobile/src/screens/editor/historyview.js index 532b8a435..24a4b9a30 100644 --- a/apps/mobile/src/screens/editor/historyview.js +++ b/apps/mobile/src/screens/editor/historyview.js @@ -1,12 +1,10 @@ import React, { useEffect, useState } from 'react'; import { Platform, View } from 'react-native'; import { IconButton } from '../../components/ui/icon-button'; -import { useThemeStore } from '../../stores/use-theme-store'; import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; +import { useThemeStore } from '../../stores/use-theme-store'; import useKeyboard from '../../utils/hooks/use-keyboard'; import { SIZE } from '../../utils/size'; -import { EditorWebView } from './Functions'; -import tiny, { safeKeyboardDismiss } from './tiny/tiny'; import { editorState } from './tiptap/utils'; const HistoryComponent = () => { @@ -48,7 +46,6 @@ const HistoryComponent = () => { }} onPress={() => { editorState().keyboardState = true; - safeKeyboardDismiss(); }} /> ) : null} @@ -64,7 +61,7 @@ const HistoryComponent = () => { }} onPress={() => { if (!historyState.undo) return; - tiny.call(EditorWebView, tiny.undo); + // tiny.call(EditorWebView, tiny.undo); }} /> { }} onPress={() => { if (!historyState.redo) return; - tiny.call(EditorWebView, tiny.redo); + // tiny.call(EditorWebView, tiny.redo); }} /> diff --git a/apps/mobile/src/screens/editor/index.js b/apps/mobile/src/screens/editor/index.js index 654d914b7..914c49ed4 100755 --- a/apps/mobile/src/screens/editor/index.js +++ b/apps/mobile/src/screens/editor/index.js @@ -4,10 +4,11 @@ import WebView from 'react-native-webview'; import { notesnook } from '../../../e2e/test.ids'; import { useUserStore } from '../../stores/use-user-store'; import EditorHeader from './header'; -import { sourceUri, _onShouldStartLoadWithRequest } from './Functions'; import { useEditor } from './tiptap/use-editor'; import { editorController } from './tiptap/utils'; +const sourceUri = ''; + const source = { uri: sourceUri + 'index.html' }; const style = { @@ -48,7 +49,7 @@ const Editor = React.memo( javaScriptEnabled={true} focusable={true} keyboardDisplayRequiresUserAction={false} - onShouldStartLoadWithRequest={_onShouldStartLoadWithRequest} + // onShouldStartLoadWithRequest={_onShouldStartLoadWithRequest} cacheMode="LOAD_DEFAULT" cacheEnabled={true} domStorageEnabled={true} @@ -63,7 +64,7 @@ const Editor = React.memo( allowUniversalAccessFromFileURLs={true} originWhitelist={['*']} source={{ - uri: 'http://192.168.10.6:3000' + uri: 'http://192.168.10.5:3000' }} style={style} autoManageStatusBarEnabled={false} diff --git a/apps/mobile/src/screens/editor/tiptap/picker.js b/apps/mobile/src/screens/editor/tiptap/picker.js new file mode 100644 index 000000000..dd48e29f5 --- /dev/null +++ b/apps/mobile/src/screens/editor/tiptap/picker.js @@ -0,0 +1,351 @@ +import React from 'react'; +import { Platform, View } from 'react-native'; +import DocumentPicker from 'react-native-document-picker'; +import { launchCamera, launchImageLibrary } from 'react-native-image-picker'; +import Sodium from 'react-native-sodium'; +import RNFetchBlob from 'rn-fetch-blob'; +import { AttachmentItem } from '../../../components/attachments/attachment-item'; +import { eSendEvent, presentSheet, ToastEvent } from '../../../services/event-manager'; +import PremiumService from '../../../services/premium'; +import { db } from '../../../utils/database'; +import { eCloseProgressDialog } from '../../../utils/events'; +import { sleep } from '../../../utils/time'; +import { editorController, editorState } from './utils'; + +const FILE_SIZE_LIMIT = 500 * 1024 * 1024; +const IMAGE_SIZE_LIMIT = 50 * 1024 * 1024; + +const showEncryptionSheet = file => { + presentSheet({ + title: 'Encrypting attachment', + paragraph: 'Please wait while we encrypt file for upload', + icon: 'attachment', + component: ( + + + + ) + }); +}; + +const santizeUri = uri => { + uri = decodeURI(uri); + uri = Platform.OS === 'ios' ? uri.replace('file:///', '/') : uri; + return uri; +}; + +const file = async fileOptions => { + try { + let options = { + mode: 'import', + allowMultiSelection: false + }; + if (Platform.OS == 'ios') { + options.copyTo = 'cachesDirectory'; + } + console.log('generate key for attachment'); + let key = await db.attachments.generateKey(); + console.log('generated key for attachments: ', key); + let file; + try { + file = await DocumentPicker.pick(options); + } catch (e) { + return; + } + + file = file[0]; + if (file.type.startsWith('image')) { + ToastEvent.show({ + title: 'Type not supported', + message: 'Please add images from gallery or camera picker.', + type: 'error' + }); + return; + } + if (file.size > FILE_SIZE_LIMIT) { + ToastEvent.show({ + title: 'File too large', + message: 'The maximum allowed size per file is 500 MB', + type: 'error' + }); + return; + } + + if (file.copyError) { + ToastEvent.show({ + heading: 'Failed to open file', + message: file.copyError, + type: 'error', + context: 'global' + }); + return; + } + + let uri = Platform.OS === 'ios' ? file.fileCopyUri : file.uri; + console.log('file uri: ', uri); + uri = Platform.OS === 'ios' ? santizeUri(uri) : uri; + showEncryptionSheet(file); + let hash = await Sodium.hashFile({ + uri: uri, + type: 'url' + }); + console.log('decoded uri: ', uri); + let result = await attachFile(uri, hash, file.type, file.name, fileOptions); + console.log('attach file: ', result); + + setTimeout(() => { + eSendEvent(eCloseProgressDialog); + }, 1000); + if (!result) return; + // tiny.call( + // EditorWebView, + // ` + // (function() { + // let file = ${JSON.stringify({ + // hash: hash, + // filename: file.name, + // type: file.type, + // size: file.size + // })} + // editor.undoManager.transact(function() { + // tinymce.activeEditor.execCommand('mceAttachFile',file); + // setTimeout(function() { + // tinymce.activeEditor.fire("input",{data:""}) + // },100) + // }); + + // })(); + // ` + // ); + } catch (e) { + ToastEvent.show({ + heading: e.message, + message: 'You need internet access to attach a file', + type: 'error', + context: 'global' + }); + console.log('attachment error: ', e); + } +}; + +const camera = async options => { + try { + await db.attachments.generateKey(); + eSendEvent(eCloseProgressDialog); + await sleep(400); + launchCamera( + { + includeBase64: true, + maxWidth: 4000, + maxHeight: 4000, + quality: 0.8, + mediaType: 'photo' + }, + response => handleImageResponse(response, options) + ); + } catch (e) { + ToastEvent.show({ + heading: e.message, + message: 'You need internet access to attach a file', + type: 'error', + context: 'global' + }); + console.log('attachment error:', e); + } +}; + +const gallery = async options => { + try { + await db.attachments.generateKey(); + eSendEvent(eCloseProgressDialog); + await sleep(400); + launchImageLibrary( + { + includeBase64: true, + maxWidth: 4000, + maxHeight: 4000, + quality: 0.8, + mediaType: 'photo', + selectionLimit: 1 + }, + response => handleImageResponse(response, options) + ); + } catch (e) { + ToastEvent.show({ + heading: e.message, + message: 'You need internet access to attach a file', + type: 'error', + context: 'global' + }); + console.log('attachment error:', e); + } +}; + +const pick = async options => { + if (!PremiumService.get()) { + let user = await db.user.getUser(); + if (editorState().isFocused) { + editorState().isFocused = true; + } + if (user && !PremiumService.get() && !user.isEmailConfirmed) { + PremiumService.showVerifyEmailDialog(); + } else { + PremiumService.sheet(); + } + return; + } + + if (options?.reupload) { + if (options?.type.startsWith('image')) { + gallery(options); + } else { + file(options); + } + return; + } + + if (editorState().isFocused) { + editorState().isFocused = true; + } + + presentSheet({ + context: options?.context, + actionsArray: [ + { + action: async () => { + eSendEvent(eCloseProgressDialog); + await sleep(400); + await file(options); + }, + actionText: 'Attach a file', + icon: 'file' + }, + { + action: () => camera(options), + actionText: 'Open camera', + icon: 'camera' + }, + { + action: () => gallery(options), + actionText: 'Select image from gallery', + icon: 'image-multiple' + } + ] + }); + + return; +}; + +const handleImageResponse = async (response, options) => { + if ( + response.didCancel || + response.errorMessage || + !response.assets || + response.assets?.length === 0 + ) { + return; + } + + let image = response.assets[0]; + if (image.fileSize > IMAGE_SIZE_LIMIT) { + ToastEvent.show({ + title: 'File too large', + message: 'The maximum allowed size per image is 50 MB', + type: 'error' + }); + return; + } + let b64 = `data:${image.type};base64, ` + image.base64; + let uri = image.uri; + uri = decodeURI(uri); + let hash = await Sodium.hashFile({ + uri: uri, + type: 'url' + }); + + let fileName = image.originalFileName || image.fileName; + let result = await attachFile(uri, hash, image.type, fileName, options); + if (!result) return; + // tiny.call( + // EditorWebView, + // ` + // (function(){ + // let image = ${JSON.stringify({ + // hash: hash, + // type: image.type, + // filename: fileName, + // dataurl: b64, + // size: image.fileSize + // })} + + // editor.undoManager.transact(function() { + // tinymce.activeEditor.execCommand('mceAttachImage',image); + // setTimeout(function() { + // tinymce.activeEditor.fire("input",{data:""}) + // },100) + // }); + // })(); + // ` + // ); +}; + +async function attachFile(uri, hash, type, filename, options) { + try { + let exists = db.attachments.exists(hash); + let encryptionInfo; + + if (options?.hash && options.hash !== hash) { + ToastEvent.show({ + heading: 'Please select the same file for reuploading', + message: `Expected hash ${options.hash} but got ${hash}.`, + type: 'error', + context: 'local' + }); + return false; + } + + if (!exists || options?.reupload) { + let key = await db.attachments.generateKey(); + encryptionInfo = await Sodium.encryptFile(key, { + uri: uri, + type: 'url', + hash: hash + }); + encryptionInfo.type = type; + encryptionInfo.filename = filename; + encryptionInfo.alg = `xcha-stream`; + encryptionInfo.size = encryptionInfo.length; + encryptionInfo.key = key; + if (options?.reupload && exists) await db.attachments.reset(hash); + } else { + encryptionInfo = { hash: hash }; + } + await db.attachments.add(encryptionInfo, editorController.current?.note?.id); + if (Platform.OS === 'ios') await RNFetchBlob.fs.unlink(uri); + + return true; + } catch (e) { + console.log('attach file error: ', e); + if (Platform.OS === 'ios') { + await RNFetchBlob.fs.unlink(uri); + } + return false; + } +} + +export default { + file, + pick +}; diff --git a/apps/mobile/src/screens/editor/tiptap/useEditor.ts b/apps/mobile/src/screens/editor/tiptap/useEditor.ts index 9e12bcc70..916d41742 100644 --- a/apps/mobile/src/screens/editor/tiptap/useEditor.ts +++ b/apps/mobile/src/screens/editor/tiptap/useEditor.ts @@ -4,8 +4,9 @@ import { DDS } from '../../../services/device-detection'; import { eSendEvent, eSubscribeEvent, eUnSubscribeEvent } from '../../../services/event-manager'; import Navigation from '../../../services/navigation'; import { TipManager } from '../../../services/tip-manager'; -import { useEditorStore, useTagStore } from '../../../stores/stores'; -import { useThemeStore } from '../../../stores/theme'; +import { useEditorStore } from '../../../stores/use-editor-store'; +import { useTagStore } from '../../../stores/use-tag-store'; +import { useThemeStore } from '../../../stores/use-theme-store'; import { db } from '../../../utils/database'; import { MMKV } from '../../../utils/database/mmkv'; import { eOnLoadNote, eOpenTagsDialog } from '../../../utils/events'; @@ -159,12 +160,7 @@ export const useEditor = () => { currentNote.current?.title !== note.title || currentNote.current?.headline !== note.headline ) { - Navigation.setRoutesToUpdate([ - Navigation.routeNames.NotesPage, - Navigation.routeNames.Favorites, - Navigation.routeNames.Notes, - Navigation.routeNames.Notebook - ]); + Navigation.queueRoutesForUpdate('ColoredNotes', 'Notes', 'TaggedNotes', 'TopicNotes'); } } @@ -284,11 +280,13 @@ export const useEditor = () => { .then(async () => { useTagStore.getState().setTags(); await commands.setTags(currentNote.current); - Navigation.setRoutesToUpdate([ - Navigation.routeNames.Notes, - Navigation.routeNames.NotesPage, - Navigation.routeNames.Tags - ]); + Navigation.queueRoutesForUpdate( + 'ColoredNotes', + 'Notes', + 'TaggedNotes', + 'TopicNotes', + 'Tags' + ); }); } break; diff --git a/apps/mobile/src/screens/editor/title.js b/apps/mobile/src/screens/editor/title.js index e6ecfd424..2b798dcc7 100644 --- a/apps/mobile/src/screens/editor/title.js +++ b/apps/mobile/src/screens/editor/title.js @@ -4,7 +4,6 @@ import Animated, { FadeInUp, FadeOutUp } from 'react-native-reanimated'; import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; import { useThemeStore } from '../../stores/use-theme-store'; import { SIZE } from '../../utils/size'; -import { post, _onMessage } from './Functions'; export const EditorTitle = () => { const colors = useThemeStore(state => state.colors); @@ -51,15 +50,15 @@ export const EditorTitle = () => { placeholderTextColor={colors.placeholder} onChangeText={text => { setTitle(text); - post('title', text); - _onMessage({ - nativeEvent: { - data: JSON.stringify({ - type: 'title', - value: text - }) - } - }); + // post('title', text); + // _onMessage({ + // nativeEvent: { + // data: JSON.stringify({ + // type: 'title', + // value: text + // }) + // } + // }); }} /> diff --git a/apps/mobile/src/services/sync.js b/apps/mobile/src/services/sync.js index 1e67c879c..c1fd7c083 100644 --- a/apps/mobile/src/services/sync.js +++ b/apps/mobile/src/services/sync.js @@ -1,12 +1,11 @@ import NetInfo from '@react-native-community/netinfo'; import { EVENTS } from 'notes-core/common'; -import { getNote, updateNoteInEditor } from '../screens/editor/Functions'; +import { editorController } from '../screens/editor/tiptap/utils'; import { initialize } from '../stores'; import { useUserStore } from '../stores/use-user-store'; import { doInBackground } from '../utils'; import { db } from '../utils/database'; import { ToastEvent } from './event-manager'; -import { editorController } from '../screens/editor/tiptap/utils'; export const ignoredMessages = ['Sync already running', 'Not allowed to start service intent']; @@ -54,7 +53,7 @@ const run = async (context = 'global', forced = false, full = true) => { userstore.setLastSynced(await db.lastSynced()); initialize(); if (editorController.current?.note?.id) { - await updateNoteInEditor(); + //await updateNoteInEditor(); } db.eventManager.publish(EVENTS.syncCompleted); console.log('sync done'); diff --git a/apps/mobile/src/stores/useAttachmentStore.ts b/apps/mobile/src/stores/useAttachmentStore.ts index e38f3b4d9..7d2dcae99 100644 --- a/apps/mobile/src/stores/useAttachmentStore.ts +++ b/apps/mobile/src/stores/useAttachmentStore.ts @@ -1,7 +1,5 @@ //@ts-ignore import create from 'zustand'; -import { EditorWebView } from '../screens/editor/Functions'; -import tiny from '../screens/editor/tiny/tiny'; interface AttachmentStore { progress?: { @@ -33,18 +31,18 @@ export const useAttachmentStore = create((set, get) => ({ let _p = get().progress; if (!_p) return; _p[hash] = null; - tiny.call( - EditorWebView, - ` - (function() { - let progress = ${JSON.stringify({ - loaded: 1, - total: 1, - hash - })} - tinymce.activeEditor._updateAttachmentProgress(progress); - })()` - ); + // tiny.call( + // EditorWebView, + // ` + // (function() { + // let progress = ${JSON.stringify({ + // loaded: 1, + // total: 1, + // hash + // })} + // tinymce.activeEditor._updateAttachmentProgress(progress); + // })()` + // ); set({ progress: { ..._p } }); }, setProgress: (sent, total, hash, recieved, type) => { @@ -52,14 +50,14 @@ export const useAttachmentStore = create((set, get) => ({ if (!_p) return; _p[hash] = { sent, total, hash, recieved, type }; let progress = { total, hash, loaded: type === 'download' ? recieved : sent }; - tiny.call( - EditorWebView, - ` - (function() { - let progress = ${JSON.stringify(progress)} - tinymce.activeEditor._updateAttachmentProgress(progress); - })()` - ); + // tiny.call( + // EditorWebView, + // ` + // (function() { + // let progress = ${JSON.stringify(progress)} + // tinymce.activeEditor._updateAttachmentProgress(progress); + // })()` + // ); set({ progress: { ..._p } }); }, encryptionProgress: 0, diff --git a/apps/mobile/src/stores/useEditorStore.ts b/apps/mobile/src/stores/useEditorStore.ts index 3ee5deb3b..94c4b8d31 100644 --- a/apps/mobile/src/stores/useEditorStore.ts +++ b/apps/mobile/src/stores/useEditorStore.ts @@ -1,8 +1,5 @@ //@ts-ignore import create, { State } from 'zustand'; -import { EditorWebView } from '../screens/editor/Functions'; -import tiny from '../screens/editor/tiny/tiny'; -import { endSearch } from '../screens/editor/tiny/toolbar/commands'; import { eSubscribeEvent, eUnSubscribeEvent } from '../services/event-manager'; export interface EditorStore extends State { @@ -23,7 +20,7 @@ export const useEditorStore = create((set, get) => ({ sessionId: null, setSessionId: sessionId => { console.log(sessionId, 'session id'); - tiny.call(EditorWebView, `sessionId="${sessionId}";`); + // tiny.call(EditorWebView, `sessionId="${sessionId}";`); set({ sessionId }); }, searchReplace: false, @@ -41,19 +38,19 @@ export const useEditorStore = create((set, get) => ({ eUnSubscribeEvent('selectionvalue', func); console.log('setSearchReplace:', value, value.length); if (!value && get().searchReplace) { - endSearch(); + // endSearch(); return; } set({ searchSelection: value, searchReplace: true }); }; eSubscribeEvent('selectionvalue', func); - tiny.call( - EditorWebView, - `(function() { - if (editor) { - reactNativeEventHandler('selectionvalue',editor.selection.getContent()); - } - })();` - ); + // tiny.call( + // EditorWebView, + // `(function() { + // if (editor) { + // reactNativeEventHandler('selectionvalue',editor.selection.getContent()); + // } + // })();` + // ); } })); diff --git a/apps/mobile/src/utils/hooks/useActions.js b/apps/mobile/src/utils/hooks/useActions.js index a36566bef..fb700204a 100644 --- a/apps/mobile/src/utils/hooks/useActions.js +++ b/apps/mobile/src/utils/hooks/useActions.js @@ -7,8 +7,6 @@ import { notesnook } from '../../../e2e/test.ids'; import { presentDialog } from '../../components/dialog/functions'; import NoteHistory from '../../components/note-history'; import { MoveNotes } from '../../components/sheets/move-notes/movenote'; -import { EditorWebView } from '../../screens/editor/Functions'; -import tiny from '../../screens/editor/tiny/tiny.js'; import { eSendEvent, eSubscribeEvent, @@ -19,12 +17,12 @@ import { } from '../../services/event-manager'; import Navigation from '../../services/navigation'; import Notifications from '../../services/notifications'; -import { useSelectionStore } from '../../stores/use-selection-store'; -import { useUserStore } from '../../stores/use-user-store'; -import { useMenuStore } from '../../stores/use-menu-store'; import { useEditorStore } from '../../stores/use-editor-store'; +import { useMenuStore } from '../../stores/use-menu-store'; +import { useSelectionStore } from '../../stores/use-selection-store'; import { useTagStore } from '../../stores/use-tag-store'; import { useThemeStore } from '../../stores/use-theme-store'; +import { useUserStore } from '../../stores/use-user-store'; import { toggleDarkMode } from '../color-scheme/utils'; import { db } from '../database'; import { @@ -532,7 +530,7 @@ export const useActions = ({ close = () => {}, item }) => { let current = db.notes.note(item.id).data.readonly; if (useEditorStore.getState().currentEditingNote === item.id) { useEditorStore.getState().setReadonly(current); - tiny.call(EditorWebView, tiny.toogleReadMode(current ? 'readonly' : 'design')); + // tiny.call(EditorWebView, tiny.toogleReadMode(current ? 'readonly' : 'design')); } Navigation.queueRoutesForUpdate( 'TaggedNotes', diff --git a/apps/mobile/src/utils/hooks/useEditorTags.ts b/apps/mobile/src/utils/hooks/useEditorTags.ts index fed67de1f..eb0d69ae5 100644 --- a/apps/mobile/src/utils/hooks/useEditorTags.ts +++ b/apps/mobile/src/utils/hooks/useEditorTags.ts @@ -1,10 +1,8 @@ import { useEffect, useState } from 'react'; +import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; import { useEditorStore } from '../../stores/use-editor-store'; import { useTagStore } from '../../stores/use-tag-store'; -import { eSubscribeEvent, eUnSubscribeEvent } from '../../services/event-manager'; import { db } from '../database'; -import { EditorWebView } from '../../screens/editor/Functions'; -import tiny from '../../screens/editor/tiny/tiny'; /** * A hook that injects/removes tags from tags bar in editor @@ -33,7 +31,7 @@ const useEditorTags = () => { function load() { if (!note) return; - tiny.call(EditorWebView, renderTags(noteTags)); + // tiny.call(EditorWebView, renderTags(noteTags)); } useEffect(() => { @@ -55,20 +53,6 @@ const useEditorTags = () => { load(); }, [noteTags]); - // const hideTagBar = ` - // toggleNode(".tag-bar-parent","hide"); - // clearNode(".tag-bar")`; - // const showTagBar = ` - // toggleNode(".tag-bar-parent","show"); - // clearNode(".tag-bar")`; - // const clearNode = `clearNode(".tag-bar")`; - const renderTags = (tags: any) => `(function() { - clearNode(".tag-bar"); - toggleNode(".tag-bar-parent","show") - let items = ${JSON.stringify(tags)}; - renderChildernInNode(items, ".tag-bar", "div", ["tag","noselect"]); - })();`; - return []; };