opt: communication between editor and javascript
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
package com.stardust.scriptdroid.ui.edit;
|
package com.stardust.scriptdroid.ui.edit;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.RequiresApi;
|
import android.support.annotation.RequiresApi;
|
||||||
@@ -11,7 +10,6 @@ import android.util.Log;
|
|||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
@@ -27,28 +25,22 @@ import android.webkit.WebViewClient;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.DialogAction;
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
|
||||||
import com.stardust.pio.PFiles;
|
import com.stardust.pio.PFiles;
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
|
||||||
import com.stardust.util.ClipboardUtil;
|
import com.stardust.util.ClipboardUtil;
|
||||||
|
|
||||||
import org.jdeferred.Deferred;
|
import org.jdeferred.Deferred;
|
||||||
import org.jdeferred.DoneCallback;
|
|
||||||
import org.jdeferred.impl.DeferredObject;
|
import org.jdeferred.impl.DeferredObject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.annotations.NonNull;
|
|
||||||
import io.reactivex.functions.Consumer;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import io.reactivex.subjects.PublishSubject;
|
import io.reactivex.subjects.PublishSubject;
|
||||||
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
|
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
|
||||||
@@ -76,11 +68,6 @@ public class CodeMirrorEditor extends FrameLayout {
|
|||||||
private Callback mCallback;
|
private Callback mCallback;
|
||||||
private Deferred<Void, Void, Void> mPageFinished = new DeferredObject<>();
|
private Deferred<Void, Void, Void> mPageFinished = new DeferredObject<>();
|
||||||
|
|
||||||
private PublishSubject<String> mStringFromJs;
|
|
||||||
private PublishSubject<Integer> mIntFromJs;
|
|
||||||
private String mTextFromAndroid;
|
|
||||||
|
|
||||||
|
|
||||||
public CodeMirrorEditor(Context context) {
|
public CodeMirrorEditor(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
init();
|
init();
|
||||||
@@ -212,41 +199,25 @@ public class CodeMirrorEditor extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setText(final String text) {
|
public void setText(final String text) {
|
||||||
mTextFromAndroid = text;
|
int id = SharedVariables.put(text);
|
||||||
mPageFinished.promise().done(result -> evalJavaScript("editor.setValue(__bridge__.getStringFromAndroid());"));
|
mPageFinished.promise().done(result -> evalJavaScript(String.format(Locale.getDefault(),
|
||||||
|
"editor.setValue(__bridge__.getStringFromAndroid(%d));", id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void insert(String text) {
|
public void insert(String text) {
|
||||||
mTextFromAndroid = text;
|
int id = SharedVariables.put(text);
|
||||||
mPageFinished.promise().done(result -> evalJavaScript("editor.replaceSelection(__bridge__.getStringFromAndroid());"));
|
mPageFinished.promise().done(result -> evalJavaScript(String.format(Locale.getDefault(),
|
||||||
|
"editor.replaceSelection(__bridge__.getStringFromAndroid(%d));", id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void loadFile(final File file) {
|
|
||||||
setProgress(true);
|
|
||||||
Observable.fromCallable(() -> PFiles.read(file))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(s -> {
|
|
||||||
setText(s);
|
|
||||||
setProgress(false);
|
|
||||||
}, err -> {
|
|
||||||
err.printStackTrace();
|
|
||||||
Toast.makeText(getContext(), getContext().getString(R.string.text_cannot_read_file, file.getPath()),
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<String> getText() {
|
public Observable<String> getText() {
|
||||||
mStringFromJs = PublishSubject.create();
|
return evalString("editor.getValue()");
|
||||||
evalJavaScript("__bridge__.setStringFromJs(editor.getValue());");
|
|
||||||
return mStringFromJs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<String> getLine() {
|
public Observable<String> getLine() {
|
||||||
mStringFromJs = PublishSubject.create();
|
return evalString("editor.getLine(editor.getCursor().line)");
|
||||||
evalJavaScript("__bridge__.setStringFromJs(editor.getLine(editor.getCursor().line))");
|
|
||||||
return mStringFromJs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteLine() {
|
public void deleteLine() {
|
||||||
@@ -297,9 +268,10 @@ public class CodeMirrorEditor extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Integer> getLineCount() {
|
public Observable<Integer> getLineCount() {
|
||||||
mIntFromJs = PublishSubject.create();
|
PublishSubject<Integer> publishSubject = PublishSubject.create();
|
||||||
evalJavaScript("__bridge__.setIntFromJs(editor.lineCount())");
|
int id = SharedVariables.put(publishSubject);
|
||||||
return mIntFromJs;
|
evalJavaScript(String.format(Locale.getDefault(), "__bridge__.setIntFromJs(%d, editor.lineCount())", id));
|
||||||
|
return publishSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -387,9 +359,14 @@ public class CodeMirrorEditor extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Observable<String> getSelection() {
|
public Observable<String> getSelection() {
|
||||||
mStringFromJs = PublishSubject.create();
|
return evalString("editor.getSelection()");
|
||||||
evalJavaScript("__bridge__.setStringFromJs(editor.getSelection());");
|
}
|
||||||
return mStringFromJs;
|
|
||||||
|
private Observable<String> evalString(String expr) {
|
||||||
|
PublishSubject<String> publishSubject = PublishSubject.create();
|
||||||
|
int id = SharedVariables.put(publishSubject);
|
||||||
|
evalJavaScript(String.format(Locale.getDefault(), "__bridge__.setStringFromJs(%d, %s);", id, expr));
|
||||||
|
return publishSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceSelection() {
|
public void replaceSelection() {
|
||||||
@@ -412,30 +389,26 @@ public class CodeMirrorEditor extends FrameLayout {
|
|||||||
public class JavaScriptBridge {
|
public class JavaScriptBridge {
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void setStringFromJs(String text) {
|
public void setStringFromJs(int id, String text) {
|
||||||
if (mStringFromJs == null) {
|
PublishSubject<String> publishSubject = SharedVariables.remove(id);
|
||||||
|
if (publishSubject == null)
|
||||||
return;
|
return;
|
||||||
}
|
publishSubject.onNext(text);
|
||||||
mStringFromJs.onNext(text);
|
publishSubject.onComplete();
|
||||||
mStringFromJs.onComplete();
|
|
||||||
mStringFromJs = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void setIntFromJs(int i) {
|
public void setIntFromJs(int id, int i) {
|
||||||
if (mIntFromJs == null) {
|
PublishSubject<Integer> publishSubject = SharedVariables.remove(id);
|
||||||
|
if (publishSubject == null)
|
||||||
return;
|
return;
|
||||||
}
|
publishSubject.onNext(i);
|
||||||
mIntFromJs.onNext(i);
|
publishSubject.onComplete();
|
||||||
mIntFromJs.onComplete();
|
|
||||||
mIntFromJs = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public String getStringFromAndroid() {
|
public String getStringFromAndroid(int id) {
|
||||||
String t = mTextFromAndroid;
|
return SharedVariables.remove(id);
|
||||||
mTextFromAndroid = null;
|
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.view.Gravity;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||||
@@ -104,6 +105,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
|||||||
private boolean mReadOnly = false;
|
private boolean mReadOnly = false;
|
||||||
private ScriptExecution mScriptExecution;
|
private ScriptExecution mScriptExecution;
|
||||||
private boolean mTextChanged = false;
|
private boolean mTextChanged = false;
|
||||||
|
private boolean mInitialText = false;
|
||||||
private AutoCompletion mAutoCompletion;
|
private AutoCompletion mAutoCompletion;
|
||||||
private FunctionsKeyboardHelper mFunctionsKeyboardHelper;
|
private FunctionsKeyboardHelper mFunctionsKeyboardHelper;
|
||||||
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
|
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
|
||||||
@@ -180,17 +182,39 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
|||||||
String path = intent.getStringExtra(EXTRA_PATH);
|
String path = intent.getStringExtra(EXTRA_PATH);
|
||||||
String content = intent.getStringExtra(EXTRA_CONTENT);
|
String content = intent.getStringExtra(EXTRA_CONTENT);
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
mEditor.setText(content);
|
setInitialText(content);
|
||||||
} else {
|
} else {
|
||||||
mFile = new File(path);
|
mFile = new File(path);
|
||||||
if (mName == null) {
|
if (mName == null) {
|
||||||
mName = mFile.getName();
|
mName = mFile.getName();
|
||||||
}
|
}
|
||||||
mEditor.loadFile(mFile);
|
loadFile(mFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void loadFile(final File file) {
|
||||||
|
mEditor.setProgress(true);
|
||||||
|
Observable.fromCallable(() -> PFiles.read(file))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(s -> {
|
||||||
|
setInitialText(s);
|
||||||
|
mEditor.setProgress(false);
|
||||||
|
}, err -> {
|
||||||
|
err.printStackTrace();
|
||||||
|
Toast.makeText(getContext(), getContext().getString(R.string.text_cannot_read_file, file.getPath()),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInitialText(String text) {
|
||||||
|
mInitialText = true;
|
||||||
|
mTextChanged = false;
|
||||||
|
mEditor.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setMenuItemStatus(int id, boolean enabled) {
|
private void setMenuItemStatus(int id, boolean enabled) {
|
||||||
findViewById(id).setEnabled(enabled);
|
findViewById(id).setEnabled(enabled);
|
||||||
}
|
}
|
||||||
@@ -230,9 +254,13 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
|
|||||||
setTheme(PreferenceManager.getDefaultSharedPreferences(getContext())
|
setTheme(PreferenceManager.getDefaultSharedPreferences(getContext())
|
||||||
.getString(KEY_EDITOR_THEME, mEditor.getTheme()));
|
.getString(KEY_EDITOR_THEME, mEditor.getTheme()));
|
||||||
mEditor.setCallback((line, cursor) -> {
|
mEditor.setCallback((line, cursor) -> {
|
||||||
mTextChanged = true;
|
if (mInitialText) {
|
||||||
setMenuItemStatus(R.id.save, true);
|
mInitialText = false;
|
||||||
autoComplete(line, cursor);
|
} else {
|
||||||
|
mTextChanged = true;
|
||||||
|
setMenuItemStatus(R.id.save, true);
|
||||||
|
autoComplete(line, cursor);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.stardust.scriptdroid.ui.edit;
|
||||||
|
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2018/2/4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SharedVariables {
|
||||||
|
|
||||||
|
private static SparseArray<Object> sSharedVariables = new SparseArray<>();
|
||||||
|
private static AtomicInteger sMaxId = new AtomicInteger();
|
||||||
|
|
||||||
|
|
||||||
|
public static int put(Object value) {
|
||||||
|
int id = sMaxId.getAndIncrement();
|
||||||
|
sSharedVariables.put(id, value);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T remove(int id) {
|
||||||
|
Object o = sSharedVariables.get(id);
|
||||||
|
if (o != null)
|
||||||
|
sSharedVariables.remove(id);
|
||||||
|
return (T) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -41,11 +41,6 @@ public class FloatyWindowManger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void closeWindow(FloatyWindow window) {
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isCircularMenuShowing() {
|
public static boolean isCircularMenuShowing() {
|
||||||
return sCircularMenu != null && sCircularMenu.get() != null;
|
return sCircularMenu != null && sCircularMenu.get() != null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user