mirror of https://github.com/laurent22/joplin.git
Merge branch 'master' of github.com:laurent22/joplin
commit
4c4ed60cfb
|
@ -1,9 +1,19 @@
|
||||||
const { PermissionsAndroid } = require('react-native');
|
const { Platform, PermissionsAndroid } = require('react-native');
|
||||||
|
|
||||||
|
type rationale = {
|
||||||
|
title: string,
|
||||||
|
message: string,
|
||||||
|
buttonPositive: string,
|
||||||
|
buttonNegative?: string
|
||||||
|
buttonNeutral?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async (permissions: string, rationale?: rationale) => {
|
||||||
|
if (Platform.OS !== 'android') return true;
|
||||||
|
|
||||||
export default async (permissions: string) => {
|
|
||||||
let result = await PermissionsAndroid.check(permissions);
|
let result = await PermissionsAndroid.check(permissions);
|
||||||
if (result !== PermissionsAndroid.RESULTS.GRANTED) {
|
if (result !== PermissionsAndroid.RESULTS.GRANTED) {
|
||||||
result = await PermissionsAndroid.request(permissions);
|
result = await PermissionsAndroid.request(permissions, rationale);
|
||||||
}
|
}
|
||||||
return result === PermissionsAndroid.RESULTS.GRANTED;
|
return result === PermissionsAndroid.RESULTS.GRANTED;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { PermissionsAndroid } from 'react-native';
|
|
||||||
import Slider from '@react-native-community/slider';
|
import Slider from '@react-native-community/slider';
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const { Platform, TouchableOpacity, Linking, View, Switch, StyleSheet, Text, Button, ScrollView, TextInput, Alert } = require('react-native');
|
const { Platform, TouchableOpacity, Linking, View, Switch, StyleSheet, Text, Button, ScrollView, TextInput, Alert, PermissionsAndroid } = require('react-native');
|
||||||
const { connect } = require('react-redux');
|
const { connect } = require('react-redux');
|
||||||
const { ScreenHeader } = require('lib/components/screen-header.js');
|
const { ScreenHeader } = require('lib/components/screen-header.js');
|
||||||
const { _ } = require('lib/locale.js');
|
const { _ } = require('lib/locale.js');
|
||||||
|
@ -20,6 +18,7 @@ const { time } = require('lib/time-utils');
|
||||||
const { shim } = require('lib/shim');
|
const { shim } = require('lib/shim');
|
||||||
const SearchEngine = require('lib/services/SearchEngine');
|
const SearchEngine = require('lib/services/SearchEngine');
|
||||||
const RNFS = require('react-native-fs');
|
const RNFS = require('react-native-fs');
|
||||||
|
const checkPermissions = require('lib/checkPermissions.js').default;
|
||||||
|
|
||||||
class ConfigScreenComponent extends BaseScreenComponent {
|
class ConfigScreenComponent extends BaseScreenComponent {
|
||||||
static navigationOptions() {
|
static navigationOptions() {
|
||||||
|
@ -101,28 +100,30 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||||
const exportPath = this.state.profileExportPath;
|
const exportPath = this.state.profileExportPath;
|
||||||
const resourcePath = `${exportPath}/resources`;
|
const resourcePath = `${exportPath}/resources`;
|
||||||
try {
|
try {
|
||||||
|
const hasPermissions = await checkPermissions(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
|
||||||
{
|
if (!hasPermissions) {
|
||||||
const copyFiles = async (source, dest) => {
|
throw new Error('Permission denied');
|
||||||
await shim.fsDriver().mkdir(dest);
|
|
||||||
|
|
||||||
const files = await shim.fsDriver().readDirStats(source);
|
|
||||||
|
|
||||||
for (const file of files) {
|
|
||||||
const source_ = `${source}/${file.path}`;
|
|
||||||
const dest_ = `${dest}/${file.path}`;
|
|
||||||
if (!file.isDirectory()) {
|
|
||||||
reg.logger().info(`Copying profile: ${source_} => ${dest_}`);
|
|
||||||
await shim.fsDriver().copy(source_, dest_);
|
|
||||||
} else {
|
|
||||||
await copyFiles(source_, dest_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await copyFiles(dbPath, exportPath);
|
|
||||||
await copyFiles(Setting.value('resourceDir'), resourcePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const copyFiles = async (source, dest) => {
|
||||||
|
await shim.fsDriver().mkdir(dest);
|
||||||
|
|
||||||
|
const files = await shim.fsDriver().readDirStats(source);
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const source_ = `${source}/${file.path}`;
|
||||||
|
const dest_ = `${dest}/${file.path}`;
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
reg.logger().info(`Copying profile: ${source_} => ${dest_}`);
|
||||||
|
await shim.fsDriver().copy(source_, dest_);
|
||||||
|
} else {
|
||||||
|
await copyFiles(source_, dest_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await copyFiles(dbPath, exportPath);
|
||||||
|
await copyFiles(Setting.value('resourceDir'), resourcePath);
|
||||||
|
|
||||||
alert('Profile has been exported!');
|
alert('Profile has been exported!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(`Could not export files: ${error.message}`);
|
alert(`Could not export files: ${error.message}`);
|
||||||
|
@ -141,16 +142,11 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||||
// Not implemented yet
|
// Not implemented yet
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const hasPermission = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
|
return await checkPermissions(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, {
|
||||||
if (hasPermission) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const requestResult = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, {
|
|
||||||
title: _('Information'),
|
title: _('Information'),
|
||||||
message: _('In order to use file system synchronisation your permission to write to external storage is required.'),
|
message: _('In order to use file system synchronisation your permission to write to external storage is required.'),
|
||||||
buttonPositive: _('OK'),
|
buttonPositive: _('OK'),
|
||||||
});
|
});
|
||||||
return requestResult === PermissionsAndroid.RESULTS.GRANTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
|
@ -451,7 +447,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||||
|
|
||||||
if (this.state.profileExportStatus === 'prompt') {
|
if (this.state.profileExportStatus === 'prompt') {
|
||||||
const profileExportPrompt = (
|
const profileExportPrompt = (
|
||||||
<View style={this.styles().settingContainer}>
|
<View style={this.styles().settingContainer} key="profileExport">
|
||||||
<Text style={this.styles().settingText}>Path:</Text>
|
<Text style={this.styles().settingText}>Path:</Text>
|
||||||
<TextInput style={{ ...this.styles().textInput, paddingRight: 20 }} onChange={(event) => this.setState({ profileExportPath: event.nativeEvent.text })} value={this.state.profileExportPath} placeholder="/path/to/sdcard" keyboardAppearance={theme.keyboardAppearance}></TextInput>
|
<TextInput style={{ ...this.styles().textInput, paddingRight: 20 }} onChange={(event) => this.setState({ profileExportPath: event.nativeEvent.text })} value={this.state.profileExportPath} placeholder="/path/to/sdcard" keyboardAppearance={theme.keyboardAppearance}></TextInput>
|
||||||
<Button title="OK" onPress={this.exportProfileButtonPress2_}></Button>
|
<Button title="OK" onPress={this.exportProfileButtonPress2_}></Button>
|
||||||
|
|
|
@ -846,8 +846,9 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||||
|
|
||||||
async folderPickerOptions_valueChanged(itemValue) {
|
async folderPickerOptions_valueChanged(itemValue) {
|
||||||
const note = this.state.note;
|
const note = this.state.note;
|
||||||
|
const isProvisionalNote = this.props.provisionalNoteIds.includes(note.id);
|
||||||
|
|
||||||
if (!note.id) {
|
if (isProvisionalNote) {
|
||||||
await this.saveNoteButton_press(itemValue);
|
await this.saveNoteButton_press(itemValue);
|
||||||
} else {
|
} else {
|
||||||
await Note.moveToFolder(note.id, itemValue);
|
await Note.moveToFolder(note.id, itemValue);
|
||||||
|
|
|
@ -119,9 +119,8 @@ const markdownUtils = {
|
||||||
return title.replace(filterRegex, '').replace(mdLinkRegex, '$1').replace(emptyMdLinkRegex, '$1').substring(0,80);
|
return title.replace(filterRegex, '').replace(mdLinkRegex, '$1').replace(emptyMdLinkRegex, '$1').substring(0,80);
|
||||||
},
|
},
|
||||||
|
|
||||||
stripMarkdown(text, options = { gfm: false }) {
|
stripMarkdown(text) {
|
||||||
// Removes Markdown syntax elements from the given text
|
return removeMarkdown(text, { gfm: false });
|
||||||
return removeMarkdown(text, options);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -720,6 +720,7 @@ class AppComponent extends React.Component {
|
||||||
return (
|
return (
|
||||||
<SideMenu
|
<SideMenu
|
||||||
menu={sideMenuContent}
|
menu={sideMenuContent}
|
||||||
|
edgeHitWidth={5}
|
||||||
menuPosition={menuPosition}
|
menuPosition={menuPosition}
|
||||||
onChange={(isOpen) => this.sideMenu_change(isOpen)}
|
onChange={(isOpen) => this.sideMenu_change(isOpen)}
|
||||||
onSliding={(percent) => {
|
onSliding={(percent) => {
|
||||||
|
|
Loading…
Reference in New Issue