diff --git a/apps/mobile/src/screens/editor/index.js b/apps/mobile/src/screens/editor/index.js
index dfa5ecc82..3b185b1c3 100755
--- a/apps/mobile/src/screens/editor/index.js
+++ b/apps/mobile/src/screens/editor/index.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { Linking, Platform, View } from 'react-native';
+import { Linking, Platform } from 'react-native';
import WebView from 'react-native-webview';
import { notesnook } from '../../../e2e/test.ids';
import { useUserStore } from '../../stores/use-user-store';
@@ -8,7 +8,6 @@ import { useEditorEvents } from './tiptap/use-editor-events';
import { editorController } from './tiptap/utils';
const sourceUri = '';
-
const source = { uri: sourceUri + 'index.html' };
const style = {
@@ -18,7 +17,11 @@ const style = {
alignSelf: 'center',
backgroundColor: 'transparent'
};
-const off = true;
+const onShouldStartLoadWithRequest = request => {
+ Linking.openURL(request.url);
+ return false;
+};
+
const Editor = React.memo(
() => {
const premiumUser = useUserStore(state => state.premium);
@@ -27,62 +30,44 @@ const Editor = React.memo(
editorController.current = editor;
const onError = () => {
- console.log('onError');
editorController.current?.setLoading(true);
setTimeout(() => editorController.current?.setLoading(false), 10);
};
- const onShouldStartLoadWithRequest = request => {
- Linking.openURL(request.url);
- return false;
- };
-
- return editor.loading || off ? null : (
- <>
-
- }
- startInLoadingState
- hideKeyboardAccessoryView={true}
- allowingReadAccessToURL={Platform.OS === 'android' ? true : null}
- allowFileAccessFromFileURLs={true}
- allowUniversalAccessFromFileURLs={true}
- originWhitelist={['*']}
- source={{
- uri: 'http://192.168.10.7:3000'
- }}
- style={style}
- autoManageStatusBarEnabled={false}
- onMessage={onMessage}
- />
-
- >
+ return editor.loading ? null : (
+
);
},
() => true
diff --git a/apps/mobile/src/screens/editor/tiptap/commands.ts b/apps/mobile/src/screens/editor/tiptap/commands.ts
index 5c8574aa5..b1906bede 100644
--- a/apps/mobile/src/screens/editor/tiptap/commands.ts
+++ b/apps/mobile/src/screens/editor/tiptap/commands.ts
@@ -6,6 +6,8 @@ import { db } from '../../../utils/database';
import { sleep } from '../../../utils/time';
import { Note } from './types';
import { getResponse, randId, textInput } from './utils';
+import { Attachment, AttachmentProgress } from 'notesnook-editor/dist/extensions/attachment/index';
+import { ImageAttributes } from 'notesnook-editor/dist/extensions/image/index';
type Action = { job: string; id: string };
@@ -49,6 +51,11 @@ class Commands {
this.ref = ref;
}
+ async doAsync(job: string) {
+ if (!this.ref) return false;
+ return await call(this.ref, fn(job));
+ }
+
focus = async () => {
if (!this.ref) return;
if (Platform.OS === 'android') {
@@ -57,70 +64,57 @@ class Commands {
if (!this.ref) return;
textInput.current?.focus();
this.ref?.current?.requestFocus();
- await call(this.ref, fn(`editor.commands.focus()`));
+ await this.doAsync(`editor.commands.focus()`);
}, 1);
} else {
await sleep(200);
- await call(this.ref, fn(`editor.commands.focus()`));
+ await this.doAsync(`editor.commands.focus()`);
}
};
- blur = async () => await call(this.ref, fn(`editor.commands.blur();editorTitle.current?.blur()`));
+ blur = async () => await this.doAsync(`editor.commands.blur();editorTitle.current?.blur()`);
clearContent = async () => {
- await call(
- this.ref,
- fn(
- `
+ await this.doAsync(
+ `
editor.commands.blur();
editorTitle.current?.blur();
editor?.commands.clearContent(false);
editorController.setTitle(null);
statusBar.current.set({date:"",saved:""});
`
- )
);
};
- setSessionId = async (id: string | null) =>
- await call(this.ref, fn(`globalThis.sessionId = "${id}"`));
+ setSessionId = async (id: string | null) => await this.doAsync(`globalThis.sessionId = "${id}"`);
setStatus = async (date: string | undefined, saved: string) =>
- await call(this.ref, fn(`statusBar.current.set({date:"${date}",saved:"${saved}"})`));
+ await this.doAsync(`statusBar.current.set({date:"${date}",saved:"${saved}"})`);
setPlaceholder = async (placeholder: string) => {
- await call(
- this.ref,
- fn(`
+ await this.doAsync(`
const element = document.querySelector(".is-editor-empty");
if (element) {
element.setAttribute("data-placeholder","${placeholder}");
}
- `)
- );
+ `);
};
setInsets = async (insets: EdgeInsets) => {
logger.info('setInsets', insets);
- await call(
- this.ref,
- fn(`
+ await this.doAsync(`
if (typeof safeAreaController !== "undefined") {
safeAreaController.update(${JSON.stringify(insets)})
}
- `)
- );
+ `);
};
setSettings = async (settings: Partial) => {
- await call(
- this.ref,
- fn(`
+ await this.doAsync(`
if (typeof globalThis.settingsController !== "undefined") {
globalThis.settingsController.update(${JSON.stringify(settings)})
}
- `)
- );
+ `);
};
setTags = async (note: Note | null | undefined) => {
@@ -130,15 +124,32 @@ statusBar.current.set({date:"",saved:""});
db.tags?.tag(t) ? { title: db.tags.tag(t).title, alias: db.tags.tag(t).alias } : null
)
.filter((t: any) => t !== null);
- await call(
- this.ref,
- fn(`
- if (typeof editorTags !== "undefined" && editorTags.current) {
- editorTags.current.setTags(${JSON.stringify(tags)});
- }
- `)
+ await this.doAsync(`
+ if (typeof editorTags !== "undefined" && editorTags.current) {
+ editorTags.current.setTags(${JSON.stringify(tags)});
+ }
+ `);
+ };
+
+ insertAttachment = async (attachment: Attachment) => {
+ this.doAsync(`editor && editor.commands.insertAttachment(${JSON.stringify(attachment)})`);
+ };
+
+ setAttachmentProgress = async (attachmentProgress: AttachmentProgress) => {
+ this.doAsync(
+ `editor && editor.commands.setAttachmentProgress(${JSON.stringify(attachmentProgress)})`
);
};
+
+ insertImage = async (image: ImageAttributes) => {
+ console.log('image data', image);
+ this.doAsync(`editor && editor.commands.insertImage(${JSON.stringify(image)})`);
+ };
+
+ updateImage = async (image: ImageAttributes) => {
+ this.doAsync(`editor && editor.commands.updateImage(${JSON.stringify(image)})`);
+ };
+ //todo add replace image function
}
export default Commands;
diff --git a/apps/mobile/src/screens/editor/tiptap/picker.js b/apps/mobile/src/screens/editor/tiptap/picker.js
index dd48e29f5..ed2455018 100644
--- a/apps/mobile/src/screens/editor/tiptap/picker.js
+++ b/apps/mobile/src/screens/editor/tiptap/picker.js
@@ -48,7 +48,7 @@ const santizeUri = uri => {
const file = async fileOptions => {
try {
- let options = {
+ const options = {
mode: 'import',
allowMultiSelection: false
};
@@ -56,7 +56,7 @@ const file = async fileOptions => {
options.copyTo = 'cachesDirectory';
}
console.log('generate key for attachment');
- let key = await db.attachments.generateKey();
+ const key = await db.attachments.generateKey();
console.log('generated key for attachments: ', key);
let file;
try {
@@ -97,38 +97,20 @@ const file = async fileOptions => {
console.log('file uri: ', uri);
uri = Platform.OS === 'ios' ? santizeUri(uri) : uri;
showEncryptionSheet(file);
- let hash = await Sodium.hashFile({
+ const 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);
-
+ if (!(await attachFile(uri, hash, file.type, file.name, fileOptions))) return;
+ editorController.current?.commands.insertAttachment({
+ hash: hash,
+ filename: file.name,
+ type: file.type,
+ size: file.size
+ });
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,
@@ -207,45 +189,29 @@ const pick = async options => {
return;
}
- if (options?.reupload) {
- if (options?.type.startsWith('image')) {
+ if (options?.type.startsWith('image')) {
+ if (options?.reupload) {
gallery(options);
} else {
- file(options);
+ presentSheet({
+ context: options?.context,
+ actionsArray: [
+ {
+ action: () => camera(options),
+ actionText: 'Open camera',
+ icon: 'camera'
+ },
+ {
+ action: () => gallery(options),
+ actionText: 'Select image from gallery',
+ icon: 'image-multiple'
+ }
+ ]
+ });
}
- return;
+ } else {
+ file(options);
}
-
- 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) => {
@@ -267,38 +233,24 @@ const handleImageResponse = async (response, options) => {
});
return;
}
- let b64 = `data:${image.type};base64, ` + image.base64;
- let uri = image.uri;
- uri = decodeURI(uri);
- let hash = await Sodium.hashFile({
+ const b64 = `data:${image.type};base64, ` + image.base64;
+ const uri = decodeURI(image.uri);
+ const 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
- // })}
+ if (!(await attachFile(uri, hash, image.type, fileName, options))) return;
- // editor.undoManager.transact(function() {
- // tinymce.activeEditor.execCommand('mceAttachImage',image);
- // setTimeout(function() {
- // tinymce.activeEditor.fire("input",{data:""})
- // },100)
- // });
- // })();
- // `
- // );
+ editorController.current?.commands.insertImage({
+ hash: hash,
+ type: image.type,
+ title: fileName,
+ src: b64,
+ size: image.fileSize,
+ filename: fileName
+ });
};
async function attachFile(uri, hash, type, filename, options) {
diff --git a/apps/mobile/src/screens/editor/tiptap/useEditor.ts b/apps/mobile/src/screens/editor/tiptap/useEditor.ts
index 56d25d8f5..aa19486de 100644
--- a/apps/mobile/src/screens/editor/tiptap/useEditor.ts
+++ b/apps/mobile/src/screens/editor/tiptap/useEditor.ts
@@ -92,6 +92,7 @@ export const useEditor = () => {
}, []);
const reset = useCallback(async (resetState = true) => {
+ currentNote.current?.id && db.fs.cancel(currentNote.current.id);
currentNote.current = null;
currentContent.current = null;
sessionHistoryId.current = undefined;
@@ -224,6 +225,7 @@ export const useEditor = () => {
await commands.setStatus(timeConverter(item.dateEdited), 'Saved');
await postMessage(EditorEvents.title, item.title);
await postMessage(EditorEvents.html, currentContent.current?.data);
+ loadImages();
await commands.setTags(currentNote.current);
overlay(false);
}
@@ -231,6 +233,14 @@ export const useEditor = () => {
[setSessionId]
);
+ const loadImages = () => {
+ if (!currentNote.current?.id) return;
+ const images = db.attachments?.ofNote(currentNote.current?.id, 'images');
+ if (images && images.length > 0) {
+ db.attachments?.downloadImages(currentNote.current.id);
+ }
+ };
+
useEffect(() => {
eSubscribeEvent(eOnLoadNote, loadNote);
return () => {
diff --git a/apps/mobile/src/screens/editor/tiptap/useEditorEvents.ts b/apps/mobile/src/screens/editor/tiptap/useEditorEvents.ts
index 14f34bd50..a61dc3a75 100644
--- a/apps/mobile/src/screens/editor/tiptap/useEditorEvents.ts
+++ b/apps/mobile/src/screens/editor/tiptap/useEditorEvents.ts
@@ -127,7 +127,7 @@ export const useEditorEvents = (editor: useEditorType) => {
premium: isPremium,
readonly: readonly
});
- }, [currentEditingNote, fullscreen, isPremium, readonly]);
+ }, [currentEditingNote, fullscreen, isPremium, readonly, editor.sessionId, editor.loading]);
const onBackPress = useCallback(async () => {
setTimeout(async () => {
@@ -272,9 +272,10 @@ export const useEditorEvents = (editor: useEditorType) => {
}
break;
case EventTypes.filepicker:
- picker.pick();
+ picker.pick({ type: editorMessage.value });
break;
case EventTypes.download:
+ console.log('download attachment request', editorMessage.value);
filesystem.downloadAttachment(editorMessage.value?.hash, true);
break;
case EventTypes.pro:
diff --git a/apps/mobile/src/stores/useAttachmentStore.ts b/apps/mobile/src/stores/useAttachmentStore.ts
index 7d2dcae99..c7dce52f5 100644
--- a/apps/mobile/src/stores/useAttachmentStore.ts
+++ b/apps/mobile/src/stores/useAttachmentStore.ts
@@ -1,5 +1,6 @@
//@ts-ignore
import create from 'zustand';
+import { editorController } from '../screens/editor/tiptap/utils';
interface AttachmentStore {
progress?: {
@@ -28,37 +29,27 @@ interface AttachmentStore {
export const useAttachmentStore = create((set, get) => ({
progress: {},
remove: hash => {
- 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);
- // })()`
- // );
- set({ progress: { ..._p } });
+ let progress = get().progress;
+ if (!progress) return;
+ editorController.current?.commands.setAttachmentProgress({
+ hash: hash,
+ progress: 100,
+ type: progress[hash]?.type || 'download'
+ });
+ progress[hash] = null;
+ set({ progress: { ...progress } });
},
setProgress: (sent, total, hash, recieved, type) => {
- let _p = get().progress;
- 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);
- // })()`
- // );
- set({ progress: { ..._p } });
+ let progress = get().progress;
+ if (!progress) return;
+ progress[hash] = { sent, total, hash, recieved, type };
+ const progressPercentage = type === 'upload' ? sent / total : recieved / total;
+ editorController.current?.commands.setAttachmentProgress({
+ hash: hash,
+ progress: Math.round(Math.max(progressPercentage * 100, 0)),
+ type: type
+ });
+ set({ progress: { ...progress } });
},
encryptionProgress: 0,
setEncryptionProgress: encryptionProgress => set({ encryptionProgress: encryptionProgress }),