From 5b120d8d2c838f1dae0097e6124ac5dc70b9f10d Mon Sep 17 00:00:00 2001 From: SuperMonster003 Date: Wed, 2 Apr 2025 10:21:27 +0800 Subject: [PATCH] =?UTF-8?q?6.6.2=20-=20Alpha5=20-=20=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E8=89=B2=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=E6=96=B0=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E6=94=AF=E6=8C=81=E6=98=BE=E7=A4=BA=E9=A2=9C=E8=89=B2?= =?UTF-8?q?=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extension/MaterialDialogExtensions.kt | 51 +++ .../autojs/extension/NumberExtensions.kt | 10 - .../autojs/extension/StringExtensions.kt | 1 - .../runtime/api/augment/colors/Colors.kt | 433 ++++++++++-------- .../theme/app/ColorInfoDialogManager.kt | 89 ++++ .../theme/app/ColorLibrariesActivity.kt | 11 +- .../autojs/theme/app/ColorLibraryAdapter.kt | 20 +- .../theme/app/ColorLibraryViewHolder.kt | 16 +- .../theme/app/ColorSelectBaseActivity.kt | 8 + .../org/autojs/autojs/ui/edit/EditorMenu.java | 2 +- .../org/autojs/autojs/ui/log/LogActivity.kt | 2 +- .../ui/main/scripts/ApkInfoDialogManager.kt | 69 +-- .../ui/main/scripts/MediaInfoDialogManager.kt | 43 +- .../java/org/autojs/autojs/util/ColorUtils.kt | 38 ++ .../layout/color_info_dialog_list_item.xml | 369 +++++++++++++++ app/src/main/res/values-ar/strings.xml | 5 +- app/src/main/res/values-en/strings.xml | 5 +- app/src/main/res/values-es/strings.xml | 5 +- app/src/main/res/values-fr/strings.xml | 5 +- app/src/main/res/values-ja/strings.xml | 5 +- app/src/main/res/values-ko/strings.xml | 5 +- app/src/main/res/values-ru/strings.xml | 5 +- app/src/main/res/values-zh-rHK/strings.xml | 5 +- app/src/main/res/values-zh-rTW/strings.xml | 5 +- app/src/main/res/values-zh/strings.xml | 5 +- app/src/main/res/values/strings.xml | 10 +- version.properties | 6 +- 27 files changed, 931 insertions(+), 297 deletions(-) create mode 100644 app/src/main/java/org/autojs/autojs/extension/MaterialDialogExtensions.kt create mode 100644 app/src/main/java/org/autojs/autojs/theme/app/ColorInfoDialogManager.kt create mode 100644 app/src/main/res/layout/color_info_dialog_list_item.xml diff --git a/app/src/main/java/org/autojs/autojs/extension/MaterialDialogExtensions.kt b/app/src/main/java/org/autojs/autojs/extension/MaterialDialogExtensions.kt new file mode 100644 index 00000000..fca4d102 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/extension/MaterialDialogExtensions.kt @@ -0,0 +1,51 @@ +package org.autojs.autojs.extension + +import android.view.View +import android.widget.TextView +import com.afollestad.materialdialogs.MaterialDialog +import org.autojs.autojs.util.ClipboardUtils +import org.autojs.autojs.util.IntentUtils +import org.autojs.autojs.util.ViewUtils +import org.autojs.autojs6.R + +object MaterialDialogExtensions { + + fun MaterialDialog.makeSettingsLaunchable(viewGetter: (dialog: MaterialDialog) -> View?, packageName: String?) { + viewGetter(this)?.setOnClickListener { + packageName?.let { pkg -> + IntentUtils.goToAppDetailSettings(this.context, pkg) + } ?: ViewUtils.showSnack(this.view, R.string.error_app_not_installed) + } + } + + fun MaterialDialog.makeTextCopyable(textViewGetter: (dialog: MaterialDialog) -> TextView?) { + makeTextCopyable(textViewGetter(this)) + } + + fun MaterialDialog.makeTextCopyable(textView: TextView?, textValue: String? = textView?.text?.toString()) { + if (textValue != null) { + val context = this.context + textView?.setOnClickListener { + ClipboardUtils.setClip(context, textValue) + ViewUtils.showSnack(this.view, "${context.getString(R.string.text_already_copied_to_clip)}: $textValue") + } + } + } + + fun TextView.setCopyableTextIfAbsent(dialog: MaterialDialog, f: () -> String?) { + val textView = this + val textValue = f.invoke() + if (textView.text == context.getString(R.string.ellipsis_six)) { + textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown) + } + dialog.makeTextCopyable(textView, textValue) + } + + fun TextView.setCopyableText(dialog: MaterialDialog, f: () -> String?) { + val textView = this + val textValue = f.invoke() + textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown) + dialog.makeTextCopyable(textView, textValue) + } + +} 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 5caadec1..3bb45b64 100644 --- a/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt +++ b/app/src/main/java/org/autojs/autojs/extension/NumberExtensions.kt @@ -26,14 +26,4 @@ object NumberExtensions { .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 ea688345..aee8c628 100644 --- a/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt +++ b/app/src/main/java/org/autojs/autojs/extension/StringExtensions.kt @@ -59,5 +59,4 @@ object StringExtensions { else -> false } - } 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 0b1883e8..835eb021 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 @@ -19,8 +19,6 @@ import org.autojs.autojs.extension.ArrayExtensions.toNativeArray 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.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 @@ -30,6 +28,10 @@ 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.ColorUtils.roundToAlphaString +import org.autojs.autojs.util.ColorUtils.roundToHueString +import org.autojs.autojs.util.ColorUtils.roundToSaturationString +import org.autojs.autojs.util.ColorUtils.roundToValueString import org.autojs.autojs.util.RhinoUtils.coerceBoolean import org.autojs.autojs.util.RhinoUtils.ensureNativeArrayLength import org.autojs.autojs.util.RhinoUtils.newNativeObject @@ -129,11 +131,11 @@ object Colors : Augmentable(), SimpleGetterProxy { ::toHsla.name, ::toRgbString.name, ::toRgbaString.name, - // ::toArgbString.name, - // ::toHsvString.name, - // ::toHsvaString.name, - // ::toHslString.name, - // ::toHslaString.name, + ::toArgbString.name, + ::toHsvString.name, + ::toHsvaString.name, + ::toHslString.name, + ::toHslaString.name, ::isSimilar.name, ::isEqual.name, ::toColorStateList.name, @@ -626,10 +628,10 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - red: ColorComponent
- * - green: ColorComponent
- * - blue: ColorComponent
+ * Parameters + * * red: `ColorComponent` + * * green: `ColorComponent` + * * blue: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -639,9 +641,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - o <1> rgbComponents: [ColorComponent, ColorComponent, ColorComponent]
- * - o <2> color: OmniColor
+ * Parameters + * * o <1> rgbComponents: `[ColorComponent, ColorComponent, ColorComponent]` + * * o <2> color: `OmniColor` */ @JvmStatic @RhinoFunctionBody @@ -664,11 +666,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - alpha: ColorComponent
- * - red: ColorComponent
- * - green: ColorComponent
- * - blue: ColorComponent
+ * Parameters + * * alpha: `ColorComponent` + * * red: `ColorComponent` + * * green: `ColorComponent` + * * blue: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -678,9 +680,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - o <1> argbComponents: [ColorComponent, ColorComponent, ColorComponent, ColorComponent]
- * - o <2> colorHex: String (#AARRGGBB)
+ * Parameters + * * o <1> argbComponents: `[ColorComponent, ColorComponent, ColorComponent, ColorComponent]` + * * o <2> colorHex: `String` (#AARRGGBB) */ @JvmStatic @RhinoFunctionBody @@ -704,11 +706,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - red: ColorComponent
- * - green: ColorComponent
- * - blue: ColorComponent
- * - alpha: ColorComponent
+ * Parameters + * * red: `ColorComponent` + * * green: `ColorComponent` + * * blue: `ColorComponent` + * * alpha: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -718,9 +720,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - rgbComponents: [ColorComponent, ColorComponent, ColorComponent]
- * - alpha: ColorComponent
+ * Parameters + * * rgbComponents: `[ColorComponent, ColorComponent, ColorComponent]` + * * alpha: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -731,9 +733,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - o <1> rgbaComponents: [ColorComponent, ColorComponent, ColorComponent, ColorComponent]
- * - o <2> colorHex: String (#RRGGBBAA)
+ * Parameters + * * o <1> rgbaComponents: `[ColorComponent, ColorComponent, ColorComponent, ColorComponent]` + * * o <2> colorHex: `String` (#RRGGBBAA) */ @JvmStatic @RhinoFunctionBody @@ -761,10 +763,10 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - h: ColorComponent
- * - s: ColorComponent
- * - v: ColorComponent
+ * Parameters + * * h: `ColorComponent` + * * s: `ColorComponent` + * * v: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -774,8 +776,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hsvComponents: [ColorComponent, ColorComponent, ColorComponent]
+ * Parameters + * * hsvComponents: `[ColorComponent, ColorComponent, ColorComponent]` */ @JvmStatic @RhinoFunctionBody @@ -797,11 +799,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - h: ColorComponent
- * - s: ColorComponent
- * - v: ColorComponent
- * - a: ColorComponent
+ * Parameters + * * h: `ColorComponent` + * * s: `ColorComponent` + * * v: `ColorComponent` + * * a: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -811,9 +813,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hsvComponents: [ColorComponent, ColorComponent, ColorComponent]
- * - alpha: ColorComponent
+ * Parameters + * * hsvComponents: `[ColorComponent, ColorComponent, ColorComponent]` + * * alpha: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -824,8 +826,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hsvaComponents: [ColorComponent, ColorComponent, ColorComponent, ColorComponent]
+ * Parameters + * * hsvaComponents: `[ColorComponent, ColorComponent, ColorComponent, ColorComponent]` */ @JvmStatic @RhinoFunctionBody @@ -846,10 +848,10 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - h: ColorComponent
- * - s: ColorComponent
- * - l: ColorComponent
+ * Parameters + * * h: `ColorComponent` + * * s: `ColorComponent` + * * l: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -859,8 +861,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hslComponents: [ColorComponent, ColorComponent, ColorComponent]
+ * Parameters + * * hslComponents: `[ColorComponent, ColorComponent, ColorComponent]` */ @JvmStatic @RhinoFunctionBody @@ -882,11 +884,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - h: ColorComponent
- * - s: ColorComponent
- * - l: ColorComponent
- * - a: ColorComponent
+ * Parameters + * * h: `ColorComponent` + * * s: `ColorComponent` + * * l: `ColorComponent` + * * a: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -896,9 +898,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hslComponents: [ColorComponent, ColorComponent, ColorComponent]
- * - alpha: ColorComponent
+ * Parameters + * * hslComponents: `[ColorComponent, ColorComponent, ColorComponent]` + * * alpha: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -909,8 +911,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - hslaComponents: [ColorComponent, ColorComponent, ColorComponent, ColorComponent]
+ * Parameters + * * hslaComponents: `[ColorComponent, ColorComponent, ColorComponent, ColorComponent]` */ @JvmStatic @RhinoFunctionBody @@ -987,8 +989,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
+ * Parameters + * * color: `OmniColor` */ @JvmStatic @RhinoFunctionBody @@ -997,9 +999,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
- * - hsvResultContainer: java.lang.Float[]
+ * Parameters + * * color: `OmniColor` + * * hsvResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody @@ -1015,10 +1017,10 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -1027,11 +1029,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
- * - hsvResultContainer: java.lang.Float[]
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` + * * hsvResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody @@ -1053,24 +1055,24 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
+ * Parameters + * * color: `OmniColor` */ @JvmStatic @RhinoFunctionBody fun toHsvaRhino(color: Any?): List { - return toHsvaRhino(color, FloatArray(3)) + return toHsvaRhino(color, FloatArray(4)) } /** - * Parameters
- * - color: OmniColor
- * - hsvaResultContainer: java.lang.Float[]
+ * Parameters + * * color: `OmniColor` + * * hsvaResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody fun toHsvaRhino(color: Any?, hsvaResultContainer: Any?): List { - require(hsvaResultContainer is FloatArray) { "Container argument \"hsvaResultContainer\" must be a Java Float Array for colors.toHsva(r, g, b, a, hsvResultContainer)" } + require(hsvaResultContainer is FloatArray) { "Container argument \"hsvaResultContainer\" must be a Java Float Array for colors.toHsva(color, hsvResultContainer)" } val r = redRhino(color) val g = greenRhino(color) val b = blueRhino(color) @@ -1083,11 +1085,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
- * - a: ColorComponent
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` + * * a: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -1096,12 +1098,12 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
- * - a: ColorComponent
- * - hsvaResultContainer: java.lang.Float[]
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` + * * a: `ColorComponent` + * * hsvaResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody @@ -1123,8 +1125,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
+ * Parameters + * * color: `OmniColor` */ @JvmStatic @RhinoFunctionBody @@ -1133,9 +1135,9 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
- * - hslResultContainer: java.lang.Float[]
+ * Parameters + * * color: `OmniColor` + * * hslResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody @@ -1151,10 +1153,10 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -1163,11 +1165,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
- * - hslResultContainer: java.lang.Float[]
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` + * * hslResultContainer: `java.lang.Float[]` */ @JvmStatic @RhinoFunctionBody @@ -1187,8 +1189,8 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - color: OmniColor
+ * Parameters + * * color: `OmniColor` */ @JvmStatic @RhinoFunctionBody @@ -1197,11 +1199,11 @@ object Colors : Augmentable(), SimpleGetterProxy { } /** - * Parameters
- * - r: ColorComponent
- * - g: ColorComponent
- * - b: ColorComponent
- * - a: ColorComponent
+ * Parameters + * * r: `ColorComponent` + * * g: `ColorComponent` + * * b: `ColorComponent` + * * a: `ColorComponent` */ @JvmStatic @RhinoFunctionBody @@ -1353,12 +1355,9 @@ object Colors : Augmentable(), SimpleGetterProxy { @JvmStatic @RhinoFunctionBody - fun summaryRhino(color: Any?): String { - 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)}) }" - } + fun summaryRhino(color: Any?): String = when (alphaDoubleRhino(color)) { + 1.0 -> "Color { ${toHexRhino(color)} | ${toRgbStringRhino(color)} | ${toHslStringRhino(color)} | ${toHsvStringRhino(color)} | int(${toIntRhino(color)}) }" + else -> "Color { ${toHexRhino(color)} | ${toRgbaString(arrayOf(color))} | ${toHslaString(arrayOf(color))} | ${toHsvaString(arrayOf(color))} | int(${toIntRhino(color)}) }" } internal fun parseRelativePercentage(percentage: Any?): Double { @@ -1474,75 +1473,135 @@ object Colors : Augmentable(), SimpleGetterProxy { 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 keepTrailingZeroForFullAlpha = when (options) { + is NativeObject -> options.inquire("keepTrailingZeroForFullAlpha", ::coerceBoolean) != false + is Boolean -> options + else -> true } val list = listOf(redRhino(color), greenRhino(color), blueRhino(color)).map { it.roundToInt().coerceIn(0..255).toString() - } + alphaDoubleRhino(color).roundToAlphaString(2, keepTrailingZeroForFullAlpha) + } + alphaDoubleRhino(color).roundToAlphaString(keepTrailingZeroForFullAlpha = 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)" - // } + @JvmStatic + @RhinoSingletonFunctionInterface + fun toArgbString(args: Array): String = ensureArgumentsAtMost(args, 2) { argList -> + val (color, options) = argList + + val keepTrailingZeroForFullAlpha = when (options) { + is NativeObject -> options.inquire("keepTrailingZeroForFullAlpha", ::coerceBoolean) != false + is Boolean -> options + else -> true + } + + val list = listOf( + alphaDoubleRhino(color).roundToAlphaString(keepTrailingZeroForFullAlpha = keepTrailingZeroForFullAlpha) + ) + listOf(redRhino(color), greenRhino(color), blueRhino(color)).map { + it.roundToInt().coerceIn(0..255).toString() + } + + list.joinToString(", ", prefix = "argb(", postfix = ")") + } + + @JvmStatic + @RhinoSingletonFunctionInterface + fun toHsvString(args: Array): String = ensureArgumentsLengthInRange(args, 1..3) { + when (it.size) { + 1 -> toHsvStringRhino(it[0]) + 3 -> toHsvStringRhino(it[0], it[1], it[2]) + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.toHsvString") + } + } + + @JvmStatic + @RhinoFunctionBody + fun toHsvStringRhino(color: Any?): String { + val (r, g, b) = toRgbRhino(color) + return toHsvStringRhino(r, g, b) + } + + @JvmStatic + @RhinoFunctionBody + fun toHsvStringRhino(r: Any?, g: Any?, b: Any?): String { + val (hue, saturation, value) = toHsvRhino(r, g, b) + return listOf( + hue.roundToHueString(), + saturation.roundToSaturationString(), + value.roundToValueString(), + ).joinToString(", ", prefix = "hsv(", postfix = ")") + } + + @JvmStatic + @RhinoSingletonFunctionInterface + fun toHsvaString(args: Array): String = ensureArgumentsAtMost(args, 2) { argList -> + val (color, options) = argList + val (hue, saturation, value) = toHsvRhino(color) + + val keepTrailingZeroForFullAlpha = when (options) { + is NativeObject -> options.inquire("keepTrailingZeroForFullAlpha", ::coerceBoolean) != false + is Boolean -> options + else -> true + } + + val list = listOf( + hue.roundToHueString(), + saturation.roundToSaturationString(), + value.roundToValueString(), + ) + alphaDoubleRhino(color).roundToAlphaString(keepTrailingZeroForFullAlpha = keepTrailingZeroForFullAlpha) + + list.joinToString(", ", prefix = "hsva(", postfix = ")") + } + + @JvmStatic + @RhinoSingletonFunctionInterface + fun toHslString(args: Array): String = ensureArgumentsLengthInRange(args, 1..3) { + when (it.size) { + 1 -> toHslStringRhino(it[0]) + 3 -> toHslStringRhino(it[0], it[1], it[2]) + else -> throw WrappedIllegalArgumentException("Invalid arguments ${it.jsArrayBrief()} for colors.toHslString") + } + } + + @JvmStatic + @RhinoFunctionBody + fun toHslStringRhino(color: Any?): String { + val (r, g, b) = toRgbRhino(color) + return toHslStringRhino(r, g, b) + } + + @JvmStatic + @RhinoFunctionBody + fun toHslStringRhino(r: Any?, g: Any?, b: Any?): String { + val (hue, saturation, lightness) = toHslRhino(r, g, b) + return listOf( + hue.roundToHueString(), + saturation.roundToSaturationString(), + lightness.roundToValueString(), + ).joinToString(", ", prefix = "hsl(", postfix = ")") + } + + @JvmStatic + @RhinoSingletonFunctionInterface + fun toHslaString(args: Array): String = ensureArgumentsAtMost(args, 2) { argList -> + val (color, options) = argList + val (hue, saturation, lightness) = toHslRhino(color) + + val keepTrailingZeroForFullAlpha = when (options) { + is NativeObject -> options.inquire("keepTrailingZeroForFullAlpha", ::coerceBoolean) != false + is Boolean -> options + else -> true + } + + val list = listOf( + hue.roundToHueString(), + saturation.roundToSaturationString(), + lightness.roundToValueString(), + ) + alphaDoubleRhino(color).roundToAlphaString(keepTrailingZeroForFullAlpha = keepTrailingZeroForFullAlpha) + + list.joinToString(", ", prefix = "hsla(", postfix = ")") + } } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/theme/app/ColorInfoDialogManager.kt b/app/src/main/java/org/autojs/autojs/theme/app/ColorInfoDialogManager.kt new file mode 100644 index 00000000..dd6269ad --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorInfoDialogManager.kt @@ -0,0 +1,89 @@ +package org.autojs.autojs.theme.app + +import android.content.Context +import android.view.LayoutInflater +import android.view.View.MeasureSpec.UNSPECIFIED +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible +import com.afollestad.materialdialogs.MaterialDialog +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText +import org.autojs.autojs.runtime.api.augment.colors.Colors +import org.autojs.autojs.util.ColorUtils +import org.autojs.autojs6.R +import org.autojs.autojs6.databinding.ColorInfoDialogListItemBinding + +object ColorInfoDialogManager { + + @JvmStatic + fun showColorInfoDialog(context: Context, @ColorInt color: Int, titleRes: Int = R.string.dialog_title_color_details) { + val binding = ColorInfoDialogListItemBinding.inflate(LayoutInflater.from(context)) + + val colorWithoutAlpha = color or -0x1000000 + + val dialog = MaterialDialog.Builder(context) + .title(titleRes) + .customView(binding.root, false) + .positiveText(R.string.dialog_button_dismiss) + .positiveColorRes(R.color.dialog_button_default) + .show() + + CoroutineScope(Dispatchers.Main).launch { + launch(Dispatchers.IO) { + ColorUtils.toHex(colorWithoutAlpha).let { binding.colorHexValue.bindWith(dialog, it) } + Colors.toRgbStringRhino(colorWithoutAlpha).let { binding.colorRgbValue.bindWith(dialog, it) } + Colors.toHslStringRhino(colorWithoutAlpha).let { binding.colorHslValue.bindWith(dialog, it) } + Colors.toHsvStringRhino(colorWithoutAlpha).let { binding.colorHsvValue.bindWith(dialog, it) } + ColorUtils.toInt(colorWithoutAlpha).let { binding.colorIntValue.bindWith(dialog, it.toString()) } + } + withContext(Dispatchers.Main) { + restoreEssentialViews(binding) + updateGuidelines(binding) + } + } + } + + private fun restoreEssentialViews(binding: ColorInfoDialogListItemBinding) { + listOf( + binding.colorHexColon to binding.colorHexValue, + binding.colorRgbColon to binding.colorRgbValue, + binding.colorHslColon to binding.colorHslValue, + binding.colorHsvColon to binding.colorHsvValue, + binding.colorIntColon to binding.colorIntValue, + ).forEach { pair -> + val (colonView, valueView) = pair + colonView.isVisible = true + valueView.isVisible = true + } + } + + private fun updateGuidelines(binding: ColorInfoDialogListItemBinding) { + val filteredBindings = listOf( + binding.colorHexLabel to binding.colorHexGuideline, + binding.colorRgbLabel to binding.colorRgbGuideline, + binding.colorHslLabel to binding.colorHslGuideline, + binding.colorHsvLabel to binding.colorHsvGuideline, + binding.colorIntLabel to binding.colorIntGuideline, + ).filter { (it.first.parent as? ConstraintLayout)?.isVisible == true } + + val maxWidth = filteredBindings.maxOfOrNull { it.first.apply { measure(UNSPECIFIED, UNSPECIFIED) }.measuredWidth } ?: return + + filteredBindings.forEach { (_, guideline) -> + guideline.layoutParams = (guideline.layoutParams as ConstraintLayout.LayoutParams).also { + it.guideBegin = maxWidth + } + } + } + + private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) { + withContext(Dispatchers.Main) { + this@bindWith.setCopyableText(dialog) { text } + } + } + +} \ 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 0cc1605a..c7a74c57 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 @@ -50,8 +50,11 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { MtActivityColorLibrariesBinding.inflate(layoutInflater).let { binding = it setContentView(it.root) - setUpToolbar(it.toolbar) setUpAppBar(it.appBar, it.appBarContainer) + it.toolbar.let { toolbar -> + setUpToolbar(toolbar) + toolbar.setOnLongClickListener { true.also { showThemeColorDetails() } } + } } binding.colorLibrariesRecyclerView.let { @@ -120,15 +123,15 @@ class ColorLibrariesActivity : ColorSelectBaseActivity() { true } R.id.action_new_color_library -> { - ViewUtils.showToast(this, R.string.text_under_development_title) + ViewUtils.showToast(this, R.string.text_under_development) true } R.id.action_import_color_library -> { - ViewUtils.showToast(this, R.string.text_under_development_title) + ViewUtils.showToast(this, R.string.text_under_development) true } R.id.action_clone_color_library -> { - ViewUtils.showToast(this, R.string.text_under_development_title) + ViewUtils.showToast(this, R.string.text_under_development) true } R.id.action_locate_current_theme_color -> { 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 index 8459fe79..88aabbc2 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryAdapter.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryAdapter.kt @@ -4,15 +4,17 @@ import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import com.afollestad.materialdialogs.MaterialDialog +import org.autojs.autojs.theme.app.ColorLibrariesActivity.Companion.PresetColorLibrary import org.autojs.autojs6.R @SuppressLint("NotifyDataSetChanged") class ColorLibraryAdapter( - private var libraries: List, - private val onItemClick: (ColorLibrariesActivity.Companion.PresetColorLibrary) -> Unit, + private var libraries: List, + private val onItemClick: (PresetColorLibrary) -> Unit, ) : RecyclerView.Adapter() { - fun updateData(newLibraries: List) { + fun updateData(newLibraries: List) { libraries = newLibraries notifyDataSetChanged() } @@ -26,7 +28,17 @@ class ColorLibraryAdapter( override fun onBindViewHolder(holder: ColorLibraryViewHolder, position: Int) { val library = libraries[position] holder.bind(library) - holder.itemView.setOnClickListener { onItemClick(library) } + holder.itemView.setOnClickListener { + when { + library.isIntelligent -> MaterialDialog.Builder(holder.itemView.context) + .title(R.string.text_under_development_title) + .content(R.string.text_under_development_content) + .positiveText(R.string.dialog_button_dismiss) + .positiveColorRes(R.color.dialog_button_default) + .show() + else -> onItemClick(library) + } + } } override fun getItemCount() = libraries.size 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 index 357e2454..c3ecbe43 100644 --- a/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryViewHolder.kt +++ b/app/src/main/java/org/autojs/autojs/theme/app/ColorLibraryViewHolder.kt @@ -1,11 +1,13 @@ package org.autojs.autojs.theme.app +import android.annotation.SuppressLint 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.theme.app.ColorLibrariesActivity.Companion.PresetColorLibrary import org.autojs.autojs.util.ColorUtils import org.autojs.autojs6.R @@ -18,11 +20,19 @@ class ColorLibraryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) private val libraryName: TextView = itemView.findViewById(R.id.name) private val description: TextView = itemView.findViewById(R.id.description) - fun bind(library: ColorLibrariesActivity.Companion.PresetColorLibrary) { + fun bind(library: PresetColorLibrary) { libraryName.text = context.getString(library.nameRes) - val size = library.colors.size - description.text = resources.getQuantityString(R.plurals.text_items_total_sum, size, size) + description.text = when { + library.isIntelligent -> { + @SuppressLint("SetTextI18n") + "[ ${context.getString(R.string.text_under_development)} ]" + } + else -> { + val size = library.colors.size + 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 { 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 11fe802f..907f36a7 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 @@ -249,6 +249,14 @@ abstract class ColorSelectBaseActivity : BaseActivity() { .show(supportFragmentManager, "ColorPickerTagForColorLibraries") } + protected fun showColorDetails(color: Int, titleRes: Int = R.string.dialog_title_color_details) { + ColorInfoDialogManager.showColorInfoDialog(this, color, titleRes) + } + + protected fun showThemeColorDetails() { + showColorDetails(ThemeColorManager.colorPrimary, R.string.dialog_title_theme_color_details) + } + private fun savePrefsForLibraries() { Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ID, COLOR_LIBRARY_ID_PALETTE) Pref.putInt(KEY_SELECTED_COLOR_LIBRARY_ITEM_ID, 0) diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java b/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java index d5da726a..61bbe184 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditorMenu.java @@ -249,7 +249,7 @@ public class EditorMenu { builder.itemsDisabledIndices(i); MaterialDialog built = builder.build(); assert built.getItems() != null; - built.getItems().set(i, built.getItems().get(i) + " (" + builder.getContext().getString(R.string.text_under_development_title).toLowerCase(Language.getPrefLanguage().getLocale()) + ")"); + built.getItems().set(i, built.getItems().get(i) + " (" + builder.getContext().getString(R.string.text_under_development).toLowerCase(Language.getPrefLanguage().getLocale()) + ")"); built.show(); } diff --git a/app/src/main/java/org/autojs/autojs/ui/log/LogActivity.kt b/app/src/main/java/org/autojs/autojs/ui/log/LogActivity.kt index abc6b2ed..48632d2d 100644 --- a/app/src/main/java/org/autojs/autojs/ui/log/LogActivity.kt +++ b/app/src/main/java/org/autojs/autojs/ui/log/LogActivity.kt @@ -69,7 +69,7 @@ class LogActivity : BaseActivity() { } R.id.action_settings -> { // TODO by SuperMonster003 on Jul 3, 2023. - showToast(this, R.string.text_under_development_title) + showToast(this, R.string.text_under_development) } } return true diff --git a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ApkInfoDialogManager.kt b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ApkInfoDialogManager.kt index fa07c46a..c5ecee45 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/scripts/ApkInfoDialogManager.kt +++ b/app/src/main/java/org/autojs/autojs/ui/main/scripts/ApkInfoDialogManager.kt @@ -5,10 +5,7 @@ import android.content.Context import android.content.pm.PackageManager.GET_META_DATA import android.os.Build import android.view.LayoutInflater -import android.view.View import android.view.View.MeasureSpec.UNSPECIFIED -import android.view.ViewGroup -import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import com.afollestad.materialdialogs.DialogAction @@ -19,11 +16,12 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable +import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable +import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableTextIfAbsent import org.autojs.autojs.pio.PFiles import org.autojs.autojs.runtime.api.AppUtils -import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.IntentUtils -import org.autojs.autojs.util.ViewUtils import org.autojs.autojs6.R import org.autojs.autojs6.databinding.ApkFileInfoDialogListItemBinding import java.io.File @@ -36,13 +34,13 @@ object ApkInfoDialogManager { @SuppressLint("SetTextI18n") fun showApkInfoDialog(context: Context, apkFile: File) { val binding = ApkFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context)) - val root = binding.root as ViewGroup val apkFilePath = apkFile.absolutePath + val packageManager = context.packageManager val dialog = MaterialDialog.Builder(context) .title(apkFile.name) - .customView(root, false) + .customView(binding.root, false) .autoDismiss(false) .iconRes(R.drawable.ic_three_dots_outline_small) .limitIconToDefaultSize() @@ -58,8 +56,6 @@ object ApkInfoDialogManager { .onNegative { materialDialog, _ -> materialDialog.dismiss() } .show() - val packageManager = context.packageManager - CoroutineScope(Dispatchers.Main).launch { val packageInfo = withContext(Dispatchers.IO) { runCatching { packageManager.getPackageArchiveInfo(apkFilePath, GET_META_DATA) }.getOrNull() @@ -91,7 +87,7 @@ object ApkInfoDialogManager { val installedPackageName: String? = packageName?.let { pkg -> AppUtils.getInstalledVersionInfo(pkg)?.let { versionInfo -> binding.installedVersionParent.isVisible = true - binding.installedVersionValue.setTextIfAbsent(dialog) { context.getString(R.string.text_full_version_info, versionInfo.versionName, versionInfo.versionCode) } + binding.installedVersionValue.setCopyableTextIfAbsent(dialog) { context.getString(R.string.text_full_version_info, versionInfo.versionName, versionInfo.versionCode) } pkg /* returns as installedPackageName */ } } @@ -102,19 +98,19 @@ object ApkInfoDialogManager { when { versionName != null -> { binding.versionPlaceholderLabel.text = context.getString(R.string.text_version) - binding.versionPlaceholderValue.setTextIfAbsent(dialog) { context.getString(R.string.text_full_version_info, versionName, versionCode) } + binding.versionPlaceholderValue.setCopyableTextIfAbsent(dialog) { context.getString(R.string.text_full_version_info, versionName, versionCode) } } versionCode != null -> { binding.versionPlaceholderLabel.text = context.getString(R.string.text_version_code) - binding.versionPlaceholderValue.setTextIfAbsent(dialog) { "$versionCode" } + binding.versionPlaceholderValue.setCopyableTextIfAbsent(dialog) { "$versionCode" } } - else -> binding.versionPlaceholderValue.setTextIfAbsent(dialog) { null } + else -> binding.versionPlaceholderValue.setCopyableTextIfAbsent(dialog) { null } } - binding.packageNameValue.setTextIfAbsent(dialog) { packageName } - binding.deviceSdkValue.setTextIfAbsent(dialog) { "${Build.VERSION.SDK_INT}" } - binding.fileSizeValue.setTextIfAbsent(dialog) { fileSize } - binding.signatureSchemeValue.setTextIfAbsent(dialog) { signatureScheme } + binding.packageNameValue.setCopyableTextIfAbsent(dialog) { packageName } + binding.deviceSdkValue.setCopyableTextIfAbsent(dialog) { "${Build.VERSION.SDK_INT}" } + binding.fileSizeValue.setCopyableTextIfAbsent(dialog) { fileSize } + binding.signatureSchemeValue.setCopyableTextIfAbsent(dialog) { signatureScheme } dialog.setIcon(applicationInfo?.apply { sourceDir = apkFilePath @@ -126,10 +122,10 @@ object ApkInfoDialogManager { val apkInfo = getApkInfo(apkFile) - binding.labelNameValue.setTextIfAbsent(dialog) { apkInfo?.label } - binding.packageNameValue.setTextIfAbsent(dialog) { apkInfo?.packageName } - binding.minSdkValue.setTextIfAbsent(dialog) { apkInfo?.minSdkVersion?.toString() } - binding.targetSdkValue.setTextIfAbsent(dialog) { apkInfo?.targetSdkVersion?.toString() } + binding.labelNameValue.setCopyableTextIfAbsent(dialog) { apkInfo?.label } + binding.packageNameValue.setCopyableTextIfAbsent(dialog) { apkInfo?.packageName } + binding.minSdkValue.setCopyableTextIfAbsent(dialog) { apkInfo?.minSdkVersion?.toString() } + binding.targetSdkValue.setCopyableTextIfAbsent(dialog) { apkInfo?.targetSdkVersion?.toString() } if (apkInfo != null) dialog.getActionButton(DialogAction.NEUTRAL).let { neutralButton -> neutralButton.isVisible = true @@ -155,37 +151,6 @@ object ApkInfoDialogManager { }.getOrNull() } - private fun MaterialDialog.makeSettingsLaunchable(viewGetter: (dialog: MaterialDialog) -> View?, packageName: String?) { - viewGetter(this)?.setOnClickListener { - packageName?.let { pkg -> - IntentUtils.goToAppDetailSettings(this.context, pkg) - } ?: ViewUtils.showSnack(this.view, R.string.error_app_not_installed) - } - } - - private fun MaterialDialog.makeTextCopyable(textViewGetter: (dialog: MaterialDialog) -> TextView?) { - makeTextCopyable(textViewGetter(this)) - } - - private fun MaterialDialog.makeTextCopyable(textView: TextView?, textValue: String? = textView?.text?.toString()) { - if (textValue != null) { - val context = this.context - textView?.setOnClickListener { - ClipboardUtils.setClip(context, textValue) - ViewUtils.showSnack(this.view, "${context.getString(R.string.text_already_copied_to_clip)}: $textValue") - } - } - } - - private fun TextView.setTextIfAbsent(dialog: MaterialDialog, f: () -> String?) { - val textView = this - val textValue = f.invoke() - if (textView.text == context.getString(R.string.ellipsis_six)) { - textView.text = textValue ?: context.getString(R.string.text_unknown) - } - dialog.makeTextCopyable(textView, textValue) - } - private fun restoreEssentialViews(binding: ApkFileInfoDialogListItemBinding, context: Context) { listOf( Triple(binding.labelNameLabel, binding.labelNameColon, binding.labelNameValue) to R.string.text_label_name, diff --git a/app/src/main/java/org/autojs/autojs/ui/main/scripts/MediaInfoDialogManager.kt b/app/src/main/java/org/autojs/autojs/ui/main/scripts/MediaInfoDialogManager.kt index 48e9ac53..c1a013f4 100644 --- a/app/src/main/java/org/autojs/autojs/ui/main/scripts/MediaInfoDialogManager.kt +++ b/app/src/main/java/org/autojs/autojs/ui/main/scripts/MediaInfoDialogManager.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.Context import android.view.LayoutInflater import android.view.View.MeasureSpec.UNSPECIFIED -import android.view.ViewGroup import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible @@ -16,6 +15,8 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable +import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText import org.autojs.autojs.model.explorer.ExplorerItem import org.autojs.autojs.util.ViewUtils import org.autojs.autojs6.R @@ -33,11 +34,10 @@ object MediaInfoDialogManager { @SuppressLint("SetTextI18n") fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) { val binding = MediaFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context)) - val root = binding.root as ViewGroup val dialog = MaterialDialog.Builder(context) .title(explorerItem.name) - .customView(root, false) + .customView(binding.root, false) .autoDismiss(false) .iconRes(R.drawable.transparent) .limitIconToDefaultSize() @@ -60,38 +60,38 @@ object MediaInfoDialogManager { launch(Dispatchers.IO) { mediaInfo(filePath, GENERAL, "FileSize/String").let { - binding.fileSizeValue.bindWith(it) + binding.fileSizeValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, GENERAL, "Duration/String").let { binding.durationValue.bindWith(it) } + mediaInfo(filePath, GENERAL, "Duration/String").let { binding.durationValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, GENERAL, "Album").let { binding.albumValue.bindWith(it) } + mediaInfo(filePath, GENERAL, "Album").let { binding.albumValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, GENERAL, "Track").let { binding.trackNameValue.bindWith(it) } + mediaInfo(filePath, GENERAL, "Track").let { binding.trackNameValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, GENERAL, "Performer").let { binding.performerValue.bindWith(it) } + mediaInfo(filePath, GENERAL, "Performer").let { binding.performerValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, AUDIO, "BitRate/String").let { binding.bitRateForAudioValue.bindWith(it) } + mediaInfo(filePath, AUDIO, "BitRate/String").let { binding.bitRateForAudioValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, VIDEO, "BitRate/String").let { binding.bitRateForVideoValue.bindWith(it) } + mediaInfo(filePath, VIDEO, "BitRate/String").let { binding.bitRateForVideoValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, VIDEO, "DisplayAspectRatio/String").let { binding.aspectRatioValue.bindWith(it) } + mediaInfo(filePath, VIDEO, "DisplayAspectRatio/String").let { binding.aspectRatioValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { - mediaInfo(filePath, VIDEO, "FrameRate").let { binding.frameRateValue.bindWith(it) } + mediaInfo(filePath, VIDEO, "FrameRate").let { binding.frameRateValue.bindWith(dialog, it) } } launch(Dispatchers.IO) { val deferredVideoWidth = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Width") } val deferredVideoHeight = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Height") } val (width, height) = awaitAll(deferredVideoWidth, deferredVideoHeight) - binding.resolutionValue.bindWith(if (width.isNotEmpty() && height.isNotEmpty()) "$width × $height" else "") + binding.resolutionValue.bindWith(dialog, if (width.isNotEmpty() && height.isNotEmpty()) "$width × $height" else "") } when { @@ -123,6 +123,7 @@ object MediaInfoDialogManager { restoreEssentialViews(binding, context) updateGuidelines(binding) updateSplitLineVisibility(binding) + dialog.makeTextCopyable { it.titleView } } when (val containerFormat = deferredContainerFormat.await()) { @@ -134,9 +135,9 @@ object MediaInfoDialogManager { } } else -> { - containerFormat.let { binding.containerFormatValue.bindWith(it) } - deferredAudioFormat.await().let { binding.audioFormatValue.bindWith(it) } - deferredVideoFormat.await().let { binding.videoFormatValue.bindWith(it) } + containerFormat.let { binding.containerFormatValue.bindWith(dialog, it) } + deferredAudioFormat.await().let { binding.audioFormatValue.bindWith(dialog, it) } + deferredVideoFormat.await().let { binding.videoFormatValue.bindWith(dialog, it) } } } @@ -182,12 +183,12 @@ object MediaInfoDialogManager { binding.performerParent.isVisible = true } - @Suppress("UNUSED_PARAMETER") + @Suppress("UNUSED_PARAMETER", "unused") private fun setViewsAsMediaMenuPlaceholder(binding: MediaFileInfoDialogListItemBinding) { /* Nothing to do yet. */ } - @Suppress("UNUSED_PARAMETER") + @Suppress("UNUSED_PARAMETER", "unused") private fun setViewsAsLeastPlaceholder(binding: MediaFileInfoDialogListItemBinding) { /* Nothing to do yet. */ } @@ -252,8 +253,10 @@ object MediaInfoDialogManager { ).any { it.isVisible } } - private suspend fun TextView.bindWith(text: String) { - withContext(Dispatchers.Main) { this@bindWith.text = text.takeUnless { text.isEmpty() } ?: context.getString(R.string.text_unknown) } + private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) { + withContext(Dispatchers.Main) { + this@bindWith.setCopyableText(dialog) { text } + } } private operator fun MediaInfo.invoke(filePath: String, streamKind: MediaInfo.StreamKind, parameter: String): String { 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 37fdb596..238a1600 100644 --- a/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/ColorUtils.kt @@ -14,6 +14,7 @@ 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 java.math.RoundingMode import kotlin.math.roundToInt import kotlin.text.RegexOption.IGNORE_CASE @@ -419,4 +420,41 @@ object ColorUtils { return null } + @JvmStatic + @JvmOverloads + fun Double.roundToAlphaString(scale: Int = 1, keepTrailingZeroForFullAlpha: Boolean = true): String { + return toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .stripTrailingZeros() + .toPlainString() + .let { if (keepTrailingZeroForFullAlpha && it == "1") "1.0" else it } + } + + @JvmStatic + @JvmOverloads + fun Double.roundToHueString(scale: Int = 0): String { + return toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .stripTrailingZeros() + .toPlainString() + } + + @JvmStatic + @JvmOverloads + fun Double.roundToSaturationString(scale: Int = 1): String { + return (this * 100.0).toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .stripTrailingZeros() + .toPlainString() + "%" + } + + @JvmStatic + @JvmOverloads + fun Double.roundToValueString(scale: Int = 1): String { + return (this * 100.0).toBigDecimal() + .setScale(scale, RoundingMode.HALF_UP) + .stripTrailingZeros() + .toPlainString() + "%" + } + } \ No newline at end of file diff --git a/app/src/main/res/layout/color_info_dialog_list_item.xml b/app/src/main/res/layout/color_info_dialog_list_item.xml new file mode 100644 index 00000000..a57fc147 --- /dev/null +++ b/app/src/main/res/layout/color_info_dialog_list_item.xml @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 0c060522..6151abc2 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -859,7 +859,8 @@ غير متوفره واجهة برمجة التطبيقات \"%s\" غير متوفرة ستكون الميزة جاهزة للاستخدام في التحديثات القليلة التالية - تحت التطوير + @string/text_under_development + تحت التطوير الغاء التحميل ينسحب غير معروف @@ -938,5 +939,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 07054c71..e86abf9e 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -855,7 +855,8 @@ Unavailable ABI \"%s\" is unavailable The feature will be ready to use in the next few updates - Under development + @string/text_under_development + Under development Undo Undo Unknown @@ -934,5 +935,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index da4b1e14..734d4419 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -858,7 +858,8 @@ No disponible ABI \"%s\" no está disponible La función estará lista para su uso en las próximas actualizaciones - En desarrollo + @string/text_under_development + En desarrollo Revocar Revoc Desconocido @@ -937,5 +938,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c7f3b700..da65bf54 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -858,7 +858,8 @@ Indisponible L\'ABI \"%s\" n\'est pas disponible La fonctionnalité sera prête à être utilisée dans les prochaines mises à jour. - En cours de développement + @string/text_under_development + En cours de développement Révoquer Révoq Inconnu @@ -937,5 +938,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 08d70d1a..c03aa67d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -858,7 +858,8 @@ 使用できません ABI \"%s\" は使用できません この機能は, 次の数回のアップデートで使用できるようになる予定です - 開発中 + @string/text_under_development + 開発中 元に戻す 戻る 不明 @@ -937,5 +938,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index b6c0371d..e25eab42 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -859,7 +859,8 @@ 사용할 수 없음 ABI \"%s\" 를 사용할 수 없습니다 기능은 다음 몇 가지 업데이트에서 사용할 준비가됩니다. - 개발중인 + @string/text_under_development + 개발중인 실행 취소 알 수 없음 @@ -938,5 +939,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fc34d61c..29990496 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -858,7 +858,8 @@ Недоступно ABI \"%s\" недоступен Функция будет готова к использованию в ближайших обновлениях - В стадии разработки + @string/text_under_development + В стадии разработки Отозвать Верни Неизвестно @@ -937,5 +938,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index b7d83f44..2fe4c575 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -857,7 +857,8 @@ 不可用 ABI \"%s\" 不可用 將在後續版本實現當前功能 - 開發中 + @string/text_under_development + 開發中 撤銷 撤銷 未知 @@ -936,5 +937,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 1dd646e5..b12556e8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -857,7 +857,8 @@ 不可用 ABI \"%s\" 不可用 將在後續版本實現當前功能 - 開發中 + @string/text_under_development + 開發中 撤銷 撤銷 未知 @@ -936,5 +937,7 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index bdfc2311..84a31c56 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -854,7 +854,8 @@ 不可用 ABI \"%s\" 不可用 将在后续版本实现当前功能 - 开发中 + @string/text_under_development + 开发中 撤销 撤销 未知 @@ -936,5 +937,7 @@ 定位失败 无法定位主题色所在颜色库 无法确定主题色条目的索引值 + 颜色详情 + 主题色详情 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6db2b01e..fef81604 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1080,7 +1080,8 @@ Unavailable ABI \"%s\" is unavailable The feature will be ready to use in the next few updates - Under development + @string/text_under_development + Under development Undo Undo Unknown @@ -1178,5 +1179,12 @@ Failed to locate Failed to locate the color library for the theme color Failed to determine the index of the theme color item + Color details + Theme color details + ColorInt + HSV + HSL + RGB + HEX diff --git a/version.properties b/version.properties index 007c31a6..70979dcd 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Tue Apr 01 11:11:49 CST 2025 -BUILD_TIME=1743477109699 +#Wed Apr 02 00:47:54 CST 2025 +BUILD_TIME=1743526074171 COMPILE_SDK_VERSION=35 JAVA_VERSION=23 JAVA_VERSION_MIN_RADICAL=0 @@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=35 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=3090 +VERSION_BUILD=3095 VERSION_NAME=6.6.2 Alpha5 VSCODE_EXT_REQUIRED_VERSION=1.0.8