mirror of
https://github.com/XeroAlpha/CA.git
synced 2024-11-22 17:26:16 +00:00
feat: 与文件系统的交互迁移至Android存储访问框架(SAF),所有文件改为Uri形式
This commit is contained in:
parent
83df2b32c3
commit
21d3ee3f3a
@ -1,9 +1,6 @@
|
||||
@downloadSource
|
||||
{
|
||||
"酷安网(最推荐)": "https://www.coolapk.com/game/com.xero.ca",
|
||||
"话唠兔的小站(直链)": "https://projectxero.top/ca/release.apk",
|
||||
"Gitee": "https://gitee.com/projectxero/ca/releases",
|
||||
"反馈群(加群303697689获得)": "https://jq.qq.com/?_wv=1027&k=5OOYWLn"
|
||||
"官方网站(最推荐)": "https://projectxero.top/ca/release.apk"
|
||||
}
|
||||
@end downloadSource
|
||||
可用的下载地址
|
||||
|
@ -21,6 +21,8 @@
|
||||
"edit": "Edit",
|
||||
"edit_desc": "Return to edit JSON",
|
||||
"nowhereEditable": "Nowhere is editable",
|
||||
"replace": "Replace",
|
||||
"replace_desc": "Create a new JSON and replace the original",
|
||||
"copy": "Copy",
|
||||
"copy_desc": "Copy JSON value",
|
||||
"copy_success": "JSON value copied",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"path": "路径",
|
||||
"fileName": "文件名",
|
||||
"fileNotExist": "文件或目录不存在",
|
||||
"directoryCannotRead": "目录不存在或拒绝访问",
|
||||
"createDir": "新建文件夹",
|
||||
"emptyDirName": "文件夹名称不能为空",
|
||||
"errCreateDir": "创建目录失败%n%s",
|
||||
@ -35,6 +36,7 @@
|
||||
"emptyFileName": "文件名不能为空",
|
||||
"dirAlreadyExist": "同名目录已存在",
|
||||
"invaildFileName": "无效的文件名",
|
||||
"loading": "获取文件列表中……",
|
||||
"errAccessDir": "拒绝访问%n%s"
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@
|
||||
"edit": "继续编辑",
|
||||
"edit_desc": "继续编辑JSON",
|
||||
"nowhereEditable": "该JSON没有可以编辑的地方",
|
||||
"replace": "替换",
|
||||
"replace_desc": "新建JSON并替换原有内容",
|
||||
"copy": "复制",
|
||||
"copy_desc": "复制JSON",
|
||||
"copy_success": "JSON已复制至剪贴板",
|
||||
|
8
main.js
8
main.js
@ -267,7 +267,7 @@ var proto = {
|
||||
return (this.println("Debug", this.debug("D", s, 0).join("\n")), s);
|
||||
},
|
||||
t : function self(s) { //显示Toast
|
||||
ctx.runOnUiThread(function() {
|
||||
gHandler.post(function() {
|
||||
if (self.last) self.last.cancel();
|
||||
(self.last = android.widget.Toast.makeText(ctx, String(s), 0)).show();
|
||||
});
|
||||
@ -335,7 +335,7 @@ MapScript.loadModule("erp", function self(error, silent, extra) {
|
||||
if (extra) tech += "\n" + Log.debug("额外数据", extra, 0).join("\n");
|
||||
android.util.Log.e("CA", tech);
|
||||
try {
|
||||
var fs = new java.io.PrintWriter(new java.io.FileOutputStream(android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/com.xero.ca.error.log", true));
|
||||
var fs = new java.io.PrintWriter(new java.io.FileOutputStream(MapScript.baseDir + "com.xero.ca.error.log", true));
|
||||
fs.println("* " + (silent ? "Warning" : "Error") + ": " + new Date().toLocaleString());
|
||||
fs.println(tech);
|
||||
fs.close();
|
||||
@ -381,7 +381,7 @@ MapScript.loadModule("erp", function self(error, silent, extra) {
|
||||
var dialog = new android.app.AlertDialog.Builder(ctx);
|
||||
dialog.setTitle("错误");
|
||||
dialog.setCancelable(false);
|
||||
dialog.setMessage("您好," + error.fileName + "出现了一个错误。您可以将这个错误反馈给我们,来推动这个Mod的更新。您也可以选择忽略。作者联系方式:QQ-814518615(Xero)\n\n错误信息:\n" + tech);
|
||||
dialog.setMessage("您好," + error.fileName + "出现了一个错误。您可以将这个错误反馈给我们,来推动这个Mod的更新。您也可以选择忽略。您可以直接在设置-关于-意见与反馈里进行反馈,也可直接联系作者:QQ-2687587184;Email-projectxero@163.com\n\n错误信息:\n" + tech);
|
||||
dialog.setPositiveButton("忽略", new android.content.DialogInterface.OnClickListener({
|
||||
onClick : function(dia,w) {
|
||||
dia.dismiss();
|
||||
@ -676,6 +676,8 @@ Loader.fromFile("modules/MCAdapter.js")
|
||||
|
||||
Loader.fromFile("modules/AndroidBridge.js")
|
||||
|
||||
Loader.fromFile("modules/utils/ExternalStorage.js")
|
||||
|
||||
Loader.fromFile("modules/core/DexPlugin.js")
|
||||
|
||||
Loader.fromFile("modules/NeteaseAdapter.js")
|
||||
|
@ -136,23 +136,30 @@ MapScript.loadModule("AndroidBridge", {
|
||||
if (!intent) return;
|
||||
switch (intent.getAction()) {
|
||||
case ScriptInterface.ACTION_ADD_LIBRARY:
|
||||
t = AndroidBridge.uriToFile(intent.getData());
|
||||
t = intent.getData();
|
||||
if (!t) {
|
||||
Common.toast("无法从" + intent.getData() + "读取拓展包");
|
||||
Common.toast("无法读取拓展包");
|
||||
break;
|
||||
}
|
||||
Common.showConfirmDialog({
|
||||
title : "确定加载拓展包“" + t + "”?",
|
||||
title : "确定加载拓展包“" + ExternalStorage.uriToName(t) + "”?",
|
||||
callback : function(id) {
|
||||
if (id != 0) return onReturn();
|
||||
if (!CA.Library.enableLibrary(String(t))) {
|
||||
Common.toast("无法导入该拓展包,可能文件不存在");
|
||||
const importFile = ExternalStorage.importFile(t, "caclib_*.json");
|
||||
try {
|
||||
CA.Library.enableLibrary(String(ExternalStorage.toUri(importFile)));
|
||||
CA.Library.initLibrary(function() {
|
||||
Common.toast("导入成功!");
|
||||
CA.showLibraryMan(onReturn);
|
||||
});
|
||||
} catch(e) {
|
||||
Log.e(e);
|
||||
Common.toast("无法导入该拓展包\n" + e);
|
||||
return CA.showLibraryMan(onReturn);
|
||||
}
|
||||
CA.Library.initLibrary(function() {
|
||||
Common.toast("导入成功!");
|
||||
CA.showLibraryMan(onReturn);
|
||||
});
|
||||
},
|
||||
onDismiss : function() {
|
||||
ctx.revokeUriPermission(ctx.getPackageName(), t, 0x3); // Intent.FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -249,12 +256,12 @@ MapScript.loadModule("AndroidBridge", {
|
||||
},
|
||||
openUriAction : function(uri, extras) {
|
||||
if (!uri) return;
|
||||
var path, obj, query, fragment;
|
||||
path = uri.getPath();
|
||||
query = uri.getEncodedQuery();
|
||||
fragment = uri.getFragment();
|
||||
switch (String(uri.getHost()).toLowerCase()) {
|
||||
case "base":
|
||||
var path, obj, query, fragment;
|
||||
path = uri.getPath();
|
||||
query = uri.getEncodedQuery();
|
||||
fragment = uri.getFragment();
|
||||
if (path) {
|
||||
obj = this.getBaseUriAction(String(path));
|
||||
if (obj) {
|
||||
@ -338,14 +345,14 @@ MapScript.loadModule("AndroidBridge", {
|
||||
},
|
||||
onclick : function(fset) {
|
||||
var self = this;
|
||||
AndroidBridge.listApp(function(pkg) {
|
||||
AndroidBridge.listLaunchableApp(function(pkg) {
|
||||
if (pkg == ctx.getPackageName()) {
|
||||
Common.toast("不能连锁启动自身!");
|
||||
return;
|
||||
}
|
||||
CA.settings.chainLaunch = pkg;
|
||||
fset(self.get());
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
}, {
|
||||
name : "WebSocket服务器",
|
||||
@ -391,12 +398,6 @@ MapScript.loadModule("AndroidBridge", {
|
||||
CA.settings.hideRecent = Boolean(v);
|
||||
Common.toast("本项设置将在重启命令助手后应用");
|
||||
}
|
||||
}, {
|
||||
name : "隐藏通知",
|
||||
description : "可能导致应用被自动关闭",
|
||||
type : "boolean",
|
||||
get : preference.getHideNotification.bind(preference),
|
||||
set : ScriptInterface.setHideNotification.bind(ScriptInterface)
|
||||
}, {
|
||||
name : "自动启动无障碍服务",
|
||||
description : "需要Root",
|
||||
@ -523,15 +524,18 @@ MapScript.loadModule("AndroidBridge", {
|
||||
};
|
||||
}
|
||||
},
|
||||
listApp : function(callback) {
|
||||
listLaunchableApp : function(callback, includeCancel) {
|
||||
Common.showProgressDialog(function(o) {
|
||||
var pm = ctx.getPackageManager();
|
||||
o.setText("正在加载列表……");
|
||||
o.setTextDelayed("正在加载列表……", 200);
|
||||
var lp = pm.getInstalledPackages(0).toArray();
|
||||
var i, r = [{
|
||||
text : "不使用",
|
||||
result : null
|
||||
}];
|
||||
var i, r = [];
|
||||
if (includeCancel) {
|
||||
r.push({
|
||||
text : "取消选择",
|
||||
result : null
|
||||
});
|
||||
}
|
||||
for (i in lp) {
|
||||
if (!lp[i].applicationInfo) continue;
|
||||
if (!pm.getLaunchIntentForPackage(lp[i].packageName)) continue;
|
||||
@ -548,6 +552,9 @@ MapScript.loadModule("AndroidBridge", {
|
||||
});
|
||||
}, true);
|
||||
},
|
||||
listApp : function(callback) { // Deprecated
|
||||
this.listLaunchableApp(callback, true);
|
||||
},
|
||||
startActivity : function(intent) {
|
||||
try {
|
||||
if (ctx.getPackageManager().queryIntentActivities(intent, android.content.pm.PackageManager.MATCH_DEFAULT_ONLY).size() > 0) {
|
||||
@ -769,48 +776,49 @@ MapScript.loadModule("AndroidBridge", {
|
||||
var i = new android.content.Intent(android.content.Intent.ACTION_GET_CONTENT);
|
||||
i.setType(mimeType);
|
||||
this.startActivityForResult(i, function(resultCode, data) {
|
||||
if (resultCode != -1) return; // RESULT_OK = -1
|
||||
if (resultCode != -1) return; // RESULT_OK
|
||||
callback(AndroidBridge.uriToFile(data.getData()));
|
||||
});
|
||||
},
|
||||
selectImage : function(callback) {
|
||||
if (MapScript.host == "Android") {
|
||||
try {
|
||||
this.selectFile("image/*", function(path) {
|
||||
callback(path);
|
||||
});
|
||||
return;
|
||||
} catch(e) {erp(e, true)}
|
||||
}
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
check : function(path) {
|
||||
var bmp = G.BitmapFactory.decodeFile(path.getAbsolutePath());
|
||||
if (!bmp) {
|
||||
Common.toast("不支持的图片格式");
|
||||
return false;
|
||||
}
|
||||
bmp.recycle();
|
||||
return true;
|
||||
},
|
||||
callback : function(f) {
|
||||
var path = String(f.result.getAbsolutePath());
|
||||
try {
|
||||
this.selectFile("image/*", function(path) {
|
||||
callback(path);
|
||||
}
|
||||
});
|
||||
});
|
||||
return;
|
||||
} catch(e) {erp(e, true)}
|
||||
},
|
||||
sendText : function(text, withSharesheet) {
|
||||
let intent = new android.content.Intent(android.content.Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(android.content.Intent.EXTRA_TEXT, new java.lang.String(String(text)));
|
||||
if (withSharesheet) {
|
||||
intent = android.content.Intent.createChooser(intent, null);
|
||||
}
|
||||
return this.startActivity(intent);
|
||||
},
|
||||
sendUri : function(uri, mimeType, withSharesheet) {
|
||||
let intent = new android.content.Intent(android.content.Intent.ACTION_SEND);
|
||||
intent.setType(mimeType);
|
||||
intent.putExtra(android.content.Intent.EXTRA_STREAM, uri);
|
||||
intent.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION | android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
if (withSharesheet) {
|
||||
intent = android.content.Intent.createChooser(intent, null);
|
||||
}
|
||||
return this.startActivity(intent);
|
||||
},
|
||||
sendFile : function(file, mimeType, withSharesheet) {
|
||||
return this.sendUri(this.fileToUri(file), mimeType, withSharesheet);
|
||||
},
|
||||
shareText : function(text) {
|
||||
return this.sendText(text, true);
|
||||
},
|
||||
viewUri : function(uri) {
|
||||
return AndroidBridge.startActivity(new android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(uri)));
|
||||
},
|
||||
createShortcut : function(intent, name, icon) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 26) {
|
||||
if (ScriptInterface.isForeground()) {
|
||||
AndroidBridge.doCreateShortcut(ctx, intent, name, icon);
|
||||
} else {
|
||||
this.beginForegroundTask("createShortcut@" + intent.hashCode().toString(16), function(activity) {
|
||||
AndroidBridge.doCreateShortcut(activity, intent, name, icon);
|
||||
});
|
||||
}
|
||||
AndroidBridge.doCreateShortcut(ctx, intent, name, icon);
|
||||
} else {
|
||||
var i = new android.content.Intent("com.android.launcher.action.INSTALL_SHORTCUT");
|
||||
i.putExtra(android.content.Intent.EXTRA_SHORTCUT_NAME, name);
|
||||
@ -976,23 +984,6 @@ MapScript.loadModule("AndroidBridge", {
|
||||
},
|
||||
checkNecessaryPermissions : function(callback) {
|
||||
AndroidBridge.requestPermissionsByGroup([{
|
||||
permissions : [
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
],
|
||||
explanation : "读取内部存储\n写入内部存储\n\n这些权限将用于读写命令库、编辑JSON、记录错误日志等",
|
||||
callback : function(flag, success, denied, sync) {
|
||||
if (!sync) {
|
||||
if (flag) {
|
||||
CA.load();
|
||||
Common.toast("权限请求成功,已重新加载配置");
|
||||
} else {
|
||||
Common.toast("权限请求失败\n将造成部分命令库无法读取等问题");
|
||||
}
|
||||
}
|
||||
},
|
||||
mode : 2
|
||||
}, {
|
||||
permissions : [
|
||||
"android.permission.READ_PHONE_STATE"
|
||||
],
|
||||
|
@ -4,7 +4,7 @@
|
||||
loadingStatus : null,
|
||||
currentLoadingLibrary : null,
|
||||
initLibrary : function(callback) {
|
||||
var info, flag = true, t, t2, lib;
|
||||
var info, flag = true, lib;
|
||||
if (this.loadingStatus) return false;
|
||||
this.loadingStatus = "core";
|
||||
CA.IntelliSense.library = lib = {
|
||||
@ -42,15 +42,15 @@
|
||||
} catch(e) {erp(e)}});
|
||||
return true;
|
||||
},
|
||||
clearCache : function(src) {
|
||||
if (src) {
|
||||
delete this.cache[src];
|
||||
clearCache : function(uriStr) {
|
||||
if (uriStr) {
|
||||
delete this.cache[uriStr];
|
||||
} else {
|
||||
this.cache = {};
|
||||
}
|
||||
},
|
||||
isLibrary : function(path) {
|
||||
return path in CA.Library.inner || new java.io.File(path).isFile();
|
||||
isLibrary : function(uriStr) { // Deprecated
|
||||
return uriStr in CA.Library.inner || ExternalStorage.canRead(ExternalStorage.toUri(uriStr));
|
||||
},
|
||||
isDeprecated : function(uuid, version) {
|
||||
if (!Array.isArray(version)) return true;
|
||||
@ -59,44 +59,45 @@
|
||||
if (uuid == "5a204d07-4b6d-4c51-9470-a2d8c8676ab8") return true; //调试屏幕:根本没用
|
||||
return false;
|
||||
},
|
||||
enableLibrary : function(path) {
|
||||
Common.removeSet(CA.settings.disabledLibrarys, path);
|
||||
Common.removeSet(CA.settings.coreLibrarys, path);
|
||||
return Common.addSet(CA.settings.enabledLibrarys, path);
|
||||
enableLibrary : function(uriStr) {
|
||||
Common.removeSet(CA.settings.disabledLibrarys, uriStr);
|
||||
Common.removeSet(CA.settings.coreLibrarys, uriStr);
|
||||
return Common.addSet(CA.settings.enabledLibrarys, uriStr);
|
||||
},
|
||||
disableLibrary : function(path) {
|
||||
Common.removeSet(CA.settings.enabledLibrarys, path);
|
||||
Common.removeSet(CA.settings.coreLibrarys, path);
|
||||
return Common.addSet(CA.settings.disabledLibrarys, path);
|
||||
disableLibrary : function(uriStr) {
|
||||
Common.removeSet(CA.settings.enabledLibrarys, uriStr);
|
||||
Common.removeSet(CA.settings.coreLibrarys, uriStr);
|
||||
return Common.addSet(CA.settings.disabledLibrarys, uriStr);
|
||||
},
|
||||
removeLibrary : function(path) {
|
||||
removeLibrary : function(uriStr) {
|
||||
var fl = false;
|
||||
fl = Common.removeSet(CA.settings.enabledLibrarys, path) || fl;
|
||||
fl = Common.removeSet(CA.settings.coreLibrarys, path) || fl;
|
||||
return Common.removeSet(CA.settings.disabledLibrarys, path) || fl;
|
||||
ExternalStorage.tryReleaseImportUri(ExternalStorage.toUri(uriStr));
|
||||
fl = Common.removeSet(CA.settings.enabledLibrarys, uriStr) || fl;
|
||||
fl = Common.removeSet(CA.settings.coreLibrarys, uriStr) || fl;
|
||||
return Common.removeSet(CA.settings.disabledLibrarys, uriStr) || fl;
|
||||
},
|
||||
enableCoreLibrary : function(path) {
|
||||
Common.removeSet(CA.settings.enabledLibrarys, path);
|
||||
Common.removeSet(CA.settings.disabledLibrarys, path);
|
||||
return Common.addSet(CA.settings.coreLibrarys, path);
|
||||
enableCoreLibrary : function(uriStr) {
|
||||
Common.removeSet(CA.settings.enabledLibrarys, uriStr);
|
||||
Common.removeSet(CA.settings.disabledLibrarys, uriStr);
|
||||
return Common.addSet(CA.settings.coreLibrarys, uriStr);
|
||||
},
|
||||
loadLibrary : function(path, targetLib) {
|
||||
var m, v, cur, resolved;
|
||||
loadLibrary : function(uriStr, targetLib) {
|
||||
var m, cur, resolved;
|
||||
try {
|
||||
if (this.cache[path]) {
|
||||
cur = this.cache[path].data;
|
||||
m = this.cache[path].mode;
|
||||
if (this.cache[uriStr]) {
|
||||
cur = this.cache[uriStr].data;
|
||||
m = this.cache[uriStr].mode;
|
||||
} else {
|
||||
cur = this.readLibrary(path);
|
||||
cur = this.readLibrary(uriStr);
|
||||
if (!cur) throw "无法读取或解析拓展包";
|
||||
if (cur.error) throw cur.error;
|
||||
if (!(cur.data instanceof Object)) throw "错误的拓展包格式";
|
||||
this.cache[path] = cur;
|
||||
this.cache[uriStr] = cur;
|
||||
m = cur.mode;
|
||||
cur = cur.data;
|
||||
}
|
||||
resolved = {
|
||||
src : path,
|
||||
src : uriStr,
|
||||
name : cur.name,
|
||||
author : cur.author,
|
||||
description : cur.description,
|
||||
@ -117,8 +118,8 @@
|
||||
return resolved;
|
||||
} else {
|
||||
return {
|
||||
src : path,
|
||||
name : m == 0 ? path : (new java.io.File(path)).getName(),
|
||||
src : uriStr,
|
||||
name : m == 0 ? uriStr : ExternalStorage.uriToName(ExternalStorage.toUri(uriStr)),
|
||||
hasError : true,
|
||||
mode : m,
|
||||
error : err
|
||||
@ -126,13 +127,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
readLibrary : function(path) {
|
||||
var t, er, f, securityLevel = CA.settings.securityLevel, requiredSecLevel;
|
||||
readLibrary : function(uriStr) {
|
||||
var t, er, uri, securityLevel = CA.settings.securityLevel, requiredSecLevel;
|
||||
//-1 禁止所有非内置拓展包
|
||||
//0 允许所有拓展包
|
||||
//1 仅允许锁定拓展包与官方拓展包
|
||||
//2+ 仅允许商店下载的拓展包
|
||||
if (t = CA.Library.inner[path]) {
|
||||
if (t = CA.Library.inner[uriStr]) {
|
||||
return {
|
||||
data : t,
|
||||
mode : 0
|
||||
@ -143,35 +144,37 @@
|
||||
};
|
||||
}
|
||||
if (securityLevel >= 0) {
|
||||
f = new java.io.File(path);
|
||||
if (!f.isFile()) {
|
||||
uri = ExternalStorage.toUri(uriStr);
|
||||
ExternalStorage.tryTakeUriPermission(uri);
|
||||
if (!ExternalStorage.isFile(uri)) {
|
||||
return {
|
||||
error : "拓展包文件不存在"
|
||||
};
|
||||
}
|
||||
requiredSecLevel = this.testSecurityLevel(f);
|
||||
requiredSecLevel = this.testSecurityLevel(uri);
|
||||
if (requiredSecLevel < securityLevel) {
|
||||
return {
|
||||
error : "您正在使用的安全等级不允许加载此拓展包\n您可以在右上角▼处打开菜单,然后点击“设置安全级别”来调整当前安全级别"
|
||||
};
|
||||
}
|
||||
if (requiredSecLevel >= 2) {
|
||||
if (t = CA.Library.loadSignedV1(f, null, er)) {
|
||||
if (t = CA.Library.loadSignedV1(uri, null, er)) {
|
||||
return {
|
||||
data : t,
|
||||
mode : 3
|
||||
};
|
||||
}
|
||||
} else if (requiredSecLevel == 1) {
|
||||
if (t = CA.Library.loadPrefixed(f, null, er)) {
|
||||
if (t = CA.Library.loadPrefixed(uri, null, er)) {
|
||||
return {
|
||||
data : t,
|
||||
mode : 2
|
||||
};
|
||||
}
|
||||
} else if (requiredSecLevel == 0) {
|
||||
if (t = Common.readFile(f.getPath(), null, false, er)) {
|
||||
t = this.safeEval(f, t, er);
|
||||
t = ExternalStorage.readFileContent(uri, "UTF-8", (error) => void (er = { error }))
|
||||
if (t) {
|
||||
t = this.safeEval(uri, t, er);
|
||||
if (t) {
|
||||
return {
|
||||
data : t,
|
||||
@ -187,29 +190,25 @@
|
||||
}
|
||||
return er;
|
||||
},
|
||||
evalLib : function(file, code) {
|
||||
return Loader.evalSpecial("(" + code + ")", file.getName(), 0, {
|
||||
path : String(file.getPath()),
|
||||
code : code,
|
||||
LibInfo : {
|
||||
file : file,
|
||||
uri : android.net.Uri.fromFile(file),
|
||||
code : code
|
||||
}
|
||||
evalLib : function(uri, code) {
|
||||
return Loader.evalSpecial("(" + code + ")", ExternalStorage.uriToName(uri), 0, {
|
||||
path : String(uri.getPath()),
|
||||
code,
|
||||
LibInfo : { uri, code }
|
||||
}, this);
|
||||
},
|
||||
safeEval :function(file, code, defaultValue, error) {
|
||||
safeEval : function(uri, code, defaultValue, error) {
|
||||
try {
|
||||
return this.evalLib(file, code);
|
||||
return this.evalLib(uri, code);
|
||||
} catch(e) {
|
||||
if (error) error.error = e;
|
||||
return defaultValue;
|
||||
}
|
||||
},
|
||||
testSecurityLevel : function(file) {
|
||||
if (this.shouldVerifySigned(file) >= 0) {
|
||||
testSecurityLevel : function(uri) {
|
||||
if (this.shouldVerifySigned(uri) >= 0) {
|
||||
return 2;
|
||||
} else if (this.isPrefixed(file)) {
|
||||
} else if (this.isPrefixed(uri)) {
|
||||
return 1;
|
||||
} else return 0;
|
||||
},
|
||||
@ -263,10 +262,10 @@
|
||||
}
|
||||
return null;
|
||||
},
|
||||
isPrefixed : function(file) {
|
||||
isPrefixed : function(uri) {
|
||||
try {
|
||||
var rd, q, start = [0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59];
|
||||
rd = new java.io.FileInputStream(file);
|
||||
rd = ExternalStorage.openInputStream(uri);
|
||||
while (start.length) {
|
||||
if (rd.read() != start.shift()) {
|
||||
rd.close();
|
||||
@ -282,10 +281,10 @@
|
||||
return false;
|
||||
}
|
||||
},
|
||||
loadPrefixed : function(file, defaultValue, error) {
|
||||
loadPrefixed : function(uri, defaultValue, error) {
|
||||
try{
|
||||
var rd, s = [], q, start = [0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59];
|
||||
rd = new java.io.FileInputStream(file);
|
||||
rd = ExternalStorage.openInputStream(uri);
|
||||
while (start.length) {
|
||||
if (rd.read() != start.shift()) {
|
||||
rd.close();
|
||||
@ -296,18 +295,16 @@
|
||||
rd = new java.io.BufferedReader(new java.io.InputStreamReader(new java.util.zip.GZIPInputStream(rd)));
|
||||
while (q = rd.readLine()) s.push(q);
|
||||
rd.close();
|
||||
return this.evalLib(file, s.join("\n"));
|
||||
return this.evalLib(uri, s.join("\n"));
|
||||
} catch(e) {
|
||||
if (error) error.error = e;
|
||||
return defaultValue;
|
||||
}
|
||||
},
|
||||
savePrefixed : function(path, object) {
|
||||
savePrefixed : function(uri, object) {
|
||||
var wr, ar;
|
||||
var f = new java.io.File(path).getParentFile();
|
||||
if (f) f.mkdirs();
|
||||
wr = new java.io.FileOutputStream(path);
|
||||
ar = java.nio.ByteBuffer.allocate(15); //LIBRARY
|
||||
wr = ExternalStorage.openOutputStream(uri);
|
||||
ar = java.nio.ByteBuffer.allocate(15); // LIBRARY
|
||||
ar.put([0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59]).putLong((new java.util.Date()).getTime());
|
||||
wr.write(ar.array());
|
||||
wr = new java.util.zip.GZIPOutputStream(wr);
|
||||
@ -424,7 +421,7 @@
|
||||
op = o.patterns;
|
||||
sp = src.patterns;
|
||||
if (Array.isArray(sp) != Array.isArray(op)) throw "命令模式格式不一致,无法合并";
|
||||
if (Array.isArray(op)) {
|
||||
if (Array.isArray(op)) { // Deprecated
|
||||
for (i in op) {
|
||||
t = sp.indexOf(op[i]);
|
||||
if (t < 0) sp.push(op[i]);
|
||||
@ -441,7 +438,7 @@
|
||||
op = o.patterns;
|
||||
sp = src.patterns;
|
||||
if (Array.isArray(sp) != Array.isArray(op)) throw "命令模式格式不一致,无法过滤";
|
||||
if (Array.isArray(op)) {
|
||||
if (Array.isArray(op)) { // Deprecated
|
||||
for (i in op) {
|
||||
t = sp.indexOf(op[i]);
|
||||
if (t >= 0) sp.splice(t, 1);
|
||||
@ -537,7 +534,7 @@
|
||||
} else if ((i in cur.commands) && l.mode != "overwrite") {
|
||||
joinCmd(cur.commands[i], l.commands[i]);
|
||||
} else {
|
||||
cur.commands[i] = l.commands[i];
|
||||
cur.commands[i] = Object.copy(l.commands[i]);
|
||||
}
|
||||
}
|
||||
for (i in l.enums) {
|
||||
@ -550,7 +547,7 @@
|
||||
} else if ((i in cur.enums) && l.mode != "overwrite") {
|
||||
joinEnum(cur.enums[i], parseAliasEnum(cur, l.enums[i]));
|
||||
} else {
|
||||
cur.enums[i] = parseAliasEnum(cur, l.enums[i]);
|
||||
cur.enums[i] = Object.copy(parseAliasEnum(cur, l.enums[i]));
|
||||
}
|
||||
}
|
||||
for (i in l.selectors) {
|
||||
@ -792,10 +789,12 @@
|
||||
os.write(arr);
|
||||
os.close();
|
||||
}
|
||||
return MapScript.baseDir + "libs/" + libinfo.uuid + ".lib";
|
||||
return ExternalStorage.toUri(MapScript.baseDir + "libs/" + libinfo.uuid + ".lib");
|
||||
},
|
||||
shouldVerifySigned : function(file) {
|
||||
if (!file.isFile()) return -1;
|
||||
shouldVerifySigned : function(uri) {
|
||||
if (!ExternalStorage.isFile(uri)) return -1;
|
||||
const file = ExternalStorage.uriToFile(uri);
|
||||
if (!file) return -1;
|
||||
var i, arr = this.readAsArray(new java.io.FileInputStream(file)), digest, bytes, buf;
|
||||
if (this.arrayStartsWith(arr, [0x4c, 0x49, 0x42, 0x53, 0x49, 0x47, 0x4e, 0x30, 0x31])) { //LIBSIGN01
|
||||
buf = java.nio.ByteBuffer.wrap(arr);
|
||||
@ -815,10 +814,10 @@
|
||||
return 1;
|
||||
} else return -1;
|
||||
},
|
||||
loadSignedV1 : function(file, defaultValue, error) {
|
||||
loadSignedV1 : function(uri, defaultValue, error) {
|
||||
try{
|
||||
var rd, s = [], q, start = [0x4c, 0x49, 0x42, 0x53, 0x49, 0x47, 0x4e, 0x30, 0x31]; //LIBSIGN01
|
||||
rd = new java.io.FileInputStream(file);
|
||||
rd = ExternalStorage.openInputStream(uri);
|
||||
while (start.length) {
|
||||
if (rd.read() != start.shift()) {
|
||||
rd.close();
|
||||
@ -832,7 +831,7 @@
|
||||
rd = new java.io.BufferedReader(new java.io.InputStreamReader(new java.util.zip.GZIPInputStream(rd)));
|
||||
while (q = rd.readLine()) s.push(q);
|
||||
rd.close();
|
||||
return this.evalLib(file, s.join("\n"));
|
||||
return this.evalLib(uri, s.join("\n"));
|
||||
} catch(e) {
|
||||
if (error) error.error = e;
|
||||
return defaultValue;
|
||||
@ -880,32 +879,33 @@
|
||||
callback(NeteaseAdapter.compareVersion(r.version, libinfo.version) > 0 ? 1 : 0, r, libinfo);
|
||||
},
|
||||
doUpdate : function(updateInfo, libInfo, statusListener) {
|
||||
var path;
|
||||
var uriStr;
|
||||
if (updateInfo.method == "intent") { //通过链接启动
|
||||
statusListener("downloadFromUri", String(updateInfo.uri));
|
||||
} else {
|
||||
statusListener("startDownload");
|
||||
try {
|
||||
if (updateInfo.source) {
|
||||
path = this.downloadLib({
|
||||
uriStr = String(this.downloadLib({
|
||||
downloadurl : updateInfo.url,
|
||||
sha1 : updateInfo.sha1,
|
||||
uuid : updateInfo.uuid
|
||||
}, this.requestSourceInfoCached(updateInfo.source));
|
||||
if (path != libInfo.src) {
|
||||
}, this.requestSourceInfoCached(updateInfo.source)));
|
||||
if (uriStr != libInfo.src) {
|
||||
ExternalStorage.tryReleaseImportUri(ExternalStorage.toUri(libInfo.src));
|
||||
if (Common.inSet(CA.settings.coreLibrarys, libInfo.src)) {
|
||||
Common.replaceLinkedSet(CA.settings.coreLibrarys, libInfo.src, path);
|
||||
Common.removeSet(CA.settings.enabledLibrarys, path);
|
||||
Common.replaceLinkedSet(CA.settings.coreLibrarys, libInfo.src, uriStr);
|
||||
Common.removeSet(CA.settings.enabledLibrarys, uriStr);
|
||||
} else {
|
||||
Common.replaceLinkedSet(CA.settings.enabledLibrarys, libInfo.src, path);
|
||||
Common.removeSet(CA.settings.coreLibrarys, path);
|
||||
Common.replaceLinkedSet(CA.settings.enabledLibrarys, libInfo.src, uriStr);
|
||||
Common.removeSet(CA.settings.coreLibrarys, uriStr);
|
||||
}
|
||||
if (libInfo.mode == 0) {
|
||||
Common.addSet(CA.settings.disabledLibrarys, libInfo.src);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NetworkUtils.download(updateInfo.url, libInfo.src);
|
||||
NetworkUtils.downloadToUri(updateInfo.url, ExternalStorage.toUri(libInfo.src));
|
||||
}
|
||||
} catch(e) {
|
||||
statusListener("downloadError", e);
|
||||
@ -936,7 +936,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (statusCode == 1) {
|
||||
} else if (statusCode == 0) {
|
||||
e.updateState = "latest";
|
||||
} else if (statusCode < 0) {
|
||||
e.updateState = "unavailable";
|
||||
|
459
modules/CA.js
459
modules/CA.js
@ -2003,13 +2003,14 @@ MapScript.loadModule("CA", {
|
||||
type : 0,
|
||||
text : "导入",
|
||||
action : function() {
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
callback : function(f) {
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "application/json",
|
||||
uri(uri) {
|
||||
try {
|
||||
var r = JSON.parse(Common.readFile(f.result, "[]"));
|
||||
const content = ExternalStorage.readFileContent(uri, "UTF-8", "[]");
|
||||
const r = JSON.parse(content);
|
||||
if (!Array.isArray(r)) throw "不正确的收藏夹格式";
|
||||
r.forEach(function(e) {
|
||||
r.forEach((e) => {
|
||||
e = String(e);
|
||||
if (e.length) CA.addHistory(e);
|
||||
});
|
||||
@ -2031,16 +2032,11 @@ MapScript.loadModule("CA", {
|
||||
if (!self.selection[i]) continue;
|
||||
z.push(CA.his[i]);
|
||||
}
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
try {
|
||||
Common.saveFile(f.result, JSON.stringify(z, null, 4));
|
||||
Common.toast("历史已保存至" + f.result);
|
||||
} catch(e) {
|
||||
erp(e, true);
|
||||
Common.toast("文件保存失败,无法导出\n" + e);
|
||||
}
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "application/json",
|
||||
hint: "历史.json",
|
||||
export(uri) {
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(z, null, 4));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -2291,13 +2287,14 @@ MapScript.loadModule("CA", {
|
||||
text : "导入",
|
||||
action : function() {
|
||||
var fd = self.path[self.path.length - 1];
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
callback : function(f) {
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "application/json",
|
||||
uri(uri) {
|
||||
try {
|
||||
var r = JSON.parse(Common.readFile(f.result, "[]"));
|
||||
const content = ExternalStorage.readFileContent(uri, "UTF-8", "[]");
|
||||
const r = JSON.parse(content);
|
||||
if (!Array.isArray(r)) throw "不正确的收藏夹格式";
|
||||
r.forEach(function(e) {
|
||||
r.forEach((e) => {
|
||||
CA.addFavorite(e, fd.children);
|
||||
});
|
||||
self.refresh();
|
||||
@ -2319,16 +2316,11 @@ MapScript.loadModule("CA", {
|
||||
if (!self.selection[i]) continue;
|
||||
a.push(self.array[i]);
|
||||
}
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
try {
|
||||
Common.saveFile(f.result, JSON.stringify(a, null, 4));
|
||||
Common.toast("收藏已保存至" + f.result);
|
||||
} catch(e) {
|
||||
erp(e, true);
|
||||
Common.toast("文件保存失败,无法导出\n" + e);
|
||||
}
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "application/json",
|
||||
hint: "收藏.json",
|
||||
export(uri) {
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(a, null, 4));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -2629,12 +2621,9 @@ MapScript.loadModule("CA", {
|
||||
name : "分享软件",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
var t = "https://www.coolapk.com/game/190152";
|
||||
var t = "https://ca.projectxero.top";
|
||||
try {
|
||||
AndroidBridge.startActivity(new android.content.Intent(android.content.Intent.ACTION_SEND)
|
||||
.setType("text/plain")
|
||||
.putExtra(android.content.Intent.EXTRA_TEXT, new java.lang.String("Hi,我发现一款很棒的Minecraft辅助软件,命令助手。下载链接:" + t))
|
||||
.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
AndroidBridge.shareText("Hi,我发现一款很棒的Minecraft辅助软件,命令助手。下载链接:" + t);
|
||||
} catch(e) {
|
||||
Common.setClipboardText(t);
|
||||
Common.toast("下载链接已复制到剪贴板");
|
||||
@ -2658,6 +2647,19 @@ MapScript.loadModule("CA", {
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name : "爱发电主页",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
try {
|
||||
if (!AndroidBridge.viewUri("afd://app/openapp?params=%7B%22url%22:%22https://afdian.net/a/projectxero%22,%22type%22:%221%22%7D")) {
|
||||
AndroidBridge.viewUri("https://afdian.net/a/projectxero");
|
||||
}
|
||||
} catch(e) {
|
||||
Common.toast("爱发电打开失败");
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
},/*{
|
||||
name : "哔哩哔哩空间",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
@ -2670,7 +2672,17 @@ MapScript.loadModule("CA", {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
},*/{
|
||||
name : "加入内测群",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
try {
|
||||
AndroidBridge.viewUri("https://projectxero.top/qqgroup/cabeta/");
|
||||
} catch(e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
},/*{
|
||||
name : "加入交流群",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
@ -2682,7 +2694,7 @@ MapScript.loadModule("CA", {
|
||||
Log.e(e);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
},*/{
|
||||
name : "许可协议",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
@ -3211,14 +3223,15 @@ MapScript.loadModule("CA", {
|
||||
name : "导入用户数据",
|
||||
type : "custom",
|
||||
onclick : function() {
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
callback : function(f) {
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "*/*",
|
||||
file(f) {
|
||||
try {
|
||||
CA.importSettings(f.result);
|
||||
CA.importSettings(f);
|
||||
} catch(e) {
|
||||
Common.toast("从" + f.result + "导入用户数据失败\n" + e);
|
||||
Common.toast("导入用户数据失败\n" + e);
|
||||
}
|
||||
ExternalStorage.tryReleaseImportFile(f);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -3290,13 +3303,13 @@ MapScript.loadModule("CA", {
|
||||
Common.showOperateDialog([{
|
||||
text : "导出",
|
||||
onclick : function() {
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
defaultFileName : "ca_settings.dat",
|
||||
callback : function(f) {
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "application/octet-stream",
|
||||
hint: "ca_settings.dat",
|
||||
export(uri) {
|
||||
try {
|
||||
Common.fileCopy(new java.io.File(CA.profilePath), f.result);
|
||||
Common.toast("配置已导出至" + f.result);
|
||||
ExternalStorage.copy(ExternalStorage.toUri(CA.profilePath), uri);
|
||||
Common.toast("配置已导出");
|
||||
} catch(e) {
|
||||
erp(e, true);
|
||||
Common.toast("文件保存失败,无法导出\n" + e);
|
||||
@ -3310,26 +3323,17 @@ MapScript.loadModule("CA", {
|
||||
onclick : function() {
|
||||
try {
|
||||
Common.fileCopy(new java.io.File(CA.profilePath), this.path);
|
||||
AndroidBridge.startActivity(this.intent);
|
||||
AndroidBridge.sendFile(this.path);
|
||||
} catch(e) {
|
||||
Log.e(e);
|
||||
Common.toast("发送配置文件失败\n" + e);
|
||||
}
|
||||
},
|
||||
hidden : function() {
|
||||
try {
|
||||
this.intent = new android.content.Intent(android.content.Intent.ACTION_SEND)
|
||||
.setType("text/plain")
|
||||
.putExtra(android.content.Intent.EXTRA_STREAM, AndroidBridge.fileToUri(this.path))
|
||||
.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION | android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION | android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
} catch(e) {Log.e(e)}
|
||||
return !this.intent;
|
||||
}
|
||||
}]);
|
||||
},
|
||||
|
||||
manageErrors : function() {
|
||||
var f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "com.xero.ca.error.log");
|
||||
var f = new java.io.File(MapScript.baseDir, "com.xero.ca.error.log");
|
||||
if (!f.isFile()) return Common.toast("无错误记录");
|
||||
Common.showOperateDialog([{
|
||||
text : "打开",
|
||||
@ -3353,19 +3357,8 @@ MapScript.loadModule("CA", {
|
||||
}
|
||||
}, {
|
||||
text : "发送",
|
||||
intent : (function() {
|
||||
try {
|
||||
return new android.content.Intent(android.content.Intent.ACTION_SEND)
|
||||
.setType("text/plain")
|
||||
.putExtra(android.content.Intent.EXTRA_STREAM, AndroidBridge.fileToUri(f))
|
||||
.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION | android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION | android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
} catch(e) {Log.e(e)}
|
||||
})(),
|
||||
onclick : function() {
|
||||
AndroidBridge.startActivity(this.intent);
|
||||
},
|
||||
hidden : function() {
|
||||
return !this.intent;
|
||||
AndroidBridge.sendFile(f);
|
||||
}
|
||||
}, {
|
||||
text : "清空",
|
||||
@ -3376,7 +3369,7 @@ MapScript.loadModule("CA", {
|
||||
}]);
|
||||
},
|
||||
listErrors : function() {
|
||||
var f = Common.readFile(android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/com.xero.ca.error.log", "");
|
||||
var f = Common.readFile(MapScript.baseDir + "com.xero.ca.error.log", "");
|
||||
if (!f.length) return;
|
||||
var a = f.slice(9).split("\n* ");
|
||||
a.reverse();
|
||||
@ -3939,17 +3932,13 @@ MapScript.loadModule("CA", {
|
||||
text : "从文件中导入",
|
||||
description : "导入外置拓展包",
|
||||
onclick : function(v, tag) {
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
callback : function(f) {
|
||||
self.postTask(function(cb) {
|
||||
var path = String(f.result.getAbsolutePath());
|
||||
if (!CA.Library.isLibrary(path)) {
|
||||
Common.toast("无法导入该拓展包,可能文件不存在");
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
CA.Library.enableLibrary(path);
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "*/*",
|
||||
hint: "caclib_*.json",
|
||||
file(f) {
|
||||
self.postTask((cb) => {
|
||||
const uriStr = String(ExternalStorage.toUri(f));
|
||||
CA.Library.enableLibrary(uriStr);
|
||||
cb(true, function() {
|
||||
Common.toast("导入成功!");
|
||||
});
|
||||
@ -3960,27 +3949,49 @@ MapScript.loadModule("CA", {
|
||||
hidden : function() {
|
||||
return CA.settings.securityLevel < 0;
|
||||
}
|
||||
},{
|
||||
text : "从外部存储加载",
|
||||
description : "从外部存储中加载外置拓展包",
|
||||
onclick : function(v, tag) {
|
||||
ExternalStorage.showOpenActions({
|
||||
mimeType: "*/*",
|
||||
callback(uri) {
|
||||
ExternalStorage.tryTakeUriPermission(uri);
|
||||
self.postTask((cb) => {
|
||||
const uriStr = String(uri);
|
||||
CA.Library.enableLibrary(uriStr);
|
||||
cb(true, function() {
|
||||
Common.toast("加载成功!");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
hidden : function() {
|
||||
return CA.settings.securityLevel != 0;
|
||||
}
|
||||
},{
|
||||
text : "新建拓展包",
|
||||
description : "新建一个不包含内容的包",
|
||||
onclick : function(v, tag) {
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
self.postTask(function(cb) {
|
||||
var fp = String(f.result.getAbsolutePath());
|
||||
ExternalStorage.showSaveActions({
|
||||
mimeType: "application/json",
|
||||
hint: "新建拓展包.json",
|
||||
callback(uri) {
|
||||
ExternalStorage.tryTakeUriPermission(uri);
|
||||
self.postTask((cb) => {
|
||||
try {
|
||||
MapScript.saveJSON(fp, {
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify({
|
||||
"name": "新建拓展包",
|
||||
"author": "作者名",
|
||||
"description": "此处填写介绍,可留空,新建于" + new Date().toLocaleDateString(),
|
||||
"description": "此处填写介绍,可留空,新建于" + new Date().toLocaleString(),
|
||||
"uuid": String(java.util.UUID.randomUUID().toString()),
|
||||
"version": [0, 0, 1],
|
||||
"require": []
|
||||
});
|
||||
CA.Library.enableLibrary(fp);
|
||||
}));
|
||||
CA.Library.enableLibrary(String(uri));
|
||||
cb(true, function() {
|
||||
Common.toast("拓展包已新建:" + fp);
|
||||
Common.toast("拓展包已新建");
|
||||
});
|
||||
} catch(e) {
|
||||
Common.toast("文件保存失败,无法新建\n" + e);
|
||||
@ -3991,7 +4002,7 @@ MapScript.loadModule("CA", {
|
||||
});
|
||||
},
|
||||
hidden : function() {
|
||||
return CA.settings.securityLevel >= 1 || CA.settings.securityLevel < 0;
|
||||
return CA.settings.securityLevel != 0;
|
||||
}
|
||||
},{
|
||||
text : "刷新",
|
||||
@ -4124,7 +4135,7 @@ MapScript.loadModule("CA", {
|
||||
text : "忽略版本",
|
||||
description : "暂时忽略版本限制",
|
||||
hidden : function() {
|
||||
return CA.Library.ignoreVersion;
|
||||
return CA.settings.securityLevel != 0 || CA.Library.ignoreVersion;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
self.postTask(function(cb) {
|
||||
@ -4139,7 +4150,7 @@ MapScript.loadModule("CA", {
|
||||
text : "取消忽略版本",
|
||||
description : "取消忽略版本限制",
|
||||
hidden : function() {
|
||||
return !CA.Library.ignoreVersion;
|
||||
return CA.settings.securityLevel != 0 || !CA.Library.ignoreVersion;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
self.postTask(function(cb) {
|
||||
@ -4155,10 +4166,12 @@ MapScript.loadModule("CA", {
|
||||
description : "将拓展包列表恢复为默认",
|
||||
onclick : function(v, tag) {
|
||||
self.postTask(function(cb) {
|
||||
CA.settings.enabledLibrarys = Object.keys(CA.Library.inner);
|
||||
CA.settings.disabledLibrarys = [];
|
||||
CA.settings.coreLibrarys = [];
|
||||
CA.settings.deprecatedLibrarys = [];
|
||||
CA.settings.enabledLibrarys.concat(
|
||||
CA.settings.disabledLibrarys,
|
||||
CA.settings.coreLibrarys
|
||||
).forEach((e) => CA.Library.removeLibrary(e));
|
||||
CA.Library.recommended.forEach((e) => CA.Library.enableLibrary(e));
|
||||
CA.Library.defaultDisabled.forEach((e) => CA.Library.disableLibrary(e));
|
||||
CA.Library.clearCache();
|
||||
cb(true, function() {
|
||||
Common.toast("已恢复为默认拓展包列表");
|
||||
@ -4186,39 +4199,46 @@ MapScript.loadModule("CA", {
|
||||
text : "查看信息",
|
||||
description : "查看该拓展包的相关信息",
|
||||
onclick : function(v, tag) {
|
||||
var f = new java.io.File(tag.data.src), s;
|
||||
s = "名称 : " + tag.data.name;
|
||||
if (f.isFile()) s += "\n位置 : " + tag.data.src + "\n大小 : " + Common.getFileSize(f, true) + "\n时间 : " + new Date(f.lastModified()).toLocaleString();
|
||||
var uri = ExternalStorage.toUri(tag.data.src);
|
||||
var s = ["名称 : " + tag.data.name];
|
||||
if (ExternalStorage.isFile(uri)) {
|
||||
s.push("位置 : " + tag.data.src);
|
||||
s.push("大小 : " + ExternalStorage.getLengthString(uri));
|
||||
s.push("时间 : " + ExternalStorage.getLastModifiedString(uri));
|
||||
}
|
||||
if (tag.data.updateState) {
|
||||
s += "\n更新状态 : ";
|
||||
let updateStateStr;
|
||||
switch (tag.data.updateState) {
|
||||
case "checking":
|
||||
s += "正在检测";
|
||||
updateStateStr = "正在检测";
|
||||
break;
|
||||
case "latest":
|
||||
s += "已是最新版";
|
||||
updateStateStr = "已是最新版";
|
||||
break;
|
||||
case "unavailable":
|
||||
s += "更新源不可用";
|
||||
updateStateStr = "更新源不可用";
|
||||
break;
|
||||
case "ready":
|
||||
s += "已准备更新";
|
||||
updateStateStr = "已准备更新";
|
||||
break;
|
||||
case "waitForUser":
|
||||
s += "等待用户手动更新";
|
||||
updateStateStr = "等待用户手动更新";
|
||||
break;
|
||||
case "error":
|
||||
s += "下载更新出错";
|
||||
updateStateStr = "下载更新出错";
|
||||
break;
|
||||
case "finished":
|
||||
s += "已下载更新";
|
||||
updateStateStr = "已下载更新";
|
||||
break;
|
||||
default:
|
||||
s += "未知";
|
||||
updateStateStr = "未知";
|
||||
}
|
||||
s.push("更新状态 : " + updateStateStr);
|
||||
}
|
||||
if (!tag.data.disabled && !tag.data.hasError && tag.data.stat) s += "\n\n" + tag.data.stat.toString();
|
||||
Common.showTextDialog(s);
|
||||
if (!tag.data.disabled && !tag.data.hasError && tag.data.stat) {
|
||||
s.push("", tag.data.stat.toString());
|
||||
}
|
||||
Common.showTextDialog(s.join("\n"));
|
||||
}
|
||||
}];
|
||||
self.enabledMenu = [{
|
||||
@ -4275,90 +4295,99 @@ MapScript.loadModule("CA", {
|
||||
text : "编辑",
|
||||
description : "用JSON编辑器编辑该拓展包",
|
||||
hidden : function(tag) {
|
||||
return tag.data.mode != 1;
|
||||
return CA.settings.securityLevel != 0 || tag.data.mode != 1;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
self.postTask(function(cb) {
|
||||
var a = MapScript.readJSON(tag.data.src, {});
|
||||
if (!(a instanceof Object)) a = {};
|
||||
JSONEdit.show({
|
||||
source : a,
|
||||
rootname : "拓展包",
|
||||
update : function() {
|
||||
var uri = ExternalStorage.toUri(tag.data.src);
|
||||
var content;
|
||||
try {
|
||||
content = ExternalStorage.readFileContent(uri, "UTF-8");
|
||||
a = JSON.parse(content);
|
||||
} catch(e) {
|
||||
Common.toast("此拓展包无法使用JSON编辑器进行编辑\n" + e);
|
||||
return;
|
||||
}
|
||||
if (!(a instanceof Object)) a = {};
|
||||
JSONEdit.show({
|
||||
source : a,
|
||||
rootname : "拓展包",
|
||||
update : function() {
|
||||
self.postTask(function(cb) {
|
||||
try {
|
||||
self.processing = true;
|
||||
MapScript.saveJSON(tag.data.src, a);
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(a));
|
||||
CA.Library.clearCache(tag.data.src);
|
||||
cb(true, function() {
|
||||
Common.toast("加载成功!");
|
||||
});
|
||||
} catch(e) {
|
||||
Common.toast("格式不合法,无法保存\n" + e);
|
||||
Common.toast("文件保存失败\n" + e);
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},{
|
||||
text : "另存为",
|
||||
description : "将该拓展包保存到一个新文件里",
|
||||
onclick : function(v, tag) {
|
||||
if (tag.data.hasError) {
|
||||
Common.toast("拓展包“" + tag.data.name + "”有错误,请先解决错误再另存为");
|
||||
return true;
|
||||
}
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
self.postTask(function(cb) {
|
||||
var fp = String(f.result.getAbsolutePath());
|
||||
try {
|
||||
if (tag.data.mode == 0) {
|
||||
MapScript.saveJSON(fp, CA.Library.inner[tag.data.src]);
|
||||
} else {
|
||||
Common.fileCopy(new java.io.File(tag.data.src), f.result);
|
||||
}
|
||||
CA.Library.clearCache(fp);
|
||||
CA.Library.disableLibrary(fp);
|
||||
cb(true, function() {
|
||||
Common.toast("拓展包“" + tag.data.name + "”已另存为" + fp);
|
||||
});
|
||||
} catch(e) {
|
||||
Common.toast("文件保存失败,无法另存为\n" + e);
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},{
|
||||
text : "导出",
|
||||
description : "将该拓展包保存到一个新文件里",
|
||||
onclick : function(v, tag) {
|
||||
if (tag.data.hasError) {
|
||||
Common.toast("拓展包“" + tag.data.name + "”有错误,请先解决错误再导出");
|
||||
return true;
|
||||
}
|
||||
if (tag.data.mode == 0) {
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "application/json",
|
||||
hint: tag.data.name + ".json",
|
||||
export(uri) {
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(CA.Library.inner[tag.data.src]));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "application/json",
|
||||
hint: tag.data.name + ".json",
|
||||
export: tag.data.src
|
||||
});
|
||||
}
|
||||
}
|
||||
},{
|
||||
text : "创建副本",
|
||||
description : "创建该拓展包的副本(副本不会被认为与原拓展包相同)",
|
||||
hidden : function(tag) {
|
||||
return tag.data.hasError || tag.data.mode >= 2;
|
||||
return CA.settings.securityLevel != 0 || tag.data.hasError || tag.data.mode >= 2;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
ExternalStorage.showSaveActions({
|
||||
mimeType: "application/json",
|
||||
hint: tag.data.name + ".json",
|
||||
callback(uri) {
|
||||
self.postTask(function(cb) {
|
||||
var fp = String(f.result.getAbsolutePath()), l;
|
||||
try {
|
||||
if (tag.data.mode == 0) {
|
||||
l = Object.copy(CA.Library.inner[tag.data.src]);
|
||||
} else {
|
||||
l = MapScript.readJSON(tag.data.src, null);
|
||||
if (!(l instanceof Object)) throw "无法读取文件";
|
||||
let l;
|
||||
const uriStr = String(uri);
|
||||
if (tag.data.mode == 0) {
|
||||
l = Object.copy(CA.Library.inner[tag.data.src]);
|
||||
} else {
|
||||
try {
|
||||
const origUri = ExternalStorage.toUri(tag.data.src);
|
||||
const content = ExternalStorage.readFileContent(origUri, "UTF-8");
|
||||
l = JSON.parse(content);
|
||||
if (!(l instanceof Object)) throw "格式错误";
|
||||
} catch(e) {
|
||||
Common.toast("此拓展包无法创建副本\n" + e);
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
l.name = String(l.name) + " 的副本";
|
||||
l.uuid = String(java.util.UUID.randomUUID().toString());
|
||||
MapScript.saveJSON(fp, l);
|
||||
CA.Library.clearCache(fp);
|
||||
CA.Library.enableLibrary(fp);
|
||||
}
|
||||
l.name = String(l.name) + " 的副本";
|
||||
l.uuid = String(java.util.UUID.randomUUID().toString());
|
||||
try {
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(l));
|
||||
CA.Library.clearCache(uriStr);
|
||||
CA.Library.enableLibrary(uriStr);
|
||||
cb(true, function() {
|
||||
Common.toast("拓展包“" + tag.data.name + "”的副本已创建" + fp);
|
||||
Common.toast("拓展包“" + tag.data.name + "”的副本已创建");
|
||||
});
|
||||
} catch(e) {
|
||||
Common.toast("文件保存失败,无法创建副本\n" + e);
|
||||
@ -4372,7 +4401,7 @@ MapScript.loadModule("CA", {
|
||||
text : "锁定",
|
||||
description : "锁定拓展包,使其不能被编辑",
|
||||
hidden : function(tag) {
|
||||
return tag.data.hasError || tag.data.mode != 1;
|
||||
return CA.settings.securityLevel != 0 || tag.data.hasError || tag.data.mode != 1;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
Common.showConfirmDialog({
|
||||
@ -4382,7 +4411,10 @@ MapScript.loadModule("CA", {
|
||||
if (id != 0) return;
|
||||
self.postTask(function(cb) {
|
||||
try {
|
||||
CA.Library.savePrefixed(tag.data.src, MapScript.readJSON(tag.data.src));
|
||||
const uri = ExternalStorage.toUri(tag.data.src);
|
||||
const content = ExternalStorage.readFileContent(uri, "UTF-8");
|
||||
const obj = JSON.parse(content);
|
||||
CA.Library.savePrefixed(uri, obj);
|
||||
CA.Library.clearCache(tag.data.src);
|
||||
cb(true, function() {
|
||||
Common.toast("拓展包“" + tag.data.name + "”已被锁定");
|
||||
@ -4531,12 +4563,18 @@ MapScript.loadModule("CA", {
|
||||
return;
|
||||
}
|
||||
var arr = CA.IntelliSense.library.info.concat(CA.settings.disabledLibrarys.map(function(e, i, a) {
|
||||
var k = e in CA.Library.inner;
|
||||
var isInternal = e in CA.Library.inner;
|
||||
var name;
|
||||
if (isInternal) {
|
||||
name = CA.Library.inner[e].name;
|
||||
} else {
|
||||
name = ExternalStorage.uriToName(ExternalStorage.toUri(e));
|
||||
}
|
||||
return {
|
||||
src : e,
|
||||
index : i,
|
||||
mode : k ? 0 : -1,
|
||||
name : k ? CA.Library.inner[e].name : (new java.io.File(e)).getName(),
|
||||
mode : isInternal ? 0 : -1,
|
||||
name : name,
|
||||
disabled : true
|
||||
};
|
||||
}));
|
||||
@ -4766,12 +4804,12 @@ MapScript.loadModule("CA", {
|
||||
}
|
||||
self.downloadLib = function(data) {
|
||||
Common.showProgressDialog(function(dia) {
|
||||
var path;
|
||||
var uriStr;
|
||||
dia.setText("正在下载拓展包: " + data.name);
|
||||
try {
|
||||
path = CA.Library.downloadLib(data, self.libsrc);
|
||||
CA.Library.clearCache(path);
|
||||
CA.Library.enableLibrary(path);
|
||||
uriStr = String(CA.Library.downloadLib(data, self.libsrc));
|
||||
CA.Library.clearCache(uriStr);
|
||||
CA.Library.enableLibrary(uriStr);
|
||||
} catch(e) {
|
||||
Common.toast("下载拓展包“" + data.name + "”失败\n" + e);
|
||||
return;
|
||||
@ -4898,6 +4936,10 @@ MapScript.loadModule("CA", {
|
||||
Common.showOperateDialog([{
|
||||
text : "不使用",
|
||||
onclick : function() {
|
||||
if (CA.settings.bgImage) {
|
||||
const file = new java.io.File(CA.settings.bgImage);
|
||||
ExternalStorage.tryReleaseImportFile(file);
|
||||
}
|
||||
CA.settings.bgImage = null;
|
||||
callback();
|
||||
Common.toast("背景图片已设置为 无");
|
||||
@ -4905,11 +4947,14 @@ MapScript.loadModule("CA", {
|
||||
}, {
|
||||
text : "从文件中选择",
|
||||
onclick : function(v, tag) {
|
||||
AndroidBridge.selectImage(function(path) {
|
||||
if (!path) return Common.toast("背景图片无效");
|
||||
CA.settings.bgImage = path;
|
||||
callback();
|
||||
Common.toast("背景图片已设置为 " + path);
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "image/*",
|
||||
hint: "ca_background_image",
|
||||
file(f) {
|
||||
CA.settings.bgImage = String(f.getAbsolutePath());
|
||||
callback();
|
||||
Common.toast("背景图片已设置");
|
||||
}
|
||||
});
|
||||
}
|
||||
}, {
|
||||
@ -4945,11 +4990,15 @@ MapScript.loadModule("CA", {
|
||||
return view;
|
||||
}
|
||||
self.selectIcon = function(callback) {
|
||||
AndroidBridge.selectImage(function(path) {
|
||||
if (!path) return Common.toast("图片无效");
|
||||
CA.settings.icon = path;
|
||||
if (self.recent.indexOf(path) < 0) self.recent.push(path);
|
||||
if (callback) callback();
|
||||
ExternalStorage.showImportActions({
|
||||
mimeType: "image/*",
|
||||
hint: "ca_icon_image",
|
||||
file(f) {
|
||||
const path = String(f.getAbsolutePath());
|
||||
CA.settings.icon = path;
|
||||
if (self.recent.indexOf(path) < 0) self.recent.push(path);
|
||||
if (callback) callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
self.recent = [];
|
||||
@ -5407,9 +5456,15 @@ MapScript.loadModule("CA", {
|
||||
|
||||
PWM.registerResetFlag(self, "linear");
|
||||
}
|
||||
self.init(list);
|
||||
self.callback = callback;
|
||||
self.popup.enter();
|
||||
Common.showProgressDialog(function(o) {
|
||||
o.setText("正在加载列表……");
|
||||
self.init(list);
|
||||
if (o.cancelled) return;
|
||||
G.ui(function() {try {
|
||||
self.callback = callback;
|
||||
self.popup.enter();
|
||||
} catch(e) {erp(e)}});
|
||||
}, true);
|
||||
} catch(e) {erp(e)}})},
|
||||
|
||||
SpecialTips : [
|
||||
@ -6033,13 +6088,13 @@ MapScript.loadModule("CA", {
|
||||
return;
|
||||
}
|
||||
self.addExp();
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
var fp = String(f.result.getAbsolutePath());
|
||||
ExternalStorage.showExportActions({
|
||||
mimeType: "text/plain",
|
||||
hint: "generated.mcfunction",
|
||||
export(uri) {
|
||||
try {
|
||||
Common.saveFile(fp, "# This file is spawned by CA\n# Template: " + self.flatten() + "\n\n" + self.export().join("\n"));
|
||||
Common.toast("已保存至" + fp);
|
||||
ExternalStorage.writeFileContent(uri, "# This file is spawned by CA\n# Template: " + self.flatten() + "\n\n" + self.export().join("\n"));
|
||||
Common.toast("函数文件已保存");
|
||||
} catch(e) {
|
||||
Common.toast("保存函数文件失败\n" + e);
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ MapScript.loadModule("Common", {
|
||||
prg.startAnimation(aset);
|
||||
}
|
||||
self.init = function(o) {G.ui(function() {try {
|
||||
var layout, text, prg, popup;
|
||||
var layout, text, prg;
|
||||
layout = new G.LinearLayout(ctx);
|
||||
layout.setOrientation(G.LinearLayout.VERTICAL);
|
||||
Common.applyStyle(layout, "message_bg");
|
||||
@ -601,34 +601,45 @@ MapScript.loadModule("Common", {
|
||||
});
|
||||
} catch(e) {erp(e)}})},
|
||||
self.controller = {
|
||||
setText : function(s) {
|
||||
setText : function(s, uptimeMillis) {
|
||||
var o = this;
|
||||
G.ui(function() {try {
|
||||
gHandler.postAtTime(() => {try {
|
||||
if (o.closed) return;
|
||||
o.currentText = s;
|
||||
if (!o.popup) {
|
||||
self.init(o);
|
||||
}
|
||||
o.text.setText(Common.toString(s));
|
||||
} catch(e) {erp(e)}});
|
||||
} catch(e) {erp(e)}}, uptimeMillis || android.os.SystemClock.uptimeMillis());
|
||||
},
|
||||
close : function() {
|
||||
setTextDelayed : function(s, millis) {
|
||||
this.setText(s, android.os.SystemClock.uptimeMillis() + millis);
|
||||
},
|
||||
close : function(callback) {
|
||||
var o = this;
|
||||
G.ui(function() {try {
|
||||
if (o.closed) return;
|
||||
o.closed = true;
|
||||
o.popup.exit();
|
||||
if (o.popup) {
|
||||
o.popup.exit();
|
||||
}
|
||||
if (callback) callback();
|
||||
} catch(e) {erp(e)}});
|
||||
},
|
||||
async : function(f) {
|
||||
async : function(f, onFinally) {
|
||||
var o = this;
|
||||
Threads.run(function() {
|
||||
try {
|
||||
f(o);
|
||||
} catch(e) {erp(e)}
|
||||
o.close();
|
||||
o.close(onFinally);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
var o = Object.create(self.controller);
|
||||
o.startTime = android.os.SystemClock.uptimeMillis();
|
||||
o.onCancel = onCancel;
|
||||
self.init(o);
|
||||
if (f) o.async(f);
|
||||
return o;
|
||||
},
|
||||
@ -1048,7 +1059,10 @@ MapScript.loadModule("Common", {
|
||||
fi.sort(self.compare);
|
||||
}
|
||||
var a = o.fileFirst ? fi.concat(dir) : dir.concat(fi);
|
||||
if (o.curdir.getParent()) a.unshift(null);
|
||||
var parent = o.curdir.getParent();
|
||||
if (parent && ExternalStorage.isInStorage(parent)) {
|
||||
a.unshift(null);
|
||||
}
|
||||
self.list.setAdapter(self.curadp = new SimpleListAdapter(a, self.vmaker, self.vbinder));
|
||||
}
|
||||
self.linear = new G.LinearLayout(ctx);
|
||||
@ -1142,10 +1156,21 @@ MapScript.loadModule("Common", {
|
||||
self.list.setOnItemClickListener(new G.AdapterView.OnItemClickListener({onItemClick : function(parent, view, pos, id) {try {
|
||||
var o = self.sets;
|
||||
var e = self.curadp.getItem(pos);
|
||||
if (!e) {
|
||||
o.curdir = o.curdir.getParentFile();
|
||||
} else if (e.isDirectory()) {
|
||||
o.curdir = e;
|
||||
var newdir;
|
||||
if (!e || e.isDirectory()) {
|
||||
if (e) {
|
||||
newdir = e;
|
||||
} else {
|
||||
newdir = o.curdir.getParentFile();
|
||||
}
|
||||
if (ExternalStorage.isAccessible(newdir.getAbsolutePath())) {
|
||||
o.curdir = newdir;
|
||||
} else {
|
||||
ExternalStorage.ensureExternalStorage(function() {
|
||||
o.curdir = newdir;
|
||||
self.refresh();
|
||||
});
|
||||
}
|
||||
} else if (o.type == 0) {
|
||||
self.choose(e);
|
||||
return true;
|
||||
@ -1217,7 +1242,9 @@ MapScript.loadModule("Common", {
|
||||
self.sets = o;
|
||||
try {
|
||||
o.curdir = new java.io.File(String(o.initDir ? o.initDir : self.lastDir));
|
||||
if (!o.curdir.isDirectory()) o.curdir = android.os.Environment.getExternalStorageDirectory();
|
||||
if (!o.curdir.isDirectory() || !ExternalStorage.isAccessible(o.curdir.getAbsolutePath())) {
|
||||
o.curdir = ExternalStorage.getAccessibleRoot();
|
||||
}
|
||||
self.refresh();
|
||||
} catch (e) {
|
||||
Common.toast(self.intl.resolve("errAccessDir", e));
|
||||
@ -1750,5 +1777,15 @@ MapScript.loadModule("Common", {
|
||||
while (o.hasNext()) r.push(o.next());
|
||||
}
|
||||
return r;
|
||||
},
|
||||
stringComparator : function(a, b) {
|
||||
a = String(a);
|
||||
b = String(b);
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
},
|
||||
stringComparatorIgnoreCase : function(a, b) {
|
||||
a = String(a).toLowerCase();
|
||||
b = String(b).toLowerCase();
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
}
|
||||
});
|
@ -139,10 +139,7 @@ MapScript.loadModule("DebugUtils", {
|
||||
_fs.println(_t);
|
||||
_fs.close();
|
||||
try {
|
||||
AndroidBridge.startActivity(new android.content.Intent(android.content.Intent.ACTION_SEND)
|
||||
.setType("text/plain")
|
||||
.putExtra(android.content.Intent.EXTRA_STREAM, AndroidBridge.fileToUri(_file))
|
||||
.addFlags(android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION | android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION | android.content.Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
AndroidBridge.sendFile(_file);
|
||||
} catch(e) {
|
||||
Common.toast("文件已生成于" + _file.getAbsolutePath());
|
||||
}
|
||||
|
@ -22,30 +22,42 @@ MapScript.loadModule("JSONEdit", {
|
||||
if (!self.menu) {
|
||||
self.intl = Intl.getNamespace("jsonEdit.main");
|
||||
self.saveMenu = [{
|
||||
text : self.intl.edit,
|
||||
description : self.intl.edit_desc,
|
||||
onclick : function(v, tag) {
|
||||
if (!JSONEdit.show(tag.par)) {
|
||||
Common.toast(self.intl.nowhereEditable);
|
||||
return true;
|
||||
}
|
||||
text: self.intl.edit,
|
||||
description: self.intl.edit_desc,
|
||||
hidden(tag) {
|
||||
return tag.data === null;
|
||||
},
|
||||
onclick(v, tag) {
|
||||
tag.editCallback();
|
||||
}
|
||||
}, {
|
||||
text : self.intl.copy,
|
||||
description : self.intl.copy_desc,
|
||||
onclick : function(v, tag) {
|
||||
text: self.intl.replace,
|
||||
description: self.intl.replace_desc,
|
||||
hidden(tag) {
|
||||
return tag.data !== null;
|
||||
},
|
||||
onclick(v, tag) {
|
||||
JSONEdit.create((data) => {
|
||||
tag.replaceCallback(data);
|
||||
});
|
||||
}
|
||||
}, {
|
||||
text: self.intl.copy,
|
||||
description: self.intl.copy_desc,
|
||||
onclick(v, tag) {
|
||||
Common.setClipboardText(JSON.stringify(tag.data, null, "\t"));
|
||||
Common.toast(self.intl.copy_success);
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
text : self.intl.save,
|
||||
description : self.intl.save_desc,
|
||||
hidden : function(tag) {
|
||||
return !tag.path;
|
||||
text: self.intl.save,
|
||||
description: self.intl.save_desc,
|
||||
hidden(tag) {
|
||||
return !tag.uri;
|
||||
},
|
||||
onclick : function(v, tag) {
|
||||
onclick(v, tag) {
|
||||
try {
|
||||
MapScript.saveJSON(tag.path, tag.data);
|
||||
ExternalStorage.writeFileContent(tag.uri, JSON.stringify(tag.data));
|
||||
Common.toast(self.intl.save_success);
|
||||
} catch(e) {
|
||||
Common.toast(self.intl.resolve("save_failed", e));
|
||||
@ -53,15 +65,17 @@ MapScript.loadModule("JSONEdit", {
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
text : self.intl.saveAs,
|
||||
description : self.intl.saveAs_desc,
|
||||
onclick : function(v, tag) {
|
||||
Common.showFileDialog({
|
||||
type : 1,
|
||||
callback : function(f) {
|
||||
text: self.intl.saveAs,
|
||||
description: self.intl.saveAs_desc,
|
||||
onclick(v, tag) {
|
||||
ExternalStorage.showSaveActions({
|
||||
mimeType: "application/json",
|
||||
hint: "untitled.json",
|
||||
callback(uri) {
|
||||
try {
|
||||
MapScript.saveJSON(tag.path = f.result.getAbsolutePath(), tag.data);
|
||||
Common.toast(self.intl.saveAs_success);
|
||||
ExternalStorage.writeFileContent(uri, JSON.stringify(tag.data));
|
||||
tag.uri = uri;
|
||||
Common.toast(self.intl.save_success);
|
||||
} catch(e) {
|
||||
Common.toast(self.intl.resolve("save_failed", e));
|
||||
}
|
||||
@ -70,46 +84,29 @@ MapScript.loadModule("JSONEdit", {
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
text : Common.intl.close,
|
||||
onclick : function(v, tag) {}
|
||||
text: Common.intl.close,
|
||||
onclick(v, tag) {}
|
||||
}];
|
||||
self.menu = [{
|
||||
text : self.intl.new,
|
||||
description : self.intl.new_desc,
|
||||
onclick : function() {
|
||||
JSONEdit.create(function cb(o) {
|
||||
Common.showOperateDialog(self.saveMenu, {
|
||||
data : o,
|
||||
path : null,
|
||||
par : {
|
||||
source : o,
|
||||
update : function() {
|
||||
cb(this.source);
|
||||
}
|
||||
}
|
||||
});
|
||||
self.openMenu = [{
|
||||
text: self.intl.new,
|
||||
description: self.intl.new_desc,
|
||||
onclick(v, tag) {
|
||||
JSONEdit.create((data) => {
|
||||
tag.saveCallback(null, data);
|
||||
});
|
||||
}
|
||||
}, {
|
||||
text : self.intl.open,
|
||||
description : self.intl.open_desc,
|
||||
onclick : function() {
|
||||
Common.showFileDialog({
|
||||
type : 0,
|
||||
callback : function(f) {
|
||||
var o;
|
||||
text: self.intl.open,
|
||||
description: self.intl.open_desc,
|
||||
onclick(v, tag) {
|
||||
ExternalStorage.showOpenActions({
|
||||
mimeType: "application/json",
|
||||
callback(uri) {
|
||||
let data;
|
||||
try {
|
||||
o = {
|
||||
data : MapScript.readJSON(f.result.getAbsolutePath(), null),
|
||||
path : f.result.getAbsolutePath()
|
||||
}
|
||||
if (!JSONEdit.show(o.par = {
|
||||
source : o.data,
|
||||
update : function() {
|
||||
o.data = this.source;
|
||||
Common.showOperateDialog(self.saveMenu, o);
|
||||
}
|
||||
})) Common.showOperateDialog(self.saveMenu, o);
|
||||
data = JSON.parse(ExternalStorage.readFileContent(uri, "UTF-8"));
|
||||
ExternalStorage.tryTakeUriPermission(uri);
|
||||
tag.openCallback(uri, data, false);
|
||||
} catch(e) {
|
||||
Common.toast(JSONEdit.intl.resolve("invaildJSON", e));
|
||||
}
|
||||
@ -118,10 +115,34 @@ MapScript.loadModule("JSONEdit", {
|
||||
}
|
||||
}, {
|
||||
text : Common.intl.close,
|
||||
onclick : function(v, tag) {}
|
||||
onclick(v, tag) {}
|
||||
}];
|
||||
}
|
||||
Common.showOperateDialog(self.menu);
|
||||
Common.showOperateDialog(self.openMenu, {
|
||||
openCallback(uri, data, needEditablePrompt) {
|
||||
const self = this;
|
||||
Log.d("open")
|
||||
if (!JSONEdit.show({
|
||||
source: data,
|
||||
update() {
|
||||
Log.d("update")
|
||||
self.saveCallback(uri, data);
|
||||
}
|
||||
})) {
|
||||
if (needEditablePrompt) {
|
||||
Common.toast(self.intl.nowhereEditable);
|
||||
}
|
||||
self.saveCallback(uri, data);
|
||||
}
|
||||
},
|
||||
saveCallback(uri, data) {
|
||||
Common.showOperateDialog(self.saveMenu, {
|
||||
uri, data,
|
||||
editCallback: () => this.openCallback(uri, data, true),
|
||||
replaceCallback: (data) => this.openCallback(uri, data),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
show : function(o) {
|
||||
var i, name, data;
|
||||
@ -438,16 +459,21 @@ MapScript.loadModule("JSONEdit", {
|
||||
holder.e = e;
|
||||
}
|
||||
self.getDesp = function(obj, propertyName) {
|
||||
var e;
|
||||
var e, result;
|
||||
try {
|
||||
e = obj[propertyName];
|
||||
if (Array.isArray(e)) {
|
||||
return e.length ? JSONEdit.intl.resolve("arrayDesc", e[0], e.length) : JSONEdit.intl.emptyArrayDesc;
|
||||
} else if (e instanceof Object && typeof e !== "function" && !(e instanceof java.lang.CharSequence)) {
|
||||
return JSONEdit.intl.resolve("objectDesc", self.itemAccessor.getCount(e));
|
||||
} else if (e === null) {
|
||||
return JSONEdit.intl.nullDesc;
|
||||
} else return String(e);
|
||||
new java.lang.Runnable(function() {
|
||||
e = obj[propertyName];
|
||||
if (Array.isArray(e)) {
|
||||
result = e.length ? JSONEdit.intl.resolve("arrayDesc", e[0], e.length) : JSONEdit.intl.emptyArrayDesc;
|
||||
} else if (e instanceof Object && typeof e !== "function" && !(e instanceof java.lang.CharSequence)) {
|
||||
result = JSONEdit.intl.resolve("objectDesc", self.itemAccessor.getCount(e));
|
||||
} else if (e === null) {
|
||||
result = JSONEdit.intl.nullDesc;
|
||||
} else {
|
||||
result = String(e);
|
||||
}
|
||||
}).run();
|
||||
return result;
|
||||
} catch(er) {
|
||||
Log.e(er);
|
||||
return String(er);
|
||||
|
@ -90,6 +90,20 @@ MapScript.loadModule("NetworkUtils", {
|
||||
is.close();
|
||||
return android.util.Base64.encodeToString(digest.digest(), android.util.Base64.NO_WRAP) == sha1;
|
||||
},
|
||||
downloadToUri : function(url, uri) {
|
||||
var url = new java.net.URL(url);
|
||||
var conn = url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setUseCaches(false);
|
||||
conn.setRequestMethod("GET");
|
||||
conn.connect();
|
||||
var is, os;
|
||||
is = conn.getInputStream();
|
||||
os = ExternalStorage.openOutputStream(uri);
|
||||
ExternalStorage.pipe(is, os, 8192);
|
||||
os.close();
|
||||
is.close();
|
||||
},
|
||||
verifyFile : function(path, sha1) {
|
||||
const BUFFER_SIZE = 8192;
|
||||
var is, digest, buf, hr;
|
||||
|
1195
modules/utils/ExternalStorage.js
Normal file
1195
modules/utils/ExternalStorage.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user