diff --git a/ElectronClient/app/gui/NoteText.jsx b/ElectronClient/app/gui/NoteText.jsx index 493e02a6f..e90b235fd 100644 --- a/ElectronClient/app/gui/NoteText.jsx +++ b/ElectronClient/app/gui/NoteText.jsx @@ -853,7 +853,7 @@ class NoteTextComponent extends React.Component { this.editor_.editor.renderer.on('afterRender', this.onAfterEditorRender_); const cancelledKeys = []; - const letters = ['F', 'T', 'P', 'Q', 'L', ',', 'G']; + const letters = ['F', 'T', 'P', 'Q', 'L', ',', 'G', 'K']; for (let i = 0; i < letters.length; i++) { const l = letters[i]; cancelledKeys.push('Ctrl+' + l); diff --git a/ReactNativeClient/lib/components/screens/config.js b/ReactNativeClient/lib/components/screens/config.js index 633e910ba..d139193bb 100644 --- a/ReactNativeClient/lib/components/screens/config.js +++ b/ReactNativeClient/lib/components/screens/config.js @@ -17,6 +17,7 @@ const { time } = require('lib/time-utils'); const SearchEngine = require('lib/services/SearchEngine'); const RNFS = require('react-native-fs'); +import { PermissionsAndroid } from 'react-native'; import Slider from '@react-native-community/slider'; class ConfigScreenComponent extends BaseScreenComponent { @@ -43,7 +44,22 @@ class ConfigScreenComponent extends BaseScreenComponent { NavService.go('EncryptionConfig'); } - this.saveButton_press = () => { + this.saveButton_press = async () => { + if ( + this.state.changedSettingKeys.includes('sync.target') + && this.state.settings['sync.target'] === SyncTargetRegistry.nameToId('filesystem') + && !await this.checkFilesystemPermission() + ) { + Alert.alert( + _('Warning'), + _( + 'Joplin does not have permission to access "%s". ' + + 'Either choose a different sync target, ' + + 'or give Joplin the "Storage" permission.', + this.state.settings['sync.2.path'], + )); + // Save settings anyway, even if permission has not been granted + } return shared.saveSettings(this); }; @@ -90,6 +106,30 @@ class ConfigScreenComponent extends BaseScreenComponent { } } + async checkFilesystemPermission() { + if (Platform.OS !== 'android') { + // Not implemented yet + return true; + } + const hasPermission = await PermissionsAndroid.check( + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE); + if (hasPermission) { + return true; + } + const requestResult = await PermissionsAndroid.request( + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, + { + title: _('Permission to write to external storage'), + message: _( + 'In order to use file system synchronization your ' + + 'permission to write to external storage is required.' + ), + buttonPositive: _('OK'), + }, + ); + return (requestResult === PermissionsAndroid.RESULTS.GRANTED); + } + UNSAFE_componentWillMount() { this.setState({ settings: this.props.settings }); }