improve editor performance

This commit is contained in:
ammarahm-ed
2020-03-03 09:49:54 +05:00
parent 231cde44e1
commit 55a6b11e20
6 changed files with 198 additions and 236 deletions

View File

@@ -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>
</>

View File

@@ -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={{

View File

@@ -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',

View File

@@ -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}],

View File

@@ -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,

View File

@@ -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>
);
};