mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-21 22:19:41 +01:00
bug fixes in new state management and navigation
This commit is contained in:
@@ -6,10 +6,12 @@ import RNExitApp from 'react-native-exit-app';
|
|||||||
import * as RNIap from 'react-native-iap';
|
import * as RNIap from 'react-native-iap';
|
||||||
import { enabled } from 'react-native-privacy-snapshot';
|
import { enabled } from 'react-native-privacy-snapshot';
|
||||||
import SplashScreen from 'react-native-splash-screen';
|
import SplashScreen from 'react-native-splash-screen';
|
||||||
import { updateEvent } from './src/components/DialogManager/recievers';
|
import {
|
||||||
import { useTracked } from './src/provider';
|
clearAllStores,
|
||||||
import { Actions } from './src/provider/Actions';
|
initialize,
|
||||||
import { clearAllStores, initialize, useNoteStore, useUserStore } from './src/provider/stores';
|
useNoteStore,
|
||||||
|
useUserStore
|
||||||
|
} from './src/provider/stores';
|
||||||
import Backup from './src/services/Backup';
|
import Backup from './src/services/Backup';
|
||||||
import BiometricService from './src/services/BiometricService';
|
import BiometricService from './src/services/BiometricService';
|
||||||
import {
|
import {
|
||||||
@@ -103,17 +105,15 @@ async function reconnectSSE(connection) {
|
|||||||
|
|
||||||
let prevState = null;
|
let prevState = null;
|
||||||
let showingDialog = false;
|
let showingDialog = false;
|
||||||
|
|
||||||
let removeInternetStateListener;
|
let removeInternetStateListener;
|
||||||
|
|
||||||
export const AppRootEvents = React.memo(
|
export const AppRootEvents = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const [state, dispatch] = useTracked();
|
|
||||||
const loading = useNoteStore(state => state.loading);
|
const loading = useNoteStore(state => state.loading);
|
||||||
const setLastSynced = useUserStore(state => state.setLastSynced);
|
const setLastSynced = useUserStore(state => state.setLastSynced);
|
||||||
const setUser = useUserStore(state => state.setUser);
|
const setUser = useUserStore(state => state.setUser);
|
||||||
const setSyncing = useUserStore(state => state.setSyncing);
|
const setSyncing = useUserStore(state => state.setSyncing);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Appearance.addChangeListener(SettingsService.setTheme);
|
Appearance.addChangeListener(SettingsService.setTheme);
|
||||||
Linking.addEventListener('url', onUrlRecieved);
|
Linking.addEventListener('url', onUrlRecieved);
|
||||||
@@ -148,9 +148,6 @@ export const AppRootEvents = React.memo(
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const onSessionExpired = async () => {
|
const onSessionExpired = async () => {
|
||||||
await Storage.write('loginSessionHasExpired', 'expired');
|
await Storage.write('loginSessionHasExpired', 'expired');
|
||||||
eSendEvent(eOpenLoginDialog, 4);
|
eSendEvent(eOpenLoginDialog, 4);
|
||||||
@@ -203,7 +200,7 @@ export const AppRootEvents = React.memo(
|
|||||||
|
|
||||||
const onSyncComplete = async () => {
|
const onSyncComplete = async () => {
|
||||||
initialize();
|
initialize();
|
||||||
setLastSynced(await db.lastSynced())
|
setLastSynced(await db.lastSynced());
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUrlRecieved = async res => {
|
const onUrlRecieved = async res => {
|
||||||
@@ -233,7 +230,7 @@ export const AppRootEvents = React.memo(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (user?.isEmailConfirmed) {
|
if (user?.isEmailConfirmed) {
|
||||||
clearMessage(dispatch);
|
clearMessage();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -281,13 +278,13 @@ export const AppRootEvents = React.memo(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (res !== true) throw new Error(res);
|
if (res !== true) throw new Error(res);
|
||||||
setLastSynced(await db.lastSynced())
|
setLastSynced(await db.lastSynced());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setSyncing(false);
|
setSyncing(false);
|
||||||
ToastEvent.show({
|
ToastEvent.show({
|
||||||
heading: 'Sync failed',
|
heading: 'Sync failed',
|
||||||
message: e.message,
|
message: e.message,
|
||||||
context: "global",
|
context: 'global',
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setSyncing(false);
|
setSyncing(false);
|
||||||
@@ -330,7 +327,7 @@ export const AppRootEvents = React.memo(
|
|||||||
const setCurrentUser = async login => {
|
const setCurrentUser = async login => {
|
||||||
try {
|
try {
|
||||||
if ((await MMKV.getItem('loginSessionHasExpired')) === 'expired')
|
if ((await MMKV.getItem('loginSessionHasExpired')) === 'expired')
|
||||||
return;
|
return;
|
||||||
let user = await db.user.getUser();
|
let user = await db.user.getUser();
|
||||||
if (user) {
|
if (user) {
|
||||||
setUser(user);
|
setUser(user);
|
||||||
@@ -479,7 +476,7 @@ export const AppRootEvents = React.memo(
|
|||||||
try {
|
try {
|
||||||
let user = await db.user.fetchUser();
|
let user = await db.user.fetchUser();
|
||||||
if (user.isEmailConfirmed) {
|
if (user.isEmailConfirmed) {
|
||||||
onEmailVerified(dispatch);
|
onEmailVerified();
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|||||||
28
apps/mobile/android/.project
Normal file
28
apps/mobile/android/.project
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>android</name>
|
||||||
|
<comment>Project android created by Buildship.</comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||||
|
</natures>
|
||||||
|
<filteredResources>
|
||||||
|
<filter>
|
||||||
|
<id>1622976477541</id>
|
||||||
|
<name></name>
|
||||||
|
<type>30</type>
|
||||||
|
<matcher>
|
||||||
|
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||||
|
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||||
|
</matcher>
|
||||||
|
</filter>
|
||||||
|
</filteredResources>
|
||||||
|
</projectDescription>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
arguments=
|
||||||
|
auto.sync=false
|
||||||
|
build.scans.enabled=false
|
||||||
|
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
|
||||||
|
connection.project.dir=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
gradle.user.home=
|
||||||
|
java.home=/usr/lib/jvm/java-15-openjdk
|
||||||
|
jvm.arguments=
|
||||||
|
offline.mode=false
|
||||||
|
override.workspace.settings=true
|
||||||
|
show.console.view=true
|
||||||
|
show.executions.view=true
|
||||||
@@ -1,39 +1,40 @@
|
|||||||
import {
|
import {
|
||||||
activateKeepAwake,
|
activateKeepAwake,
|
||||||
deactivateKeepAwake
|
deactivateKeepAwake,
|
||||||
} from '@sayem314/react-native-keep-awake';
|
} from '@sayem314/react-native-keep-awake';
|
||||||
import React, { Component, createRef, useEffect, useRef, useState } from 'react';
|
import React, {useEffect, useRef, useState} from 'react';
|
||||||
import { Dimensions, FlatList, TextInput, View } from 'react-native';
|
import {Dimensions, View} from 'react-native';
|
||||||
import Animated, { useValue } from 'react-native-reanimated';
|
import Animated, {useValue} from 'react-native-reanimated';
|
||||||
import { notesnook } from './e2e/test.ids';
|
import {notesnook} from './e2e/test.ids';
|
||||||
import ContextMenu from './src/components/ContextMenu';
|
import ContextMenu from './src/components/ContextMenu';
|
||||||
import { DialogManager } from './src/components/DialogManager';
|
import CustomTabs from './src/components/CustomTabs';
|
||||||
import { DummyText } from './src/components/DummyText';
|
import {DialogManager} from './src/components/DialogManager';
|
||||||
import { Menu } from './src/components/Menu';
|
import {DummyText} from './src/components/DummyText';
|
||||||
import { Toast } from './src/components/Toast';
|
import {Menu} from './src/components/Menu';
|
||||||
import { NavigatorStack } from './src/navigation/NavigatorStack';
|
import {Toast} from './src/components/Toast';
|
||||||
import { useTracked } from './src/provider';
|
import {NavigatorStack} from './src/navigation/NavigatorStack';
|
||||||
import { useSettingStore } from './src/provider/stores';
|
import {useTracked} from './src/provider';
|
||||||
import { DDS } from './src/services/DeviceDetection';
|
import {useSettingStore} from './src/provider/stores';
|
||||||
|
import {DDS} from './src/services/DeviceDetection';
|
||||||
import {
|
import {
|
||||||
eSendEvent,
|
eSendEvent,
|
||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent
|
eUnSubscribeEvent,
|
||||||
} from './src/services/EventManager';
|
} from './src/services/EventManager';
|
||||||
import { editing, setWidthHeight } from './src/utils';
|
import {editing, setWidthHeight} from './src/utils';
|
||||||
import { updateStatusBarColor } from './src/utils/Colors';
|
import {updateStatusBarColor} from './src/utils/Colors';
|
||||||
import {
|
import {
|
||||||
eClearEditor,
|
eClearEditor,
|
||||||
eCloseFullscreenEditor,
|
eCloseFullscreenEditor,
|
||||||
eCloseSideMenu,
|
eCloseSideMenu,
|
||||||
eOnLoadNote,
|
eOnLoadNote,
|
||||||
eOpenFullscreenEditor,
|
eOpenFullscreenEditor,
|
||||||
eOpenSideMenu
|
eOpenSideMenu,
|
||||||
} from './src/utils/Events';
|
} from './src/utils/Events';
|
||||||
import { editorRef, tabBarRef } from './src/utils/Refs';
|
import {editorRef, tabBarRef} from './src/utils/Refs';
|
||||||
import { sleep } from './src/utils/TimeUtils';
|
import {sleep} from './src/utils/TimeUtils';
|
||||||
import { EditorWrapper } from './src/views/Editor/EditorWrapper';
|
import {EditorWrapper} from './src/views/Editor/EditorWrapper';
|
||||||
import { EditorWebView, getNote } from './src/views/Editor/Functions';
|
import {EditorWebView, getNote} from './src/views/Editor/Functions';
|
||||||
import tiny from './src/views/Editor/tiny/tiny';
|
import tiny from './src/views/Editor/tiny/tiny';
|
||||||
let {width, height} = Dimensions.get('window');
|
let {width, height} = Dimensions.get('window');
|
||||||
let layoutTimer = null;
|
let layoutTimer = null;
|
||||||
@@ -53,7 +54,6 @@ const onChangeTab = async obj => {
|
|||||||
!editing.isRestoringState &&
|
!editing.isRestoringState &&
|
||||||
(!editing.currentlyEditing || !getNote())
|
(!editing.currentlyEditing || !getNote())
|
||||||
) {
|
) {
|
||||||
console.log('new note');
|
|
||||||
eSendEvent(eOnLoadNote, {type: 'new'});
|
eSendEvent(eOnLoadNote, {type: 'new'});
|
||||||
editing.currentlyEditing = true;
|
editing.currentlyEditing = true;
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ export const RootView = React.memo(
|
|||||||
() => {
|
() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppStack />
|
<NativeStack />
|
||||||
<Toast />
|
<Toast />
|
||||||
<ContextMenu />
|
<ContextMenu />
|
||||||
<DummyText />
|
<DummyText />
|
||||||
@@ -93,64 +93,15 @@ export const RootView = React.memo(
|
|||||||
() => true,
|
() => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
let updatedDimensions = {
|
const NativeStack = React.memo(
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
};
|
|
||||||
|
|
||||||
let currentScroll = 0;
|
|
||||||
let startLocation = 0;
|
|
||||||
let startLocationX = 0;
|
|
||||||
const _responder = e => {
|
|
||||||
startLocation = e.nativeEvent.pageY;
|
|
||||||
startLocationX = e.nativeEvent.pageX;
|
|
||||||
_handleTouch();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
const _moveResponder = e => {
|
|
||||||
_handleTouch();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
let touchEndTimer = null;
|
|
||||||
|
|
||||||
const _handleTouch = () => {
|
|
||||||
{
|
|
||||||
let heightCheck = !editing.tooltip
|
|
||||||
? updatedDimensions.height - 70
|
|
||||||
: updatedDimensions.height - 140;
|
|
||||||
if (
|
|
||||||
(currentTab === 1 && startLocation > heightCheck) ||
|
|
||||||
(currentTab === 1 && startLocationX > 50) ||
|
|
||||||
(currentTab === 0 && startLocationX < 150)
|
|
||||||
) {
|
|
||||||
if (currentScroll === 0 || currentScroll === 1) {
|
|
||||||
tabBarRef.current?.setScrollEnabled(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tabBarRef.current?.setScrollEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const _onTouchEnd = e => {
|
|
||||||
startLocation = 0;
|
|
||||||
clearTimeout(touchEndTimer);
|
|
||||||
touchEndTimer = null;
|
|
||||||
touchEndTimer = setTimeout(() => {
|
|
||||||
tabBarRef.current?.setScrollEnabled(true);
|
|
||||||
}, 200);
|
|
||||||
};
|
|
||||||
|
|
||||||
const AppStack = React.memo(
|
|
||||||
() => {
|
() => {
|
||||||
const [state, dispatch] = useTracked();
|
const [state] = useTracked();
|
||||||
const {colors} = state;
|
const {colors} = state;
|
||||||
|
|
||||||
const deviceMode = useSettingStore(state => state.deviceMode);
|
const deviceMode = useSettingStore(state => state.deviceMode);
|
||||||
const setFullscreen = useSettingStore(state => state.setFullscreen);
|
const setFullscreen = useSettingStore(state => state.setFullscreen);
|
||||||
const setDeviceModeState = useSettingStore(state => state.setDeviceMode);
|
const setDeviceModeState = useSettingStore(state => state.setDeviceMode);
|
||||||
|
|
||||||
const [dimensions, setDimensions] = useState({width, height});
|
const [dimensions, setDimensions] = useState({width, height});
|
||||||
const animatedOpacity = useValue(0);
|
const animatedOpacity = useValue(0);
|
||||||
const overlayRef = useRef();
|
const overlayRef = useRef();
|
||||||
@@ -202,7 +153,7 @@ const AppStack = React.memo(
|
|||||||
if (!size || (size.width === dimensions.width && deviceMode !== null)) {
|
if (!size || (size.width === dimensions.width && deviceMode !== null)) {
|
||||||
DDS.setSize(size);
|
DDS.setSize(size);
|
||||||
//console.log(deviceMode, 'MODE__');
|
//console.log(deviceMode, 'MODE__');
|
||||||
setDeviceModeState(deviceMode)
|
setDeviceModeState(deviceMode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,16 +174,25 @@ const AppStack = React.memo(
|
|||||||
if (DDS.isLargeTablet()) {
|
if (DDS.isLargeTablet()) {
|
||||||
//console.log('setting large tab');
|
//console.log('setting large tab');
|
||||||
setDeviceMode('tablet', size);
|
setDeviceMode('tablet', size);
|
||||||
tabBarRef.current?.goToIndex(0)
|
tabBarRef.current?.goToIndex(0);
|
||||||
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
||||||
} else if (DDS.isSmallTab) {
|
} else if (DDS.isSmallTab) {
|
||||||
//console.log('setting small tab');
|
//console.log('setting small tab');
|
||||||
setDeviceMode('smallTablet', size);
|
setDeviceMode('smallTablet', size);
|
||||||
tabBarRef.current?.goToIndex(0)
|
if (!editing.movedAway) {
|
||||||
|
tabBarRef.current?.goToIndex(2);
|
||||||
|
} else {
|
||||||
|
tabBarRef.current?.goToIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
||||||
} else {
|
} else {
|
||||||
setDeviceMode('mobile', size);
|
setDeviceMode('mobile', size);
|
||||||
tabBarRef.current?.goToIndex(1)
|
if (!editing.movedAway) {
|
||||||
|
tabBarRef.current?.goToIndex(2);
|
||||||
|
} else {
|
||||||
|
tabBarRef.current?.goToIndex(1);
|
||||||
|
}
|
||||||
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
sleep(300).then(r => eSendEvent(eOpenSideMenu));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,9 +210,6 @@ const AppStack = React.memo(
|
|||||||
paddingHorizontal: 0,
|
paddingHorizontal: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!editing.movedAway && current !== 'tablet') {
|
|
||||||
tabBarRef.current?.goToPage(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onScroll = scrollOffset => {
|
const onScroll = scrollOffset => {
|
||||||
@@ -281,6 +238,24 @@ const AppStack = React.memo(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const offsets = {
|
||||||
|
mobile: {
|
||||||
|
a: dimensions.width * 0.75,
|
||||||
|
b: dimensions.width + dimensions.width * 0.75,
|
||||||
|
c: dimensions.width * 2 + dimensions.width * 0.75,
|
||||||
|
},
|
||||||
|
smallTablet: {
|
||||||
|
a: dimensions.width,
|
||||||
|
b: dimensions.width,
|
||||||
|
c: dimensions.width * 2,
|
||||||
|
},
|
||||||
|
tablet: {
|
||||||
|
a: dimensions.width,
|
||||||
|
b: dimensions.width,
|
||||||
|
c: dimensions.width,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
onLayout={_onLayout}
|
onLayout={_onLayout}
|
||||||
@@ -293,24 +268,14 @@ const AppStack = React.memo(
|
|||||||
{deviceMode && (
|
{deviceMode && (
|
||||||
<CustomTabs
|
<CustomTabs
|
||||||
ref={tabBarRef}
|
ref={tabBarRef}
|
||||||
|
dimensions={dimensions}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
onDrawerStateChange={state => {
|
initialIndex={
|
||||||
//console.log(state);
|
deviceMode === 'smallTablet' || deviceMode === 'tablet' ? 0 : 1
|
||||||
}}
|
}
|
||||||
initialIndex={deviceMode === 'smallTablet' ? 0 : 1}
|
offsets={offsets[deviceMode]}
|
||||||
offsets={{
|
|
||||||
a: deviceMode === 'smallTablet' ? dimensions.width : 300,
|
|
||||||
b:
|
|
||||||
deviceMode === 'smallTablet'
|
|
||||||
? dimensions.width
|
|
||||||
: dimensions.width + 300,
|
|
||||||
c:
|
|
||||||
deviceMode === 'smallTablet'
|
|
||||||
? dimensions.width * 2
|
|
||||||
: dimensions.width * 2 + 300,
|
|
||||||
}}
|
|
||||||
items={[
|
items={[
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -318,7 +283,9 @@ const AppStack = React.memo(
|
|||||||
width:
|
width:
|
||||||
deviceMode === 'smallTablet'
|
deviceMode === 'smallTablet'
|
||||||
? dimensions.width * 0.35
|
? dimensions.width * 0.35
|
||||||
: 300,
|
: deviceMode === 'smallTablet'
|
||||||
|
? dimensions.width * 0.15
|
||||||
|
: dimensions.width * 0.75,
|
||||||
}}>
|
}}>
|
||||||
<Menu />
|
<Menu />
|
||||||
</View>,
|
</View>,
|
||||||
@@ -328,6 +295,8 @@ const AppStack = React.memo(
|
|||||||
width:
|
width:
|
||||||
deviceMode === 'mobile'
|
deviceMode === 'mobile'
|
||||||
? dimensions.width
|
? dimensions.width
|
||||||
|
: deviceMode === 'tablet'
|
||||||
|
? dimensions.width * 0.3
|
||||||
: dimensions.width * 0.65,
|
: dimensions.width * 0.65,
|
||||||
}}>
|
}}>
|
||||||
{deviceMode === 'mobile' && (
|
{deviceMode === 'mobile' && (
|
||||||
@@ -342,7 +311,7 @@ const AppStack = React.memo(
|
|||||||
ref={overlayRef}>
|
ref={overlayRef}>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
onTouchEnd={() => {
|
onTouchEnd={() => {
|
||||||
tabBarRef.current?.goToIndex(1)
|
tabBarRef.current?.goToIndex(1);
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'rgba(0,0,0,0.2)',
|
backgroundColor: 'rgba(0,0,0,0.2)',
|
||||||
@@ -362,279 +331,8 @@ const AppStack = React.memo(
|
|||||||
onChangeTab={onChangeTab}
|
onChangeTab={onChangeTab}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* {deviceMode !== 'tablet' && (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: dimensions.width,
|
|
||||||
height: '100%',
|
|
||||||
borderRightColor: colors.nav,
|
|
||||||
borderRightWidth: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
}}>
|
|
||||||
{deviceMode === 'smallTablet' && (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
height: '100%',
|
|
||||||
width: dimensions.width * 0.35,
|
|
||||||
}}>
|
|
||||||
<Menu />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
height: '100%',
|
|
||||||
width:
|
|
||||||
deviceMode === 'mobile'
|
|
||||||
? dimensions.width
|
|
||||||
: dimensions.width * 0.65,
|
|
||||||
}}>
|
|
||||||
<NavigatorStack />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
flexDirection: 'row',
|
|
||||||
backgroundColor: colors.bg,
|
|
||||||
}}>
|
|
||||||
{deviceMode === '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> */}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
() => true,
|
() => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
class CustomTabs extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.listRef = createRef();
|
|
||||||
this.scrollOffset = props.initialIndex === 0 ? 0 : 300;
|
|
||||||
this.page = 0;
|
|
||||||
this.currentDrawerState = false;
|
|
||||||
this.inputElement = createRef();
|
|
||||||
this.keyboardState = false;
|
|
||||||
this.scrollTimeout = null;
|
|
||||||
this.scrollEnabled = true;
|
|
||||||
this.responderAllowedScroll = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
renderItem = ({item, index}) => this.props.items[index];
|
|
||||||
|
|
||||||
onMoveShouldSetResponder = event => {
|
|
||||||
// console.log(this.responderAllowedScroll,'allowed scrolling')
|
|
||||||
if (this.responderAllowedScroll) return;
|
|
||||||
let x = event.nativeEvent.pageX;
|
|
||||||
let y = event.nativeEvent.pageY;
|
|
||||||
this.hideKeyboardIfVisible();
|
|
||||||
let cOffset = this.scrollOffset.toFixed(0);
|
|
||||||
let pOffset = this.props.offsets.b.toFixed(0);
|
|
||||||
let heightCheck = !editing.tooltip
|
|
||||||
? updatedDimensions.height - 70
|
|
||||||
: updatedDimensions.height - 140;
|
|
||||||
|
|
||||||
if (cOffset > pOffset - 50) {
|
|
||||||
if (x > 50 || y > heightCheck) {
|
|
||||||
this.responderAllowedScroll = false;
|
|
||||||
this.setScrollEnabled(false);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.responderAllowedScroll = true;
|
|
||||||
this.setScrollEnabled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.responderAllowedScroll = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
openDrawer = () => {
|
|
||||||
console.log('open');
|
|
||||||
if (this.page === 0) {
|
|
||||||
this.goToIndex(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
closeDrawer = () => {
|
|
||||||
console.log('close');
|
|
||||||
if (this.page === 0) {
|
|
||||||
this.goToIndex(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
hideKeyboardIfVisible() {
|
|
||||||
if ((editing.keyboardState || editing.isFocused) && this.scrollOffset < this.props.offsets.b - 50) {
|
|
||||||
editing.isFocused = false;
|
|
||||||
editing.keyboardState = false;
|
|
||||||
this.inputElement.current?.focus();
|
|
||||||
this.inputElement.current?.blur();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
goToIndex(index, animated = true) {
|
|
||||||
// console.log('called me', index);
|
|
||||||
this.listRef.current?.scrollToIndex({
|
|
||||||
animated: animated,
|
|
||||||
index: index,
|
|
||||||
viewOffset: 0,
|
|
||||||
viewPosition: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setScrollEnabled = enabled => {
|
|
||||||
this.scrollEnabled = enabled;
|
|
||||||
this.listRef.current?.getNativeScrollRef().setNativeProps({
|
|
||||||
scrollEnabled: enabled,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onTouchEnd = () => {
|
|
||||||
//console.log('touch has ended');
|
|
||||||
this.responderAllowedScroll = false;
|
|
||||||
this.listRef.current?.getNativeScrollRef().setNativeProps({
|
|
||||||
scrollEnabled: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onScroll = event => {
|
|
||||||
this.scrollOffset = event.nativeEvent.contentOffset.x;
|
|
||||||
if (this.page === 1) {
|
|
||||||
this.hideKeyboardIfVisible();
|
|
||||||
}
|
|
||||||
this.props.onScroll(this.scrollOffset);
|
|
||||||
if (this.scrollTimeout) {
|
|
||||||
clearTimeout(this.scrollTimeout);
|
|
||||||
this.scrollTimeout = null;
|
|
||||||
}
|
|
||||||
this.scrollTimeout = setTimeout(() => {
|
|
||||||
if (
|
|
||||||
this.scrollOffset !== this.props.offsets.a &&
|
|
||||||
this.page === 1 &&
|
|
||||||
!this.scrollEnabled
|
|
||||||
) {
|
|
||||||
this.goToIndex(2, false);
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
};
|
|
||||||
|
|
||||||
goToPage = page => {
|
|
||||||
if (page === 0) {
|
|
||||||
this.scrollOffset = this.props.offsets.a;
|
|
||||||
this.hideKeyboardIfVisible();
|
|
||||||
this.goToIndex(1);
|
|
||||||
} else if (page === 1) {
|
|
||||||
this.goToIndex(2);
|
|
||||||
}
|
|
||||||
if (this.page !== page) {
|
|
||||||
this.props.onChangeTab({i: page, from: this.page});
|
|
||||||
this.page = page;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
keyExtractor = (item, index) => item;
|
|
||||||
|
|
||||||
onScrollEnd = event => {
|
|
||||||
//console.log('scroll end');
|
|
||||||
this.responderAllowedScroll = false;
|
|
||||||
let page = 0;
|
|
||||||
if (this.scrollOffset > this.props.offsets.b - 50) {
|
|
||||||
page = 1;
|
|
||||||
} else {
|
|
||||||
this.hideKeyboardIfVisible();
|
|
||||||
}
|
|
||||||
let drawerState = page === 0 && this.scrollOffset < 10;
|
|
||||||
if (drawerState !== this.currentDrawerState) {
|
|
||||||
this.currentDrawerState = drawerState;
|
|
||||||
this.props.onDrawerStateChange(this.currentDrawerState);
|
|
||||||
}
|
|
||||||
if (this.page !== page) {
|
|
||||||
console.log(page);
|
|
||||||
this.props.onChangeTab({i: page, from: this.page});
|
|
||||||
this.page = page;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
onTouchEnd={this.onTouchEnd}
|
|
||||||
onMoveShouldSetResponderCapture={this.onMoveShouldSetResponder}
|
|
||||||
onStartShouldSetResponderCapture={this.onMoveShouldSetResponder}
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
}}>
|
|
||||||
<TextInput
|
|
||||||
ref={this.inputElement}
|
|
||||||
style={{height: 1, padding: 0, width: 1, position: 'absolute'}}
|
|
||||||
blurOnSubmit={false}
|
|
||||||
/>
|
|
||||||
<FlatList
|
|
||||||
ref={this.listRef}
|
|
||||||
horizontal
|
|
||||||
onMomentumScrollEnd={this.onScrollEnd}
|
|
||||||
onScrollAnimationEnd={this.onScrollEnd}
|
|
||||||
keyExtractor={this.keyExtractor}
|
|
||||||
onScroll={this.onScroll}
|
|
||||||
bounces={false}
|
|
||||||
bouncesZoom={false}
|
|
||||||
initialNumToRender={100}
|
|
||||||
alwaysBounceHorizontal={false}
|
|
||||||
scrollToOverflowEnabled={false}
|
|
||||||
scrollsToTop={false}
|
|
||||||
scrollEventThrottle={1}
|
|
||||||
directionalLockEnabled
|
|
||||||
maintainVisibleContentPosition={true}
|
|
||||||
overScrollMode="never"
|
|
||||||
maxToRenderPerBatch={100}
|
|
||||||
removeClippedSubviews={false}
|
|
||||||
keyboardDismissMode="none"
|
|
||||||
keyboardShouldPersistTaps="always"
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
disableIntervalMomentum={true}
|
|
||||||
snapToOffsets={[
|
|
||||||
this.props.offsets.a,
|
|
||||||
this.props.offsets.b,
|
|
||||||
this.props.offsets.c,
|
|
||||||
]}
|
|
||||||
initialScrollIndex={this.props.initialIndex}
|
|
||||||
data={['drawer', 'navigation', 'editor']}
|
|
||||||
renderItem={this.renderItem}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const ActionSheetWrapper = ({
|
|||||||
<ActionSheet
|
<ActionSheet
|
||||||
ref={fwdRef}
|
ref={fwdRef}
|
||||||
hideUnderlay={true}
|
hideUnderlay={true}
|
||||||
|
|
||||||
containerStyle={style}
|
containerStyle={style}
|
||||||
gestureEnabled={gestureEnabled}
|
gestureEnabled={gestureEnabled}
|
||||||
extraScroll={largeTablet ? 50 : 0}
|
extraScroll={largeTablet ? 50 : 0}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, {createRef} from 'react';
|
import React, {createRef} from 'react';
|
||||||
import {
|
import {
|
||||||
|
ActionSheetIOS,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -20,6 +21,7 @@ import {db} from '../../utils/DB';
|
|||||||
import {ph, pv, SIZE} from '../../utils/SizeUtils';
|
import {ph, pv, SIZE} from '../../utils/SizeUtils';
|
||||||
import {sleep} from '../../utils/TimeUtils';
|
import {sleep} from '../../utils/TimeUtils';
|
||||||
import {ActionIcon} from '../ActionIcon';
|
import {ActionIcon} from '../ActionIcon';
|
||||||
|
import ActionSheetWrapper from '../ActionSheetComponent/ActionSheetWrapper';
|
||||||
import BaseDialog from '../Dialog/base-dialog';
|
import BaseDialog from '../Dialog/base-dialog';
|
||||||
import DialogButtons from '../Dialog/dialog-buttons';
|
import DialogButtons from '../Dialog/dialog-buttons';
|
||||||
import DialogHeader from '../Dialog/dialog-header';
|
import DialogHeader from '../Dialog/dialog-header';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, {createRef} from 'react';
|
import React, {createRef} from 'react';
|
||||||
import {Actions} from '../../provider/Actions';
|
import {Actions} from '../../provider/Actions';
|
||||||
import { useMenuStore } from '../../provider/stores';
|
import {useMenuStore} from '../../provider/stores';
|
||||||
import {
|
import {
|
||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent,
|
eUnSubscribeEvent,
|
||||||
|
|||||||
201
apps/mobile/src/components/CustomTabs/index.js
Normal file
201
apps/mobile/src/components/CustomTabs/index.js
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
import React, { Component, createRef } from 'react';
|
||||||
|
import { FlatList, TextInput, View } from 'react-native';
|
||||||
|
import { editing } from '../../utils';
|
||||||
|
|
||||||
|
|
||||||
|
export default class CustomTabs extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.listRef = createRef();
|
||||||
|
this.scrollOffset = props.initialIndex === 0 ? 0 : this.props.offsets.a;
|
||||||
|
this.page = 0;
|
||||||
|
this.currentDrawerState = false;
|
||||||
|
this.inputElement = createRef();
|
||||||
|
this.keyboardState = false;
|
||||||
|
this.scrollTimeout = null;
|
||||||
|
this.scrollEnabled = true;
|
||||||
|
this.responderAllowedScroll = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
renderItem = ({item, index}) => this.props.items[index];
|
||||||
|
|
||||||
|
onMoveShouldSetResponder = event => {
|
||||||
|
if (this.responderAllowedScroll) return;
|
||||||
|
let x = event.nativeEvent.pageX;
|
||||||
|
let y = event.nativeEvent.pageY;
|
||||||
|
this.hideKeyboardIfVisible();
|
||||||
|
let cOffset = this.scrollOffset.toFixed(0);
|
||||||
|
let pOffset = this.props.offsets.b.toFixed(0);
|
||||||
|
let heightCheck = !editing.tooltip
|
||||||
|
? this.props.dimensions.height - 70
|
||||||
|
: this.props.dimensions.height - 140;
|
||||||
|
|
||||||
|
if (cOffset > pOffset - 50) {
|
||||||
|
if (x > 50 || y > heightCheck) {
|
||||||
|
this.responderAllowedScroll = false;
|
||||||
|
this.setScrollEnabled(false);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.responderAllowedScroll = true;
|
||||||
|
this.setScrollEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.responderAllowedScroll = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
openDrawer = () => {
|
||||||
|
if (this.page === 0) {
|
||||||
|
this.goToIndex(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
closeDrawer = () => {
|
||||||
|
if (this.page === 0) {
|
||||||
|
this.goToIndex(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
hideKeyboardIfVisible() {
|
||||||
|
if ((editing.keyboardState || editing.isFocused) && this.scrollOffset < this.props.offsets.b - 50) {
|
||||||
|
editing.isFocused = false;
|
||||||
|
editing.keyboardState = false;
|
||||||
|
this.inputElement.current?.focus();
|
||||||
|
this.inputElement.current?.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goToIndex(index, animated = true) {
|
||||||
|
this.listRef.current?.scrollToIndex({
|
||||||
|
animated: animated,
|
||||||
|
index: index,
|
||||||
|
viewOffset: 0,
|
||||||
|
viewPosition: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setScrollEnabled = enabled => {
|
||||||
|
this.scrollEnabled = enabled;
|
||||||
|
this.listRef.current?.getNativeScrollRef().setNativeProps({
|
||||||
|
scrollEnabled: enabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onTouchEnd = () => {
|
||||||
|
this.responderAllowedScroll = false;
|
||||||
|
this.setScrollEnabled(true)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
onScroll = event => {
|
||||||
|
this.scrollOffset = event.nativeEvent.contentOffset.x;
|
||||||
|
if (this.page === 1) {
|
||||||
|
this.hideKeyboardIfVisible();
|
||||||
|
}
|
||||||
|
this.props.onScroll(this.scrollOffset);
|
||||||
|
if (this.scrollTimeout) {
|
||||||
|
clearTimeout(this.scrollTimeout);
|
||||||
|
this.scrollTimeout = null;
|
||||||
|
}
|
||||||
|
this.scrollTimeout = setTimeout(() => {
|
||||||
|
if (
|
||||||
|
this.scrollOffset !== this.props.offsets.a &&
|
||||||
|
this.page === 1 &&
|
||||||
|
!this.scrollEnabled
|
||||||
|
) {
|
||||||
|
this.goToIndex(2, false);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
goToPage = page => {
|
||||||
|
if (page === 0) {
|
||||||
|
this.scrollOffset = this.props.offsets.a;
|
||||||
|
this.hideKeyboardIfVisible();
|
||||||
|
this.goToIndex(1);
|
||||||
|
} else if (page === 1) {
|
||||||
|
this.goToIndex(2);
|
||||||
|
}
|
||||||
|
if (this.page !== page) {
|
||||||
|
this.props.onChangeTab({i: page, from: this.page});
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
keyExtractor = (item, index) => item;
|
||||||
|
|
||||||
|
onScrollEnd = event => {
|
||||||
|
this.responderAllowedScroll = false;
|
||||||
|
let page = 0;
|
||||||
|
if (this.scrollOffset > this.props.offsets.b - 50) {
|
||||||
|
page = 1;
|
||||||
|
} else {
|
||||||
|
this.hideKeyboardIfVisible();
|
||||||
|
}
|
||||||
|
let drawerState = page === 0 && this.scrollOffset < 10;
|
||||||
|
if (drawerState !== this.currentDrawerState) {
|
||||||
|
this.currentDrawerState = drawerState;
|
||||||
|
this.props.onDrawerStateChange(this.currentDrawerState);
|
||||||
|
}
|
||||||
|
if (this.page !== page) {
|
||||||
|
this.props.onChangeTab({i: page, from: this.page});
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
onTouchEnd={this.onTouchEnd}
|
||||||
|
onMoveShouldSetResponderCapture={this.onMoveShouldSetResponder}
|
||||||
|
onStartShouldSetResponderCapture={this.onMoveShouldSetResponder}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}>
|
||||||
|
<TextInput
|
||||||
|
ref={this.inputElement}
|
||||||
|
style={{height: 1, padding: 0, width: 1, position: 'absolute'}}
|
||||||
|
blurOnSubmit={false}
|
||||||
|
/>
|
||||||
|
<FlatList
|
||||||
|
ref={this.listRef}
|
||||||
|
horizontal
|
||||||
|
onMomentumScrollEnd={this.onScrollEnd}
|
||||||
|
onScrollAnimationEnd={this.onScrollEnd}
|
||||||
|
keyExtractor={this.keyExtractor}
|
||||||
|
onScroll={this.onScroll}
|
||||||
|
bounces={false}
|
||||||
|
bouncesZoom={false}
|
||||||
|
initialNumToRender={100}
|
||||||
|
alwaysBounceHorizontal={false}
|
||||||
|
scrollToOverflowEnabled={false}
|
||||||
|
scrollsToTop={false}
|
||||||
|
scrollEventThrottle={1}
|
||||||
|
directionalLockEnabled
|
||||||
|
maintainVisibleContentPosition={true}
|
||||||
|
overScrollMode="never"
|
||||||
|
maxToRenderPerBatch={100}
|
||||||
|
removeClippedSubviews={false}
|
||||||
|
keyboardDismissMode="none"
|
||||||
|
keyboardShouldPersistTaps="always"
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
disableIntervalMomentum={true}
|
||||||
|
snapToOffsets={[
|
||||||
|
this.props.offsets.a,
|
||||||
|
this.props.offsets.b,
|
||||||
|
this.props.offsets.c,
|
||||||
|
]}
|
||||||
|
initialScrollIndex={this.props.initialIndex}
|
||||||
|
data={['drawer', 'navigation', 'editor']}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomTabs.defaultProps = {
|
||||||
|
onDrawerStateChange:() => {}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import {Button} from '../Button';
|
|||||||
import Heading from '../Typography/Heading';
|
import Heading from '../Typography/Heading';
|
||||||
import Paragraph from '../Typography/Paragraph';
|
import Paragraph from '../Typography/Paragraph';
|
||||||
|
|
||||||
const DialogHeader = ({icon, title, paragraph, button,paragraphColor}) => {
|
const DialogHeader = ({icon, title, paragraph, button, paragraphColor}) => {
|
||||||
const [state, dispatch] = useTracked();
|
const [state, dispatch] = useTracked();
|
||||||
const colors = state.colors;
|
const colors = state.colors;
|
||||||
|
|
||||||
@@ -46,7 +46,9 @@ const DialogHeader = ({icon, title, paragraph, button,paragraphColor}) => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{paragraph ? (
|
{paragraph ? (
|
||||||
<Paragraph color={paragraphColor || colors.icon}>{paragraph}</Paragraph>
|
<Paragraph color={paragraphColor || colors.icon}>
|
||||||
|
{paragraph}
|
||||||
|
</Paragraph>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import BaseDialog from '../../components/Dialog/base-dialog';
|
|||||||
import {PressableButton} from '../../components/PressableButton';
|
import {PressableButton} from '../../components/PressableButton';
|
||||||
import Seperator from '../../components/Seperator';
|
import Seperator from '../../components/Seperator';
|
||||||
import {useTracked} from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import { useNoteStore, useSettingStore } from '../../provider/stores';
|
import {useNoteStore, useSettingStore} from '../../provider/stores';
|
||||||
import {DDS} from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
|
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
|
||||||
import {getElevation} from '../../utils';
|
import {getElevation} from '../../utils';
|
||||||
@@ -21,7 +21,7 @@ let timeout = null;
|
|||||||
const JumpToDialog = ({scrollRef}) => {
|
const JumpToDialog = ({scrollRef}) => {
|
||||||
const [state] = useTracked();
|
const [state] = useTracked();
|
||||||
const {colors} = state;
|
const {colors} = state;
|
||||||
|
|
||||||
const notes = useNoteStore(state => state.notes);
|
const notes = useNoteStore(state => state.notes);
|
||||||
const settings = useSettingStore(state => state.settings);
|
const settings = useSettingStore(state => state.settings);
|
||||||
|
|
||||||
@@ -36,7 +36,10 @@ const JumpToDialog = ({scrollRef}) => {
|
|||||||
ind = ind + 1;
|
ind = ind + 1;
|
||||||
ind = ind - (index + 1);
|
ind = ind - (index + 1);
|
||||||
offset = offset + ind * 100 + 200;
|
offset = offset + ind * 100 + 200;
|
||||||
scrollRef.current?.scrollToOffset(0, index === 0 ? 0 : offset, true);
|
scrollRef.current?.scrollToOffset({
|
||||||
|
offset: offset,
|
||||||
|
animated: true,
|
||||||
|
});
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Seperator from '../../components/Seperator';
|
|||||||
import {Toast} from '../../components/Toast';
|
import {Toast} from '../../components/Toast';
|
||||||
import {Actions} from '../../provider/Actions';
|
import {Actions} from '../../provider/Actions';
|
||||||
import {useTracked} from '../../provider/index';
|
import {useTracked} from '../../provider/index';
|
||||||
import { useUserStore } from '../../provider/stores';
|
import {useUserStore} from '../../provider/stores';
|
||||||
import BiometricService from '../../services/BiometricService';
|
import BiometricService from '../../services/BiometricService';
|
||||||
import {DDS} from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
import {
|
import {
|
||||||
@@ -74,8 +74,8 @@ const LoginDialog = () => {
|
|||||||
const colors = state.colors;
|
const colors = state.colors;
|
||||||
|
|
||||||
const setUser = useUserStore(state => state.setUser);
|
const setUser = useUserStore(state => state.setUser);
|
||||||
const setLastSynced = useUserStore(state => state.setLastSynced)
|
const setLastSynced = useUserStore(state => state.setLastSynced);
|
||||||
|
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [status, setStatus] = useState(null);
|
const [status, setStatus] = useState(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -86,7 +86,6 @@ const LoginDialog = () => {
|
|||||||
const [confirm, setConfirm] = useState(false);
|
const [confirm, setConfirm] = useState(false);
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
|
|
||||||
const _email = useRef();
|
const _email = useRef();
|
||||||
const _pass = useRef();
|
const _pass = useRef();
|
||||||
const _username = useRef();
|
const _username = useRef();
|
||||||
@@ -251,9 +250,6 @@ const LoginDialog = () => {
|
|||||||
context: 'local',
|
context: 'local',
|
||||||
});
|
});
|
||||||
close();
|
close();
|
||||||
if (MODES.sessionExpired === mode) {
|
|
||||||
await MMKV.removeItem('loginSessionHasExpired');
|
|
||||||
}
|
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
eSendEvent('userLoggedIn', true);
|
eSendEvent('userLoggedIn', true);
|
||||||
eSendEvent(eOpenProgressDialog, {
|
eSendEvent(eOpenProgressDialog, {
|
||||||
@@ -261,6 +257,7 @@ const LoginDialog = () => {
|
|||||||
paragraph: 'Please wait while we sync all your data.',
|
paragraph: 'Please wait while we sync all your data.',
|
||||||
noProgress: false,
|
noProgress: false,
|
||||||
});
|
});
|
||||||
|
await MMKV.removeItem('loginSessionHasExpired');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setStatus(null);
|
setStatus(null);
|
||||||
@@ -325,7 +322,7 @@ const LoginDialog = () => {
|
|||||||
let user = await db.user.getUser();
|
let user = await db.user.getUser();
|
||||||
setStatus('Setting Crenditials');
|
setStatus('Setting Crenditials');
|
||||||
setUser(user);
|
setUser(user);
|
||||||
setLastSynced(await db.lastSynced())
|
setLastSynced(await db.lastSynced());
|
||||||
clearMessage();
|
clearMessage();
|
||||||
setEmailVerifyMessage();
|
setEmailVerifyMessage();
|
||||||
close();
|
close();
|
||||||
@@ -554,7 +551,7 @@ const LoginDialog = () => {
|
|||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
height: 50,
|
height: 50,
|
||||||
}}>
|
}}>
|
||||||
{DDS.isTab ? (
|
{DDS.isTab && MODES.sessionExpired !== mode ? (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
name="close"
|
name="close"
|
||||||
size={SIZE.xxxl}
|
size={SIZE.xxxl}
|
||||||
@@ -569,7 +566,7 @@ const LoginDialog = () => {
|
|||||||
}}
|
}}
|
||||||
color={colors.heading}
|
color={colors.heading}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : MODES.sessionExpired !== mode && (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
name="arrow-left"
|
name="arrow-left"
|
||||||
size={SIZE.xxxl}
|
size={SIZE.xxxl}
|
||||||
@@ -586,6 +583,7 @@ const LoginDialog = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
<View />
|
<View />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
|||||||
paddingVertical: 2,
|
paddingVertical: 2,
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
marginVertical: 2.5,
|
marginVertical: 2.5,
|
||||||
maxWidth: 70,
|
maxWidth: 100,
|
||||||
}}>
|
}}>
|
||||||
<Paragraph
|
<Paragraph
|
||||||
size={SIZE.xs}
|
size={SIZE.xs}
|
||||||
@@ -117,6 +117,7 @@ export const NotebookItem = ({item, isTopic = false, notebookID, isTrash}) => {
|
|||||||
justifyContent: 'flex-start',
|
justifyContent: 'flex-start',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginTop: 2.5,
|
marginTop: 2.5,
|
||||||
|
minHeight:SIZE.md + 2
|
||||||
}}>
|
}}>
|
||||||
{isTrash ? (
|
{isTrash ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,32 +1,25 @@
|
|||||||
import React, {useEffect, useRef, useState} from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import {FlatList} from 'react-native';
|
import { FlatList, RefreshControl } from 'react-native';
|
||||||
import {RefreshControl, useWindowDimensions} from 'react-native';
|
import { useTracked } from '../../provider';
|
||||||
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
|
|
||||||
import {useTracked} from '../../provider';
|
|
||||||
import {useMessageStore, useSettingStore} from '../../provider/stores';
|
|
||||||
import {DDS} from '../../services/DeviceDetection';
|
|
||||||
import {
|
import {
|
||||||
eSendEvent,
|
eSendEvent
|
||||||
eSubscribeEvent,
|
|
||||||
eUnSubscribeEvent,
|
|
||||||
} from '../../services/EventManager';
|
} from '../../services/EventManager';
|
||||||
import SettingsService from '../../services/SettingsService';
|
import SettingsService from '../../services/SettingsService';
|
||||||
import Sync from '../../services/Sync';
|
import Sync from '../../services/Sync';
|
||||||
import {dHeight, dWidth} from '../../utils';
|
import { COLORS_NOTE } from '../../utils/Colors';
|
||||||
import {COLORS_NOTE} from '../../utils/Colors';
|
import { eScrollEvent } from '../../utils/Events';
|
||||||
import {eScrollEvent} from '../../utils/Events';
|
|
||||||
import useAnnouncement from '../../utils/useAnnouncement';
|
import useAnnouncement from '../../utils/useAnnouncement';
|
||||||
import JumpToDialog from '../JumpToDialog';
|
import JumpToDialog from '../JumpToDialog';
|
||||||
import {NotebookItem} from '../NotebookItem';
|
import { NotebookItem } from '../NotebookItem';
|
||||||
import {NotebookWrapper} from '../NotebookItem/wrapper';
|
import { NotebookWrapper } from '../NotebookItem/wrapper';
|
||||||
import NoteItem from '../NoteItem';
|
import NoteItem from '../NoteItem';
|
||||||
import {NoteWrapper} from '../NoteItem/wrapper';
|
import { NoteWrapper } from '../NoteItem/wrapper';
|
||||||
import TagItem from '../TagItem';
|
import TagItem from '../TagItem';
|
||||||
import {Announcement} from './announcement';
|
import { Announcement } from './announcement';
|
||||||
import {Empty} from './empty';
|
import { Empty } from './empty';
|
||||||
import {Footer} from './footer';
|
import { Footer } from './footer';
|
||||||
import {Header} from './header';
|
import { Header } from './header';
|
||||||
import {SectionHeader} from './section-header';
|
import { SectionHeader } from './section-header';
|
||||||
|
|
||||||
const heights = {
|
const heights = {
|
||||||
note: 100,
|
note: 100,
|
||||||
@@ -47,6 +40,7 @@ const TrashI = ({item, index}) => {
|
|||||||
let renderItems = {
|
let renderItems = {
|
||||||
notes: NoteWrapper,
|
notes: NoteWrapper,
|
||||||
notebooks: NotebookWrapper,
|
notebooks: NotebookWrapper,
|
||||||
|
topics:NotebookWrapper,
|
||||||
tags: TagItem,
|
tags: TagItem,
|
||||||
section: SectionHeader,
|
section: SectionHeader,
|
||||||
trash: TrashI,
|
trash: TrashI,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
|
TouchableOpacity,
|
||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
View
|
View
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
@@ -41,12 +42,15 @@ export const SectionHeader = ({
|
|||||||
: colors.nav,
|
: colors.nav,
|
||||||
marginTop: index === 0 ? 0 : 5 * fontScale,
|
marginTop: index === 0 ? 0 : 5 * fontScale,
|
||||||
}}>
|
}}>
|
||||||
<TouchableWithoutFeedback
|
<TouchableOpacity
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
console.log('called')
|
||||||
if (jumpToDialog) {
|
if (jumpToDialog) {
|
||||||
|
console.log('sending event')
|
||||||
eSendEvent(eOpenJumpToDialog);
|
eSendEvent(eOpenJumpToDialog);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
activeOpacity={0.9}
|
||||||
hitSlop={{top: 10, left: 10, right: 30, bottom: 15}}
|
hitSlop={{top: 10, left: 10, right: 30, bottom: 15}}
|
||||||
style={{
|
style={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -62,7 +66,7 @@ export const SectionHeader = ({
|
|||||||
}}>
|
}}>
|
||||||
{!item.title || item.title === '' ? 'Pinned' : item.title}
|
{!item.title || item.title === '' ? 'Pinned' : item.title}
|
||||||
</Heading>
|
</Heading>
|
||||||
</TouchableWithoutFeedback>
|
</TouchableOpacity>
|
||||||
{index === 0 && sortMenuButton ? <HeaderMenu /> : null}
|
{index === 0 && sortMenuButton ? <HeaderMenu /> : null}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { createDrawerNavigator } from '@react-navigation/drawer';
|
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { State } from 'react-native-gesture-handler';
|
|
||||||
import { Menu } from '../components/Menu';
|
|
||||||
import { useTracked } from '../provider';
|
|
||||||
import { useSettingStore } from '../provider/stores';
|
|
||||||
import { eSubscribeEvent, eUnSubscribeEvent } from '../services/EventManager';
|
|
||||||
import { eCloseSideMenu, eOpenSideMenu } from '../utils/Events';
|
|
||||||
import { sideMenuRef, tabBarRef } from '../utils/Refs';
|
|
||||||
import { NavigatorStack } from './NavigatorStack';
|
|
||||||
|
|
||||||
const Drawer = createDrawerNavigator();
|
|
||||||
|
|
||||||
const onStateChange = state => {
|
|
||||||
let s = state[0];
|
|
||||||
if (s && s !== State.ACTIVE && s !== State.BEGAN) {
|
|
||||||
let state = sideMenuRef.current.getRootState();
|
|
||||||
if (state.history.findIndex(o => o.type === 'drawer') === -1) {
|
|
||||||
tabBarRef.current?.setScrollEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onNavigatorStateChange = e => {
|
|
||||||
if (e.history.find(i => i.type === 'drawer')) {
|
|
||||||
//changeContainerScale(ContainerScale, 0.95, 250);
|
|
||||||
//changeContainerScale(DrawerScale, 1, 250);
|
|
||||||
} else {
|
|
||||||
//changeContainerScale(DrawerScale, 0.95, 250);
|
|
||||||
//changeContainerScale(ContainerScale, 1, 250);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const NavigationStack = ({component = NavigatorStack}) => {
|
|
||||||
const deviceMode = useSettingStore(state => state.deviceMode);
|
|
||||||
const [locked, setLocked] = React.useState(false);
|
|
||||||
|
|
||||||
const setGestureDisabled = () => {
|
|
||||||
setLocked(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setGestureEnabled = () => {
|
|
||||||
if (locked) {
|
|
||||||
setLocked(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
eSubscribeEvent(eOpenSideMenu, setGestureEnabled);
|
|
||||||
eSubscribeEvent(eCloseSideMenu, setGestureDisabled);
|
|
||||||
return () => {
|
|
||||||
eUnSubscribeEvent(eOpenSideMenu, setGestureEnabled);
|
|
||||||
eUnSubscribeEvent(eCloseSideMenu, setGestureDisabled);
|
|
||||||
};
|
|
||||||
}, [locked]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NavigationContainer
|
|
||||||
//onStateChange={onNavigatorStateChange}
|
|
||||||
ref={sideMenuRef}>
|
|
||||||
<Drawer.Navigator
|
|
||||||
screenOptions={{
|
|
||||||
swipeEnabled: locked || deviceMode !== 'mobile' ? false : true,
|
|
||||||
gestureEnabled: locked || deviceMode !== 'mobile' ? false : true,
|
|
||||||
}}
|
|
||||||
onStateChange={onStateChange}
|
|
||||||
drawerStyle={{
|
|
||||||
width: deviceMode !== 'mobile' ? 0 : '75%',
|
|
||||||
borderRightWidth: 0,
|
|
||||||
}}
|
|
||||||
|
|
||||||
edgeWidth={200}
|
|
||||||
drawerType="slide"
|
|
||||||
drawerContent={deviceMode !== 'mobile' ? () => <></> : DrawerComponent}
|
|
||||||
initialRouteName="Main">
|
|
||||||
<Drawer.Screen name="Main" component={component} />
|
|
||||||
</Drawer.Navigator>
|
|
||||||
</NavigationContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DrawerComponent = () => {
|
|
||||||
return <Menu />;
|
|
||||||
};
|
|
||||||
@@ -1,27 +1,24 @@
|
|||||||
import {NavigationContainer} from '@react-navigation/native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Animated} from 'react-native';
|
import { createNativeStackNavigator } from 'react-native-screens/native-stack';
|
||||||
import {createNativeStackNavigator} from 'react-native-screens/native-stack';
|
|
||||||
import Container from '../components/Container';
|
import Container from '../components/Container';
|
||||||
import {useTracked} from '../provider';
|
|
||||||
import {Actions} from '../provider/Actions';
|
|
||||||
import { useSelectionStore } from '../provider/stores';
|
import { useSelectionStore } from '../provider/stores';
|
||||||
import {
|
import {
|
||||||
eSendEvent,
|
eSendEvent,
|
||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent,
|
eUnSubscribeEvent
|
||||||
} from '../services/EventManager';
|
} from '../services/EventManager';
|
||||||
import Navigation from '../services/Navigation';
|
import Navigation from '../services/Navigation';
|
||||||
import SettingsService from '../services/SettingsService';
|
import SettingsService from '../services/SettingsService';
|
||||||
import {history} from '../utils';
|
import { history } from '../utils';
|
||||||
import {eOpenSideMenu} from '../utils/Events';
|
import { eOpenSideMenu } from '../utils/Events';
|
||||||
import {rootNavigatorRef} from '../utils/Refs';
|
import { rootNavigatorRef } from '../utils/Refs';
|
||||||
import Favorites from '../views/Favorites';
|
import Favorites from '../views/Favorites';
|
||||||
import Folders from '../views/Folders';
|
import Folders from '../views/Folders';
|
||||||
import Home from '../views/Home';
|
import Home from '../views/Home';
|
||||||
import Notebook from '../views/Notebook';
|
import Notebook from '../views/Notebook';
|
||||||
import Notes from '../views/Notes';
|
import Notes from '../views/Notes';
|
||||||
import {Search} from '../views/Search';
|
import { Search } from '../views/Search';
|
||||||
import Settings from '../views/Settings';
|
import Settings from '../views/Settings';
|
||||||
import Tags from '../views/Tags';
|
import Tags from '../views/Tags';
|
||||||
import Trash from '../views/Trash';
|
import Trash from '../views/Trash';
|
||||||
@@ -34,44 +31,6 @@ const forFade = ({current}) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const forSlide = ({current, next, inverted, layouts: {screen}}) => {
|
|
||||||
const progress = Animated.add(
|
|
||||||
current.progress.interpolate({
|
|
||||||
inputRange: [0, 1],
|
|
||||||
outputRange: [0, 1],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
}),
|
|
||||||
next
|
|
||||||
? next.progress.interpolate({
|
|
||||||
inputRange: [0, 1],
|
|
||||||
outputRange: [0, 1],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
})
|
|
||||||
: 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
cardStyle: {
|
|
||||||
transform: [
|
|
||||||
{
|
|
||||||
translateX: Animated.multiply(
|
|
||||||
progress.interpolate({
|
|
||||||
inputRange: [0, 1, 2],
|
|
||||||
outputRange: [
|
|
||||||
screen.width, // Focused, but offscreen in the beginning
|
|
||||||
0, // Fully focused
|
|
||||||
screen.width * -0.3, // Fully unfocused
|
|
||||||
],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
}),
|
|
||||||
inverted,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const screenOptionsForAnimation = {
|
const screenOptionsForAnimation = {
|
||||||
animationEnabled: true,
|
animationEnabled: true,
|
||||||
cardStyleInterpolator: forFade,
|
cardStyleInterpolator: forFade,
|
||||||
@@ -80,7 +39,6 @@ const screenOptionsForAnimation = {
|
|||||||
|
|
||||||
export const NavigatorStack = React.memo(
|
export const NavigatorStack = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const [, dispatch] = useTracked();
|
|
||||||
const [render, setRender] = React.useState(true);
|
const [render, setRender] = React.useState(true);
|
||||||
const clearSelection = useSelectionStore(state => state.clearSelection);
|
const clearSelection = useSelectionStore(state => state.clearSelection);
|
||||||
const onStateChange = React.useCallback(() => {
|
const onStateChange = React.useCallback(() => {
|
||||||
@@ -124,9 +82,8 @@ export const NavigatorStack = React.memo(
|
|||||||
initialRouteName={SettingsService.get().homepage}
|
initialRouteName={SettingsService.get().homepage}
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
animationEnabled: false,
|
|
||||||
gestureEnabled: false,
|
gestureEnabled: false,
|
||||||
stackAnimation: 'none',
|
stackAnimation: 'fade',
|
||||||
}}>
|
}}>
|
||||||
<Stack.Screen name="Notes" component={Home} />
|
<Stack.Screen name="Notes" component={Home} />
|
||||||
<Stack.Screen name="Notebooks" component={Folders} />
|
<Stack.Screen name="Notebooks" component={Folders} />
|
||||||
|
|||||||
@@ -73,13 +73,20 @@ export type Settings = {
|
|||||||
appLockMode?: string,
|
appLockMode?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Dimensions = {
|
||||||
|
width:number,
|
||||||
|
height:number
|
||||||
|
}
|
||||||
|
|
||||||
export interface SettingStore extends State {
|
export interface SettingStore extends State {
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
fullscreen: boolean,
|
fullscreen: boolean,
|
||||||
deviceMode: string | null,
|
deviceMode: string | null,
|
||||||
|
dimensions:Dimensions
|
||||||
setSettings: (settings: Settings) => void,
|
setSettings: (settings: Settings) => void,
|
||||||
setFullscreen: (fullscreen: boolean) => void,
|
setFullscreen: (fullscreen: boolean) => void,
|
||||||
setDeviceMode: (mode: string) => void
|
setDeviceMode: (mode: string) => void,
|
||||||
|
setDimensions: (dimensions:Dimensions) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Dimensions } from 'react-native';
|
||||||
import create, {State} from 'zustand';
|
import create, {State} from 'zustand';
|
||||||
import {eSendEvent} from '../services/EventManager';
|
import {eSendEvent} from '../services/EventManager';
|
||||||
import {history, SORT, sortSettings} from '../utils';
|
import {history, SORT, sortSettings} from '../utils';
|
||||||
@@ -143,6 +144,8 @@ export const useUserStore = create<UserStore>((set, get) => ({
|
|||||||
setLastSynced: lastSynced => set({lastSynced: lastSynced}),
|
setLastSynced: lastSynced => set({lastSynced: lastSynced}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let {width, height} = Dimensions.get('window');
|
||||||
|
|
||||||
export const useSettingStore = create<SettingStore>((set, get) => ({
|
export const useSettingStore = create<SettingStore>((set, get) => ({
|
||||||
settings: {
|
settings: {
|
||||||
showToolbarOnTop: false,
|
showToolbarOnTop: false,
|
||||||
@@ -161,9 +164,11 @@ export const useSettingStore = create<SettingStore>((set, get) => ({
|
|||||||
},
|
},
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
deviceMode: null,
|
deviceMode: null,
|
||||||
|
dimensions:{width,height},
|
||||||
setSettings: settings => set({settings}),
|
setSettings: settings => set({settings}),
|
||||||
setFullscreen: fullscreen => set({fullscreen}),
|
setFullscreen: fullscreen => set({fullscreen}),
|
||||||
setDeviceMode: mode => set({deviceMode: mode}),
|
setDeviceMode: mode => set({deviceMode: mode}),
|
||||||
|
setDimensions: dimensions => set({dimensions:dimensions})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useMenuStore = create<MenuStore>((set, get) => ({
|
export const useMenuStore = create<MenuStore>((set, get) => ({
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ async function clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function encrypt(password, data) {
|
async function encrypt(password, data) {
|
||||||
|
if (!password.password && !password.key) return undefined
|
||||||
|
if (password.password && password.password === "" && !password.key) return undefined
|
||||||
|
|
||||||
let message = {
|
let message = {
|
||||||
type: 'plain',
|
type: 'plain',
|
||||||
data: data,
|
data: data,
|
||||||
@@ -69,6 +72,8 @@ function getAlgorithm(base64Variant) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function decrypt(password, data) {
|
async function decrypt(password, data) {
|
||||||
|
if (!password.password && !password.key) return undefined
|
||||||
|
if (password.password && password.password === "" && !password.key) return undefined
|
||||||
data.output = 'plain';
|
data.output = 'plain';
|
||||||
return await Sodium.decrypt(password, data);
|
return await Sodium.decrypt(password, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
eUnSubscribeEvent,
|
eUnSubscribeEvent,
|
||||||
} from '../../services/EventManager';
|
} from '../../services/EventManager';
|
||||||
import {getCurrentColors} from '../../utils/Colors';
|
import {getCurrentColors} from '../../utils/Colors';
|
||||||
|
import { eOpenLoginDialog } from '../../utils/Events';
|
||||||
|
import { MMKV } from '../../utils/mmkv';
|
||||||
import {normalize} from '../../utils/SizeUtils';
|
import {normalize} from '../../utils/SizeUtils';
|
||||||
import {sleep} from '../../utils/TimeUtils';
|
import {sleep} from '../../utils/TimeUtils';
|
||||||
import EditorHeader from './EditorHeader';
|
import EditorHeader from './EditorHeader';
|
||||||
@@ -55,6 +57,11 @@ const Editor = React.memo(
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
setTimeout(async () => {
|
||||||
|
if ((await MMKV.getItem('loginSessionHasExpired')) === 'expired')
|
||||||
|
eSendEvent(eOpenLoginDialog, 4);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
if (premiumUser) {
|
if (premiumUser) {
|
||||||
tiny.call(EditorWebView,tiny.setMarkdown,true)
|
tiny.call(EditorWebView,tiny.setMarkdown,true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import SearchService from '../../services/SearchService';
|
|||||||
import { InteractionManager, scrollRef } from '../../utils';
|
import { InteractionManager, scrollRef } from '../../utils';
|
||||||
import { db } from '../../utils/DB';
|
import { db } from '../../utils/DB';
|
||||||
import { eOnLoadNote, eScrollEvent } from '../../utils/Events';
|
import { eOnLoadNote, eScrollEvent } from '../../utils/Events';
|
||||||
|
import { MMKV } from '../../utils/mmkv';
|
||||||
import { tabBarRef } from '../../utils/Refs';
|
import { tabBarRef } from '../../utils/Refs';
|
||||||
import Storage from '../../utils/storage';
|
import Storage from '../../utils/storage';
|
||||||
|
|
||||||
@@ -83,11 +84,6 @@ export const Home = ({navigation}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _onPressBottomButton = React.useCallback(async () => {
|
const _onPressBottomButton = React.useCallback(async () => {
|
||||||
let result = Storage.encrypt({
|
|
||||||
password:""
|
|
||||||
},"hello world");
|
|
||||||
console.log(result);
|
|
||||||
return;
|
|
||||||
if (!DDS.isLargeTablet()) {
|
if (!DDS.isLargeTablet()) {
|
||||||
eSendEvent(eOnLoadNote, {type: 'new'});
|
eSendEvent(eOnLoadNote, {type: 'new'});
|
||||||
tabBarRef.current?.goToPage(1);
|
tabBarRef.current?.goToPage(1);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const Notebook = ({route, navigation}) => {
|
|||||||
ranAfterInteractions = true;
|
ranAfterInteractions = true;
|
||||||
runAfterInteractions();
|
runAfterInteractions();
|
||||||
}
|
}
|
||||||
Navigation.setHeaderState('Notebooks', params, {
|
Navigation.setHeaderState('Notebook', params, {
|
||||||
heading: params.title,
|
heading: params.title,
|
||||||
id: params.notebook.id,
|
id: params.notebook.id,
|
||||||
type: 'notebook',
|
type: 'notebook',
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import React, {createRef, useCallback, useEffect, useState} from 'react';
|
import React, {
|
||||||
|
createRef,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import {
|
import {
|
||||||
Appearance,
|
Appearance,
|
||||||
Linking,
|
Linking,
|
||||||
@@ -28,7 +34,11 @@ import Heading from '../../components/Typography/Heading';
|
|||||||
import Paragraph from '../../components/Typography/Paragraph';
|
import Paragraph from '../../components/Typography/Paragraph';
|
||||||
import {useTracked} from '../../provider';
|
import {useTracked} from '../../provider';
|
||||||
import {Actions} from '../../provider/Actions';
|
import {Actions} from '../../provider/Actions';
|
||||||
import { useMessageStore, useSettingStore, useUserStore } from '../../provider/stores';
|
import {
|
||||||
|
useMessageStore,
|
||||||
|
useSettingStore,
|
||||||
|
useUserStore,
|
||||||
|
} from '../../provider/stores';
|
||||||
import Backup from '../../services/Backup';
|
import Backup from '../../services/Backup';
|
||||||
import BiometricService from '../../services/BiometricService';
|
import BiometricService from '../../services/BiometricService';
|
||||||
import {DDS} from '../../services/DeviceDetection';
|
import {DDS} from '../../services/DeviceDetection';
|
||||||
@@ -72,6 +82,7 @@ import {
|
|||||||
} from '../../utils/Events';
|
} from '../../utils/Events';
|
||||||
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 {pv, SIZE} from '../../utils/SizeUtils';
|
import {pv, SIZE} from '../../utils/SizeUtils';
|
||||||
import Storage from '../../utils/storage';
|
import Storage from '../../utils/storage';
|
||||||
import {sleep, timeConverter} from '../../utils/TimeUtils';
|
import {sleep, timeConverter} from '../../utils/TimeUtils';
|
||||||
@@ -579,23 +590,53 @@ const getTimeLeft = t2 => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let passwordVerifyValue = null;
|
||||||
const SettingsUserSection = () => {
|
const SettingsUserSection = () => {
|
||||||
const [state] = useTracked();
|
const [state] = useTracked();
|
||||||
const {colors} = state;
|
const {colors} = state;
|
||||||
|
|
||||||
const user = useUserStore(state => state.user);
|
const user = useUserStore(state => state.user);
|
||||||
const messageBoardState = useMessageStore(state => state.message);
|
const messageBoardState = useMessageStore(state => state.message);
|
||||||
|
const [verifyUser, setVerifyUser] = useState(false);
|
||||||
const subscriptionDaysLeft =
|
const subscriptionDaysLeft =
|
||||||
user && getTimeLeft(parseInt(user.subscription?.expiry));
|
user && getTimeLeft(parseInt(user.subscription?.expiry));
|
||||||
const isExpired = user && subscriptionDaysLeft.time < 0;
|
const isExpired = user && subscriptionDaysLeft.time < 0;
|
||||||
const expiryDate = dayjs(user?.subscription?.expiry).format(
|
const expiryDate = dayjs(user?.subscription?.expiry).format('MMMM D, YYYY');
|
||||||
'MMMM D, YYYY',
|
const startDate = dayjs(user?.subscription?.start).format('MMMM D, YYYY');
|
||||||
);
|
const input = useRef();
|
||||||
const startDate = dayjs(user?.subscription?.start).format(
|
const tryVerification = async () => {
|
||||||
'MMMM D, YYYY',
|
if (!passwordVerifyValue) {
|
||||||
)
|
ToastEvent.show({
|
||||||
console.log(user?.subscription)
|
heading: 'Account Password is required',
|
||||||
|
type: 'error',
|
||||||
|
context: 'local',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let verify = await db.user.verifyPassword(passwordVerifyValue);
|
||||||
|
if (verify) {
|
||||||
|
setVerifyUser(false);
|
||||||
|
passwordVerifyValue = null;
|
||||||
|
await sleep(300);
|
||||||
|
eSendEvent(eOpenRecoveryKeyDialog);
|
||||||
|
} else {
|
||||||
|
ToastEvent.show({
|
||||||
|
heading: 'Incorrect password',
|
||||||
|
message: 'Please enter the correct password to save recovery key.',
|
||||||
|
type: 'error',
|
||||||
|
context: 'local',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ToastEvent.show({
|
||||||
|
heading: 'Incorrect password',
|
||||||
|
message: e.message,
|
||||||
|
type: 'error',
|
||||||
|
context: 'local',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -757,11 +798,9 @@ const SettingsUserSection = () => {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
<Paragraph color={colors.pri}>
|
<Paragraph color={colors.pri}>
|
||||||
{user.subscription.type === 2
|
{user.subscription.type === 2
|
||||||
? 'You signed up on ' +
|
? 'You signed up on ' + startDate
|
||||||
startDate
|
|
||||||
: user.subscription.type === 1
|
: user.subscription.type === 1
|
||||||
? 'Your trial period started on ' +
|
? 'Your trial period started on ' + startDate
|
||||||
startDate
|
|
||||||
: user.subscription.type === 6
|
: user.subscription.type === 6
|
||||||
? subscriptionDaysLeft.time < -3
|
? subscriptionDaysLeft.time < -3
|
||||||
? 'Your subscription has ended'
|
? 'Your subscription has ended'
|
||||||
@@ -786,7 +825,7 @@ const SettingsUserSection = () => {
|
|||||||
}}
|
}}
|
||||||
width="100%"
|
width="100%"
|
||||||
style={{
|
style={{
|
||||||
paddingHorizontal:0
|
paddingHorizontal: 0,
|
||||||
}}
|
}}
|
||||||
fontSize={SIZE.md}
|
fontSize={SIZE.md}
|
||||||
title={
|
title={
|
||||||
@@ -847,21 +886,71 @@ const SettingsUserSection = () => {
|
|||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{verifyUser && (
|
||||||
|
<BaseDialog
|
||||||
|
onRequestClose={() => {
|
||||||
|
setVerifyUser(false);
|
||||||
|
passwordVerifyValue = null;
|
||||||
|
}}
|
||||||
|
onShow={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
input.current?.focus();
|
||||||
|
}, 300);
|
||||||
|
}}
|
||||||
|
statusBarTranslucent={false}
|
||||||
|
visible={true}>
|
||||||
|
<DialogContainer>
|
||||||
|
<DialogHeader
|
||||||
|
title="Verify it's you"
|
||||||
|
paragraph="To save your account recovery key, enter your account password"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
fwdRef={input}
|
||||||
|
placeholder="Enter account password"
|
||||||
|
onChangeText={v => {
|
||||||
|
passwordVerifyValue = v;
|
||||||
|
}}
|
||||||
|
onSubmit={tryVerification}
|
||||||
|
secureTextEntry={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
setVerifyUser(false);
|
||||||
|
passwordVerifyValue = null;
|
||||||
|
}}
|
||||||
|
fontSize={SIZE.md}
|
||||||
|
type="gray"
|
||||||
|
title="Cancel"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onPress={tryVerification}
|
||||||
|
fontSize={SIZE.md}
|
||||||
|
style={{
|
||||||
|
marginLeft: 10,
|
||||||
|
}}
|
||||||
|
type="transparent"
|
||||||
|
title="Verify"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</DialogContainer>
|
||||||
|
<Toast context="local" />
|
||||||
|
</BaseDialog>
|
||||||
|
)}
|
||||||
|
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
name: 'Save data recovery key',
|
name: 'Save data recovery key',
|
||||||
func: async () => {
|
func: async () => {
|
||||||
if (BiometricService.isBiometryAvailable() === false) {
|
setVerifyUser(true);
|
||||||
eSendEvent(eOpenRecoveryKeyDialog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let result = await BiometricService.validateUser(
|
|
||||||
"Verify it's you",
|
|
||||||
'',
|
|
||||||
);
|
|
||||||
if (result) {
|
|
||||||
eSendEvent(eOpenRecoveryKeyDialog);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
desc:
|
desc:
|
||||||
'Recover your data using the recovery key if your password is lost.',
|
'Recover your data using the recovery key if your password is lost.',
|
||||||
@@ -876,11 +965,10 @@ const SettingsUserSection = () => {
|
|||||||
{
|
{
|
||||||
name: 'Having problems with syncing?',
|
name: 'Having problems with syncing?',
|
||||||
func: async () => {
|
func: async () => {
|
||||||
await Sync.run("global",true);
|
await Sync.run('global', true);
|
||||||
},
|
},
|
||||||
desc: 'Try force sync to resolve issues with syncing.',
|
desc: 'Try force sync to resolve issues with syncing.',
|
||||||
},
|
},
|
||||||
|
|
||||||
].map(item => (
|
].map(item => (
|
||||||
<CustomButton
|
<CustomButton
|
||||||
key={item.name}
|
key={item.name}
|
||||||
@@ -958,6 +1046,12 @@ const SettingsAppearanceSection = () => {
|
|||||||
<ScrollView
|
<ScrollView
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
|
onMoveShouldSetResponderCapture={() => {
|
||||||
|
tabBarRef.current?.setScrollEnabled(false);
|
||||||
|
}}
|
||||||
|
onMomentumScrollEnd={() => {
|
||||||
|
tabBarRef.current?.setScrollEnabled(true);
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
padding: 5,
|
padding: 5,
|
||||||
@@ -966,6 +1060,7 @@ const SettingsAppearanceSection = () => {
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
}}
|
}}
|
||||||
|
nestedScrollEnabled
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
@@ -1365,7 +1460,7 @@ const SettingsBackupAndRestore = () => {
|
|||||||
const {colors} = state;
|
const {colors} = state;
|
||||||
const settings = useSettingStore(state => state.settings);
|
const settings = useSettingStore(state => state.settings);
|
||||||
const user = useUserStore(state => state.user);
|
const user = useUserStore(state => state.user);
|
||||||
|
|
||||||
const backupItemsList = [
|
const backupItemsList = [
|
||||||
{
|
{
|
||||||
name: 'Backup data',
|
name: 'Backup data',
|
||||||
|
|||||||
Reference in New Issue
Block a user