6.7.0 - Alpha23 - Fine tuning

This commit is contained in:
SuperMonster003
2026-03-07 13:10:49 +08:00
parent ac9e091be4
commit 042e723eb1
45 changed files with 219 additions and 229 deletions

View File

@@ -167,13 +167,14 @@
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

View File

@@ -3,34 +3,21 @@ package androidx.recyclerview.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EdgeEffect;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.widget.EdgeEffectCompat;
import org.autojs.autojs.theme.ThemeColor;
import org.autojs.autojs.theme.ThemeColorManager;
import org.autojs.autojs.theme.ThemeColorMutable;
import java.lang.reflect.Field;
/**
* Created by Stardust on Aug 14, 2016.
* Modified by SuperMonster003 as of Dec 1, 2021.
* Modified by JetBrains AI Assistant (GPT-5.3-Codex (xhigh)) as of Mar 6, 2026.
* Modified by SuperMonster003 as of Mar 6, 2026.
*/
public class ThemeColorRecyclerView extends RecyclerView implements ThemeColorMutable {
private int mColorPrimary;
private Field mLeftGlowField;
private Field mTopGlowField;
private Field mRightGlowField;
private Field mBottomGlowField;
private Field mEdgeEffectField;
private boolean hasAppliedThemeColorLeft;
private boolean hasAppliedThemeColorTop;
private boolean hasAppliedThemeColorRight;
private boolean hasAppliedThemeColorBottom;
public ThemeColorRecyclerView(Context context) {
super(context);
init();
@@ -46,65 +33,17 @@ public class ThemeColorRecyclerView extends RecyclerView implements ThemeColorMu
init();
}
private boolean applyThemeColor(Field edgeEffectCompatField) {
try {
EdgeEffectCompat edgeEffectCompat = (EdgeEffectCompat) edgeEffectCompatField.get(this);
if (edgeEffectCompat != null) {
return setEdgeEffectColor(edgeEffectCompat, mColorPrimary);
}
} catch (Exception ignored) {
/* Ignored. */
}
return false;
}
private void init() {
try {
mEdgeEffectField = EdgeEffectCompat.class.getDeclaredField("mEdgeEffect");
mEdgeEffectField.setAccessible(true);
mLeftGlowField = RecyclerView.class.getDeclaredField("mLeftGlow");
mLeftGlowField.setAccessible(true);
mRightGlowField = RecyclerView.class.getDeclaredField("mRightGlow");
mRightGlowField.setAccessible(true);
mTopGlowField = RecyclerView.class.getDeclaredField("mTopGlow");
mTopGlowField.setAccessible(true);
mBottomGlowField = RecyclerView.class.getDeclaredField("mBottomGlow");
mBottomGlowField.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
// android:fadeScrollbars="true"
// setScrollbarFadingEnabled(true);
// android:scrollbarDefaultDelayBeforeFade="600"
// setScrollBarDefaultDelayBeforeFade(600);
// android:scrollbarFadeDuration="500"
// setScrollBarFadeDuration(500);
// android:scrollbars="vertical"
// setVerticalScrollBarEnabled(true);
// To ensure scrollbar fading works properly.
// setFadingEdgeLength(0);
ThemeColorManager.add(this);
}
private boolean setEdgeEffectColor(EdgeEffectCompat compat, int color) {
if (compat == null) {
return false;
}
try {
EdgeEffect edgeEffect = (EdgeEffect) mEdgeEffectField.get(compat);
if (edgeEffect != null) {
edgeEffect.setColor(color);
setEdgeEffectFactory(new EdgeEffectFactory() {
@NonNull
@Override
protected EdgeEffect createEdgeEffect(@NonNull RecyclerView view, int direction) {
EdgeEffect edgeEffect = new EdgeEffect(view.getContext());
edgeEffect.setColor(mColorPrimary);
return edgeEffect;
}
} catch (Exception ignored) {
/* Ignored. */
}
return true;
});
ThemeColorManager.add(this);
}
@Override
@@ -113,36 +52,7 @@ public class ThemeColorRecyclerView extends RecyclerView implements ThemeColorMu
return;
}
mColorPrimary = color.colorPrimary;
invalidateGlows();
}
void invalidateGlows() {
super.invalidateGlows();
hasAppliedThemeColorLeft = false;
hasAppliedThemeColorTop = false;
hasAppliedThemeColorRight = false;
hasAppliedThemeColorBottom = false;
}
void ensureLeftGlow() {
super.ensureLeftGlow();
hasAppliedThemeColorLeft = hasAppliedThemeColorLeft || applyThemeColor(mLeftGlowField);
}
void ensureTopGlow() {
super.ensureTopGlow();
hasAppliedThemeColorTop = hasAppliedThemeColorTop || applyThemeColor(mTopGlowField);
}
void ensureRightGlow() {
super.ensureLeftGlow();
hasAppliedThemeColorRight = hasAppliedThemeColorRight || applyThemeColor(mRightGlowField);
}
void ensureBottomGlow() {
super.ensureBottomGlow();
hasAppliedThemeColorBottom = hasAppliedThemeColorBottom || applyThemeColor(mBottomGlowField);
}
}

