mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Getting Dropbox to work in mobile app
This commit is contained in:
parent
6e994fd8b9
commit
96fb7c2087
@ -6,71 +6,22 @@ const { Header } = require('./Header.min.js');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Shared = require('lib/components/shared/dropbox-login-shared');
|
||||
|
||||
class DropboxLoginScreenComponent extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.dropboxApi_ = null;
|
||||
|
||||
this.state = {
|
||||
loginUrl: '',
|
||||
authCode: '',
|
||||
checkingAuthToken: false,
|
||||
};
|
||||
|
||||
this.loginUrl_click = () => {
|
||||
if (!this.state.loginUrl) return;
|
||||
bridge().openExternal(this.state.loginUrl)
|
||||
}
|
||||
|
||||
this.authCodeInput_change = (event) => {
|
||||
this.setState({
|
||||
authCode: event.target.value
|
||||
});
|
||||
}
|
||||
|
||||
this.submit_click = async () => {
|
||||
this.setState({ checkingAuthToken: true });
|
||||
|
||||
const api = await this.dropboxApi();
|
||||
try {
|
||||
const response = await api.execAuthToken(this.state.authCode);
|
||||
Setting.setValue('sync.' + this.syncTargetId() + '.auth', response.access_token);
|
||||
api.setAuthToken(response.access_token);
|
||||
bridge().showInfoMessageBox(_('The application has been authorised!'));
|
||||
this.props.dispatch({ type: 'NAV_BACK' });
|
||||
} catch (error) {
|
||||
bridge().showErrorMessageBox(_('Could not authorise application:\n\n%s\n\nPlease try again.', error.message));
|
||||
} finally {
|
||||
this.setState({ checkingAuthToken: false });
|
||||
}
|
||||
}
|
||||
this.shared_ = new Shared(
|
||||
this,
|
||||
(msg) => bridge().showInfoMessageBox(msg),
|
||||
(msg) => bridge().showErrorMessageBox(msg)
|
||||
);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.refreshUrl();
|
||||
}
|
||||
|
||||
syncTargetId() {
|
||||
return SyncTargetRegistry.nameToId('dropbox');
|
||||
}
|
||||
|
||||
async dropboxApi() {
|
||||
if (this.dropboxApi_) return this.dropboxApi_;
|
||||
|
||||
const syncTarget = reg.syncTarget(this.syncTargetId());
|
||||
this.dropboxApi_ = await syncTarget.api();
|
||||
return this.dropboxApi_;
|
||||
}
|
||||
|
||||
async refreshUrl() {
|
||||
const api = await this.dropboxApi();
|
||||
|
||||
this.setState({
|
||||
loginUrl: api.loginUrl(),
|
||||
});
|
||||
this.shared_.refreshUrl();
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -89,10 +40,10 @@ class DropboxLoginScreenComponent extends React.Component {
|
||||
<div style={{padding: theme.margin}}>
|
||||
<p style={theme.textStyle}>{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}</p>
|
||||
<p style={theme.textStyle}>{_('Step 1: Open this URL in your browser to authorise the application:')}</p>
|
||||
<a style={theme.textStyle} href="#" onClick={this.loginUrl_click}>{this.state.loginUrl}</a>
|
||||
<a style={theme.textStyle} href="#" onClick={this.shared_.loginUrl_click}>{this.state.loginUrl}</a>
|
||||
<p style={theme.textStyle}>{_('Step 2: Enter the code provided by Dropbox:')}</p>
|
||||
<p><input type="text" value={this.state.authCode} onChange={this.authCodeInput_change} style={inputStyle}/></p>
|
||||
<button disabled={this.state.checkingAuthToken} onClick={this.submit_click}>{_('Submit')}</button>
|
||||
<p><input type="text" value={this.state.authCode} onChange={this.shared_.authCodeInput_change} style={inputStyle}/></p>
|
||||
<button disabled={this.state.checkingAuthToken} onClick={this.shared_.submit_click}>{_('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
57
ReactNativeClient/lib/components/screens/dropbox-login.js
Normal file
57
ReactNativeClient/lib/components/screens/dropbox-login.js
Normal file
@ -0,0 +1,57 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { View, Button, Text, TextInput, TouchableOpacity } = 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 DialogBox = require('react-native-dialogbox').default;
|
||||
const { dialogs } = require('lib/dialogs.js');
|
||||
const Shared = require('lib/components/shared/dropbox-login-shared');
|
||||
|
||||
class DropboxLoginScreenComponent extends BaseScreenComponent {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.shared_ = new Shared(
|
||||
this,
|
||||
(msg) => dialogs.info(this, msg),
|
||||
(msg) => dialogs.error(this, msg)
|
||||
);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.shared_.refreshUrl();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={this.styles().screen}>
|
||||
<ScreenHeader title={_('Login with Dropbox')}/>
|
||||
|
||||
<Text>{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}</Text>
|
||||
<Text>{_('Step 1: Open this URL in your browser to authorise the application:')}</Text>
|
||||
<View>
|
||||
<TouchableOpacity onPress={this.shared_.loginUrl_click}>
|
||||
<Text>{this.state.loginUrl}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text>{_('Step 2: Enter the code provided by Dropbox:')}</Text>
|
||||
<TextInput value={this.state.authCode} onChangeText={this.shared_.authCodeInput_change}/>
|
||||
|
||||
<Button disabled={this.state.checkingAuthToken} title={_("Submit")} onPress={this.shared_.submit_click}></Button>
|
||||
|
||||
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const DropboxLoginScreen = connect(
|
||||
(state) => {
|
||||
return {};
|
||||
}
|
||||
)(DropboxLoginScreenComponent)
|
||||
|
||||
module.exports = { DropboxLoginScreen };
|
@ -0,0 +1,74 @@
|
||||
const { shim } = require('lib/shim');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting');
|
||||
|
||||
class Shared {
|
||||
|
||||
constructor(comp, showInfoMessageBox, showErrorMessageBox) {
|
||||
this.comp_ = comp;
|
||||
|
||||
this.dropboxApi_ = null;
|
||||
|
||||
this.comp_.state = {
|
||||
loginUrl: '',
|
||||
authCode: '',
|
||||
checkingAuthToken: false,
|
||||
};
|
||||
|
||||
this.loginUrl_click = () => {
|
||||
if (!this.comp_.state.loginUrl) return;
|
||||
shim.openUrl(this.comp_.state.loginUrl);
|
||||
}
|
||||
|
||||
this.authCodeInput_change = (event) => {
|
||||
this.comp_.setState({
|
||||
authCode: typeof event === 'object' ? event.target.value : event
|
||||
});
|
||||
}
|
||||
|
||||
this.submit_click = async () => {
|
||||
this.comp_.setState({ checkingAuthToken: true });
|
||||
|
||||
const api = await this.dropboxApi();
|
||||
try {
|
||||
const response = await api.execAuthToken(this.comp_.state.authCode);
|
||||
|
||||
Setting.setValue('sync.' + this.syncTargetId() + '.auth', response.access_token);
|
||||
api.setAuthToken(response.access_token);
|
||||
await showInfoMessageBox(_('The application has been authorised!'));
|
||||
this.comp_.props.dispatch({ type: 'NAV_BACK' });
|
||||
reg.scheduleSync();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await showErrorMessageBox(_('Could not authorise application:\n\n%s\n\nPlease try again.', error.message));
|
||||
} finally {
|
||||
this.comp_.setState({ checkingAuthToken: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTargetId() {
|
||||
return SyncTargetRegistry.nameToId('dropbox');
|
||||
}
|
||||
|
||||
async dropboxApi() {
|
||||
if (this.dropboxApi_) return this.dropboxApi_;
|
||||
|
||||
const syncTarget = reg.syncTarget(this.syncTargetId());
|
||||
this.dropboxApi_ = await syncTarget.api();
|
||||
return this.dropboxApi_;
|
||||
}
|
||||
|
||||
async refreshUrl() {
|
||||
const api = await this.dropboxApi();
|
||||
|
||||
this.comp_.setState({
|
||||
loginUrl: api.loginUrl(),
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Shared;
|
@ -67,6 +67,11 @@ dialogs.error = (parentComponent, message) => {
|
||||
return parentComponent.dialogbox.alert(message);
|
||||
}
|
||||
|
||||
dialogs.info = (parentComponent, message) => {
|
||||
Keyboard.dismiss();
|
||||
return parentComponent.dialogbox.alert(message);
|
||||
}
|
||||
|
||||
dialogs.DialogBox = DialogBox
|
||||
|
||||
module.exports = { dialogs };
|
@ -150,7 +150,7 @@ class FileApiDriverDropbox {
|
||||
|
||||
async put(path, content, options = null) {
|
||||
// See https://github.com/facebook/react-native/issues/14445#issuecomment-352965210
|
||||
if (typeof content === 'string') content = Buffer.from(content, 'utf8')
|
||||
if (typeof content === 'string') content = shim.Buffer.from(content, 'utf8')
|
||||
|
||||
await this.api().exec('POST', 'files/upload', content, {
|
||||
'Dropbox-API-Arg': JSON.stringify({
|
||||
|
@ -183,6 +183,11 @@ function shimInit() {
|
||||
|
||||
shim.Buffer = Buffer;
|
||||
|
||||
shim.openUrl = (url) => {
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
bridge().openExternal(url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = { shimInit };
|
@ -6,6 +6,7 @@ const { generateSecureRandom } = require('react-native-securerandom');
|
||||
const FsDriverRN = require('lib/fs-driver-rn.js').FsDriverRN;
|
||||
const urlValidator = require('valid-url');
|
||||
const { Buffer } = require('buffer');
|
||||
const { Linking } = require('react-native');
|
||||
|
||||
function shimInit() {
|
||||
shim.Geolocation = GeolocationReact;
|
||||
@ -118,6 +119,10 @@ function shimInit() {
|
||||
}
|
||||
|
||||
shim.Buffer = Buffer;
|
||||
|
||||
shim.openUrl = (url) => {
|
||||
Linking.openURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { shimInit };
|
@ -130,5 +130,6 @@ shim.stringByteLength = function(string) { throw new Error('Not implemented'); }
|
||||
shim.detectAndSetLocale = null;
|
||||
shim.attachFileToNote = async (note, filePath) => {}
|
||||
shim.Buffer = null;
|
||||
shim.openUrl = () => { throw new Error('Not implemented'); }
|
||||
|
||||
module.exports = { shim };
|
@ -36,6 +36,7 @@ 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 { DropboxLoginScreen } = require('lib/components/screens/dropbox-login.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { MenuContext } = require('react-native-popup-menu');
|
||||
const { SideMenu } = require('lib/components/side-menu.js');
|
||||
@ -55,10 +56,12 @@ const SyncTargetFilesystem = require('lib/SyncTargetFilesystem.js');
|
||||
const SyncTargetOneDriveDev = require('lib/SyncTargetOneDriveDev.js');
|
||||
const SyncTargetNextcloud = require('lib/SyncTargetNextcloud.js');
|
||||
const SyncTargetWebDAV = require('lib/SyncTargetWebDAV.js');
|
||||
const SyncTargetDropbox = require('lib/SyncTargetDropbox.js');
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDriveDev);
|
||||
SyncTargetRegistry.addClass(SyncTargetNextcloud);
|
||||
SyncTargetRegistry.addClass(SyncTargetWebDAV);
|
||||
SyncTargetRegistry.addClass(SyncTargetDropbox);
|
||||
|
||||
// Disabled because not fully working
|
||||
//SyncTargetRegistry.addClass(SyncTargetFilesystem);
|
||||
@ -365,16 +368,6 @@ async function initialize(dispatch) {
|
||||
await db.open({ name: 'joplin.sqlite' })
|
||||
} else {
|
||||
await db.open({ name: 'joplin-68.sqlite' })
|
||||
//await db.open({ name: 'joplin-67.sqlite' })
|
||||
|
||||
// await db.exec('DELETE FROM notes');
|
||||
// await db.exec('DELETE FROM folders');
|
||||
// await db.exec('DELETE FROM tags');
|
||||
// await db.exec('DELETE FROM note_tags');
|
||||
// await db.exec('DELETE FROM resources');
|
||||
// await db.exec('DELETE FROM deleted_items');
|
||||
|
||||
// await db.exec('UPDATE notes SET is_conflict = 1 where id like "546f%"');
|
||||
}
|
||||
|
||||
reg.logger().info('Database is ready.');
|
||||
@ -559,6 +552,7 @@ class AppComponent extends React.Component {
|
||||
Note: { screen: NoteScreen },
|
||||
Folder: { screen: FolderScreen },
|
||||
OneDriveLogin: { screen: OneDriveLoginScreen },
|
||||
DropboxLogin: { screen: DropboxLoginScreen },
|
||||
EncryptionConfig: { screen: EncryptionConfigScreen },
|
||||
Log: { screen: LogScreen },
|
||||
Status: { screen: StatusScreen },
|
||||
|
Loading…
Reference in New Issue
Block a user