6.6.2 - Alpha4 - 修复 Rhino 引擎升级后打包应用无法使用正则表达式及 XML 语法的问题

This commit is contained in:
SuperMonster003
2025-03-11 15:25:08 +08:00
parent fc6c912dec
commit d355964591
30 changed files with 234 additions and 178 deletions

View File

@@ -9,8 +9,7 @@ import android.os.Build
import android.util.Log
import com.mcal.apksigner.ApkSigner
import com.reandroid.arsc.chunk.TableBlock
import org.apache.commons.io.FileUtils.copyFile
import org.apache.commons.io.FileUtils.copyInputStreamToFile
import org.apache.commons.io.FileUtils
import org.autojs.autojs.apkbuilder.keystore.AESUtils
import org.autojs.autojs.app.GlobalAppContext
import org.autojs.autojs.engine.encryption.AdvancedEncryptionStandard
@@ -308,7 +307,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
val defaultKeyStoreFile = File(buildPath, "default_key_store.bks")
val tmpOutputApk = File(buildPath, "temp.apk")
copyInputStreamToFile(GlobalAppContext.get().assets.open("default_key_store.bks"), defaultKeyStoreFile)
FileUtils.copyInputStreamToFile(GlobalAppContext.get().assets.open("default_key_store.bks"), defaultKeyStoreFile)
val signer = ApkSigner(outApkFile, tmpOutputApk).apply {
useDefaultSignatureVersion = false
@@ -336,7 +335,7 @@ open class ApkBuilder(apkInputStream: InputStream?, private val outApkFile: File
}
try {
copyFile(tmpOutputApk, outApkFile)
FileUtils.copyFile(tmpOutputApk, outApkFile)
} catch (e: java.lang.Exception) {
throw java.lang.RuntimeException(e)
}

View File

@@ -48,7 +48,6 @@ public class TinySign {
}
}
}
}
private static void doFile(String name, File f, ZipOutputStream zos, DigestOutputStream dos, Manifest m) throws IOException {
@@ -119,6 +118,7 @@ public class TinySign {
Manifest sf = generateSF(manifest);
byte[] sign = writeSF(zos, sf, sha1Manifest);
writeRSA(zos, sign);
writeServices(dir, zos);
zos.close();
}
@@ -142,6 +142,32 @@ public class TinySign {
zos.closeEntry();
}
// @Hint by SuperMonster003 on Mar 11, 2025.
// ! Rhino 1.8.1-SNAPSHOT requires dynamically loading services during initialization (e.g., org.mozilla.javascript.RegExpLoader).
// ! When loading these services, it needs to read the service provider configuration files located in the META-INF/services/ directory.
// ! During signing, these configuration files need to be written into the ZipOutputStream.
// ! zh-CN:
// ! Rhino 1.8.1-SNAPSHOT 在初始化时需要动态加载服务 (如 org.mozilla.javascript.RegExpLoader),
// ! 这些服务加载时, 需要读取位于 META-INF/services/ 目录下的服务提供者配置文件 (Service Provider Configuration Files).
// ! 签名时, 需要将这些配置文件写入 ZipOutputStream 中.
private static void writeServices(File dir, ZipOutputStream zos) throws IOException {
File servicesDir = new File(dir, "META-INF/services");
if (!servicesDir.isDirectory()) {
return;
}
File[] files = servicesDir.listFiles(File::isFile);
if (files == null) {
return;
}
for (File file : files) {
try (FileInputStream fis = new FileInputStream(file)) {
zos.putNextEntry(new ZipEntry("META-INF/services/" + file.getName()));
StreamUtils.write(fis, zos);
zos.closeEntry();
}
}
}
private static byte[] writeSF(ZipOutputStream zos, Manifest sf, String sha1Manifest) throws Exception {
Signature signature = instanceSignature();
zos.putNextEntry(new ZipEntry("META-INF/CERT.SF"));

View File

@@ -39,6 +39,7 @@ object ArrayExtensions {
else -> o.hashCode()
}
}
fun <T> Array<T>.unshiftWith(thisObj: Any?): Array<Any?> {
return Array(this.size + 1) { if (it == 0) thisObj else this[it - 1] }
}
@@ -50,15 +51,17 @@ object ArrayExtensions {
}
fun Iterable<*>.toNativeArray(): NativeArray {
return withRhinoContext { context, standardObjects ->
context.newArray(standardObjects, this.map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
}!!
return withRhinoContext { cx ->
val standardObjects = cx.initStandardObjects()
cx.newArray(standardObjects, this.map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
}
}
fun Array<*>.toNativeArray(): NativeArray {
return withRhinoContext { context, standardObjects ->
context.newArray(standardObjects, this.toList().map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
}!!
return withRhinoContext { cx ->
val standardObjects = cx.initStandardObjects()
cx.newArray(standardObjects, this.toList().map { Context.javaToJS(it, standardObjects) }.toTypedArray()) as NativeArray
}
}
fun <K, V> Map<K, V>.toNativeObject(): NativeObject = newNativeObject().also { o ->

View File

@@ -78,7 +78,7 @@ open class AugmentableProxy(private val scriptRuntime: ScriptRuntime) : Augmenta
// ! but defined in a certain object in its prototype chain.
// ! zh-CN: 表示 `key` 未定义在 `augmented` 上, 但定义在其原型链对象上.
!augmented.has(key) && ScriptableObject.hasProperty(augmented, key) -> {
withRhinoContext { ctx -> BoundFunction(ctx, augmented, value, augmented, arrayOf()) }
withRhinoContext { cx -> BoundFunction(cx, augmented, value, augmented, arrayOf()) }
}
else -> value
}

View File

@@ -667,12 +667,12 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
return object : AccessibilityService.GestureResultCallback() {
override fun onCompleted(gestureDescription: GestureDescription) {
when (callback) {
is BaseFunction -> withRhinoContext { context ->
callback.call(context, ImporterTopLevel(context), callback, arrayOf(true))
is BaseFunction -> withRhinoContext { cx ->
callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(true))
}
is NativeObject -> callback.prop("onCompleted")?.let {
if (it is BaseFunction) withRhinoContext { context ->
it.call(context, ImporterTopLevel(context), callback, arrayOf(gestureDescription))
if (it is BaseFunction) withRhinoContext { cx ->
it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription))
}
}
}
@@ -680,12 +680,12 @@ class Automator(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override fun onCancelled(gestureDescription: GestureDescription) {
when (callback) {
is BaseFunction -> withRhinoContext { context ->
callback.call(context, ImporterTopLevel(context), callback, arrayOf(false))
is BaseFunction -> withRhinoContext { cx ->
callback.call(cx, ImporterTopLevel(cx), callback, arrayOf(false))
}
is NativeObject -> callback.prop("onCancelled")?.let {
if (it is BaseFunction) withRhinoContext { context ->
it.call(context, ImporterTopLevel(context), callback, arrayOf(gestureDescription))
if (it is BaseFunction) withRhinoContext { cx ->
it.call(cx, ImporterTopLevel(cx), callback, arrayOf(gestureDescription))
}
}
}

View File

@@ -45,8 +45,8 @@ class RootAutomatorNativeObject(scriptRuntime: ScriptRuntime, waitForReady: Any?
// # 'touchDown', 'touchUp', 'touchMove', 'getDefaultId', 'setDefaultId', 'exit',
// # ]
return when (val o = mRootAutomatorObject.prop(name)) {
is BaseFunction -> withRhinoContext { ctx ->
BoundFunction(ctx, mRootAutomatorObject, o, mRootAutomatorObject, arrayOf())
is BaseFunction -> withRhinoContext { cx ->
BoundFunction(cx, mRootAutomatorObject, o, mRootAutomatorObject, arrayOf())
}
else -> super.get(name, start)
}

View File

@@ -129,11 +129,11 @@ class Console(scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRuntime) {
::launch.name to "launchConsole",
)
private fun getStackTrace() = withRhinoContext { context ->
private fun getStackTrace() = withRhinoContext { cx ->
newNativeObject().also { o ->
val globalErrorObject = mTopLevelScope.prop(NativeError.ERROR_TAG) as ScriptableObject
NativeError.js_captureStackTrace(
context,
cx,
mCaptureStack,
globalErrorObject,
arrayOf(o, mCaptureStack),

View File

@@ -61,7 +61,7 @@ object Species : Augmentable(), Invokable {
when {
o == null -> "Null"
Undefined.isUndefined(o) -> "Undefined"
else -> when (val obj = withRhinoContext { _, standardObjects -> Context.javaToJS(o, standardObjects) }) {
else -> when (val obj = withRhinoContext { cx -> Context.javaToJS(o, cx.initStandardObjects()) }) {
is Boolean -> "Boolean"
is String -> "String"
is BigInteger -> "BigInt"

View File

@@ -138,15 +138,15 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
override fun onResponse(call: Call, response: Response) {
val wrappedResponse = ResponseWrapper(response).wrap()
cont?.resume(wrappedResponse)
if (callback is BaseFunction) withRhinoContext { context ->
callback.call(context, callback, callback, arrayOf(wrappedResponse, null))
if (callback is BaseFunction) withRhinoContext { cx ->
callback.call(cx, callback, callback, arrayOf(wrappedResponse, null))
}
}
override fun onFailure(call: Call, e: IOException) {
cont?.resumeError(e)
if (callback is BaseFunction) withRhinoContext { context ->
callback.call(context, callback, callback, arrayOf(null, e))
if (callback is BaseFunction) withRhinoContext { cx ->
callback.call(cx, callback, callback, arrayOf(null, e))
}
}
})
@@ -403,8 +403,8 @@ class Http(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
}
override fun writeTo(sink: BufferedSink) {
withRhinoContext { context ->
body.call(context, body, body, arrayOf(sink))
withRhinoContext { cx ->
body.call(cx, body, body, arrayOf(sink))
}
}
}

View File

@@ -161,13 +161,13 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun distinctByRhino(it: Array<Any?>): NativeArray = withRhinoContext { context ->
fun distinctByRhino(it: Array<Any?>): NativeArray = withRhinoContext { cx ->
val (arr, selector) = it
coerceArray(arr).distinctBy { ele ->
require(arr is NativeArray)
coerceFunction(selector).call(context, arr, arr, arrayOf(ele))
coerceFunction(selector).call(cx, arr, arr, arrayOf(ele))
}.toNativeArray()
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -206,18 +206,18 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { context ->
fun sortByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument arr for Arrayx.sortBy must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument selector for Arrayx.sortBy must be a JavaScript Function" }
when {
arr.length < 2 -> arr
else -> {
// In-place sorting (zh-CN: 原地排序)
NativeArray.js_sort(context, arr, arr, arrayOf(toCompareFunctionAsc(selector)))
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionAsc(selector)))
arr
}
}
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -228,18 +228,18 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { context ->
fun sortByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument arr for Arrayx.sortByDescending must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument selector for Arrayx.sortByDescending must be a JavaScript Function" }
when {
arr.length < 2 -> arr
else -> {
// In-place sorting (zh-CN: 原地排序)
NativeArray.js_sort(context, arr, arr, arrayOf(toCompareFunctionDesc(selector)))
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionDesc(selector)))
arr
}
}
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -249,11 +249,11 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortDescendingRhino(arr: Any?): NativeArray = withRhinoContext { context ->
fun sortDescendingRhino(arr: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument arr for Arrayx.sortDescending must be a JavaScript Array" }
NativeArray.js_sort(context, arr, arr, arrayOf(toCompareFunctionDesc()))
NativeArray.js_sort(cx, arr, arr, arrayOf(toCompareFunctionDesc()))
arr
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -263,12 +263,12 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortedRhino(it: Any?): NativeArray = withRhinoContext { context ->
fun sortedRhino(it: Any?): NativeArray = withRhinoContext { cx ->
require(it is NativeArray) { "Argument arr for Arrayx.sorted must be a JavaScript Array" }
val copied = it.slice(it.indices).toNativeArray()
NativeArray.js_sort(context, it, copied, arrayOf(toCompareFunctionAsc()))
NativeArray.js_sort(cx, it, copied, arrayOf(toCompareFunctionAsc()))
copied
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -278,12 +278,12 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortedDescendingRhino(it: Any?): NativeArray = withRhinoContext { context ->
fun sortedDescendingRhino(it: Any?): NativeArray = withRhinoContext { cx ->
require(it is NativeArray) { "Argument arr for Arrayx.sortedDescending must be a JavaScript Array" }
val copied = it.slice(it.indices).toNativeArray()
NativeArray.js_sort(context, it, copied, arrayOf(toCompareFunctionDesc()))
NativeArray.js_sort(cx, it, copied, arrayOf(toCompareFunctionDesc()))
copied
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -294,18 +294,18 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortedByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { context ->
fun sortedByRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument arr for Arrayx.sortedBy must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument selector for Arrayx.sortedBy must be a JavaScript Function" }
val copied = arr.slice(arr.indices).toNativeArray()
when {
arr.length < 2 -> copied
else -> {
NativeArray.js_sort(context, arr, copied, arrayOf(toCompareFunctionAsc(selector)))
NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionAsc(selector)))
copied
}
}
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -316,18 +316,18 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun sortedByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { context ->
fun sortedByDescendingRhino(arr: Any?, selector: Any?): NativeArray = withRhinoContext { cx ->
require(arr is NativeArray) { "Argument arr for Arrayx.sortedByDescending must be a JavaScript Array" }
require(selector is BaseFunction) { "Argument selector for Arrayx.sortedByDescending must be a JavaScript Function" }
val copied = arr.slice(arr.indices).toNativeArray()
when {
arr.length < 2 -> copied
else -> {
NativeArray.js_sort(context, arr, copied, arrayOf(toCompareFunctionDesc(selector)))
NativeArray.js_sort(cx, arr, copied, arrayOf(toCompareFunctionDesc(selector)))
copied
}
}
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
@@ -337,11 +337,11 @@ class Arrayx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti
@JvmStatic
@RhinoFunctionBody
fun shuffleRhino(it: Any?): NativeArray = withRhinoContext { context ->
fun shuffleRhino(it: Any?): NativeArray = withRhinoContext { cx ->
require(it is NativeArray) { "Argument arr for Arrayx.shuffle must be a JavaScript Array" }
NativeArray.js_sort(context, it, it, arrayOf(toCompareFunctionRandom()))
NativeArray.js_sort(cx, it, it, arrayOf(toCompareFunctionRandom()))
it
}!!
}
private fun toCompareFunctionAsc(selector: BaseFunction) = object : BaseFunction() {
override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable?, args: Array<out Any>): Int {

View File

@@ -6,20 +6,19 @@ import org.autojs.autojs.core.automator.UiObject
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.extension.AnyExtensions.jsUnwrapped
import org.autojs.autojs.extension.FlexibleArray
import org.autojs.autojs.extension.ScriptableExtensions.hasProp
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.hasProp
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.runtime.exception.ShouldNeverHappenException
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils.NOT_CONSTRUCTABLE
import org.autojs.autojs.util.RhinoUtils.coerceBoolean
import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.newBaseFunction
import org.autojs.autojs.util.RhinoUtils.withRhinoContext
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.ConsString
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
import java.lang.reflect.Method
@@ -57,7 +56,7 @@ class Selector(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
// @Hint by SuperMonster003 on Jul 25, 2024.
// ! For scope binding.
// ! zh-CN: 用于绑定作用域.
withRhinoContext { context ->
withRhinoContext { cx ->
global.defineProp(methodName, newBaseFunction(null, { argList ->
val methodKey = coerceString(argList[0])
newBaseFunction(methodKey, { arguments ->
@@ -101,7 +100,7 @@ class Selector(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
throw e
}
}, NOT_CONSTRUCTABLE)
}, NOT_CONSTRUCTABLE).call(context, global, global, arrayOf(methodName)))
}, NOT_CONSTRUCTABLE).call(cx, global, global, arrayOf(methodName)))
}
}
}

View File

@@ -46,6 +46,7 @@ import org.autojs.autojs.util.RhinoUtils.newBaseFunction
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.autojs.autojs.util.RhinoUtils.undefined
import org.autojs.autojs.util.RhinoUtils.withRhinoContext
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context
@@ -187,8 +188,8 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
val widgets = scriptRuntime.ui.widgets
if (widgets.contains(viewName)) {
val ctor = widgets.prop(viewName) as NativeFunction
val widget = withRhinoContext { ctx ->
ctor.construct(ctx, scriptRuntime.topLevelScope, arrayOf())
val widget = withRhinoContext { cx ->
ctor.construct(cx, scriptRuntime.topLevelScope, arrayOf())
} as ScriptableObject
val f = widget.prop("renderInternal") as BaseFunction
return __inflateRhinoRuntime__(scriptRuntime, scriptRuntime.ui.layoutInflater.newInflateContext().also { ctx ->
@@ -509,9 +510,7 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
fun statusBarColor(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { color ->
ensureActivity(scriptRuntime) { activity ->
runRhinoRuntime(scriptRuntime, newBaseFunction("action", {
Colors.toIntRhino(color).also {
activity.window.statusBarColor = it
}
Colors.toIntRhino(color).also { ViewUtils.setStatusBarBackgroundColor(activity, it) }
}, NOT_CONSTRUCTABLE))
}
UNDEFINED
@@ -734,8 +733,8 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
}
}
}, NOT_CONSTRUCTABLE)
withRhinoContext { context ->
arrayObserveFunc.call(context, global, globalArray, arrayOf(dataSource, handlerFunc))
withRhinoContext { cx ->
arrayObserveFunc.call(cx, global, globalArray, arrayOf(dataSource, handlerFunc))
}
}
})
@@ -744,10 +743,10 @@ class UI(private val scriptRuntime: ScriptRuntime) : AugmentableProxy(scriptRunt
private fun wrapUiAction(scriptRuntime: ScriptRuntime, action: BaseFunction) = Runnable {
when {
!getActivity(scriptRuntime).isJsNullish() -> callFunction(scriptRuntime, action, scriptRuntime.topLevelScope, arrayOf())
else -> withRhinoContext { context ->
else -> withRhinoContext { cx ->
val scope = scriptRuntime.topLevelScope
val func = scope.prop("__exitIfError__") as BaseFunction
func.call(context, scope, scope, arrayOf(newBaseFunction("action", {
func.call(cx, scope, scope, arrayOf(newBaseFunction("action", {
callFunction(scriptRuntime, action, arrayOf())
}, NOT_CONSTRUCTABLE)))
}

View File

@@ -274,13 +274,13 @@ object Util : Augmentable() {
val bPrototype: Scriptable? = when {
niceB == null -> js_object_create(null)
else -> withRhinoContext { context ->
else -> withRhinoContext { cx ->
val tmp = object : BaseFunction() {
override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable?, args: Array<out Any?>) = newNativeObject().also {
it.defineProperty("constructor", d, READONLY or DONTENUM or PERMANENT)
}
}
tmp.construct(context, ImporterTopLevel(context), arrayOf()).also { instance ->
tmp.construct(cx, ImporterTopLevel(cx), arrayOf()).also { instance ->
// FIXME by SuperMonster003 on Jul 13, 2024.
// ! I'm not sure if there is a better way
// ! to implement JavaScript snippet `tmp.prototype = b.prototype;`,
@@ -739,7 +739,7 @@ object Util : Augmentable() {
private fun getClassInternal(o: Any): Scriptable = when (o) {
is Class<*> -> o
else -> o.javaClass
}.let { cls -> withRhinoContext { cx -> cx.wrapFactory.wrapJavaClass(cx, ImporterTopLevel(cx), cls) }!! }
}.let { cls -> withRhinoContext { cx -> cx.wrapFactory.wrapJavaClass(cx, ImporterTopLevel(cx), cls) } }
internal class RegularFunction(private val func: BaseFunction) : BaseFunction() {

View File

@@ -35,7 +35,7 @@ class Web(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic
@RhinoFunctionBody
fun newInjectableWebViewRhinoWithRuntime(scriptRuntime: ScriptRuntime, vararg args: Any?): InjectableWebView = withRhinoContext { jsCtx ->
fun newInjectableWebViewRhinoWithRuntime(scriptRuntime: ScriptRuntime, vararg args: Any?): InjectableWebView = withRhinoContext { cx ->
when (args.size) {
2 -> {
val (androidContext, url) = args
@@ -44,7 +44,7 @@ class Web(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
else -> Context.toString(url)
}
val contextForWebView = androidContext.jsUnwrapped() as? AndroidContext ?: globalContext
InjectableWebView(contextForWebView, jsCtx, scriptRuntime.topLevelScope, niceUrl)
InjectableWebView(contextForWebView, cx, scriptRuntime.topLevelScope, niceUrl)
}
1 -> when {
args[0] is String -> {
@@ -55,12 +55,12 @@ class Web(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
0 -> newInjectableWebViewRhinoWithRuntime(scriptRuntime, scriptRuntime.topLevelScope.prop("activity"))
else -> throw WrappedIllegalArgumentException("Invalid arguments length ${args.size} for web.newInjectableWebView")
}
}!!
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun newInjectableWebClient(scriptRuntime: ScriptRuntime, args: Array<out Any?>): InjectableWebClient = ensureArgumentsIsEmpty(args) {
withRhinoContext { context -> InjectableWebClient(context, scriptRuntime.topLevelScope) }!!
withRhinoContext { cx -> InjectableWebClient(cx, scriptRuntime.topLevelScope) }
}
@JvmStatic

View File

@@ -43,6 +43,7 @@ public class AppsIconSelectActivity extends BaseActivity {
private RecyclerView mAppsRecyclerView;
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
public static final String EXTRA_USE_DEFAULT_ICON = "use_default_icon";
private PackageManager mPackageManager;
private final List<AppItem> mAppList = new ArrayList<>();
@@ -101,8 +102,13 @@ public class AppsIconSelectActivity extends BaseActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT)
.setType(Mime.IMAGE_WILDCARD), 11234);
if (item.getItemId() == R.id.action_select_image) {
startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT)
.setType(Mime.IMAGE_WILDCARD), 11234);
} else if (item.getItemId() == R.id.action_use_default_icon) {
setResult(RESULT_OK, new Intent().putExtra(EXTRA_USE_DEFAULT_ICON, true));
finish();
}
return true;
}
@@ -116,6 +122,10 @@ public class AppsIconSelectActivity extends BaseActivity {
}
public static Observable<Drawable> getDrawableFromIntent(Context context, Intent data) {
boolean useDefaultIcon = data.getBooleanExtra(EXTRA_USE_DEFAULT_ICON, false);
if (useDefaultIcon) {
return Observable.fromCallable(() -> context.getResources().getDrawable(R.mipmap.ic_launcher, context.getTheme()));
}
String packageName = data.getStringExtra(EXTRA_PACKAGE_NAME);
if (packageName != null) {
return Observable.fromCallable(() -> context.getPackageManager().getApplicationIcon(packageName));

View File

@@ -30,7 +30,6 @@ import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeDate
import org.mozilla.javascript.NativeJSON
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.RegExpLoader
import org.mozilla.javascript.ScriptRuntime.emptyArgs
import org.mozilla.javascript.ScriptRuntime.setBuiltinProtoAndParent
import org.mozilla.javascript.ScriptRuntime.toObject
@@ -97,8 +96,8 @@ object RhinoUtils {
}
@JvmStatic
fun callGlobalFunction(scriptRuntime: ScriptRuntime?, name: String, paramsToFunction: Array<Any?>) = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
fun callGlobalFunction(scriptRuntime: ScriptRuntime?, name: String, paramsToFunction: Array<Any?>) = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
callFunction(scriptRuntime, topLevel, name, paramsToFunction)
}
@@ -159,7 +158,7 @@ object RhinoUtils {
@Throws(NoSuchMethodException::class, InvocationTargetException::class, IllegalAccessException::class)
fun callFunction(scriptRuntime: ScriptRuntime?, func: BaseFunction, scope: Scriptable?, thisObj: Scriptable?, args: Array<Any?>): Any? = withRhinoContext { cx ->
try {
val niceScope = scope ?: ImporterTopLevel(cx)
val niceScope = scope ?: cx.initStandardObjects()
when {
RhinoScriptRuntime.hasTopCall(cx) -> func.call(cx, niceScope, thisObj, args)
else -> RhinoScriptRuntime.doTopCall(func, cx, niceScope, thisObj, args, false)
@@ -182,7 +181,7 @@ object RhinoUtils {
@JvmStatic
fun constructFunction(ctor: BaseFunction, scope: TopLevelScope, args: Array<Any?>): Scriptable = withRhinoContext { cx ->
ctor.construct(cx, scope, args)
}!!
}
@JvmStatic
fun newBaseFunction(
@@ -262,9 +261,9 @@ object RhinoUtils {
}
@JvmStatic
fun wrap(o: Any?): Any = withRhinoContext { context ->
context.wrapFactory.wrap(context, ImporterTopLevel(context), o, o?.let { it::class.java })
}!!
fun wrap(o: Any?): Any = withRhinoContext { cx ->
cx.wrapFactory.wrap(cx, ImporterTopLevel(cx), o, o?.let { it::class.java })
}
@JvmStatic
fun unwrap(o: Any?): Any? = when (o) {
@@ -370,8 +369,8 @@ object RhinoUtils {
fun toFunctionName(cls: KClass<*>, func: KFunction<*>, paramName: String): String = "${cls.simpleName}.${func.name}($paramName)"
@JvmStatic
fun runJavaScript(code: String): Any? = withRhinoContext { context, standardObjects ->
context.evaluateString(standardObjects, code, null, 1, null)
fun runJavaScript(code: String): Any? = withRhinoContext { cx ->
cx.evaluateString(standardObjects, code, null, 1, null)
}
@JvmStatic
@@ -492,28 +491,28 @@ object RhinoUtils {
@JvmStatic
@JvmOverloads
fun callPrototypeFunction(builtins: TopLevel.Builtins, funcName: String, thisObj: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { context ->
callPrototypeFunction(builtins, funcName, thisObj, ImporterTopLevel(context), args)
fun callPrototypeFunction(builtins: TopLevel.Builtins, funcName: String, thisObj: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { cx ->
callPrototypeFunction(builtins, funcName, thisObj, ImporterTopLevel(cx), args)
}
@JvmStatic
@JvmOverloads
fun callPrototypeFunction(className: String, funcName: String, thisObj: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { context ->
callPrototypeFunction(className, funcName, thisObj, ImporterTopLevel(context), args)
fun callPrototypeFunction(className: String, funcName: String, thisObj: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { cx ->
callPrototypeFunction(className, funcName, thisObj, ImporterTopLevel(cx), args)
}
@JvmStatic
@JvmOverloads
fun callPrototypeFunction(builtins: TopLevel.Builtins, funcName: String, thisObj: Scriptable, scope: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { context ->
fun callPrototypeFunction(builtins: TopLevel.Builtins, funcName: String, thisObj: Scriptable, scope: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { cx ->
val prototypeFunction = getPrototypeFunction(scope, builtins, funcName)
prototypeFunction.call(context, scope, thisObj, args)
prototypeFunction.call(cx, scope, thisObj, args)
}
@JvmStatic
@JvmOverloads
fun callPrototypeFunction(className: String, funcName: String, thisObj: Scriptable, scope: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { context ->
fun callPrototypeFunction(className: String, funcName: String, thisObj: Scriptable, scope: Scriptable, args: Array<Any?> = arrayOf()): Any? = withRhinoContext { cx ->
val prototypeFunction = getPrototypeFunction(scope, className, funcName)
prototypeFunction.call(context, scope, thisObj, args)
prototypeFunction.call(cx, scope, thisObj, args)
}
@JvmStatic
@@ -551,48 +550,48 @@ object RhinoUtils {
@Suppress("UnnecessaryVariable")
@JvmStatic
fun js_object_assign(tar: Scriptable?, src: Scriptable?): Scriptable = withRhinoContext { context ->
val topeLevelScope = ImporterTopLevel(context)
fun js_object_assign(tar: Scriptable?, src: Scriptable?): Scriptable = withRhinoContext { cx ->
val topeLevelScope = ImporterTopLevel(cx)
val targetObj = when (tar != null) {
true -> toObject(context, topeLevelScope, tar)
else -> toObject(context, topeLevelScope, UNDEFINED)
true -> toObject(cx, topeLevelScope, tar)
else -> toObject(cx, topeLevelScope, UNDEFINED)
}
if (src.isJsNullish()) {
return@withRhinoContext targetObj
}
val sourceObj = toObject(context, topeLevelScope, src)
val sourceObj = toObject(cx, topeLevelScope, src)
for (key in sourceObj.ids) {
when (key) {
is Int -> {
val intId = key
if (sourceObj.has(intId, sourceObj)) {
AbstractEcmaObjectOperations.put(context, targetObj, intId, sourceObj[intId, sourceObj], true)
AbstractEcmaObjectOperations.put(cx, targetObj, intId, sourceObj[intId, sourceObj], true)
}
}
else -> {
val stringId = toString(key)
if (sourceObj.has(stringId, sourceObj)) {
AbstractEcmaObjectOperations.put(context, targetObj, stringId, sourceObj.prop(stringId), true)
AbstractEcmaObjectOperations.put(cx, targetObj, stringId, sourceObj.prop(stringId), true)
}
}
}
}
return@withRhinoContext targetObj
}!!
}
@JvmStatic
fun js_object_keys(arg: ScriptableObject): NativeArray = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
val obj = toObject(context, topLevel, arg)
fun js_object_keys(arg: ScriptableObject): NativeArray = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
val obj = toObject(cx, topLevel, arg)
val ids = obj.ids
ids.indices.forEach { i -> ids[i] = toString(ids[i]) }
context.newArray(topLevel, ids) as NativeArray
}!!
cx.newArray(topLevel, ids) as NativeArray
}
@JvmStatic
fun js_object_values(arg: ScriptableObject): NativeArray = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
val obj = toObject(context, topLevel, arg)
fun js_object_values(arg: ScriptableObject): NativeArray = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
val obj = toObject(cx, topLevel, arg)
var ids = obj.ids
var j = 0
for (i in ids.indices) {
@@ -612,13 +611,13 @@ object RhinoUtils {
if (j != ids.size) {
ids = ids.copyOf(j)
}
context.newArray(topLevel, ids) as NativeArray
}!!
cx.newArray(topLevel, ids) as NativeArray
}
@JvmStatic
@JvmOverloads
fun js_object_create(o: Scriptable? = null, properties: ScriptableObject? = null): NativeObject = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
fun js_object_create(o: Scriptable? = null, properties: ScriptableObject? = null): NativeObject = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
newNativeObject().also {
it.parentScope = topLevel
it.prototype = when (o) {
@@ -626,15 +625,15 @@ object RhinoUtils {
else -> ensureScriptable(o)
}
if (!properties.isJsNullish()) {
it.defineOwnProperties(context, ensureScriptableObject(Context.toObject(properties, topLevel)))
it.defineOwnProperties(cx, ensureScriptableObject(Context.toObject(properties, topLevel)))
}
}
}!!
}
@JvmStatic
fun js_object_getPrototypeOf(o: Scriptable?): Scriptable? = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
NativeObject.getCompatibleObject(context, topLevel, o).prototype
fun js_object_getPrototypeOf(o: Scriptable?): Scriptable? = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
NativeObject.getCompatibleObject(cx, topLevel, o).prototype
}
@JvmStatic
@@ -662,36 +661,36 @@ object RhinoUtils {
}
@JvmStatic
fun js_object_hasOwnProperty(o: Scriptable, property: String): Boolean = withRhinoContext { context ->
fun js_object_hasOwnProperty(o: Scriptable, property: String): Boolean = withRhinoContext { cx ->
// Context.toBoolean(callPrototypeFunction(TopLevel.Builtins.Object, "hasOwnProperty", o, arrayOf(property)))
AbstractEcmaObjectOperations.hasOwnProperty(context, o, property)
}!!
@JvmStatic
fun js_object_getOwnPropertyNames(o: Scriptable): NativeArray = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
val obj = ensureScriptableObject(toObject(context, topLevel, o))
val ids = obj.getIds(true, false)
ids.indices.forEach { i -> ids[i] = toString(ids[i]) }
context.newArray(topLevel, ids) as NativeArray
}!!
@JvmStatic
fun js_object_getOwnPropertyDescriptor(value: ScriptableObject, key: Any): ScriptableObject? = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
val obj = ensureScriptableObject(toObject(context, topLevel, value))
obj.getOwnPropertyDescriptor(context, key)
AbstractEcmaObjectOperations.hasOwnProperty(cx, o, property)
}
@JvmStatic
fun js_function_bind(scope: Scriptable? = null, targetFunction: Callable, vararg args: Scriptable): BoundFunction = withRhinoContext { context ->
val topLevel = scope ?: ImporterTopLevel(context)
fun js_object_getOwnPropertyNames(o: Scriptable): NativeArray = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
val obj = ensureScriptableObject(toObject(cx, topLevel, o))
val ids = obj.getIds(true, false)
ids.indices.forEach { i -> ids[i] = toString(ids[i]) }
cx.newArray(topLevel, ids) as NativeArray
}
@JvmStatic
fun js_object_getOwnPropertyDescriptor(value: ScriptableObject, key: Any): ScriptableObject? = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
val obj = ensureScriptableObject(toObject(cx, topLevel, value))
obj.getOwnPropertyDescriptor(cx, key)
}
@JvmStatic
fun js_function_bind(scope: Scriptable? = null, targetFunction: Callable, vararg args: Scriptable): BoundFunction = withRhinoContext { cx ->
val topLevel = scope ?: ImporterTopLevel(cx)
val argc: Int = args.size
val boundThis: Scriptable?
val boundArgs: Array<Any?>
when {
argc > 0 -> {
boundThis = RhinoScriptRuntime.toObjectOrNull(context, args[0], topLevel)
boundThis = RhinoScriptRuntime.toObjectOrNull(cx, args[0], topLevel)
boundArgs = arrayOfNulls(argc - 1)
System.arraycopy(args, 1, boundArgs, 0, argc - 1)
}
@@ -700,21 +699,21 @@ object RhinoUtils {
boundArgs = emptyArgs
}
}
BoundFunction(context, topLevel, targetFunction, boundThis, boundArgs)
}!!
BoundFunction(cx, topLevel, targetFunction, boundThis, boundArgs)
}
@JvmStatic
fun js_json_parse(text: String): Any? = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
JsonParser(context, topLevel).parseValue(text)
fun js_json_parse(text: String): Any? = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
JsonParser(cx, topLevel).parseValue(text)
}
@JvmStatic
@JvmOverloads
fun js_json_stringify(value: Any?, replacer: Any? = null, space: Any? = null): Any = withRhinoContext { context ->
val topLevel = ImporterTopLevel(context)
NativeJSON.stringify(context, topLevel, value, replacer, space)
}!!
fun js_json_stringify(value: Any?, replacer: Any? = null, space: Any? = null): Any = withRhinoContext { cx ->
val topLevel = ImporterTopLevel(cx)
NativeJSON.stringify(cx, topLevel, value, replacer, space)
}
@JvmStatic
fun js_typeof(value: Any?): String = `typeof`(value)
@@ -725,29 +724,31 @@ object RhinoUtils {
}
@JvmStatic
fun js_date_parseString(s: String): Double = withRhinoContext { context ->
NativeDate.date_parseString(context, s)
}!!
fun js_date_parseString(s: String): Double = withRhinoContext { cx ->
NativeDate.date_parseString(cx, s)
}
@JvmStatic
fun js_eval(scope: Scriptable, s: String): Any? = withRhinoContext { context ->
fun js_eval(scope: Scriptable, s: String): Any? = withRhinoContext { cx ->
val global = ScriptableObject.getTopLevelScope(scope)
RhinoScriptRuntime.evalSpecial(context, global, global, arrayOf(s), "eval code", 1)
RhinoScriptRuntime.evalSpecial(cx, global, global, arrayOf(s), "eval code", 1)
}
fun <R> withRhinoContext(function: (context: Context) -> R?): R? {
try {
return function.invoke(Context.enter().apply { initStandardObjects() })
fun <R> withRhinoContext(function: (context: Context) -> R): R {
var cxRhino: Context? = null
return try {
val cx = Context.getCurrentContext()
?: Context.enter().also {
it.initStandardObjects()
cxRhino = it
}
@Suppress("DEPRECATION")
cx.optimizationLevel = -1
cx.languageVersion = Context.VERSION_ES6
cx.isInterpretedMode = true
function.invoke(cx)
} finally {
Context.exit()
}
}
fun <R> withRhinoContext(function: (context: Context, standardObjects: ScriptableObject) -> R?): R? {
try {
return Context.enter().let { cx -> function.invoke(cx, cx.initStandardObjects()) }
} finally {
Context.exit()
cxRhino?.let { Context.exit() }
}
}

View File

@@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
android:fitsSystemWindows="true">
<org.autojs.autojs.ui.common.NestedOuterScrollView
android:id="@+id/outerScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingVertical="2sp"
android:scrollbars="vertical">
<HorizontalScrollView
android:id="@+id/innerScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingHorizontal="8sp"
android:scrollbars="horizontal">
<org.autojs.autojs.ui.widget.SelectableTextView
@@ -23,7 +26,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:padding="16dp"
android:scrollbars="vertical"
android:fontFamily="monospace" />

View File

@@ -3,6 +3,12 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
app:popupTheme="@style/Widget.AppCompat.PopupMenu">
<item
android:id="@+id/action_use_default_icon"
android:icon="@mipmap/ic_launcher"
android:title="@string/text_use_default_icon"
app:showAsAction="never"/>
<item
android:id="@+id/action_select_image"
android:icon="@drawable/ic_insert_photo_white_48dp"

View File

@@ -731,6 +731,7 @@
<string name="text_select_file_to_upload">حدد ملف للتحميل</string>
<string name="text_select_icon">حدد أيقونة</string>
<string name="text_select_image">حدد صورة</string>
<string name="text_use_default_icon">استخدام الرمز الافتراضي</string>
<string name="text_send">إرسال</string>
<string name="text_send_shortcut">انشاء اختصار</string>
<string name="text_server_mode">وضع الخادم</string>

View File

@@ -727,6 +727,7 @@
<string name="text_select_file_to_upload">Select file to upload</string>
<string name="text_select_icon">Select icon</string>
<string name="text_select_image">Select an image</string>
<string name="text_use_default_icon">Use default icon</string>
<string name="text_send">Send</string>
<string name="text_send_shortcut">Create shortcut</string>
<string name="text_server_mode">Server mode</string>

View File

@@ -730,6 +730,7 @@
<string name="text_select_file_to_upload">Seleccionar el archivo a cargar</string>
<string name="text_select_icon">Seleccionar un icono</string>
<string name="text_select_image">Seleccionar una imagen</string>
<string name="text_use_default_icon">Usar icono predeterminado</string>
<string name="text_send">Enviar</string>
<string name="text_send_shortcut">Crear acceso directo</string>
<string name="text_server_mode">Modo servidor</string>

View File

@@ -730,6 +730,7 @@
<string name="text_select_file_to_upload">Sélectionnez le fichier à télécharger</string>
<string name="text_select_icon">Sélectionner l\'icône</string>
<string name="text_select_image">Sélectionner une image</string>
<string name="text_use_default_icon">Utiliser l\'icône par défaut</string>
<string name="text_send">Envoyer</string>
<string name="text_send_shortcut">Créer un raccourci</string>
<string name="text_server_mode">Mode serveur</string>

View File

@@ -730,6 +730,7 @@
<string name="text_select_file_to_upload">アップロードするファイルを選択します</string>
<string name="text_select_icon">アイコンを選択する</string>
<string name="text_select_image">画像を選択する</string>
<string name="text_use_default_icon">デフォルトのアイコンを使用する</string>
<string name="text_send">送信する</string>
<string name="text_send_shortcut">ショートカットの作成</string>
<string name="text_server_mode">サーバーモード</string>

View File

@@ -731,6 +731,7 @@
<string name="text_select_file_to_upload">업로드 할 파일을 선택하십시오</string>
<string name="text_select_icon">아이콘을 선택하십시오</string>
<string name="text_select_image">이미지를 선택하십시오</string>
<string name="text_use_default_icon">기본 아이콘 사용</string>
<string name="text_send">보내다</string>
<string name="text_send_shortcut">바로 가기를 만듭니다</string>
<string name="text_server_mode">서버 모드</string>

View File

@@ -730,6 +730,7 @@
<string name="text_select_file_to_upload">Выберите файл для загрузки</string>
<string name="text_select_icon">Выбрать значок</string>
<string name="text_select_image">Выбрать изображение</string>
<string name="text_use_default_icon">Использовать значок по умолчанию</string>
<string name="text_send">Отправить</string>
<string name="text_send_shortcut">Создать ярлык</string>
<string name="text_server_mode">Режим сервера</string>

View File

@@ -729,6 +729,7 @@
<string name="text_select_file_to_upload">選擇要上傳的文件</string>
<string name="text_select_icon">選擇圖標</string>
<string name="text_select_image">選擇圖片</string>
<string name="text_use_default_icon">使用默認圖標</string>
<string name="text_send">發送</string>
<string name="text_send_shortcut">創建快捷方式</string>
<string name="text_server_mode">服務端模式</string>

View File

@@ -729,6 +729,7 @@
<string name="text_select_file_to_upload">選擇要上傳的檔案</string>
<string name="text_select_icon">選擇圖示</string>
<string name="text_select_image">選擇圖片</string>
<string name="text_use_default_icon">使用預設圖示</string>
<string name="text_send">傳送</string>
<string name="text_send_shortcut">建立快捷方式</string>
<string name="text_server_mode">服務端模式</string>

View File

@@ -725,6 +725,7 @@
<string name="text_select_file_to_upload">选择要上传的文件</string>
<string name="text_select_icon">选择图标</string>
<string name="text_select_image">选择图片</string>
<string name="text_use_default_icon">使用默认图标</string>
<string name="text_send">发送</string>
<string name="text_send_shortcut">创建快捷方式</string>
<string name="text_server_mode">服务端模式</string>

View File

@@ -935,6 +935,7 @@
<string name="text_select_file_to_upload">Select file to upload</string>
<string name="text_select_icon">Select icon</string>
<string name="text_select_image">Select an image</string>
<string name="text_use_default_icon">Use default icon</string>
<string name="text_send">Send</string>
<string name="text_send_shortcut">Create shortcut</string>
<string name="text_server_mode">Server mode</string>

View File

@@ -1,5 +1,5 @@
#Mon Mar 10 23:16:02 CST 2025
BUILD_TIME=1741619762219
#Tue Mar 11 15:15:22 CST 2025
BUILD_TIME=1741677322038
COMPILE_SDK_VERSION=35
JAVA_VERSION=23
JAVA_VERSION_MIN_RADICAL=0
@@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3009
VERSION_BUILD=3011
VERSION_NAME=6.6.2 Alpha4
VSCODE_EXT_REQUIRED_VERSION=1.0.8