View File

@@ -44,6 +44,6 @@ class ScriptPromiseAdapter {
}
companion object {
private val UNSET = Object()
private val UNSET = Any()
}
}

View File

@@ -156,7 +156,7 @@ open class RhinoJavaScriptEngine(private val mAndroidContext: android.content.Co
override fun wrap(cx: Context, scope: Scriptable, obj: Any?, staticType: Class<*>?): Any? {
return when {
obj is String -> runtime.bridges.toString(obj.toString())
obj is String -> runtime.bridges.toString(obj)
staticType == UiObjectCollection::class.java -> runtime.bridges.asArray(obj)
else -> super.wrap(cx, scope, obj, staticType)
}

View File

@@ -32,7 +32,7 @@ class SearchUpTargetAction(action: Int, filter: FilterAction.Filter) : SearchTar
companion object {
private val TAG = SearchUpTargetAction::class.java!!.getSimpleName()
private val TAG = SearchUpTargetAction::class.java.getSimpleName()
private val LOOP_MAX = 20
}
}

View File

@@ -863,13 +863,17 @@ open class UiSelector : UiObjectActions, StringReadable {
internal fun pick(scriptRuntime: ScriptRuntime) = Detector(compass, object : Result(resultType) {
override fun byOne() = selector?.let { sel ->
root?.let { return sel.findOneOf(it) } ?: sel.findOnce()
override fun byOne(): UiObject? {
return selector?.let { sel ->
root?.let { return sel.findOneOf(it) } ?: sel.findOnce()
}
}
override fun byAll() = selector?.let { sel ->
root?.let { return sel.findOf(it) } ?: sel.find()
} ?: EMPTY
override fun byAll(): UiObjectCollection {
return selector?.let { sel ->
root?.let { return sel.findOf(it) } ?: sel.find()
} ?: EMPTY
}
}, callback, selector).detect(scriptRuntime)

View File

@@ -41,15 +41,17 @@ class StartForResultActivity : Activity() {
}
}
if (extras == null) {
finish().also { return }
finish()
return
}
val callback = extras!!.map["callback"]
val callback = extras.map["callback"]
if (callback is Callback) {
mCallback = callback
}
if (callback == null) {
mCallback = null
finish().also { return }
finish()
return
}
mCallback!!.onActivityCreate(this)
}

View File

@@ -23,7 +23,7 @@ enum class Language(@JvmField val languageTag: String, @KeyRes private val keyRe
;
val locale: Locale = when (languageTag.isBlank()) {
true -> LocaleUtils.getSystemLocale()
true -> LocaleUtils.getPrimarySystemLocale()
else -> Locale.forLanguageTag(languageTag)
}
@@ -39,7 +39,7 @@ enum class Language(@JvmField val languageTag: String, @KeyRes private val keyRe
return languageTag
}
val systemTag = LocaleUtils.getSystemLocale().toLanguageTag()
val systemTag = LocaleUtils.getPrimarySystemLocale().toLanguageTag()
val availableTags = values().map { it.languageTag }
if (systemTag in availableTags) {

View File

@@ -7,10 +7,6 @@ import android.util.Log
import android.view.View
import org.autojs.autojs.core.ui.ViewExtras
import org.autojs.autojs.engine.module.AssetAndUrlModuleSourceProvider
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
import org.autojs.autojs.pio.PFiles
import org.autojs.autojs.pio.UncheckedIOException
import org.autojs.autojs.project.ScriptConfig
@@ -18,6 +14,10 @@ import org.autojs.autojs.rhino.AndroidContextFactory
import org.autojs.autojs.rhino.AutoJsContext
import org.autojs.autojs.rhino.RhinoAndroidHelper
import org.autojs.autojs.rhino.TopLevelScope
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.rhino.extension.ScriptableExtensions.prop
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.proxy.PaintProxyObject
import org.autojs.autojs.script.JavaScriptSource
@@ -42,7 +42,7 @@ import java.io.IOException
import java.io.InputStreamReader
import java.io.Reader
import java.net.URI
import java.util.*
import java.util.Locale
/**
* Created by Stardust on Apr 2, 2017.
@@ -215,9 +215,9 @@ open class RhinoJavaScriptEngine(private val androidContext: android.content.Con
private inner class WrapFactory : AndroidContextFactory.WrapFactory() {
override fun wrapAsJavaObject(cx: Context?, scope: Scriptable, javaObject: Any?, staticType: TypeInfo): Scriptable? {
return when (javaObject) {
is View -> ViewExtras.getNativeView(scope, /* view = */ javaObject, staticType.asClass(), runtime)
is Paint if Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
return when {
javaObject is View -> ViewExtras.getNativeView(scope, /* view = */ javaObject, staticType.asClass(), runtime)
javaObject is Paint && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
// Use composition-based proxy to preserve Paint identity and intercept setColor only.
// zh-CN: 使用组合式代理以保持 Paint 身份一致性, 且仅拦截 setColor.
val base = super.wrapAsJavaObject(cx, scope, javaObject, staticType) ?: return null
@@ -226,11 +226,12 @@ open class RhinoJavaScriptEngine(private val androidContext: android.content.Con
else -> super.wrapAsJavaObject(cx, scope, javaObject, staticType)
}
}
}
companion object {
private const val TAG = "RhinoJavaScriptEngine"
const val SOURCE_FILE_INIT = "init.js"
const val SOURCE_NAME_INIT = "<init>"
const val MODULES_ROOT_PATH = "modules"
@@ -238,9 +239,5 @@ open class RhinoJavaScriptEngine(private val androidContext: android.content.Con
@JvmField
val JS_BEAUTIFY_FILE = PFiles.join(JS_BEAUTIFY_PATH, "beautify.js")
private val TAG = RhinoJavaScriptEngine::class.java.simpleName
}
}

View File

@@ -65,7 +65,7 @@ object ScriptIntents {
JavaScriptFileSource(path).let { fss: JavaScriptFileSource ->
source = script?.let { SequenceScriptSource(fss.name, StringScriptSource(it), fss) } ?: fss
}
File(path!!).parent?.let { config.workingDirectory = it }
File(path).parent?.let { config.workingDirectory = it }
}
}
source?.let { AutoJs.instance.scriptEngineService.execute(it, config) }

