You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	All: Got E2EE working in mobile app
This commit is contained in:
		| @@ -8,22 +8,13 @@ const { themeStyle } = require('../theme.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const { time } = require('lib/time-utils.js'); | ||||
| const dialogs = require('./dialogs'); | ||||
| const shared = require('lib/components/shared/encryption-config-shared.js'); | ||||
|  | ||||
| class EncryptionConfigScreenComponent extends React.Component { | ||||
|  | ||||
| 	constructor() { | ||||
| 		super(); | ||||
| 		this.state = { | ||||
| 			masterKeys: [], | ||||
| 			passwords: {}, | ||||
| 			passwordChecks: {}, | ||||
| 			stats: { | ||||
| 				encrypted: null, | ||||
| 				total: null, | ||||
| 			}, | ||||
| 		}; | ||||
| 		this.isMounted_ = false; | ||||
| 		this.refreshStatsIID_ = null; | ||||
| 		shared.constructor(this); | ||||
| 	} | ||||
|  | ||||
| 	componentDidMount() { | ||||
| @@ -35,28 +26,11 @@ class EncryptionConfigScreenComponent extends React.Component { | ||||
| 	} | ||||
|  | ||||
| 	initState(props) { | ||||
| 		this.setState({ | ||||
| 			masterKeys: props.masterKeys, | ||||
| 			passwords: props.passwords ? props.passwords : {}, | ||||
| 		}, () => { | ||||
| 			this.checkPasswords(); | ||||
| 		}); | ||||
| 		return shared.initState(this, props); | ||||
| 	} | ||||
|  | ||||
| 		this.refreshStats(); | ||||
|  | ||||
| 		if (this.refreshStatsIID_) { | ||||
| 			clearInterval(this.refreshStatsIID_); | ||||
| 			this.refreshStatsIID_ = null; | ||||
| 		} | ||||
|  | ||||
| 		this.refreshStatsIID_ = setInterval(() => { | ||||
| 			if (!this.isMounted_) { | ||||
| 				clearInterval(this.refreshStatsIID_); | ||||
| 				this.refreshStatsIID_ = null; | ||||
| 				return; | ||||
| 			} | ||||
| 			this.refreshStats(); | ||||
| 		}, 3000); | ||||
| 	async refreshStats() { | ||||
| 		return shared.refreshStats(this); | ||||
| 	} | ||||
|  | ||||
| 	componentWillMount() { | ||||
| @@ -67,40 +41,19 @@ class EncryptionConfigScreenComponent extends React.Component { | ||||
| 		this.initState(nextProps); | ||||
| 	} | ||||
|  | ||||
| 	async refreshStats() { | ||||
| 		const stats = await BaseItem.encryptedItemsStats(); | ||||
| 		this.setState({ stats: stats }); | ||||
| 	} | ||||
|  | ||||
| 	async checkPasswords() { | ||||
| 		const passwordChecks = Object.assign({}, this.state.passwordChecks); | ||||
| 		for (let i = 0; i < this.state.masterKeys.length; i++) { | ||||
| 			const mk = this.state.masterKeys[i]; | ||||
| 			const password = this.state.passwords[mk.id]; | ||||
| 			const ok = password ? await EncryptionService.instance().checkMasterKeyPassword(mk, password) : false; | ||||
| 			passwordChecks[mk.id] = ok; | ||||
| 		} | ||||
| 		this.setState({ passwordChecks: passwordChecks }); | ||||
| 		return shared.checkPasswords(this); | ||||
| 	} | ||||
|  | ||||
| 	renderMasterKey(mk) { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		const onSaveClick = () => { | ||||
| 			const password = this.state.passwords[mk.id]; | ||||
| 			if (!password) { | ||||
| 				Setting.deleteObjectKey('encryption.passwordCache', mk.id); | ||||
| 			} else { | ||||
| 				Setting.setObjectKey('encryption.passwordCache', mk.id, password); | ||||
| 			} | ||||
|  | ||||
| 			this.checkPasswords(); | ||||
| 			return shared.onSavePasswordClick(this, mk); | ||||
| 		} | ||||
|  | ||||
| 		const onPasswordChange = (event) => { | ||||
| 			const passwords = this.state.passwords; | ||||
| 			passwords[mk.id] = event.target.value; | ||||
| 			this.setState({ passwords: passwords }); | ||||
| 			return shared.onPasswordChange(this, mk, event.target.value); | ||||
| 		} | ||||
|  | ||||
| 		const password = this.state.passwords[mk.id] ? this.state.passwords[mk.id] : ''; | ||||
| @@ -166,8 +119,7 @@ class EncryptionConfigScreenComponent extends React.Component { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const stats = this.state.stats; | ||||
| 		const decryptedItemsInfo = this.props.encryptionEnabled ? <p style={theme.textStyle}>{_('Decrypted items: %s / %s', stats.encrypted !== null ? (stats.total - stats.encrypted) : '-', stats.total !== null ? stats.total : '-')}</p> : null; | ||||
| 		const decryptedItemsInfo = this.props.encryptionEnabled ? <p style={theme.textStyle}>{shared.decryptedStatText(this)}</p> : null; | ||||
| 		const toggleButton = <button onClick={() => { onToggleButtonClick() }}>{this.props.encryptionEnabled ? _('Disable encryption') : _('Enable encryption')}</button> | ||||
|  | ||||
| 		let masterKeySection = null; | ||||
|   | ||||
| @@ -19,6 +19,8 @@ const globalStyle = { | ||||
| 	raisedColor: "#003363", | ||||
| 	raisedHighlightedColor: "#ffffff", | ||||
|  | ||||
| 	warningBackgroundColor: "#FFD08D", | ||||
|  | ||||
| 	// For WebView - must correspond to the properties above | ||||
| 	htmlFontSize: '16px', | ||||
| 	htmlColor: 'black', // Note: CSS in WebView component only supports named colors or rgb() notation | ||||
|   | ||||
| @@ -43,7 +43,7 @@ class ScreenHeaderComponent extends Component { | ||||
|  | ||||
| 		let styleObject = { | ||||
| 			container: { | ||||
| 				flexDirection: 'row', | ||||
| 				flexDirection: 'column', | ||||
| 				backgroundColor: theme.raisedBackgroundColor, | ||||
| 				alignItems: 'center', | ||||
| 				shadowColor: '#000000', | ||||
| @@ -123,11 +123,17 @@ class ScreenHeaderComponent extends Component { | ||||
| 			}, | ||||
| 			titleText: { | ||||
| 				flex: 1, | ||||
| 				textAlignVertical: 'center', | ||||
| 				marginLeft: 0, | ||||
| 				color: theme.raisedHighlightedColor, | ||||
| 				fontWeight: 'bold', | ||||
| 				fontSize: theme.fontSize, | ||||
| 			} | ||||
| 			}, | ||||
| 			warningBox: { | ||||
| 				backgroundColor: "#ff9900", | ||||
| 				flexDirection: 'row', | ||||
| 				padding: theme.marginLeft, | ||||
| 			}, | ||||
| 		}; | ||||
|  | ||||
| 		styleObject.topIcon = Object.assign({}, theme.icon); | ||||
| @@ -198,6 +204,20 @@ class ScreenHeaderComponent extends Component { | ||||
| 		});	 | ||||
| 	} | ||||
|  | ||||
| 	encryptionConfig_press() { | ||||
| 		this.props.dispatch({ | ||||
| 			type: 'NAV_GO', | ||||
| 			routeName: 'EncryptionConfig', | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	warningBox_press() { | ||||
| 		this.props.dispatch({ | ||||
| 			type: 'NAV_GO', | ||||
| 			routeName: 'EncryptionConfig', | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	async debugReport_press() { | ||||
| 		const service = new ReportService(); | ||||
|  | ||||
| @@ -324,6 +344,11 @@ class ScreenHeaderComponent extends Component { | ||||
| 				menuOptionComponents.push(<View key={'menuOption_' + key++} style={this.styles().divider}/>); | ||||
| 			} | ||||
|  | ||||
| 			menuOptionComponents.push( | ||||
| 				<MenuOption value={() => this.encryptionConfig_press()} key={'menuOption_encryptionConfig'} style={this.styles().contextMenuItem}> | ||||
| 					<Text style={this.styles().contextMenuItemText}>{_('Encryption Configuration')}</Text> | ||||
| 				</MenuOption>); | ||||
|  | ||||
| 			menuOptionComponents.push( | ||||
| 				<MenuOption value={() => this.config_press()} key={'menuOption_config'} style={this.styles().contextMenuItem}> | ||||
| 					<Text style={this.styles().contextMenuItemText}>{_('Configuration')}</Text> | ||||
| @@ -405,6 +430,12 @@ class ScreenHeaderComponent extends Component { | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const warningComp = this.props.showMissingMasterKeyMessage ? ( | ||||
| 			<TouchableOpacity style={this.styles().warningBox} onPress={() => this.warningBox_press()} activeOpacity={0.8}> | ||||
| 				<Text style={{flex:1}}>{_('Press to set the decryption password.')}</Text> | ||||
| 			</TouchableOpacity> | ||||
| 		) : null; | ||||
|  | ||||
| 		const titleComp = createTitleComponent(); | ||||
| 		const sideMenuComp = this.props.noteSelectionEnabled ? null : sideMenuButton(this.styles(), () => this.sideMenuButton_press()); | ||||
| 		const backButtonComp = backButton(this.styles(), () => this.backButton_press(), !this.props.historyCanGoBack); | ||||
| @@ -427,13 +458,16 @@ class ScreenHeaderComponent extends Component { | ||||
|  | ||||
| 		return ( | ||||
| 			<View style={this.styles().container} > | ||||
| 				{ sideMenuComp } | ||||
| 				{ backButtonComp } | ||||
| 				{ saveButton(this.styles(), () => { if (this.props.onSaveButtonPress) this.props.onSaveButtonPress() }, this.props.saveButtonDisabled === true, this.props.showSaveButton === true) } | ||||
| 				{ titleComp } | ||||
| 				{ searchButtonComp } | ||||
| 				{ deleteButtonComp } | ||||
| 				{ menuComp } | ||||
| 				<View style={{flexDirection:'row'}}> | ||||
| 					{ sideMenuComp } | ||||
| 					{ backButtonComp } | ||||
| 					{ saveButton(this.styles(), () => { if (this.props.onSaveButtonPress) this.props.onSaveButtonPress() }, this.props.saveButtonDisabled === true, this.props.showSaveButton === true) } | ||||
| 					{ titleComp } | ||||
| 					{ searchButtonComp } | ||||
| 					{ deleteButtonComp } | ||||
| 					{ menuComp } | ||||
| 				</View> | ||||
| 				{ warningComp } | ||||
| 				<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/> | ||||
| 			</View> | ||||
| 		); | ||||
| @@ -455,6 +489,7 @@ const ScreenHeader = connect( | ||||
| 			showAdvancedOptions: state.settings.showAdvancedOptions, | ||||
| 			noteSelectionEnabled: state.noteSelectionEnabled, | ||||
| 			selectedNoteIds: state.selectedNoteIds, | ||||
| 			showMissingMasterKeyMessage: state.notLoadedMasterKeys.length && state.masterKeys.length, | ||||
| 		}; | ||||
| 	} | ||||
| )(ScreenHeaderComponent) | ||||
|   | ||||
							
								
								
									
										151
									
								
								ReactNativeClient/lib/components/screens/encryption-config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								ReactNativeClient/lib/components/screens/encryption-config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| const React = require('react'); const Component = React.Component; | ||||
| const { TextInput, TouchableOpacity, Linking, View, Switch, Slider, StyleSheet, Text, Button, ScrollView } = require('react-native'); | ||||
| const { connect } = require('react-redux'); | ||||
| const { ScreenHeader } = require('lib/components/screen-header.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const { BaseScreenComponent } = require('lib/components/base-screen.js'); | ||||
| const { Dropdown } = require('lib/components/Dropdown.js'); | ||||
| const { themeStyle } = require('lib/components/global-style.js'); | ||||
| const { time } = require('lib/time-utils.js'); | ||||
| const Setting = require('lib/models/Setting.js'); | ||||
| const shared = require('lib/components/shared/encryption-config-shared.js'); | ||||
|  | ||||
| class EncryptionConfigScreenComponent extends BaseScreenComponent { | ||||
| 	 | ||||
| 	static navigationOptions(options) { | ||||
| 		return { header: null }; | ||||
| 	} | ||||
|  | ||||
| 	constructor() { | ||||
| 		super(); | ||||
|  | ||||
| 		shared.constructor(this); | ||||
|  | ||||
| 		this.styles_ = {}; | ||||
| 	} | ||||
|  | ||||
| 	componentDidMount() { | ||||
| 		this.isMounted_ = true; | ||||
| 	} | ||||
|  | ||||
| 	componentWillUnmount() { | ||||
| 		this.isMounted_ = false; | ||||
| 	} | ||||
|  | ||||
| 	initState(props) { | ||||
| 		return shared.initState(this, props); | ||||
| 	} | ||||
|  | ||||
| 	async refreshStats() { | ||||
| 		return shared.refreshStats(this); | ||||
| 	} | ||||
|  | ||||
| 	componentWillMount() { | ||||
| 		this.initState(this.props); | ||||
| 	} | ||||
|  | ||||
| 	componentWillReceiveProps(nextProps) { | ||||
| 		this.initState(nextProps); | ||||
| 	} | ||||
|  | ||||
| 	async checkPasswords() { | ||||
| 		return shared.checkPasswords(this); | ||||
| 	} | ||||
|  | ||||
| 	styles() { | ||||
| 		const themeId = this.props.theme; | ||||
| 		const theme = themeStyle(themeId); | ||||
|  | ||||
| 		if (this.styles_[themeId]) return this.styles_[themeId]; | ||||
| 		this.styles_ = {}; | ||||
|  | ||||
| 		let styles = { | ||||
| 			titleText: { | ||||
| 				flex: 1, | ||||
| 				fontWeight: 'bold', | ||||
| 				flexDirection: 'column', | ||||
| 				fontSize: theme.fontSize, | ||||
| 				paddingTop: 5, | ||||
| 				paddingBottom: 5, | ||||
| 			}, | ||||
| 			normalText: { | ||||
| 				flex: 1, | ||||
| 				fontSize: theme.fontSize, | ||||
| 			}, | ||||
| 			container: { | ||||
| 				flex: 1, | ||||
| 				padding: theme.margin, | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| 		this.styles_[themeId] = StyleSheet.create(styles); | ||||
| 		return this.styles_[themeId]; | ||||
| 	} | ||||
|  | ||||
| 	renderMasterKey(num, mk) { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		const onSaveClick = () => { | ||||
| 			return shared.onSavePasswordClick(this, mk); | ||||
| 		} | ||||
|  | ||||
| 		const onPasswordChange = (text) => { | ||||
| 			return shared.onPasswordChange(this, mk, text); | ||||
| 		} | ||||
|  | ||||
| 		const password = this.state.passwords[mk.id] ? this.state.passwords[mk.id] : ''; | ||||
| 		const passwordOk = this.state.passwordChecks[mk.id] === true ? '✔' : '❌'; | ||||
| 		const active = this.props.activeMasterKeyId === mk.id ? '✔' : ''; | ||||
|  | ||||
| 		return ( | ||||
| 			<View key={mk.id}> | ||||
| 				<Text style={this.styles().titleText}>{_('Master Key %d', num)}</Text> | ||||
| 				<Text style={this.styles().normalText}>{_('Created: %s', time.formatMsToLocal(mk.created_time))}</Text> | ||||
| 				<View style={{flexDirection: 'row', alignItems: 'center'}}> | ||||
| 					<Text style={{flex:0, fontSize: theme.fontSize, marginRight: 10}}>{_('Password:')}</Text> | ||||
| 					<TextInput value={password} onChangeText={(text) => onPasswordChange(text)} style={{flex:1, marginRight: 10}}></TextInput> | ||||
| 					<Text style={{fontSize: theme.fontSize, marginRight: 10}}>{passwordOk}</Text> | ||||
| 					<Button title={_('Save')} onPress={() => onSaveClick()}></Button> | ||||
| 				</View> | ||||
| 			</View> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const masterKeys = this.state.masterKeys; | ||||
| 		const decryptedItemsInfo = this.props.encryptionEnabled ? <Text style={this.styles().normalText}>{shared.decryptedStatText(this)}</Text> : null; | ||||
|  | ||||
| 		const mkComps = []; | ||||
| 		for (let i = 0; i < masterKeys.length; i++) { | ||||
| 			const mk = masterKeys[i]; | ||||
| 			mkComps.push(this.renderMasterKey(i+1, mk)); | ||||
| 		} | ||||
|  | ||||
| 		return ( | ||||
| 			<View style={this.rootStyle(this.props.theme).root}> | ||||
| 				<ScreenHeader title={_('Configuration')}/> | ||||
| 				<ScrollView style={this.styles().container}> | ||||
| 					<Text style={this.styles().titleText}>{_('Status')}</Text> | ||||
| 					<Text style={this.styles().normalText}>{_('Encryption is: %s', this.props.encryptionEnabled ? _('Enabled') : _('Disabled'))}</Text> | ||||
| 					{decryptedItemsInfo} | ||||
| 					{mkComps} | ||||
| 				</ScrollView> | ||||
| 			</View> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| const EncryptionConfigScreen = connect( | ||||
| 	(state) => { | ||||
| 		return { | ||||
| 			theme: state.settings.theme, | ||||
| 			masterKeys: state.masterKeys, | ||||
| 			passwords: state.settings['encryption.passwordCache'], | ||||
| 			encryptionEnabled: state.settings['encryption.enabled'], | ||||
| 			activeMasterKeyId: state.settings['encryption.activeMasterKeyId'], | ||||
| 		}; | ||||
| 	} | ||||
| )(EncryptionConfigScreenComponent) | ||||
|  | ||||
| module.exports = { EncryptionConfigScreen }; | ||||
| @@ -0,0 +1,87 @@ | ||||
| const EncryptionService = require('lib/services/EncryptionService'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const BaseItem = require('lib/models/BaseItem.js'); | ||||
| const Setting = require('lib/models/Setting.js'); | ||||
|  | ||||
| const shared = {}; | ||||
|  | ||||
| shared.constructor = function(comp) { | ||||
| 	comp.state = { | ||||
| 		masterKeys: [], | ||||
| 		passwords: {}, | ||||
| 		passwordChecks: {}, | ||||
| 		stats: { | ||||
| 			encrypted: null, | ||||
| 			total: null, | ||||
| 		}, | ||||
| 	}; | ||||
| 	comp.isMounted_ = false; | ||||
|  | ||||
| 	comp.refreshStatsIID_ = null; | ||||
| } | ||||
|  | ||||
| shared.initState = function(comp, props) { | ||||
| 	comp.setState({ | ||||
| 		masterKeys: props.masterKeys, | ||||
| 		passwords: props.passwords ? props.passwords : {}, | ||||
| 	}, () => { | ||||
| 		comp.checkPasswords(); | ||||
| 	}); | ||||
|  | ||||
| 	comp.refreshStats(); | ||||
|  | ||||
| 	if (comp.refreshStatsIID_) { | ||||
| 		clearInterval(comp.refreshStatsIID_); | ||||
| 		comp.refreshStatsIID_ = null; | ||||
| 	} | ||||
|  | ||||
| 	comp.refreshStatsIID_ = setInterval(() => { | ||||
| 		if (!comp.isMounted_) { | ||||
| 			clearInterval(comp.refreshStatsIID_); | ||||
| 			comp.refreshStatsIID_ = null; | ||||
| 			return; | ||||
| 		} | ||||
| 		comp.refreshStats(); | ||||
| 	}, 3000); | ||||
| } | ||||
|  | ||||
| shared.refreshStats = async function(comp) { | ||||
| 	const stats = await BaseItem.encryptedItemsStats(); | ||||
| 	comp.setState({ stats: stats }); | ||||
| } | ||||
|  | ||||
| shared.checkPasswords = async function(comp) { | ||||
| 	const passwordChecks = Object.assign({}, comp.state.passwordChecks); | ||||
| 	for (let i = 0; i < comp.state.masterKeys.length; i++) { | ||||
| 		const mk = comp.state.masterKeys[i]; | ||||
| 		const password = comp.state.passwords[mk.id]; | ||||
| 		const ok = password ? await EncryptionService.instance().checkMasterKeyPassword(mk, password) : false; | ||||
| 		passwordChecks[mk.id] = ok; | ||||
| 	} | ||||
| 	console.info(passwordChecks); | ||||
| 	comp.setState({ passwordChecks: passwordChecks }); | ||||
| } | ||||
|  | ||||
| shared.decryptedStatText = function(comp) { | ||||
| 	const stats = comp.state.stats; | ||||
| 	return _('Decrypted items: %s / %s', stats.encrypted !== null ? (stats.total - stats.encrypted) : '-', stats.total !== null ? stats.total : '-'); | ||||
| } | ||||
|  | ||||
| shared.onSavePasswordClick = function(comp, mk) { | ||||
| 	const password = comp.state.passwords[mk.id]; | ||||
| 	if (!password) { | ||||
| 		Setting.deleteObjectKey('encryption.passwordCache', mk.id); | ||||
| 	} else { | ||||
| 		Setting.setObjectKey('encryption.passwordCache', mk.id, password); | ||||
| 	} | ||||
|  | ||||
| 	comp.checkPasswords(); | ||||
| } | ||||
|  | ||||
| shared.onPasswordChange = function(comp, mk, password) { | ||||
| 	const passwords = comp.state.passwords; | ||||
| 	passwords[mk.id] = password; | ||||
| 	comp.setState({ passwords: passwords }); | ||||
| } | ||||
|  | ||||
| module.exports = shared; | ||||
| @@ -33,6 +33,7 @@ const { StatusScreen } = require('lib/components/screens/status.js'); | ||||
| const { WelcomeScreen } = require('lib/components/screens/welcome.js'); | ||||
| const { SearchScreen } = require('lib/components/screens/search.js'); | ||||
| const { OneDriveLoginScreen } = require('lib/components/screens/onedrive-login.js'); | ||||
| const { EncryptionConfigScreen } = require('lib/components/screens/encryption-config.js'); | ||||
| const Setting = require('lib/models/Setting.js'); | ||||
| const { MenuContext } = require('react-native-popup-menu'); | ||||
| const { SideMenu } = require('lib/components/side-menu.js'); | ||||
| @@ -51,6 +52,10 @@ const SyncTargetOneDriveDev = require('lib/SyncTargetOneDriveDev.js'); | ||||
| SyncTargetRegistry.addClass(SyncTargetOneDrive); | ||||
| SyncTargetRegistry.addClass(SyncTargetOneDriveDev); | ||||
|  | ||||
| const FsDriverRN = require('lib/fs-driver-rn.js').FsDriverRN; | ||||
| const DecryptionWorker = require('lib/services/DecryptionWorker'); | ||||
| const EncryptionService = require('lib/services/EncryptionService'); | ||||
|  | ||||
| const generalMiddleware = store => next => async (action) => { | ||||
| 	if (action.type !== 'SIDE_MENU_OPEN_PERCENT') reg.logger().info('Reducer action', action.type); | ||||
| 	PoorManIntervals.update(); // This function needs to be called regularly so put it here | ||||
| @@ -85,6 +90,10 @@ const generalMiddleware = store => next => async (action) => { | ||||
| 		Setting.setValue('activeFolderId', newState.selectedFolderId); | ||||
| 	} | ||||
|  | ||||
| 	if (action.type === 'SYNC_GOT_ENCRYPTED_ITEM') { | ||||
| 		DecryptionWorker.instance().scheduleStart(); | ||||
| 	} | ||||
|  | ||||
|   	return result; | ||||
| } | ||||
|  | ||||
| @@ -307,6 +316,10 @@ async function initialize(dispatch) { | ||||
| 	BaseItem.loadClass('NoteTag', NoteTag); | ||||
| 	BaseItem.loadClass('MasterKey', MasterKey); | ||||
|  | ||||
| 	const fsDriver = new FsDriverRN(); | ||||
|  | ||||
| 	Resource.fsDriver_ = fsDriver; | ||||
|  | ||||
| 	AlarmService.setDriver(new AlarmServiceDriver()); | ||||
| 	AlarmService.setLogger(mainLogger); | ||||
|  | ||||
| @@ -343,6 +356,21 @@ async function initialize(dispatch) { | ||||
|  | ||||
| 		setLocale(Setting.value('locale')); | ||||
|  | ||||
| 		// ---------------------------------------------------------------- | ||||
| 		// E2EE SETUP | ||||
| 		// ---------------------------------------------------------------- | ||||
|  | ||||
| 		EncryptionService.fsDriver_ = fsDriver; | ||||
| 		EncryptionService.instance().setLogger(mainLogger); | ||||
| 		BaseItem.encryptionService_ = EncryptionService.instance(); | ||||
| 		DecryptionWorker.instance().setLogger(mainLogger); | ||||
| 		DecryptionWorker.instance().setEncryptionService(EncryptionService.instance()); | ||||
| 		await EncryptionService.instance().loadMasterKeysFromSettings(); | ||||
|  | ||||
| 		// ---------------------------------------------------------------- | ||||
| 		// / E2EE SETUP | ||||
| 		// ---------------------------------------------------------------- | ||||
|  | ||||
| 		reg.logger().info('Loading folders...'); | ||||
|  | ||||
| 		await FoldersScreenUtils.refreshFolders(); | ||||
| @@ -354,6 +382,13 @@ async function initialize(dispatch) { | ||||
| 			items: tags, | ||||
| 		}); | ||||
|  | ||||
| 		const masterKeys = await MasterKey.all(); | ||||
|  | ||||
| 		dispatch({ | ||||
| 			type: 'MASTERKEY_UPDATE_ALL', | ||||
| 			items: masterKeys, | ||||
| 		}); | ||||
|  | ||||
| 		let folderId = Setting.value('activeFolderId'); | ||||
| 		let folder = await Folder.load(folderId); | ||||
|  | ||||
| @@ -385,6 +420,8 @@ async function initialize(dispatch) { | ||||
| 		// Wait for the first sync before updating the notifications, since synchronisation | ||||
| 		// might change the notifications. | ||||
| 		AlarmService.updateAllNotifications(); | ||||
|  | ||||
| 		DecryptionWorker.instance().scheduleStart(); | ||||
| 	}); | ||||
|  | ||||
| 	reg.logger().info('Application initialized'); | ||||
| @@ -472,6 +509,7 @@ class AppComponent extends React.Component { | ||||
| 			Note: { screen: NoteScreen }, | ||||
| 			Folder: { screen: FolderScreen }, | ||||
| 			OneDriveLogin: { screen: OneDriveLoginScreen }, | ||||
| 			EncryptionConfig: { screen: EncryptionConfigScreen }, | ||||
| 			Log: { screen: LogScreen }, | ||||
| 			Status: { screen: StatusScreen }, | ||||
| 			Search: { screen: SearchScreen }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user