6.3.4 Alpha - 修复 VSCode 插件保存文件丢失扩展名

This commit is contained in:
SuperMonster003
2023-07-27 13:58:42 +08:00
parent 0ddec17e31
commit 47564fa377
19 changed files with 340 additions and 312 deletions

View File

@@ -88,7 +88,7 @@ class Loopers(runtime: ScriptRuntime) : IdleHandler {
if (mTimers.hasPendingCallbacks()) {
return false
}
if (waitWhenIdle.get() || !waitIds.get().isEmpty()) {
if (waitWhenIdle.get() == true || waitIds.get()?.isNotEmpty() == true) {
return false
}
if ((Context.getCurrentContext() as AutoJsContext).hasPendingContinuation()) {
@@ -104,11 +104,13 @@ class Loopers(runtime: ScriptRuntime) : IdleHandler {
}
private fun initServantThread() {
val lock = this@Loopers as Object
ThreadCompat {
Looper.prepare()
mServantLooper = Looper.myLooper()
synchronized(lock) { lock.notifyAll() }
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
synchronized(this@Loopers as Object) {
notifyAll()
}
Looper.loop()
}.start()
}
@@ -117,10 +119,10 @@ class Loopers(runtime: ScriptRuntime) : IdleHandler {
get() {
if (mServantLooper == null) {
initServantThread()
val lock = this@Loopers as Object
synchronized(lock) {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
synchronized(this@Loopers as Object) {
try {
lock.wait()
wait()
} catch (e: InterruptedException) {
throw ScriptInterruptedException(e)
}
@@ -134,16 +136,16 @@ class Loopers(runtime: ScriptRuntime) : IdleHandler {
}
fun waitWhenIdle(): Int {
val id = maxWaitId.get()
val id = maxWaitId.get()!!
Log.d(LOG_TAG, "waitWhenIdle: $id")
maxWaitId.set(id + 1)
waitIds.get().add(id)
waitIds.get()!!.add(id)
return id
}
fun doNotWaitWhenIdle(waitId: Int) {
Log.d(LOG_TAG, "doNotWaitWhenIdle: $waitId")
waitIds.get().remove(waitId)
waitIds.get()!!.remove(waitId)
}
fun waitWhenIdle(b: Boolean) {

View File

@@ -27,6 +27,7 @@ class Timer @JvmOverloads constructor(runtime: ScriptRuntime, maxCallbackMillisF
private val mHandlerCallbacks = SparseArray<Runnable?>()
private var mCallbackMaxId = 0
private val mRuntime: ScriptRuntime = runtime
@Suppress("DEPRECATION")
private val mHandler = looper?.let { Handler(it) } ?: Handler()
private var mMaxCallbackUptimeMillis: Long = 0
private val mMaxCallbackMillisForAllThread: VolatileBox<Long> = maxCallbackMillisForAllThread

View File

@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap
// ! Sorry but my current capabilities are not sufficient
// ! to fully understand everything from above pull request(s),
// ! so most of the code will remain as is. :)
@Suppress("unused")
open class TimerThread(
private val scriptRuntime: ScriptRuntime,
private val maxCallbackUptimeMillisForAllThreads: VolatileBox<Long>,
@@ -43,6 +44,7 @@ open class TimerThread(
}
(scriptRuntime.engines.myEngine() as? RhinoJavaScriptEngine)?.enterContext()
notifyRunning()
@Suppress("DEPRECATION")
Looper.myLooper()?.let {
Handler(it).post(target)
} ?: Handler().post(target)

View File

@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import com.afollestad.materialdialogs.MaterialDialog;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
@@ -26,11 +27,9 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.concurrent.Callable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
/**
@@ -76,7 +75,7 @@ public class DevPluginResponseHandler implements Handler {
.handler("save", data -> {
String script = data.get("script").getAsString();
String name = getName(data);
saveScript(name, script);
saveFile(name, script);
return true;
})
.handler("stopAll", data -> {
@@ -151,45 +150,56 @@ public class DevPluginResponseHandler implements Handler {
return element.getAsString();
}
private void saveScript(String name, String script) {
private void saveFile(String name, String content) {
if (TextUtils.isEmpty(name)) {
name = "untitled";
}
name = PFiles.getNameWithoutExtension(name);
if (!name.endsWith(".js")) {
name = name + ".js";
name = getUntitledTitle();
}
name = PFiles.getName(name);
// @Comment by SuperMonster003 on Jun 1, 2022.
// ! Keep the original extension name of source file.
// name = PFiles.getNameWithoutExtension(name);
// if (!name.endsWith(".js")) {
// name = name + ".js";
// }
File file = new File(WorkingDirectoryUtils.getPath(), name);
PFiles.ensureDir(file.getPath());
PFiles.write(file, script);
ViewUtils.showToast(mContext, R.string.text_script_save_succeeded, true);
PFiles.write(file, content);
ViewUtils.showToast(mContext, R.string.text_remote_file_saved_to_local_storage_successfully, true);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
@SuppressLint("CheckResult")
private void saveProject(String name, String dir) {
if (TextUtils.isEmpty(name)) {
name = "untitled";
name = getUntitledTitle();
}
name = PFiles.getNameWithoutExtension(name);
name = PFiles.getName(name);
File toDir = new File(WorkingDirectoryUtils.getPath(), name);
Callable<String> stringCallable = () -> {
copyDir(new File(dir), toDir);
return toDir.getPath();
};
Consumer<String> stringConsumer = dest -> ViewUtils
.showToast(mContext, mContext.getString(R.string.text_project_save_succeeded) + "\n" + dest);
Consumer<Throwable> throwableConsumer = err -> ViewUtils
.showToast(mContext, mContext.getString(R.string.text_project_save_error) + "\n" + err.getMessage());
Observable
.fromCallable(stringCallable)
.fromCallable(() -> {
copyDir(new File(dir), toDir);
return toDir.getPath();
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(stringConsumer, throwableConsumer);
.subscribe(
dest -> ViewUtils.showToast(mContext, mContext.getString(R.string.text_remote_project_saved_to_local_storage_successfully), true),
err -> {
var msg = mContext.getString(R.string.text_failed_to_save_remote_project_to_local_storage);
var e = err.getMessage();
if (e != null) msg += "\n" + e;
new MaterialDialog.Builder(mContext)
.title(R.string.text_failed)
.content(msg)
.positiveText(R.string.dialog_button_confirm)
.show();
}
);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
@@ -209,4 +219,8 @@ public class DevPluginResponseHandler implements Handler {
}
}
private String getUntitledTitle() {
return "untitled" + "-" + System.currentTimeMillis();
}
}

View File

@@ -531,10 +531,12 @@ class CodeEditor : HVScrollView {
@Suppress("RegExpSimplifiable")
replaceSelectedLines(Regex("^(\\s{$insetPosition})(\\s*\\S+)")) { matchResult ->
"$prefix\u0020"
.also { selectionEnd += it.length }
.also { hasEverMatched = true }
.let { "${matchResult.groupValues[1]}$it${matchResult.groupValues[2]}" }
"$prefix\u0020".let {
selectionEnd += it.length
hasEverMatched = true
val (_, former, latter) = matchResult.groupValues
"$former$it$latter"
}
}
@Suppress("ControlFlowWithEmptyBody")
@@ -555,8 +557,9 @@ class CodeEditor : HVScrollView {
var selectionEnd = codeEditText.selectionEnd
replaceSelectedLines(Regex("(\\s*)($prefix\\s?)(.*)")) { matchResult ->
selectionEnd -= matchResult.groupValues[2].length
"${matchResult.groupValues[1]}${matchResult.groupValues[3]}"
val (_, former, feature, latter) = matchResult.groupValues
selectionEnd -= feature.length
"$former$latter"
}
codeEditText.setSelection(selectionEnd)