mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
fetchblob
This commit is contained in:
parent
40ed3216a3
commit
8ee0c38f86
@ -131,6 +131,7 @@ dependencies {
|
||||
compile "com.android.support:appcompat-v7:23.0.1"
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
compile project(':react-native-sqlite-storage')
|
||||
compile project(':react-native-fetch-blob')
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
|
@ -4,6 +4,7 @@
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
@ -25,6 +26,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
|
@ -9,36 +9,38 @@ import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import org.pgsqlite.SQLitePluginPackage;
|
||||
import com.RNFetchBlob.RNFetchBlobPackage;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new SQLitePluginPackage(),
|
||||
new MainReactPackage(),
|
||||
new RNFSPackage()
|
||||
);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new SQLitePluginPackage(),
|
||||
new MainReactPackage(),
|
||||
new RNFSPackage(),
|
||||
new RNFetchBlobPackage()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
}
|
||||
}
|
||||
|
@ -5,4 +5,7 @@ project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../no
|
||||
include ':app'
|
||||
|
||||
include ':react-native-sqlite-storage'
|
||||
project(':react-native-sqlite-storage').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sqlite-storage/src/android')
|
||||
project(':react-native-sqlite-storage').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sqlite-storage/src/android')
|
||||
|
||||
include ':react-native-fetch-blob'
|
||||
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')
|
@ -85,15 +85,21 @@ class FileApiDriverOneDrive {
|
||||
}
|
||||
}
|
||||
|
||||
async get(path) {
|
||||
let content = null;
|
||||
async get(path, options = null) {
|
||||
if (!options) options = {};
|
||||
|
||||
try {
|
||||
content = await this.api_.execText('GET', this.makePath_(path) + ':/content');
|
||||
if (options.target == 'file') {
|
||||
let response = await this.api_.exec('GET', this.makePath_(path) + ':/content', null, null, options);
|
||||
return response;
|
||||
} else {
|
||||
let content = await this.api_.execText('GET', this.makePath_(path) + ':/content');
|
||||
return content;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code == 'itemNotFound') return null;
|
||||
throw error;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
async mkdir(path) {
|
||||
|
@ -62,7 +62,8 @@ class FileApi {
|
||||
});
|
||||
}
|
||||
|
||||
get(path, options = {}) {
|
||||
get(path, options = null) {
|
||||
if (!options) options = {};
|
||||
if (!options.encoding) options.encoding = 'utf8';
|
||||
this.logger().debug('get ' + this.fullPath_(path));
|
||||
return this.driver_.get(this.fullPath_(path), options);
|
||||
|
@ -46,6 +46,7 @@ class Setting extends BaseModel {
|
||||
}
|
||||
|
||||
static setConstant(key, value) {
|
||||
if (!(key in this.constants_)) throw new Error('Unknown constant key: ' + key);
|
||||
this.constants_[key] = value;
|
||||
}
|
||||
|
||||
@ -152,6 +153,9 @@ Setting.defaults_ = {
|
||||
Setting.constants_ = {
|
||||
'appName': 'joplin',
|
||||
'appId': 'SET_ME', // Each app should set this identifier
|
||||
'resourceDir': '',
|
||||
'profileDir': '',
|
||||
'tempDir': '',
|
||||
}
|
||||
|
||||
export { Setting };
|
@ -84,6 +84,7 @@ class OneDriveApi {
|
||||
try {
|
||||
const json = await r.json();
|
||||
this.setAuth(json);
|
||||
this.dispatch('authRefreshed', this.auth());
|
||||
} catch (error) {
|
||||
const text = await r.text();
|
||||
error.message += ': ' + text;
|
||||
@ -110,6 +111,7 @@ class OneDriveApi {
|
||||
|
||||
if (!options) options = {};
|
||||
if (!options.headers) options.headers = {};
|
||||
if (!options.target) options.target = 'string';
|
||||
|
||||
if (method != 'GET') {
|
||||
options.method = method;
|
||||
@ -137,7 +139,13 @@ class OneDriveApi {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
options.headers['Authorization'] = 'bearer ' + this.token();
|
||||
|
||||
let response = await shim.fetch(url, options);
|
||||
let response = null;
|
||||
if (options.target == 'string') {
|
||||
response = await shim.fetch(url, options);
|
||||
} else { // file
|
||||
response = await shim.fetchBlob(url, options);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
let errorResponse = await response.json();
|
||||
let error = this.oneDriveErrorResponseToError(errorResponse);
|
||||
@ -194,7 +202,7 @@ class OneDriveApi {
|
||||
|
||||
let body = new shim.FormData();
|
||||
body.append('client_id', this.clientId());
|
||||
body.append('client_secret', this.clientSecret());
|
||||
// body.append('client_secret', this.clientSecret()); // TODO: NEEDED FOR NODE
|
||||
body.append('refresh_token', this.auth_.refresh_token);
|
||||
body.append('redirect_uri', 'http://localhost:1917');
|
||||
body.append('grant_type', 'refresh_token');
|
||||
|
@ -29,6 +29,7 @@ reg.oneDriveApi = () => {
|
||||
}
|
||||
|
||||
reg.oneDriveApi_.on('authRefreshed', (a) => {
|
||||
reg.logger().info('Saving updated OneDrive auth.');
|
||||
Setting.setValue('sync.onedrive.auth', JSON.stringify(a));
|
||||
});
|
||||
|
||||
@ -58,6 +59,7 @@ reg.synchronizer = async () => {
|
||||
|
||||
let fileApi = await reg.fileApi();
|
||||
reg.synchronizer_ = new Synchronizer(reg.db(), fileApi);
|
||||
reg.synchronizer_.setLogger(reg.logger());
|
||||
return reg.synchronizer_;
|
||||
}
|
||||
|
||||
|
@ -320,6 +320,12 @@ class Synchronizer {
|
||||
// await Resource.setContent(newContent, remoteResourceContent);
|
||||
// }
|
||||
|
||||
if (newContent.type_ == BaseModel.TYPE_RESOURCE && action == 'createLocal') {
|
||||
let localResourceContentPath = Resource.fullPath(newContent);
|
||||
let remoteResourceContentPath = this.resourceDirName_ + '/' + newContent.id;
|
||||
await this.api().get(remoteResourceContentPath, { path: localResourceContentPath, target: 'file' });
|
||||
}
|
||||
|
||||
await ItemClass.save(newContent, options);
|
||||
|
||||
this.logSyncOperation(action, local, content, reason);
|
||||
|
@ -10,10 +10,11 @@
|
||||
"dropbox": "^2.5.4",
|
||||
"form-data": "^2.1.4",
|
||||
"moment": "^2.18.1",
|
||||
"react": "16.0.0-alpha.6",
|
||||
"react-native": "0.44.0",
|
||||
"react": "16.0.0-alpha.12",
|
||||
"react-native": "0.46.0",
|
||||
"react-native-action-button": "^2.6.9",
|
||||
"react-native-checkbox": "^1.1.0",
|
||||
"react-native-fetch-blob": "^0.10.6",
|
||||
"react-native-fs": "^2.3.3",
|
||||
"react-native-popup-menu": "^0.7.4",
|
||||
"react-native-side-menu": "^0.20.1",
|
||||
|
@ -6,6 +6,7 @@ import { createStore } from 'redux';
|
||||
import { combineReducers } from 'redux';
|
||||
import { StackNavigator } from 'react-navigation';
|
||||
import { addNavigationHelpers } from 'react-navigation';
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { Log } from 'lib/log.js'
|
||||
import { Note } from 'lib/models/note.js'
|
||||
import { Folder } from 'lib/models/folder.js'
|
||||
@ -193,9 +194,47 @@ const AppNavigator = StackNavigator({
|
||||
OneDriveLogin: { screen: OneDriveLoginScreen },
|
||||
});
|
||||
|
||||
import RNFetchBlob from 'react-native-fetch-blob'
|
||||
|
||||
|
||||
class AppComponent extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
async componentDidMount() {
|
||||
|
||||
shim.fetchBlob = async function(url, options) {
|
||||
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');
|
||||
if (!options.method) options.method = 'GET';
|
||||
|
||||
let headers = options.headers ? options.headers : {};
|
||||
let method = options.method ? options.method : 'GET';
|
||||
|
||||
let dirs = RNFetchBlob.fs.dirs;
|
||||
let localFilePath = options.path;
|
||||
if (localFilePath.indexOf('/') !== 0) localFilePath = dirs.DocumentDir + '/' + localFilePath;
|
||||
|
||||
delete options.path;
|
||||
|
||||
try {
|
||||
let response = await RNFetchBlob.config({
|
||||
path: localFilePath
|
||||
}).fetch(method, url, headers);
|
||||
|
||||
// Returns an object that roughtly compatible with a standard Response object
|
||||
let output = {
|
||||
ok: response.respInfo.status < 400,
|
||||
path: response.data,
|
||||
text: response.text,
|
||||
json: response.json,
|
||||
status: response.respInfo.status,
|
||||
headers: response.respInfo.headers,
|
||||
};
|
||||
|
||||
return output;
|
||||
} catch (error) {
|
||||
throw new Error('fetchBlob: ' + method + ' ' + url + ': ' + error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
let db = new Database(new DatabaseDriverReactNative());
|
||||
reg.setDb(db);
|
||||
|
||||
@ -209,33 +248,39 @@ class AppComponent extends React.Component {
|
||||
BaseItem.loadClass('Tag', Tag);
|
||||
BaseItem.loadClass('NoteTag', NoteTag);
|
||||
|
||||
db.open({ name: '/storage/emulated/0/Download/joplin-44.sqlite' }).then(() => {
|
||||
try {
|
||||
await db.open({ name: '/storage/emulated/0/Download/joplin-44.sqlite' })
|
||||
Log.info('Database is ready.');
|
||||
}).then(() => {
|
||||
|
||||
//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');
|
||||
|
||||
Log.info('Loading settings...');
|
||||
return Setting.load();
|
||||
}).then(() => {
|
||||
await Setting.load();
|
||||
|
||||
Setting.setConstant('appId', 'net.cozic.joplin-android');
|
||||
Setting.setConstant('resourceDir', RNFetchBlob.fs.dirs.DocumentDir);
|
||||
|
||||
Log.info('Loading folders...');
|
||||
|
||||
return Folder.all().then((folders) => {
|
||||
this.props.dispatch({
|
||||
type: 'FOLDERS_UPDATE_ALL',
|
||||
folders: folders,
|
||||
});
|
||||
return folders;
|
||||
}).catch((error) => {
|
||||
Log.warn('Cannot load folders', error);
|
||||
let folders = await Folder.all();
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'FOLDERS_UPDATE_ALL',
|
||||
folders: folders,
|
||||
});
|
||||
}).then((folders) => {
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'Navigation/NAVIGATE',
|
||||
routeName: 'Folders',
|
||||
});
|
||||
}).catch((error) => {
|
||||
} catch (error) {
|
||||
Log.error('Initialization error:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sideMenu_change(isOpen) {
|
||||
|
Loading…
Reference in New Issue
Block a user