cleanup and refactor

This commit is contained in:
ammarahm-ed
2020-10-13 17:02:14 +05:00
parent cbb9249781
commit 4e9d71a969
96 changed files with 1974 additions and 2285 deletions

View File

@@ -3,10 +3,11 @@
"runnerConfig": "e2e/config.json",
"configurations": {
"ios": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/Notesnook.app",
"build": "xcodebuild -workspace ios/Notesnook.xcworkspace -scheme Notesnook -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"binaryPath": "SPECIFY_PATH_TO_YOUR_APP_BINARY",
"device": {
"type": "iPhone 11"
"type": "iPhone 11 Pro"
}
},
"android.emu.debug": {

View File

@@ -1,41 +1,28 @@
import {useNetInfo} from '@react-native-community/netinfo';
import React, {useEffect, useState} from 'react';
import {Dimensions, useColorScheme} from 'react-native';
import {useColorScheme} from 'react-native';
import Orientation from 'react-native-orientation';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {
getColorScheme,
getDeviceSize,
scale,
updateSize,
} from './src/common/common';
import {useTracked} from './src/provider';
import {ACTIONS} from './src/provider/actions';
import {defaultState} from './src/provider/defaultState';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from './src/services/eventManager';
import {
eDispatchAction,
eOnLoadNote,
eResetApp,
eStartSyncer,
} from './src/services/events';
import {MMKV} from './src/utils/storage';
import {db, DDS, sleep, ToastEvent} from './src/utils/utils';
import {Actions} from './src/provider/Actions';
import {defaultState} from './src/provider/DefaultState';
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent, ToastEvent,} from './src/services/EventManager';
import {eDispatchAction, eOnLoadNote, eResetApp, eStartSyncer,} from './src/utils/Events';
import DeviceInfo from 'react-native-device-info';
import {getNote} from './src/views/Editor/func';
import {openEditorAnimation} from './src/utils/animations';
import {getNote} from './src/views/Editor/Functions';
import {openEditorAnimation} from './src/utils/Animations';
import {sleep} from "./src/utils/TimeUtils";
import {getColorScheme} from "./src/utils/ColorUtils";
import {getDeviceSize, scale, updateSize} from "./src/utils/SizeUtils";
import {db} from "./src/utils/DB";
import {DDS} from "./src/services/DeviceDetection";
import {MMKV} from "./src/utils/MMKV";
let firstLoad = true;
let note = null;
const App = () => {
const [, dispatch] = useTracked();
const [init, setInit] = useState(false);
const netInfo = useNetInfo();
const colorScheme = useColorScheme();
const [, dispatch] = useTracked(), [init, setInit] = useState(false), netInfo = useNetInfo(),
colorScheme = useColorScheme();
let I =
DDS.isTab && !DDS.isSmallTab
? require('./index.tablet')
@@ -61,8 +48,9 @@ const App = () => {
}, 1000);
};
useEffect(() => {
updateTheme();
updateTheme().then(r => r);
}, [colorScheme]);
const updateTheme = async () => {
@@ -72,13 +60,12 @@ const App = () => {
} catch (e) {
console.log(e.message);
} finally {
if (!settings) {
return;
}
if (settings) {
settings = JSON.parse(settings);
if (settings.useSystemTheme) {
let newColors = await getColorScheme(settings.useSystemTheme);
dispatch({type: ACTIONS.THEME, colors: newColors});
dispatch({type: Actions.THEME, colors: newColors});
}
}
}
};
@@ -101,21 +88,9 @@ const App = () => {
}
}, [netInfo]);
const startSyncer = async () => {
try {
let user = await db.user.get();
if (user) {
db.ev.subscribe('db:refresh', syncChanges);
}
} catch (e) {
console.log(e);
}
};
const syncChanges = async () => {
dispatch({type: ACTIONS.ALL});
};
const resetApp = () => {
dispatch({type: Actions.ALL});
}, resetApp = () => {
note = getNote();
console.log(note, 'NOTE BEFORE RELOAD');
setInit(false);
@@ -132,6 +107,15 @@ const App = () => {
note = null;
}
});
}, startSyncer = async () => {
try {
let user = await db.user.get();
if (user) {
db.ev.subscribe('db:refresh', syncChanges);
}
} catch (e) {
console.log(e);
}
};
useEffect(() => {
@@ -148,6 +132,7 @@ const App = () => {
eUnSubscribeEvent(eDispatchAction, (type) => {
dispatch(type);
});
Orientation.removeOrientationListener(_onOrientationChange);
};
}, []);
@@ -162,13 +147,13 @@ const App = () => {
user = await db.user.get();
} catch (e) {
error = e;
console.log(e,"ERROR IN DB")
console.log(e, "ERROR IN DB")
} finally {
if (user) {
dispatch({type: ACTIONS.USER, user: user});
startSyncer();
dispatch({type: Actions.USER, user: user});
await startSyncer();
}
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.ALL});
setInit(true);
@@ -181,7 +166,7 @@ const App = () => {
});
}, []);
async function Initialize(colors = colors) {
async function Initialize() {
let settings;
scale.fontScale = 1;
@@ -210,8 +195,8 @@ const App = () => {
}
} finally {
let newColors = await getColorScheme(settings.useSystemTheme);
dispatch({type: ACTIONS.SETTINGS, settings: {...settings}});
dispatch({type: ACTIONS.THEME, colors: newColors});
dispatch({type: Actions.SETTINGS, settings: {...settings}});
dispatch({type: Actions.THEME, colors: newColors});
}
}
@@ -222,7 +207,7 @@ const App = () => {
<>
<SafeAreaProvider>
<>
<I.Initialize />
<I.Initialize/>
</>
</SafeAreaProvider>
</>

View File

@@ -8,31 +8,30 @@ it('CHECK APP LOADED', async () => {
});
it('CHECK MENU NAVIGATION', async () => {
menu = element(by.id('left_menu_button'));
await expect(element(by.id('left_menu_button'))).toBeVisible();
/* await element(by.id('Notebooks')).tap();
menu.tap();
await sleep(200);
element(by.id('Notebooks')).tap();
await element(by.id('Favorites')).tap();
menu.tap();
await sleep(200);
element(by.id('Favorites')).tap();
await element(by.id('Trash')).tap();
menu.tap();
await sleep(200);
element(by.id('Trash')).tap();
await element(by.text('Tags')).tap();
menu.tap();
await sleep(200);
element(by.text('Tags')).tap();
await element(by.id('Settings')).tap();
menu.tap();
await sleep(200);
element(by.id('Settings')).tap();
menu.tap();
await sleep(200);
await sleep(200); */
});
it('CHECK NIGHT MODE SWITCHING', async () => {
element(by.id('night_mode')).tap();
/* await element(by.id('night_mode')).tap();
await sleep(2000);
element(by.id('night_mode')).tap();
await element(by.id('night_mode')).tap(); */
});

View File

@@ -6,14 +6,14 @@ import {Screen, ScreenContainer} from 'react-native-screens';
import {DialogManager} from './src/components/DialogManager';
import {Toast} from './src/components/Toast';
import {useTracked} from './src/provider';
import {NavigationStack} from './src/services/Navigator';
import {
EditorOpacity,
EditorPosition,
EditorScale,
EditorTranslateY,
} from './src/utils/animations';
} from './src/utils/Animations';
import Editor from './src/views/Editor';
import {NavigationStack} from "./src/navigation/Drawer";
const editorRef = createRef();

View File

@@ -8,14 +8,15 @@ import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from './src/services/eventManager';
} from './src/services/EventManager';
import {
eCloseFullscreenEditor,
eOnLoadNote,
eOpenFullscreenEditor,
} from './src/services/events';
import {MainComponent, NavigationStack} from './src/services/Navigator';
} from './src/utils/Events';
import {NavigatorStack} from './src/navigation/NavigatorStack';
import Editor from './src/views/Editor';
import {NavigationStack} from "./src/navigation/Drawer";
const editorRef = createRef();
let outColors;
@@ -100,7 +101,7 @@ const NavWrapper = () => {
borderRightColor: colors.nav,
borderRightWidth: 1,
}}>
<MainComponent />
<NavigatorStack />
</View>
<View

View File

@@ -1,10 +1,10 @@
import React from 'react';
import * as Animatable from 'react-native-animatable';
import {SIZE, WEIGHT} from './src/common/common';
import {DialogManager} from './src/components/DialogManager';
import {Toast} from './src/components/Toast';
import {useTracked} from './src/provider';
import {w} from './src/utils/utils';
import {dWidth} from './src/utils';
import {SIZE, WEIGHT} from "./src/utils/SizeUtils";
export const Loading = () => {
const [state, dispatch] = useTracked();
const {colors, loading} = state;
@@ -27,7 +27,7 @@ export const Loading = () => {
zIndex: 999,
transform: [
{
translateX: loading ? 0 : -w * 2,
translateX: loading ? 0 : -dWidth * 2,
},
],
}}>
@@ -71,7 +71,7 @@ export const Loading = () => {
zIndex: 999,
transform: [
{
translateX: loading ? 0 : w * 2,
translateX: loading ? 0 : dWidth * 2,
},
],
}}>

View File

@@ -1,249 +0,0 @@
import {
Dimensions,
PixelRatio,
StatusBar,
Platform,
Appearance,
} from 'react-native';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../services/eventManager';
import {eThemeUpdated} from '../services/events';
import {DDS} from '../utils/utils';
import {MMKV} from '../utils/storage';
export const scale = {
fontScale: 1,
};
const {height, width} = Dimensions.get('window');
//COLOR SCHEME
export const ACCENT = {
color: '#0560FF',
shade: '#0560FF12',
};
const fixedColors = {
accent: ACCENT.color,
shade: ACCENT.shade,
fg: ACCENT.color,
normal: 'black',
icon: 'gray',
errorBg: '#FFD2D2',
errorText: '#ff6961',
successBg: '#DFF2BF',
successText: '#4F8A10',
warningBg: '#FEEFB3',
warningText: '#9F6000',
};
export var COLOR_SCHEME = {
night: false,
bg: 'white',
navbg: '#f6fbfc',
nav: '#f0f0f0',
pri: '#000000',
sec: 'white',
...fixedColors,
};
export const COLOR_SCHEME_LIGHT = {
night: false,
bg: 'white',
navbg: '#f6fbfc',
nav: '#f0f0f0',
input: 'transparent',
heading: '#000000',
pri: '#24292e',
sec: 'white',
...fixedColors,
};
export const COLOR_SCHEME_DARK = {
night: true,
bg: '#1f1f1f',
navbg: '#1c1c1c',
input: '#2d2d2d',
nav: '#2d2d2d',
heading: '#ffffff',
pri: '#D3D3D3',
sec: 'black',
...fixedColors,
};
let windowSize = Dimensions.get('window');
let adjustedWidth = windowSize.width * PixelRatio.get();
let adjustedHeight = windowSize.height * PixelRatio.get();
const pixelDensity = PixelRatio.get();
export const COLORS_NOTE = {
red: '#f44336',
orange: '#FF9800',
yellow: '#FFD600',
green: '#4CAF50',
blue: '#2196F3',
purple: '#673AB7',
gray: '#9E9E9E',
};
export const getDeviceSize = () => {
let dpi = getDpi(pixelDensity);
let deviceWidthInInches = adjustedWidth / dpi;
let deviceHeightInInches = adjustedHeight / dpi;
let diagonalSize = Math.sqrt(
Math.pow(deviceWidthInInches, 2) + Math.pow(deviceHeightInInches, 2),
);
return diagonalSize;
};
const getDpi = (pd) => {
return 160 * pd;
};
const correction = (size, multiplier) => {
let dSize = getDeviceSize();
if (dSize >= 4 && dSize <= 5.3 && pixelDensity <= 3) {
return size * 0.92;
} else if (dSize > 5.3 && dSize < 7 && pixelDensity < 3 && !DDS.isTab) {
if (Platform.OS === 'ios') {
return size;
}
return size * 0.93;
} else if (dSize <= 7 && pixelDensity >= 3 && !DDS.isTab) {
return size * 0.98;
} else if (dSize >= 6.5 && dSize <= 7.2 && DDS.isTab) {
return size * multiplier;
} else if (dSize > 7.2 && dSize <= 8.5 && DDS.isTab) {
return size * (multiplier + 0.10);
} else if (dSize > 8.5 && dSize <= 9.8 && DDS.isTab) {
return size * (multiplier + 0.15);
} else if (dSize > 9.8) {
return size;
} else {
return size;
}
};
export const normalize = (size) => {
let pd = pixelDensity;
if (pd === 1 || pd < 1) {
return correction(size, 0.82);
} else if (pd > 1 && pd <= 1.5) {
return correction(size, 0.7);
} else if (pd > 1.5 && pd <= 2) {
return correction(size, 0.9);
} else if (pd > 2 && pd <= 3) {
return correction(size, 0.93);
} else if (pd > 3) {
return correction(size, 1);
}
};
export const SIZE = {
xxs: 10 * scale.fontScale,
xs: 12 * scale.fontScale,
sm: normalize(15) * scale.fontScale,
md: normalize(17) * scale.fontScale,
lg: normalize(24) * scale.fontScale,
xl: normalize(27) * scale.fontScale,
xxl: normalize(31) * scale.fontScale,
xxxl: normalize(34) * scale.fontScale,
};
export function updateSize() {
SIZE.xxs = 10 * scale.fontScale;
SIZE.xs = 12 * scale.fontScale;
SIZE.sm = normalize(15) * scale.fontScale;
SIZE.md = normalize(17) * scale.fontScale;
SIZE.lg = normalize(24) * scale.fontScale;
SIZE.xl = normalize(27) * scale.fontScale;
SIZE.xxl = normalize(31) * scale.fontScale;
SIZE.xxxl = normalize(34) * scale.fontScale;
ph = normalize(10) * scale.fontScale;
pv = normalize(10) * scale.fontScale;
}
export const br = 5; // border radius
export var ph = normalize(10); // padding horizontal
export var pv = normalize(10); // padding vertical
export const opacity = 0.5; // active opacity
// GLOBAL FONT
export const WEIGHT = {
light: 'DMSans-Regular',
regular: 'DMSans-Regular',
medium: 'DMSans-Regular',
semibold: 'DMSerifText-Regular',
bold: 'DMSerifText-Regular',
};
export function setColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
COLOR_SCHEME = {...colors, accent: accent.color, shade: accent.shade};
eSendEvent(eThemeUpdated);
return COLOR_SCHEME;
}
export async function getColorScheme(useSystemTheme) {
let accentColor;
let theme;
try {
accentColor = await MMKV.getStringAsync('accentColor');
} catch (e) {}
try {
theme = await MMKV.getStringAsync('theme');
} catch (e) {}
if (typeof accentColor !== 'string') {
MMKV.setStringAsync('accentColor', '#0560FF');
setAccentColor('#0560FF');
} else {
setAccentColor(accentColor);
}
if (useSystemTheme) {
StatusBar.setBarStyle(
Appearance.getColorScheme() === 'dark' ? 'light-content' : 'dark-content',
);
Appearance.getColorScheme() === 'dark'
? setColorScheme(COLOR_SCHEME_DARK)
: setColorScheme(COLOR_SCHEME_LIGHT);
return COLOR_SCHEME;
}
if (typeof theme !== 'string') {
MMKV.setStringAsync('theme', JSON.stringify({night: false}));
setColorScheme(COLOR_SCHEME_LIGHT);
} else {
theme = JSON.parse(theme);
theme.night
? setColorScheme(COLOR_SCHEME_DARK)
: setColorScheme(COLOR_SCHEME_LIGHT);
StatusBar.setBarStyle(theme.night ? 'light-content' : 'dark-content');
}
eSendEvent(eThemeUpdated);
return COLOR_SCHEME;
}
export function setAccentColor(color) {
ACCENT.color = color;
ACCENT.shade = color + '12';
return ACCENT;
}
export const onThemeUpdate = (func = () => {}) => {
return eSubscribeEvent(eThemeUpdated, func);
};
export const clearThemeUpdateListener = (func = () => {}) => {
return eUnSubscribeEvent(eThemeUpdated, func);
};

View File

