mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-21 22:19:41 +01:00
cleanup and refactor
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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(); */
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
}}>
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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');
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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 {
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}}>
|
||||
{[
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}}>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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});
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -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');
|
||||
|
||||
68
apps/mobile/src/navigation/Drawer.js
Normal file
68
apps/mobile/src/navigation/Drawer.js
Normal 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()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
54
apps/mobile/src/navigation/NavigatorStack.js
Normal file
54
apps/mobile/src/navigation/NavigatorStack.js
Normal 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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const ACTIONS = {
|
||||
export const Actions = {
|
||||
NOTES: 'note',
|
||||
NOTEBOOKS: 'notebook',
|
||||
TRASH: 'trash',
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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};
|
||||
@@ -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();
|
||||
70
apps/mobile/src/services/EventManager.js
Normal file
70
apps/mobile/src/services/EventManager.js
Normal 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,
|
||||
});
|
||||
},
|
||||
};
|
||||
94
apps/mobile/src/services/Exporter.js
Normal file
94
apps/mobile/src/services/Exporter.js
Normal 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',
|
||||
};
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import {db} from '../utils/utils';
|
||||
import {db} from "../utils/DB";
|
||||
|
||||
let regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
121
apps/mobile/src/utils/ColorUtils.js
Normal file
121
apps/mobile/src/utils/ColorUtils.js
Normal 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);
|
||||
};
|
||||
76
apps/mobile/src/utils/Colors.js
Normal file
76
apps/mobile/src/utils/Colors.js
Normal 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;
|
||||
}
|
||||
12
apps/mobile/src/utils/DB.js
Normal file
12
apps/mobile/src/utils/DB.js
Normal 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")
|
||||
@@ -107,3 +107,5 @@ export const eCloseProgressDialog = '552';
|
||||
export const eOpenRestoreDialog = '553';
|
||||
|
||||
export const eCloseRestoreDialog = '554';
|
||||
|
||||
export const eOnNoteEdited = '555';
|
||||
@@ -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';
|
||||
|
||||
|
||||
|
||||
3
apps/mobile/src/utils/MMKV.js
Normal file
3
apps/mobile/src/utils/MMKV.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import MMKVStorage from "react-native-mmkv-storage";
|
||||
|
||||
export const MMKV = new MMKVStorage.Loader().initialize();
|
||||
94
apps/mobile/src/utils/SizeUtils.js
Normal file
94
apps/mobile/src/utils/SizeUtils.js
Normal 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',
|
||||
};
|
||||
128
apps/mobile/src/utils/Storage.js
Normal file
128
apps/mobile/src/utils/Storage.js
Normal 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
|
||||
};
|
||||
86
apps/mobile/src/utils/TimeUtils.js
Normal file
86
apps/mobile/src/utils/TimeUtils.js
Normal 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
58
apps/mobile/src/utils/index.js
Executable 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'],
|
||||
});
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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'],
|
||||
});
|
||||
315
apps/mobile/src/views/Editor/Functions.js
Normal file
315
apps/mobile/src/views/Editor/Functions.js
Normal 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');
|
||||
};
|
||||
@@ -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');
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.',
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user