View File

@@ -2,8 +2,10 @@ package org.autojs.autojs.inrt
import android.os.Bundle
import android.view.View
import android.widget.EdgeEffect
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceFragmentCompat
import androidx.recyclerview.widget.RecyclerView
import org.autojs.autojs.runtime.api.Permissions
import org.autojs.autojs.theme.preference.Syncable
import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar
@@ -67,11 +69,17 @@ class SettingsActivity : AppCompatActivity() {
setDivider(null)
setDividerHeight(0)
listView.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
override fun createEdgeEffect(recyclerView: RecyclerView, direction: Int): EdgeEffect {
return EdgeEffect(recyclerView.context).apply {
color = recyclerView.context.getColor(R.color.md_blue_gray_500)
}
}
}
listView.isHorizontalScrollBarEnabled = false
listView.isVerticalScrollBarEnabled = false
listView.excludePaddingClippableViewFromBottomNavigationBar()
}
}
}

View File

@@ -61,12 +61,13 @@ class AppUtils(context: Context, @get:ScriptInterface val fileProviderAuthority:
* @param o < alias | packageName >
*/
@ScriptInterface
fun launchPackage(o: String?) = runCatching {
o ?: return false
val nicePackageName = getAppByAlias(alias = o)?.packageName ?: (/* packageName = */ o)
val intent = mPackageManager.getLaunchIntentForPackage(nicePackageName) ?: return false
intent.start(mContext)
}.isSuccess
fun launchPackage(o: String?): Boolean =
runCatching {
o ?: return false
val nicePackageName = getAppByAlias(alias = o)?.packageName ?: (/* packageName = */ o)
val intent = mPackageManager.getLaunchIntentForPackage(nicePackageName) ?: return false
intent.start(mContext)
}.isSuccess
@ScriptInterface
@Suppress("unused")

View File

@@ -122,14 +122,14 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
@JvmStatic
@RhinoFunctionBody
fun vibrateRhinoWithRuntime(scriptRuntime: ScriptRuntime, o: Any?, p: Any?) {
when (o) {
is String -> {
when {
o is String -> {
MorseCode.vibrateRhino(o, p)
}
is Number if p is Number -> {
o is Number && p is Number -> {
scriptRuntime.device.vibrate(/* off = */ o.toLong(), /* millis = */ p.toLong())
}
is NativeArray if p is Number -> {
o is NativeArray && p is Number -> {
val listOff = listOf(p.toLong())
val listOthers = o.map { toVibrateTimingElement(it) }
val timings = (listOff + listOthers).toLongArray()

View File

@@ -494,15 +494,16 @@ class Dialogs(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
}
private fun applyDialogProperty(builder: JsDialogBuilder, name: String, value: Any?) {
when (val propertySetter = propertySetterMap[name]) {
PropertyConverter.COLOR_INT -> {
val propertySetter = propertySetterMap[name]
when {
propertySetter == PropertyConverter.COLOR_INT -> {
val colorInt = Colors.toIntRhino(value)
invokeJavaMethod(builder, name, arrayOf(colorInt))
}
PropertyConverter.BOOLEAN if coerceBoolean(value, false) -> {
propertySetter == PropertyConverter.BOOLEAN && coerceBoolean(value, false) -> {
invokeJavaMethod(builder, name, emptyArray())
}
is String -> when (propertySetter) {
propertySetter is String -> when (propertySetter) {
in propertySetterMap -> {
applyDialogProperty(builder, propertySetter, value)
}

View File

@@ -1494,7 +1494,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
val similarityMethod = runCatching {
ImageSimilarity::class.java.getDeclaredMethod(metric, OpencvMat::class.java, OpencvMat::class.java)
}.getOrElse { throw WrappedIllegalArgumentException("Unknown similarity metric: $metric") }
if (similarityMethod.returnType != Double::class.java && similarityMethod.returnType != java.lang.Double::class.java) {
if (similarityMethod.returnType != Double::class.java) {
throw WrappedIllegalArgumentException("Similarity metric ($metric) method must return Double type. Found: ${similarityMethod.returnType}")
}
similarityMethod.invoke(ImageSimilarity, matA, matB) as Double

View File

@@ -587,9 +587,7 @@ object Inspect : Augmentable(), Invokable {
private fun formatProperty(ctx: Ctx, value: ScriptableObject, recurseTimes: Int?, visibleKeys: NativeObject, key: String, array: Boolean): String {
var name: String? = null
val desc = js_object_getOwnPropertyDescriptor(value, key) ?: newNativeObject().apply {
put("value", this, value.prop(key))
}
val desc = js_object_getOwnPropertyDescriptor(value, key)
val getter = desc.prop(PROXY_GETTER_KEY)
val setter = desc.prop(PROXY_SETTER_KEY)

View File

@@ -1,10 +1,11 @@
package org.autojs.autojs.theme.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.EdgeEffect;
import android.widget.HorizontalScrollView;
import org.autojs.autojs.theme.ThemeColor;
import org.autojs.autojs.theme.ThemeColorManager;
import org.autojs.autojs.theme.ThemeColorMutable;
@@ -60,17 +61,23 @@ public class ThemeColorHorizontalScrollView extends HorizontalScrollView impleme
invalidate();
}
@SuppressLint("DiscouragedPrivateApi")
private void syncEdgeEffect() {
try {
Field f1 = HorizontalScrollView.class.getDeclaredField("mEdgeGlowLeft");
f1.setAccessible(true);
f1.set(this, mEdgeGlowLeft);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setLeftEdgeEffectColor(mFadingEdgeColor);
setRightEdgeEffectColor(mFadingEdgeColor);
} else {
try {
Field f1 = HorizontalScrollView.class.getDeclaredField("mEdgeGlowLeft");
f1.setAccessible(true);
f1.set(this, mEdgeGlowLeft);
Field f2 = HorizontalScrollView.class.getDeclaredField("mEdgeGlowRight");
f2.setAccessible(true);
f2.set(this, mEdgeGlowRight);
} catch (Exception e) {
e.printStackTrace();
Field f2 = HorizontalScrollView.class.getDeclaredField("mEdgeGlowRight");
f2.setAccessible(true);
f2.set(this, mEdgeGlowRight);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1080,7 +1080,7 @@ public class ScriptOperations {
// zh-CN: 删除操作使用不确定进度条即可, 行为更稳定.
MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext)
.title(titleRes)
.content(R.string.text_deleting)
.content(mContext.getString(R.string.text_deleting) + mContext.getString(R.string.text_half_ellipsis))
.negativeText(R.string.dialog_button_abort)
.negativeColorRes(R.color.dialog_button_caution)
.onNegative((dialog, which) -> {

View File

@@ -8,6 +8,7 @@ import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.database.Cursor
import android.graphics.Color
import android.graphics.Rect
import android.net.Uri
import android.os.Build
@@ -1328,8 +1329,8 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
mNormalToolbar.apply {
setOnMenuItemClickListener(this@EditorView)
setOnMenuItemLongClickListener { id ->
when (id) {
R.id.run if !mReadOnly -> true.also { debug() }
when {
id == R.id.run && !mReadOnly -> true.also { debug() }
else -> false
}
}
@@ -1338,8 +1339,8 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
(existing as? ToolbarFragment<*>)?.apply {
setOnMenuItemClickListener(this@EditorView)
setOnMenuItemLongClickListener { id ->
when (id) {
R.id.run if !mReadOnly -> true.also { debug() }
when {
id == R.id.run && !mReadOnly -> true.also { debug() }
else -> false
}
}
@@ -1513,7 +1514,12 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
mCodeCompletionBar.setTextColor(textColor)
mSymbolBar.setTextColor(textColor)
mShowFunctionsButton.setColorFilter(textColor)
ViewUtils.setNavigationBarBackgroundColor(activity, imeBarBackgroundColor)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ViewUtils.setNavigationBarBackgroundColor(activity, imeBarBackgroundColor)
} else {
val adjustedImageContrastColor = ColorUtils.adjustColorForContrast(Color.WHITE, ColorUtils.applyAlpha(imeBarBackgroundColor, 1.0), 2.3)
ViewUtils.setNavigationBarBackgroundColor(activity, adjustedImageContrastColor)
}
invalidate()
}
}
@@ -2683,7 +2689,7 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
private const val MIN_CONFIDENCE_TO_WRITE_FILE = 90
private val DEFAULT_CHARSET_TO_WRITE_FILE = StandardCharsets.UTF_8
private const val LARGE_FILE_MODE_THRESHOLD = JavaScriptHighlighter.MAX_HIGHLIGHT_CHARS
private const val LARGE_FILE_MODE_THRESHOLD = JavaScriptHighlighter.MAX_HIGHLIGHT_CHARS
// Internal storage root (no external SD).
// zh-CN: 内部存储根目录 (不访问外置 SD).

View File

@@ -597,11 +597,14 @@ class CodeEditText : AppCompatEditText {
runCatching { event.text.clear() }
runCatching { event.contentDescription = null }
// Also drop selection-changed events entirely in large-text mode.
// zh-CN: 大文本模式下直接丢弃 selection-changed 事件.
if (event.eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) return
if (event.eventType == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) return
if (event.eventType == AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY) return
// Also drop selection-changed events entirely in large-text mode to avoid TransactionTooLargeException.
// zh-CN: 大文本模式下直接丢弃 selection-changed 事件以避免 TransactionTooLargeException.
when (event.eventType) {
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> return
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> return
AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> return
else -> Unit
}
}
super.sendAccessibilityEventUnchecked(event)
}

View File

@@ -178,7 +178,7 @@ class CodeEditor : HVScrollView {
if (mProcessDialog?.isShowing == true) return@Runnable
mProcessDialog = MaterialDialog.Builder(context)
.content(R.string.text_processing)
.content(R.string.text_in_progress)
// Text only, no progress spinner.
// zh-CN: 仅显示文字, 不使用进度圆圈动画.
.cancelable(false)

View File

@@ -225,7 +225,7 @@ object SymbolsConfigStore {
fun getAllDefaultNameAliases(context: Context): Set<String> {
val appLang = Language.getPrefLanguageOrNull()
val appKey = appLang?.languageTag ?: "null"
val sysKey = LocaleUtils.getSystemLocale().toLanguageTag()
val sysKey = LocaleUtils.getPrimarySystemLocale().toLanguageTag()
val cacheKey = "app=$appKey|sys=$sysKey"
sDefaultAliasesCache[cacheKey]?.let { return it }

View File

@@ -184,7 +184,7 @@ class NodeInfoView : RecyclerView {
}
}
return when (NodeInfo::class.java.getDeclaredField(attr).type) {
java.lang.String::class.java -> "$attr('$value')"
String::class.java -> "$attr('$value')"
else -> "$attr($value)"
}
}

View File

@@ -2,7 +2,10 @@ package org.autojs.autojs.ui.settings
import android.os.Bundle
import android.view.View
import android.widget.EdgeEffect
import androidx.preference.PreferenceFragmentCompat
import androidx.recyclerview.widget.RecyclerView
import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar
import org.autojs.autojs6.R
@@ -14,9 +17,15 @@ class PreferencesFragment : PreferenceFragmentCompat() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.edgeEffectFactory = object : RecyclerView.EdgeEffectFactory() {
override fun createEdgeEffect(recyclerView: RecyclerView, direction: Int): EdgeEffect {
return EdgeEffect(recyclerView.context).apply {
color = ThemeColorManager.colorPrimary
}
}
}
listView.isHorizontalScrollBarEnabled = false
listView.isVerticalScrollBarEnabled = false
listView.excludePaddingClippableViewFromBottomNavigationBar()
}
}
}

View File

@@ -384,10 +384,8 @@ object ColorUtils {
)
@JvmStatic
fun applyAlpha(@ColorInt color: Int, alpha: Double): Int = when (alpha) {
1.0 -> color
else -> ColorUtils.setAlphaComponent(color, (alpha * 255).roundToInt())
}
fun applyAlpha(@ColorInt color: Int, alpha: Double): Int =
ColorUtils.setAlphaComponent(color, (alpha * 255).roundToInt())
/**
* Calculate the contrast ratio between two colors using the W3C WCAG formula.

View File

@@ -3091,16 +3091,17 @@ object FileUtils {
}.getOrElse { false }
@JvmStatic
fun File.isBinDiscImageLike() = runCatching {
this@isBinDiscImageLike.inputStream().use { inputStream ->
val header = ByteArray(2048) // Read first sector
if (inputStream.read(header) != header.size) return false
fun File.isBinDiscImageLike(): Boolean =
runCatching {
this@isBinDiscImageLike.inputStream().use { inputStream ->
val header = ByteArray(2048) // Read first sector
if (inputStream.read(header) != header.size) return false
// Check for very basic ISO 9660 primary volume descriptor
val pvdDescriptor = "CD001".toByteArray()
header.sliceArray(0x800 until 0x800 + pvdDescriptor.size).contentEquals(pvdDescriptor)
}
}.getOrElse { false }
// Check for very basic ISO 9660 primary volume descriptor
val pvdDescriptor = "CD001".toByteArray()
header.sliceArray(0x800 until 0x800 + pvdDescriptor.size).contentEquals(pvdDescriptor)
}
}.getOrElse { false }
// Determines if a CUE file describes audio tracks
@JvmStatic
@@ -3168,17 +3169,26 @@ object FileUtils {
}.getOrElse { false }
@JvmStatic
fun File.isSegaMDLike() = runCatching {
this@isSegaMDLike.inputStream().use { inputStream ->
val header = ByteArray(512) // 假设 SEGA 游戏文件有特定的头部
if (inputStream.read(header) != header.size) return false
fun File.isSegaMDLike(): Boolean =
runCatching {
this@isSegaMDLike.inputStream().use { inputStream ->
// Assume SEGA game files have a specific header.
// zh-CN: 假设 SEGA 游戏文件有特定的头部.
val header = ByteArray(512)
if (inputStream.read(header) != header.size) return false
// 这里你需要根据 SEGA 文件的具体特征来调整条件
// 例如: 找到特定的标识符或者模式
val segaIdentifier = byteArrayOf(0x53, 0x45, 0x47, 0x41) // 可能的 "SEGA" 标记
header.sliceArray(segaIdentifier.indices).contentEquals(segaIdentifier)
}
}.getOrElse { false }
// Here is the modification needed to adjust the conditions based on specific SEGA file characteristics.
// This requires identifying specific identifiers or patterns within the header.
// zh-CN:
// 这里需要根据 SEGA 文件的具体特征来调整条件.
// 例如: 找到特定的标识符或者模式.
// Possible "SEGA" marker.
// zh-CN: 可能的 "SEGA" 标记.
val segaIdentifier = byteArrayOf(0x53, 0x45, 0x47, 0x41)
header.sliceArray(segaIdentifier.indices).contentEquals(segaIdentifier)
}
}.getOrElse { false }
// Function to check if a file is likely a macro based on scripting patterns found in samples
@JvmStatic

View File

@@ -38,18 +38,41 @@ object LocaleUtils {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.getSystemService(LocaleManager::class.java).applicationLocales = LocaleList.getEmptyLocaleList()
} else {
setLocale(context, getSystemLocale())
setLocale(context, getPrimarySystemLocale())
}
}
@JvmStatic
@Deprecated("Use getSystemLocaleList instead", ReplaceWith("getPrimarySystemLocale()"))
fun getSystemLocale(): Locale = Resources.getSystem().configuration.locales[0] ?: Locale.getDefault()
@JvmStatic
@JvmOverloads
fun getSystemLocaleList(context: Context? = null): List<Locale> {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
val localeManager = (context ?: GlobalAppContext.get()).getSystemService(LocaleManager::class.java)
val localeList: LocaleList = localeManager.systemLocales
List(localeList.size()) { index -> localeList[index] }
}
else -> {
val localeList = Resources.getSystem().configuration.locales
List(localeList.size()) { index -> localeList[index] }
}
}
}
@JvmStatic
@JvmOverloads
fun getPrimarySystemLocale(context: Context? = null): Locale {
return getSystemLocaleList(context).firstOrNull() ?: Locale.getDefault()
}
@JvmStatic
fun getResources(desiredLocale: Locale?): Resources {
return GlobalAppContext.get().let { context ->
context.resources.configuration.let { Configuration(it) }.run {
setLocale(desiredLocale ?: getSystemLocale())
setLocale(desiredLocale ?: getPrimarySystemLocale())
context.createConfigurationContext(this).resources
}
}

View File

@@ -1,15 +1,25 @@
package org.autojs.autojs.util;
package org.autojs.autojs.util
/**
* Created by Stardust on Nov 26, 2017.
* Transformed by SuperMonster003 on Mar 5, 2026.
* Modified by SuperMonster003 as of Mar 5, 2026.
*/
public class MathUtils {
object MathUtils {
public static int min(int... ints) {
int min = ints[0];
for (int i = 1; i < ints.length; i++) {
min = Math.min(ints[i], min);
}
return min;
}
@JvmStatic
fun min(vararg ints: Int): Int =
ints.minOrNull() ?: throw NoSuchElementException("Array is empty")
@JvmStatic
fun Int.floorMod(mod: Int): Int =
Math.floorMod(this, mod)
@JvmStatic
fun Long.floorMod(mod: Long): Long =
Math.floorMod(this, mod)
@JvmStatic
fun Long.floorMod(mod: Int): Int =
Math.floorMod(this, mod)
}

View File

@@ -22,7 +22,7 @@
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/apps"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -46,7 +46,7 @@
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -29,7 +29,7 @@
android:layout_marginTop="6dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

View File

@@ -105,7 +105,7 @@
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -35,7 +35,7 @@
tools:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -35,7 +35,7 @@
tools:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -13,7 +13,7 @@
android:layout_gravity="center_horizontal"
android:background="@drawable/little_triangle" />
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@@ -5,7 +5,7 @@
android:animateLayoutChanges="true"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/log_list"
android:layout_width="match_parent"
android:layout_height="0dp"

View File

@@ -5,7 +5,7 @@
android:animateLayoutChanges="true"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/log_list"
android:layout_width="match_parent"
android:layout_height="0dp"

View File

@@ -46,7 +46,7 @@
app:tint="@android:color/white" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/variables"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -23,7 +23,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/result_list"
android:layout_width="match_parent"
android:layout_height="400dp" />

View File

@@ -4,7 +4,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@@ -14,7 +14,7 @@
app:cardElevation="0.97dp"
app:cardUseCompatPadding="true" />
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/explorer_item_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

View File

@@ -13,7 +13,7 @@
android:importantForAccessibility="no"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/drawer_menu"
android:layout_width="match_parent"
android:layout_height="0dp"

View File

@@ -10,7 +10,7 @@
android:layout_height="1dp"
android:background="@color/divider_functions_keyboard" />
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/properties"
android:layout_width="match_parent"
android:layout_height="0dp"
@@ -22,7 +22,7 @@
android:layout_height="1dp"
android:background="@color/divider_functions_keyboard" />
<androidx.recyclerview.widget.RecyclerView
<androidx.recyclerview.widget.ThemeColorRecyclerView
android:id="@+id/module_list"
android:layout_width="match_parent"
android:layout_height="50dp" />