@@ -1,8 +1,8 @@
import React from 'react';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE} from '../../common/common';
import {useTracked} from '../../provider';
import {PressableButton} from '../PressableButton';
import {SIZE} from "../../utils/SizeUtils";
export const ActionIcon = ({
onPress,
@@ -34,6 +34,7 @@ export const ActionIcon = ({
alignItems: 'center',
borderRadius: 100,
...customStyle,
}}>
<Icon name={name} style={iconStyle} color={color} size={size} />
</PressableButton>

View File

@@ -17,7 +17,7 @@ import {
ViewPropTypes,
} from 'react-native';
import {w} from '../../utils/utils';
import {dWidth} from '../../utils';
import {styles} from './styles';
var deviceHeight = getDeviceHeight();
@@ -514,7 +514,7 @@ export default class ActionSheet extends Component {
onScroll={this._onScroll}
style={styles.scrollView}
contentContainerStyle={{
width: w,
width: dWidth,
}}
data={['dummy']}
keyExtractor={(item) => item}

View File

@@ -1,10 +1,10 @@
import {StyleSheet} from 'react-native';
import { w } from '../../utils/utils';
import { dWidth } from '../../utils';
export const styles = StyleSheet.create({
scrollview: {
height: '100%',
width: w,
width: dWidth,
backgroundColor: 'transparent',
},
container: {

View File

@@ -11,39 +11,31 @@ import {
} from 'react-native';
import Share from 'react-native-share';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {
ACCENT,
COLORS_NOTE,
COLOR_SCHEME,
COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT,
opacity,
ph,
pv,
setColorScheme,
SIZE,
WEIGHT,
} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent, openVault} from '../../services/eventManager';
import {Actions} from '../../provider/Actions';
import {eSendEvent, openVault, ToastEvent} from '../../services/EventManager';
import {
eOpenLoginDialog,
eOpenMoveNoteDialog,
refreshNotesPage,
} from '../../services/events';
import {MMKV} from '../../utils/storage';
import {
db,
DDS,
hexToRGBA,
RGB_Linear_Shade,
timeConverter,
ToastEvent,
} from '../../utils/utils';
} from '../../utils/Events';
import {PremiumTag} from '../Premium/PremiumTag';
import {PressableButton} from '../PressableButton';
import {Toast} from '../Toast';
import {hexToRGBA, RGB_Linear_Shade} from "../../utils/ColorUtils";
import {timeConverter} from "../../utils/TimeUtils";
import {
ACCENT,
COLOR_SCHEME,
COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT,
COLORS_NOTE,
setColorScheme
} from "../../utils/Colors";
import {opacity, ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
import {MMKV} from "../../utils/MMKV";
const w = Dimensions.get('window').width;
const h = Dimensions.get('window').height;
@@ -82,7 +74,7 @@ export const ActionSheetComponent = ({
let newColors = setColorScheme(colors, accent);
StatusBar.setBarStyle(colors.night ? 'light-content' : 'dark-content');
dispatch({type: ACTIONS.THEME, colors: newColors});
dispatch({type: Actions.THEME, colors: newColors});
}
useEffect(() => {
@@ -111,7 +103,7 @@ export const ActionSheetComponent = ({
await db.notes.note(note.id).tag(tag);
setNote({...db.notes.note(note.id).data});
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
tagsInputRef.current?.setNativeProps({
text: '',
});
@@ -201,8 +193,8 @@ export const ActionSheetComponent = ({
if (!nodispatch) {
dispatch({type: type});
dispatch({type: ACTIONS.PINNED});
dispatch({type: ACTIONS.FAVORITES});
dispatch({type: Actions.PINNED});
dispatch({type: Actions.FAVORITES});
}
setNote({...toAdd});
};
@@ -212,8 +204,8 @@ export const ActionSheetComponent = ({
name: 'Add to',
icon: 'book-outline',
func: () => {
dispatch({type: ACTIONS.MODAL_NAVIGATOR, enabled: true});
dispatch({type: ACTIONS.SELECTED_ITEMS, item: note});
dispatch({type: Actions.MODAL_NAVIGATOR, enabled: true});
dispatch({type: Actions.SELECTED_ITEMS, item: note});
close();
setTimeout(() => {
eSendEvent(eOpenMoveNoteDialog);
@@ -277,7 +269,7 @@ export const ActionSheetComponent = ({
name: 'Restore',
icon: 'delete-restore',
func: async () => {
dispatch({type: ACTIONS.TRASH});
dispatch({type: Actions.TRASH});
localRefresh(note.type);
ToastEvent.show(
item.type === 'note' ? 'Note restored' : 'Notebook restored',
@@ -328,7 +320,7 @@ export const ActionSheetComponent = ({
} else {
await db.notebooks.notebook(note.id).pin();
}
dispatch({type: ACTIONS.PINNED});
dispatch({type: Actions.PINNED});
localRefresh(item.type);
},
close: false,
@@ -349,7 +341,7 @@ export const ActionSheetComponent = ({
} else {
await db.notebooks.notebook(note.id).favorite();
}
dispatch({type: ACTIONS.FAVORITES});
dispatch({type: Actions.FAVORITES});
localRefresh(item.type);
},
close: false,
@@ -374,9 +366,9 @@ export const ActionSheetComponent = ({
db.vault
.add(note.id)
.then(() => {
dispatch({type: ACTIONS.NOTES});
dispatch({type: Actions.NOTES});
eSendEvent(refreshNotesPage);
dispatch({type: ACTIONS.PINNED});
dispatch({type: Actions.PINNED});
close();
})
.catch(async (e) => {
@@ -410,7 +402,7 @@ export const ActionSheetComponent = ({
.note(note.id)
.untag(oldProps.tags[oldProps.tags.indexOf(tag)]);
localRefresh(oldProps.type);
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
} catch (e) {
localRefresh(oldProps.type);
}
@@ -464,7 +456,7 @@ export const ActionSheetComponent = ({
} else {
await db.notes.note(note.id).color(color.name);
}
dispatch({type: ACTIONS.COLORS});
dispatch({type: Actions.COLORS});
localRefresh(note.type);
}}
customStyle={{
@@ -611,7 +603,7 @@ export const ActionSheetComponent = ({
setRefreshing(true);
try {
let user = await db.user.get();
dispatch({type: ACTIONS.USER, user: user});
dispatch({type: Actions.USER, user: user});
await db.sync();
localRefresh();
ToastEvent.show('Note synced', 'success', 'local');
@@ -620,7 +612,7 @@ export const ActionSheetComponent = ({
} finally {
setRefreshing(false);
}
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.ALL});
}
};

View File

@@ -11,12 +11,14 @@ import {
} from 'react-native';
import {FlatList, TextInput} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {ACTIONS} from '../../provider/actions';
import {db, DDS, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {Button} from '../Button';
import {updateEvent} from '../DialogManager/recievers';
import {Toast} from '../Toast';
import {ToastEvent} from "../../services/EventManager";
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
let refs = [];
@@ -173,8 +175,8 @@ export class AddNotebookDialog extends React.Component {
});
}
this.close();
updateEvent({type: ACTIONS.NOTEBOOKS});
updateEvent({type: ACTIONS.PINNED});
updateEvent({type: Actions.NOTEBOOKS});
updateEvent({type: Actions.PINNED});
//ToastEvent.show('New notebook added', 'success', 'local');
};

View File

@@ -2,15 +2,17 @@ import React, {createRef} from 'react';
import {Modal, Text, TouchableOpacity, View} from 'react-native';
import {TextInput} from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {opacity, ph, pv, SIZE, WEIGHT} from '../../common/common';
import {getElevation, ToastEvent, db, DDS} from '../../utils/utils';
import {eSendEvent} from '../../services/eventManager';
import {eOnNewTopicAdded} from '../../services/events';
import {getElevation} from '../../utils';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eOnNewTopicAdded} from '../../utils/Events';
import {Toast} from '../Toast';
import {Button} from '../Button';
import BaseDialog from '../Dialog/base-dialog';
import DialogHeader from '../Dialog/dialog-header';
import DialogButtons from '../Dialog/dialog-buttons';
import {opacity, ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
export class AddTopicDialog extends React.Component {
constructor(props) {

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { ActivityIndicator, StyleSheet, Text } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { ph, pv, SIZE, WEIGHT } from '../../common/common';
import { useTracked } from '../../provider';
import { PressableButton } from '../PressableButton';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
export const Button = ({
height = 40,

View File

@@ -2,10 +2,11 @@ import React, {useEffect, useState} from 'react';
import {Keyboard, Platform, Text, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {DDS, getElevation} from '../../utils/utils';
import {getElevation} from '../../utils';
import {PressableButton} from '../PressableButton';
import {pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
export const ContainerBottomButton = ({title, onPress, color}) => {
const [state, dispatch] = useTracked();

View File

@@ -1,7 +1,7 @@
import React, {useEffect} from 'react';
import Animated, {Easing, useValue} from 'react-native-reanimated';
import {useTracked} from '../../provider';
import {Header} from '../header';
import {Header} from '../Header';
import {Search} from '../SearchInput';
export const ContainerTopSection = ({root}) => {
@@ -38,8 +38,9 @@ export const ContainerTopSection = ({root}) => {
},
],
}}>
<Header root={root} />
<Header root={root} />
<Search root={root} />
</Animated.View>
);

View File

@@ -1,9 +1,9 @@
import React, {useEffect, useState} from 'react';
import {Text, View} from 'react-native';
import {SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import { getElevation } from '../../utils/utils';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import { getElevation } from '../../utils';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
let contextTimeout = null;

View File

@@ -1,8 +1,8 @@
import React from 'react';
import {Text, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { SIZE, WEIGHT } from '../../common/common';
import {useTracked} from '../../provider';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
const DialogHeader = ({icon, title, paragraph}) => {
const [state, dispatch] = useTracked();

View File

@@ -1,24 +1,26 @@
import React, {Component} from 'react';
import {Modal, Text, TouchableOpacity, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {
eApplyChanges,
eClearEditor,
eCloseFullscreenEditor,
eOnLoadNote,
eOnNewTopicAdded,
} from '../../services/events';
import NavigationService from '../../services/NavigationService';
import {db, DDS, getElevation, history, ToastEvent} from '../../utils/utils';
} from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import {getElevation, history} from '../../utils';
import {Button} from '../Button';
import {dialogActions} from '../DialogManager/dialogActions';
import {dialogActions} from '../DialogManager/DialogActions';
import {updateEvent} from '../DialogManager/recievers';
import BaseDialog from './base-dialog';
import DialogButtons from './dialog-buttons';
import DialogHeader from './dialog-header';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
export class Dialog extends Component {
constructor(props) {
@@ -55,7 +57,7 @@ export class Dialog extends Component {
updateEvent({type: it.type});
}
}
updateEvent({type: ACTIONS.PINNED});
updateEvent({type: Actions.PINNED});
let message;
let notes = history.selectedItemsList.filter((o) => o.type === 'note');
@@ -99,15 +101,15 @@ export class Dialog extends Component {
await db.trash.restore(trashItem.id);
updateEvent({type: it.type});
}
updateEvent({type: ACTIONS.TRASH});
updateEvent({type: ACTIONS.PINNED});
updateEvent({type: Actions.TRASH});
updateEvent({type: Actions.PINNED});
ToastEvent.hide();
},
'Undo',
);
updateEvent({type: ACTIONS.CLEAR_SELECTION});
updateEvent({type: ACTIONS.SELECTION_MODE, enabled: false});
updateEvent({type: Actions.CLEAR_SELECTION});
updateEvent({type: Actions.SELECTION_MODE, enabled: false});
this.hide();
break;
@@ -122,9 +124,9 @@ export class Dialog extends Component {
await db.trash.delete(...ids);
updateEvent({type: ACTIONS.TRASH});
updateEvent({type: ACTIONS.CLEAR_SELECTION});
updateEvent({type: ACTIONS.SELECTION_MODE, enabled: false});
updateEvent({type: Actions.TRASH});
updateEvent({type: Actions.CLEAR_SELECTION});
updateEvent({type: Actions.SELECTION_MODE, enabled: false});
ToastEvent.show('Item permanantly deleted');
this.hide();
break;
@@ -144,17 +146,17 @@ export class Dialog extends Component {
}
case dialogActions.ACTION_EMPTY_TRASH: {
await db.trash.clear();
updateEvent({type: ACTIONS.TRASH});
updateEvent({type: Actions.TRASH});
updateEvent({type: ACTIONS.CLEAR_SELECTION});
updateEvent({type: ACTIONS.SELECTION_MODE, enabled: false});
updateEvent({type: Actions.CLEAR_SELECTION});
updateEvent({type: Actions.SELECTION_MODE, enabled: false});
ToastEvent.show('Trash cleared', 'error');
this.hide();
break;
}
case dialogActions.ACTION_EXIT_FULLSCREEN: {
updateEvent({type: ACTIONS.NOTES});
updateEvent({type: Actions.NOTES});
eSendEvent(eCloseFullscreenEditor);
this.hide();
break;
@@ -169,7 +171,7 @@ export class Dialog extends Component {
'success',
);
updateEvent({type: ACTIONS.TRASH});
updateEvent({type: Actions.TRASH});
this.hide();
break;
}

View File

@@ -1,4 +1,4 @@
import {eSendEvent} from '../../services/eventManager';
import {eSendEvent} from '../../services/EventManager';
import {
eCloseActionSheet,
eCloseAddNotebookDialog,
@@ -11,7 +11,7 @@ import {
eOpenMoveNoteDialog,
eOpenSimpleDialog,
eDispatchAction,
} from '../../services/events';
} from '../../utils/Events';
export const ActionSheetEvent = (
item,

View File

@@ -1,5 +1,5 @@
import {dialogActions} from './dialogActions';
import {timeConverter} from '../../utils/utils';
import {dialogActions} from './DialogActions';
import {timeConverter} from "../../utils/TimeUtils";
export const TEMPLATE_DELETE = type => {
return {

View File

@@ -5,7 +5,7 @@ import {
eSubscribeEvent,
eUnSubscribeEvent,
openVault,
} from '../../services/eventManager';
} from '../../services/EventManager';
import {
eCloseActionSheet,
eCloseAddNotebookDialog,
@@ -23,8 +23,7 @@ import {
eOpenMoveNoteDialog,
eOpenPremiumDialog,
eOpenSimpleDialog,
} from '../../services/events';
import {DDS, hexToRGBA} from '../../utils/utils';
} from '../../utils/Events';
import ActionSheet from '../ActionSheet';
import {ActionSheetComponent} from '../ActionSheetComponent';
import {AddNotebookDialog} from '../AddNotebookDialog';
@@ -41,7 +40,9 @@ import ProgressDialog from '../ProgressDialog';
import RecoveryKeyDialog from '../RecoveryKeyDialog';
import RestoreDialog from '../RestoreDialog';
import {VaultDialog} from '../VaultDialog';
import {TEMPLATE_DELETE, TEMPLATE_PERMANANT_DELETE} from './templates';
import {TEMPLATE_DELETE, TEMPLATE_PERMANANT_DELETE} from './Templates';
import {hexToRGBA} from "../../utils/ColorUtils";
import {DDS} from "../../services/DeviceDetection";
export class DialogManager extends Component {
constructor(props) {

View File

@@ -10,24 +10,27 @@ import {
import FileViewer from 'react-native-file-viewer';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import RNFetchBlob from 'rn-fetch-blob';
import {opacity, ph, pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import storage from '../../utils/storage';
import {DDS, getElevation, sleep, ToastEvent} from '../../utils/utils';
import {getElevation} from '../../utils';
import {Button} from '../Button/index';
import BaseDialog from '../Dialog/base-dialog';
import DialogHeader from '../Dialog/dialog-header';
import {Loading} from '../Loading';
import Seperator from '../Seperator';
import {sleep} from "../../utils/TimeUtils";
import {ToastEvent} from "../../services/EventManager";
import {opacity, ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
const {
eSubscribeEvent,
eUnSubscribeEvent,
} = require('../../services/eventManager');
} = require('../../services/EventManager');
const {
eOpenExportDialog,
eCloseExportDialog,
} = require('../../services/events');
} = require('../../utils/Events');
const ExportDialog = () => {
const [state, dispatch] = useTracked();

View File

@@ -1,9 +1,9 @@
import React, { createRef } from 'react';
import Menu, { MenuDivider, MenuItem } from 'react-native-material-menu';
import { SIZE, WEIGHT } from '../../common/common';
import { useTracked } from '../../provider';
import { ACTIONS } from '../../provider/actions';
import { Actions } from '../../provider/Actions';
import { ActionIcon } from '../ActionIcon';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
const menuRef = createRef();
export const HeaderMenu = () => {
const [state, dispatch] = useTracked();
@@ -51,7 +51,7 @@ export const HeaderMenu = () => {
color: colors.pri,
}}
onPress={() => {
dispatch({type: ACTIONS.NOTES, sort: null});
dispatch({type: Actions.NOTES, sort: null});
menuRef.current?.hide();
}}>
Default
@@ -62,7 +62,7 @@ export const HeaderMenu = () => {
color: colors.pri,
}}
onPress={() => {
dispatch({type: ACTIONS.NOTES, sort: 'abc'});
dispatch({type: Actions.NOTES, sort: 'abc'});
menuRef.current?.hide();
}}>
Alphabetical
@@ -73,7 +73,7 @@ export const HeaderMenu = () => {
color: colors.pri,
}}
onPress={() => {
dispatch({type: ACTIONS.NOTES, sort: 'year'});
dispatch({type: Actions.NOTES, sort: 'year'});
menuRef.current?.hide();
}}>
By year
@@ -84,7 +84,7 @@ export const HeaderMenu = () => {
color: colors.pri,
}}
onPress={() => {
dispatch({type: ACTIONS.NOTES, sort: 'month'});
dispatch({type: Actions.NOTES, sort: 'month'});
menuRef.current?.hide();
}}>
By month
@@ -95,7 +95,7 @@ export const HeaderMenu = () => {
color: colors.pri,
}}
onPress={() => {
dispatch({type: ACTIONS.NOTES, sort: 'week'});
dispatch({type: Actions.NOTES, sort: 'week'});
menuRef.current?.hide();
}}>
By week

View File

@@ -1,7 +1,7 @@
import React from 'react';
import {Text} from 'react-native';
import {SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
export const HeaderTitle = ({root}) => {
const [state, dispatch] = useTracked();

View File

@@ -2,15 +2,16 @@ import React from 'react';
import {ActivityIndicator, Platform, StyleSheet, View} from 'react-native';
import * as Animatable from 'react-native-animatable';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {SIZE} from '../../common/common';
import {useTracked} from '../../provider';
import {eSendEvent} from '../../services/eventManager';
import NavigationService from '../../services/NavigationService';
import {useHideHeader} from '../../utils/hooks';
import {DDS, w} from '../../utils/utils';
import {eSendEvent} from '../../services/EventManager';
import NavigationService from '../../services/Navigation';
import {useHideHeader} from '../../utils/Hooks';
import {dWidth} from '../../utils';
import {ActionIcon} from '../ActionIcon';
import {HeaderMenu} from './HeaderMenu';
import {HeaderTitle} from './HeaderTitle';
import {SIZE} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
export const Header = ({showSearch, root}) => {
const [state, dispatch] = useTracked();
@@ -37,6 +38,25 @@ export const Header = ({showSearch, root}) => {
overflow: 'hidden',
},
]}>
<View style={styles.leftBtnContainer}>
{!DDS.isTab ? (
<ActionIcon
testID="left_menu_button"
customStyle={styles.leftBtn}
onPress={onLeftButtonPress}
name={headerState.canGoBack ? 'arrow-left' : 'menu'}
size={SIZE.xxxl}
color={colors.pri}
iconStyle={{
marginLeft: headerState.canGoBack ? -5 : 0,
}}
/>
) : undefined}
{Platform.OS === 'android' ? <HeaderTitle root={root} /> : null}
</View>
{Platform.OS !== 'android' ? <HeaderTitle root={root} /> : null}
<Animatable.View
transition={['opacity']}
duration={300}
@@ -57,25 +77,6 @@ export const Header = ({showSearch, root}) => {
<ActivityIndicator size={25} color={colors.accent} />
</Animatable.View>
<View style={styles.leftBtnContainer}>
{!DDS.isTab ? (
<ActionIcon
testID="left_menu_button"
customStyle={styles.leftBtn}
onPress={onLeftButtonPress}
name={headerState.canGoBack ? 'arrow-left' : 'menu'}
size={SIZE.xxxl}
color={colors.pri}
iconStyle={{
marginLeft: headerState.canGoBack ? -5 : 0,
}}
/>
) : undefined}
{Platform.OS === 'android' ? <HeaderTitle root={root} /> : null}
</View>
{Platform.OS !== 'android' ? <HeaderTitle root={root} /> : null}
<View style={styles.rightBtnContainer}>
<Animatable.View
transition="opacity"
@@ -119,7 +120,7 @@ const styles = StyleSheet.create({
alignItems: 'center',
justifyContent: 'center',
zIndex: 999,
left: w / 2 - 20,
left: dWidth / 2 - 20,
top: -20,
width: 40,
height: 40,

View File

@@ -1,8 +1,8 @@
import React from 'react';
import {ActivityIndicator, StyleSheet, Text, View} from 'react-native';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {Button} from '../Button';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
export const Loading = ({
height = 150,

View File

@@ -5,31 +5,33 @@ import {TextInput} from 'react-native-gesture-handler';
import QRCode from 'react-native-qrcode-generator';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {opacity, ph, pv, SIZE, WEIGHT} from '../../common/common';
import {Button} from '../../components/Button';
import Seperator from '../../components/Seperator';
import {Toast} from '../../components/Toast';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {useTracked} from '../../provider/index';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
eUnSubscribeEvent, ToastEvent,
} from '../../services/EventManager';
import {
eCloseLoginDialog,
eOpenLoginDialog,
eStartSyncer,
refreshNotesPage,
} from '../../services/events';
} from '../../utils/Events';
import {
validateEmail,
validatePass,
validateUsername,
} from '../../services/validation';
import {db, DDS, getElevation, ToastEvent} from '../../utils/utils';
} from '../../services/Validation';
import {getElevation} from '../../utils';
import { ActionIcon } from '../ActionIcon';
import {Loading} from '../Loading';
import {opacity, ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
const LoginDialog = () => {
const [state, dispatch] = useTracked();
@@ -120,18 +122,18 @@ const LoginDialog = () => {
let user = await db.user.get();
if (!user) throw new Error('Username or password incorrect');
setStatus('Syncing your notes');
dispatch({type: ACTIONS.USER, user: user});
dispatch({type: ACTIONS.SYNCING, syncing: true});
dispatch({type: Actions.USER, user: user});
dispatch({type: Actions.SYNCING, syncing: true});
await db.sync();
eSendEvent(eStartSyncer);
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.ALL});
eSendEvent(refreshNotesPage);
setVisible(false);
ToastEvent.show(`Logged in as ${username}`, 'success', 'local');
} catch (e) {
ToastEvent.show(e.message, 'error', 'local');
} finally {
dispatch({type: ACTIONS.SYNCING, syncing: false});
dispatch({type: Actions.SYNCING, syncing: false});
setLoggingIn(false);
}
};
@@ -189,7 +191,7 @@ const LoginDialog = () => {
let k = await db.user.key();
setKey(k.key);
setStatus('Setting up crenditials');
dispatch({type: ACTIONS.USER, user: user});
dispatch({type: Actions.USER, user: user});
eSendEvent(eStartSyncer);
setModalVisible(true);
} catch (e) {

View File

@@ -1,12 +1,13 @@
import React, { useEffect } from 'react';
import { Text, View } from 'react-native';
import { COLORS_NOTE, SIZE } from '../../common/common';
import { useTracked } from '../../provider';
import { ACTIONS } from '../../provider/actions';
import { eSendEvent } from '../../services/eventManager';
import { refreshNotesPage } from '../../services/events';
import NavigationService from '../../services/NavigationService';
import { Actions } from '../../provider/Actions';
import { eSendEvent } from '../../services/EventManager';
import { refreshNotesPage } from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import { PressableButton } from '../PressableButton';
import {COLORS_NOTE} from "../../utils/Colors";
import {SIZE} from "../../utils/SizeUtils";
export const ColorSection = ({noTextMode}) => {
const [state, dispatch] = useTracked();
@@ -14,7 +15,7 @@ export const ColorSection = ({noTextMode}) => {
useEffect(() => {
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
}, []);
return (
@@ -40,18 +41,18 @@ export const ColorSection = ({noTextMode}) => {
color: item,
};
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.CONTAINER_BOTTOM_BUTTON,
type: Actions.CONTAINER_BOTTOM_BUTTON,
state: {
bottomButtonText: 'Create a new Note',
},
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: item.title,
},

View File

@@ -1,14 +1,15 @@
import React from 'react';
import {Text, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eClearSearch} from '../../services/events';
import NavigationService from '../../services/NavigationService';
import {DDS, showContext} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSendEvent} from '../../services/EventManager';
import {eClearSearch} from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import {showContext} from '../../utils';
import {PressableButton} from '../PressableButton';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
export const MenuListItem = ({item, index, noTextMode, ignore, testID}) => {
const [state, dispatch] = useTracked();
@@ -17,7 +18,7 @@ export const MenuListItem = ({item, index, noTextMode, ignore, testID}) => {
const _onPress = (event) => {
if (!ignore) {
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: item.name,
},

View File

@@ -1,11 +1,11 @@
import React, { useEffect } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { opacity, SIZE, WEIGHT } from '../../common/common';
import { useTracked } from '../../provider';
import { ACTIONS } from '../../provider/actions';
import { eSendEvent } from '../../services/eventManager';
import { refreshNotesPage } from '../../services/events';
import NavigationService from '../../services/NavigationService';
import { Actions } from '../../provider/Actions';
import { eSendEvent } from '../../services/EventManager';
import { refreshNotesPage } from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import {opacity, SIZE, WEIGHT} from "../../utils/SizeUtils";
export const TagsSection = () => {
@@ -14,7 +14,7 @@ export const TagsSection = () => {
useEffect(() => {
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
}, []);
return (<View
@@ -38,18 +38,18 @@ export const TagsSection = () => {
};
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.CONTAINER_BOTTOM_BUTTON,
type: Actions.CONTAINER_BOTTOM_BUTTON,
state: {
bottomButtonText:'Create a new Note',
},
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: item.title,
},

View File

@@ -1,6 +1,6 @@
import React, {useEffect, useState} from 'react';
import {Text} from 'react-native';
import {timeSince} from '../../utils/utils';
import {timeSince} from "../../utils/TimeUtils";
export const TimeSince = ({time}) => {
const [timeAgo, setTimeAgo] = useState(null);

View File

@@ -7,14 +7,16 @@ import {
View,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eOpenLoginDialog} from '../../services/events';
import {db, hexToRGBA, showContext, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eOpenLoginDialog} from '../../utils/Events';
import {showContext} from '../../utils';
import {PressableButton} from '../PressableButton';
import {TimeSince} from './TimeSince';
import {hexToRGBA} from "../../utils/ColorUtils";
import {pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
export const UserSection = ({noTextMode}) => {
const [state, dispatch] = useTracked();
@@ -22,7 +24,7 @@ export const UserSection = ({noTextMode}) => {
useEffect(() => {
console.log(user);
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
}, []);
return user && user.username ? (
@@ -66,13 +68,13 @@ export const UserSection = ({noTextMode}) => {
<TouchableOpacity
onPress={async () => {
dispatch({
type: ACTIONS.SYNCING,
type: Actions.SYNCING,
syncing: true,
});
try {
if (!user) {
let u = await db.user.get();
dispatch({type: ACTIONS.USER, user: u});
dispatch({type: Actions.USER, user: u});
}
await db.sync();
ToastEvent.show('Sync Complete', 'success');
@@ -80,10 +82,10 @@ export const UserSection = ({noTextMode}) => {
ToastEvent.show(e.message, 'error');
}
let u = await db.user.get();
dispatch({type: ACTIONS.USER, user: u});
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.USER, user: u});
dispatch({type: Actions.ALL});
dispatch({
type: ACTIONS.SYNCING,
type: Actions.SYNCING,
syncing: false,
});
}}

View File

@@ -10,27 +10,21 @@ import {
import {createAnimatableComponent} from 'react-native-animatable';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {
ACCENT,
COLOR_SCHEME,
COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT,
ph,
setColorScheme,
SIZE,
} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import NavigationService from '../../services/NavigationService';
import {sideMenuRef} from '../../utils/refs';
import {DDS, w} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import NavigationService from '../../services/Navigation';
import {sideMenuRef} from '../../utils/Refs';
import {dWidth} from '../../utils';
import {ColorSection} from './ColorSection';
import {MenuListItem} from './MenuListItem';
import {TagsSection} from './TagsSection';
import {UserSection} from './UserSection';
import {MMKV} from '../../utils/storage';
import Seperator from '../Seperator';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {ACCENT, COLOR_SCHEME, COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT, setColorScheme} from "../../utils/Colors";
import {ph, SIZE} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
import {MMKV} from "../../utils/MMKV";
export const Menu = ({
close = () => {},
@@ -46,7 +40,7 @@ export const Menu = ({
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent);
StatusBar.setBarStyle(colors.night ? 'light-content' : 'dark-content');
dispatch({type: ACTIONS.THEME, colors: newColors});
dispatch({type: Actions.THEME, colors: newColors});
}
const listItems = [

View File

@@ -3,28 +3,29 @@ import {Modal, Text, TouchableOpacity, View, SafeAreaView} from 'react-native';
import Animated, {Easing} from 'react-native-reanimated';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import WebView from 'react-native-webview';
import {normalize, SIZE} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
} from '../../services/EventManager';
import {
eApplyChanges,
eShowMergeDialog,
refreshNotesPage,
} from '../../services/events';
import {db, h} from '../../utils/utils';
} from '../../utils/Events';
import {dHeight} from '../../utils';
import {Button} from '../Button';
import {simpleDialogEvent, updateEvent} from '../DialogManager/recievers';
import {TEMPLATE_APPLY_CHANGES} from '../DialogManager/templates';
import {TEMPLATE_APPLY_CHANGES} from '../DialogManager/Templates';
import {normalize, SIZE} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
const {Value, timing} = Animated;
const firstWebViewHeight = new Value(h * 0.5 - 50);
const secondWebViewHeight = new Value(h * 0.5 - 50);
const firstWebViewHeight = new Value(dHeight * 0.5 - 50);
const secondWebViewHeight = new Value(dHeight * 0.5 - 50);
const primaryWebView = createRef();
const secondaryWebView = createRef();
let note = null;
@@ -36,13 +37,13 @@ function openEditorAnimation(
) {
let openConfig = {
duration: 300,
toValue: !siblingStatus ? h - 100 : h * 0.5 - 50,
toValue: !siblingStatus ? dHeight - 100 : dHeight * 0.5 - 50,
easing: Easing.inOut(Easing.ease),
};
let extendConfig = {
duration: 300,
toValue: h * 0.5 - 50,
toValue: dHeight * 0.5 - 50,
easing: Easing.inOut(Easing.ease),
};
@@ -61,7 +62,7 @@ function closeEditorAnimation(heightToAnimate, heightToExtend = null) {
let extendConfig = {
duration: 300,
toValue: h - 100,
toValue: dHeight - 100,
easing: Easing.inOut(Easing.ease),
};
if (heightToExtend) {
@@ -189,8 +190,8 @@ const MergeEditor = () => {
});
}
eSendEvent(refreshNotesPage);
updateEvent({type: ACTIONS.NOTES});
updateEvent({type: ACTIONS.FAVORITES});
updateEvent({type: Actions.NOTES});
updateEvent({type: Actions.FAVORITES});
close();
};

View File

@@ -9,14 +9,16 @@ import {
} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eOpenMoveNoteDialog} from '../../services/events';
import {db, DDS, getElevation, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSubscribeEvent, eUnSubscribeEvent, ToastEvent} from '../../services/EventManager';
import {eOpenMoveNoteDialog} from '../../utils/Events';
import {getElevation} from '../../utils';
import {PressableButton} from '../PressableButton';
import {Toast} from '../Toast';
import {pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
let newNotebookTitle = null;
let newTopicTitle = null;
@@ -64,8 +66,8 @@ const MoveNoteDialog = () => {
});
notebookInput.current?.clear();
notebookInput.current?.blur();
dispatch({type: ACTIONS.NOTEBOOKS});
dispatch({type: ACTIONS.PINNED});
dispatch({type: Actions.NOTEBOOKS});
dispatch({type: Actions.PINNED});
};
const addNewTopic = async () => {
@@ -75,8 +77,8 @@ const MoveNoteDialog = () => {
let res = await db.notebooks.notebook(expanded).topics.add(newTopicTitle);
dispatch({type: ACTIONS.NOTEBOOKS});
dispatch({type: ACTIONS.PINNED});
dispatch({type: Actions.NOTEBOOKS});
dispatch({type: Actions.PINNED});
topicInput.current?.clear();
topicInput.current?.blur();
newTopicTitle = null;
@@ -364,9 +366,9 @@ const MoveNoteDialog = () => {
},
...noteIds,
);
dispatch({type: ACTIONS.CLEAR_SELECTION});
dispatch({type: ACTIONS.NOTEBOOKS});
dispatch({type: ACTIONS.PINNED});
dispatch({type: Actions.CLEAR_SELECTION});
dispatch({type: Actions.NOTEBOOKS});
dispatch({type: Actions.PINNED});
close();
let notebookName = db.notebooks.notebook(
item.notebookId,

View File

@@ -1,10 +1,10 @@
import React from 'react';
import { Dimensions, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { ph, SIZE, WEIGHT } from '../../common/common';
import { timeSince } from '../../utils/utils';
import { ActionIcon } from '../ActionIcon';
import { ActionSheetEvent } from '../DialogManager/recievers';
import {timeSince} from "../../utils/TimeUtils";
import {ph, SIZE, WEIGHT} from "../../utils/SizeUtils";
const w = Dimensions.get('window').width;
const h = Dimensions.get('window').height;

View File

@@ -1,11 +1,11 @@
import React from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import NavigationService from '../../services/NavigationService';
import NavigationService from '../../services/Navigation';
import {ActionSheetEvent} from '../DialogManager/recievers';
import Seperator from '../Seperator';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
export const NotebookItem = ({
item,

View File

@@ -1,11 +1,13 @@
import React, {createRef} from 'react';
import {Text, View} from 'react-native';
import {SIZE, WEIGHT} from '../../common/common';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eClosePendingDialog, eOpenPendingDialog} from '../../services/events';
import {db, DDS, w} from '../../utils/utils';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {eClosePendingDialog, eOpenPendingDialog} from '../../utils/Events';
import {dWidth} from '../../utils';
import ActionSheet from '../ActionSheet';
import Seperator from '../Seperator';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
const actionSheet = createRef();
class PendingDialog extends React.Component {
@@ -74,7 +76,7 @@ class PendingDialog extends React.Component {
initialOffsetFromBottom={1}>
<View
style={{
width: DDS.isTab? 500 : w,
width: DDS.isTab? 500 : dWidth,
backgroundColor: colors.bg,
justifyContent: 'space-between',
paddingHorizontal: 12,

View File

@@ -2,13 +2,15 @@ import React, {createRef} from 'react';
import {ScrollView, Text, View} from 'react-native';
import * as RNIap from 'react-native-iap';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE, WEIGHT} from '../../common/common';
import {eSendEvent} from '../../services/eventManager';
import {eOpenLoginDialog, eOpenPendingDialog} from '../../services/events';
import {db, DDS, h, itemSkus, ToastEvent, w} from '../../utils/utils';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eOpenLoginDialog, eOpenPendingDialog} from '../../utils/Events';
import {dHeight, itemSkus, dWidth} from '../../utils';
import ActionSheet from '../ActionSheet';
import {Button} from '../Button';
import Seperator from '../Seperator';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
class PremiumDialog extends React.Component {
constructor(props) {
super(props);
@@ -93,7 +95,7 @@ class PremiumDialog extends React.Component {
initialOffsetFromBottom={1}>
<View
style={{
width: DDS.isTab ? 500 : w,
width: DDS.isTab ? 500 : dWidth,
backgroundColor: colors.bg,
justifyContent: 'space-between',
paddingHorizontal: 12,
@@ -123,7 +125,7 @@ class PremiumDialog extends React.Component {
}
style={{
width: '100%',
maxHeight: DDS.isTab ? h * 0.35 : h * 0.5,
maxHeight: DDS.isTab ? dHeight * 0.35 : dHeight * 0.5,
}}>
{[
{

View File

@@ -1,19 +1,20 @@
import React, {useEffect, useState} from 'react';
import {Modal, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {DDS, getElevation} from '../../utils/utils';
import {getElevation} from '../../utils';
import Seperator from '../Seperator';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
const {
eSubscribeEvent,
eUnSubscribeEvent,
} = require('../../services/eventManager');
} = require('../../services/EventManager');
const {
eOpenPremiumStatusDialog,
eClosePremiumStatusDialog,
} = require('../../services/events');
} = require('../../utils/Events');
const PremiumStatusDialog = () => {
const [state, dispatch] = useTracked();

View File

@@ -1,7 +1,7 @@
import React from 'react';
import {Text, View} from 'react-native';
import {WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {WEIGHT} from "../../utils/SizeUtils";
export const PremiumTag = ({pro}) => {
const [state, dispatch] = useTracked();

View File

@@ -1,7 +1,7 @@
import React from 'react';
import {Pressable} from 'react-native';
import {br} from '../../common/common';
import {hexToRGBA, RGB_Linear_Shade} from '../../utils/utils';
import {hexToRGBA, RGB_Linear_Shade} from "../../utils/ColorUtils";
import {br} from "../../utils/SizeUtils";
export const PressableButton = ({
color,

View File

@@ -1,12 +1,13 @@
import React, {useEffect, useState} from 'react';
import {Text, View} from 'react-native';
import {ph, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eOpenProgressDialog, eCloseProgressDialog} from '../../services/events';
import {DDS, getElevation} from '../../utils/utils';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {eOpenProgressDialog, eCloseProgressDialog} from '../../utils/Events';
import {getElevation} from '../../utils';
import BaseDialog from '../Dialog/base-dialog';
import {Loading} from '../Loading';
import {ph, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
const ProgressDialog = () => {
const [state, dispatch] = useTracked();

View File

@@ -4,14 +4,15 @@ import QRCode from 'react-native-qrcode-svg';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import RNFetchBlob from 'rn-fetch-blob';
import {LOGO_BASE64} from '../../assets/images/assets';
import {SIZE, WEIGHT} from '../../common/common';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eOpenRecoveryKeyDialog} from '../../services/events';
import {db, ToastEvent, w} from '../../utils/utils';
import {eSubscribeEvent, eUnSubscribeEvent, ToastEvent} from '../../services/EventManager';
import {eOpenRecoveryKeyDialog} from '../../utils/Events';
import {dWidth} from '../../utils';
import ActionSheet from '../ActionSheet';
import {Button} from '../Button';
import Seperator from '../Seperator';
import {Toast} from '../Toast';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
class RecoveryKeyDialog extends React.Component {
constructor(props) {
super(props);
@@ -92,7 +93,7 @@ class RecoveryKeyDialog extends React.Component {
initialOffsetFromBottom={1}>
<View
style={{
width: w,
width: dWidth,
backgroundColor: colors.bg,
justifyContent: 'space-between',
paddingHorizontal: 12,
@@ -146,7 +147,7 @@ class RecoveryKeyDialog extends React.Component {
{this.state.key ? (
<QRCode
getRef={this.svg}
size={w / 2.2}
size={dWidth / 2.2}
value={this.state.key}
logo={{uri: LOGO_BASE64}}
logoBorderRadius={10}
@@ -157,7 +158,7 @@ class RecoveryKeyDialog extends React.Component {
<View
style={{
alignItems: 'center',
width: w / 2.2,
width: dWidth / 2.2,
justifyContent: 'center',
}}>
<Button

View File

@@ -1,25 +1,24 @@
import React, {useEffect, useState} from 'react';
import {FlatList, Text, View} from 'react-native';
import {FlatList, Platform, Text, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import RNFetchBlob from 'rn-fetch-blob';
import {ph, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eCloseRestoreDialog, eOpenRestoreDialog} from '../../services/events';
import {Actions} from '../../provider/Actions';
import {eSubscribeEvent, eUnSubscribeEvent, ToastEvent} from '../../services/EventManager';
import {eCloseRestoreDialog, eOpenRestoreDialog} from '../../utils/Events';
import storage from '../../utils/storage';
import {
db,
DDS,
getElevation,
requestStoragePermission,
sleep,
ToastEvent,
} from '../../utils/utils';
} from '../../utils';
import {ActionIcon} from '../ActionIcon';
import {Button} from '../Button';
import BaseDialog from '../Dialog/base-dialog';
import {Loading} from '../Loading';
import {sleep} from "../../utils/TimeUtils";
import {ph, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
const RestoreDialog = () => {
const [state, dispatch] = useTracked();
@@ -51,17 +50,21 @@ const RestoreDialog = () => {
animation="slide"
visible={visible}
onShow={async () => {
let granted = await requestStoragePermission();
if (Platform.OS === "android") {
let granted = await storage.requestPermission();
if (!granted) {
ToastEvent.show('Storage permission required to check for backups.');
return;
}
await storage.checkAndCreateDir(
RNFetchBlob.fs.dirs.SDCardDir + '/Notesnook/backups',
);
let files = await RNFetchBlob.fs.lstat(
RNFetchBlob.fs.dirs.SDCardDir + '/Notesnook/backups',
);
}
let path =
Platform.OS === 'ios'
? RNFetchBlob.fs.dirs.DocumentDir + "/backups/'"
: RNFetchBlob.fs.dirs.SDCardDir + '/Notesnook/backups/';
await storage.checkAndCreateDir(path);
let files = await RNFetchBlob.fs.lstat(path);
console.log(files);
setFiles(files);
}}
@@ -214,14 +217,15 @@ const RestoreDialog = () => {
width={80}
height={30}
onPress={async () => {
let granted = await requestStoragePermission();
if (Platform.OS === 'android') {
let granted = storage.requestPermission();
if (!granted) {
ToastEvent.show(
'Restore Failed! Storage access denied',
'error',
);
ToastEvent.show('Restore Failed! Storage access denied');
return;
}
}
setRestoring(true);
let backup = await RNFetchBlob.fs.readFile(
'file:/' + item.path,
@@ -230,7 +234,7 @@ const RestoreDialog = () => {
await db.backup.import(backup);
await sleep(2000);
setRestoring(false);
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.ALL});
ToastEvent.show('Restore Complete!', 'success');
setVisible(false);
}}

View File

@@ -1,14 +1,16 @@
import React, {useEffect, useState} from 'react';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eClearSearch, eScrollEvent} from '../../services/events';
import {inputRef} from '../../utils/refs';
import {db, DDS, selection, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSubscribeEvent, eUnSubscribeEvent, ToastEvent} from '../../services/EventManager';
import {eClearSearch, eScrollEvent} from '../../utils/Events';
import {inputRef} from '../../utils/Refs';
import {selection} from '../../utils';
import Animated, {Easing} from 'react-native-reanimated';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {br, WEIGHT, SIZE} from '../../common/common';
import {TextInput, Text} from 'react-native';
import {br, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
const {Value, timing, block} = Animated;
let searchResult = [];
@@ -106,7 +108,7 @@ export const Search = (props) => {
text: '',
});
dispatch({
type: ACTIONS.SEARCH_RESULTS,
type: Actions.SEARCH_RESULTS,
results: {
results: [],
type: null,
@@ -146,7 +148,7 @@ export const Search = (props) => {
return;
} else {
dispatch({
type: ACTIONS.SEARCH_RESULTS,
type: Actions.SEARCH_RESULTS,
results: {
type,
results: searchResult,

View File

@@ -3,13 +3,13 @@ import {Text, TouchableOpacity, View} from 'react-native';
import Animated, {Easing, useValue} from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eOpenMoveNoteDialog, eOpenSimpleDialog} from '../../services/events';
import {db, ToastEvent} from '../../utils/utils';
import {TEMPLATE_DELETE} from '../DialogManager/templates';
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eOpenMoveNoteDialog, eOpenSimpleDialog} from '../../utils/Events';
import {TEMPLATE_DELETE} from '../DialogManager/Templates';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
export const SelectionHeader = () => {
// State
@@ -66,8 +66,8 @@ export const SelectionHeader = () => {
}}>
<TouchableOpacity
onPress={() => {
dispatch({type: ACTIONS.SELECTION_MODE, enabled: !selectionMode});
dispatch({type: ACTIONS.CLEAR_SELECTION});
dispatch({type: Actions.SELECTION_MODE, enabled: !selectionMode});
dispatch({type: Actions.CLEAR_SELECTION});
}}
hitSlop={{top: 20, bottom: 20, left: 50, right: 40}}
style={{
@@ -113,8 +113,8 @@ export const SelectionHeader = () => {
paddingRight: 0,
}}
onPress={() => {
dispatch({type: ACTIONS.SELECTION_MODE, enabled: false});
dispatch({type: ACTIONS.CLEAR_SELECTION});
dispatch({type: Actions.SELECTION_MODE, enabled: false});
dispatch({type: Actions.CLEAR_SELECTION});
eSendEvent(eOpenMoveNoteDialog);
}}>
<Icon color={colors.heading} name={'plus'} size={SIZE.xl} />
@@ -197,9 +197,9 @@ export const SelectionHeader = () => {
await db.trash.restore(...noteIds);
dispatch({type: ACTIONS.TRASH});
dispatch({type: ACTIONS.SELECTION_MODE, enabled: false});
dispatch({type: ACTIONS.CLEAR_SELECTION});
dispatch({type: Actions.TRASH});
dispatch({type: Actions.SELECTION_MODE, enabled: false});
dispatch({type: Actions.CLEAR_SELECTION});
ToastEvent.show('Restore complete', 'success');
}
}}>

View File

@@ -1,11 +1,13 @@
import React, {useEffect, useState} from 'react';
import {TouchableOpacity, View} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {db, getElevation, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {getElevation} from '../../utils';
import {PressableButton} from '../PressableButton';
import {ToastEvent} from "../../services/EventManager";
import {SIZE} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
const SelectionWrapper = ({
children,
@@ -41,12 +43,12 @@ const SelectionWrapper = ({
if (!item.id) return;
if (item.type === 'note') {
await db.notes.note(item.id).pin();
dispatch({type: ACTIONS.PINNED});
dispatch({type: ACTIONS.NOTES});
dispatch({type: Actions.PINNED});
dispatch({type: Actions.NOTES});
} else {
await db.notebooks.notebook(item.id).pin();
dispatch({type: ACTIONS.PINNED});
dispatch({type: ACTIONS.NOTEBOOKS});
dispatch({type: Actions.PINNED});
dispatch({type: Actions.NOTEBOOKS});
}
};
func();
@@ -66,7 +68,7 @@ const SelectionWrapper = ({
return (
<PressableButton
color={
currentEditingNote === item.dateCreated || pinned
currentEditingNote || pinned
? colors.shade
: background
? background
@@ -75,12 +77,12 @@ const SelectionWrapper = ({
onLongPress={onLongPress}
onPress={onPress}
selectedColor={
currentEditingNote === item.dateCreated || pinned
currentEditingNote || pinned
? colors.accent
: colors.nav
}
alpha={!colors.night ? -0.02 : 0.02}
opacity={currentEditingNote === item.dateCreated || pinned ? 0.12 : 1}
opacity={currentEditingNote || pinned ? 0.12 : 1}
customStyle={{
flexDirection: 'row',
justifyContent: 'space-between',
@@ -137,7 +139,7 @@ const SelectionWrapper = ({
<TouchableOpacity
activeOpacity={1}
onPress={() => {
dispatch({type: ACTIONS.SELECTED_ITEMS, item: item});
dispatch({type: Actions.SELECTED_ITEMS, item: item});
}}
style={{
justifyContent: 'center',

View File

@@ -2,13 +2,14 @@ import React, {useEffect, useMemo, useState} from 'react';
import NoteItem from '../../components/NoteItem';
import SelectionWrapper from '../../components/SelectionWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent, openVault} from '../../services/eventManager';
import {eShowMergeDialog, eOnLoadNote, eOnNoteEdited} from '../../services/events';
import {Actions} from '../../provider/Actions';
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent, openVault} from '../../services/EventManager';
import {eShowMergeDialog, eOnLoadNote, eOnNoteEdited} from '../../utils/Events';
import {simpleDialogEvent} from '../DialogManager/recievers';
import {TEMPLATE_TRASH} from '../DialogManager/templates';
import {openEditorAnimation} from '../../utils/animations';
import {db, DDS} from '../../utils/utils';
import {TEMPLATE_TRASH} from '../DialogManager/Templates';
import {openEditorAnimation} from '../../utils/Animations';
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
@@ -53,9 +54,9 @@ export const NoteItemWrapper = ({
const onLongPress = () => {
if (!selectionMode) {
dispatch({type: ACTIONS.SELECTION_MODE, enabled: true});
dispatch({type: Actions.SELECTION_MODE, enabled: true});
}
dispatch({type: ACTIONS.SELECTED_ITEMS, item: item});
dispatch({type: Actions.SELECTED_ITEMS, item: item});
};
const onPress = async () => {

View File

@@ -2,8 +2,8 @@ import React, {useMemo} from 'react';
import {NotebookItem} from '../../components/NotebookItem';
import SelectionWrapper from '../../components/SelectionWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import NavigationService from '../../services/NavigationService';
import {Actions} from '../../provider/Actions';
import NavigationService from '../../services/Navigation';
export const NotebookItemWrapper = ({
item,
@@ -22,13 +22,13 @@ export const NotebookItemWrapper = ({
const onLongPress = () => {
if (!selectionMode) {
dispatch({
type: ACTIONS.SELECTION_MODE,
type: Actions.SELECTION_MODE,
enabled: !selectionMode,
});
}
dispatch({
type: ACTIONS.SELECTED_ITEMS,
type: Actions.SELECTED_ITEMS,
item: item,
});
};
@@ -39,20 +39,20 @@ export const NotebookItemWrapper = ({
return;
}
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: item.title,
},
});
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
canGoBack: true,
menu: false,
},
});
dispatch({
type: ACTIONS.CONTAINER_BOTTOM_BUTTON,
type: Actions.CONTAINER_BOTTOM_BUTTON,
state: {
bottomButtonText: 'Add new topic',
},

View File

@@ -3,13 +3,14 @@ import {Platform, RefreshControl, StyleSheet, Text, useWindowDimensions, View} f
import {initialWindowMetrics} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
import {COLORS_NOTE, SIZE, WEIGHT} from '../../common/common';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eClearSearch, eOpenLoginDialog, eScrollEvent,} from '../../services/events';
import {db, ToastEvent} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eClearSearch, eOpenLoginDialog, eScrollEvent,} from '../../utils/Events';
import {PressableButton} from '../PressableButton';
import {COLORS_NOTE} from "../../utils/Colors";
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
const header = {
type: 'MAIN_HEADER',
@@ -82,7 +83,7 @@ const SimpleList = ({
const _onRefresh = useCallback(async () => {
if (Platform.OS === 'ios') {
dispatch({
type: ACTIONS.SYNCING,
type: Actions.SYNCING,
syncing: true,
});
} else {
@@ -90,7 +91,7 @@ const SimpleList = ({
}
try {
let user = await db.user.get();
dispatch({type: ACTIONS.USER, user: user});
dispatch({type: Actions.USER, user: user});
await db.sync();
ToastEvent.show('Sync Complete', 'success');
} catch (e) {
@@ -107,7 +108,7 @@ const SimpleList = ({
} finally {
if (Platform.OS === 'ios') {
dispatch({
type: ACTIONS.SYNCING,
type: Actions.SYNCING,
syncing: false,
});
} else {
@@ -116,7 +117,7 @@ const SimpleList = ({
if (refreshCallback) {
refreshCallback();
}
dispatch({type: ACTIONS.ALL});
dispatch({type: Actions.ALL});
}
}, []);

View File

@@ -2,11 +2,13 @@ import React, {useEffect, useState} from 'react';
import {Keyboard, Text, TouchableOpacity, View} from 'react-native';
import Animated, {Easing, useValue} from 'react-native-reanimated';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {SIZE} from '../../common/common';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eHideToast, eShowToast} from '../../services/events';
import {DDS, getElevation, sleep} from '../../utils/utils';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/EventManager';
import {eHideToast, eShowToast} from '../../utils/Events';
import {getElevation} from '../../utils';
import {sleep} from "../../utils/TimeUtils";
import {SIZE} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
const {spring, timing} = Animated;
const toastMessages = [];

View File

@@ -3,27 +3,29 @@ import {Modal, Text, View} from 'react-native';
import {TextInput} from 'react-native-gesture-handler';
import Share from 'react-native-share';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {ph, pv, SIZE, WEIGHT} from '../../common/common';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
eUnSubscribeEvent, ToastEvent,
} from '../../services/EventManager';
import {
eCloseVaultDialog,
eOnLoadNote,
eOpenVaultDialog,
refreshNotesPage,
} from '../../services/events';
import {openEditorAnimation} from '../../utils/animations';
import {db, DDS, getElevation, ToastEvent} from '../../utils/utils';
} from '../../utils/Events';
import {openEditorAnimation} from '../../utils/Animations';
import {getElevation} from '../../utils';
import {Button} from '../Button/index';
import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogHeader from '../Dialog/dialog-header';
import {updateEvent} from '../DialogManager/recievers';
import {Toast} from '../Toast';
import {ph, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
const passInputRef = createRef();
const confirmPassRef = createRef();
@@ -78,7 +80,7 @@ export class VaultDialog extends Component {
};
close = () => {
updateEvent({type: ACTIONS.NOTES});
updateEvent({type: Actions.NOTES});
this.password = null;
this.confirmPassword = null;
@@ -181,8 +183,8 @@ export class VaultDialog extends Component {
}
async _deleteNote() {
await db.notes.delete(this.state.note.id);
updateEvent({type: ACTIONS.NOTES});
updateEvent({type: ACTIONS.FAVORITES});
updateEvent({type: Actions.NOTES});
updateEvent({type: Actions.FAVORITES});
eSendEvent(refreshNotesPage);
this.close();
ToastEvent.show('Note deleted', 'success', 'local');

View File

@@ -0,0 +1,68 @@
import * as React from "react";
import {eSubscribeEvent, eUnSubscribeEvent} from "../services/EventManager";
import {eCloseSideMenu, eOpenSideMenu} from "../utils/Events";
import {NavigationContainer} from "@react-navigation/native";
import {sideMenuRef} from "../utils/Refs";
import {Dimensions} from "react-native";
import {NavigatorStack} from "./NavigatorStack";
import {Menu} from "../components/Menu";
import NavigationService from "../services/Navigation";
import {createDrawerNavigator} from '@react-navigation/drawer';
import {DDS} from "../services/DeviceDetection";
const Drawer = createDrawerNavigator();
export const NavigationStack = ({component = NavigatorStack}) => {
const [locked, setLocked] = React.useState(false);
const setGestureDisabled = () => {
setLocked(true);
};
const setGestureEnabled = () => {
setLocked(false);
};
React.useEffect(() => {
eSubscribeEvent(eOpenSideMenu, setGestureEnabled);
eSubscribeEvent(eCloseSideMenu, setGestureDisabled);
return () => {
eUnSubscribeEvent(eOpenSideMenu, setGestureEnabled);
eUnSubscribeEvent(eCloseSideMenu, setGestureDisabled);
};
}, []);
return (
<NavigationContainer ref={sideMenuRef}>
<Drawer.Navigator
screenOptions={{
swipeEnabled: locked ? false : true,
}}
drawerStyle={{
width: DDS.isTab && !DDS.isSmallTab
? Dimensions.get('window').width * 0.05
: DDS.isSmallTab
? '40%'
: Dimensions.get('window').width * 0.75,
borderRightWidth: 0,
}}
edgeWidth={200}
drawerType={DDS.isTab || DDS.isSmallTab ? 'permanent' : 'slide'}
drawerContent={DrawerComponent}
initialRouteName="Main">
<Drawer.Screen name="Main" component={component}/>
</Drawer.Navigator>
</NavigationContainer>
);
};
const DrawerComponent = (props) => {
return (
<Menu
menuProps={props}
hide={false}
noTextMode={DDS.isTab && !DDS.isSmallTab}
close={() => NavigationService.closeDrawer()}
/>
);
};

View File

@@ -0,0 +1,54 @@
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import * as React from 'react';
import Container from '../components/Container';
import {rootNavigatorRef} from '../utils/Refs';
import Favorites from '../views/Favorites';
import Folders from '../views/Folders';
import Home from '../views/Home';
import Notebook from '../views/Notebook';
import Notes from '../views/Notes';
import Settings from '../views/Settings';
import Tags from '../views/Tags';
import Trash from '../views/Trash';
const Stack = createStackNavigator();
export const NavigatorStack = () => {
return (
<Container root={true}>
<NavigationContainer independent={true} ref={rootNavigatorRef}>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
animationEnabled: false,
gestureEnabled: false,
cardOverlayEnabled: false,
cardShadowEnabled: false,
}}>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen
initialParams={{
title: 'Notebooks',
canGoBack: false,
root: true,
}}
name="Folders"
component={Folders}
/>
<Stack.Screen name="Favorites" component={Favorites} />
<Stack.Screen name="Trash" component={Trash} />
<Stack.Screen name="Notes" component={Notes} />
<Stack.Screen name="Tags" component={Tags} />
<Stack.Screen name="Notebook" component={Notebook} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
</Container>
);
};

View File

@@ -1,4 +1,4 @@
export const ACTIONS = {
export const Actions = {
NOTES: 'note',
NOTEBOOKS: 'notebook',
TRASH: 'trash',

View File

@@ -1,12 +1,13 @@
import { eSendEvent } from '../services/eventManager';
import { eCloseSideMenu, eOpenSideMenu } from '../services/events';
import { eSendEvent } from '../services/EventManager';
import { eCloseSideMenu, eOpenSideMenu } from '../utils/Events';
import storage from '../utils/storage';
import { db, history } from '../utils/utils';
import { ACTIONS } from './actions';
import { history} from '../utils/index';
import { Actions } from './Actions';
import {db} from "../utils/DB";
export const reducer = (state, action) => {
switch (action.type) {
case ACTIONS.ALL: {
case Actions.ALL: {
let notes = db.notes.pinned;
let notebooks = db.notebooks.pinned;
@@ -24,13 +25,13 @@ export const reducer = (state, action) => {
colorNotes: db.colors.all,
};
}
case ACTIONS.SYNCING: {
case Actions.SYNCING: {
return {
...state,
syncing: action.syncing,
};
}
case ACTIONS.CLEAR_ALL: {
case Actions.CLEAR_ALL: {
storage.clear();
return {
...state,
@@ -47,7 +48,7 @@ export const reducer = (state, action) => {
user: null,
};
}
case ACTIONS.NOTES:
case Actions.NOTES:
let notes;
if (action.sort) {
notes = db.notes.group(action.sort);
@@ -60,38 +61,38 @@ export const reducer = (state, action) => {
notes: notes,
loading: false,
};
case ACTIONS.THEME: {
case Actions.THEME: {
return {
...state,
colors: action.colors,
};
}
case ACTIONS.USER: {
case Actions.USER: {
let user = action.user;
return {
...state,
user: user,
};
}
case ACTIONS.NOTEBOOKS: {
case Actions.NOTEBOOKS: {
return {
...state,
notebooks: db.notebooks.all,
};
}
case ACTIONS.SETTINGS: {
case Actions.SETTINGS: {
return {
...state,
settings: action.settings,
};
}
case ACTIONS.TRASH: {
case Actions.TRASH: {
return {
...state,
trash: db.trash.all,
};
}
case ACTIONS.PINNED: {
case Actions.PINNED: {
let notes = db.notes.pinned;
let notebooks = db.notebooks.pinned;
@@ -103,31 +104,31 @@ export const reducer = (state, action) => {
},
};
}
case ACTIONS.CURRENT_SCREEN: {
case Actions.CURRENT_SCREEN: {
return {
...state,
currentScreen: action.screen,
};
}
case ACTIONS.TAGS: {
case Actions.TAGS: {
return {
...state,
tags: db.tags.all,
};
}
case ACTIONS.FAVORITES: {
case Actions.FAVORITES: {
return {
...state,
favorites: db.notes.favorites,
};
}
case ACTIONS.COLORS: {
case Actions.COLORS: {
return {
...state,
colorNotes: db.colors.all,
};
}
case ACTIONS.SELECTION_MODE: {
case Actions.SELECTION_MODE: {
if (action.enabled) {
eSendEvent(eCloseSideMenu);
} else {
@@ -139,13 +140,13 @@ export const reducer = (state, action) => {
selectionMode: action.enabled,
};
}
case ACTIONS.SELECT_ALL: {
case Actions.SELECT_ALL: {
return {
...state,
selectedItemsList: action.selected,
};
}
case ACTIONS.SELECTED_ITEMS: {
case Actions.SELECTED_ITEMS: {
let selectedItems = [...state.selectedItemsList];
if (selectedItems.includes(action.item)) {
selectedItems.splice(selectedItems.indexOf(action.item), 1);
@@ -162,7 +163,7 @@ export const reducer = (state, action) => {
selectionMode: selectedItems.length > 0 ? state.selectionMode : false,
};
}
case ACTIONS.CLEAR_SELECTION: {
case Actions.CLEAR_SELECTION: {
history.selectedItemsList = [];
eSendEvent(eOpenSideMenu);
return {
@@ -170,25 +171,25 @@ export const reducer = (state, action) => {
selectedItemsList: [],
};
}
case ACTIONS.MODAL_NAVIGATOR: {
case Actions.MODAL_NAVIGATOR: {
return {
...state,
preventDefaultMargins: action.enabled,
};
}
case ACTIONS.LOGIN_NAVIGATOR: {
case Actions.LOGIN_NAVIGATOR: {
return {
...state,
isLoginNavigator: action.enabled,
};
}
case ACTIONS.CURRENT_EDITING_NOTE: {
case Actions.CURRENT_EDITING_NOTE: {
return {
...state,
currentEditingNote: action.id,
};
}
case ACTIONS.SEARCH_RESULTS: {
case Actions.SEARCH_RESULTS: {
let results = action.results;
return {
@@ -196,7 +197,7 @@ export const reducer = (state, action) => {
searchResults: {...results},
};
}
case ACTIONS.HEADER_STATE: {
case Actions.HEADER_STATE: {
let header = {
...state.headerState,
...action.state,
@@ -206,7 +207,7 @@ export const reducer = (state, action) => {
headerState: header,
};
}
case ACTIONS.SEARCH_STATE: {
case Actions.SEARCH_STATE: {
let stat = {
...state.searchState,
...action.state,
@@ -217,13 +218,13 @@ export const reducer = (state, action) => {
searchState: stat,
};
}
case ACTIONS.CONTAINER_STATE: {
case Actions.CONTAINER_STATE: {
return {
...state,
containerState: action.state,
};
}
case ACTIONS.HEADER_TEXT_STATE: {
case Actions.HEADER_TEXT_STATE: {
let stat ={
...state.headerTextState,
...action.state,
@@ -233,13 +234,13 @@ export const reducer = (state, action) => {
headerTextState: stat,
};
}
case ACTIONS.HEADER_VERTICAL_MENU: {
case Actions.HEADER_VERTICAL_MENU: {
return {
...state,
headerVerticalMenu: action.state,
};
}
case ACTIONS.CONTAINER_BOTTOM_BUTTON: {
case Actions.CONTAINER_BOTTOM_BUTTON: {
let containerBottomButton = {
...state.containerBottomButton,
...action.state,

View File

@@ -1,7 +1,7 @@
import {useReducer} from 'react';
import {createContainer} from 'react-tracked';
import {reducer} from './reducer';
import {defaultState} from './defaultState';
import {reducer} from './Reducer';
import {defaultState} from './DefaultState';
const useValue = () => useReducer(reducer, defaultState);

View File

@@ -1,77 +0,0 @@
import {useTrackedState} from '.';
const useAppContext = () => {
const state = useTrackedState();
/*
// Themeing
async function updateAppTheme(colors = state.colors) {
let newColors = await getColorScheme(colors);
dispatch(draft => {
draft.colors = {...newColors};
});
}
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent);
StatusBar.setBarStyle(newColors.night ? 'light-content' : 'dark-content');
dispatch(draft => {
draft.colors = {...newColors};
});
}
function changeAccentColor(accentColor) {
ACCENT.color = accentColor;
ACCENT.shade = accentColor + '12';
changeColorScheme();
}
// Handling Selection Items
function changeSelectionMode(enabled) {
dispatch(draft => {
draft.selectionMode = enabled;
if (!enabled) {
draft.selectedItemsList = [...[]];
}
});
}
function updateSelectionList(item) {
let selectedItems = [...state.selectedItemsList];
if (selectedItems.includes(item)) {
selectedItems.splice(selectedItems.indexOf(item), 1);
} else {
selectedItems.push(item);
}
dispatch(draft => {
draft.selectedItemsList = selectedItems;
});
}
// Database Control
function updateDB() {
let notes = db.groupNotes();
let notebooks = db.getNotebooks();
let trash = db.getTrash();
let favorites = db.getFavorites();
let pinned = db.getPinned();
dispatch(draft => {
draft.notes = notes;
draft.notebooks = notebooks;
draft.trash = trash;
draft.favorites = favorites;
draft.pinned = pinned;
});
} */
return {
...state,
};
};
export {useAppContext};

View File

@@ -1,19 +1,11 @@
import {Dimensions, PixelRatio, Platform} from 'react-native';
import DeviceInfo from 'react-native-device-info';
let windowSize = Dimensions.get('window');
export class DeviceDetectionService {
constructor() {
this.pixelDensity = PixelRatio.get();
this.width = windowSize.width;
this.height = windowSize.height;
this.adjustedWidth = this.width * this.pixelDensity;
this.adjustedHeight = this.height * this.pixelDensity;
this.isPhoneOrTablet();
this.isIosOrAndroid();
this.detectIphoneX();
this.checkSmallTab();
this.setNewValues();
}
setNewValues() {
@@ -33,24 +25,16 @@ export class DeviceDetectionService {
let dpi = this.pixelDensity * 160;
let deviceWidthInInches = this.adjustedWidth / dpi;
let deviceHeightInInches = this.adjustedHeight / dpi;
let diagonalSize = Math.sqrt(
return Math.sqrt(
Math.pow(deviceWidthInInches, 2) + Math.pow(deviceHeightInInches, 2),
);
return diagonalSize;
};
checkSmallTab(orientation) {
this.width = Dimensions.get('screen').width;
this.height = Dimensions.get('screen').height;
let deviceSize = this.getDeviceSize();
console.log(
'device size',
deviceSize,
this.width,
this.height,
deviceSize < 9,
DeviceInfo.isTablet(),
);
if (DeviceInfo.isTablet() && (orientation === "PORTRAIT" || deviceSize < 9)) {
console.log('small tab');
this.isTab = true;
@@ -111,15 +95,11 @@ export class DeviceDetectionService {
}
detectIphoneX() {
if (
Platform.OS === 'ios' &&
this.isIphoneX = Platform.OS === 'ios' &&
!Platform.isTVOS &&
!Platform.isTVOS &&
(windowSize.height === 812 || windowSize.width === 812)
) {
this.isIphoneX = true;
} else {
this.isIphoneX = false;
}
(windowSize.height === 812 || windowSize.width === 812);
}
}
export const DDS = new DeviceDetectionService();

View File

@@ -0,0 +1,70 @@
import {DeviceEventEmitter} from 'react-native';
import {eHideToast, eOpenVaultDialog, eShowToast} from '../utils/Events';
export const eSubscribeEvent = (eventName, action) => {
DeviceEventEmitter.addListener(eventName, action);
};
export const eUnSubscribeEvent = (eventName, action) => {
DeviceEventEmitter.removeListener(eventName, action);
};
export const eSendEvent = (eventName, data) => {
DeviceEventEmitter.emit(eventName, data);
};
export const openVault = (
item,
novault = false,
locked = false,
permanant = false,
editor = false,
share = false,
deleteNote = false,
) => {
eSendEvent(eOpenVaultDialog, {
item,
novault,
locked,
permanant,
goToEditor: editor,
share,
deleteNote,
});
};
export const ToastEvent = {
show: (
message,
type = 'error',
context = 'global',
duration = 3000,
func = null,
actionText = '',
) => {
eSendEvent(eShowToast, {
message,
type,
context,
duration,
func,
actionText,
});
},
hide: (
message,
type = 'error',
context = 'global',
duration = 3000,
func = null,
actionText = '',
) => {
eSendEvent(eHideToast, {
message,
type,
context,
duration,
func,
actionText,
});
},
};

View File

@@ -0,0 +1,94 @@
import {Platform} from "react-native";
import {db} from "../utils/DB";
import RNFetchBlob from "rn-fetch-blob";
import {ToastEvent} from "./EventManager";
import he from "he";
import RNHTMLtoPDF from "react-native-html-to-pdf";
import Storage from "../utils/Storage";
const dirs = RNFetchBlob.fs.dirs;
export async function saveToPDF(note) {
let androidSavePath = '/Notesnook/exported/PDF';
if (Platform.OS === 'android') {
let hasPermission = await Storage.requestPermission();
if (!hasPermission) {
ToastEvent.show('Failed to get storage permission');
return null;
}
} else {
await Storage.checkAndCreateDir (dirs.DocumentDir + '/exported/PDF/');
}
let html = await db.notes.note(note).export('html');
html = he.decode(html);
let options = {
html: html,
fileName:
Platform.OS === 'ios' ? '/exported/PDF/' + note.title : note.title,
directory: Platform.OS === 'ios' ? 'Documents' : androidSavePath,
};
let res = await RNHTMLtoPDF.convert(options);
return {
filePath: res.filePath,
type: 'application/pdf',
name: 'PDF',
};
}
export async function saveToMarkdown(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Markdown/'
: dirs.SDCardDir + '/Notesnook/exported/Markdown/';
await Storage.checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('md');
let path = savePath + note.title + '.md';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/markdown',
name: 'Markdown',
};
}
export async function saveToText(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Text/'
: dirs.SDCardDir + '/Notesnook/exported/Text/';
await Storage.checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('txt');
let path = savePath + note.title + '.txt';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/plain',
name: 'Text',
};
}
export async function saveToHTML(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Html/'
: dirs.SDCardDir + '/Notesnook/exported/Html/';
await Storage.checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('html');
let path = savePath + note.title + '.html';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/html',
name: 'Html',
};
}

View File

@@ -1,5 +1,5 @@
import { DrawerActions, StackActions } from '@react-navigation/native';
import { rootNavigatorRef, sideMenuRef } from '../utils/refs';
import { rootNavigatorRef, sideMenuRef } from '../utils/Refs';
function navigate(name, params) {

View File

@@ -1,113 +0,0 @@
import {createDrawerNavigator} from '@react-navigation/drawer';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import * as React from 'react';
import {Dimensions} from 'react-native';
import Container from '../components/Container';
import {Menu} from '../components/Menu';
import {rootNavigatorRef, sideMenuRef} from '../utils/refs';
import {DDS, w} from '../utils/utils';
import Favorites from '../views/Favorites';
import Folders from '../views/Folders';
import Home from '../views/Home/index';
import Notebook from '../views/Notebook';
import Notes from '../views/Notes';
import Settings from '../views/Settings';
import Tags from '../views/Tags';
import Trash from '../views/Trash';
import {eSubscribeEvent, eUnSubscribeEvent} from './eventManager';
import {eCloseSideMenu, eOpenSideMenu} from './events';
import NavigationService from './NavigationService';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
export const MainComponent = () => {
return (
<Container root={true}>
<NavigationContainer independent={true} ref={rootNavigatorRef}>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
animationEnabled: false,
gestureEnabled: false,
cardOverlayEnabled: false,
cardShadowEnabled: false,
}}>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen
initialParams={{
title: 'Notebooks',
canGoBack: false,
root: true,
}}
name="Folders"
component={Folders}
/>
<Stack.Screen name="Favorites" component={Favorites} />
<Stack.Screen name="Trash" component={Trash} />
<Stack.Screen name="Notes" component={Notes} />
<Stack.Screen name="Tags" component={Tags} />
<Stack.Screen name="Notebook" component={Notebook} />
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
</Container>
);
};
const DrawerComponent = (props) => {
return (
<Menu
menuProps={props}
hide={false}
noTextMode={DDS.isTab && !DDS.isSmallTab}
close={() => NavigationService.closeDrawer()}
/>
);
};
export const NavigationStack = ({component = MainComponent}) => {
const [locked, setLocked] = React.useState(false);
const setGestureDisabled = () => {
setLocked(true);
};
const setGestureEnabled = () => {
setLocked(false);
};
React.useEffect(() => {
eSubscribeEvent(eOpenSideMenu, setGestureEnabled);
eSubscribeEvent(eCloseSideMenu, setGestureDisabled);
return () => {
eUnSubscribeEvent(eOpenSideMenu, setGestureEnabled);
eUnSubscribeEvent(eCloseSideMenu, setGestureDisabled);
};
}, []);
return (
<NavigationContainer ref={sideMenuRef}>
<Drawer.Navigator
screenOptions={{
swipeEnabled: locked ? false : true,
}}
drawerStyle={{
width: DDS.isTab && !DDS.isSmallTab
? Dimensions.get('window').width * 0.05
: DDS.isSmallTab
? '40%'
: Dimensions.get('window').width * 0.75,
borderRightWidth: 0,
}}
edgeWidth={200}
drawerType={DDS.isTab || DDS.isSmallTab ? 'permanent' : 'slide'}
drawerContent={DrawerComponent}
initialRouteName="Main">
<Drawer.Screen name="Main" component={component} />
</Drawer.Navigator>
</NavigationContainer>
);
};

View File

@@ -1,4 +1,4 @@
import {db} from '../utils/utils';
import {db} from "../utils/DB";
let regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;

View File

@@ -1,34 +0,0 @@
import {DeviceEventEmitter} from 'react-native';
import {eOpenVaultDialog} from './events';
export const eSubscribeEvent = (eventName, action) => {
DeviceEventEmitter.addListener(eventName, action);
};
export const eUnSubscribeEvent = (eventName, action) => {
DeviceEventEmitter.removeListener(eventName, action);
};
export const eSendEvent = (eventName, data) => {
DeviceEventEmitter.emit(eventName, data);
};
export const openVault = (
item,
novault = false,
locked = false,
permanant = false,
editor = false,
share = false,
deleteNote = false,
) => {
eSendEvent(eOpenVaultDialog, {
item,
novault,
locked,
permanant,
goToEditor: editor,
share,
deleteNote,
});
};

View File

@@ -1,6 +1,6 @@
import Animated, {Easing} from 'react-native-reanimated';
import {Dimensions} from 'react-native';
import {editing} from './utils';
import {editing} from './index';
const {Value, timing} = Animated;

View File

@@ -0,0 +1,121 @@
import {Appearance, StatusBar} from "react-native";
import {COLOR_SCHEME, COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT, setAccentColor, setColorScheme} from "./Colors";
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent} from "../services/EventManager";
import {eThemeUpdated} from "./Events";
import {MMKV} from "./MMKV";
const isValidHex = (hex) => /^#([A-Fa-f0-9]{3,4}){1,2}$/.test(hex);
const getChunksFromString = (st, chunkSize) =>
st.match(new RegExp(`.{${chunkSize}}`, 'g'));
const convertHexUnitTo256 = (hexStr) =>
parseInt(hexStr.repeat(2 / hexStr.length), 16);
const getAlphaFloat = (a, alpha) => {
if (typeof a !== 'undefined') {
return a / 256;
}
if (typeof alpha !== 'undefined') {
if (1 < alpha && alpha <= 100) {
return alpha / 100;
}
if (0 <= alpha && alpha <= 1) {
return alpha;
}
}
return 1;
};
const rgbRes = {
color: '',
result: '',
};
export const hexToRGBA = (hex, alpha) => {
if (rgbRes.color === hex) return rgbRes.result;
if (!isValidHex(hex)) {
return hex;
}
const chunkSize = Math.floor((hex.length - 1) / 3);
const hexArr = getChunksFromString(hex.slice(1), chunkSize);
const [r, g, b, a] = hexArr.map(convertHexUnitTo256);
return `rgba(${r}, ${g}, ${b}, ${getAlphaFloat(a, alpha)})`;
};
const shadeRes = {
color: '',
alpha: 0,
result: '',
};
export const RGB_Linear_Shade = (p, rgba) => {
if (shadeRes.color === rgba && shadeRes.alpha === p) return shadeRes.result;
let i = parseInt,
r = Math.round,
P = p < 0,
t = P ? 0 : 255 * p,
[a, b, c, d] = rgba.split(',');
P = P ? 1 + p : 1 - p;
return (
'rgb' +
(d ? 'a(' : '(') +
r(i(a[3] === 'a' ? a.slice(5) : a.slice(4)) * P + t) +
',' +
r(i(b) * P + t) +
',' +
r(i(c) * P + t) +
(d ? ',' + d : ')')
);
};
export async function getColorScheme(useSystemTheme) {
let accentColor;
let theme;
try {
accentColor = await MMKV.getStringAsync('accentColor');
} catch (e) {
}
try {
theme = await MMKV.getStringAsync('theme');
} catch (e) {
}
if (typeof accentColor !== 'string') {
MMKV.setStringAsync('accentColor', '#0560FF');
setAccentColor('#0560FF');
} else {
setAccentColor(accentColor);
}
if (useSystemTheme) {
StatusBar.setBarStyle(
Appearance.getColorScheme() === 'dark' ? 'light-content' : 'dark-content',
);
Appearance.getColorScheme() === 'dark'
? setColorScheme(COLOR_SCHEME_DARK)
: setColorScheme(COLOR_SCHEME_LIGHT);
return COLOR_SCHEME;
}
if (typeof theme !== 'string') {
MMKV.setStringAsync('theme', JSON.stringify({night: false}));
setColorScheme(COLOR_SCHEME_LIGHT);
} else {
theme = JSON.parse(theme);
theme.night
? setColorScheme(COLOR_SCHEME_DARK)
: setColorScheme(COLOR_SCHEME_LIGHT);
StatusBar.setBarStyle(theme.night ? 'light-content' : 'dark-content');
}
eSendEvent(eThemeUpdated);
return COLOR_SCHEME;
}
export const onThemeUpdate = (func = () => {
}) => {
return eSubscribeEvent(eThemeUpdated, func);
};
export const clearThemeUpdateListener = (func = () => {
}) => {
return eUnSubscribeEvent(eThemeUpdated, func);
};

View File

@@ -0,0 +1,76 @@
import {eSendEvent} from "../services/EventManager";
import {eThemeUpdated} from "./Events";
export const ACCENT = {
color: '#0560FF',
shade: '#0560FF12',
};
const fixedColors = {
accent: ACCENT.color,
shade: ACCENT.shade,
fg: ACCENT.color,
normal: 'black',
icon: 'gray',
errorBg: '#FFD2D2',
errorText: '#ff6961',
successBg: '#DFF2BF',
successText: '#4F8A10',
warningBg: '#FEEFB3',
warningText: '#9F6000',
};
export var COLOR_SCHEME = {
night: false,
bg: 'white',
navbg: '#f6fbfc',
nav: '#f0f0f0',
pri: '#000000',
sec: 'white',
...fixedColors,
};
export const COLOR_SCHEME_LIGHT = {
night: false,
bg: 'white',
navbg: '#f6fbfc',
nav: '#f0f0f0',
input: 'transparent',
heading: '#000000',
pri: '#24292e',
sec: 'white',
...fixedColors,
};
export const COLOR_SCHEME_DARK = {
night: true,
bg: '#1f1f1f',
navbg: '#1c1c1c',
input: '#2d2d2d',
nav: '#2d2d2d',
heading: '#ffffff',
pri: '#D3D3D3',
sec: 'black',
...fixedColors,
};
export const COLORS_NOTE = {
red: '#f44336',
orange: '#FF9800',
yellow: '#FFD600',
green: '#4CAF50',
blue: '#2196F3',
purple: '#673AB7',
gray: '#9E9E9E',
};
export function setColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
COLOR_SCHEME = {...colors, accent: accent.color, shade: accent.shade};
eSendEvent(eThemeUpdated);
return COLOR_SCHEME;
}
export function setAccentColor(color) {
ACCENT.color = color;
ACCENT.shade = color + '12';
return ACCENT;
}

View File

@@ -0,0 +1,12 @@
import {Platform} from "react-native";
import Storage from "./Storage";
import EventSource from "rn-eventsource";
import AndroidEventSource from "./EventSource";
import Database from "notes-core/api/index";
global.Buffer = require('buffer').Buffer;
export const db = new Database(
Storage,
Platform.OS === 'ios' ? EventSource : AndroidEventSource,
);
db.host("https://192.168.10.8:5000")

View File

@@ -107,3 +107,5 @@ export const eCloseProgressDialog = '552';
export const eOpenRestoreDialog = '553';
export const eCloseRestoreDialog = '554';
export const eOnNoteEdited = '555';

View File

@@ -3,8 +3,8 @@ import { useTracked } from '../provider';
import {
eSubscribeEvent,
eUnSubscribeEvent
} from '../services/eventManager';
import { eScrollEvent } from '../services/events';
} from '../services/EventManager';
import { eScrollEvent } from './Events';

View File

@@ -0,0 +1,3 @@
import MMKVStorage from "react-native-mmkv-storage";
export const MMKV = new MMKVStorage.Loader().initialize();

View File

@@ -0,0 +1,94 @@
import {Dimensions, PixelRatio, Platform} from "react-native";
import {DDS} from "../services/DeviceDetection";
export const scale = {
fontScale: 1,
};
let windowSize = Dimensions.get('window');
let adjustedWidth = windowSize.width * PixelRatio.get();
let adjustedHeight = windowSize.height * PixelRatio.get();
const pixelDensity = PixelRatio.get();
export const getDeviceSize = () => {
let dpi = getDpi(pixelDensity);
let deviceWidthInInches = adjustedWidth / dpi;
let deviceHeightInInches = adjustedHeight / dpi;
let diagonalSize = Math.sqrt(
Math.pow(deviceWidthInInches, 2) + Math.pow(deviceHeightInInches, 2),
);
return diagonalSize;
};
const getDpi = (pd) => {
return 160 * pd;
};
const correction = (size, multiplier) => {
let dSize = getDeviceSize();
if (dSize >= 4 && dSize <= 5.3 && pixelDensity <= 3) {
return size * 0.92;
} else if (dSize > 5.3 && dSize < 7 && pixelDensity < 3 && !DDS.isTab) {
if (Platform.OS === 'ios') {
return size;
}
return size * 0.93;
} else if (dSize <= 7 && pixelDensity >= 3 && !DDS.isTab) {
return size * 0.98;
} else if (dSize >= 6.5 && dSize <= 7.2 && DDS.isTab) {
return size * multiplier;
} else if (dSize > 7.2 && dSize <= 8.5 && DDS.isTab) {
return size * (multiplier + 0.10);
} else if (dSize > 8.5 && dSize <= 9.8 && DDS.isTab) {
return size * (multiplier + 0.15);
} else if (dSize > 9.8) {
return size;
} else {
return size;
}
};
export const normalize = (size) => {
let pd = pixelDensity;
if (pd === 1 || pd < 1) {
return correction(size, 0.82);
} else if (pd > 1 && pd <= 1.5) {
return correction(size, 0.7);
} else if (pd > 1.5 && pd <= 2) {
return correction(size, 0.9);
} else if (pd > 2 && pd <= 3) {
return correction(size, 0.93);
} else if (pd > 3) {
return correction(size, 1);
}
};
export const SIZE = {
xxs: 10 * scale.fontScale,
xs: 12 * scale.fontScale,
sm: normalize(15) * scale.fontScale,
md: normalize(17) * scale.fontScale,
lg: normalize(24) * scale.fontScale,
xl: normalize(27) * scale.fontScale,
xxl: normalize(31) * scale.fontScale,
xxxl: normalize(34) * scale.fontScale,
};
export function updateSize() {
SIZE.xxs = 10 * scale.fontScale;
SIZE.xs = 12 * scale.fontScale;
SIZE.sm = normalize(15) * scale.fontScale;
SIZE.md = normalize(17) * scale.fontScale;
SIZE.lg = normalize(24) * scale.fontScale;
SIZE.xl = normalize(27) * scale.fontScale;
SIZE.xxl = normalize(31) * scale.fontScale;
SIZE.xxxl = normalize(34) * scale.fontScale;
ph = normalize(10) * scale.fontScale;
pv = normalize(10) * scale.fontScale;
}
export const br = 5; // border radius
export var ph = normalize(10); // padding horizontal
export var pv = normalize(10); // padding vertical
export const opacity = 0.5; // active opacity
export const WEIGHT = {
light: 'DMSans-Regular',
regular: 'DMSans-Regular',
medium: 'DMSans-Regular',
semibold: 'DMSerifText-Regular',
bold: 'DMSerifText-Regular',
};

View File

@@ -0,0 +1,128 @@
import "react-native-get-random-values";
import {generateSecureRandom} from 'react-native-securerandom';
import Sodium from 'react-native-sodium';
import RNFetchBlob from 'rn-fetch-blob';
import {PERMISSIONS, requestMultiple, RESULTS} from "react-native-permissions";
import {MMKV} from "./MMKV";
async function read(key, isArray = false) {
let data;
try {
data = await MMKV.getItem(key);
} catch (e) {}
if (!data) return null;
try {
data = JSON.parse(data);
data = isArray ? [...data] : data;
} catch (e) {}
return data;
}
async function write(key, data) {
return await MMKV.setItem(
key,
typeof data === 'string' ? data : JSON.stringify(data),
);
}
async function readMulti(keys) {
if (keys.length <= 0) {
return [];
} else {
let data = await MMKV.getMultipleItemsAsync(keys.slice());
return data.map(([key, value]) => {
let obj;
try {
obj = JSON.parse(value);
} catch (e) {
obj = value;
}
return [key, obj];
});
}
}
async function remove(key) {
return await MMKV.removeItem(key);
}
async function clear() {
return await MMKV.clearStore();
}
function encrypt(password, data) {
return Sodium.encrypt(password, data).then((result) => result);
}
function decrypt(password, data) {
return Sodium.decrypt(password, data).then((result) => result);
}
async function deriveKey(password, salt) {
try {
let data = await Sodium.deriveKey(password, salt);
return data.key;
} catch (e) {}
}
async function getAllKeys() {
return await MMKV.indexer.getKeys();
}
async function getRandomBytes(length) {
return await generateSecureRandom(length);
}
async function requestPermission() {
let granted = false;
try {
const response = await requestMultiple([
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
]);
granted =
response['android.permission.READ_EXTERNAL_STORAGE'] ===
RESULTS.GRANTED &&
response['android.permission.WRITE_EXTERNAL_STORAGE'] === RESULTS.GRANTED;
} catch (err) {
}
return granted;
}
async function checkAndCreateDir(dir) {
try {
let exists = await RNFetchBlob.fs.exists(dir);
let isDir = await RNFetchBlob.fs.isDir(dir);
if (!exists || !isDir) {
await RNFetchBlob.fs.mkdir(dir);
}
} catch (e) {
console.log(e);
await RNFetchBlob.fs.mkdir(dir);
} finally {
}
return dir;
}
export default {
read,
write,
readMulti,
remove,
clear,
encrypt,
decrypt,
deriveKey,
getAllKeys,
getRandomBytes,
checkAndCreateDir,
requestPermission
};

View File

@@ -0,0 +1,86 @@
export const sleep = (duration) =>
new Promise((resolve) => setTimeout(() => resolve(), duration));
export function timeSince(date) {
let seconds = Math.floor((new Date() - date) / 1000);
let interval = Math.floor(seconds / 31536000);
if (interval > 0.9) {
return interval < 2 ? interval + ' year ago' : interval + ' years ago';
}
interval = Math.floor(seconds / 2592000);
if (interval > 0.9) {
return interval < 2 ? interval + ' month ago' : interval + ' months ago';
}
interval = Math.floor(seconds / 86400);
if (interval > 0.9) {
return interval < 2 ? interval + ' day ago' : interval + ' days ago';
}
interval = Math.floor(seconds / 3600);
if (interval > 0.9) {
return interval < 2 ? interval + ' hour ago' : interval + ' hours ago';
}
interval = Math.floor(seconds / 60);
if (interval > 0.9) {
return interval < 2 ? interval + ' min ago' : interval + ' min ago';
}
return Math.floor(seconds) + ' secs ago';
}
export const timeConverter = (timestamp) => {
if (!timestamp) return;
let d = new Date(timestamp), // Convert the passed timestamp to milliseconds
yyyy = d.getFullYear(),
mm = ('0' + (d.getMonth() + 1)).slice(-2), // Months are zero based. Add leading 0.
dd = ('0' + d.getDate()).slice(-2), // Add leading 0.
currentDay = d.getDay(),
hh = d.getHours(),
h = hh,
min = ('0' + d.getMinutes()).slice(-2), // Add leading 0.
ampm = 'AM',
time;
let days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
let months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
if (hh > 12) {
h = hh - 12;
ampm = 'PM';
} else if (hh === 12) {
h = 12;
ampm = 'PM';
} else if (hh === 0) {
h = 12;
}
// ie: 2013-02-18, 8:35 AM
time =
days[currentDay] +
' ' +
dd +
' ' +
months[d.getMonth()] +
', ' +
yyyy +
', ' +
h +
':' +
min +
' ' +
ampm;
return time;
};

58
apps/mobile/src/utils/index.js Executable file
View File

@@ -0,0 +1,58 @@
import {Dimensions, Platform} from 'react-native';
import {eSendEvent} from '../services/EventManager';
import {updateEvent} from '../components/DialogManager/recievers';
import {Actions} from '../provider/Actions';
import {MMKV} from "./MMKV";
export async function setSetting(settings, name, value) {
let s = {...settings};
s[name] = value;
await MMKV.setStringAsync('settings', JSON.stringify(s));
updateEvent({type: Actions.SETTINGS, settings: s});
}
export const getElevation = (elevation) => {
return {
elevation,
shadowColor: 'black',
shadowOffset: {width: 0.3 * elevation, height: 0.5 * elevation},
shadowOpacity: 0.2,
shadowRadius: 0.7 * elevation,
};
};
export const editing = {
currentlyEditing: false,
isFullscreen: false,
actionAfterFirstSave: {
type: null,
},
};
export const selection = {
data: [],
type: null,
selectedItems: [],
};
export const history = {
selectedItemsList: [],
};
export async function showContext(event, title) {
eSendEvent('showContextMenu', {
location: {
x: event.nativeEvent.pageX + 50,
y: event.nativeEvent.pageY - 10,
},
title: title,
});
}
export const dWidth = Dimensions.get('window').width;
export const dHeight = Dimensions.get('window').height;
export const itemSkus = Platform.select({
ios: ['com.streetwriters.notesnook.sub.mo'],
android: ['com.streetwriters.notesnook.sub.mo'],
});

View File

@@ -1,204 +0,0 @@
import he from 'he';
import {Platform} from 'react-native';
import 'react-native-get-random-values';
import RNHTMLtoPDF from 'react-native-html-to-pdf';
import MMKVStorage from 'react-native-mmkv-storage';
import {generateSecureRandom} from 'react-native-securerandom';
import Sodium from 'react-native-sodium';
import RNFetchBlob from 'rn-fetch-blob';
import {db, requestStoragePermission, ToastEvent} from './utils';
export const MMKV = new MMKVStorage.Loader().initialize();
const dirs = RNFetchBlob.fs.dirs;
async function read(key, isArray = false) {
let data;
try {
data = await MMKV.getItem(key);
} catch (e) {}
if (!data) return null;
try {
data = JSON.parse(data);
data = isArray ? [...data] : data;
} catch (e) {}
return data;
}
async function write(key, data) {
return await MMKV.setItem(
key,
typeof data === 'string' ? data : JSON.stringify(data),
);
}
async function readMulti(keys) {
if (keys.length <= 0) {
return [];
} else {
let data = await MMKV.getMultipleItemsAsync(keys.slice());
return data.map(([key, value]) => {
let obj;
try {
obj = JSON.parse(value);
} catch (e) {
obj = value;
}
return [key, obj];
});
}
}
async function remove(key) {
return await MMKV.removeItem(key);
}
async function clear() {
return await MMKV.clearStore();
}
function encrypt(password, data) {
return Sodium.encrypt(password, data).then((result) => result);
}
function decrypt(password, data) {
return Sodium.decrypt(password, data).then((result) => result);
}
async function deriveKey(password, salt) {
try {
let data = await Sodium.deriveKey(password, salt);
return data.key;
} catch (e) {}
}
async function getAllKeys() {
return await MMKV.indexer.getKeys();
}
async function getRandomBytes(length) {
return await generateSecureRandom(length);
}
async function saveToPDF(note) {
let androidSavePath = '/Notesnook/exported/PDF';
if (Platform.OS === 'android') {
let hasPermission = await requestStoragePermission();
if (!hasPermission) {
ToastEvent.show('Failed to get storage permission');
return null;
}
} else {
await checkAndCreateDir(dirs.DocumentDir + '/exported/PDF/');
}
let html = await db.notes.note(note).export('html');
html = he.decode(html);
let options = {
html: html,
fileName:
Platform.OS === 'ios' ? '/exported/PDF/' + note.title : note.title,
directory: Platform.OS === 'ios' ? 'Documents' : androidSavePath,
};
let res = await RNHTMLtoPDF.convert(options);
return {
filePath: res.filePath,
type: 'application/pdf',
name: 'PDF',
};
}
async function saveToMarkdown(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Markdown/'
: dirs.SDCardDir + '/Notesnook/exported/Markdown/';
await checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('md');
let path = savePath + note.title + '.md';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/markdown',
name: 'Markdown',
};
}
async function saveToText(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Text/'
: dirs.SDCardDir + '/Notesnook/exported/Text/';
await checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('txt');
let path = savePath + note.title + '.txt';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/plain',
name: 'Text',
};
}
async function saveToHTML(note) {
let savePath =
Platform.OS === 'ios'
? dirs.DocumentDir + '/exported/Html/'
: dirs.SDCardDir + '/Notesnook/exported/Html/';
await checkAndCreateDir(savePath);
let markdown = await db.notes.note(note.id).export('html');
let path = savePath + note.title + '.html';
await RNFetchBlob.fs.writeFile(path, markdown, 'utf8');
return {
filePath: path,
type: 'text/html',
name: 'Html',
};
}
async function checkAndCreateDir(dir) {
try {
let exists = await RNFetchBlob.fs.exists(dir);
let isDir = await RNFetchBlob.fs.isDir(dir);
if (!exists || !isDir) {
await RNFetchBlob.fs.mkdir(dir);
}
} catch (e) {
console.log(e);
await RNFetchBlob.fs.mkdir(dir);
} finally {
}
return dir;
}
export default {
read,
write,
readMulti,
remove,
clear,
encrypt,
decrypt,
deriveKey,
saveToPDF,
getAllKeys,
getRandomBytes,
checkAndCreateDir,
saveToMarkdown,
saveToText,
saveToHTML,
};

View File

@@ -1,381 +0,0 @@
import {Dimensions, Platform} from 'react-native';
import Database from 'notes-core/api/';
import {eSendEvent} from '../services/eventManager';
import {eShowToast, eHideToast} from '../services/events';
import {DeviceDetectionService} from './deviceDetection';
import StorageInterface, {MMKV} from './storage';
import {updateEvent} from '../components/DialogManager/recievers';
import {ACTIONS} from '../provider/actions';
import ESource from './event-source';
import EventSource from 'rn-eventsource';
import {PERMISSIONS, requestMultiple, RESULTS} from 'react-native-permissions';
global.Buffer = require('buffer').Buffer;
export const DDS = new DeviceDetectionService();
export const db = new Database(
StorageInterface,
Platform.OS === 'ios' ? EventSource : ESource,
);
db.host('http://192.168.10.8:8000');
export const sleep = (duration) =>
new Promise((resolve) => setTimeout(() => resolve(), duration));
export async function setSetting(settings, name, value) {
let s = {...settings};
s[name] = value;
await MMKV.setStringAsync('settings', JSON.stringify(s));
updateEvent({type: ACTIONS.SETTINGS, settings: s});
}
export const getElevation = (elevation) => {
return {
elevation,
shadowColor: 'black',
shadowOffset: {width: 0.3 * elevation, height: 0.5 * elevation},
shadowOpacity: 0.2,
shadowRadius: 0.7 * elevation,
};
};
export const editing = {
currentlyEditing: false,
isFullscreen: false,
actionAfterFirstSave: {
type: null,
},
};
export const selection = {
data: [],
type: null,
selectedItems: [],
};
export const history = {
selectedItemsList: [],
};
export async function showContext(event, title) {
eSendEvent('showContextMenu', {
location: {
x: event.nativeEvent.pageX + 50,
y: event.nativeEvent.pageY - 10,
},
title: title,
});
}
export async function requestStoragePermission() {
let granted = false;
try {
const response = await requestMultiple([
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
]);
granted =
response['android.permission.READ_EXTERNAL_STORAGE'] ===
RESULTS.GRANTED &&
response['android.permission.WRITE_EXTERNAL_STORAGE'] === RESULTS.GRANTED;
} catch (err) {
} finally {
return granted;
}
}
export function timeSince(date) {
var seconds = Math.floor((new Date() - date) / 1000);
var interval = Math.floor(seconds / 31536000);
if (interval > 0.9) {
return interval < 2 ? interval + ' year ago' : interval + ' years ago';
}
interval = Math.floor(seconds / 2592000);
if (interval > 0.9) {
return interval < 2 ? interval + ' month ago' : interval + ' months ago';
}
interval = Math.floor(seconds / 86400);
if (interval > 0.9) {
return interval < 2 ? interval + ' day ago' : interval + ' days ago';
}
interval = Math.floor(seconds / 3600);
if (interval > 0.9) {
return interval < 2 ? interval + ' hour ago' : interval + ' hours ago';
}
interval = Math.floor(seconds / 60);
if (interval > 0.9) {
return interval < 2 ? interval + ' min ago' : interval + ' min ago';
}
return Math.floor(seconds) + ' secs ago';
}
export const w = Dimensions.get('window').width;
export const h = Dimensions.get('window').height;
export const ToastEvent = {
show: (
message,
type = 'error',
context = 'global',
duration = 3000,
func = null,
actionText = '',
) => {
eSendEvent(eShowToast, {
message,
type,
context,
duration,
func,
actionText,
});
},
hide: (
message,
type = 'error',
context = 'global',
duration = 3000,
func = null,
actionText = '',
) => {
eSendEvent(eHideToast, {
message,
type,
context,
duration,
func,
actionText,
});
},
};
export const timeConverter = (timestamp) => {
if (!timestamp) return;
var d = new Date(timestamp), // Convert the passed timestamp to milliseconds
yyyy = d.getFullYear(),
mm = ('0' + (d.getMonth() + 1)).slice(-2), // Months are zero based. Add leading 0.
dd = ('0' + d.getDate()).slice(-2), // Add leading 0.
currentDay = d.getDay(),
hh = d.getHours(),
h = hh,
min = ('0' + d.getMinutes()).slice(-2), // Add leading 0.
ampm = 'AM',
time;
let days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
var months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
if (hh > 12) {
h = hh - 12;
ampm = 'PM';
} else if (hh === 12) {
h = 12;
ampm = 'PM';
} else if (hh == 0) {
h = 12;
}
// ie: 2013-02-18, 8:35 AM
time =
days[currentDay] +
' ' +
dd +
' ' +
months[d.getMonth()] +
', ' +
yyyy +
', ' +
h +
':' +
min +
' ' +
ampm;
return time;
};
const isValidHex = (hex) => /^#([A-Fa-f0-9]{3,4}){1,2}$/.test(hex);
const getChunksFromString = (st, chunkSize) =>
st.match(new RegExp(`.{${chunkSize}}`, 'g'));
const convertHexUnitTo256 = (hexStr) =>
parseInt(hexStr.repeat(2 / hexStr.length), 16);
const getAlphafloat = (a, alpha) => {
if (typeof a !== 'undefined') {
return a / 256;
}
if (typeof alpha !== 'undefined') {
if (1 < alpha && alpha <= 100) {
return alpha / 100;
}
if (0 <= alpha && alpha <= 1) {
return alpha;
}
}
return 1;
};
const rgbRes = {
color: '',
result: '',
};
export const hexToRGBA = (hex, alpha) => {
if (rgbRes.color === hex) return rgbRes.result;
if (!isValidHex(hex)) {
return hex;
}
const chunkSize = Math.floor((hex.length - 1) / 3);
const hexArr = getChunksFromString(hex.slice(1), chunkSize);
const [r, g, b, a] = hexArr.map(convertHexUnitTo256);
return `rgba(${r}, ${g}, ${b}, ${getAlphafloat(a, alpha)})`;
};
export const shadeBlendConvert = function (p, from, to) {
if (
typeof p != 'number' ||
p < -1 ||
p > 1 ||
typeof from != 'string' ||
(from[0] != 'r' && from[0] != '#') ||
(to && typeof to != 'string')
)
return null; //ErrorCheck
if (!this.sbcRip)
this.sbcRip = (d) => {
let l = d.length,
RGB = {};
if (l > 9) {
d = d.split(',');
if (d.length < 3 || d.length > 4) return null; //ErrorCheck
(RGB[0] = i(d[0].split('(')[1])),
(RGB[1] = i(d[1])),
(RGB[2] = i(d[2])),
(RGB[3] = d[3] ? parseFloat(d[3]) : -1);
} else {
if (l == 8 || l == 6 || l < 4) return null; //ErrorCheck
if (l < 6)
d =
'#' +
d[1] +
d[1] +
d[2] +
d[2] +
d[3] +
d[3] +
(l > 4 ? d[4] + '' + d[4] : ''); //3 or 4 digit
(d = i(d.slice(1), 16)),
(RGB[0] = (d >> 16) & 255),
(RGB[1] = (d >> 8) & 255),
(RGB[2] = d & 255),
(RGB[3] = -1);
if (l == 9 || l == 5)
(RGB[3] = r((RGB[2] / 255) * 10000) / 10000),
(RGB[2] = RGB[1]),
(RGB[1] = RGB[0]),
(RGB[0] = (d >> 24) & 255);
}
return RGB;
};
var i = parseInt,
r = Math.round,
h = from.length > 9,
h =
typeof to == 'string'
? to.length > 9
? true
: to == 'c'
? !h
: false
: h,
b = p < 0,
p = b ? p * -1 : p,
to = to && to != 'c' ? to : b ? '#000000' : '#FFFFFF',
f = this.sbcRip(from),
t = this.sbcRip(to);
if (!f || !t) return null; //ErrorCheck
if (h)
return (
'rgb' +
(f[3] > -1 || t[3] > -1 ? 'a(' : '(') +
r((t[0] - f[0]) * p + f[0]) +
',' +
r((t[1] - f[1]) * p + f[1]) +
',' +
r((t[2] - f[2]) * p + f[2]) +
(f[3] < 0 && t[3] < 0
? ')'
: ',' +
(f[3] > -1 && t[3] > -1
? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000
: t[3] < 0
? f[3]
: t[3]) +
')')
);
else
return (
'#' +
(
0x100000000 +
r((t[0] - f[0]) * p + f[0]) * 0x1000000 +
r((t[1] - f[1]) * p + f[1]) * 0x10000 +
r((t[2] - f[2]) * p + f[2]) * 0x100 +
(f[3] > -1 && t[3] > -1
? r(((t[3] - f[3]) * p + f[3]) * 255)
: t[3] > -1
? r(t[3] * 255)
: f[3] > -1
? r(f[3] * 255)
: 255)
)
.toString(16)
.slice(1, f[3] > -1 || t[3] > -1 ? undefined : -2)
);
};
const shadeRes = {
color: '',
alpha: 0,
result: '',
};
export const RGB_Linear_Shade = (p, c) => {
if (shadeRes.color === c && shadeRes.alpha === p) return shadeRes.result;
var i = parseInt,
r = Math.round,
[a, b, c, d] = c.split(','),
P = p < 0,
t = P ? 0 : 255 * p,
P = P ? 1 + p : 1 - p;
return (
'rgb' +
(d ? 'a(' : '(') +
r(i(a[3] == 'a' ? a.slice(5) : a.slice(4)) * P + t) +
',' +
r(i(b) * P + t) +
',' +
r(i(c) * P + t) +
(d ? ',' + d : ')')
);
};
export const itemSkus = Platform.select({
ios: ['com.streetwriters.notesnook.sub.mo'],
android: ['com.streetwriters.notesnook.sub.mo'],
});

View File

@@ -0,0 +1,315 @@
import {createRef} from 'react';
import {Linking, Platform} from 'react-native';
import {updateEvent} from '../../components/DialogManager/recievers';
import {Actions} from '../../provider/Actions';
import {eSendEvent} from '../../services/EventManager';
import {eOnNoteEdited, refreshNotesPage} from '../../utils/Events';
import {editing} from '../../utils';
import {sleep, timeConverter} from "../../utils/TimeUtils";
import {normalize} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
export const EditorWebView = createRef();
export const params = 'platform=' + Platform.OS;
export const sourceUri =
(Platform.OS === 'android' ? 'file:///android_asset/' : '') +
'Web.bundle/loader.html';
export const injectedJS = `if (!window.location.search) {
var link = document.getElementById('progress-bar');
link.href = './site/index.html?${params}';
link.click();
}
`;
let noteEdited = false;
let note = {};
let id = null;
let content = null;
let title = null;
let saveCounter = 0;
let canSave = false;
let timer = null;
export function isNotedEdited() {
return noteEdited;
}
export const INJECTED_JAVASCRIPT = (premium) =>
premium
? `(function() {
setTimeout(() => {
loadAction(true,false);
},100)
})();`
: `(function() {
setTimeout(() => {
loadAction(false,false);
},100)
})();`;
export function getNote() {
return note;
}
export function post(type, value = null) {
let message = {
type,
value,
};
EditorWebView.current?.postMessage(JSON.stringify(message));
}
export const _onShouldStartLoadWithRequest = async (request) => {
if (request.url.includes('https')) {
await Linking.openURL(request.url);
return false;
} else {
return true;
}
};
export function checkNote() {
return note && note.id;
}
export async function loadNote(item) {
editing.currentlyEditing = true;
if (item && item.type === 'new') {
await clearEditor();
post('focusTitle');
canSave = true;
} else {
note = item;
canSave = false;
eSendEvent(eOnNoteEdited + item.id, {id: item.id});
await onWebViewLoad();
}
noteEdited = false;
}
const onChange = (data) => {
if (!data || data === '') return;
let rawData = JSON.parse(data);
console.log(content, "onChange", noteEdited);
if (rawData.type === 'content') {
if (
!id && rawData.text !== "" ||
(content &&
JSON.stringify(content.delta) !== JSON.stringify(rawData.delta))
) {
noteEdited = true;
}
content = rawData;
} else {
if (!id || (rawData.value !== '' && rawData.value !== title)) {
noteEdited = true;
}
title = rawData.value;
}
};
export const _onMessage = async (evt) => {
if (!evt || !evt.nativeEvent || !evt.nativeEvent.data) return;
let message = evt.nativeEvent.data;
if (message === 'loaded') {
} else if (message !== '' && message !== 'loaded') {
clearTimeout(timer);
timer = null;
if (!canSave) {
await sleep(2000);
canSave = true;
}
onChange(message);
timer = setTimeout(() => {
if (noteEdited) {
saveNote(true);
} else {
}
}, 500);
}
};
export async function clearEditor() {
if (noteEdited) {
await saveNote(true);
}
if (note && note.id) {
eSendEvent(eOnNoteEdited + note.id, {id: note.id, closed: true});
}
noteEdited = false;
title = null;
content = null;
note = null;
id = null;
saveCounter = 0;
canSave = false;
post('reset');
}
function checkIfContentIsSavable() {
if (!canSave) return false;
if (!title && !content) return false;
if (content && content.text.length < 2 && title && title?.length < 2)
return false;
if (!content && title && title.length < 2) return false;
if (!title && content.text.length < 2) return false;
if (title && !content) {
content = {
text: '',
delta: {ops: []},
};
}
return true;
}
async function setNoteInEditorAfterSaving(oldId, currentId) {
if (oldId !== currentId) {
id = currentId;
note = db.notes.note(id);
if (note) {
note = note.data;
} else {
setTimeout(() => {
note = db.notes.note(id);
if (note) {
note = note.data;
}
}, 500);
}
}
}
async function addToCollection(id) {
switch (editing.actionAfterFirstSave.type) {
case 'topic': {
await db.notes.move(
{
topic: editing.actionAfterFirstSave.id,
id: editing.actionAfterFirstSave.notebook,
},
id,
);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
case 'tag': {
await db.notes.note(note.id).tag(editing.actionAfterFirstSave.id);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
case 'color': {
await db.notes.note(id).color(editing.actionAfterFirstSave.id);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
default: {
break;
}
}
}
export async function saveNote() {
if (!checkIfContentIsSavable()) return;
console.log("saving", id);
let lockedNote = id ? db.notes.note(id).data.locked : null;
post('saving', 'Saving');
if (!lockedNote) {
let rId = await db.notes.add({
title,
content: {
text: content.text,
delta: content.delta,
},
id: id,
});
console.log(rId);
await setNoteInEditorAfterSaving(id, rId);
if (saveCounter < 2) {
updateEvent({
type: Actions.NOTES,
});
eSendEvent(refreshNotesPage);
}
eSendEvent(eOnNoteEdited + rId, {id: rId});
if (id) {
await addToCollection(id);
updateEvent({
type: Actions.CURRENT_EDITING_NOTE,
id: id,
});
}
saveCounter++;
} else {
await db.vault.save({
title,
content: {
text: content.text,
delta: content.delta,
},
id: id,
});
}
let n = db.notes.note(id).data.dateEdited;
post('dateEdited', timeConverter(n));
post('saving', 'Saved');
}
export async function onWebViewLoad(noMenu, premium, colors) {
EditorWebView.current?.injectJavaScript(INJECTED_JAVASCRIPT(premium, false));
await loadNoteInEditor();
let theme = {...colors, factor: normalize(1)};
post('theme', theme);
await sleep(1000);
if (!checkNote()) {
Platform.OS === 'android' ? EditorWebView.current?.requestFocus() : null;
}
post('blur');
}
const loadNoteInEditor = async () => {
saveCounter = 0;
content = {};
content.text = '';
if (note?.id) {
title = note.title;
id = note.id;
content.text = await db.notes.note(id).text();
post('dateEdited', timeConverter(note.dateEdited));
await sleep(50);
post('title', title);
content.delta = note.content.delta;
if (!note.locked) {
content.delta = await db.notes.note(id).delta();
}
post('delta', content.delta);
} else {
post('focusTitle');
}
await sleep(50);
post('clearHistory');
};

View File

@@ -1,311 +0,0 @@
import {createRef} from 'react';
import {Linking, Platform} from 'react-native';
import {normalize} from '../../common/common';
import {updateEvent} from '../../components/DialogManager/recievers';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {refreshNotesPage} from '../../services/events';
import {db, editing, sleep, timeConverter} from '../../utils/utils';
export const EditorWebView = createRef();
export const params = 'platform=' + Platform.OS;
export const sourceUri =
(Platform.OS === 'android' ? 'file:///android_asset/' : '') +
'Web.bundle/loader.html';
export const injectedJS = `if (!window.location.search) {
var link = document.getElementById('progress-bar');
link.href = './site/index.html?${params}';
link.click();
}
`;
let noteEdited = false;
export function isNotedEdited() {
return noteEdited;
}
export const INJECTED_JAVASCRIPT = (premium, noMenu) =>
premium
? `(function() {
setTimeout(() => {
loadAction(true,false);
},100)
})();`
: `(function() {
setTimeout(() => {
loadAction(false,false);
},100)
})();`;
var note = {};
export function getNote() {
return note;
}
var id = null;
var content = null;
var title = null;
var saveCounter = 0;
var canSave = false;
var timer = null;
export function post(type, value = null) {
let message = {
type,
value,
};
EditorWebView.current?.postMessage(JSON.stringify(message));
}
export const _onShouldStartLoadWithRequest = (request) => {
if (request.url.includes('https')) {
Linking.openURL(request.url);
return false;
} else {
return true;
}
};
export function checkNote() {
return note && note.id;
}
export async function loadNote(item) {
editing.currentlyEditing = true;
updateEvent({type: ACTIONS.NOTES});
if (item && item.type === 'new') {
await clearEditor();
post('focusTitle');
canSave = true;
} else {
note = item;
canSave = false;
updateEvent({
type: ACTIONS.CURRENT_EDITING_NOTE,
id: item.id,
});
await onWebViewLoad();
}
}
const onChange = (data) => {
if (!data || data === '') return;
let rawData = JSON.parse(data);
console.log(rawData);
if (rawData.type === 'content') {
if (
!content ||
(content &&
JSON.stringify(content.delta) !== JSON.stringify(rawData.delta))
) {
noteEdited = true;
}
content = rawData;
} else {
if (rawData.value !== '' && rawData.value !== title) {
noteEdited = true;
}
title = rawData.value;
}
};
export const _onMessage = async (evt) => {
console.log(evt.nativeEvent.data);
if (!evt || !evt.nativeEvent || !evt.nativeEvent.data) return;
let message = evt.nativeEvent.data;
if (message === 'loaded') {
} else if (message !== '' && message !== 'loaded') {
clearTimeout(timer);
timer = null;
if (!canSave) {
await sleep(2000);
canSave = true;
}
onChange(message);
timer = setTimeout(() => {
console.log('noteEdited', noteEdited);
if (noteEdited) {
saveNote(true);
} else {
console.log('NOTHING CHANGED');
}
}, 500);
}
};
export async function clearEditor() {
await saveNote(true);
title = null;
content = null;
note = null;
id = null;
tapCount = 0;
saveCounter = 0;
canSave = false;
post('reset');
}
function checkIfContentIsSavable() {
if (!canSave) return false;
if (!title && !content) return false;
if (content && content.text.length < 2 && title && title?.length < 2)
return false;
if (!content && title && title.length < 2) return false;
if (!title && content.text.length < 2) return false;
if (title && !content) {
content = {
text: '',
delta: {ops: []},
};
}
return true;
}
async function setNoteInEditorAferSaving(oldId, currentId) {
if (oldId !== currentId) {
id = currentId;
note = db.notes.note(id);
if (note) {
note = note.data;
} else {
setTimeout(() => {
note = db.notes.note(id);
if (note) {
note = note.data;
}
}, 500);
}
}
}
async function addToCollection(id) {
switch (editing.actionAfterFirstSave.type) {
case 'topic': {
await db.notes.move(
{
topic: editing.actionAfterFirstSave.id,
id: editing.actionAfterFirstSave.notebook,
},
id,
);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
case 'tag': {
await db.notes.note(note.id).tag(editing.actionAfterFirstSave.id);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
case 'color': {
await db.notes.note(id).color(editing.actionAfterFirstSave.id);
editing.actionAfterFirstSave = {
type: null,
};
break;
}
default: {
break;
}
}
}
export async function saveNote(lockNote = true) {
if (!checkIfContentIsSavable()) return;
let lockedNote = id ? db.notes.note(id).data.locked : null;
post('saving', 'Saving');
if (!lockedNote) {
let rId = await db.notes.add({
title,
content: {
text: content.text,
delta: content.delta,
},
id: id,
});
setNoteInEditorAferSaving(id, rId);
if (content.text.length < 200 || saveCounter < 2) {
updateEvent({
type: ACTIONS.NOTES,
});
eSendEvent(refreshNotesPage);
}
if (id) {
await addToCollection(id);
updateEvent({
type: ACTIONS.CURRENT_EDITING_NOTE,
id: id,
});
}
saveCounter++;
} else {
await db.vault.save({
title,
content: {
text: content.text,
delta: content.delta,
},
id: id,
});
}
let n = db.notes.note(id).data.dateEdited;
post('dateEdited', timeConverter(n));
post('saving', 'Saved');
}
export async function onWebViewLoad(noMenu, premium, colors) {
EditorWebView.current?.injectJavaScript(INJECTED_JAVASCRIPT(premium, false));
await loadNoteInEditor();
let theme = {...colors, factor: normalize(1)};
post('theme', theme);
await sleep(1000);
if (!checkNote()) {
Platform.OS === 'android' ? EditorWebView.current?.requestFocus() : null;
}
post('blur');
}
const loadNoteInEditor = async () => {
saveCounter = 0;
content = {};
content.text = '';
if (note?.id) {
title = note.title;
id = note.id;
content.text = await db.notes.note(id).text();
post('dateEdited', timeConverter(note.dateEdited));
await sleep(50);
post('title', title);
content.delta = note.content.delta;
console.log(content.delta, 'DELTA');
if (!note.locked) {
content.delta = await db.notes.note(id).delta();
}
post('delta', content.delta);
} else {
post('focusTitle');
}
await sleep(50);
post('clearHistory');
};

View File

@@ -1,15 +1,14 @@
import React, {useEffect, useState} from 'react';
import {BackHandler, KeyboardAvoidingView, Platform, SafeAreaView, StatusBar, View,} from 'react-native';
import WebView from 'react-native-webview';
import {normalize} from '../../common/common';
import {ActionIcon} from '../../components/ActionIcon';
import {ActionSheetEvent, simpleDialogEvent,} from '../../components/DialogManager/recievers';
import {TEMPLATE_EXIT_FULLSCREEN, TEMPLATE_NEW_NOTE,} from '../../components/DialogManager/templates';
import {TEMPLATE_EXIT_FULLSCREEN, TEMPLATE_NEW_NOTE,} from '../../components/DialogManager/Templates';
import {useTracked} from '../../provider';
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent,} from '../../services/eventManager';
import {eClearEditor, eCloseFullscreenEditor, eOnLoadNote, eOpenFullscreenEditor,} from '../../services/events';
import {exitEditorAnimation} from '../../utils/animations';
import {DDS, editing, ToastEvent} from '../../utils/utils';
import {eSendEvent, eSubscribeEvent, eUnSubscribeEvent, ToastEvent,} from '../../services/EventManager';
import {eClearEditor, eCloseFullscreenEditor, eOnLoadNote, eOpenFullscreenEditor,} from '../../utils/Events';
import {exitEditorAnimation} from '../../utils/Animations';
import {editing} from '../../utils';
import {
_onMessage,
_onShouldStartLoadWithRequest,
@@ -23,7 +22,9 @@ import {
onWebViewLoad,
post,
sourceUri,
} from './func';
} from './Functions';
import {normalize} from "../../utils/SizeUtils";
import {DDS} from "../../services/DeviceDetection";
let handleBack;
let tapCount = 0;

View File

@@ -3,7 +3,7 @@ import {Placeholder} from '../../components/ListPlaceholders';
import SimpleList from '../../components/SimpleList';
import {NoteItemWrapper} from '../../components/SimpleList/NoteItemWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
export const Favorites = ({route, navigation}) => {
const [state, dispatch] = useTracked();
const {favorites} = state;
@@ -11,7 +11,7 @@ export const Favorites = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'notes',
menu: true,
@@ -21,13 +21,13 @@ export const Favorites = ({route, navigation}) => {
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: 'Favorites',
},
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all favorites',
data: favorites,
@@ -38,10 +38,10 @@ export const Favorites = ({route, navigation}) => {
});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'favorites',
});
dispatch({type: ACTIONS.FAVORITES});
dispatch({type: Actions.FAVORITES});
}, []);
useEffect(() => {
@@ -54,7 +54,7 @@ export const Favorites = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all favorites',
data: favorites,
@@ -71,7 +71,7 @@ export const Favorites = ({route, navigation}) => {
data={favorites}
type="notes"
refreshCallback={() => {
dispatch({type: ACTIONS.FAVORITES});
dispatch({type: Actions.FAVORITES});
}}
refreshing={refreshing}
focused={() => navigation.isFocused()}

View File

@@ -4,7 +4,7 @@ import {Placeholder} from '../../components/ListPlaceholders';
import SimpleList from '../../components/SimpleList';
import {NotebookItemWrapper} from '../../components/SimpleList/NotebookItemWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
export const Folders = ({route, navigation}) => {
const [state, dispatch] = useTracked();
@@ -13,7 +13,7 @@ export const Folders = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'notebooks',
menu: true,
@@ -22,7 +22,7 @@ export const Folders = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all notebooks',
data: notebooks,
@@ -33,19 +33,19 @@ export const Folders = ({route, navigation}) => {
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: params.title,
},
});
dispatch({type: ACTIONS.PINNED});
dispatch({type: ACTIONS.NOTEBOOKS});
dispatch({type: Actions.PINNED});
dispatch({type: Actions.NOTEBOOKS});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'notebooks',
});
@@ -61,7 +61,7 @@ export const Folders = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all notebooks',
data: notebooks,

View File

@@ -1,126 +1 @@
import React, {createRef, useEffect} from 'react';
import {SafeAreaView, Text, TouchableOpacity, View} from 'react-native';
import {TextInput} from 'react-native-gesture-handler';
import {opacity, pv, SIZE, WEIGHT, DDS} from '../../common/common';
import {Header} from '../../components/header';
import {useTracked} from '../../provider';
import {eSubscribeEvent, eUnSubscribeEvent} from '../../services/eventManager';
import {eLoginDialogNavigateBack} from '../../services/events';
import { useIsFocused } from '@react-navigation/native';
export const ForgotPassword = ({navigation}) => {
const [state, dispatch] = useTracked();
const {colors, isLoginNavigator} = state;
let isFocused = useIsFocused();
const handleBackPress = () => {
navigation.goBack();
};
useEffect(() => {
eSubscribeEvent(eLoginDialogNavigateBack, handleBackPress);
return () => {
eUnSubscribeEvent(eLoginDialogNavigateBack, handleBackPress);
};
}, [isFocused]);
return (
<SafeAreaView
style={{
backgroundColor: colors.bg,
height: '100%',
}}>
<Header
isLoginNavigator={isLoginNavigator}
colors={colors}
navigation={navigation}
heading={'Recover Password'}
/>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
width: '100%',
}}>
{renderForgotPassword(colors)}
</View>
</SafeAreaView>
);
};
ForgotPassword.navigationOptions = {
header: null,
headerStyle: {
backgroundColor: 'transparent',
borderBottomWidth: 0,
height: 0,
},
};
export default ForgotPassword;
const renderForgotPassword = colors => {
const _email = createRef();
return (
<View
style={{
justifyContent: DDS.isTab ? 'center' : 'space-between',
width: DDS.isTab ? '80%' : '100%',
width: DDS.isTab ? '80%' : '100%',
alignSelf: 'center',
}}>
<View>
<TextInput
ref={_email}
onFocus={() => {
_email.current.setNativeProps({
style: {
borderColor: colors.navbg,
},
});
}}
onBlur={() => {
_email.current.setNativeProps({
style: {
borderColor: colors.nav,
},
});
}}
style={{
padding: pv,
borderWidth: 1.5,
borderColor: colors.nav,
marginHorizontal: '5%',
borderRadius: 5,
fontSize: SIZE.md,
fontFamily: WEIGHT.regular,
marginBottom: 20,
}}
placeholder="Email"
placeholderTextColor={colors.icon}
/>
<TouchableOpacity
activeOpacity={opacity}
style={{
padding: pv,
backgroundColor: colors.accent,
borderRadius: 5,
marginHorizontal: '5%',
marginBottom: 10,
alignItems: 'center',
}}>
<Text
style={{
fontSize: SIZE.md,
fontFamily: WEIGHT.medium,
color: 'white',
}}>
Recover
</Text>
</TouchableOpacity>
</View>
</View>
);
};

View File

@@ -6,11 +6,11 @@ import {Placeholder} from '../../components/ListPlaceholders';
import SimpleList from '../../components/SimpleList';
import {NoteItemWrapper} from '../../components/SimpleList/NoteItemWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {eOnLoadNote, eScrollEvent} from '../../services/events';
import {openEditorAnimation} from '../../utils/animations';
import {DDS} from '../../utils/utils';
import {Actions} from '../../provider/Actions';
import {eSendEvent} from '../../services/EventManager';
import {eOnLoadNote, eScrollEvent} from '../../utils/Events';
import {openEditorAnimation} from '../../utils/Animations';
import {DDS} from "../../services/DeviceDetection";
export const Home = ({route, navigation}) => {
const [state, dispatch] = useTracked();
@@ -18,11 +18,11 @@ export const Home = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'home',
});
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'notes',
menu: true,
@@ -31,11 +31,11 @@ export const Home = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: true,
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all notes',
data: notes,
@@ -45,20 +45,20 @@ export const Home = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: 'Home',
},
});
eSendEvent(eScrollEvent, 0);
dispatch({type: ACTIONS.COLORS});
dispatch({type: ACTIONS.NOTES});
dispatch({type: Actions.COLORS});
dispatch({type: Actions.NOTES});
}, []);
const onBlur = useCallback(() => {
console.log(navigation.isFocused());
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
}, []);
@@ -75,7 +75,7 @@ export const Home = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all notes',
data: notes,

View File

@@ -1,5 +1,6 @@
import {StyleSheet} from 'react-native';
import {SIZE, COLOR_SCHEME} from '../../common/common';
import {COLOR_SCHEME} from "../../utils/Colors";
import {SIZE} from "../../utils/SizeUtils";
export const styles = StyleSheet.create({
container: {

View File

@@ -4,17 +4,17 @@ import {NotebookItem} from '../../components/NotebookItem';
import SelectionWrapper from '../../components/SelectionWrapper';
import SimpleList from '../../components/SimpleList';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
import {eOnNewTopicAdded, eScrollEvent} from '../../services/events';
import NavigationService from '../../services/NavigationService';
import {db} from '../../utils/utils';
} from '../../services/EventManager';
import {eOnNewTopicAdded, eScrollEvent} from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import { Dimensions } from 'react-native';
import {db} from "../../utils/DB";
export const Notebook = ({route, navigation}) => {
const [, dispatch] = useTracked();
@@ -43,7 +43,7 @@ export const Notebook = ({route, navigation}) => {
const onFocus = useCallback(() => {
onLoad();
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'topics',
menu: false,
@@ -53,7 +53,7 @@ export const Notebook = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: `Search in "${params.title}"`,
data: topics,
@@ -64,19 +64,19 @@ export const Notebook = ({route, navigation}) => {
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: params.title,
},
});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'notebook',
});
}, []);
@@ -91,7 +91,7 @@ export const Notebook = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: `Search in "${params.title}"`,
data: topics,
@@ -151,12 +151,12 @@ const RenderItem = ({item, index}) => {
onLongPress={() => {
if (!selectionMode) {
dispatch({
type: ACTIONS.SELECTION_MODE,
type: Actions.SELECTION_MODE,
enabled: !selectionMode,
});
}
dispatch({
type: ACTIONS.SELECTED_ITEMS,
type: Actions.SELECTED_ITEMS,
item: item,
});
}}

View File

@@ -1,23 +1,25 @@
import React, {useCallback, useEffect, useState} from 'react';
import {COLORS_NOTE} from '../../common/common';
import {Placeholder} from '../../components/ListPlaceholders';
import SimpleList from '../../components/SimpleList';
import {NoteItemWrapper} from '../../components/SimpleList/NoteItemWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
import {
eSendEvent,
eSubscribeEvent,
eUnSubscribeEvent,
} from '../../services/eventManager';
} from '../../services/EventManager';
import {
eOnLoadNote,
eScrollEvent,
refreshNotesPage,
} from '../../services/events';
import {openEditorAnimation} from '../../utils/animations';
import {db, DDS, editing} from '../../utils/utils';
} from '../../utils/Events';
import {openEditorAnimation} from '../../utils/Animations';
import {editing} from '../../utils';
import {COLORS_NOTE} from "../../utils/Colors";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
export const Notes = ({route, navigation}) => {
const [state, dispatch] = useTracked();
@@ -76,7 +78,7 @@ export const Notes = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'notes',
menu: params.type === 'color' ? true : false,
@@ -85,11 +87,11 @@ export const Notes = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading:
params.type == 'tag'
@@ -99,7 +101,7 @@ export const Notes = ({route, navigation}) => {
});
init();
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: params.type === 'color' ? params.color.title : params.type,
});
}, []);
@@ -123,7 +125,7 @@ export const Notes = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: `Search in ${
params.type == 'tag' ? '#' + params.title : params.title

View File

@@ -12,23 +12,12 @@ import {
import * as Animatable from 'react-native-animatable';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import RNFetchBlob from 'rn-fetch-blob';
import {
ACCENT,
COLOR_SCHEME,
COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT,
opacity,
pv,
setColorScheme,
SIZE,
WEIGHT,
} from '../../common/common';
import {Button} from '../../components/Button';
import {PressableButton} from '../../components/PressableButton';
import Seperator from '../../components/Seperator';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {eSendEvent} from '../../services/eventManager';
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {
eCloseProgressDialog,
eOpenLoginDialog,
@@ -37,28 +26,28 @@ import {
eOpenRecoveryKeyDialog,
eOpenRestoreDialog,
eResetApp,
} from '../../services/events';
import NavigationService from '../../services/NavigationService';
import storage, {MMKV} from '../../utils/storage';
} from '../../utils/Events';
import NavigationService from '../../services/Navigation';
import storage from '../../utils/storage';
import {
db,
DDS,
hexToRGBA,
requestStoragePermission,
RGB_Linear_Shade,
setSetting,
sleep,
ToastEvent,
w,
} from '../../utils/utils';
dWidth,
} from '../../utils';
import {hexToRGBA, RGB_Linear_Shade} from "../../utils/ColorUtils";
import {sleep} from "../../utils/TimeUtils";
import {ACCENT, COLOR_SCHEME, COLOR_SCHEME_DARK, COLOR_SCHEME_LIGHT, setColorScheme} from "../../utils/Colors";
import {opacity, pv, SIZE, WEIGHT} from "../../utils/SizeUtils";
import {db} from "../../utils/DB";
import {DDS} from "../../services/DeviceDetection";
import {MMKV} from "../../utils/MMKV";
export const Settings = ({route, navigation}) => {
export const Settings = ({ navigation}) => {
const [state, dispatch] = useTracked();
const {colors, user, settings} = state;
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent);
StatusBar.setBarStyle(colors.night ? 'light-content' : 'dark-content');
dispatch({type: ACTIONS.THEME, colors: newColors});
dispatch({type: Actions.THEME, colors: newColors});
}
function changeAccentColor(accentColor) {
@@ -69,7 +58,7 @@ export const Settings = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: null,
menu: true,
@@ -78,23 +67,23 @@ export const Settings = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: 'Settings',
},
});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'settings',
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
noSearch: true,
},
@@ -137,21 +126,33 @@ export const Settings = ({route, navigation}) => {
{
name: 'Backup data',
func: async () => {
let granted = requestStoragePermission();
if (Platform.OS === 'android') {
let granted = storage.requestPermission();
if (!granted) {
ToastEvent.show('Backup failed! Storage access was denied.');
return;
}
}
eSendEvent(eOpenProgressDialog, {
title: 'Backing up your data',
paragraph:
"All your backups are stored in 'Phone Storage/Notesnook/backups' folder",
});
let backup = await db.backup.export();
let backup;
try {
backup = await db.backup.export();
} catch (e) {
console.log('error', e);
}
let backupName =
'notesnook_backup_' + new Date().toString() + '.nnbackup';
let path = RNFetchBlob.fs.dirs.SDCardDir + '/Notesnook/backups/';
let path =
Platform.OS === 'ios'
? RNFetchBlob.fs.dirs.DocumentDir + "/backups/'"
: RNFetchBlob.fs.dirs.SDCardDir + '/Notesnook/backups/';
console.log('HERE');
await storage.checkAndCreateDir(path);
await RNFetchBlob.fs.writeFile(path + backupName, backup, 'utf8');
@@ -175,7 +176,7 @@ export const Settings = ({route, navigation}) => {
await setSetting(settings, 'useSystemTheme', !settings.useSystemTheme);
if (!settings.useSystemTheme) {
MMKV.setStringAsync(
await MMKV.setStringAsync(
'theme',
JSON.stringify({night: Appearance.getColorScheme() === 'dark'}),
);
@@ -234,7 +235,7 @@ export const Settings = ({route, navigation}) => {
}}>
<View
style={{
marginTop: Platform.OS == 'ios' ? 125 - 60 : 125 - 60,
marginTop: Platform.OS === 'ios' ? 125 - 60 : 125 - 60,
}}
/>
<ScrollView
@@ -352,8 +353,8 @@ export const Settings = ({route, navigation}) => {
name: 'Logout',
func: async () => {
await db.user.logout();
dispatch({type: ACTIONS.USER, user: null});
dispatch({type: ACTIONS.CLEAR_ALL});
dispatch({type: Actions.USER, user: null});
dispatch({type: Actions.CLEAR_ALL});
},
desc:
'Logout of your account, this will clear everything and reset the app.',
@@ -506,10 +507,10 @@ export const Settings = ({route, navigation}) => {
selectedColor={item}
alpha={!colors.night ? -0.1 : 0.1}
opacity={1}
onPress={() => {
onPress={async () => {
changeAccentColor(item);
MMKV.setStringAsync('accentColor', item);
await MMKV.setStringAsync('accentColor', item);
}}
customStyle={{
flexDirection: 'row',
@@ -517,11 +518,9 @@ export const Settings = ({route, navigation}) => {
alignItems: 'center',
marginHorizontal: 5,
marginVertical: 5,
width: DDS.isTab ? (w * 0.28) / 5 - 35 : w / 5 - 35,
height: DDS.isTab ? (w * 0.28) / 5 - 35 : w / 5 - 35,
width: DDS.isTab ? (dWidth * 0.28) / 5 - 35 : dWidth / 5 - 35,
height: DDS.isTab ? (dWidth * 0.28) / 5 - 35 : dWidth / 5 - 35,
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center',
}}>
{colors.accent === item ? (
<Icon size={SIZE.lg} color="white" name="check" />
@@ -534,8 +533,8 @@ export const Settings = ({route, navigation}) => {
title="Use System Dark Mode"
tagline={
settings.useSystemTheme
? 'Switch to dark theme based on system settings'
: 'Keep the app theme independent from system settings'
? 'App will switch to dark mode based on system theme'
: 'App dark mode is independent from system theme'
}
onPress={switchTheme}
customComponent={
@@ -551,13 +550,15 @@ export const Settings = ({route, navigation}) => {
<CustomButton
title="Dark Mode"
tagline={colors.night ? 'Turn off dark mode' : 'Turn on dark mode'}
onPress={() => {
tagline={
colors.night ? 'Dark mode is turned off' : 'Dark mode is turned on'
}
onPress={async () => {
if (!colors.night) {
MMKV.setStringAsync('theme', JSON.stringify({night: true}));
await MMKV.setStringAsync('theme', JSON.stringify({night: true}));
changeColorScheme(COLOR_SCHEME_DARK);
} else {
MMKV.setStringAsync('theme', JSON.stringify({night: false}));
await MMKV.setStringAsync('theme', JSON.stringify({night: false}));
changeColorScheme(COLOR_SCHEME_LIGHT);
}
@@ -806,22 +807,22 @@ export const Settings = ({route, navigation}) => {
{[
{
name: 'Privacy Policy',
func: () => {
Linking.openURL('https://www.notesnook.com/privacy.html');
func: async () => {
await Linking.openURL('https://www.notesnook.com/privacy.html');
},
desc: 'Read our privacy policy',
},
{
name: 'Check for updates',
func: () => {
Linking.openURL('https://www.notesnook.com/privacy.html');
func: async () => {
await Linking.openURL('https://www.notesnook.com/privacy.html');
},
desc: 'Check for a newer version of app',
},
{
name: 'About',
func: () => {
Linking.openURL('https://www.notesnook.com');
func: async () => {
await Linking.openURL('https://www.notesnook.com');
},
desc: 'You are using the latest version of our app.',
},

View File

@@ -1,12 +1,12 @@
import React, {useCallback, useEffect} from 'react';
import {Text} from 'react-native';
import {SIZE, WEIGHT} from '../../common/common';
import {Placeholder} from '../../components/ListPlaceholders';
import {PressableButton} from '../../components/PressableButton';
import SimpleList from '../../components/SimpleList';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import NavigationService from '../../services/NavigationService';
import {Actions} from '../../provider/Actions';
import NavigationService from '../../services/Navigation';
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
export const Tags = ({route, navigation}) => {
const [state, dispatch] = useTracked();
@@ -15,7 +15,7 @@ export const Tags = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'trash',
menu: true,
@@ -24,17 +24,17 @@ export const Tags = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: 'Tags',
},
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all tags',
data: tags,
@@ -44,9 +44,9 @@ export const Tags = ({route, navigation}) => {
},
});
dispatch({type: ACTIONS.TAGS});
dispatch({type: Actions.TAGS});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'tags',
});
}, []);
@@ -61,7 +61,7 @@ export const Tags = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all tags',
data: tags,

View File

@@ -1,13 +1,13 @@
import React, {useCallback, useEffect} from 'react';
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
import {simpleDialogEvent} from '../../components/DialogManager/recievers';
import {TEMPLATE_EMPTY_TRASH} from '../../components/DialogManager/templates';
import {TEMPLATE_EMPTY_TRASH} from '../../components/DialogManager/Templates';
import {Placeholder} from '../../components/ListPlaceholders';
import SimpleList from '../../components/SimpleList';
import {NotebookItemWrapper} from '../../components/SimpleList/NotebookItemWrapper';
import {NoteItemWrapper} from '../../components/SimpleList/NoteItemWrapper';
import {useTracked} from '../../provider';
import {ACTIONS} from '../../provider/actions';
import {Actions} from '../../provider/Actions';
export const Trash = ({route, navigation}) => {
const [state, dispatch] = useTracked();
@@ -15,7 +15,7 @@ export const Trash = ({route, navigation}) => {
const onFocus = useCallback(() => {
dispatch({
type: ACTIONS.HEADER_STATE,
type: Actions.HEADER_STATE,
state: {
type: 'trash',
menu: true,
@@ -24,18 +24,18 @@ export const Trash = ({route, navigation}) => {
},
});
dispatch({
type: ACTIONS.HEADER_VERTICAL_MENU,
type: Actions.HEADER_VERTICAL_MENU,
state: false,
});
dispatch({
type: ACTIONS.HEADER_TEXT_STATE,
type: Actions.HEADER_TEXT_STATE,
state: {
heading: 'Trash',
},
});
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all trash',
data: trash,
@@ -46,11 +46,11 @@ export const Trash = ({route, navigation}) => {
});
dispatch({
type: ACTIONS.TRASH,
type: Actions.TRASH,
});
dispatch({
type: ACTIONS.CURRENT_SCREEN,
type: Actions.CURRENT_SCREEN,
screen: 'trash',
});
}, []);
@@ -65,7 +65,7 @@ export const Trash = ({route, navigation}) => {
useEffect(() => {
if (navigation.isFocused()) {
dispatch({
type: ACTIONS.SEARCH_STATE,
type: Actions.SEARCH_STATE,
state: {
placeholder: 'Search all trash',
data: trash,