diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 591d972c..f09a437f 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -5,7 +5,7 @@ "feature": [ "ui.statusBarAppearanceLight/statusBarAppearanceLightBy/navigationBarColor 等方法", "设置页面增加 \"文件扩展名\" 设置选项", - "主题色设置页面增加新布局支持" + "主题色设置页面增加新布局支持 (颜色库分组/主题色定位/颜色搜索)" ], "fix": [ "Android 15 状态栏背景颜色与主题色不一致的问题", diff --git a/app/src/main/java/org/autojs/autojs/annotation/ReservedForCompatibility.kt b/app/src/main/java/org/autojs/autojs/annotation/ReservedForCompatibility.kt index a35a332b..a7d7ddb5 100644 --- a/app/src/main/java/org/autojs/autojs/annotation/ReservedForCompatibility.kt +++ b/app/src/main/java/org/autojs/autojs/annotation/ReservedForCompatibility.kt @@ -1,4 +1,3 @@ -package org.autojs.autojs.annotation; +package org.autojs.autojs.annotation -public @interface ReservedForCompatibility { -} +annotation class ReservedForCompatibility diff --git a/app/src/main/java/org/autojs/autojs/extension/ArrayExtensions.kt b/app/src/main/java/org/autojs/autojs/extension/ArrayExtensions.kt index 8b4e83ec..76eb581a 100644 --- a/app/src/main/java/org/autojs/autojs/extension/ArrayExtensions.kt +++ b/app/src/main/java/org/autojs/autojs/extension/ArrayExtensions.kt @@ -1,5 +1,6 @@ package org.autojs.autojs.extension +import org.autojs.autojs.extension.AnyExtensions.jsBrief import org.autojs.autojs.util.RhinoUtils.UNDEFINED import org.autojs.autojs.util.RhinoUtils.newNativeObject import org.autojs.autojs.util.RhinoUtils.withRhinoContext @@ -84,4 +85,9 @@ object ArrayExtensions { } } + fun Array.jsArrayBrief(separator: String = ", ", appendPaddingSpace: Boolean = true) = when (appendPaddingSpace) { + true -> "[ ${this.joinToString(separator) { it.jsBrief() }} ]" + else -> "[${this.joinToString(separator) { it.jsBrief() }}]" + } + } diff --git a/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt b/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt index 7e1d00c8..5caadec1 100644 --- a/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt +++ b/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt @@ -1,8 +1,10 @@ package org.autojs.autojs.extension +import java.math.RoundingMode + object NumberExtensions { - val Number.string + val Number.jsString get() = when (this) { is Double -> when { this % 1.0 == 0.0 -> "%.0f".format(this) @@ -15,4 +17,23 @@ object NumberExtensions { else -> this.toString() } + @JvmStatic + @JvmOverloads + fun Double.roundToString(scale: Int, stripTrailingZeros: Boolean = true): String { + return toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .let { if (stripTrailingZeros) it.stripTrailingZeros() else it } + .toPlainString() + } + + @JvmStatic + @JvmOverloads + fun Double.roundToAlphaString(scale: Int = 2, keepTrailingZeroForFullAlpha: Boolean = true): String { + return toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .stripTrailingZeros() + .toPlainString() + .let { if (keepTrailingZeroForFullAlpha && it == "1") "1.0" else it } + } + } diff --git a/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt b/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt index c6e0a324..ea688345 100644 --- a/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt +++ b/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt @@ -4,6 +4,22 @@ import java.text.Normalizer object StringExtensions { + val String.estimateVisualWidth: Int + get() { + var width = 0 + var i = 0 + while (i < length) { + // 取 code point (可能是两位 surrogates 拼成一个 code point) + val cp = codePointAt(i) + // 移动下标, 跳过组合过的 surrogate + i += Character.charCount(cp) + + // 简易判断: 东亚全宽/Emoji 等 + width += if (isLikelyFullwidth(cp)) 2 else 1 + } + return width + } + fun String.toDoubleOrNaN() = this.toDoubleOrNull() ?: Double.NaN fun String.padStart(length: Int, padStr: String) = when { @@ -34,4 +50,14 @@ object StringExtensions { .lowercase() } + private fun isLikelyFullwidth(codePoint: Int) = when (codePoint) { + // CJK 中日韩统一表意文字 + in 0x4E00..0x9FFF -> true + // 常见的 Emoji 起始, 又或者判断 Character.getType(cp) + in 0x1F300..0x1FAFF -> true + // East Asian Fullwidth, Wide 等范围, 可参考 EastAsianWidth.txt + else -> false + } + + } diff --git a/app/src/main/java/org/autojs/autojs/runtime/ConsoleTimeTable.kt b/app/src/main/java/org/autojs/autojs/runtime/ConsoleTimeTable.kt index 05354296..f55c7571 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/ConsoleTimeTable.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/ConsoleTimeTable.kt @@ -1,7 +1,7 @@ package org.autojs.autojs.runtime import android.os.SystemClock -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.runtime.api.augment.console.Console import java.util.concurrent.ConcurrentHashMap @@ -17,7 +17,7 @@ class ConsoleTimeTable(private val scriptRuntime: ScriptRuntime) { @Synchronized fun print(label: String? = null) { val gap = SystemClock.uptimeMillis() - (mData[parseLabel(label)] ?: Double.NaN) - Console.log(scriptRuntime, arrayOf("${parseLabel(label)}: ${gap.string}ms")) + Console.log(scriptRuntime, arrayOf("${parseLabel(label)}: ${gap.jsString}ms")) mData.remove(parseLabel(label)) } diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/colors/Colors.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/colors/Colors.kt index b7ac08ef..0b1883e8 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/colors/Colors.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/colors/Colors.kt @@ -14,17 +14,23 @@ import org.autojs.autojs.core.image.ColorDetector import org.autojs.autojs.core.image.ColorTable import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.AnyExtensions.jsSpecies +import org.autojs.autojs.extension.ArrayExtensions.jsArrayBrief import org.autojs.autojs.extension.ArrayExtensions.toNativeArray import org.autojs.autojs.extension.ArrayExtensions.toNativeObject -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.FlexibleArray.Companion.component1 +import org.autojs.autojs.extension.FlexibleArray.Companion.component2 +import org.autojs.autojs.extension.NumberExtensions.jsString +import org.autojs.autojs.extension.NumberExtensions.roundToAlphaString import org.autojs.autojs.extension.ScriptableExtensions.prop +import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.api.augment.SimpleGetterProxy import org.autojs.autojs.runtime.api.augment.jsox.Numberx -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.theme.ThemeColor import org.autojs.autojs.util.ColorUtils +import org.autojs.autojs.util.RhinoUtils.coerceBoolean import org.autojs.autojs.util.RhinoUtils.ensureNativeArrayLength import org.autojs.autojs.util.RhinoUtils.newNativeObject import org.mozilla.javascript.Context @@ -32,7 +38,6 @@ import org.mozilla.javascript.NativeArray import org.mozilla.javascript.NativeObject import org.mozilla.javascript.Scriptable import org.mozilla.javascript.Scriptable.NOT_FOUND -import java.math.RoundingMode import java.util.function.Supplier import kotlin.math.abs import kotlin.math.roundToInt @@ -122,6 +127,13 @@ object Colors : Augmentable(), SimpleGetterProxy { ::toHsva.name, ::toHsl.name, ::toHsla.name, + ::toRgbString.name, + ::toRgbaString.name, + // ::toArgbString.name, + // ::toHsvString.name, + // ::toHsvaString.name, + // ::toHslString.name, + // ::toHslaString.name, ::isSimilar.name, ::isEqual.name, ::toColorStateList.name, @@ -609,7 +621,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 1 -> rgbRhino(it[0]) 3 -> rgbRhino(it[0], it[1], it[2]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.rgb") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.rgb") } } @@ -647,7 +659,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 1 -> argbRhino(it[0]) 4 -> argbRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.argb") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.argb") } } @@ -687,7 +699,7 @@ object Colors : Augmentable(), SimpleGetterProxy { 1 -> rgbaRhino(it[0]) 2 -> rgbaRhino(it[0], it[1]) 4 -> rgbaRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.rgba") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.rgba") } } @@ -744,7 +756,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 1 -> hsvRhino(it[0]) 3 -> hsvRhino(it[0], it[1], it[2]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.hsv") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.hsv") } } @@ -780,7 +792,7 @@ object Colors : Augmentable(), SimpleGetterProxy { 1 -> hsvaRhino(it[0]) 2 -> hsvaRhino(it[0], it[1]) 4 -> hsvaRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.hsva") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.hsva") } } @@ -829,7 +841,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 1 -> hslRhino(it[0]) 3 -> hslRhino(it[0], it[1], it[2]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.hsl") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.hsl") } } @@ -865,7 +877,7 @@ object Colors : Augmentable(), SimpleGetterProxy { 1 -> hslaRhino(it[0]) 2 -> hslaRhino(it[0], it[1]) 4 -> hslaRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.hsla") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.hsla") } } @@ -914,7 +926,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 1 -> toRgbRhino(it[0]) 3 -> toRgbRhino(it[0], it[1], it[2]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.rgb") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.rgb") }.toNativeArray() } @@ -949,9 +961,9 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoSingletonFunctionInterface - fun toArgb(args: Array): List = ensureArgumentsLengthInRange(args, 1..2) { + fun toArgb(args: Array): NativeArray = ensureArgumentsLengthInRange(args, 1..2) { val (colorArg, optionsArg) = it - toArgbRhino(colorArg, optionsArg) + toArgbRhino(colorArg, optionsArg).toNativeArray() } @JvmStatic @@ -964,14 +976,14 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoSingletonFunctionInterface - fun toHsv(args: Array) = ensureArgumentsLengthInRange(args, 1..4) { + fun toHsv(args: Array): NativeArray = ensureArgumentsLengthInRange(args, 1..4) { when (it.size) { 1 -> toHsvRhino(it[0]) 2 -> toHsvRhino(it[0], it[1]) 3 -> toHsvRhino(it[0], it[1], it[2]) 4 -> toHsvRhino(it[0], it[1], it[2], it[3]) - else -> ShouldNeverHappenException() - } + else -> throw ShouldNeverHappenException() + }.toNativeArray() } /** @@ -1030,14 +1042,14 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoSingletonFunctionInterface - fun toHsva(args: Array) = ensureArgumentsLengthInRange(args, 1..5) { + fun toHsva(args: Array): NativeArray = ensureArgumentsLengthInRange(args, 1..5) { when (it.size) { 1 -> toHsvaRhino(it[0]) 2 -> toHsvaRhino(it[0], it[1]) 4 -> toHsvaRhino(it[0], it[1], it[2], it[3]) 5 -> toHsvaRhino(it[0], it[1], it[2], it[3], it[4]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.toHsva") - } + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.toHsva") + }.toNativeArray() } /** @@ -1100,14 +1112,14 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoSingletonFunctionInterface - fun toHsl(args: Array) = ensureArgumentsLengthInRange(args, 1..4) { + fun toHsl(args: Array): NativeArray = ensureArgumentsLengthInRange(args, 1..4) { when (it.size) { 1 -> toHslRhino(it[0]) 2 -> toHslRhino(it[0], it[1]) 3 -> toHslRhino(it[0], it[1], it[2]) 4 -> toHslRhino(it[0], it[1], it[2], it[3]) - else -> ShouldNeverHappenException() - } + else -> throw ShouldNeverHappenException() + }.toNativeArray() } /** @@ -1166,12 +1178,12 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoSingletonFunctionInterface - fun toHsla(args: Array) = ensureArgumentsLengthInRange(args, 1..4) { + fun toHsla(args: Array): NativeArray = ensureArgumentsLengthInRange(args, 1..4) { when (it.size) { 1 -> toHslaRhino(it[0]) 4 -> toHslaRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.toHsla") - } + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.toHsla") + }.toNativeArray() } /** @@ -1205,7 +1217,7 @@ object Colors : Augmentable(), SimpleGetterProxy { 2 -> isSimilarRhino(it[0], it[1]) 3 -> isSimilarRhino(it[0], it[1], it[2]) 4 -> isSimilarRhino(it[0], it[1], it[2], it[3]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.isSimilar") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.isSimilar") } } @@ -1268,7 +1280,7 @@ object Colors : Augmentable(), SimpleGetterProxy { when (it.size) { 2 -> isSimilarRhino(it[0], it[1]) 3 -> isSimilarRhino(it[0], it[1], it[2]) - else -> throw WrappedIllegalArgumentException("Invalid arguments \"[$it]\" for colors.isEqual") + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.isEqual") } } @@ -1342,12 +1354,11 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoFunctionBody fun summaryRhino(color: Any?): String { - val (r, g, b, a) = toRgbaRhino(color) - val niceA = when (val doubleA = toDoubleComponent(a)) { - 1.0 -> "1.0" - else -> doubleA.toBigDecimal().setScale(2, RoundingMode.HALF_EVEN).stripTrailingZeros().toPlainString() + var (r, g, b, a) = toRgbaRhino(color) + return when (val doubleA = toDoubleComponent(a)) { + 1.0 -> "Color { ${toHexRhino(color)} | rgb(${r.jsString}, ${g.jsString}, ${b.jsString}) | int(${toIntRhino(color)}) }" + else -> "Color { ${toHexRhino(color)} | rgba(${r.jsString}, ${g.jsString}, ${b.jsString}, ${doubleA.roundToAlphaString()}) | int(${toIntRhino(color)}) }" } - return "Color { hex(${toHexRhino(color)}), rgba(${r.string},${g.string},${b.string}/$niceA), int(${toIntRhino(color)}) }" } internal fun parseRelativePercentage(percentage: Any?): Double { @@ -1432,4 +1443,106 @@ object Colors : Augmentable(), SimpleGetterProxy { return Numberx.clampToRhino(x, listOf(0, 360), 360).toFloat() } + @JvmStatic + @RhinoSingletonFunctionInterface + fun toRgbString(args: Array): String = ensureArgumentsLengthInRange(args, 1..3) { + when (it.size) { + 1 -> toRgbStringRhino(it[0]) + 3 -> toRgbStringRhino(it[0], it[1], it[2]) + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.toRgbString") + } + } + + @JvmStatic + @RhinoFunctionBody + fun toRgbStringRhino(color: Any?): String { + return toRgbRhino(color).joinToString(", ", prefix = "rgb(", postfix = ")") { + it.roundToInt().coerceIn(0..255).toString() + } + } + + @JvmStatic + @RhinoFunctionBody + fun toRgbStringRhino(r: Any?, g: Any?, b: Any?): String { + return toRgbRhino(r, g, b).joinToString(", ", prefix = "rgb(", postfix = ")") { + it.roundToInt().coerceIn(0..255).toString() + } + } + + @JvmStatic + @RhinoSingletonFunctionInterface + fun toRgbaString(args: Array): String = ensureArgumentsAtMost(args, 2) { argList -> + val (color, options) = argList + + var keepTrailingZeroForFullAlpha = true + + when (options) { + is NativeObject -> { + options.inquire("keepTrailingZeroForFullAlpha", ::coerceBoolean)?.let { + keepTrailingZeroForFullAlpha = it + } + } + is Boolean -> { + keepTrailingZeroForFullAlpha = options + } + } + + val list = listOf(redRhino(color), greenRhino(color), blueRhino(color)).map { + it.roundToInt().coerceIn(0..255).toString() + } + alphaDoubleRhino(color).roundToAlphaString(2, keepTrailingZeroForFullAlpha) + list.joinToString(", ", prefix = "rgba(", postfix = ")") + } + + // // 格式化 argb 格式为 "argb(a, r, g, b)" + // fun toArgbString(color: Int): String { + // val arr = rawToArgb(color) + // return "argb(${arr[0]}, ${arr[1]}, ${arr[2]}, ${arr[3]})" + // } + // + // // 格式化 hsv 格式为 "hsv(h, s%, v%)",其中 h 取整,s 和 v 转换为百分比(整数) + // fun toHsvString(color: Int): String { + // val arr = rawToHsv(color) + // val h = arr[0].roundToInt() + // val s = (arr[1] * 100).roundToInt() + // val v = (arr[2] * 100).roundToInt() + // return "hsv($h, ${s}%, ${v}%)" + // } + // + // // 格式化 hsva 格式为 "hsva(h, s%, v%, a)",其中 a 保留两位小数(或整数) + // fun toHsvaString(color: Int): String { + // val arr = rawToHsva(color) + // val h = arr[0].roundToInt() + // val s = (arr[1] * 100).roundToInt() + // val v = (arr[2] * 100).roundToInt() + // val a = arr[3] + // val aStr = if (a % 1.0 == 0.0) + // a.roundToInt().toString() + // else + // String.format("%.2f", a) + // return "hsva($h, ${s}%, ${v}%, $aStr)" + // } + // + // // 格式化 hsl 格式为 "hsl(h, s%, l%)" + // fun toHslString(color: Int): String { + // val arr = rawToHsl(color) + // val h = arr[0].roundToInt() + // val s = (arr[1] * 100).roundToInt() + // val l = (arr[2] * 100).roundToInt() + // return "hsl($h, ${s}%, ${l}%)" + // } + // + // // 格式化 hsla 格式为 "hsla(h, s%, l%, a)" + // fun toHslaString(color: Int): String { + // val arr = rawToHsla(color) + // val h = arr[0].roundToInt() + // val s = (arr[1] * 100).roundToInt() + // val l = (arr[2] * 100).roundToInt() + // val a = arr[3] + // val aStr = if (a % 1.0 == 0.0) + // a.roundToInt().toString() + // else + // String.format("%.2f", a) + // return "hsla($h, ${s}%, ${l}%, $aStr)" + // } + } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt index 7f7c4847..e54a4e2f 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt @@ -6,7 +6,7 @@ import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.core.automator.UiObject import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.AnyExtensions.jsBrief -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.extension.ScriptableExtensions.defineProp import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire @@ -500,7 +500,7 @@ class Global(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti "指定的 AutoJs6 应用版本号需大于 461" } require(BuildConfig.VERSION_CODE >= num.toInt()) { - "AutoJs6 应用版本号需不低于 ${num.string}" + "AutoJs6 应用版本号需不低于 ${num.jsString}" } } } diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/jsox/Numberx.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/jsox/Numberx.kt index 4bcec2f3..ea09f557 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/jsox/Numberx.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/jsox/Numberx.kt @@ -8,7 +8,7 @@ import org.autojs.autojs.extension.AnyExtensions.jsBrief import org.autojs.autojs.extension.ArrayExtensions.toNativeArray import org.autojs.autojs.extension.ArrayExtensions.unshiftWith import org.autojs.autojs.extension.FlexibleArray -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.extension.StringExtensions.padEnd import org.autojs.autojs.extension.StringExtensions.padStart import org.autojs.autojs.extension.StringExtensions.toDoubleOrNaN @@ -276,10 +276,10 @@ class Numberx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt require(!niceTargetLength.isNaN() && niceTargetLength.isFinite()) { "Argument \"targetLength\" for Numberx.padStart must be a number" } val nicePad: String = when { pad.isJsNullish() -> DEFAULT_PADDING_STRING - pad is Number -> pad.toDouble().string + pad is Number -> pad.toDouble().jsString else -> pad.toString() } - return parseAnyRhino(num).string.padStart(niceTargetLength.roundToInt(), nicePad) + return parseAnyRhino(num).jsString.padStart(niceTargetLength.roundToInt(), nicePad) } @JvmStatic @@ -297,10 +297,10 @@ class Numberx(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt require(!niceTargetLength.isNaN() && niceTargetLength.isFinite()) { "Argument \"targetLength\" for Numberx.padEnd must be a number" } val nicePad: String = when { pad.isJsNullish() -> DEFAULT_PADDING_STRING - pad is Number -> pad.toDouble().string + pad is Number -> pad.toDouble().jsString else -> pad.toString() } - return parseAnyRhino(num).string.padEnd(niceTargetLength.roundToInt(), nicePad) + return parseAnyRhino(num).jsString.padEnd(niceTargetLength.roundToInt(), nicePad) } @JvmStatic diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Inspect.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Inspect.kt index c776410f..78485071 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Inspect.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Inspect.kt @@ -7,7 +7,7 @@ import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.ArrayExtensions.toNativeObject import org.autojs.autojs.extension.FlexibleArray.Companion.component1 import org.autojs.autojs.extension.FlexibleArray.Companion.component2 -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_GETTER_KEY import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_SETTER_KEY @@ -542,7 +542,7 @@ object Inspect : Augmentable(), Invokable { ctx.stylize(content, "string") } value is Number -> { - ctx.stylize(value.string, "number") + ctx.stylize(value.jsString, "number") } value is Boolean -> { ctx.stylize(Context.toString(value), "boolean") diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Util.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Util.kt index 68cc185e..bda079b1 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Util.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/Util.kt @@ -20,7 +20,7 @@ import org.autojs.autojs.extension.AnyExtensions.isJsSymbol import org.autojs.autojs.extension.AnyExtensions.isJsUndefined import org.autojs.autojs.extension.AnyExtensions.jsBrief import org.autojs.autojs.extension.FlexibleArray -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.extension.ScriptableExtensions.defineProp import org.autojs.autojs.runtime.api.augment.Augmentable @@ -352,7 +352,7 @@ object Util : Augmentable() { when (matchResult.value) { "%s" -> Context.toString(args[index++]) - "%d" -> Context.toNumber(args[index++]).string + "%d" -> Context.toNumber(args[index++]).jsString "%j" -> try { Context.toString(js_json_stringify(args[index++])) } catch (e: Exception) { diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/VersionCodes.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/VersionCodes.kt index cb98ea54..e293d050 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/VersionCodes.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/util/VersionCodes.kt @@ -5,7 +5,7 @@ import org.autojs.autojs.annotation.RhinoStandardFunctionInterface import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.ArrayExtensions.toNativeArray import org.autojs.autojs.extension.FlexibleArray -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException @@ -81,7 +81,7 @@ object VersionCodes : Augmentable() { val releaseDate: String, ) { private val releaseTimestampLong = parseTimestamp(releaseDate) - val releaseTimestamp = releaseTimestampLong.string + val releaseTimestamp = releaseTimestampLong.jsString fun toNativeObject() = newNativeObject().also { it.put("versionCode", it, versionCode) @@ -171,7 +171,7 @@ object VersionCodes : Augmentable() { private fun normalizeSearcherSource(o: Any) = when (o) { is NativeDate -> wrapNumber(o.date).toString() - is Number -> o.string + is Number -> o.jsString is String -> o else -> throw WrappedIllegalArgumentException("Invalid argument type: $o for versionCodes.search") } diff --git a/app/src/main/java/org/autojs/autojs/theme/ThemeColorManager.kt b/app/src/main/java/org/autojs/autojs/theme/ThemeColorManager.kt index bf52dfb1..3f39ed53 100644 --- a/app/src/main/java/org/autojs/autojs/theme/ThemeColorManager.kt +++ b/app/src/main/java/org/autojs/autojs/theme/ThemeColorManager.kt @@ -94,6 +94,11 @@ object ThemeColorManager { ViewUtils.setStatusBarBackgroundColor(activity, colorPrimary) } + @JvmStatic + fun setStatusBarAppearanceLight(activity: Activity) { + ViewUtils.setStatusBarAppearanceLight(activity, isLuminanceDark()) + } + private object BackgroundColorManager { private val views: MutableList> = LinkedList() diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorItemAdapter.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorItemAdapter.kt new file mode 100644 index 00000000..0e7f5bd3 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorItemAdapter.kt @@ -0,0 +1,128 @@ +package org.autojs.autojs.theme.app + +import android.animation.ValueAnimator +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.autojs.autojs.core.image.ColorItems +import org.autojs.autojs.core.pref.Pref +import org.autojs.autojs.theme.ThemeChangeNotifier +import org.autojs.autojs.theme.ThemeColorManager +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_DEFAULT +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_MATERIAL +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorItem +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_LEGACY_SELECTED_COLOR_INDEX +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_SELECTED_COLOR_LIBRARY_ID +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_SELECTED_COLOR_LIBRARY_ITEM_ID +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.SELECT_NONE +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.customColorPosition +import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.defaultColorPosition +import org.autojs.autojs6.R + +@SuppressLint("NotifyDataSetChanged") +class ColorItemAdapter( + var items: List, + var isLibraryIdentifierAppendedToDesc: Boolean = false, + private val onItemClick: ((PresetColorItem, View) -> Unit)? = null, +) : RecyclerView.Adapter() { + + var selectedItemId = SELECT_NONE + var selectedLibraryId = SELECT_NONE + + fun updateData(newItems: List) { + items = newItems + notifyDataSetChanged() + } + + fun items() = items + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColorItemViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.mt_color_library_recycler_view_item, parent, false) + return ColorItemViewHolder(view) + } + + override fun onBindViewHolder(holder: ColorItemViewHolder, position: Int) { + val itemView = holder.itemView + val context = itemView.context + val item = items[position] + + when (val tag = itemView.tag) { + is ValueAnimator -> { + tag.cancel() + itemView.tag = null + itemView.setBackgroundColor(context.getColor(R.color.window_background)) + } + } + + holder.bind(item, selectedLibraryId, selectedItemId, isLibraryIdentifierAppendedToDesc) + + itemView.setOnClickListener { + savePrefsForLibraries(item) + savePrefsForLegacy(context, item) + + when (selectedItemId) { + SELECT_NONE -> { + selectedLibraryId = item.libraryId + selectedItemId = item.itemId + notifyItemChanged(holder.bindingAdapterPosition) + } + else -> { + val positionBeforeSelection = items().indexOfFirst { + it.libraryId == selectedLibraryId && it.itemId == selectedItemId + } + val positionOfCurrentSelection = holder.bindingAdapterPosition + if (positionBeforeSelection != positionOfCurrentSelection && positionBeforeSelection >= 0) { + notifyItemChanged(positionBeforeSelection) + } + selectedLibraryId = item.libraryId + selectedItemId = item.itemId + notifyItemChanged(positionOfCurrentSelection) + } + } + + ThemeColorManager.setThemeColor(context.getColor(item.colorRes)) + ThemeChangeNotifier.notifyThemeChanged() + + onItemClick?.let { it(item, itemView) } + } + } + + override fun getItemCount() = items.size + + private fun savePrefsForLibraries(colorItem: PresetColorItem) { + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, colorItem.libraryId) + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, colorItem.itemId) + } + + private fun savePrefsForLegacy(context: Context, colorItem: PresetColorItem) { + when (colorItem.libraryId) { + COLOR_LIBRARY_ID_DEFAULT -> { + if (context.getColor(colorItem.colorRes) == context.getColor(R.color.theme_color_default)) { + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, defaultColorPosition) + } else { + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) + } + } + COLOR_LIBRARY_ID_MATERIAL -> { + val index = colorItem.itemId + if (index !in ColorItems.MATERIAL_COLORS.indices) { + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) + } else { + val fixedIndex = maxOf( + defaultColorPosition, + customColorPosition, + ) + 1 + index + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, fixedIndex) + } + } + else -> { + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorItemViewHolder.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorItemViewHolder.kt new file mode 100644 index 00000000..9d61ceea --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorItemViewHolder.kt @@ -0,0 +1,51 @@ +package org.autojs.autojs.theme.app + +import android.content.res.ColorStateList +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.RecyclerView +import org.autojs.autojs.theme.ThemeColorHelper +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorItem +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.presetColorLibraries +import org.autojs.autojs.util.ViewUtils +import org.autojs.autojs6.R + +class ColorItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + private val context = itemView.context + + private val colorView: ImageView = itemView.findViewById(R.id.color) + private val nameView: TextView = itemView.findViewById(R.id.name) + private val descView: TextView = itemView.findViewById(R.id.description) + + fun bind(item: PresetColorItem, selectedLibraryId: Int, selectedItemId: Int, isLibraryIdentifierAppendedToDesc: Boolean) { + val color = context.getColor(item.colorRes) + val colorName = context.getString(item.nameRes) + val colorDesc = String.format("#%06X", 0xFFFFFF and color) + + ThemeColorHelper.setBackgroundColor(colorView, color) + nameView.text = colorName + descView.text = when { + isLibraryIdentifierAppendedToDesc -> { + presetColorLibraries.find { it.id == item.libraryId }?.let { + "${context.getString(it.identifierRes)} | $colorDesc" + } ?: colorDesc + } + else -> colorDesc + } + setChecked(color, selectedLibraryId == item.libraryId && selectedItemId == item.itemId) + } + + fun setChecked(@ColorInt color: Int, checked: Boolean) { + if (checked) { + colorView.setImageResource(R.drawable.mt_ic_check_white_36dp) + val tintRes = if (ViewUtils.isLuminanceLight(color)) R.color.day else R.color.night + colorView.imageTintList = ColorStateList.valueOf(context.getColor(tintRes)) + } else { + colorView.setImageDrawable(null) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibrariesActivity.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibrariesActivity.kt index 223ba383..0cc1605a 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibrariesActivity.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibrariesActivity.kt @@ -2,26 +2,18 @@ package org.autojs.autojs.theme.app import android.annotation.SuppressLint import android.content.Intent -import android.content.res.ColorStateList import android.os.Bundle -import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView -import androidx.appcompat.widget.SearchView +import androidx.core.view.forEach import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.VERTICAL -import com.jaredrummler.android.colorpicker.ColorPickerDialog +import androidx.recyclerview.widget.ThemeColorRecyclerView import org.autojs.autojs.core.image.ColorItems import org.autojs.autojs.core.pref.Pref import org.autojs.autojs.theme.ThemeChangeNotifier import org.autojs.autojs.theme.ThemeColorManager -import org.autojs.autojs.util.ColorUtils import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByColorLuminance import org.autojs.autojs6.R @@ -32,17 +24,27 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { private lateinit var binding: MtActivityColorLibrariesBinding - private lateinit var mAdapter: ColorLibraryAdapter + private lateinit var mRecyclerView: ThemeColorRecyclerView - private val customColor: Int - get() = Pref.getInt(KEY_CUSTOM_COLOR, getColor(R.color.custom_color_default)) + private val libraryAdapter: ColorLibraryAdapter by lazy { + ColorLibraryAdapter(presetColorLibraries) { library -> + val intent = Intent(this, ColorLibraryActivity::class.java) + intent.putExtra(INTENT_IDENTIFIER_LIBRARY_ID, library.id) + startActivity(intent) + } + } + + private val colorItemAdapter: ColorItemAdapter by lazy { + ColorItemAdapter(presetColorItems, isLibraryIdentifierAppendedToDesc = true) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ThemeChangeNotifier.themeChanged.observe(this) { - setColor(ThemeColorManager.colorPrimary) - mAdapter.notifyDataSetChanged() + updateAppBarColorContent(ThemeColorManager.colorPrimary) + libraryAdapter.notifyDataSetChanged() + colorItemAdapter.notifyDataSetChanged() } MtActivityColorLibrariesBinding.inflate(layoutInflater).let { @@ -53,12 +55,9 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { } binding.colorLibrariesRecyclerView.let { + mRecyclerView = it it.layoutManager = LinearLayoutManager(this) - it.adapter = ColorLibraryAdapter(colorLibraries) { library -> - val intent = Intent(this, ColorLibraryActivity::class.java) - intent.putExtra(INTENT_IDENTIFIER_LIBRARY_ID, library.id) - startActivity(intent) - }.also { mAdapter = it } + it.adapter = libraryAdapter it.addItemDecoration(DividerItemDecoration(this, VERTICAL)) ViewUtils.excludePaddingClippableViewFromNavigationBar(it) } @@ -69,32 +68,50 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { binding.toolbar.setMenuIconsColorByColorLuminance(this, currentColor) - val searchItem = menu.findItem(R.id.action_search_color) - val searchView = searchItem.actionView as? SearchView - searchView?.queryHint = "搜索颜色库" - searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - filterLibraries(query) - return true + setUpSearchMenu( + menu, + onQueryTextSimpleListener = { query -> + filterColorsFromColorItems(query, presetColorItems, colorItemAdapter) + }, + onMenuItemActionExpand = { + mRecyclerView.adapter = colorItemAdapter + setUpSelectedPosition(colorItemAdapter) + menu.forEach { it.isVisible = it.isVisible.not() } + }, + onMenuItemActionCollapse = { + mRecyclerView.adapter = libraryAdapter + menu.forEach { it.isVisible = it.isVisible.not() } } + )?.apply { queryHint = getString(R.string.text_search_all_colors) } - override fun onQueryTextChange(newText: String?): Boolean { - filterLibraries(newText) - return true - } - }) - return true + return super.onCreateOptionsMenu(menu) } - private fun filterLibraries(query: String?) { - val filteredLibraries = when { - query.isNullOrBlank() -> colorLibraries - else -> colorLibraries.filter { - val name = it.nameString ?: getString(it.nameRes) - name.contains(query, ignoreCase = true) + private fun setUpSelectedPosition(adapter: ColorItemAdapter) { + when (Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE)) { + SELECT_NONE -> when (val legacyIndex = Pref.getInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE)) { + customColorPosition -> Unit + SELECT_NONE, defaultColorPosition -> { + adapter.selectedLibraryId = COLOR_LIBRARY_ID_DEFAULT + adapter.selectedItemId = adapter.items.firstOrNull { + it.libraryId == COLOR_LIBRARY_ID_DEFAULT && getColor(it.colorRes) == getColor(R.color.theme_color_default) + }?.itemId ?: SELECT_NONE + } + else -> when (val calculatedIndex = legacyIndex - maxOf(customColorPosition, defaultColorPosition) - 1) { + in ColorItems.MATERIAL_COLORS.indices -> { + val (colorRes, _) = ColorItems.MATERIAL_COLORS[calculatedIndex] + adapter.selectedLibraryId = COLOR_LIBRARY_ID_MATERIAL + adapter.selectedItemId = adapter.items.firstOrNull { + it.libraryId == COLOR_LIBRARY_ID_MATERIAL && it.colorRes == colorRes + }?.itemId ?: SELECT_NONE + } + } + } + else -> { + adapter.selectedLibraryId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE) + adapter.selectedItemId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, SELECT_NONE) } } - mAdapter.updateData(filteredLibraries) } override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { @@ -102,11 +119,15 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { showColorPicker() true } - R.id.action_search_color -> { + R.id.action_new_color_library -> { ViewUtils.showToast(this, R.string.text_under_development_title) true } - R.id.action_new_color_library -> { + R.id.action_import_color_library -> { + ViewUtils.showToast(this, R.string.text_under_development_title) + true + } + R.id.action_clone_color_library -> { ViewUtils.showToast(this, R.string.text_under_development_title) true } @@ -122,39 +143,6 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { else -> super.onOptionsItemSelected(item) } - private fun showColorPicker() { - ColorPickerDialog.newBuilder() - .setAllowCustom(true) - .setAllowPresets(true) - .setDialogType(ColorPickerDialog.TYPE_CUSTOM) - .setShowAlphaSlider(false) - .setDialogTitle(R.string.dialog_title_color_palette) - .setColor(customColor) - .create() - .setColorPickerDialogListener { dialogId: Int, color: Int -> - savePrefsForLibraries() - savePrefsForLegacy(color) - - binding.toolbar.post { binding.toolbar.subtitle = getCurrentColorSummary(this, true) } - - setColorWithAnimation(color) - - ThemeColorManager.setThemeColor(color) - ThemeChangeNotifier.notifyThemeChanged() - } - .show(supportFragmentManager, "ColorPickerTagForColorLibraries") - } - - private fun savePrefsForLibraries() { - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_CUSTOM_COLOR_ID) - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, 0) - } - - private fun savePrefsForLegacy(color: Int) { - Pref.putInt(KEY_CUSTOM_COLOR, color or -0x1000000) - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, customColorPosition) - } - private fun locateCurrentThemeColor() { checkAndGetTargetInfoForThemeColorLocate()?.let { target -> Intent(this, ColorLibraryActivity::class.java).apply { @@ -166,73 +154,24 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { override fun getSubtitle() = getCurrentColorSummary(this) - inner class ColorLibraryAdapter( - private var libraries: List, - private val onItemClick: (ColorLibrary) -> Unit, - ) : RecyclerView.Adapter() { - - // 当上层需要搜索过滤时调用该方法更新数据 - fun updateData(newLibraries: List) { - libraries = newLibraries - notifyDataSetChanged() - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LibraryViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.mt_color_libraries_recycler_view_item, parent, false) - return LibraryViewHolder(view) - } - - override fun onBindViewHolder(holder: LibraryViewHolder, position: Int) { - val library = libraries[position] - holder.bind(library) - holder.itemView.setOnClickListener { onItemClick(library) } - } - - override fun getItemCount() = libraries.size - - } - - inner class LibraryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - private val colorItemView: ImageView = itemView.findViewById(R.id.library_item) - private val libraryName: TextView = itemView.findViewById(R.id.name) - private val description: TextView = itemView.findViewById(R.id.description) - - fun bind(library: ColorLibrary) { - libraryName.text = library.nameString ?: getString(library.nameRes) - - val size = library.colors.size - description.text = resources.getQuantityString(R.plurals.text_items_total_sum, size, size) - - val adjustedContrastColor = ColorUtils.adjustColorForContrast(getColor(R.color.window_background), ThemeColorManager.colorPrimary, 2.3) - when { - library.id == COLOR_LIBRARY_DEFAULT_COLORS_ID -> { - colorItemView.setImageResource(R.drawable.ic_color_library_default) - } - !library.isUserDefined -> { - colorItemView.setImageResource(R.drawable.ic_color_library_preset) - } - } - colorItemView.imageTintList = ColorStateList.valueOf(adjustedContrastColor) - } - - } - companion object { - const val COLOR_LIBRARY_CUSTOM_COLOR_ID = 0x10001 + const val COLOR_LIBRARY_ID_PALETTE = 0x10001 + const val COLOR_LIBRARY_ID_INTELLIGENT = 0x10002 + const val COLOR_LIBRARY_ID_CREATED = 0x10003 + const val COLOR_LIBRARY_ID_IMPORTED = 0x10004 + const val COLOR_LIBRARY_ID_CLONED = 0x10005 - const val COLOR_LIBRARY_DEFAULT_COLORS_ID = 0x20001 - const val COLOR_LIBRARY_MATERIAL_COLORS_ID = 0x20002 - const val COLOR_LIBRARY_ANDROID_COLORS_ID = 0x20003 - const val COLOR_LIBRARY_CSS_COLORS_ID = 0x20004 - const val COLOR_LIBRARY_WEB_COLORS_ID = 0x20005 + const val COLOR_LIBRARY_ID_DEFAULT = 0x20001 + const val COLOR_LIBRARY_ID_MATERIAL = 0x20002 + const val COLOR_LIBRARY_ID_ANDROID = 0x20003 + const val COLOR_LIBRARY_ID_CSS = 0x20004 + const val COLOR_LIBRARY_ID_WEB = 0x20005 - val colorLibraries by lazy { + val presetColorLibraries by lazy { listOf( - ColorLibrary( - id = COLOR_LIBRARY_DEFAULT_COLORS_ID, + PresetColorLibrary( + id = COLOR_LIBRARY_ID_DEFAULT, nameRes = R.string.color_library_default_colors, titleRes = R.string.color_library_title_default_colors, identifierRes = R.string.color_library_identifier_default_colors, @@ -242,66 +181,80 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { R.color.window_background_light to R.string.window_background_light, R.color.window_background_night to R.string.window_background_night, ).mapIndexed { index, (colorRes, nameRes) -> - ColorItem(index, colorRes, nameRes) + PresetColorItem(index, COLOR_LIBRARY_ID_DEFAULT, colorRes, nameRes) }, ), - ColorLibrary( - id = COLOR_LIBRARY_MATERIAL_COLORS_ID, + PresetColorLibrary( + id = COLOR_LIBRARY_ID_INTELLIGENT, + nameRes = R.string.color_library_intelligent_colors, + titleRes = R.string.color_library_title_intelligent_colors, + identifierRes = R.string.color_library_identifier_intelligent_colors, + colors = emptyList(), + ), + PresetColorLibrary( + id = COLOR_LIBRARY_ID_MATERIAL, nameRes = R.string.color_library_material_design_colors, titleRes = R.string.color_library_title_material_design_colors, identifierRes = R.string.color_library_identifier_material_design_colors, colors = ColorItems.MATERIAL_COLORS.mapIndexed { index, (colorRes, nameRes) -> - ColorItem(index, colorRes, nameRes) + PresetColorItem(index, COLOR_LIBRARY_ID_MATERIAL, colorRes, nameRes) }, ), - ColorLibrary( - id = COLOR_LIBRARY_ANDROID_COLORS_ID, + PresetColorLibrary( + id = COLOR_LIBRARY_ID_ANDROID, nameRes = R.string.color_library_android_colors, titleRes = R.string.color_library_title_android_colors, identifierRes = R.string.color_library_identifier_android_colors, colors = ColorItems.ANDROID_COLORS.mapIndexed { index, (colorRes, nameRes) -> - ColorItem(index, colorRes, nameRes) + PresetColorItem(index, COLOR_LIBRARY_ID_ANDROID, colorRes, nameRes) }, ), - ColorLibrary( - id = COLOR_LIBRARY_CSS_COLORS_ID, + PresetColorLibrary( + id = COLOR_LIBRARY_ID_CSS, nameRes = R.string.color_library_css_colors, titleRes = R.string.color_library_title_css_colors, identifierRes = R.string.color_library_identifier_css_colors, colors = ColorItems.CSS_COLORS.mapIndexed { index, (colorRes, nameRes) -> - ColorItem(index, colorRes, nameRes) + PresetColorItem(index, COLOR_LIBRARY_ID_CSS, colorRes, nameRes) }, ), - ColorLibrary( - id = COLOR_LIBRARY_WEB_COLORS_ID, + PresetColorLibrary( + id = COLOR_LIBRARY_ID_WEB, nameRes = R.string.color_library_web_colors, titleRes = R.string.color_library_title_web_colors, identifierRes = R.string.color_library_identifier_web_colors, colors = ColorItems.WEB_COLORS.mapIndexed { index, (colorRes, nameRes) -> - ColorItem(index, colorRes, nameRes) + PresetColorItem(index, COLOR_LIBRARY_ID_WEB, colorRes, nameRes) }, ), ) } - data class ColorItem( - val id: Int, - val colorRes: Int = R.color.md_black_1000, - val nameRes: Int = R.string.text_unknown, - val colorInt: Int? = null, - val nameString: String? = null, + val presetColorItems by lazy { + presetColorLibraries.flatMap { it.colors } + } + + data class PresetColorItem( + val itemId: Int, + val libraryId: Int, + val colorRes: Int, + val nameRes: Int, ) - data class ColorLibrary( + data class PresetColorLibrary( val id: Int, - val nameRes: Int = R.string.text_color_library, - val titleRes: Int? = null, - val identifierRes: Int? = null, - val nameString: String? = null, - val titleString: String? = null, - val colors: List = emptyList(), - var isUserDefined: Boolean = false, - ) + val nameRes: Int, + val titleRes: Int, + val identifierRes: Int, + val colors: List = emptyList(), + ) { + val isIntelligent get() = id == COLOR_LIBRARY_ID_INTELLIGENT + val isCreated get() = id == COLOR_LIBRARY_ID_CREATED + val isImported get() = id == COLOR_LIBRARY_ID_IMPORTED + val isCloned get() = id == COLOR_LIBRARY_ID_CLONED + val isDefault get() = id == COLOR_LIBRARY_ID_DEFAULT + val isMaterial get() = id == COLOR_LIBRARY_ID_MATERIAL + } } diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryActivity.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryActivity.kt index c1c70235..1b6f6df2 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryActivity.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryActivity.kt @@ -6,18 +6,12 @@ import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.annotation.SuppressLint import android.content.Intent -import android.content.res.ColorStateList import android.graphics.drawable.ColorDrawable import android.os.Bundle -import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView -import androidx.annotation.ColorInt -import androidx.appcompat.widget.SearchView +import androidx.core.view.forEach import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearSmoothScroller @@ -26,14 +20,11 @@ import androidx.recyclerview.widget.RecyclerView.VERTICAL import androidx.recyclerview.widget.ThemeColorRecyclerView import org.autojs.autojs.core.image.ColorItems import org.autojs.autojs.core.pref.Pref -import org.autojs.autojs.theme.ThemeChangeNotifier -import org.autojs.autojs.theme.ThemeColorHelper -import org.autojs.autojs.theme.ThemeColorManager -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_DEFAULT_COLORS_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_MATERIAL_COLORS_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.ColorItem -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.ColorLibrary -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.colorLibraries +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_DEFAULT +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_MATERIAL +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorItem +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorLibrary +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.presetColorLibraries import org.autojs.autojs.util.ColorUtils import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils.onceGlobalLayout @@ -49,69 +40,39 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { private lateinit var binding: MtActivityColorLibraryBinding private lateinit var mAdapter: ColorItemAdapter - private lateinit var mLibrary: ColorLibrary + private lateinit var mLibrary: PresetColorLibrary - private var mInitiallyIdScrollTo by Delegates.notNull() - - private var mSelectedPosition = SELECT_NONE - private var mSelectedColor: Int? = null + private var mInitiallyItemIdScrollTo by Delegates.notNull() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val libraryId = intent.getIntExtra(INTENT_IDENTIFIER_LIBRARY_ID, -1) - val library = colorLibraries.find { it.id == libraryId }?.also { lib -> + val library = presetColorLibraries.find { it.id == libraryId }?.also { lib -> mLibrary = lib } ?: throw RuntimeException("Unknown library id: $libraryId") - mInitiallyIdScrollTo = intent.getIntExtra(INTENT_IDENTIFIER_COLOR_ITEM_ID_SCROLL_TO, -1) + mInitiallyItemIdScrollTo = intent.getIntExtra(INTENT_IDENTIFIER_COLOR_ITEM_ID_SCROLL_TO, -1) MtActivityColorLibraryBinding.inflate(layoutInflater).let { binding = it setContentView(it.root) setUpToolbar(it.toolbar) setUpAppBar(it.appBar, it.appBarContainer) - it.toolbar.title = library.let { - it.titleString - ?: it.titleRes?.let { resId -> getString(resId) } - ?: it.nameString - ?: getString(it.nameRes) - } - if (library.id == Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE)) { - it.toolbar.subtitle = getCurrentColorSummary(this, true) - } + it.toolbar.title = getString(library.titleRes) + updateSubtitle() } binding.colorLibraryRecyclerView.let { it -> it.layoutManager = LinearLayoutManager(this) it.adapter = ColorItemAdapter(library.colors) { colorItem, itemView -> - savePrefsForLibraries(library, colorItem) - savePrefsForLegacy(library, colorItem) - - it.post { binding.toolbar.subtitle = getCurrentColorSummary(this, true) } - - val selectedColor = getColor(colorItem.colorRes).also { mSelectedColor = it } - setColorWithAnimation(selectedColor) - - val adapter = it.adapter as ColorItemAdapter - val currentPosition = it.getChildViewHolder(itemView).bindingAdapterPosition - if (mSelectedPosition != SELECT_NONE) { - adapter.notifyItemChanged(mSelectedPosition) - mSelectedPosition = currentPosition - adapter.notifyItemChanged(currentPosition) - } else { - mSelectedPosition = currentPosition - adapter.notifyDataSetChanged() - } - - ThemeColorManager.setThemeColor(selectedColor) - ThemeChangeNotifier.notifyThemeChanged() + updateAppBarColorContent(getColor(colorItem.colorRes)) }.also { mAdapter = it } it.addItemDecoration(DividerItemDecoration(this, VERTICAL)) ViewUtils.excludePaddingClippableViewFromNavigationBar(it) - setUpSelectedPosition() + setUpSelectedPosition(mAdapter) it.onceGlobalLayout { scrollToPositionOnceIfNeeded(it) @@ -119,36 +80,43 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { } } - private fun setUpSelectedPosition() { + override fun getSubtitle(): String? = when (mLibrary.id) { + Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE) -> { + getCurrentColorSummary(this, true) + } + else -> null + } + + private fun setUpSelectedPosition(adapter: ColorItemAdapter) { when (Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE)) { SELECT_NONE -> when (val legacyIndex = Pref.getInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE)) { customColorPosition -> Unit SELECT_NONE, defaultColorPosition -> when (mLibrary.id) { - COLOR_LIBRARY_DEFAULT_COLORS_ID -> { - val index = mLibrary.colors.indexOfFirst { getColor(it.colorRes) == getColor(R.color.theme_color_default) } - if (index >= 0) mSelectedPosition = index + COLOR_LIBRARY_ID_DEFAULT -> { + adapter.selectedLibraryId = COLOR_LIBRARY_ID_DEFAULT + adapter.selectedItemId = mLibrary.colors.firstOrNull { getColor(it.colorRes) == getColor(R.color.theme_color_default) }?.itemId ?: SELECT_NONE } } else -> when (val calculatedIndex = legacyIndex - maxOf(customColorPosition, defaultColorPosition) - 1) { in ColorItems.MATERIAL_COLORS.indices -> { val (colorRes, _) = ColorItems.MATERIAL_COLORS[calculatedIndex] - val index = mLibrary.colors.indexOfFirst { it.colorRes == colorRes } - if (index >= 0) mSelectedPosition = index + adapter.selectedLibraryId = COLOR_LIBRARY_ID_MATERIAL + adapter.selectedItemId = mLibrary.colors.firstOrNull { it.colorRes == colorRes }?.itemId ?: SELECT_NONE } } } mLibrary.id -> { - val libraryItemId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, SELECT_NONE) - mSelectedPosition = mLibrary.colors.indexOfFirst { it.id == libraryItemId }.takeIf { it != SELECT_NONE } ?: SELECT_NONE + adapter.selectedLibraryId = mLibrary.id + adapter.selectedItemId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, SELECT_NONE) } } } private fun scrollToPositionOnceIfNeeded(recyclerView: ThemeColorRecyclerView) { - if (mInitiallyIdScrollTo < 0) return - val targetPosition = mLibrary.colors.indexOfFirst { it.id == mInitiallyIdScrollTo } + if (mInitiallyItemIdScrollTo < 0) return + val targetPosition = mLibrary.colors.indexOfFirst { it.itemId == mInitiallyItemIdScrollTo } if (targetPosition < 0) { - mInitiallyIdScrollTo = -1 + mInitiallyItemIdScrollTo = -1 return } val targetItem = mLibrary.colors[targetPosition] @@ -174,10 +142,10 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { manager.startSmoothScroll(smoothScroller) } ?: recyclerView.smoothScrollToPosition(targetPosition) - mInitiallyIdScrollTo = -1 + mInitiallyItemIdScrollTo = -1 } - private fun highlightColorItem(recyclerView: RecyclerView, targetPosition: Int, targetItem: ColorItem) { + private fun highlightColorItem(recyclerView: RecyclerView, targetPosition: Int, targetItem: PresetColorItem) { val viewHolder = recyclerView.findViewHolderForAdapterPosition(targetPosition) viewHolder?.itemView?.let { itemView -> val originalColor = (itemView.background as? ColorDrawable)?.color ?: getColor(R.color.window_background) @@ -229,79 +197,22 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { animator.start() } - private fun savePrefsForLibraries(library: ColorLibrary?, colorItem: ColorItem) { - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, library?.id ?: -1) - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, colorItem.id) - } - - private fun savePrefsForLegacy(library: ColorLibrary?, colorItem: ColorItem) { - when (library?.id) { - COLOR_LIBRARY_DEFAULT_COLORS_ID -> { - if (getColor(colorItem.colorRes) == getColor(R.color.theme_color_default)) { - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, defaultColorPosition) - } else { - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) - } - } - COLOR_LIBRARY_MATERIAL_COLORS_ID -> { - val index = colorItem.id - if (index !in ColorItems.MATERIAL_COLORS.indices) { - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) - } else { - val fixedIndex = maxOf( - defaultColorPosition, - customColorPosition, - ) + 1 + index - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, fixedIndex) - } - } - else -> { - Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) - } - } - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_color_library, menu) binding.toolbar.setMenuIconsColorByColorLuminance(this, currentColor) - val searchItem = menu.findItem(R.id.action_search_color) - val searchView = searchItem.actionView as? SearchView - searchView?.queryHint = "搜索颜色" - searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - filterColors(query) - return true - } + setUpSearchMenu( + menu, + onQueryTextSimpleListener = { query -> filterColorsFromColorItems(query, mLibrary.colors, mAdapter) }, + onMenuItemActionExpand = { menu.forEach { it.isVisible = it.isVisible.not() } }, + onMenuItemActionCollapse = { menu.forEach { it.isVisible = it.isVisible.not() } }, + ) - override fun onQueryTextChange(newText: String?): Boolean { - filterColors(newText) - return true - } - }) - return true - } - - private fun filterColors(@Suppress("unused") query: String?) { - // if (library == null) return - // val filteredColors = if (query.isNullOrBlank()) { - // library!!.colors - // } else { - // library!!.colors.filter { colorItem -> - // // 假设可以通过资源 id 获取对应的字符串显示,再做匹配 - // val name = getString(colorItem.nameRes) - // name.contains(query, ignoreCase = true) - // } - // } - // adapter.updateData(filteredColors) + return super.onCreateOptionsMenu(menu) } override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { - R.id.action_search_color -> { - ViewUtils.showToast(this, R.string.text_under_development_title) - true - } R.id.action_locate_current_theme_color -> { locateCurrentThemeColor() true @@ -323,7 +234,7 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { itemView.setBackgroundColor(getColor(R.color.window_background)) } - mInitiallyIdScrollTo = targetIndex + mInitiallyItemIdScrollTo = targetIndex scrollToPositionOnceIfNeeded(recyclerView) } else -> { @@ -337,65 +248,4 @@ class ColorLibraryActivity : ColorSelectBaseActivity() { } } - inner class ColorItemAdapter( - private var items: List, - private val onItemClick: (ColorItem, View) -> Unit, - ) : RecyclerView.Adapter() { - - fun updateData(newItems: List) { - items = newItems - notifyDataSetChanged() - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColorViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.mt_color_library_recycler_view_item, parent, false) - return ColorViewHolder(view) - } - - override fun onBindViewHolder(holder: ColorViewHolder, position: Int) { - val item = items[position] - - when (val tag = holder.itemView.tag) { - is ValueAnimator -> { - tag.cancel() - holder.itemView.tag = null - holder.itemView.setBackgroundColor(getColor(R.color.window_background)) - } - } - - holder.bind(item, position) - holder.itemView.setOnClickListener { onItemClick(item, holder.itemView) } - } - - override fun getItemCount() = items.size - - } - - inner class ColorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - private val colorView: ImageView = itemView.findViewById(R.id.color) - private val nameView: TextView = itemView.findViewById(R.id.name) - private val descView: TextView = itemView.findViewById(R.id.description) - - fun bind(item: ColorItem, position: Int) { - val color = getColor(item.colorRes) - ThemeColorHelper.setBackgroundColor(colorView, color) - nameView.text = item.nameString ?: getString(item.nameRes) - descView.text = String.format("#%06X", 0xFFFFFF and color) - setChecked(color, mSelectedPosition == position) - } - - fun setChecked(@ColorInt color: Int, checked: Boolean) { - if (checked) { - colorView.setImageResource(R.drawable.mt_ic_check_white_36dp) - val tintRes = if (ViewUtils.isLuminanceLight(color)) R.color.day else R.color.night - colorView.imageTintList = ColorStateList.valueOf(getColor(tintRes)) - } else { - colorView.setImageDrawable(null) - } - } - - } - } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryAdapter.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryAdapter.kt new file mode 100644 index 00000000..8459fe79 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryAdapter.kt @@ -0,0 +1,34 @@ +package org.autojs.autojs.theme.app + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.autojs.autojs6.R + +@SuppressLint("NotifyDataSetChanged") +class ColorLibraryAdapter( + private var libraries: List, + private val onItemClick: (ColorLibrariesActivity.Companion.PresetColorLibrary) -> Unit, +) : RecyclerView.Adapter() { + + fun updateData(newLibraries: List) { + libraries = newLibraries + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColorLibraryViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.mt_color_libraries_recycler_view_item, parent, false) + return ColorLibraryViewHolder(view) + } + + override fun onBindViewHolder(holder: ColorLibraryViewHolder, position: Int) { + val library = libraries[position] + holder.bind(library) + holder.itemView.setOnClickListener { onItemClick(library) } + } + + override fun getItemCount() = libraries.size + +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryViewHolder.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryViewHolder.kt new file mode 100644 index 00000000..357e2454 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryViewHolder.kt @@ -0,0 +1,39 @@ +package org.autojs.autojs.theme.app + +import android.content.res.ColorStateList +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import org.autojs.autojs.theme.ThemeColorManager +import org.autojs.autojs.util.ColorUtils +import org.autojs.autojs6.R + +class ColorLibraryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + private val context = itemView.context + private val resources = itemView.resources + + private val colorItemView: ImageView = itemView.findViewById(R.id.library_item) + private val libraryName: TextView = itemView.findViewById(R.id.name) + private val description: TextView = itemView.findViewById(R.id.description) + + fun bind(library: ColorLibrariesActivity.Companion.PresetColorLibrary) { + libraryName.text = context.getString(library.nameRes) + + val size = library.colors.size + description.text = resources.getQuantityString(R.plurals.text_items_total_sum, size, size) + + val adjustedContrastColor = ColorUtils.adjustColorForContrast(context.getColor(R.color.window_background), ThemeColorManager.colorPrimary, 2.3) + when { + library.isDefault -> colorItemView.setImageResource(R.drawable.ic_color_library_default) + library.isIntelligent -> colorItemView.setImageResource(R.drawable.ic_color_library_intelligent) + library.isCreated -> colorItemView.setImageResource(R.drawable.ic_color_library_created) + library.isImported -> colorItemView.setImageResource(R.drawable.ic_color_library_imported) + library.isCloned -> colorItemView.setImageResource(R.drawable.ic_color_library_cloned) + else -> colorItemView.setImageResource(R.drawable.ic_color_library_preset) + } + colorItemView.imageTintList = ColorStateList.valueOf(adjustedContrastColor) + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectActivity.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectActivity.kt index 19f38887..8aebe4f9 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectActivity.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectActivity.kt @@ -23,7 +23,7 @@ class ColorSelectActivity : ColorSelectBaseActivity() { override fun onItemClick(v: View?, position: Int) { mColorSettingRecyclerView.selectedThemeColor?.let { mSelectedPosition = position - setColorWithAnimation(it.colorPrimary) + updateAppBarColorContent(it.colorPrimary) } } } diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectBaseActivity.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectBaseActivity.kt index 797366d7..11fe802f 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectBaseActivity.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorSelectBaseActivity.kt @@ -2,26 +2,43 @@ package org.autojs.autojs.theme.app import android.content.Context import android.content.Intent +import android.content.res.Configuration import android.os.Bundle import android.view.Menu +import android.view.MenuItem import android.view.View import android.view.ViewAnimationUtils +import androidx.annotation.StringRes +import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar +import androidx.lifecycle.lifecycleScope +import com.afollestad.materialdialogs.MaterialDialog import com.google.android.material.appbar.AppBarLayout +import com.jaredrummler.android.colorpicker.ColorPickerDialog import io.codetail.widget.RevealFrameLayout +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.autojs.autojs.annotation.ReservedForCompatibility import org.autojs.autojs.core.image.ColorItems import org.autojs.autojs.core.pref.Pref +import org.autojs.autojs.theme.ThemeChangeNotifier import org.autojs.autojs.theme.ThemeColorManager -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_CUSTOM_COLOR_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.colorLibraries +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_PALETTE +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorItem +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorLibrary +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.presetColorLibraries import org.autojs.autojs.ui.BaseActivity import org.autojs.autojs.util.ColorUtils import org.autojs.autojs.util.ViewUtils +import org.autojs.autojs.util.ViewUtils.onceGlobalLayout +import org.autojs.autojs.util.ViewUtils.setColorsByColorLuminance import org.autojs.autojs.util.ViewUtils.setMenuIconsColorByColorLuminance import org.autojs.autojs.util.ViewUtils.setNavigationIconColorByColorLuminance import org.autojs.autojs.util.ViewUtils.setTitlesTextColorByColorLuminance import org.autojs.autojs6.R +import java.util.* import kotlin.math.hypot import kotlin.properties.Delegates @@ -40,6 +57,12 @@ abstract class ColorSelectBaseActivity : BaseActivity() { private lateinit var mTitle: String + private var mSearchJob: Job? = null + private var mSearchView: SearchView? = null + + private val customColor: Int + get() = Pref.getInt(KEY_CUSTOM_COLOR, getColor(R.color.custom_color_default)) + protected var currentColor by Delegates.notNull() override fun onCreate(savedInstanceState: Bundle?) { @@ -61,27 +84,76 @@ abstract class ColorSelectBaseActivity : BaseActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) } + protected fun setUpSearchMenu(menu: Menu, onQueryTextSimpleListener: (text: String?) -> Unit, onMenuItemActionExpand: (item: MenuItem) -> Unit = {}, onMenuItemActionCollapse: (item: MenuItem) -> Unit = {}): SearchView? { + val menuItem = menu.findItem(R.id.action_search_color) ?: return null + menuItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem) = true.also { + mToolbar.onceGlobalLayout { updateToolbarColors() } + onMenuItemActionExpand(item) + } + + override fun onMenuItemActionCollapse(item: MenuItem) = true.also { + onQueryTextSimpleListener(null) + onMenuItemActionCollapse(item) + } + }) + return setUpSearchMenu(menuItem.actionView, onQueryTextSimpleListener) + } + + private fun setUpSearchMenu(searchView: View?, onQueryTextSimpleListener: (text: String?) -> Unit): SearchView? { + return setUpSearchMenu(searchView, object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?) = true.also { onQueryTextSimpleListener(query) } + override fun onQueryTextChange(newText: String?) = true.also { onQueryTextSimpleListener(newText) } + }) + } + + protected fun setUpSearchMenu(menu: Menu, onQueryTextListener: SearchView.OnQueryTextListener? = null, onMenuItemActionExpand: (item: MenuItem) -> Unit = {}, onMenuItemActionCollapse: (item: MenuItem) -> Unit = {}): SearchView? { + val menuItem = menu.findItem(R.id.action_search_color) ?: return null + menuItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem) = true.also { onMenuItemActionExpand(item) } + override fun onMenuItemActionCollapse(item: MenuItem) = true.also { onMenuItemActionCollapse(item) } + }) + return setUpSearchMenu(menuItem.actionView, onQueryTextListener) + } + + private fun setUpSearchMenu(searchView: View?, onQueryTextListener: SearchView.OnQueryTextListener? = null): SearchView? { + if (searchView !is SearchView) return null + return searchView.apply { + mSearchView = this + queryHint = context.getString(R.string.text_search_color) + setOnQueryTextListener(onQueryTextListener) + } + } + protected open fun getSubtitle(): String? = null override fun initThemeColors() { super.initThemeColors() - mToolbar.setTitlesTextColorByColorLuminance(this, currentColor) - mToolbar.setNavigationIconColorByColorLuminance(this, currentColor) + updateToolbarColors() + updateSearchViewColors() ViewUtils.setStatusBarAppearanceLightByColorLuminance(this, currentColor) } override fun onCreateOptionsMenu(menu: Menu): Boolean { - updateToolbarIconsColor() + updateToolbarColors() + updateSearchViewColors() return super.onCreateOptionsMenu(menu) } - private fun updateToolbarIconsColor() { + private fun updateToolbarColors() { mToolbar.setMenuIconsColorByColorLuminance(this, currentColor) + mToolbar.setNavigationIconColorByColorLuminance(this, currentColor) + mToolbar.setTitlesTextColorByColorLuminance(this, currentColor) } - protected fun setColorWithAnimation(colorTo: Int) { - setColor(colorTo) - ViewAnimationUtils.createCircularReveal( + private fun updateSearchViewColors() { + mSearchView?.setColorsByColorLuminance(this, currentColor) + } + + protected fun updateAppBarColorContent(colorTo: Int) { + setColors(colorTo) + updateSubtitle() + if (hasWindowFocus()) ViewAnimationUtils.createCircularReveal( /* view = */ mAppBarLayout, /* centerX = */ mAppBarLayout.left, /* centerY = */ mAppBarLayout.bottom, @@ -93,14 +165,15 @@ abstract class ColorSelectBaseActivity : BaseActivity() { } } - protected fun setColor(colorTo: Int) { + protected fun updateSubtitle() { + mToolbar.post { mToolbar.subtitle = getSubtitle() } + } + + private fun setColors(colorTo: Int) { mAppBarContainer.setBackgroundColor(currentColor) mAppBarLayout.setBackgroundColor(colorTo) currentColor = colorTo - initThemeColors() - updateToolbarIconsColor() - mToolbar.subtitle = getSubtitle() } protected fun setUpAppBar(appBar: AppBarLayout, appBarContainer: RevealFrameLayout) { @@ -110,42 +183,135 @@ abstract class ColorSelectBaseActivity : BaseActivity() { protected fun checkAndGetTargetInfoForThemeColorLocate(): TargetInfoForLocate? { val targetLibraryId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, -1) - if (targetLibraryId == COLOR_LIBRARY_CUSTOM_COLOR_ID) { - ViewUtils.showToast(this, "当前主题色为自定义颜色", true) - // 提示 - // 当前主题色为自定义颜色 - // - // HEX: #FF3300 - // RGB: 255, 0, 0 - // HSL: 0, 0, 0.14 - // - // 使用调色盘可查看或修改自定义主题颜色 - // 调色盘 关闭 + if (targetLibraryId == COLOR_LIBRARY_ID_PALETTE) { + MaterialDialog.Builder(this) + .title(R.string.text_prompt) + .content(R.string.content_current_theme_color_configured_by_palette, ColorUtils.toHex(currentColor, 6)) + .neutralText(R.string.dialog_button_open_color_palette) + .neutralColorRes(R.color.dialog_button_hint) + .onNeutral { _, _ -> showColorPicker() } + .negativeText(R.string.dialog_button_dismiss) + .negativeColorRes(R.color.dialog_button_default) + .show() return null } - val targetLibrary = colorLibraries.find { it.id == targetLibraryId } + val targetLibrary = presetColorLibraries.find { it.id == targetLibraryId } if (targetLibrary == null) { - ViewUtils.showToast(this, "主题色库定位失败", true) - // 定位失败 - // 无法定位主题色所在颜色库 - // - // Target lib ID: targetLibraryId - // Color libs IDs: [ colorLibraries.sorted().joinToString(", ") { "${it.id}" } ] - // 复制信息 关闭 + MaterialDialog.Builder(this) + .title(R.string.text_failed_to_locate) + .content( + getString(R.string.content_failed_to_locate_library_for_theme_color) + "\n" + + "\n" + + "Target library ID: 0x${targetLibraryId.toString(16)}" + "\n" + + "Color library IDs: [ ${presetColorLibraries.sortedBy { it.id }.joinToString(", ") { "0x${it.id.toString(16)}" }} ]" + ) + .negativeText(R.string.dialog_button_dismiss) + .negativeColorRes(R.color.dialog_button_default) + .show() return null } - val targetIndex = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, -1) - if (targetIndex !in targetLibrary.colors.indices) { - ViewUtils.showToast(this, "主题色条目定位失败", true) - // 定位失败 - // 无法确定主题色条目的索引值 - // - // Target index: targetLibraryId - // Color indicies: [ 0..90 ] (注意 90 为 size - 1) - // 复制信息 关闭 + val targetItemIndex = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, -1) + if (targetItemIndex !in targetLibrary.colors.indices) { + MaterialDialog.Builder(this) + .title(R.string.text_failed_to_locate) + .content( + getString(R.string.content_failed_to_determine_index_of_theme_color_item) + "\n" + + "\n" + + "Target item index: $targetItemIndex" + "\n" + + "Item indicies: [ 0..${targetLibrary.colors.size - 1} ]" + ) + .negativeText(R.string.dialog_button_dismiss) + .negativeColorRes(R.color.dialog_button_default) + .show() return null } - return TargetInfoForLocate(targetLibraryId, targetIndex) + return TargetInfoForLocate(targetLibraryId, targetItemIndex) + } + + protected fun showColorPicker() { + ColorPickerDialog.newBuilder() + .setAllowCustom(true) + .setAllowPresets(true) + .setDialogType(ColorPickerDialog.TYPE_CUSTOM) + .setShowAlphaSlider(false) + .setDialogTitle(R.string.dialog_title_color_palette) + .setColor(customColor) + .create() + .setColorPickerDialogListener { dialogId: Int, color: Int -> + savePrefsForLibraries() + savePrefsForLegacy(color) + + updateAppBarColorContent(color) + + ThemeColorManager.setThemeColor(color) + ThemeChangeNotifier.notifyThemeChanged() + } + .show(supportFragmentManager, "ColorPickerTagForColorLibraries") + } + + private fun savePrefsForLibraries() { + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_ID_PALETTE) + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, 0) + } + + private fun savePrefsForLegacy(color: Int) { + Pref.putInt(KEY_CUSTOM_COLOR, color or -0x1000000) + Pref.putInt(KEY_LEGACY_SELECTED_COLOR_INDEX, customColorPosition) + } + + protected fun filterColorsFromColorItems(query: String?, colorItems: List, colorItemAdapter: ColorItemAdapter) { + mSearchJob?.cancel() + mSearchJob = lifecycleScope.launch { + withContext(Dispatchers.Default) { + if (query.isNullOrBlank()) return@withContext colorItems + val normalizedQuery = normalizeForMatching(query) + colorItems.filter { colorItem -> + val colorHex = String.format("#%06X", 0xFFFFFF and getColor(colorItem.colorRes)) + if (query.startsWith("#")) { + if (isRegexSearch(query.drop(1))) { + val regex = compileRegexOrNull(extractPatternFromQuery(query.drop(1))) ?: return@filter false + return@filter regex.containsMatchIn(colorHex) + } + return@filter colorHex.contains(query, ignoreCase = true) + } + val localName = getString(colorItem.nameRes) + val enName = getLocalizedString(this@ColorSelectBaseActivity, colorItem.nameRes, Locale("en")) + if (isRegexSearch(query)) { + val regex = compileRegexOrNull(extractPatternFromQuery(query)) ?: return@filter false + return@filter regex.containsMatchIn(localName) || regex.containsMatchIn(enName) + } + return@filter normalizeForMatching(localName).contains(normalizedQuery, ignoreCase = true) + || normalizeForMatching(enName).contains(normalizedQuery, ignoreCase = true) + } + }.let { filteredResult -> colorItemAdapter.updateData(filteredResult) } + } + } + + private fun normalizeForMatching(input: String): String { + // 去掉所有非字母或数字字符 (例如空格/括号/斜线等). + // \p{L} 表示任何语言的字母字符, \p{N} 表示数字. + return input.replace("[^\\p{L}\\p{N}]+".toRegex(), "") + } + + private fun getLocalizedString(context: Context, @StringRes resId: Int, locale: Locale): String { + val config = Configuration(context.resources.configuration).apply { setLocale(locale) } + val localizedContext = context.createConfigurationContext(config) + return localizedContext.getString(resId) + } + + private fun isRegexSearch(query: String?): Boolean { + if (query.isNullOrBlank()) return false + return query.length > 2 && query.startsWith("/") && query.endsWith("/") + } + + private fun extractPatternFromQuery(query: String): String { + // 假设已检查过 isRegexSearch() == true + // 去掉最前和最后的斜杠 + return query.substring(1, query.length - 1) + } + + private fun compileRegexOrNull(pattern: String): Regex? { + return runCatching { Regex(pattern, RegexOption.IGNORE_CASE) }.getOrNull() } interface OnItemClickListener { @@ -233,13 +399,13 @@ abstract class ColorSelectBaseActivity : BaseActivity() { val libraryId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ID, SELECT_NONE) val libraryItemId = Pref.getInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, SELECT_NONE) when (libraryId) { - COLOR_LIBRARY_CUSTOM_COLOR_ID -> { - identifier = context.getString(R.string.mt_custom) + COLOR_LIBRARY_ID_PALETTE -> { + identifier = context.getString(R.string.color_library_identifier_palette) } SELECT_NONE -> { val legacyIndex = Pref.getInt(KEY_LEGACY_SELECTED_COLOR_INDEX, SELECT_NONE) when (legacyIndex) { - customColorPosition -> identifier = context.getString(R.string.color_library_identifier_custom) + customColorPosition -> identifier = context.getString(R.string.color_library_identifier_palette) SELECT_NONE, defaultColorPosition -> identifier = context.getString(R.string.color_library_identifier_default_colors) else -> { val calculatedIndex = legacyIndex - maxOf(customColorPosition, defaultColorPosition) - 1 @@ -251,17 +417,43 @@ abstract class ColorSelectBaseActivity : BaseActivity() { } } } - else -> colorLibraries.find { it.id == libraryId }?.let { lib -> + else -> presetColorLibraries.find { it.id == libraryId }?.let { lib: PresetColorLibrary -> identifier = when { - lib.isUserDefined -> context.getString(R.string.color_library_identifier_custom) - else -> lib.identifierRes?.let { resId -> context.getString(resId) } + lib.isCreated -> { + // lib.identifierString?.let { idStr -> + // when { + // idStr.estimateVisualWidth <= 10 -> idStr + // else -> { + // var newStr = idStr + // while (newStr.estimateVisualWidth > 8) { + // newStr = newStr.dropLast(1) + // } + // "$newStr..." + // } + // } + // } ?: lib.titleString?.let { titleStr -> + // when { + // titleStr.estimateVisualWidth <= 10 -> titleStr + // else -> { + // var newStr = titleStr + // while (newStr.estimateVisualWidth > 8) { + // newStr = newStr.dropLast(1) + // } + // "$newStr..." + // } + // } + // } ?: context.getString(R.string.color_library_identifier_created) + context.getString(R.string.color_library_identifier_created) + } + else -> context.getString(lib.identifierRes) } if (libraryItemId != -1) { - lib.colors.find { it.id == libraryItemId }?.let { item -> - colorName = item.nameString - ?: item.nameRes.takeUnless { - it == R.string.text_unknown - }?.let { context.getString(it) } + lib.colors.find { it.itemId == libraryItemId }?.let { item -> + // colorName = item.nameString + // ?: item.nameRes.takeUnless { + // it == R.string.text_unknown + // }?.let { context.getString(it) } + colorName = context.getString(item.nameRes) } } } diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorSettingRecyclerView.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorSettingRecyclerView.kt index 99200df8..12be131d 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorSettingRecyclerView.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorSettingRecyclerView.kt @@ -3,6 +3,7 @@ package org.autojs.autojs.theme.app import android.annotation.SuppressLint import android.content.Context import android.content.res.ColorStateList +import android.graphics.Color import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -20,10 +21,10 @@ import org.autojs.autojs.theme.ThemeChangeNotifier import org.autojs.autojs.theme.ThemeColor import org.autojs.autojs.theme.ThemeColorHelper import org.autojs.autojs.theme.ThemeColorManager -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_CUSTOM_COLOR_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_DEFAULT_COLORS_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_MATERIAL_COLORS_ID -import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.colorLibraries +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_PALETTE +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_DEFAULT +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.COLOR_LIBRARY_ID_MATERIAL +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.presetColorLibraries import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_LEGACY_SELECTED_COLOR_INDEX import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_SELECTED_COLOR_LIBRARY_ID import org.autojs.autojs.theme.app.ColorSelectBaseActivity.Companion.KEY_SELECTED_COLOR_LIBRARY_ITEM_ID @@ -99,22 +100,22 @@ class ColorSettingRecyclerView : ThemeColorRecyclerView { private fun savePrefsForLibraries() { when (mSelectedPosition) { 0 -> { - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_CUSTOM_COLOR_ID) + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_ID_PALETTE) Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, 0) } 1 -> { - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_DEFAULT_COLORS_ID) - colorLibraries.find { it.id == COLOR_LIBRARY_DEFAULT_COLORS_ID }!!.colors.find { colorItem -> + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_ID_DEFAULT) + presetColorLibraries.find { it.isDefault }!!.colors.find { colorItem -> context.getColor(colorItem.colorRes) == context.getColor(R.color.theme_color_default) - }?.let { Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, it.id) } + }?.let { Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, it.itemId) } } else -> { selectedThemeColor?.colorPrimary?.let { c -> - colorLibraries.find { it.id == COLOR_LIBRARY_MATERIAL_COLORS_ID }!!.colors.find { colorItem -> + presetColorLibraries.find { it.isMaterial }!!.colors.find { colorItem -> context.getColor(colorItem.colorRes) == c }?.let { - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_MATERIAL_COLORS_ID) - Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, it.id) + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_ID_MATERIAL) + Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, it.itemId) } } } @@ -143,8 +144,8 @@ class ColorSettingRecyclerView : ThemeColorRecyclerView { .setColor(customColor) .create() .setColorPickerDialogListener { dialogId: Int, color: Int -> - val c = color or -0x1000000 - Pref.putInt(ColorSelectBaseActivity.KEY_CUSTOM_COLOR, c) + val colorWithFullAlpha = color or Color.BLACK + Pref.putInt(ColorSelectBaseActivity.KEY_CUSTOM_COLOR, colorWithFullAlpha) setSelectedPosition(customColorPosition) mOnItemClickListener?.onItemClick(v, customColorPosition) } diff --git a/app/src/main/java/org/autojs/autojs/theme/widget/ThemeColorToolbar.kt b/app/src/main/java/org/autojs/autojs/theme/widget/ThemeColorToolbar.kt index c5a49e13..c8a49f1d 100644 --- a/app/src/main/java/org/autojs/autojs/theme/widget/ThemeColorToolbar.kt +++ b/app/src/main/java/org/autojs/autojs/theme/widget/ThemeColorToolbar.kt @@ -50,7 +50,5 @@ open class ThemeColorToolbar : Toolbar, ThemeColorMutable { navigationIcon?.let { navigationIcon = it.applyColorFilterWith(tintColor) } collapseIcon?.let { collapseIcon = it.applyColorFilterWith(tintColor) } overflowIcon?.let { overflowIcon = it.applyColorFilterWith(tintColor) } - - popupTheme = if (ViewUtils.isLuminanceLight(currentThemeColor)) R.style.PopupMenuThemeLight else R.style.PopupMenuThemeDark } } diff --git a/app/src/main/java/org/autojs/autojs/ui/BaseActivity.kt b/app/src/main/java/org/autojs/autojs/ui/BaseActivity.kt index cfa0faf7..1707fdc2 100644 --- a/app/src/main/java/org/autojs/autojs/ui/BaseActivity.kt +++ b/app/src/main/java/org/autojs/autojs/ui/BaseActivity.kt @@ -98,7 +98,7 @@ abstract class BaseActivity : AppCompatActivity() { } protected fun setUpStatusBarAppearanceLightByThemeColor() { - ViewUtils.setStatusBarAppearanceLight(this, ThemeColorManager.isLuminanceDark()) + ThemeColorManager.setStatusBarAppearanceLight(this) } } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt index d07c9322..41348622 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt +++ b/app/src/main/java/org/autojs/autojs/ui/floating/layoutinspector/NodeInfoView.kt @@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration import org.autojs.autojs.core.accessibility.NodeInfo -import org.autojs.autojs.extension.NumberExtensions.string +import org.autojs.autojs.extension.NumberExtensions.jsString import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.ViewUtils import org.autojs.autojs6.R @@ -68,7 +68,7 @@ class NodeInfoView : RecyclerView { else -> { when (FIELDS[i].name) { "bounds" -> (value as? Rect)?.let { "[ ${it.left}, ${it.top}, ${it.right}, ${it.bottom} ]" } ?: value?.toString() ?: "" - "center" -> (value as? Point)?.let { "[ ${it.x.string}, ${it.y.string} ]" } ?: value?.toString() ?: "" + "center" -> (value as? Point)?.let { "[ ${it.x.jsString}, ${it.y.jsString} ]" } ?: value?.toString() ?: "" else -> value?.toString() ?: "" } } @@ -158,13 +158,13 @@ class NodeInfoView : RecyclerView { result = if (x == x.toLong().toDouble()) { result.replace("%X%", x.toLong().toString()) } else { - result.replace("%X%", "${floor(x).string}, ${ceil(x).string}") + result.replace("%X%", "${floor(x).jsString}, ${ceil(x).jsString}") } result = if (y == y.toLong().toDouble()) { result.replace("%Y%", y.toLong().toString()) } else { - result.replace("%Y%", "${floor(y).string}, ${ceil(y).string}") + result.replace("%Y%", "${floor(y).jsString}, ${ceil(y).jsString}") } return result diff --git a/app/src/main/java/org/autojs/autojs/ui/main/FloatingActionMenu.java b/app/src/main/java/org/autojs/autojs/ui/main/FloatingActionMenu.java index fe552001..155978db 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/FloatingActionMenu.java +++ b/app/src/main/java/org/autojs/autojs/ui/main/FloatingActionMenu.java @@ -33,7 +33,7 @@ public class FloatingActionMenu extends FrameLayout implements View.OnClickListe private static final int[] ICONS = { R.drawable.ic_floating_action_menu_dir, R.drawable.ic_floating_action_menu_file, - R.drawable.ic_import_thick, + R.drawable.ic_file_download_white_cropped, R.drawable.ic_project_white}; private static final int[] LABELS = { diff --git a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.kt b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.kt index 04481835..9d596fd6 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.kt +++ b/app/src/main/java/org/autojs/autojs/ui/main/MainActivity.kt @@ -16,6 +16,7 @@ import android.view.MenuItem import android.view.View import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions import androidx.appcompat.app.ActionBarDrawerToggle +import androidx.appcompat.widget.SearchView import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.Fragment import androidx.viewpager.widget.ViewPager @@ -280,7 +281,7 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity { private fun setUpToolbarColors() { mToolbar.setMenuIconsColorByThemeColorLuminance(this) mToolbar.setNavigationIconColorByThemeColorLuminance(this) - mSearchViewItem?.initThemeColors() + mSearchViewItem?.setColorsByThemeColorLuminance() } private fun setUpTabLayoutColors() { @@ -416,7 +417,10 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity { return super.onMenuItemActionCollapse(item) } }.apply { - setQueryCallback { query: String? -> submitQuery(query) } + setQueryCallback(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?) = true.also { submitQuery(query) } + override fun onQueryTextChange(newText: String?) = true.also { submitQuery(newText) } + }) } } diff --git a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerFragment.kt b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerFragment.kt index fc7b18fb..53fc93f1 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerFragment.kt +++ b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ExplorerFragment.kt @@ -173,7 +173,7 @@ class ExplorerFragment : ViewPagerFragment(0), OnFloatingActionButtonClickListen mExplorerView?.setFilter(null) return } - mExplorerView?.setFilter { item: ExplorerItem -> item.name.contains(event.query) } + mExplorerView?.setFilter { item: ExplorerItem -> item.name.contains(event.query, true) } } override fun onStop() { diff --git a/app/src/main/java/org/autojs/autojs/ui/widget/SearchViewItem.java b/app/src/main/java/org/autojs/autojs/ui/widget/SearchViewItem.java index b5d13c8e..cdce4548 100644 --- a/app/src/main/java/org/autojs/autojs/ui/widget/SearchViewItem.java +++ b/app/src/main/java/org/autojs/autojs/ui/widget/SearchViewItem.java @@ -4,12 +4,9 @@ import android.app.Activity; import android.app.SearchManager; import android.content.Context; import android.view.MenuItem; -import android.widget.EditText; -import android.widget.ImageView; import androidx.appcompat.widget.SearchView; import androidx.core.view.MenuItemCompat; -import org.autojs.autojs.theme.ThemeColorManager; -import org.autojs.autojs6.R; +import org.autojs.autojs.util.ViewUtils; /** * Created by Stardust on Oct 25, 2017. @@ -20,49 +17,33 @@ public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, Se void summitQuery(String query); } - private QueryCallback mQueryCallback; + private SearchView.OnQueryTextListener mQueryCallback; private final MenuItem mSearchMenuItem; + private final SearchView mSearchView; private final Activity mActivity; - private EditText mTextview; - private ImageView mCloseButtonView; - private ImageView mSearchGoButtonView; public SearchViewItem(Activity activity, MenuItem searchMenuItem) { mActivity = activity; mSearchMenuItem = searchMenuItem; SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE); - SearchView searchView = (SearchView) searchMenuItem.getActionView(); - if (searchView == null) { + mSearchView = (SearchView) searchMenuItem.getActionView(); + if (mSearchView == null) { return; } - searchView.setSubmitButtonEnabled(true); - searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName())); - mTextview = searchView.findViewById(androidx.appcompat.R.id.search_src_text); - mCloseButtonView = searchView.findViewById(androidx.appcompat.R.id.search_close_btn); - mSearchGoButtonView = searchView.findViewById(androidx.appcompat.R.id.search_go_btn); - initThemeColors(); + mSearchView.setSubmitButtonEnabled(false); + mSearchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName())); + setColorsByThemeColorLuminance(); MenuItemCompat.setOnActionExpandListener(searchMenuItem, this); - searchView.setOnQueryTextListener(this); + mSearchView.setOnQueryTextListener(this); } - public void initThemeColors() { - boolean isThemeColorLuminanceLight = ThemeColorManager.isLuminanceLight(); - int fullColor = mActivity.getColor(isThemeColorLuminanceLight ? R.color.day_full : R.color.night_full); - int hintColor = mActivity.getColor(isThemeColorLuminanceLight ? R.color.day : R.color.night); - - if (mTextview != null) { - mTextview.setTextColor(fullColor); - mTextview.setHintTextColor(hintColor); - } - if (mCloseButtonView != null) { - mCloseButtonView.setColorFilter(fullColor); - } - if (mSearchGoButtonView != null) { - mSearchGoButtonView.setColorFilter(fullColor); + public void setColorsByThemeColorLuminance() { + if (mSearchView != null) { + ViewUtils.setSearchViewColorsByThemeColorLuminance(mActivity, mSearchView); } } - public void setQueryCallback(QueryCallback queryCallback) { + public void setQueryCallback(SearchView.OnQueryTextListener queryCallback) { mQueryCallback = queryCallback; } @@ -80,21 +61,23 @@ public class SearchViewItem implements MenuItemCompat.OnActionExpandListener, Se if (mQueryCallback == null) { return true; } - mQueryCallback.summitQuery(null); + mQueryCallback.onQueryTextSubmit(null); return true; } @Override public boolean onQueryTextSubmit(String query) { - if (mQueryCallback == null) { - return true; + if (mQueryCallback != null) { + mQueryCallback.onQueryTextSubmit(query); } - mQueryCallback.summitQuery(query); return true; } @Override public boolean onQueryTextChange(String newText) { + if (mQueryCallback != null) { + mQueryCallback.onQueryTextChange(newText); + } return false; } diff --git a/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt b/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt index adc61c80..37fdb596 100644 --- a/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt @@ -14,7 +14,6 @@ import androidx.core.graphics.ColorUtils import org.autojs.autojs.app.GlobalAppContext import org.autojs.autojs.core.image.ColorTable import org.autojs.autojs.theme.ThemeColor -import kotlin.math.pow import kotlin.math.roundToInt import kotlin.text.RegexOption.IGNORE_CASE @@ -57,7 +56,7 @@ object ColorUtils { } @JvmStatic - fun toInt(num: Long) = toInt(toHex(num)) + fun toInt(num: Number) = toInt(toHex(num)) @JvmStatic fun toInt(themeColor: ThemeColor) = toInt(toHex(themeColor)) @@ -72,17 +71,17 @@ object ColorUtils { @JvmStatic @JvmOverloads - fun toHex(num: Long, alpha: String = "auto"): String { + fun toHex(num: Number, alpha: String = "auto"): String { return toHex(toString(toJavaIntegerRange(num)), alpha) } @JvmStatic - fun toHex(num: Long, hasAlpha: Boolean): String { + fun toHex(num: Number, hasAlpha: Boolean): String { return toHex(toString(toJavaIntegerRange(num)), hasAlpha) } @JvmStatic - fun toHex(num: Long, resultLength: Int): String { + fun toHex(num: Number, resultLength: Int): String { return toHex(toString(toJavaIntegerRange(num)), resultLength) } @@ -163,7 +162,7 @@ object ColorUtils { } @JvmStatic - fun toFullHex(num: Long) = toHex(num, 8) + fun toFullHex(num: Number) = toHex(num, 8) @JvmStatic fun toFullHex(themeColor: ThemeColor) = toHex(themeColor, 8) @@ -189,14 +188,16 @@ object ColorUtils { else -> toInt(color) } - private fun toJavaIntegerRange(x: Long): Int { - val t = 2f.pow(32).toLong() - val min = (-2f).pow(31).toLong() - val max = 2f.pow(31 - 1).toLong() - var tmp = x - while (tmp < min) tmp += t - while (tmp > max) tmp -= t - return tmp.toInt() + private fun toJavaIntegerRange(x: Number): Int { + // @Commented by SuperMonster003 on Apr 1, 2025. + // # val t = 2f.pow(32).toLong() + // # val min = (-2f).pow(31).toLong() + // # val max = 2f.pow(31 - 1).toLong() + // # var tmp = x.toLong() + // # while (tmp < min) tmp += t + // # while (tmp > max) tmp -= t + // # return tmp.toInt() + return x.toLong().toInt() } fun toColorStateList(color: String) = ColorStateList.valueOf(toInt(color)) diff --git a/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt b/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt index 6a64905a..e2e1a8d5 100644 --- a/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/ViewUtils.kt @@ -20,23 +20,26 @@ import android.os.Looper import android.util.DisplayMetrics import android.util.TypedValue import android.view.Gravity +import android.view.Menu import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver import android.view.Window import android.view.WindowInsets import android.view.WindowManager +import android.widget.EditText import android.widget.FrameLayout +import android.widget.ImageView import android.widget.Toast import androidx.annotation.IdRes import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat -import androidx.core.view.forEach import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar import org.autojs.autojs.app.GlobalAppContext @@ -44,8 +47,6 @@ import org.autojs.autojs.core.pref.Pref import org.autojs.autojs.theme.ThemeColorManager import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs6.R -import org.autojs.autojs6.R.color.day -import org.autojs.autojs6.R.color.night import kotlin.math.roundToInt /** @@ -186,12 +187,12 @@ object ViewUtils { @JvmStatic fun getDayOrNightColorByLuminance(context: Context, color: Int): Int { - return context.getColor(if (isLuminanceLight(color)) day else night) + return context.getColor(if (isLuminanceLight(color)) R.color.day else R.color.night) } @JvmStatic fun getDayOrNightColorResByLuminance(color: Int): Int { - return if (isLuminanceLight(color)) day else night + return if (isLuminanceLight(color)) R.color.day else R.color.night } @JvmStatic @@ -408,13 +409,19 @@ object ViewUtils { fun Toolbar.setMenuIconsColorByColorLuminance(context: Context, aimColor: Int) { val color = getDayOrNightColorByLuminance(context, aimColor) - this.menu.forEach { menu -> - menu.icon?.let { ic -> menu.icon = ic.applyColorFilterWith(color) } - } + this.menu.setItemsColor(color) this.collapseIcon?.let { this.collapseIcon = it.applyColorFilterWith(color) } this.overflowIcon?.let { this.overflowIcon = it.applyColorFilterWith(color) } } + fun Menu.setItemsColor(color: Int) { + for (i in 0 until size()) { + val menuItem = getItem(i) + menuItem.icon = menuItem.icon?.applyColorFilterWith(color) + menuItem.subMenu?.setItemsColor(color) + } + } + @JvmStatic fun setToolbarMenuIconsColorByColorLuminance(context: Context, toolbar: Toolbar, aimColor: Int) { toolbar.setMenuIconsColorByColorLuminance(context, aimColor) @@ -496,6 +503,41 @@ object ViewUtils { toolbar.setTitlesTextColorByColorLuminance(context, aimColor) } + fun SearchView.setColorsByColorLuminance(context: Context, aimColor: Int) { + val isAimColorLight = isLuminanceLight(aimColor) + val fullColor = context.getColor(if (isAimColorLight) R.color.day_full else R.color.night_full) + val hintColor = context.getColor(if (isAimColorLight) R.color.day_alpha_70 else R.color.night_alpha_70) + + findViewById(androidx.appcompat.R.id.search_src_text).apply { + setTextColor(fullColor) + setHintTextColor(hintColor) + setLinkTextColor(fullColor) + } + findViewById(androidx.appcompat.R.id.search_close_btn)?.apply { + setColorFilter(fullColor) + } + findViewById(androidx.appcompat.R.id.search_mag_icon)?.apply { + setColorFilter(fullColor) + } + findViewById(androidx.appcompat.R.id.search_go_btn)?.apply { + setColorFilter(fullColor) + } + } + + fun SearchView.setColorsByThemeColorLuminance(context: Context) { + this.setColorsByColorLuminance(context, ThemeColorManager.colorPrimary) + } + + @JvmStatic + fun setSearchViewColorsByColorLuminance(context: Context, searchView: SearchView, aimColor: Int) { + searchView.setColorsByColorLuminance(context, aimColor) + } + + @JvmStatic + fun setSearchViewColorsByThemeColorLuminance(context: Context, searchView: SearchView) { + setSearchViewColorsByColorLuminance(context, searchView, ThemeColorManager.colorPrimary) + } + @JvmStatic fun showToast(context: Context, stringRes: Int) = showToast(context, stringRes, false) diff --git a/app/src/main/res/drawable/ic_add_rounded_rectangle_outline_black.png b/app/src/main/res/drawable/ic_add_rounded_rectangle_outline_black.png new file mode 100644 index 00000000..7162815a Binary files /dev/null and b/app/src/main/res/drawable/ic_add_rounded_rectangle_outline_black.png differ diff --git a/app/src/main/res/drawable/ic_color_library_cloned.png b/app/src/main/res/drawable/ic_color_library_cloned.png new file mode 100644 index 00000000..d5e399a8 Binary files /dev/null and b/app/src/main/res/drawable/ic_color_library_cloned.png differ diff --git a/app/src/main/res/drawable/ic_color_library_created.png b/app/src/main/res/drawable/ic_color_library_created.png new file mode 100644 index 00000000..bcb9966a Binary files /dev/null and b/app/src/main/res/drawable/ic_color_library_created.png differ diff --git a/app/src/main/res/drawable/ic_color_library_custom.png b/app/src/main/res/drawable/ic_color_library_custom.png deleted file mode 100644 index 0103cd56..00000000 Binary files a/app/src/main/res/drawable/ic_color_library_custom.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_color_library_imported.png b/app/src/main/res/drawable/ic_color_library_imported.png new file mode 100644 index 00000000..6f9862a7 Binary files /dev/null and b/app/src/main/res/drawable/ic_color_library_imported.png differ diff --git a/app/src/main/res/drawable/ic_color_library_intelligent.png b/app/src/main/res/drawable/ic_color_library_intelligent.png new file mode 100644 index 00000000..082a05e5 Binary files /dev/null and b/app/src/main/res/drawable/ic_color_library_intelligent.png differ diff --git a/app/src/main/res/drawable/ic_color_palette_vector.xml b/app/src/main/res/drawable/ic_color_palette_vector.xml index a073bc4c..dc1ed752 100644 --- a/app/src/main/res/drawable/ic_color_palette_vector.xml +++ b/app/src/main/res/drawable/ic_color_palette_vector.xml @@ -15,12 +15,12 @@ diff --git a/app/src/main/res/drawable/ic_customize.png b/app/src/main/res/drawable/ic_customize.png new file mode 100644 index 00000000..82ac7a9d Binary files /dev/null and b/app/src/main/res/drawable/ic_customize.png differ diff --git a/app/src/main/res/drawable/ic_file_download_black.png b/app/src/main/res/drawable/ic_file_download_black.png new file mode 100644 index 00000000..4547fae5 Binary files /dev/null and b/app/src/main/res/drawable/ic_file_download_black.png differ diff --git a/app/src/main/res/drawable/ic_file_download_white.png b/app/src/main/res/drawable/ic_file_download_white.png new file mode 100644 index 00000000..1e51685e Binary files /dev/null and b/app/src/main/res/drawable/ic_file_download_white.png differ diff --git a/app/src/main/res/drawable/ic_file_download_white_cropped.png b/app/src/main/res/drawable/ic_file_download_white_cropped.png new file mode 100644 index 00000000..5ef38eee Binary files /dev/null and b/app/src/main/res/drawable/ic_file_download_white_cropped.png differ diff --git a/app/src/main/res/drawable/ic_filter.png b/app/src/main/res/drawable/ic_filter.png new file mode 100644 index 00000000..803fff0c Binary files /dev/null and b/app/src/main/res/drawable/ic_filter.png differ diff --git a/app/src/main/res/drawable/ic_import_from_top.png b/app/src/main/res/drawable/ic_import_from_top.png new file mode 100644 index 00000000..7e59a4ed Binary files /dev/null and b/app/src/main/res/drawable/ic_import_from_top.png differ diff --git a/app/src/main/res/drawable/ic_import_from_top_thick.png b/app/src/main/res/drawable/ic_import_from_top_thick.png new file mode 100644 index 00000000..5a55510e Binary files /dev/null and b/app/src/main/res/drawable/ic_import_from_top_thick.png differ diff --git a/app/src/main/res/drawable/ic_regex.png b/app/src/main/res/drawable/ic_regex.png new file mode 100644 index 00000000..344d96e1 Binary files /dev/null and b/app/src/main/res/drawable/ic_regex.png differ diff --git a/app/src/main/res/layout/mt_color_libraries_recycler_view_item.xml b/app/src/main/res/layout/mt_color_libraries_recycler_view_item.xml index 221321d3..d8d7aac9 100644 --- a/app/src/main/res/layout/mt_color_libraries_recycler_view_item.xml +++ b/app/src/main/res/layout/mt_color_libraries_recycler_view_item.xml @@ -17,7 +17,7 @@ android:layout_width="36dp" android:layout_height="36dp" android:layout_marginTop="1dp" - android:src="@drawable/ic_color_library_custom" /> + android:src="@drawable/ic_color_library_created" /> + app:showAsAction="always" /> + android:imeOptions="actionSearch" + android:inputType="text" + app:actionViewClass="androidx.appcompat.widget.SearchView" + app:showAsAction="always|collapseActionView" /> + android:id="@+id/action_add_color_library" + android:title="@string/text_add_color_library"> + + + + + + + + + + + + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_color_library.xml b/app/src/main/res/menu/menu_color_library.xml index 845f9504..d8f9d2b0 100644 --- a/app/src/main/res/menu/menu_color_library.xml +++ b/app/src/main/res/menu/menu_color_library.xml @@ -7,7 +7,10 @@ android:id="@+id/action_search_color" android:title="@string/text_search_color" android:icon="@drawable/ic_search_black_48dp" - app:showAsAction="ifRoom" /> + android:imeOptions="actionSearch" + android:inputType="text" + app:actionViewClass="androidx.appcompat.widget.SearchView" + app:showAsAction="always|collapseActionView" /> Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 4a72a5e9..07054c71 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -919,5 +919,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 84ee50e6..da4b1e14 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -922,5 +922,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 78d8d1f2..c7f3b700 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -922,5 +922,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 113b92f2..08d70d1a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -922,5 +922,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 330c23f4..b6c0371d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -923,5 +923,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index af1a3b6d..fc34d61c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -922,5 +922,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 8c4c2459..b7d83f44 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -921,5 +921,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 601a9f71..1dd646e5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -921,5 +921,20 @@ Default Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index e33e322f..bdfc2311 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -921,5 +921,20 @@ 默认 自定义 调色盘 + 添加颜色库 + 导入颜色库 + 新建智能颜色库 + 克隆颜色库 + 智能颜色库 + 智能颜色 + 智能 + 调色盘 + 自建 + 搜索全部颜色 + 打开调色盘 + 当前主题色 %1$s 由调色盘配置 + 定位失败 + 无法定位主题色所在颜色库 + 无法确定主题色条目的索引值 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0ae4ac32..84ec43ed 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,8 +2,16 @@ #DE212121 + #B3212121 + #9A212121 + #4D212121 + #33212121 @color/md_gray_900 #DEFBFBFB + #B3FBFBFB + #9AFBFBFB + #4DFBFBFB + #33FBFBFB #FBFBFB #DE252525 #252525 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 441b5dd7..6db2b01e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1163,5 +1163,20 @@ WEB Custom Color palette + Add a color library + Import a color library + New intelligent color library + Clone a color library + Intelligent color library + Intelligent colors + Intell. + Palette + Created + Search all colors + Palette + Current theme color %1$s is configured by the color palette + Failed to locate + Failed to locate the color library for the theme color + Failed to determine the index of the theme color item diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 3fcf0227..84e1dae6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -121,7 +121,8 @@