mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 23:19:40 +01:00
feat: attachment download & progress from editor
This commit is contained in:
@@ -124,6 +124,9 @@ function init_tiny(size) {
|
|||||||
directionality: EDITOR_SETTINGS.directionality,
|
directionality: EDITOR_SETTINGS.directionality,
|
||||||
skin_url: 'dist/skins/notesnook',
|
skin_url: 'dist/skins/notesnook',
|
||||||
content_css: 'dist/skins/notesnook',
|
content_css: 'dist/skins/notesnook',
|
||||||
|
attachmenthandler_download_attachment:(hash) => {
|
||||||
|
reactNativeEventHandler('attachment_download',hash);
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
'checklist advlist autolink textpattern hr lists link noneditable image',
|
'checklist advlist autolink textpattern hr lists link noneditable image',
|
||||||
'searchreplace codeblock inlinecode keyboardquirks attachmentshandler',
|
'searchreplace codeblock inlinecode keyboardquirks attachmentshandler',
|
||||||
@@ -177,24 +180,6 @@ function init_tiny(size) {
|
|||||||
.h {
|
.h {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.img_float_left {
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
.img_float_right {
|
|
||||||
float:right;
|
|
||||||
}
|
|
||||||
.img_float_none {
|
|
||||||
float:none;
|
|
||||||
}
|
|
||||||
.img_size_one {
|
|
||||||
width:100%;
|
|
||||||
}
|
|
||||||
.img_size_two {
|
|
||||||
width:50%;
|
|
||||||
}
|
|
||||||
.img_size_three {
|
|
||||||
width:25%;
|
|
||||||
}
|
|
||||||
span.diff-del {
|
span.diff-del {
|
||||||
background-color: #FDB0C0;
|
background-color: #FDB0C0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import React, {useEffect, useRef, useState} from 'react';
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
import {Platform, ScrollView, Text, View} from 'react-native';
|
import {Platform, TouchableOpacity, View} from 'react-native';
|
||||||
import {FlatList} from 'react-native-gesture-handler';
|
import {FlatList} from 'react-native-gesture-handler';
|
||||||
|
import * as Progress from 'react-native-progress';
|
||||||
|
import * as ScopedStorage from 'react-native-scoped-storage';
|
||||||
|
import Sodium from 'react-native-sodium';
|
||||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
import {useTracked} from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import {useAttachmentStore} from '../../provider/stores';
|
import {useAttachmentStore} from '../../provider/stores';
|
||||||
@@ -12,24 +15,15 @@ import {
|
|||||||
import {db} from '../../utils/database';
|
import {db} from '../../utils/database';
|
||||||
import {
|
import {
|
||||||
eCloseAttachmentDialog,
|
eCloseAttachmentDialog,
|
||||||
eCloseTagsDialog,
|
eOpenAttachmentsDialog
|
||||||
eOpenAttachmentsDialog,
|
|
||||||
eOpenTagsDialog
|
|
||||||
} from '../../utils/Events';
|
} from '../../utils/Events';
|
||||||
|
import filesystem from '../../utils/filesystem';
|
||||||
import {SIZE} from '../../utils/SizeUtils';
|
import {SIZE} from '../../utils/SizeUtils';
|
||||||
import {sleep} from '../../utils/TimeUtils';
|
import Storage from '../../utils/storage';
|
||||||
import {ActionIcon} from '../ActionIcon';
|
import {ActionIcon} from '../ActionIcon';
|
||||||
import ActionSheetWrapper from '../ActionSheetComponent/ActionSheetWrapper';
|
import ActionSheetWrapper from '../ActionSheetComponent/ActionSheetWrapper';
|
||||||
import DialogHeader from '../Dialog/dialog-header';
|
import DialogHeader from '../Dialog/dialog-header';
|
||||||
import {PressableButton} from '../PressableButton';
|
|
||||||
import Heading from '../Typography/Heading';
|
|
||||||
import Paragraph from '../Typography/Paragraph';
|
import Paragraph from '../Typography/Paragraph';
|
||||||
import * as Progress from 'react-native-progress';
|
|
||||||
import filesystem from '../../utils/filesystem';
|
|
||||||
import * as ScopedStorage from 'react-native-scoped-storage';
|
|
||||||
import RNFetchBlob from 'rn-fetch-blob';
|
|
||||||
import Sodium from 'react-native-sodium';
|
|
||||||
import Storage from '../../utils/storage';
|
|
||||||
|
|
||||||
export const AttachmentDialog = () => {
|
export const AttachmentDialog = () => {
|
||||||
const [state] = useTracked();
|
const [state] = useTracked();
|
||||||
@@ -142,7 +136,6 @@ const Attachment = ({attachment, note, setNote}) => {
|
|||||||
const [state] = useTracked();
|
const [state] = useTracked();
|
||||||
const colors = state.colors;
|
const colors = state.colors;
|
||||||
const progress = useAttachmentStore(state => state.progress);
|
const progress = useAttachmentStore(state => state.progress);
|
||||||
const setProgress = useAttachmentStore(state => state.setProgress);
|
|
||||||
const [currentProgress, setCurrentProgress] = useState(null);
|
const [currentProgress, setCurrentProgress] = useState(null);
|
||||||
|
|
||||||
const onPress = async () => {
|
const onPress = async () => {
|
||||||
@@ -151,57 +144,22 @@ const Attachment = ({attachment, note, setNote}) => {
|
|||||||
useAttachmentStore.getState().remove(attachment.metadata.hash);
|
useAttachmentStore.getState().remove(attachment.metadata.hash);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
filesystem.downloadAttachment(attachment.metadata.hash);
|
||||||
let folder = {};
|
|
||||||
if (Platform.OS === 'android') {
|
|
||||||
folder = await ScopedStorage.openDocumentTree(false);
|
|
||||||
if (!folder) return;
|
|
||||||
} else {
|
|
||||||
folder.uri = await Storage.checkAndCreateDir('/Downloads/');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setCurrentProgress({
|
|
||||||
value: 0,
|
|
||||||
percent: '0%'
|
|
||||||
});
|
|
||||||
await db.fs.downloadFile(
|
|
||||||
attachment.metadata.hash,
|
|
||||||
attachment.metadata.hash
|
|
||||||
);
|
|
||||||
let key = await db.user.getEncryptionKey();
|
|
||||||
let info = {
|
|
||||||
iv: attachment.iv,
|
|
||||||
salt: attachment.salt,
|
|
||||||
length: attachment.length,
|
|
||||||
alg: attachment.alg,
|
|
||||||
hash: attachment.metadata.hash,
|
|
||||||
hashType: attachment.metadata.hashType,
|
|
||||||
mime: attachment.metadata.type,
|
|
||||||
fileName: attachment.metadata.filename,
|
|
||||||
uri: folder.uri
|
|
||||||
};
|
|
||||||
await Sodium.decryptFile(key, info, false);
|
|
||||||
ToastEvent.show({
|
|
||||||
heading: 'Download successful',
|
|
||||||
message: attachment.metadata.filename + 'downloaded',
|
|
||||||
type: 'success',
|
|
||||||
context: 'local'
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log('download attachment error: ', e);
|
|
||||||
useAttachmentStore.getState().remove(attachment.metadata.hash);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let prog = progress[attachment.metadata.hash];
|
let prog = progress[attachment.metadata.hash];
|
||||||
if (prog && prog.type === 'download') {
|
if (prog) {
|
||||||
prog = prog.recieved / prog.total;
|
let type = prog.type;
|
||||||
|
let loaded = prog.type === 'download' ? prog.recieved : prog.sent;
|
||||||
|
prog = loaded / prog.total;
|
||||||
prog = (prog * 100).toFixed(0);
|
prog = (prog * 100).toFixed(0);
|
||||||
console.log('progress: ', prog);
|
console.log('progress: ', prog);
|
||||||
|
console.log(prog);
|
||||||
setCurrentProgress({
|
setCurrentProgress({
|
||||||
value: prog,
|
value: prog,
|
||||||
percent: prog + '%'
|
percent: prog + '%',
|
||||||
|
type: type
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setCurrentProgress(null);
|
setCurrentProgress(null);
|
||||||
@@ -263,30 +221,38 @@ const Attachment = ({attachment, note, setNote}) => {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<Paragraph color={colors.icon} size={SIZE.xs}>
|
<Paragraph color={colors.icon} size={SIZE.xs}>
|
||||||
{formatBytes(attachment.length)} ({attachment.metadata.type})
|
{formatBytes(attachment.length)}{' '}
|
||||||
|
{currentProgress?.type ? '(' + currentProgress.type + 'ing - tap to cancel)' : ''}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{currentProgress ? (
|
{currentProgress ? (
|
||||||
<View
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.9}
|
||||||
|
onPress={() => {
|
||||||
|
db.fs.cancel(attachment.metadata.hash);
|
||||||
|
setCurrentProgress(null);
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
marginLeft: 5
|
marginLeft: 5,
|
||||||
|
marginTop:5,
|
||||||
|
marginRight:-5
|
||||||
}}>
|
}}>
|
||||||
<Progress.Circle
|
<Progress.Circle
|
||||||
size={SIZE.xxl}
|
size={SIZE.xxl}
|
||||||
progress={currentProgress?.value ? currentProgress?.value / 100 : 0}
|
progress={currentProgress?.value ? currentProgress?.value / 100 : 0}
|
||||||
showsText
|
showsText
|
||||||
textStyle={{
|
textStyle={{
|
||||||
fontSize: 9
|
fontSize: 10
|
||||||
}}
|
}}
|
||||||
color={colors.accent}
|
color={colors.accent}
|
||||||
formatText={progress => (progress * 100).toFixed(0)}
|
formatText={progress => (progress * 100).toFixed(0)}
|
||||||
borderWidth={0}
|
borderWidth={0}
|
||||||
thickness={2}
|
thickness={2}
|
||||||
/>
|
/>
|
||||||
</View>
|
</TouchableOpacity>
|
||||||
) : (
|
) : (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
onPress={() => onPress(attachment)}
|
onPress={() => onPress(attachment)}
|
||||||
|
|||||||
@@ -158,11 +158,10 @@ interface AttachmentStore {
|
|||||||
hash: string,
|
hash: string,
|
||||||
recieved: number,
|
recieved: number,
|
||||||
type: "upload" | "download",
|
type: "upload" | "download",
|
||||||
success: boolean
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
remove:(hash:string) => void
|
remove:(hash:string) => void
|
||||||
setProgress: (sent: number, total: number, hash: string, recieved: number, type: "upload" | "download", success) => void
|
setProgress: (sent: number, total: number, hash: string, recieved: number, type: "upload" | "download") => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAttachmentStore = create<AttachmentStore>((set, get) => ({
|
export const useAttachmentStore = create<AttachmentStore>((set, get) => ({
|
||||||
@@ -170,11 +169,20 @@ export const useAttachmentStore = create<AttachmentStore>((set, get) => ({
|
|||||||
remove:(hash) => {
|
remove:(hash) => {
|
||||||
let _p = get().progress;
|
let _p = get().progress;
|
||||||
_p[hash] = null
|
_p[hash] = null
|
||||||
|
tiny.call(EditorWebView, `
|
||||||
|
(function() {
|
||||||
|
let progress = ${JSON.stringify({
|
||||||
|
loaded:1,
|
||||||
|
total:1,
|
||||||
|
hash
|
||||||
|
})}
|
||||||
|
tinymce.activeEditor.execCommand("mceUpdateAttachmentProgress",progress);
|
||||||
|
})()`);
|
||||||
set({ progress: { ..._p } });
|
set({ progress: { ..._p } });
|
||||||
},
|
},
|
||||||
setProgress: (sent, total, hash, recieved, type, success) => {
|
setProgress: (sent, total, hash, recieved, type) => {
|
||||||
let _p = get().progress;
|
let _p = get().progress;
|
||||||
_p[hash] = { sent, total, hash, recieved, type, success };
|
_p[hash] = { sent, total, hash, recieved, type };
|
||||||
let progress = { total, hash, loaded: type === "download" ? recieved : sent };
|
let progress = { total, hash, loaded: type === "download" ? recieved : sent };
|
||||||
tiny.call(EditorWebView, `
|
tiny.call(EditorWebView, `
|
||||||
(function() {
|
(function() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -19,6 +19,7 @@ import {
|
|||||||
eShowGetPremium,
|
eShowGetPremium,
|
||||||
eShowMergeDialog
|
eShowMergeDialog
|
||||||
} from '../../utils/Events';
|
} from '../../utils/Events';
|
||||||
|
import filesystem from '../../utils/filesystem';
|
||||||
import {openLinkInBrowser} from '../../utils/functions';
|
import {openLinkInBrowser} from '../../utils/functions';
|
||||||
import {MMKV} from '../../utils/mmkv';
|
import {MMKV} from '../../utils/mmkv';
|
||||||
import {tabBarRef} from '../../utils/Refs';
|
import {tabBarRef} from '../../utils/Refs';
|
||||||
@@ -31,6 +32,7 @@ export const editorTitleInput = createRef();
|
|||||||
export const sourceUri =
|
export const sourceUri =
|
||||||
Platform.OS === 'android' ? 'file:///android_asset/' : 'Web.bundle/site/';
|
Platform.OS === 'android' ? 'file:///android_asset/' : 'Web.bundle/site/';
|
||||||
|
|
||||||
|
let lastEditTime = 0;
|
||||||
let EDITOR_SETTINGS = null;
|
let EDITOR_SETTINGS = null;
|
||||||
let webviewOK = true;
|
let webviewOK = true;
|
||||||
let noteEdited = false;
|
let noteEdited = false;
|
||||||
@@ -153,6 +155,7 @@ async function setNote(item) {
|
|||||||
title = note.title;
|
title = note.title;
|
||||||
id = note.id;
|
id = note.id;
|
||||||
noteEdited = false;
|
noteEdited = false;
|
||||||
|
lastEditTime = item.dateEdited;
|
||||||
if (note.locked) {
|
if (note.locked) {
|
||||||
content.data = note.content.data;
|
content.data = note.content.data;
|
||||||
content.type = note.content.type;
|
content.type = note.content.type;
|
||||||
@@ -188,6 +191,7 @@ export const loadNote = async item => {
|
|||||||
console.log('.....OPEN NOTE.....');
|
console.log('.....OPEN NOTE.....');
|
||||||
editing.currentlyEditing = true;
|
editing.currentlyEditing = true;
|
||||||
editing.movedAway = false;
|
editing.movedAway = false;
|
||||||
|
|
||||||
if (editing.isFocused) {
|
if (editing.isFocused) {
|
||||||
tiny.call(EditorWebView, tiny.blur);
|
tiny.call(EditorWebView, tiny.blur);
|
||||||
}
|
}
|
||||||
@@ -197,6 +201,7 @@ export const loadNote = async item => {
|
|||||||
await clearEditor(true, true, true);
|
await clearEditor(true, true, true);
|
||||||
}
|
}
|
||||||
disableSaving = false;
|
disableSaving = false;
|
||||||
|
lastEditTime = 0;
|
||||||
clearNote();
|
clearNote();
|
||||||
noteEdited = false;
|
noteEdited = false;
|
||||||
isFirstLoad = false;
|
isFirstLoad = false;
|
||||||
@@ -274,7 +279,6 @@ const checkStatus = async noreset => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
let lastEditTime = 0;
|
|
||||||
|
|
||||||
export const _onMessage = async evt => {
|
export const _onMessage = async evt => {
|
||||||
if (!evt || !evt.nativeEvent || !evt.nativeEvent.data) return;
|
if (!evt || !evt.nativeEvent || !evt.nativeEvent.data) return;
|
||||||
@@ -303,7 +307,6 @@ export const _onMessage = async evt => {
|
|||||||
case 'title':
|
case 'title':
|
||||||
if (message.value !== title) {
|
if (message.value !== title) {
|
||||||
noteEdited = true;
|
noteEdited = true;
|
||||||
|
|
||||||
lastEditTime = Date.now();
|
lastEditTime = Date.now();
|
||||||
title = message.value;
|
title = message.value;
|
||||||
eSendEvent('editorScroll', {
|
eSendEvent('editorScroll', {
|
||||||
@@ -315,6 +318,9 @@ export const _onMessage = async evt => {
|
|||||||
case 'scroll':
|
case 'scroll':
|
||||||
eSendEvent('editorScroll', message);
|
eSendEvent('editorScroll', message);
|
||||||
break;
|
break;
|
||||||
|
case 'attachment_download':
|
||||||
|
filesystem.downloadAttachment(message.value);
|
||||||
|
break;
|
||||||
case 'noteLoaded':
|
case 'noteLoaded':
|
||||||
tiny.call(EditorWebView, tiny.notLoading);
|
tiny.call(EditorWebView, tiny.notLoading);
|
||||||
eSendEvent('loadingNote');
|
eSendEvent('loadingNote');
|
||||||
@@ -611,6 +617,7 @@ export async function saveNote(preventUpdate) {
|
|||||||
Navigation.routeNames.Notes
|
Navigation.routeNames.Notes
|
||||||
]);
|
]);
|
||||||
let n = db.notes.note(id)?.data?.dateEdited;
|
let n = db.notes.note(id)?.data?.dateEdited;
|
||||||
|
lastEditTime = n + 10;
|
||||||
tiny.call(EditorWebView, tiny.updateDateEdited(timeConverter(n)));
|
tiny.call(EditorWebView, tiny.updateDateEdited(timeConverter(n)));
|
||||||
tiny.call(EditorWebView, tiny.updateSavingState('Saved'));
|
tiny.call(EditorWebView, tiny.updateSavingState('Saved'));
|
||||||
}
|
}
|
||||||
@@ -678,16 +685,28 @@ export async function updateNoteInEditor() {
|
|||||||
presentResolveConflictDialog(_note);
|
presentResolveConflictDialog(_note);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let data = await db.content.raw(note.contentId);
|
let data = await db.content.raw(_note.contentId);
|
||||||
if (lastEditTime > _note.dateEdited) return;
|
if (lastEditTime > _note.dateEdited) return;
|
||||||
if (data.data === content.data) return;
|
if (data.data === content.data) return;
|
||||||
if (content.data.indexOf(data.data) !== -1) return;
|
if (content.data.indexOf(data.data) !== -1) return;
|
||||||
if (note.dateEdited === _note.dateEdited) return;
|
if (note.dateEdited === _note.dateEdited) return;
|
||||||
|
|
||||||
|
console.log('injecting note in editor', lastEditTime, _note.dateEdited);
|
||||||
|
title = note.title;
|
||||||
|
content.data = data.data;
|
||||||
|
note = _note;
|
||||||
|
lastEditTime = _note.dateEdited + 10;
|
||||||
tiny.call(EditorWebView, tiny.isLoading);
|
tiny.call(EditorWebView, tiny.isLoading);
|
||||||
await setNote(_note);
|
await setNote(_note);
|
||||||
|
tiny.call(EditorWebView, tiny.isLoading);
|
||||||
post('title', title);
|
post('title', title);
|
||||||
post('inject', content.data);
|
post('inject', content.data);
|
||||||
|
setTimeout(() => {
|
||||||
|
tiny.call(EditorWebView, tiny.notLoading);
|
||||||
|
}, 50);
|
||||||
|
if (id) {
|
||||||
|
db.attachments.download(id);
|
||||||
|
}
|
||||||
tiny.call(EditorWebView, tiny.notLoading);
|
tiny.call(EditorWebView, tiny.notLoading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,12 @@ export const execCommands = {
|
|||||||
EditorWebView,
|
EditorWebView,
|
||||||
`
|
`
|
||||||
(function() {
|
(function() {
|
||||||
let file = ${JSON.stringify(attachment)}
|
let file = ${JSON.stringify({
|
||||||
|
hash:hash,
|
||||||
|
filename:file.name,
|
||||||
|
type:file.type,
|
||||||
|
size:file.size
|
||||||
|
})}
|
||||||
tinymce.activeEditor.execCommand('mceAttachFile',file);
|
tinymce.activeEditor.execCommand('mceAttachFile',file);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
||||||
@@ -127,8 +132,7 @@ export const execCommands = {
|
|||||||
maxHeight: 2000,
|
maxHeight: 2000,
|
||||||
quality: 0.8,
|
quality: 0.8,
|
||||||
mediaType: 'photo',
|
mediaType: 'photo',
|
||||||
encryptToFile: false,
|
encryptToFile: false
|
||||||
...key
|
|
||||||
},
|
},
|
||||||
handleImageResponse
|
handleImageResponse
|
||||||
);
|
);
|
||||||
@@ -147,8 +151,7 @@ export const execCommands = {
|
|||||||
maxHeight: 2000,
|
maxHeight: 2000,
|
||||||
quality: 0.8,
|
quality: 0.8,
|
||||||
mediaType: 'photo',
|
mediaType: 'photo',
|
||||||
encryptToFile: false,
|
encryptToFile: false
|
||||||
...key
|
|
||||||
},
|
},
|
||||||
handleImageResponse
|
handleImageResponse
|
||||||
);
|
);
|
||||||
@@ -170,69 +173,9 @@ export const execCommands = {
|
|||||||
tablesplitcell: "tinymce.activeEditor.execCommand('mceTableSplitCells');",
|
tablesplitcell: "tinymce.activeEditor.execCommand('mceTableSplitCells');",
|
||||||
tablemergecell: "tinymce.activeEditor.execCommand('mceTableMergeCells');",
|
tablemergecell: "tinymce.activeEditor.execCommand('mceTableMergeCells');",
|
||||||
tablerowprops: "tinymce.activeEditor.execCommand('mceTableRowProps');",
|
tablerowprops: "tinymce.activeEditor.execCommand('mceTableRowProps');",
|
||||||
imageResize25: `(function() {
|
imageResize25: () => setImageSize(0.25),
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
imageResize50: () => setImageSize(0.5),
|
||||||
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
imageResize100: () => setImageSize(1),
|
||||||
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_one")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_one")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_two")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_two")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_size_three")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
`,
|
|
||||||
imageResize50: `(function() {
|
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
|
||||||
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_one")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_one")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_three")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_three")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_size_two")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
`,
|
|
||||||
imageResize100: `(function() {
|
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
|
||||||
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_three")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_three")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_size_two")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_size_two")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_size_one")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
`,
|
|
||||||
imagepreview: `(function() {
|
imagepreview: `(function() {
|
||||||
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
@@ -272,67 +215,9 @@ export const execCommands = {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
`,
|
`,
|
||||||
imagefloatleft: `(function () {
|
imagefloatleft: () => setFloat('left'),
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
imagefloatright: () => setFloat('right'),
|
||||||
if (node.tagName === 'IMG') {
|
imagefloatnone: () => setFloat('none'),
|
||||||
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_right")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_float_right")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_none")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_float_none")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_float_left")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
`,
|
|
||||||
imagefloatright: `(function () {
|
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
|
||||||
if (node.tagName === 'IMG') {
|
|
||||||
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_left")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node, "img_float_left")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_none")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_float_none")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_float_right")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
`,
|
|
||||||
imagefloatnone: `(function () {
|
|
||||||
let node = tinymce.activeEditor.selection.getNode();
|
|
||||||
if (node.tagName === 'IMG') {
|
|
||||||
|
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_left")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_float_left")
|
|
||||||
}
|
|
||||||
if (tinymce.activeEditor.dom.hasClass(node,"img_float_right")) {
|
|
||||||
tinymce.activeEditor.dom.removeClass(node,"img_float_right")
|
|
||||||
}
|
|
||||||
tinymce.activeEditor.dom.addClass(node,"img_float_none")
|
|
||||||
setTimeout(function() {
|
|
||||||
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
|
||||||
},100)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
`,
|
|
||||||
'line-break': `
|
'line-break': `
|
||||||
tinymce.activeEditor.undoManager.transact(function() {
|
tinymce.activeEditor.undoManager.transact(function() {
|
||||||
tinymce.activeEditor.execCommand('InsertLineBreak');
|
tinymce.activeEditor.execCommand('InsertLineBreak');
|
||||||
@@ -358,7 +243,7 @@ const handleImageResponse = async response => {
|
|||||||
uri: image.uri,
|
uri: image.uri,
|
||||||
type: 'url'
|
type: 'url'
|
||||||
});
|
});
|
||||||
console.log('hash: ',hash);
|
|
||||||
tiny.call(
|
tiny.call(
|
||||||
EditorWebView,
|
EditorWebView,
|
||||||
`
|
`
|
||||||
@@ -367,7 +252,8 @@ const handleImageResponse = async response => {
|
|||||||
hash: hash,
|
hash: hash,
|
||||||
type: image.type,
|
type: image.type,
|
||||||
filename: image.fileName,
|
filename: image.fileName,
|
||||||
dataurl: b64
|
dataurl: b64,
|
||||||
|
size: image.fileSize
|
||||||
})}
|
})}
|
||||||
tinymce.activeEditor.execCommand('mceAttachImage',image);
|
tinymce.activeEditor.execCommand('mceAttachImage',image);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
@@ -404,3 +290,39 @@ async function attachFile(uri, hash, type, filename) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setFloat = float => `(function () {
|
||||||
|
let node = tinymce.activeEditor.selection.getNode();
|
||||||
|
if (node.tagName === 'IMG') {
|
||||||
|
tinymce.activeEditor.undoManager.transact(function() {
|
||||||
|
node.style.float = "${float}";
|
||||||
|
setTimeout(function() {
|
||||||
|
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
||||||
|
},100)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})()`;
|
||||||
|
|
||||||
|
const setImageSize = size => `(function() {
|
||||||
|
let node = tinymce.activeEditor.selection.getNode();
|
||||||
|
if (tinymce.activeEditor.selection.getNode().tagName === 'IMG') {
|
||||||
|
tinymce.activeEditor.undoManager.transact(function() {
|
||||||
|
let rect = node.getBoundingClientRect();
|
||||||
|
let originalWidth = rect.width;
|
||||||
|
let originalHeight = rect.height;
|
||||||
|
if (node.dataset.width) {
|
||||||
|
originalWidth = node.dataset.width;
|
||||||
|
originalHeight = node.dataset.height;
|
||||||
|
} else {
|
||||||
|
node.dataset.width = originalWidth;
|
||||||
|
node.dataset.height = originalHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.width = originalWidth * ${size}
|
||||||
|
setTimeout(function() {
|
||||||
|
tinymce.activeEditor.nodeChanged({selectionChange:true})
|
||||||
|
},100)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user