mirror of
https://github.com/logseq/logseq.git
synced 2026-02-01 14:43:56 +00:00
refactor(android): use file-sync as lib
This commit is contained in:
@@ -40,7 +40,6 @@ dependencies {
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||
implementation project(':capacitor-cordova-android-plugins')
|
||||
implementation project(':file-sync')
|
||||
}
|
||||
|
||||
apply from: 'capacitor.build.gradle'
|
||||
|
||||
@@ -1,351 +0,0 @@
|
||||
package com.logseq.app;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.getcapacitor.JSArray;
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.annotation.CapacitorPlugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
import com.getcapacitor.PluginMethod;
|
||||
import com.logseq.sync.FileMeta;
|
||||
import com.logseq.sync.RSFileSync;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CapacitorPlugin(name = "FileSync")
|
||||
public class FileSync extends Plugin {
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
|
||||
Log.i("FileSync", "Android plugin loaded");
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void keygen(PluginCall call) {
|
||||
call.setKeepAlive(true);
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
String[] keyPairs = RSFileSync.keygen();
|
||||
JSObject data = new JSObject();
|
||||
data.put("secretKey", keyPairs[0]);
|
||||
data.put("publicKey", keyPairs[1]);
|
||||
call.resolve(data);
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void setKey(PluginCall call) {
|
||||
String secretKey = call.getString("secretKey");
|
||||
String publicKey = call.getString("publicKey");
|
||||
long code = RSFileSync.setKeys(secretKey, publicKey);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject("invalid setKey call");
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void setEnv(PluginCall call) {
|
||||
String env = call.getString("env");
|
||||
if (env == null) {
|
||||
call.reject("required parameter: env");
|
||||
return;
|
||||
}
|
||||
this.setKey(call);
|
||||
long code = RSFileSync.setEnvironment(env);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject("invalid setEnv call");
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void encryptFnames(PluginCall call) {
|
||||
call.setKeepAlive(true);
|
||||
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<String> filePaths = null;
|
||||
try {
|
||||
filePaths = call.getArray("filePaths").toList();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
String filePath = filePaths.get(i);
|
||||
filePaths.set(i, Uri.decode(filePath));
|
||||
}
|
||||
|
||||
String[] raw;
|
||||
raw = RSFileSync.encryptFilenames(filePaths);
|
||||
if (raw != null) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("value", JSArray.from(raw));
|
||||
call.resolve(ret);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void decryptFnames(PluginCall call) {
|
||||
call.setKeepAlive(true);
|
||||
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
JSArray filePaths = call.getArray("filePaths");
|
||||
String[] raw;
|
||||
try {
|
||||
raw = RSFileSync.decryptFilenames(filePaths.toList());
|
||||
for (int i = 0; i < raw.length; i++) {
|
||||
raw[i] = Uri.encode(raw[i], "/");
|
||||
}
|
||||
if (raw != null) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("value", JSArray.from(raw));
|
||||
call.resolve(ret);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
call.reject("cannot decrypt fnames: " + e.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
//@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
|
||||
@PluginMethod()
|
||||
public void getLocalFilesMeta(PluginCall call) throws JSONException {
|
||||
String basePath = call.getString("basePath");
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
|
||||
|
||||
call.setKeepAlive(true);
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
String filePath = filePaths.get(i);
|
||||
filePaths.set(i, Uri.decode(filePath));
|
||||
}
|
||||
|
||||
FileMeta[] metas = RSFileSync.getLocalFilesMeta(basePath, filePaths);
|
||||
if (metas == null) {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
return;
|
||||
}
|
||||
JSObject dict = new JSObject();
|
||||
for (FileMeta meta : metas) {
|
||||
if (meta == null) {
|
||||
continue;
|
||||
}
|
||||
Log.i("FileSync", "got meta " + meta.toString());
|
||||
JSObject item = new JSObject();
|
||||
item.put("md5", meta.md5);
|
||||
item.put("size", meta.size);
|
||||
item.put("encryptedFname", meta.encryptedFilename);
|
||||
|
||||
item.put("mtime", meta.mtime); // not used for now
|
||||
dict.put(Uri.encode(meta.filePath, "/"), item);
|
||||
}
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("result", dict);
|
||||
call.resolve(ret);
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void getLocalAllFilesMeta(PluginCall call) {
|
||||
call.setKeepAlive(true);
|
||||
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
String basePath = call.getString("basePath");
|
||||
FileMeta[] metas = RSFileSync.getLocalAllFilesMeta(basePath);
|
||||
if (metas == null) {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
return;
|
||||
}
|
||||
JSObject dict = new JSObject();
|
||||
for (FileMeta meta : metas) {
|
||||
JSObject item = new JSObject();
|
||||
item.put("md5", meta.md5);
|
||||
item.put("size", meta.size);
|
||||
item.put("encryptedFname", meta.encryptedFilename);
|
||||
|
||||
item.put("mtime", meta.mtime); // not used for now
|
||||
dict.put(Uri.encode(meta.filePath, "/"), item);
|
||||
}
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("result", dict);
|
||||
call.resolve(ret);
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void deleteLocalFiles(PluginCall call) throws JSONException {
|
||||
String basePath = call.getString("basePath");
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
filePaths.set(i, Uri.decode(filePaths.get(i)));
|
||||
}
|
||||
|
||||
RSFileSync.deleteLocalFiles(basePath, filePaths);
|
||||
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
call.resolve(ret);
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void updateLocalFiles(PluginCall call) throws JSONException {
|
||||
String basePath = call.getString("basePath");
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
String graphUUID = call.getString("graphUUID");
|
||||
String token = call.getString("token");
|
||||
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
filePaths.set(i, Uri.decode(filePaths.get(i)));
|
||||
}
|
||||
|
||||
call.setKeepAlive(true);
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
long code = RSFileSync.updateLocalFiles(basePath, filePaths, graphUUID, token);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
}
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void updateLocalVersionFiles(PluginCall call) throws JSONException {
|
||||
String basePath = call.getString("basePath");
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
String graphUUID = call.getString("graphUUID");
|
||||
String token = call.getString("token");
|
||||
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
filePaths.set(i, Uri.decode(filePaths.get(i)));
|
||||
}
|
||||
|
||||
call.setKeepAlive(true);
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
long code = RSFileSync.updateLocalVersionFiles(basePath, filePaths, graphUUID, token);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
}
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void deleteRemoteFiles(PluginCall call) throws JSONException {
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
String graphUUID = call.getString("graphUUID");
|
||||
String token = call.getString("token");
|
||||
long txid = call.getInt("txid").longValue();
|
||||
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
filePaths.set(i, Uri.decode(filePaths.get(i)));
|
||||
}
|
||||
|
||||
call.setKeepAlive(true);
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
long code = RSFileSync.deleteRemoteFiles(filePaths, graphUUID, token, txid);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
ret.put("txid", code);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
}
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void updateRemoteFiles(PluginCall call) throws JSONException {
|
||||
String basePath = call.getString("basePath");
|
||||
List<String> filePaths = call.getArray("filePaths").toList();
|
||||
String graphUUID = call.getString("graphUUID");
|
||||
String token = call.getString("token");
|
||||
long txid = call.getInt("txid").longValue();
|
||||
// NOTE: fnameEncryption is ignored. since it's always on.
|
||||
|
||||
for (int i = 0; i < filePaths.size(); i++) {
|
||||
filePaths.set(i, Uri.decode(filePaths.get(i)));
|
||||
}
|
||||
|
||||
Thread runner = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
long code = RSFileSync.updateRemoteFiles(basePath, filePaths, graphUUID, token, txid);
|
||||
if (code != -1) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("ok", true);
|
||||
ret.put("txid", code);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject(RSFileSync.getLastError());
|
||||
}
|
||||
}
|
||||
};
|
||||
runner.start();
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void ageEncryptWithPassphrase(PluginCall call) {
|
||||
call.reject("unimplemented");
|
||||
}
|
||||
|
||||
@PluginMethod()
|
||||
public void ageDecryptWithPassphrase(PluginCall call) {
|
||||
call.reject("unimplemented");
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ public class MainActivity extends BridgeActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
registerPlugin(FolderPicker.class);
|
||||
registerPlugin(FsWatcher.class);
|
||||
registerPlugin(FileSync.class);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
new Timer().schedule(new TimerTask() {
|
||||
|
||||
1
android/file-sync/.gitignore
vendored
1
android/file-sync/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -1,36 +0,0 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
||||
21
android/file-sync/proguard-rules.pro
vendored
21
android/file-sync/proguard-rules.pro
vendored
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.logseq.sync">
|
||||
|
||||
</manifest>
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.logseq.sync;
|
||||
|
||||
public class FileMeta {
|
||||
public String filePath;
|
||||
public long size;
|
||||
public long mtime;
|
||||
public String md5;
|
||||
public String encryptedFilename;
|
||||
|
||||
public FileMeta(String filePath, long size, long mtime, String md5) {
|
||||
this.filePath = filePath;
|
||||
this.size = size;
|
||||
this.mtime = mtime;
|
||||
this.md5 = md5;
|
||||
this.encryptedFilename = encryptedFilename;
|
||||
}
|
||||
|
||||
public FileMeta(long size, long mtime, String md5) {
|
||||
this.size = size;
|
||||
this.mtime = mtime;
|
||||
this.md5 = md5;
|
||||
this.encryptedFilename = null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "FileMeta{" +
|
||||
"size=" + size +
|
||||
", mtime=" + mtime +
|
||||
", md5='" + md5 + '\'' +
|
||||
", encryptedFilename='" + encryptedFilename + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.logseq.sync;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RSFileSync {
|
||||
static {
|
||||
System.loadLibrary("rsapi");
|
||||
}
|
||||
|
||||
public static native String getLastError();
|
||||
|
||||
public static native String[] keygen();
|
||||
|
||||
public static native long setEnvironment(String env);
|
||||
public static native long setKeys(String secretKey, String publicKey);
|
||||
|
||||
public static native String[] encryptFilenames(List<String> filenames);
|
||||
public static native String[] decryptFilenames(List<String> encryptedFilenames);
|
||||
|
||||
public static native FileMeta[] getLocalFilesMeta(String basePath, List<String> filePaths);
|
||||
public static native FileMeta[] getLocalAllFilesMeta(String basePath);
|
||||
|
||||
public static native long renameLocalFile(String basePath, String oldPath, String newPath);
|
||||
|
||||
public static native void deleteLocalFiles(String basePath, List<String> filePaths);
|
||||
|
||||
public static native long updateLocalFiles(String basePath, List<String> filePaths, String graphUUID, String token);
|
||||
|
||||
public static native long updateLocalVersionFiles(String basePath, List<String> filePaths, String graphUUID, String token);
|
||||
|
||||
public static native long deleteRemoteFiles(List<String> filePaths, String graphUUID, String token, long txid);
|
||||
|
||||
public static native long updateRemoteFiles(String basePath, List<String> filePaths, String graphUUID, String token, long txid);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,4 +3,4 @@ include ':capacitor-cordova-android-plugins'
|
||||
project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
|
||||
|
||||
apply from: 'capacitor.settings.gradle'
|
||||
include ':file-sync'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user