mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-24 07:29:30 +01:00
fix keychain issue causing slow app load
This commit is contained in:
@@ -34,10 +34,12 @@ const App = () => {
|
||||
? 'smallTablet'
|
||||
: 'mobile',
|
||||
});
|
||||
SplashScreen.hide();
|
||||
|
||||
});
|
||||
|
||||
|
||||
//let p = performance.now();
|
||||
await db.init();
|
||||
//console.log("[INIT CALL]", performance.now() - p);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
@@ -58,7 +60,7 @@ const App = () => {
|
||||
}, []);
|
||||
|
||||
const loadMainApp = () => {
|
||||
|
||||
SplashScreen.hide();
|
||||
dispatch({type: Actions.ALL});
|
||||
eSendEvent(eOpenSideMenu);
|
||||
|
||||
|
||||
@@ -112,7 +112,6 @@ export const AppRootEvents = React.memo(
|
||||
const {loading} = state;
|
||||
|
||||
useEffect(() => {
|
||||
attachIAPListeners();
|
||||
Appearance.addChangeListener(SettingsService.setTheme);
|
||||
Linking.addEventListener('url', onUrlRecieved);
|
||||
EV.subscribe(EVENTS.appRefreshRequested, onSyncComplete);
|
||||
@@ -135,7 +134,6 @@ export const AppRootEvents = React.memo(
|
||||
|
||||
Appearance.removeChangeListener(SettingsService.setTheme);
|
||||
Linking.removeEventListener('url', onUrlRecieved);
|
||||
unsubIAP();
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -176,6 +174,7 @@ export const AppRootEvents = React.memo(
|
||||
return () => {
|
||||
unsubscribe && unsubscribe();
|
||||
AppState.removeEventListener('change', onAppStateChanged);
|
||||
unsubIAP();
|
||||
};
|
||||
}, [loading]);
|
||||
|
||||
@@ -299,6 +298,7 @@ export const AppRootEvents = React.memo(
|
||||
try {
|
||||
let user = await db.user.fetchUser(true);
|
||||
if (user) {
|
||||
attachIAPListeners();
|
||||
clearMessage(dispatch);
|
||||
dispatch({type: Actions.USER, user: user});
|
||||
await PremiumService.setPremiumStatus();
|
||||
|
||||
@@ -24,16 +24,15 @@ import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.learnium.RNDeviceInfo.RNDeviceModule;
|
||||
import com.oblador.keychain.KeychainPackage;
|
||||
import com.onibenjo.htmltopdf.RNHTMLtoPDFModule;
|
||||
import com.vinzscam.reactnativefileviewer.RNFileViewerModule;
|
||||
|
||||
import chat.rocket.rnshareextension.ShareModule;
|
||||
import cl.json.RNShareModule;
|
||||
import io.github.elyx0.reactnativedocumentpicker.DocumentPickerModule;
|
||||
import px.tooltips.RNTooltipsModule;
|
||||
|
||||
import com.oblador.keychain.KeychainModuleBuilder;
|
||||
|
||||
public class MainApplication extends MultiDexApplication implements ReactApplication {
|
||||
|
||||
@@ -48,6 +47,7 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
protected List<ReactPackage> getPackages() {
|
||||
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
packages.add(new KeychainPackage(new KeychainModuleBuilder().withoutWarmUp()));
|
||||
|
||||
packages.add(new TurboReactPackage() {
|
||||
@Override
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
rootProject.name = 'Notesnook'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
include ':react-native-keychain'
|
||||
project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: [
|
||||
"transform-remove-console"
|
||||
//"transform-remove-console"
|
||||
]
|
||||
};
|
||||
|
||||
@@ -4,6 +4,11 @@ module.exports = {
|
||||
platforms: {
|
||||
ios: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
'react-native-keychain': {
|
||||
platforms: {
|
||||
android: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -95,7 +95,7 @@ class RecoveryKeyDialog extends React.Component {
|
||||
|
||||
this.svg.current?.toDataURL(async (data) => {
|
||||
let path = await Storage.checkAndCreateDir('/');
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require("rn-fetch-blob").default
|
||||
let fileName = 'nn_' + this.user.email + '_recovery_key_qrcode.png';
|
||||
RNFetchBlob.fs.writeFile(path + fileName, data, 'base64').then((res) => {
|
||||
RNFetchBlob.fs
|
||||
@@ -124,7 +124,7 @@ class RecoveryKeyDialog extends React.Component {
|
||||
}
|
||||
let path = await Storage.checkAndCreateDir('/');
|
||||
let fileName = 'nn_' + this.user.email + '_recovery_key.txt';
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob')
|
||||
RNFetchBlob.fs
|
||||
.writeFile(path + fileName, this.state.key, 'utf8')
|
||||
.then((r) => {
|
||||
|
||||
@@ -124,7 +124,7 @@ const RestoreDataComponent = ({close, setRestoring, restoring}) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
try {
|
||||
let path = await storage.checkAndCreateDir('/backups/');
|
||||
let files = await RNFetchBlob.fs.lstat(path);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component, createRef } from 'react';
|
||||
import { InteractionManager, TouchableOpacity, View } from 'react-native';
|
||||
import * as Keychain from 'react-native-keychain';
|
||||
|
||||
import Share from 'react-native-share';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { notesnook } from '../../../e2e/test.ids';
|
||||
@@ -33,6 +33,7 @@ import Input from '../Input';
|
||||
import { Toast } from '../Toast';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
|
||||
let Keychain;
|
||||
const passInputRef = createRef();
|
||||
const confirmPassRef = createRef();
|
||||
const changePassInputRef = createRef();
|
||||
@@ -287,6 +288,9 @@ export class VaultDialog extends Component {
|
||||
loading: true,
|
||||
},
|
||||
async () => {
|
||||
if (!Keychain) {
|
||||
Keychain = require('react-native-keychain');
|
||||
}
|
||||
await sleep(20);
|
||||
await Keychain.setInternetCredentials(
|
||||
'nn_vault',
|
||||
@@ -298,6 +302,8 @@ export class VaultDialog extends Component {
|
||||
authenticationPrompt: {cancel: null},
|
||||
accessible:
|
||||
Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS,
|
||||
storage: kc.STORAGE_TYPE.AES,
|
||||
rules: "none"
|
||||
},
|
||||
);
|
||||
this.setState({
|
||||
@@ -391,6 +397,9 @@ export class VaultDialog extends Component {
|
||||
|
||||
_revokeFingerprintAccess = async () => {
|
||||
try {
|
||||
if (!Keychain) {
|
||||
Keychain = require('react-native-keychain');
|
||||
}
|
||||
await Keychain.resetInternetCredentials('nn_vault', {
|
||||
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE,
|
||||
authenticationType:
|
||||
@@ -398,6 +407,8 @@ export class VaultDialog extends Component {
|
||||
authenticationPrompt: {
|
||||
cancel: null,
|
||||
},
|
||||
storage: kc.STORAGE_TYPE.AES,
|
||||
rules: "none"
|
||||
});
|
||||
eSendEvent('vaultUpdated');
|
||||
ToastEvent.show('Fingerprint access revoked!', 'success');
|
||||
@@ -408,6 +419,10 @@ export class VaultDialog extends Component {
|
||||
|
||||
_onPressFingerprintAuth = async () => {
|
||||
try {
|
||||
|
||||
if (!Keychain) {
|
||||
Keychain = require('react-native-keychain');
|
||||
}
|
||||
let credentials = await Keychain.getInternetCredentials('nn_vault', {
|
||||
accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE,
|
||||
authenticationType:
|
||||
@@ -415,6 +430,8 @@ export class VaultDialog extends Component {
|
||||
authenticationPrompt: {
|
||||
cancel: null,
|
||||
},
|
||||
storage: kc.STORAGE_TYPE.AES,
|
||||
rules: "none"
|
||||
});
|
||||
if (credentials?.password) {
|
||||
this.password = credentials.password;
|
||||
|
||||
@@ -75,20 +75,7 @@ const screenOptionsForAnimation = {
|
||||
|
||||
export const NavigatorStack = React.memo(
|
||||
() => {
|
||||
React.useEffect(() => {
|
||||
sleep(2000).then(() => {
|
||||
Navigation.setHeaderState(
|
||||
SettingsService.get().homepage,
|
||||
{
|
||||
menu: true,
|
||||
},
|
||||
{
|
||||
heading: SettingsService.get().homepage,
|
||||
id: SettingsService.get().homepage.toLowerCase() + '_navigation',
|
||||
},
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<Container root={true}>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
const {MMKV} = require('../utils/MMKV');
|
||||
|
||||
import storage from '../utils/storage';
|
||||
import {db} from '../utils/DB';
|
||||
import {eSendEvent, ToastEvent} from './EventManager';
|
||||
import SettingsService from './SettingsService';
|
||||
import {eCloseProgressDialog, eOpenProgressDialog} from '../utils/Events';
|
||||
import {sleep} from '../utils/TimeUtils';
|
||||
import Share from 'react-native-share';
|
||||
|
||||
const MS_DAY = 86400000;
|
||||
@@ -19,7 +17,7 @@ async function run() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RNFetchBlob = require('rn-fetch-blob');
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
eSendEvent(eOpenProgressDialog, {
|
||||
title: 'Backing up your data',
|
||||
paragraph:
|
||||
@@ -35,6 +33,7 @@ async function run() {
|
||||
} catch (e) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
try {
|
||||
let backupName = 'notesnook_backup_' + Date.now() + '.nnbackup';
|
||||
@@ -42,6 +41,7 @@ async function run() {
|
||||
await RNFetchBlob.fs.createFile(path + backupName, backup, 'utf8');
|
||||
await MMKV.setItem('backupDate', JSON.stringify(Date.now()));
|
||||
ToastEvent.show('Backup complete!', 'success');
|
||||
|
||||
eSendEvent(eOpenProgressDialog, {
|
||||
title: 'Backup Complete',
|
||||
icon: 'cloud-upload',
|
||||
|
||||
@@ -44,7 +44,7 @@ async function saveToMarkdown(note) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
let markdown = await db.notes.note(note.id).export('md');
|
||||
|
||||
path = path + note.title + '.md';
|
||||
@@ -66,7 +66,7 @@ async function saveToText(note) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
let text = await db.notes.note(note.id).export('txt');
|
||||
path = path + note.title + '.txt';
|
||||
await RNFetchBlob.fs.writeFile(path, text, 'utf8');
|
||||
@@ -87,7 +87,7 @@ async function saveToHTML(note) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
let html = await db.notes.note(note.id).export('html');
|
||||
path = path + note.title + '.html';
|
||||
await RNFetchBlob.fs.writeFile(path, html, 'utf8');
|
||||
|
||||
@@ -7,6 +7,7 @@ import {MMKV} from '../utils/mmkv';
|
||||
import {scale, updateSize} from '../utils/SizeUtils';
|
||||
import {enabled} from 'react-native-privacy-snapshot';
|
||||
import {Platform} from 'react-native';
|
||||
import Navigation from './Navigation';
|
||||
|
||||
let settings = defaultState.settings;
|
||||
|
||||
@@ -22,13 +23,24 @@ function getApploaded() {
|
||||
|
||||
async function init() {
|
||||
scale.fontScale = 1;
|
||||
settings = await MMKV.getStringAsync('appSettings');
|
||||
settings = await MMKV.getItem('appSettings');
|
||||
if (!settings) {
|
||||
settings = defaultState.settings;
|
||||
await MMKV.setStringAsync('appSettings', JSON.stringify(settings));
|
||||
await MMKV.setItem('appSettings', JSON.stringify(settings));
|
||||
} else {
|
||||
settings = JSON.parse(settings);
|
||||
}
|
||||
Navigation.setHeaderState(
|
||||
settings.homepage,
|
||||
{
|
||||
menu: true,
|
||||
},
|
||||
{
|
||||
heading: settings.homepage,
|
||||
id: settings.homepage.toLowerCase() + '_navigation',
|
||||
},
|
||||
);
|
||||
|
||||
if (settings.fontScale) {
|
||||
scale.fontScale = settings.fontScale;
|
||||
}
|
||||
@@ -56,14 +68,13 @@ async function init() {
|
||||
const setTheme = async () => {
|
||||
if (settings) {
|
||||
let newColors = await getColorScheme(settings.useSystemTheme);
|
||||
|
||||
updateEvent({type: Actions.THEME, colors: newColors});
|
||||
}
|
||||
};
|
||||
|
||||
async function set(name, value) {
|
||||
settings[name] = value;
|
||||
await MMKV.setStringAsync('appSettings', JSON.stringify(settings));
|
||||
await MMKV.setItem('appSettings', JSON.stringify(settings));
|
||||
updateEvent({type: Actions.SETTINGS, settings: {...settings}});
|
||||
}
|
||||
|
||||
@@ -71,8 +82,6 @@ function get() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
init,
|
||||
setTheme,
|
||||
|
||||
@@ -64,12 +64,12 @@ export const RGB_Linear_Shade = (p, rgba) => {
|
||||
|
||||
export async function getColorScheme(useSystemTheme) {
|
||||
|
||||
let accentColor = await MMKV.getStringAsync('accentColor');
|
||||
let theme= await MMKV.getStringAsync('theme');
|
||||
let accentColor = await MMKV.getItem('accentColor');
|
||||
let theme= await MMKV.getItem('theme');
|
||||
|
||||
|
||||
if (!accentColor ) {
|
||||
await MMKV.setStringAsync('accentColor', '#0560FF');
|
||||
await MMKV.setItem('accentColor', '#0560FF');
|
||||
setAccentColor('#0560FF');
|
||||
} else {
|
||||
setAccentColor(accentColor);
|
||||
@@ -84,7 +84,7 @@ export async function getColorScheme(useSystemTheme) {
|
||||
}
|
||||
|
||||
if (!theme) {
|
||||
await MMKV.setStringAsync('theme', JSON.stringify({night: false}));
|
||||
await MMKV.setItem('theme', JSON.stringify({night: false}));
|
||||
setColorScheme(COLOR_SCHEME_LIGHT);
|
||||
} else {
|
||||
theme = JSON.parse(theme);
|
||||
|
||||
@@ -8,12 +8,12 @@ let Sodium;
|
||||
let Keychain;
|
||||
let RNFetchBlob;
|
||||
async function read(key, isArray = false) {
|
||||
let data = await MMKV.getItem(key);
|
||||
if (!data) return null;
|
||||
try {
|
||||
data = JSON.parse(data);
|
||||
} catch (e) {}
|
||||
|
||||
//let per = performance.now();
|
||||
let data = await MMKV.getItem(key);
|
||||
//console.log("[INIT S1]",key + "_key", performance.now() - per);
|
||||
if (!data) return null;
|
||||
data = JSON.parse(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -74,10 +74,11 @@ let CRYPT_CONFIG = (kc) =>
|
||||
android: {
|
||||
authenticationType: kc.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS,
|
||||
accessControl: kc.ACCESS_CONTROL.DEVICE_PASSCODE,
|
||||
rules: kc.SECURITY_RULES.AUTOMATIC_UPGRADE,
|
||||
rules: "none",
|
||||
authenticationPrompt: {
|
||||
cancel: null,
|
||||
},
|
||||
storage: kc.STORAGE_TYPE.AES
|
||||
},
|
||||
});
|
||||
|
||||
@@ -87,7 +88,7 @@ async function deriveCryptoKey(name, data) {
|
||||
}
|
||||
|
||||
if (!Sodium) {
|
||||
Sodium = require('react-native-sodium');
|
||||
Sodium = require('react-native-sodium')
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -96,7 +97,9 @@ async function deriveCryptoKey(name, data) {
|
||||
'notesnook',
|
||||
name,
|
||||
credentials.key,
|
||||
CRYPT_CONFIG(Keychain),
|
||||
{
|
||||
|
||||
},
|
||||
);
|
||||
return credentials.key;
|
||||
} catch (e) {}
|
||||
@@ -121,7 +124,7 @@ async function getCryptoKey(name) {
|
||||
|
||||
async function removeCryptoKey(name) {
|
||||
if (!Keychain) {
|
||||
Keychain = require('react-native-keychain');
|
||||
Keychain = require('react-native-keychain')
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -154,7 +157,7 @@ async function requestPermission() {
|
||||
}
|
||||
async function checkAndCreateDir(path) {
|
||||
if (!RNFetchBlob) {
|
||||
RNFetchBlob = require('rn-fetch-blob');
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
}
|
||||
|
||||
let dir =
|
||||
|
||||
@@ -48,7 +48,7 @@ const style = {
|
||||
const Editor = React.memo(
|
||||
() => {
|
||||
const [state] = useTracked();
|
||||
const {premiumUser, loading} = state;
|
||||
const {premiumUser} = state;
|
||||
const [resetting, setResetting] = useState(false);
|
||||
const [localLoading, setLocalLoading] = useState(false);
|
||||
const onLoad = async () => {
|
||||
@@ -65,15 +65,14 @@ const Editor = React.memo(
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) {
|
||||
eSubscribeEvent('webviewreset', onResetRequested);
|
||||
}
|
||||
eSubscribeEvent('webviewreset', onResetRequested);
|
||||
|
||||
return () => {
|
||||
eUnSubscribeEvent('webviewreset', onResetRequested);
|
||||
};
|
||||
}, [loading]);
|
||||
}, []);
|
||||
|
||||
return resetting || loading ? (
|
||||
return resetting ? (
|
||||
<Loading
|
||||
tagline={resetting ? 'Reloading Editor' : 'Loading Editor'}
|
||||
height="100%"
|
||||
|
||||
@@ -54,7 +54,7 @@ export const execCommands = {
|
||||
type: [DocumentPicker.types.images],
|
||||
}).then((r) => {
|
||||
|
||||
RNFetchBlob = require("rn-fetch-blob");
|
||||
RNFetchBlob = require('rn-fetch-blob').default
|
||||
RNFetchBlob.fs.readFile(r.uri, 'base64').then((read) => {
|
||||
let b64 = `data:${r.type};base64, ` + read;
|
||||
formatSelection(`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
import { AsyncStorage } from 'react-native';
|
||||
import {InteractionManager} from 'react-native';
|
||||
import {ContainerBottomButton} from '../../components/Container/ContainerBottomButton';
|
||||
import SimpleList from '../../components/SimpleList';
|
||||
@@ -85,6 +86,7 @@ export const Home = ({route, navigation}) => {
|
||||
};
|
||||
|
||||
const _onPressBottomButton = async () => {
|
||||
|
||||
if (!DDS.isLargeTablet()) {
|
||||
tabBarRef.current?.goToPage(1);
|
||||
} else {
|
||||
|
||||
@@ -1100,13 +1100,7 @@ const SettingsBackupAndRestore = () => {
|
||||
{
|
||||
name: 'Backup data',
|
||||
func: async () => {
|
||||
eSendEvent(eOpenProgressDialog, {
|
||||
title: 'Backing up your data',
|
||||
paragraph:
|
||||
"All your backups are stored in 'Phone Storage/Notesnook/backups/' folder",
|
||||
});
|
||||
await Backup.run();
|
||||
eSendEvent(eCloseProgressDialog);
|
||||
},
|
||||
desc: 'Backup your data to phone storage',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user