6.6.3 - Alpha5 - 修复示例代码子目录文件自动加载问题; 支持将示例代码文件夹重置为初始内容

This commit is contained in:
SuperMonster003
2025-05-25 20:48:26 +08:00
parent 1fdaf36e7b
commit 38118dd1a4
7 changed files with 104 additions and 58 deletions

View File

@@ -11,7 +11,7 @@
"images.compressToBytes 方法, 用于压缩图像并生成字节数组", "images.compressToBytes 方法, 用于压缩图像并生成字节数组",
"images.downsample 方法, 用于像素降采样并生成新的 ImageWrapper", "images.downsample 方法, 用于像素降采样并生成新的 ImageWrapper",
"ui.keepScreenOn 方法, 用于 UI 页面获取焦点时保持设备屏幕常亮", "ui.keepScreenOn 方法, 用于 UI 页面获取焦点时保持设备屏幕常亮",
"ui.root 属性 (getter), 用于获取 UI 页面布局的 \"窗口内容根容器\" 节点", "ui.root 属性 (getter), 用于获取 UI 页面布局的 \"窗口内容根容器\" 节点"
], ],
"fix": [ "fix": [
"主页文档标签显示在线文档时部分内容被系统导航栏遮挡的问题", "主页文档标签显示在线文档时部分内容被系统导航栏遮挡的问题",
@@ -20,6 +20,7 @@
"无障碍服务关闭时音量加键停止所有脚本功能失效的问题", "无障碍服务关闭时音量加键停止所有脚本功能失效的问题",
"定时任务页面编辑自定义广播内容时出现的输入法遮挡问题", "定时任务页面编辑自定义广播内容时出现的输入法遮挡问题",
"APK 文件类型信息对话框可能无法获取应用名称及 SDK 信息的问题", "APK 文件类型信息对话框可能无法获取应用名称及 SDK 信息的问题",
"文件管理器示例代码进入项目目录时可能无法自动加载子目录文件内容的问题",
"Android 15 部分页面状态栏背景颜色可能无法动态跟随主题色的问题", "Android 15 部分页面状态栏背景颜色可能无法动态跟随主题色的问题",
"dialogs 模块无法正常使用 customView 属性的问题 _[`issue #364`](http://issues.autojs6.com/364)_", "dialogs 模块无法正常使用 customView 属性的问题 _[`issue #364`](http://issues.autojs6.com/364)_",
"dialogs.input 方法的表达式参数可能无法获得执行结果的问题", "dialogs.input 方法的表达式参数可能无法获得执行结果的问题",
@@ -49,6 +50,7 @@
"版本更新信息支持多语言显示 (与当前显示语言同步)", "版本更新信息支持多语言显示 (与当前显示语言同步)",
"使用异步加载方式一定程度提升文件管理器列表滑动流畅性", "使用异步加载方式一定程度提升文件管理器列表滑动流畅性",
"脚本异常消息在控制台的显示内容与格式", "脚本异常消息在控制台的显示内容与格式",
"示例代码支持将文件夹重置为初始内容",
"APK 文件签名信息提升检测效率", "APK 文件签名信息提升检测效率",
"APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑", "APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑",
"Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_" "Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_"

View File

@@ -2,9 +2,10 @@ package org.autojs.autojs.model.explorer;
import android.content.Context; import android.content.Context;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
import org.autojs.autojs.pio.PFile; import org.autojs.autojs.pio.PFile;
import org.autojs.autojs.pio.PFiles; import org.autojs.autojs.pio.PFiles;
@@ -14,11 +15,7 @@ import org.autojs.autojs.util.WorkingDirectoryUtils;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.IOException;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
public class WorkspaceFileProvider extends ExplorerFileProvider { public class WorkspaceFileProvider extends ExplorerFileProvider {
@@ -88,31 +85,47 @@ public class WorkspaceFileProvider extends ExplorerFileProvider {
return Observable.just(pathOfAsset) return Observable.just(pathOfAsset)
.flatMap(path -> Observable.fromArray(mAssetManager.list(path))) .flatMap(path -> Observable.fromArray(mAssetManager.list(path)))
.map(child -> { .map(child -> {
PFile file = new PFile(new File(directory, child).getPath()); PFile localFile = new PFile(new File(directory, child).getPath());
if (file.exists()) { copyAssetRecursively(pathOfAsset + File.separator + child, localFile);
return file; return localFile;
}
try {
InputStream stream = mAssetManager.open(pathOfAsset + File.separator + child);
PFiles.copyStream(stream, file.getPath());
} catch (FileNotFoundException e) {
file.mkdirs();
}
return file;
}); });
} }
private void copyAssetRecursively(String assetPath, File dest) throws IOException {
String[] children = mAssetManager.list(assetPath);
if (children == null || children.length == 0) {
if (!dest.exists()) {
try {
PFiles.copyAssetFile(mAssetManager, assetPath, dest.getPath());
} catch (FileNotFoundException ignored) {
/* Ignored. */
}
}
return;
}
if (!dest.exists()) {
dest.mkdirs();
}
for (String child : children) {
copyAssetRecursively(assetPath + File.separator + child, new File(dest, child));
}
}
@Nullable @Nullable
public Observable<ScriptFile> resetSample(ScriptFile file) { public Observable<ScriptFile> resetSample(ScriptFile file) {
if (file.getPath().length() <= mSampleDir.getPath().length() + 1) { if (!file.getPath().startsWith(mSampleDir.getPath())) {
return null; return null;
} }
String pathOfSample = file.getPath().substring(mSampleDir.getPath().length()); String pathOfSample = file.getPath().substring(mSampleDir.getPath().length());
String pathOfAsset = SAMPLE_PATH + pathOfSample; String pathOfAsset = SAMPLE_PATH + pathOfSample;
return Observable return Observable
.fromCallable(() -> { .fromCallable(() -> {
try (InputStream stream = mAssetManager.open(pathOfAsset)) { try {
PFiles.copyStream(stream, file.getPath()); if (file.isDirectory()) {
PFiles.copyAssetDir(mAssetManager, pathOfAsset, file.getPath());
} else {
PFiles.copyAssetFile(mAssetManager, pathOfAsset, file.getPath());
}
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
return new ScriptFile(System.currentTimeMillis() + "\ufeff" + Math.random()); return new ScriptFile(System.currentTimeMillis() + "\ufeff" + Math.random());
} }

View File

@@ -281,23 +281,31 @@ object PFiles {
} }
@JvmStatic @JvmStatic
@JvmOverloads
@Throws(IOException::class) @Throws(IOException::class)
fun copyAssetDir(manager: AssetManager, assetsDir: String, toDir: String, list: Array<String?>?) { fun copyAssetDir(manager: AssetManager, assetsDir: String, toDir: String, list: Array<String?>? = null) {
File(toDir).mkdirs() File(toDir).mkdirs()
val ls = list ?: manager.list(assetsDir) ?: throw IOException("Not a directory: $assetsDir") val ls = list ?: manager.list(assetsDir) ?: throw IOException("Not a directory: $assetsDir")
ls.forEach { file -> ls.forEach { file ->
if (!TextUtils.isEmpty(file)) { if (!TextUtils.isEmpty(file)) {
val fullAssetsPath = join(assetsDir, file) val fullAssetsPath = join(assetsDir, file)
val children = manager.list(fullAssetsPath) val children = manager.list(fullAssetsPath)
val toPath = join(toDir, file)
if (children.isNullOrEmpty()) { if (children.isNullOrEmpty()) {
manager.open(fullAssetsPath).use { stream -> copyStream(stream, join(toDir, file)) } copyAssetFile(manager, fullAssetsPath, toPath)
} else { } else {
copyAssetDir(manager, fullAssetsPath, join(toDir, file), children) copyAssetDir(manager, fullAssetsPath, toPath, children)
} }
} }
} }
} }
@JvmStatic
@Throws(IOException::class)
fun copyAssetFile(manager: AssetManager, assetFile: String, toPath: String) {
manager.open(assetFile).use { stream -> copyStream(stream, toPath) }
}
fun renameWithoutExtensionAndReturnNewPath(path: String, newName: String): String { fun renameWithoutExtensionAndReturnNewPath(path: String, newName: String): String {
val file = File(path) val file = File(path)
val newFile = File(file.parent, newName + "." + getExtension(file.name)) val newFile = File(file.parent, newName + "." + getExtension(file.name))

View File

@@ -43,7 +43,7 @@ class Plugins(private val context: Context, private val runtime: PluginRuntime)
try { try {
val plugin = Plugin.load(context, packageContext, runtime, runtime.topLevelScope) val plugin = Plugin.load(context, packageContext, runtime, runtime.topLevelScope)
val scriptCacheDir = getScriptCacheDir(packageName) val scriptCacheDir = getScriptCacheDir(packageName)
copyAssetDir(packageContext.context.assets, plugin.assetsScriptDir, scriptCacheDir.path, null) copyAssetDir(packageContext.context.assets, plugin.assetsScriptDir, scriptCacheDir.path)
plugin.mainScriptPath = File(scriptCacheDir, "index.js").path plugin.mainScriptPath = File(scriptCacheDir, "index.js").path
bindService(plugin) bindService(plugin)
mPlugins[packageName] = plugin mPlugins[packageName] = plugin

View File

@@ -904,7 +904,7 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
menu.removeItem(R.id.action_set_as_working_dir) menu.removeItem(R.id.action_set_as_working_dir)
} }
val samplePath = PFile(context.filesDir, WorkspaceFileProvider.SAMPLE_PATH).path val samplePath = PFile(context.filesDir, WorkspaceFileProvider.SAMPLE_PATH).path
if (!(mExplorerItem.path.startsWith(samplePath))) { if (!mExplorerItem.path.startsWith(samplePath)) {
menu.removeItem(R.id.reset) menu.removeItem(R.id.reset)
} }
popupMenu.setOnMenuItemClickListener(this@ExplorerView) popupMenu.setOnMenuItemClickListener(this@ExplorerView)
@@ -961,6 +961,10 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
if (!mExplorerPage!!.canBuildApk()) { if (!mExplorerPage!!.canBuildApk()) {
menu.removeItem(R.id.action_build_apk) menu.removeItem(R.id.action_build_apk)
} }
val samplePath = PFile(context.filesDir, WorkspaceFileProvider.SAMPLE_PATH).path
if (!mExplorerPage!!.path.startsWith(samplePath)) {
menu.removeItem(R.id.reset)
}
popupMenu.setOnMenuItemClickListener { item: MenuItem -> popupMenu.setOnMenuItemClickListener { item: MenuItem ->
when (item.itemId) { when (item.itemId) {
R.id.action_rename -> { R.id.action_rename -> {
@@ -979,6 +983,22 @@ open class ExplorerView : ThemeColorSwipeRefreshLayout, SwipeRefreshLayout.OnRef
R.id.action_build_apk -> { R.id.action_build_apk -> {
BuildActivity.launch(context, selectedItem!!.path) BuildActivity.launch(context, selectedItem!!.path)
} }
R.id.reset -> {
val o = Explorers.Providers.workspace()
.resetSample(selectedItem!!.toScriptFile())
if (o == null) {
resetFailed()
} else {
o.observeOn(AndroidSchedulers.mainThread())
.subscribe({ file: ScriptFile ->
if (file.exists()) {
resetSucceeded()
} else {
resetFailed()
}
}, Observers.toastMessage())
}
}
else -> null else -> null
} != null } != null
} }

View File

@@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/action_rename" android:id="@+id/action_rename"
android:title="@string/text_rename" /> android:title="@string/text_rename" />
<item <item
android:id="@+id/action_delete" android:id="@+id/action_delete"
android:title="@string/text_delete" /> android:title="@string/text_delete" />
<item <item
android:id="@+id/action_set_as_working_dir" android:id="@+id/action_set_as_working_dir"
android:title="@string/text_set_as_working_dir" /> android:title="@string/text_set_as_working_dir" />
<item <item
android:id="@+id/action_build_apk" android:id="@+id/action_build_apk"
android:title="@string/text_build_apk" /> android:title="@string/text_build_apk" />
<item
android:id="@+id/reset"
android:title="@string/text_reset_to_initial_content" />
</menu> </menu>

View File

@@ -1,31 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/rename" android:id="@+id/rename"
android:title="@string/text_rename" /> android:title="@string/text_rename" />
<item <item
android:id="@+id/delete" android:id="@+id/delete"
android:title="@string/text_delete" /> android:title="@string/text_delete" />
<item <item
android:id="@+id/timed_task" android:id="@+id/timed_task"
android:title="@string/text_timed_task" /> android:title="@string/text_timed_task" />
<item <item
android:id="@+id/create_shortcut" android:id="@+id/create_shortcut"
android:title="@string/text_send_shortcut" /> android:title="@string/text_send_shortcut" />
<item <item
android:id="@+id/action_build_apk" android:id="@+id/action_build_apk"
android:title="@string/text_build_apk" /> android:title="@string/text_build_apk" />
<item <item
android:id="@+id/reset" android:id="@+id/reset"
android:title="@string/text_reset_to_initial_content" /> android:title="@string/text_reset_to_initial_content" />
<item <item
android:id="@+id/send" android:id="@+id/send"
android:title="@string/text_send" /> android:title="@string/text_send" />
<item <item
android:id="@+id/open_by_other_apps" android:id="@+id/open_by_other_apps"
android:title="@string/text_open_by_other_apps" /> android:title="@string/text_open_by_other_apps" />
<item <item
android:id="@+id/run_repeatedly" android:id="@+id/run_repeatedly"
android:title="@string/text_run_repeatedly" /> android:title="@string/text_run_repeatedly" />
</menu> </menu>