This commit is contained in:
ammarahm-ed
2020-11-23 11:30:55 +05:00
parent a497c4cdf9
commit 55290c563e
3 changed files with 365 additions and 88 deletions

View File

@@ -1,16 +1,11 @@
import * as NetInfo from '@react-native-community/netinfo'; import * as NetInfo from '@react-native-community/netinfo';
import * as Sentry from '@sentry/react-native';
import {EV} from 'notes-core/common'; import {EV} from 'notes-core/common';
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {Appearance, AppState, Platform, StatusBar} from 'react-native'; import {Appearance, AppState, Platform, StatusBar} from 'react-native';
import {enabled} from 'react-native-privacy-snapshot'; import {enabled} from 'react-native-privacy-snapshot';
import {SafeAreaProvider} from 'react-native-safe-area-context'; import {SafeAreaProvider} from 'react-native-safe-area-context';
import SplashScreen from 'react-native-splash-screen';
import {RootView} from './RootView';
import {useTracked} from './src/provider'; import {useTracked} from './src/provider';
import {Actions} from './src/provider/Actions'; import {Actions} from './src/provider/Actions';
import Backup from './src/services/Backup';
import {DDS} from './src/services/DeviceDetection';
import { import {
eSendEvent, eSendEvent,
eSubscribeEvent, eSubscribeEvent,
@@ -19,27 +14,21 @@ import {
} from './src/services/EventManager'; } from './src/services/EventManager';
import IntentService from './src/services/IntentService'; import IntentService from './src/services/IntentService';
import {setLoginMessage} from './src/services/Message'; import {setLoginMessage} from './src/services/Message';
import SettingsService from './src/services/SettingsService'; import Navigation from './src/services/Navigation';
import {editing} from './src/utils';
import {COLOR_SCHEME} from './src/utils/Colors'; import {COLOR_SCHEME} from './src/utils/Colors';
import {db} from './src/utils/DB'; import {db} from './src/utils/DB';
import { import {eDispatchAction, eOnLoadNote, eStartSyncer} from './src/utils/Events';
eDispatchAction,
eOnLoadNote,
eResetApp,
eStartSyncer,
} from './src/utils/Events';
import {MMKV} from './src/utils/mmkv'; import {MMKV} from './src/utils/mmkv';
import {tabBarRef} from './src/utils/Refs'; import {tabBarRef} from './src/utils/Refs';
import {sleep} from './src/utils/TimeUtils'; import {getNote, setIntentNote} from './src/views/Editor/Functions';
import {getNote} from './src/views/Editor/Functions';
Sentry.init({ let AppRootView = require('./initializer.intent').IntentView;
dsn: let SettingsService = null;
'https://317a5c31caf64d1e9b27abf15eb1a554@o477952.ingest.sentry.io/5519681', let Sentry = null;
});
let note = null;
const onAppStateChanged = async (state) => { const onAppStateChanged = async (state) => {
console.log('app state', state);
if (state === 'active') { if (state === 'active') {
StatusBar.setBarStyle( StatusBar.setBarStyle(
COLOR_SCHEME.night ? 'light-content' : 'dark-content', COLOR_SCHEME.night ? 'light-content' : 'dark-content',
@@ -52,7 +41,18 @@ const onAppStateChanged = async (state) => {
if (SettingsService.get().privacyScreen) { if (SettingsService.get().privacyScreen) {
enabled(false); enabled(false);
} }
MMKV.removeItem('appState');
} else { } else {
if (editing.currentlyEditing) {
MMKV.setItem(
'appState',
JSON.stringify({
editing: editing.currentlyEditing,
note: getNote(),
}),
);
}
if (SettingsService.get().privacyScreen) { if (SettingsService.get().privacyScreen) {
enabled(true); enabled(true);
} }
@@ -75,35 +75,22 @@ const onNetworkStateChanged = (netInfo) => {
const App = () => { const App = () => {
const [, dispatch] = useTracked(), const [, dispatch] = useTracked(),
[init, setInit] = useState(false); [init, setInit] = useState(false),
[intent, setIntent] = useState(false);
const syncChanges = async () => { const syncChanges = async () => {
dispatch({type: Actions.ALL}); dispatch({type: Actions.ALL});
}, };
resetApp = async () => { const startSyncer = async () => {
note = getNote(); try {
setInit(false); let user = await db.user.get();
await SettingsService.init(); if (user) {
setInit(true); EV.subscribe('db:refresh', syncChanges);
await sleep(300);
if (note && note.id) {
eSendEvent(eOnLoadNote, note);
if (!DDS.isLargeTablet()) {
tabBarRef.current?.goToPage(1);
}
note = null;
} }
}, } catch (e) {
startSyncer = async () => { console.log(e);
try { }
let user = await db.user.get(); };
if (user) {
EV.subscribe('db:refresh', syncChanges);
}
} catch (e) {
console.log(e);
}
};
const onSystemThemeChanged = async () => { const onSystemThemeChanged = async () => {
await SettingsService.setTheme(); await SettingsService.setTheme();
@@ -111,70 +98,72 @@ const App = () => {
useEffect(() => { useEffect(() => {
eSubscribeEvent(eStartSyncer, startSyncer); eSubscribeEvent(eStartSyncer, startSyncer);
eSubscribeEvent(eResetApp, resetApp);
eSubscribeEvent(eDispatchAction, (type) => { eSubscribeEvent(eDispatchAction, (type) => {
dispatch(type); dispatch(type);
}); });
AppState.addEventListener('change', onAppStateChanged); AppState.addEventListener('change', onAppStateChanged);
eSubscribeEvent('nointent', loadMainApp);
Appearance.addChangeListener(onSystemThemeChanged); Appearance.addChangeListener(onSystemThemeChanged);
let unsub = NetInfo.addEventListener(onNetworkStateChanged); let unsub = NetInfo.addEventListener(onNetworkStateChanged);
return () => { return () => {
EV.unsubscribe('db:refresh', syncChanges); EV.unsubscribe('db:refresh', syncChanges);
eUnSubscribeEvent(eStartSyncer, startSyncer); eUnSubscribeEvent(eStartSyncer, startSyncer);
eUnSubscribeEvent(eResetApp, resetApp);
eUnSubscribeEvent(eDispatchAction, (type) => { eUnSubscribeEvent(eDispatchAction, (type) => {
dispatch(type); dispatch(type);
}); });
eUnSubscribeEvent('nointent', loadMainApp);
AppState.removeEventListener('change', onAppStateChanged); AppState.removeEventListener('change', onAppStateChanged);
Appearance.removeChangeListener(onSystemThemeChanged); Appearance.removeChangeListener(onSystemThemeChanged);
unsub(); unsub();
}; };
}, []); }, []);
const loadMainApp = () => {
setIntent(false);
AppRootView = require('./initializer.root').RootView;
setInit(true);
backupData().then((r) => r);
Sentry = require('@sentry/react-native');
Sentry.init({
dsn:
'https://317a5c31caf64d1e9b27abf15eb1a554@o477952.ingest.sentry.io/5519681',
});
};
const getUser = async () => { const getUser = async () => {
let user = await db.user.get(); try {
if (user) { let user = await db.user.get();
dispatch({type: Actions.USER, user: user}); if (user) {
dispatch({type: Actions.SYNCING, syncing: true}); dispatch({type: Actions.USER, user: user});
await db.sync(); dispatch({type: Actions.SYNCING, syncing: true});
dispatch({type: Actions.SYNCING, syncing: false}); await db.sync();
dispatch({type: Actions.ALL}); dispatch({type: Actions.SYNCING, syncing: false});
await startSyncer(); dispatch({type: Actions.ALL});
} else { await startSyncer();
setLoginMessage(dispatch); } else {
setLoginMessage(dispatch);
}
} catch (e) {
console.log(e);
} }
}; };
useEffect(() => { useEffect(() => {
SettingsService.init().then((r) => r); SettingsService = require('./src/services/SettingsService').default;
let error = null; SettingsService.init().finally(() => {
(async () => { db.init().finally(runAfterInit);
try { });
await db.init();
} catch (e) {
error = e;
console.log(e, 'ERROR DB');
} finally {
dispatch({type: Actions.ALL});
getUser().catch((e) => console.log);
backupData().then((r) => r);
}
setInit(true);
setTimeout(() => {
if (error) {
console.log(error);
ToastEvent.show('Error initializing database.');
}
IntentService.check();
SplashScreen.hide();
}, 100);
})();
}, []); }, []);
const runAfterInit = () => {
setIntent(true);
dispatch({type: Actions.ALL});
getUser().catch((e) => console.log);
};
async function backupData() { async function backupData() {
await sleep(1000); let settings = SettingsService.get();
let settings = await MMKV.getStringAsync('settings'); let Backup = require('./src/services/Backup').default;
settings = JSON.parse(settings);
if (await Backup.checkBackupRequired(settings.reminder)) { if (await Backup.checkBackupRequired(settings.reminder)) {
try { try {
await Backup.run(); await Backup.run();
@@ -185,11 +174,10 @@ const App = () => {
} }
return ( return (
<> <SafeAreaProvider>
<SafeAreaProvider> {intent && <AppRootView />}
<>{!init ? <></> : <RootView />}</> {init && !intent && <AppRootView />}
</SafeAreaProvider> </SafeAreaProvider>
</>
); );
}; };

View File

@@ -0,0 +1,20 @@
import React from 'react';
import { DialogManager } from './src/components/DialogManager';
import { DummyText } from './src/components/DummyText';
import { Toast } from './src/components/Toast';
import { useTracked } from './src/provider';
import { EditorWrapper } from './src/views/Editor/EditorWrapper';
export const IntentView = () => {
const [state] = useTracked();
const {colors} = state;
return (
<>
<EditorWrapper dimensions={{width: '100%', height: '100%'}} />
<Toast />
<DummyText />
<DialogManager colors={colors} />
</>
);
};

View File

@@ -0,0 +1,269 @@
import React, {useEffect, useState} from 'react';
import {Dimensions, View} from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import SplashScreen from 'react-native-splash-screen';
import ContextMenu from './src/components/ContextMenu';
import {DialogManager} from './src/components/DialogManager';
import {DummyText} from './src/components/DummyText';
import {Menu} from './src/components/Menu';
import {Toast} from './src/components/Toast';
import {NavigationStack} from './src/navigation/Drawer';
import {NavigatorStack} from './src/navigation/NavigatorStack';
import {useTracked} from './src/provider';
import {Actions} from './src/provider/Actions';
import {DDS} from './src/services/DeviceDetection';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from './src/services/EventManager';
import {editing, setWidthHeight} from './src/utils';
import {
eCloseFullscreenEditor,
eCloseSideMenu,
eOnLoadNote,
eOpenFullscreenEditor,
eOpenSideMenu,
} from './src/utils/Events';
import {editorRef, tabBarRef} from './src/utils/Refs';
import {sleep} from './src/utils/TimeUtils';
import {EditorWrapper} from './src/views/Editor/EditorWrapper';
import {getIntent, getNote, post} from './src/views/Editor/Functions';
let {width, height} = Dimensions.get('window');
let movedAway = true;
let layoutTimer = null;
const onChangeTab = async (obj) => {
if (obj.i === 1) {
eSendEvent(eCloseSideMenu);
if (getIntent()) return;
movedAway = false;
if (!editing.currentlyEditing || !getNote()) {
eSendEvent(eOnLoadNote, {type: 'new'});
editing.currentlyEditing = true;
}
} else {
if (obj.from === 1) {
movedAway = true;
post('blur');
}
eSendEvent(eOpenSideMenu);
}
};
export const RootView = () => {
const [state] = useTracked();
const {colors} = state;
return (
<>
<NavigationStack component={AppStack} />
<Toast />
<ContextMenu />
<DummyText />
<DialogManager colors={colors} />
</>
);
};
const AppStack = React.memo(
() => {
const [state, dispatch] = useTracked();
const {colors} = state;
const [mode, setMode] = useState(null);
const [dimensions, setDimensions] = useState({width, height});
const showFullScreenEditor = () => {
dispatch({type: Actions.FULLSCREEN, state: true});
editorRef.current?.setNativeProps({
style: {
position: 'absolute',
width: dimensions.width,
zIndex: 999,
paddingHorizontal: dimensions.width * 0.15,
backgroundColor: colors.bg,
},
});
};
const closeFullScreenEditor = () => {
dispatch({type: Actions.FULLSCREEN, state: false});
editorRef.current?.setNativeProps({
style: {
position: 'relative',
width: dimensions.width * 0.55,
zIndex: null,
paddingHorizontal: 0,
},
});
};
useEffect(() => {
eSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
eSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
return () => {
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
};
}, []);
const _onLayout = async (event) => {
if (layoutTimer) {
clearTimeout(layoutTimer);
layoutTimer = null;
}
let size = event?.nativeEvent?.layout;
if (!size || (size.width === dimensions.width && mode !== null)) {
return;
}
layoutTimer = setTimeout(async () => {
checkDeviceType(size);
}, 500);
};
function checkDeviceType(size) {
setDimensions({
width: size.width,
height: size.height,
});
setWidthHeight(size);
DDS.setSize(size);
DDS.checkSmallTab(size.width > size.height ? 'LANDSCAPE' : 'PORTRAIT');
if (DDS.isLargeTablet()) {
setDeviceMode('tablet', size);
} else if (DDS.isSmallTab) {
setDeviceMode('smallTablet', size);
} else {
setDeviceMode('mobile', size);
}
}
function setDeviceMode(current, size) {
eSendEvent(current !== 'mobile' ? eCloseSideMenu : eOpenSideMenu);
setMode(current);
dispatch({type: Actions.DEVICE_MODE, state: current});
dispatch({type: Actions.FULLSCREEN, state: false});
editorRef.current?.setNativeProps({
style: {
position: 'relative',
width: current === 'tablet' ? size.width * 0.55 : size.width,
zIndex: null,
paddingHorizontal: 0,
},
});
if (!movedAway && current !== 'tablet') {
tabBarRef.current?.goToPage(1);
}
sleep(50).then(() => SplashScreen.hide());
}
const _responder = (e) => {
const swiperLeftAreaLocation = 60;
const swiperRightAreaLocation = dimensions.width - 100;
let pageX = e.nativeEvent.pageX;
if (pageX <= swiperLeftAreaLocation || pageX >= swiperRightAreaLocation) {
tabBarRef.current?.setScrollEnabled(true);
} else {
tabBarRef.current?.setScrollEnabled(false);
}
return false;
};
return (
<View
onLayout={_onLayout}
style={{
width: '100%',
height: '100%',
backgroundColor: colors.bg,
}}
onStartShouldSetResponder={_responder}>
{mode && (
<ScrollableTabView
ref={tabBarRef}
style={{
zIndex: 1,
}}
initialPage={0}
prerenderingSiblingsNumber={Infinity}
onChangeTab={onChangeTab}
renderTabBar={() => <></>}>
{mode !== 'tablet' && (
<View
style={{
width: dimensions.width,
height: '100%',
borderRightColor: colors.nav,
borderRightWidth: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
}}>
{mode === 'smallTablet' && (
<View
style={{
height: '100%',
width: dimensions.width * 0.35,
}}>
<Menu />
</View>
)}
<View
style={{
height: '100%',
width:
mode === 'mobile'
? dimensions.width
: dimensions.width * 0.65,
}}>
<NavigatorStack />
</View>
</View>
)}
<View
style={{
width: '100%',
height: '100%',
flexDirection: 'row',
backgroundColor: colors.bg,
}}>
{mode === 'tablet' && (
<View
style={{
width: dimensions.width * 0.45,
height: '100%',
borderRightColor: colors.nav,
borderRightWidth: 1,
flexDirection: 'row',
alignItems: 'center',
}}>
<View
style={{
height: '100%',
width: dimensions.width * 0.15,
}}>
<Menu />
</View>
<View
style={{
height: '100%',
width: dimensions.width * 0.3,
}}>
<NavigatorStack />
</View>
</View>
)}
<EditorWrapper dimensions={dimensions} />
</View>
</ScrollableTabView>
)}
</View>
);
},
() => true,
);