mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
improve editor performance
This commit is contained in:
@@ -39,6 +39,7 @@ import Animated, {Easing} from 'react-native-reanimated';
|
||||
import {useForceUpdate} from './src/views/ListsEditor';
|
||||
import FastStorage from 'react-native-fast-storage';
|
||||
import {defaultState} from './src/provider/defaultState';
|
||||
import {EditorPosition} from './src/utils/animations';
|
||||
export const DDS = new DeviceDetectionService();
|
||||
export const db = new Storage(StorageInterface);
|
||||
|
||||
@@ -176,9 +177,9 @@ const App = () => {
|
||||
} else {
|
||||
s = JSON.parse(s);
|
||||
scale.fontScale = s.fontScale;
|
||||
console.log(scale.fontScale);
|
||||
|
||||
updateSize();
|
||||
console.log(SIZE.lg);
|
||||
|
||||
dispatch({type: ACTIONS.SETTINGS, settings: {...s}});
|
||||
}
|
||||
dispatch({type: ACTIONS.THEME, colors: newColors});
|
||||
@@ -367,7 +368,27 @@ const App = () => {
|
||||
/>
|
||||
</SideMenu>
|
||||
)}
|
||||
|
||||
<Animated.View
|
||||
ref={ref => (editorRef = ref)}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
zIndex: 10,
|
||||
backgroundColor: colors.bg,
|
||||
elevation: 10,
|
||||
transform: [
|
||||
{
|
||||
translateX: EditorPosition,
|
||||
},
|
||||
],
|
||||
}}>
|
||||
<Editor noMenu={false} />
|
||||
</Animated.View>
|
||||
|
||||
<Toast />
|
||||
|
||||
<DialogManager colors={colors} />
|
||||
</Animatable.View>
|
||||
</>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
simpleDialogEvent,
|
||||
TEMPLATE_TRASH,
|
||||
} from '../DialogManager';
|
||||
import {openEditorAnimation} from '../../utils/animations';
|
||||
|
||||
const w = Dimensions.get('window').width;
|
||||
const h = Dimensions.get('window').height;
|
||||
@@ -116,14 +117,15 @@ export default class NoteItem extends React.Component {
|
||||
onPress={() => {
|
||||
if (item.locked) {
|
||||
eSendEvent(eOpenVaultDialog, {unlock: true, i: item});
|
||||
return;
|
||||
}
|
||||
if (DDS.isTab) {
|
||||
eSendEvent(eOnLoadNote, item);
|
||||
} else if (isTrash) {
|
||||
simpleDialogEvent(TEMPLATE_TRASH(item.type));
|
||||
} else {
|
||||
DDS.isTab
|
||||
? eSendEvent(eOnLoadNote, item)
|
||||
: isTrash
|
||||
? simpleDialogEvent(TEMPLATE_TRASH(item.type))
|
||||
: NavigationService.navigate('Editor', {
|
||||
note: item,
|
||||
});
|
||||
eSendEvent(eOnLoadNote, item);
|
||||
openEditorAnimation();
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
|
||||
@@ -65,16 +65,17 @@ export const Toast = () => {
|
||||
return (
|
||||
<Animatable.View
|
||||
transition={['translateY', 'opacity']}
|
||||
duration={500}
|
||||
duration={10}
|
||||
delay={toast ? 300 : 0}
|
||||
useNativeDriver={true}
|
||||
style={{
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
height: 60,
|
||||
opacity: toast ? 1 : 0,
|
||||
bottom: 100,
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
elevation: 15,
|
||||
transform: [
|
||||
{
|
||||
translateY: toast ? 0 : 300,
|
||||
@@ -83,6 +84,8 @@ export const Toast = () => {
|
||||
}}>
|
||||
<AnimatedTouchableOpacity
|
||||
activeOpacity={opacity + 0.1}
|
||||
transition={['opacity']}
|
||||
duration={300}
|
||||
style={{
|
||||
...toastStyle,
|
||||
maxWidth: DDS.isTab ? normalize(350) : w - 24,
|
||||
@@ -91,6 +94,7 @@ export const Toast = () => {
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: ph,
|
||||
paddingVertical: pv,
|
||||
opacity: toast ? 1 : 0,
|
||||
justifyContent: 'center',
|
||||
elevation: 25,
|
||||
flexDirection: 'row',
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
import Animated, {Easing} from 'react-native-reanimated';
|
||||
import {Dimensions} from 'react-native';
|
||||
|
||||
const {color, Value, timing} = Animated;
|
||||
|
||||
export const EditorPosition = new Value(Dimensions.get('window').width * 1.5);
|
||||
|
||||
export function openEditorAnimation() {
|
||||
let openConfigH = {
|
||||
duration: 300,
|
||||
toValue: 0,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
};
|
||||
timing(EditorPosition, openConfigH).start();
|
||||
}
|
||||
|
||||
export function exitEditorAnimation() {
|
||||
let openConfigH = {
|
||||
duration: 300,
|
||||
toValue: Dimensions.get('window').width * 1.5,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
};
|
||||
timing(EditorPosition, openConfigH).start();
|
||||
}
|
||||
|
||||
export const slideRight = {
|
||||
0: {
|
||||
transform: [{translateX: -4}],
|
||||
|
||||
@@ -58,7 +58,7 @@ export const w = Dimensions.get('window').width;
|
||||
export const h = Dimensions.get('window').height;
|
||||
|
||||
export const ToastEvent = {
|
||||
show: (message, type, duration = 1000, func = null, actionText = '') => {
|
||||
show: (message, type, duration = 3000, func = null, actionText = '') => {
|
||||
eSendEvent(eShowToast, {
|
||||
message,
|
||||
type,
|
||||
@@ -67,7 +67,7 @@ export const ToastEvent = {
|
||||
actionText,
|
||||
});
|
||||
},
|
||||
hide: (message, type, duration = 1000, func = null, actionText = '') => {
|
||||
hide: (message, type, duration = 3000, func = null, actionText = '') => {
|
||||
eSendEvent(eHideToast, {
|
||||
message,
|
||||
type,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import React, {createRef, useEffect, useState} from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
BackHandler,
|
||||
KeyboardAvoidingView,
|
||||
Linking,
|
||||
@@ -9,16 +8,15 @@ import {
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
SafeAreaView,
|
||||
} from 'react-native';
|
||||
import * as Animatable from 'react-native-animatable';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import WebView from 'react-native-webview';
|
||||
import {db, DDS} from '../../../App';
|
||||
import {SIZE, WEIGHT, normalize, opacity} from '../../common/common';
|
||||
import {normalize, SIZE, WEIGHT} from '../../common/common';
|
||||
import {
|
||||
ActionSheetEvent,
|
||||
simpleDialogEvent,
|
||||
TEMPLATE_EXIT,
|
||||
TEMPLATE_EXIT_FULLSCREEN,
|
||||
TEMPLATE_INFO,
|
||||
} from '../../components/DialogManager';
|
||||
@@ -34,19 +32,17 @@ import {
|
||||
eOnLoadNote,
|
||||
eOpenFullscreenEditor,
|
||||
} from '../../services/events';
|
||||
import {exitEditorAnimation} from '../../utils/animations';
|
||||
import {
|
||||
editing,
|
||||
SideMenuEvent,
|
||||
timeConverter,
|
||||
ToastEvent,
|
||||
editing,
|
||||
} from '../../utils/utils';
|
||||
import {AnimatedSafeAreaView} from '../Home';
|
||||
import NavigationService from '../../services/NavigationService';
|
||||
|
||||
let EditorWebView;
|
||||
const EditorWebView = createRef();
|
||||
let note = {};
|
||||
let id = null;
|
||||
let dateEdited = null;
|
||||
var content = null;
|
||||
var title = null;
|
||||
let timer = null;
|
||||
@@ -57,12 +53,18 @@ const Editor = ({navigation, noMenu}) => {
|
||||
// Global State
|
||||
const [state, dispatch] = useTracked();
|
||||
const {colors} = state;
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [fullscreen, setFullscreen] = useState(false);
|
||||
|
||||
const [dateEdited, setDateEdited] = useState(0);
|
||||
// FUNCTIONS
|
||||
|
||||
const post = value => EditorWebView.postMessage(value);
|
||||
const post = value => EditorWebView.current?.postMessage(value);
|
||||
|
||||
useEffect(() => {
|
||||
let c = {...colors};
|
||||
c.factor = normalize(1);
|
||||
post(JSON.stringify(c));
|
||||
}, [colors.bg]);
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent(eOnLoadNote, loadNote);
|
||||
|
||||
@@ -71,56 +73,44 @@ const Editor = ({navigation, noMenu}) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 3000);
|
||||
}, [colors.bg]);
|
||||
|
||||
const loadNote = item => {
|
||||
const loadNote = async item => {
|
||||
if (note && note.id) {
|
||||
saveNote(true).then(() => {
|
||||
dispatch({type: ACTIONS.NOTES});
|
||||
if (item && item.type === 'new') {
|
||||
clearEditor();
|
||||
await clearEditor();
|
||||
} else {
|
||||
note = item;
|
||||
if (DDS.isTab) {
|
||||
dispatch({
|
||||
type: ACTIONS.CURRENT_EDITING_NOTE,
|
||||
id: item.id,
|
||||
});
|
||||
}
|
||||
|
||||
updateEditor();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
dispatch({type: ACTIONS.NOTES});
|
||||
if (item && item.type === 'new') {
|
||||
clearEditor();
|
||||
await clearEditor();
|
||||
} else {
|
||||
note = item;
|
||||
if (DDS.isTab) {
|
||||
dispatch({
|
||||
type: ACTIONS.CURRENT_EDITING_NOTE,
|
||||
id: item.id,
|
||||
});
|
||||
}
|
||||
updateEditor();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clearEditor = () => {
|
||||
id = null;
|
||||
const clearEditor = async () => {
|
||||
await saveNote();
|
||||
title = null;
|
||||
content = null;
|
||||
note = {};
|
||||
note = null;
|
||||
id = null;
|
||||
tapCount = 0;
|
||||
saveCounter = 0;
|
||||
EditorWebView.reload();
|
||||
|
||||
post('clear');
|
||||
post(JSON.stringify({type: 'text', value: ''}));
|
||||
post('focusTitle');
|
||||
};
|
||||
|
||||
@@ -137,7 +127,6 @@ const Editor = ({navigation, noMenu}) => {
|
||||
|
||||
const _onMessage = evt => {
|
||||
if (evt.nativeEvent.data === 'loaded') {
|
||||
setLoading(false);
|
||||
} else if (
|
||||
evt.nativeEvent.data !== '' &&
|
||||
evt.nativeEvent.data !== 'loaded'
|
||||
@@ -171,8 +160,6 @@ const Editor = ({navigation, noMenu}) => {
|
||||
};
|
||||
}
|
||||
|
||||
console.log(content.delta, 'i am called');
|
||||
|
||||
let rId = await db.notes.add({
|
||||
title,
|
||||
content: {
|
||||
@@ -195,8 +182,7 @@ const Editor = ({navigation, noMenu}) => {
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
if (DDS.isTab) {
|
||||
if (id) {
|
||||
dispatch({
|
||||
type: ACTIONS.CURRENT_EDITING_NOTE,
|
||||
id: id,
|
||||
@@ -254,17 +240,10 @@ const Editor = ({navigation, noMenu}) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (navigation && navigation.state.params && navigation.state.params.note) {
|
||||
note = navigation.state.params.note;
|
||||
|
||||
updateEditor();
|
||||
} else if (note && note.id) {
|
||||
if (note && note.id) {
|
||||
updateEditor();
|
||||
} else {
|
||||
post('focusTitle');
|
||||
wait(500).then(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
let c = {...colors};
|
||||
c.factor = normalize(1);
|
||||
@@ -280,17 +259,14 @@ const Editor = ({navigation, noMenu}) => {
|
||||
});
|
||||
|
||||
const updateEditor = async () => {
|
||||
console.log('before', content, title, id);
|
||||
title = note.title;
|
||||
id = note.id;
|
||||
dateEdited = note.dateEdited;
|
||||
setDateEdited(note.dateEdited);
|
||||
content = note.content;
|
||||
if (!note.locked) {
|
||||
content.delta = await db.notes.note(id).delta();
|
||||
}
|
||||
|
||||
console.log('after', content, title, id);
|
||||
|
||||
saveCounter = 0;
|
||||
|
||||
if (title !== null || title === '') {
|
||||
@@ -303,18 +279,11 @@ const Editor = ({navigation, noMenu}) => {
|
||||
} else {
|
||||
post('focusTitle');
|
||||
post('clear');
|
||||
wait(500).then(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
if (note.content.text === '' && note.content.delta === null) {
|
||||
post('clear');
|
||||
wait(500).then(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
} else if (note.content.delta) {
|
||||
let delta;
|
||||
console.log(note.content.delta, 'HERE');
|
||||
if (typeof note.content.delta !== 'string') {
|
||||
delta = note.content.delta;
|
||||
} else {
|
||||
@@ -324,9 +293,6 @@ const Editor = ({navigation, noMenu}) => {
|
||||
post(JSON.stringify(delta));
|
||||
} else {
|
||||
post(JSON.stringify({type: 'text', value: note.content.text}));
|
||||
wait(2000).then(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -340,8 +306,92 @@ const Editor = ({navigation, noMenu}) => {
|
||||
link.click();
|
||||
}`;
|
||||
|
||||
const _renderEditor = () => {
|
||||
const closeFullscreen = () => {
|
||||
setFullscreen(false);
|
||||
};
|
||||
|
||||
// EFFECTS
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
|
||||
|
||||
return () => {
|
||||
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
|
||||
};
|
||||
});
|
||||
|
||||
const _onHardwareBackPress = async () => {
|
||||
if (tapCount > 0) {
|
||||
exitEditorAnimation();
|
||||
await clearEditor();
|
||||
ToastEvent.show('Note Saved!', 'success');
|
||||
return true;
|
||||
} else {
|
||||
tapCount = 1;
|
||||
setTimeout(() => {
|
||||
tapCount = 0;
|
||||
}, 3000);
|
||||
ToastEvent.show('Press back again to exit editor', 'success');
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
editing.currentlyEditing = true;
|
||||
|
||||
let handleBack;
|
||||
if (!noMenu && DDS.isTab) {
|
||||
handleBack = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
|
||||
editing.isFullscreen = false;
|
||||
return true;
|
||||
});
|
||||
} else if (!DDS.isTab) {
|
||||
handleBack = BackHandler.addEventListener(
|
||||
'hardwareBackPress',
|
||||
_onHardwareBackPress,
|
||||
);
|
||||
} else {
|
||||
if (handleBack) {
|
||||
handleBack.remove();
|
||||
handleBack = null;
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
editing.currentlyEditing = false;
|
||||
if (handleBack) {
|
||||
handleBack.remove();
|
||||
handleBack = null;
|
||||
}
|
||||
title = null;
|
||||
content = null;
|
||||
id = null;
|
||||
timer = null;
|
||||
note = {};
|
||||
};
|
||||
}, [noMenu]);
|
||||
|
||||
useEffect(() => {
|
||||
noMenu ? null : SideMenuEvent.disable();
|
||||
|
||||
return () => {
|
||||
if (noMenu) return;
|
||||
DDS.isTab ? SideMenuEvent.open() : null;
|
||||
SideMenuEvent.enable();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: DDS.isTab ? 'transparent' : colors.bg,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
style={{
|
||||
@@ -359,7 +409,9 @@ const Editor = ({navigation, noMenu}) => {
|
||||
if (DDS.isTab) {
|
||||
simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
|
||||
} else {
|
||||
await closeEditor();
|
||||
exitEditorAnimation();
|
||||
await clearEditor();
|
||||
ToastEvent.show('Note Saved!', 'success');
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
@@ -469,7 +521,7 @@ const Editor = ({navigation, noMenu}) => {
|
||||
</Text>
|
||||
</View>
|
||||
<WebView
|
||||
ref={ref => (EditorWebView = ref)}
|
||||
ref={EditorWebView}
|
||||
onError={error => console.log(error)}
|
||||
onLoad={onWebViewLoad}
|
||||
javaScriptEnabled={true}
|
||||
@@ -511,149 +563,7 @@ const Editor = ({navigation, noMenu}) => {
|
||||
onMessage={_onMessage}
|
||||
/>
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
};
|
||||
|
||||
const closeFullscreen = () => {
|
||||
setFullscreen(false);
|
||||
};
|
||||
|
||||
// EFFECTS
|
||||
|
||||
useEffect(() => {
|
||||
eSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
|
||||
|
||||
return () => {
|
||||
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullscreen);
|
||||
};
|
||||
});
|
||||
|
||||
const closeEditor = async () => {
|
||||
await saveNote();
|
||||
title = null;
|
||||
content = null;
|
||||
note = null;
|
||||
id = null;
|
||||
dateEdited = null;
|
||||
tapCount = 0;
|
||||
NavigationService.goBack();
|
||||
ToastEvent.show('Note Saved!', 'success');
|
||||
};
|
||||
|
||||
const _onHardwareBackPress = async () => {
|
||||
if (tapCount > 0) {
|
||||
await closeEditor();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
tapCount = 1;
|
||||
setTimeout(() => {
|
||||
tapCount = 0;
|
||||
}, 3000);
|
||||
ToastEvent.show('Press back again to exit editor', 'success');
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
editing.currentlyEditing = true;
|
||||
|
||||
let handleBack;
|
||||
if (!noMenu && DDS.isTab) {
|
||||
handleBack = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
simpleDialogEvent(TEMPLATE_EXIT_FULLSCREEN());
|
||||
editing.isFullscreen = false;
|
||||
return true;
|
||||
});
|
||||
} else if (!DDS.isTab) {
|
||||
handleBack = BackHandler.addEventListener(
|
||||
'hardwareBackPress',
|
||||
_onHardwareBackPress,
|
||||
);
|
||||
} else {
|
||||
if (handleBack) {
|
||||
handleBack.remove();
|
||||
handleBack = null;
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
editing.currentlyEditing = false;
|
||||
if (handleBack) {
|
||||
handleBack.remove();
|
||||
handleBack = null;
|
||||
}
|
||||
title = null;
|
||||
content = null;
|
||||
id = null;
|
||||
timer = null;
|
||||
note = {};
|
||||
};
|
||||
}, [noMenu]);
|
||||
|
||||
useEffect(() => {
|
||||
noMenu ? null : SideMenuEvent.disable();
|
||||
|
||||
return () => {
|
||||
if (noMenu) return;
|
||||
DDS.isTab ? SideMenuEvent.open() : null;
|
||||
SideMenuEvent.enable();
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
EditorWebView.reload();
|
||||
}, [colors]);
|
||||
|
||||
return (
|
||||
<AnimatedSafeAreaView
|
||||
transition={['backgroundColor', 'width']}
|
||||
duration={300}
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: DDS.isTab ? 'transparent' : colors.bg,
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
}}>
|
||||
<Animatable.View
|
||||
transition="opacity"
|
||||
useNativeDriver={true}
|
||||
duration={150}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
zIndex: 1,
|
||||
backgroundColor: colors.bg,
|
||||
opacity: loading ? 1 : 0,
|
||||
position: 'absolute',
|
||||
}}>
|
||||
<ActivityIndicator color={colors.accent} size={SIZE.xxxl} />
|
||||
|
||||
<Text
|
||||
style={{
|
||||
color: colors.accent,
|
||||
fontFamily: WEIGHT.regular,
|
||||
fontSize: SIZE.md,
|
||||
marginTop: 10,
|
||||
}}>
|
||||
Write with confidence.
|
||||
</Text>
|
||||
</Animatable.View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
zIndex: 2,
|
||||
opacity: loading ? 0 : 1,
|
||||
}}>
|
||||
{_renderEditor()}
|
||||
</View>
|
||||
</AnimatedSafeAreaView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user