1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

fetchblob

This commit is contained in:
Laurent Cozic 2017-07-06 22:30:45 +01:00
parent 40ed3216a3
commit 8ee0c38f86
12 changed files with 130 additions and 49 deletions

View File

@ -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

View File

@ -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" />

View File

@ -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);
}
}

View File

@ -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')

View File

@ -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) {

View File

@ -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);

View File

@ -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 };

View File

@ -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');

View File

@ -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_;
}

View File

@ -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);

View File

@ -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",

View File

@ -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) {