6.7.0 - Alpha12 - Fine tuning
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"android_studio_latest_recommended_version_name": "Android Studio Otter | 2025.2.1 Patch 1",
|
"android_studio_latest_recommended_version_name": "Android Studio Otter 2 Feature Drop | 2025.2.2",
|
||||||
"var_date_android_studio_latest_recommended_version_name": "2025/11/17",
|
"var_date_android_studio_latest_recommended_version_name": "2025/12/04",
|
||||||
"android_studio_latest_recommended_file_name_of_exe": "android-studio-2025.2.1.8-windows.exe",
|
"android_studio_latest_recommended_file_name_of_exe": "android-studio-2025.2.2.7-windows.exe",
|
||||||
"android_studio_latest_recommended_download_address_of_exe": "https://redirector.gvt1.com/edgedl/android/studio/install/2025.2.1.8/android-studio-2025.2.1.8-windows.exe",
|
"android_studio_latest_recommended_download_address_of_exe": "https://redirector.gvt1.com/edgedl/android/studio/install/2025.2.2.7/android-studio-2025.2.2.7-windows.exe",
|
||||||
"android_studio_latest_recommended_file_size_of_exe": "1.34 GiB",
|
"android_studio_latest_recommended_file_size_of_exe": "1.34 GiB",
|
||||||
"android_studio_latest_recommended_file_name_of_zip": "android-studio-2025.2.1.8-windows.zip",
|
"android_studio_latest_recommended_file_name_of_zip": "android-studio-2025.2.2.7-windows.zip",
|
||||||
"android_studio_latest_recommended_download_address_of_zip": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.2.1.8/android-studio-2025.2.1.8-windows.zip",
|
"android_studio_latest_recommended_download_address_of_zip": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.2.2.7/android-studio-2025.2.2.7-windows.zip",
|
||||||
"android_studio_latest_recommended_file_size_of_zip": "1.35 GiB",
|
"android_studio_latest_recommended_file_size_of_zip": "1.35 GiB",
|
||||||
"android_studio_latest_recommended_file_name_of_tar": "android-studio-2025.2.1.8-linux.tar.gz",
|
"android_studio_latest_recommended_file_name_of_tar": "android-studio-2025.2.2.7-linux.tar.gz",
|
||||||
"android_studio_latest_recommended_download_address_of_tar": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.2.1.8/android-studio-2025.2.1.8-linux.tar.gz",
|
"android_studio_latest_recommended_download_address_of_tar": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.2.2.7/android-studio-2025.2.2.7-linux.tar.gz",
|
||||||
"android_studio_latest_recommended_file_size_of_tar": "1.37 GiB",
|
"android_studio_latest_recommended_file_size_of_tar": "1.38 GiB",
|
||||||
"var_date_contribution_table_data_updated": "2025/09/06",
|
"var_date_contribution_table_data_updated": "2025/09/06",
|
||||||
"latest_rhino_engine_name_with_github_lineno_address": "[v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)",
|
"latest_rhino_engine_name_with_github_lineno_address": "[v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)",
|
||||||
"var_date_rhino_engine_latest_committed": "2025/10/05",
|
"var_date_rhino_engine_latest_committed": "2025/10/05",
|
||||||
|
|||||||
43
.utils/declarations/index.d.ts
vendored
43
.utils/declarations/index.d.ts
vendored
@@ -76,6 +76,49 @@ interface FindTargetRowsOptionsBase {
|
|||||||
interface FindTargetRowsOptions extends FindTargetRowsOptionsBase {
|
interface FindTargetRowsOptions extends FindTargetRowsOptionsBase {
|
||||||
/** @default [] */
|
/** @default [] */
|
||||||
tableDataStructure?: Array<{ [dataItemName: TableDataStructureItemName]: TableDataStructureItem } | TableDataStructureItemName>;
|
tableDataStructure?: Array<{ [dataItemName: TableDataStructureItemName]: TableDataStructureItem } | TableDataStructureItemName>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for "expand" actions needed before searching the table.
|
||||||
|
* Example: { toggleSelector: 'a.exw-control' } will click Devsite's collapsible controls.
|
||||||
|
* zh-CN:
|
||||||
|
* 在查找表格前需要进行的 "展开" 动作配置.
|
||||||
|
* 示例: { toggleSelector: 'a.exw-control' } 将点击 Devsite 的可折叠控件.
|
||||||
|
*/
|
||||||
|
expandBeforeFinding?: ExpandBeforeFindingOptions | ExpandBeforeFindingOptions[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ExpandBeforeFindingOptions {
|
||||||
|
/**
|
||||||
|
* Optional container selector to limit the scope of operation.
|
||||||
|
* zh-CN: 限定作用范围容器选择器, 可选.
|
||||||
|
*/
|
||||||
|
containerSelector?: string;
|
||||||
|
/**
|
||||||
|
* Selector for the "expand/collapse" button or toggle that needs to be clicked (required).
|
||||||
|
* zh-CN: 需要点击的 "展开/折叠" 按钮或开关的选择器 (必填).
|
||||||
|
*/
|
||||||
|
toggleSelector: string;
|
||||||
|
/**
|
||||||
|
* Attribute name to determine if expanded, defaults to 'aria-expanded'.
|
||||||
|
* zh-CN: 判定已展开的属性名, 默认 'aria-expanded'.
|
||||||
|
*
|
||||||
|
* @default 'aria-expanded'
|
||||||
|
*/
|
||||||
|
expandedAttr?: string;
|
||||||
|
/**
|
||||||
|
* Attribute value to determine if expanded, defaults to 'true'.
|
||||||
|
* zh-CN: 判定已展开的属性值, 默认 'true'.
|
||||||
|
*
|
||||||
|
* @default 'true'
|
||||||
|
*/
|
||||||
|
expandedValue?: string;
|
||||||
|
/**
|
||||||
|
* Maximum number of targets to click, no limit by default.
|
||||||
|
* zh-CN: 最多点击的目标数量, 默认无限制.
|
||||||
|
*
|
||||||
|
* @default Infinity
|
||||||
|
*/
|
||||||
|
maxClicks?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FindTargetRowsOptionsForPageEvaluate extends FindTargetRowsOptionsBase {
|
interface FindTargetRowsOptionsForPageEvaluate extends FindTargetRowsOptionsBase {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ export async function fetchStudioAgpTable() {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return findTargetRows({
|
return findTargetRows({
|
||||||
url: URL,
|
url: URL,
|
||||||
|
expandBeforeFinding: {
|
||||||
|
toggleSelector: 'a.exw-control',
|
||||||
|
},
|
||||||
tableFilter: {
|
tableFilter: {
|
||||||
th: /Android Studio version/i,
|
th: /Android Studio version/i,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ async function getPRCommitStatsByAuthor(pr) {
|
|||||||
* zh-CN: 要处理的输入项列表.
|
* zh-CN: 要处理的输入项列表.
|
||||||
* @param {number} limit
|
* @param {number} limit
|
||||||
* Maximum concurrency (>=1).<br>
|
* Maximum concurrency (>=1).<br>
|
||||||
* zh=CN: 最大并发数 (>=1).
|
* zh-CN: 最大并发数 (>=1).
|
||||||
* @param {(item: Item, idx: number) => Promise<MapperResult>} mapper
|
* @param {(item: Item, idx: number) => Promise<MapperResult>} mapper
|
||||||
* Async function to process one item.<br>
|
* Async function to process one item.<br>
|
||||||
* zh-CN: 处理单个项的异步函数.
|
* zh-CN: 处理单个项的异步函数.
|
||||||
|
|||||||
@@ -55,6 +55,66 @@ function toEncodedRegexTagOptions(options) {
|
|||||||
return structuredClone(traverse(options));
|
return structuredClone(traverse(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to click the "Expand" control before searching for the table.
|
||||||
|
* zh-CN: 在查找表格前尝试点击 "展开" 控件.
|
||||||
|
*
|
||||||
|
* @param {import('puppeteer').Page} page
|
||||||
|
* @param {FindTargetRowsOptions & PuppeteerOptions} options
|
||||||
|
* @returns {Promise<number>} Actual number of clicks. (zh-CN: 实际点击次数.)
|
||||||
|
*/
|
||||||
|
async function expandContentIfNeeded(page, options) {
|
||||||
|
const configs = options.expandBeforeFinding;
|
||||||
|
if (!configs) return 0;
|
||||||
|
|
||||||
|
/** @type {ExpandBeforeFindingOptions[]} */
|
||||||
|
const list = Array.isArray(configs) ? configs : [ configs ];
|
||||||
|
|
||||||
|
let totalClicked = 0;
|
||||||
|
for (const cfg of list) {
|
||||||
|
if (!cfg || !cfg.toggleSelector) continue;
|
||||||
|
const {
|
||||||
|
containerSelector,
|
||||||
|
toggleSelector,
|
||||||
|
expandedAttr = 'aria-expanded',
|
||||||
|
expandedValue = 'true',
|
||||||
|
maxClicks = Infinity,
|
||||||
|
} = cfg;
|
||||||
|
|
||||||
|
const containerHandle = containerSelector ? await page.$(containerSelector) : null;
|
||||||
|
const toggles = containerHandle
|
||||||
|
? await containerHandle.$$(toggleSelector)
|
||||||
|
: await page.$$(toggleSelector);
|
||||||
|
|
||||||
|
let clicked = 0;
|
||||||
|
for (const toggle of toggles) {
|
||||||
|
if (clicked >= maxClicks) break;
|
||||||
|
const isExpanded = await toggle.evaluate((el, attr, val) => {
|
||||||
|
const cur = el.getAttribute(attr);
|
||||||
|
return cur === val;
|
||||||
|
}, expandedAttr, expandedValue);
|
||||||
|
if (!isExpanded) {
|
||||||
|
try {
|
||||||
|
await toggle.click({ delay: 10 });
|
||||||
|
clicked++;
|
||||||
|
totalClicked++;
|
||||||
|
await sleep(200);
|
||||||
|
} catch {
|
||||||
|
/* Ignored. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (containerHandle) {
|
||||||
|
try {
|
||||||
|
await containerHandle.dispose();
|
||||||
|
} catch {
|
||||||
|
/* Ignored. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalClicked;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Page} page
|
* @param {Page} page
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
@@ -87,7 +147,7 @@ async function findTargetRowsWithPage(page, options = {}) {
|
|||||||
return await page.evaluate((options, consts) => {
|
return await page.evaluate((options, consts) => {
|
||||||
const regex = new RegExp(consts.regexId + String.raw`(?:(\w+):)?(.+)`);
|
const regex = new RegExp(consts.regexId + String.raw`(?:(\w+):)?(.+)`);
|
||||||
const targets = Array.from(document.querySelectorAll(options.tableSelector ?? 'table'));
|
const targets = Array.from(document.querySelectorAll(options.tableSelector ?? 'table'));
|
||||||
const target = targets.find(t => {
|
const filteredTargets = targets.filter(t => {
|
||||||
for (const [ selector, filter ] of Object.entries(options.tableFilter ?? {})) {
|
for (const [ selector, filter ] of Object.entries(options.tableFilter ?? {})) {
|
||||||
const elements = Array.from(t.querySelectorAll(selector));
|
const elements = Array.from(t.querySelectorAll(selector));
|
||||||
if (Array.isArray(filter)) {
|
if (Array.isArray(filter)) {
|
||||||
@@ -130,11 +190,11 @@ async function findTargetRowsWithPage(page, options = {}) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!target) {
|
if (!filteredTargets.length) {
|
||||||
throw new Error('No target table found');
|
throw new Error('No target table found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableRows = Array.from(target.querySelectorAll(options.tableRowSelector ?? 'tbody tr'));
|
const tableRows = filteredTargets.map(target => Array.from(target.querySelectorAll(options.tableRowSelector ?? 'tbody tr'))).flat(1);
|
||||||
const tableDataList = [];
|
const tableDataList = [];
|
||||||
tableRows.forEach((tr) => {
|
tableRows.forEach((tr) => {
|
||||||
const tableData = {};
|
const tableData = {};
|
||||||
@@ -209,8 +269,11 @@ export async function findTargetRows(options) {
|
|||||||
let rows = null;
|
let rows = null;
|
||||||
const deadline = Date.now() + (options.findTargetRowsTimeout ?? 30000);
|
const deadline = Date.now() + (options.findTargetRowsTimeout ?? 30000);
|
||||||
while (Date.now() < deadline) {
|
while (Date.now() < deadline) {
|
||||||
|
await expandContentIfNeeded(page, options);
|
||||||
|
|
||||||
rows = await findTargetRowsWithPage(page, options);
|
rows = await findTargetRowsWithPage(page, options);
|
||||||
if (rows && rows.length) break;
|
if (rows && rows.length) break;
|
||||||
|
|
||||||
await autoScroll(page);
|
await autoScroll(page);
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ class ConsoleFloaty(private val console: ConsoleImpl) : AbstractResizableExpanda
|
|||||||
internal fun setCloseButton(resId: Int) {
|
internal fun setCloseButton(resId: Int) {
|
||||||
mCloseButton?.let {
|
mCloseButton?.let {
|
||||||
val res = console.uiHandler.applicationContext.resources
|
val res = console.uiHandler.applicationContext.resources
|
||||||
val padding = (7 * res.displayMetrics.density).toInt()
|
val padding = (7 * res.displayMetrics.density).roundToInt()
|
||||||
it.post {
|
it.post {
|
||||||
it.setImageDrawable(ResourcesCompat.getDrawable(res, resId, null))
|
it.setImageDrawable(ResourcesCompat.getDrawable(res, resId, null))
|
||||||
it.setPadding(padding, padding, padding, padding)
|
it.setPadding(padding, padding, padding, padding)
|
||||||
|
|||||||
@@ -132,8 +132,11 @@ public class DevPluginResponseHandler implements Handler {
|
|||||||
if (message == null) {
|
if (message == null) {
|
||||||
ViewUtils.showToast(mContext, R.string.text_invalid_project, true);
|
ViewUtils.showToast(mContext, R.string.text_invalid_project, true);
|
||||||
} else {
|
} else {
|
||||||
// 使用 ErrorDialogActivity 代替直接显示 MaterialDialog
|
// Use ErrorDialogActivity instead of showing MaterialDialog directly
|
||||||
// 这样可以避免在非UI线程或Activity不可见状态下调用对话框的问题
|
// This avoids issues when calling dialogs from non-UI threads or when Activity is not visible.
|
||||||
|
// zh-CN:
|
||||||
|
// 使用 ErrorDialogActivity 代替直接显示 MaterialDialog,
|
||||||
|
// 这样可以避免在非 UI 线程或 Activity 不可见状态下调用对话框的问题.
|
||||||
ErrorDialogActivity.showErrorDialog(
|
ErrorDialogActivity.showErrorDialog(
|
||||||
mContext.getApplicationContext(),
|
mContext.getApplicationContext(),
|
||||||
R.string.text_invalid_project,
|
R.string.text_invalid_project,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText
|
|||||||
import org.autojs.autojs.runtime.api.augment.colors.Colors
|
import org.autojs.autojs.runtime.api.augment.colors.Colors
|
||||||
import org.autojs.autojs.util.ColorUtils
|
import org.autojs.autojs.util.ColorUtils
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
import org.autojs.autojs6.databinding.ColorInfoDialogListItemBinding
|
import org.autojs.autojs6.databinding.ColorInfoDialogItemsBinding
|
||||||
|
|
||||||
object ColorInfoDialogManager {
|
object ColorInfoDialogManager {
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ object ColorInfoDialogManager {
|
|||||||
.show()
|
.show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val binding = ColorInfoDialogListItemBinding.inflate(LayoutInflater.from(context))
|
val binding = ColorInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
val colorWithoutAlpha = color or -0x1000000
|
val colorWithoutAlpha = color or -0x1000000
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ object ColorInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreEssentialViews(binding: ColorInfoDialogListItemBinding) {
|
private fun restoreEssentialViews(binding: ColorInfoDialogItemsBinding) {
|
||||||
listOf(
|
listOf(
|
||||||
binding.colorHexColon to binding.colorHexValue,
|
binding.colorHexColon to binding.colorHexValue,
|
||||||
binding.colorRgbColon to binding.colorRgbValue,
|
binding.colorRgbColon to binding.colorRgbValue,
|
||||||
@@ -87,7 +87,7 @@ object ColorInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGuidelines(binding: ColorInfoDialogListItemBinding) {
|
private fun updateGuidelines(binding: ColorInfoDialogItemsBinding) {
|
||||||
val filteredBindings = listOf(
|
val filteredBindings = listOf(
|
||||||
binding.colorHexLabel to binding.colorHexGuideline,
|
binding.colorHexLabel to binding.colorHexGuideline,
|
||||||
binding.colorRgbLabel to binding.colorRgbGuideline,
|
binding.colorRgbLabel to binding.colorRgbGuideline,
|
||||||
|
|||||||
@@ -54,15 +54,13 @@ class ColorSelectActivity : ColorSelectBaseActivity() {
|
|||||||
return super.onCreateOptionsMenu(menu)
|
return super.onCreateOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||||
when (item.itemId) {
|
R.id.action_toggle_color_select_layout -> {
|
||||||
R.id.action_toggle_color_select_layout -> {
|
isLegacyLayout = false
|
||||||
isLegacyLayout = false
|
startActivity(this, isToggled = true)
|
||||||
startActivity(this, isToggled = true)
|
true
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,21 @@
|
|||||||
package org.autojs.autojs.ui.error;
|
package org.autojs.autojs.ui.error;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import org.autojs.autojs.extension.MaterialDialogExtensions;
|
import org.autojs.autojs.extension.MaterialDialogExtensions;
|
||||||
import org.autojs.autojs.ui.BaseActivity;
|
import org.autojs.autojs.ui.BaseActivity;
|
||||||
|
import org.autojs.autojs.util.ClipboardUtils;
|
||||||
|
import org.autojs.autojs.util.ViewUtils;
|
||||||
import org.autojs.autojs6.R;
|
import org.autojs.autojs6.R;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple activity to show error dialogs when a context is not available or valid
|
* A simple activity to show error dialogs when a context is not available or valid
|
||||||
* for showing dialogs directly.
|
* for showing dialogs directly.
|
||||||
|
* zh-CN: 一个简单的 Activity,用于在上下文不可用或无效而无法直接显示对话框时显示错误对话框.
|
||||||
*/
|
*/
|
||||||
public class ErrorDialogActivity extends BaseActivity {
|
public class ErrorDialogActivity extends BaseActivity {
|
||||||
|
|
||||||
@@ -21,35 +27,51 @@ public class ErrorDialogActivity extends BaseActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// Get extras from intent
|
// Get extras from intent.
|
||||||
|
// zh-CN: 从 Intent 获取附加数据.
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
String title = intent.getStringExtra(EXTRA_TITLE);
|
String title = intent.getStringExtra(EXTRA_TITLE);
|
||||||
String message = intent.getStringExtra(EXTRA_MESSAGE);
|
String message = intent.getStringExtra(EXTRA_MESSAGE);
|
||||||
String positiveButtonText = intent.getStringExtra(EXTRA_POSITIVE_BUTTON_TEXT);
|
String positiveButtonText = intent.getStringExtra(EXTRA_POSITIVE_BUTTON_TEXT);
|
||||||
|
|
||||||
// If no positive button text provided, use default dismiss text
|
// If no positive button text provided, use default dismiss text.
|
||||||
|
// zh-CN: 如果没有提供确认按钮文本,则使用默认的关闭文本.
|
||||||
if (positiveButtonText == null) {
|
if (positiveButtonText == null) {
|
||||||
positiveButtonText = getString(R.string.dialog_button_dismiss);
|
positiveButtonText = getString(R.string.dialog_button_dismiss);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show dialog
|
String content = Objects.requireNonNullElse(message, "");
|
||||||
var materialDialog = new MaterialDialog.Builder(this)
|
|
||||||
.title(title)
|
MaterialDialog.Builder builder = new MaterialDialog.Builder(this)
|
||||||
.content(message)
|
.title(Objects.requireNonNullElse(title, getString(R.string.text_prompt)))
|
||||||
|
.content(content)
|
||||||
.positiveText(positiveButtonText)
|
.positiveText(positiveButtonText)
|
||||||
.positiveColorRes(R.color.dialog_button_default)
|
.positiveColorRes(R.color.dialog_button_default)
|
||||||
|
.autoDismiss(false)
|
||||||
.cancelable(false)
|
.cancelable(false)
|
||||||
.canceledOnTouchOutside(false)
|
.canceledOnTouchOutside(false)
|
||||||
.onPositive((dialog, which) -> finish())
|
.onPositive((dialog, which) -> dialog.dismiss())
|
||||||
.show();
|
.dismissListener(dialog -> finish());
|
||||||
|
|
||||||
|
if (!content.isBlank()) {
|
||||||
|
builder.neutralText(R.string.text_copy_all);
|
||||||
|
builder.neutralColorRes(R.color.dialog_button_hint);
|
||||||
|
builder.onNeutral((dialog, which) -> {
|
||||||
|
ClipboardUtils.setClip(dialog.getContext(), content);
|
||||||
|
ViewUtils.showSnack(dialog.getView(), R.string.text_already_copied_to_clip, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var materialDialog = builder.show();
|
||||||
|
|
||||||
MaterialDialogExtensions.makeTextCopyable(materialDialog, materialDialog.getContentView());
|
MaterialDialogExtensions.makeTextCopyable(materialDialog, materialDialog.getContentView());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to show an error dialog from any context
|
* Helper method to show an error dialog from any context.
|
||||||
|
* zh-CN: 用于从任何上下文显示错误对话框的辅助方法.
|
||||||
*/
|
*/
|
||||||
public static void showErrorDialog(android.content.Context context, int titleRes, String message) {
|
public static void showErrorDialog(Context context, int titleRes, String message) {
|
||||||
Intent intent = new Intent(context, ErrorDialogActivity.class);
|
Intent intent = new Intent(context, ErrorDialogActivity.class);
|
||||||
intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
|
intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
|
||||||
intent.putExtra(EXTRA_MESSAGE, message);
|
intent.putExtra(EXTRA_MESSAGE, message);
|
||||||
@@ -58,9 +80,10 @@ public class ErrorDialogActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to show an error dialog from any context with custom positive button text
|
* Helper method to show an error dialog from any context with custom positive button text.
|
||||||
|
* zh-CN: 用于从任何上下文显示带有自定义确认按钮文本的错误对话框的辅助方法.
|
||||||
*/
|
*/
|
||||||
public static void showErrorDialog(android.content.Context context, int titleRes, String message, int positiveButtonTextRes) {
|
public static void showErrorDialog(Context context, int titleRes, String message, int positiveButtonTextRes) {
|
||||||
Intent intent = new Intent(context, ErrorDialogActivity.class);
|
Intent intent = new Intent(context, ErrorDialogActivity.class);
|
||||||
intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
|
intent.putExtra(EXTRA_TITLE, context.getString(titleRes));
|
||||||
intent.putExtra(EXTRA_MESSAGE, message);
|
intent.putExtra(EXTRA_MESSAGE, message);
|
||||||
@@ -68,4 +91,5 @@ public class ErrorDialogActivity extends BaseActivity {
|
|||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class WindowSwitchingDialog extends AppLevelThemeDialogBuilder {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.window_switching_dialog_list_item, parent, false));
|
return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.window_switching_dialog_items, parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.autojs.autojs.util.IntentUtils.SnackExceptionHolder
|
|||||||
import org.autojs.autojs.util.StringUtils
|
import org.autojs.autojs.util.StringUtils
|
||||||
import org.autojs.autojs.util.StringUtils.dropBom
|
import org.autojs.autojs.util.StringUtils.dropBom
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
import org.autojs.autojs6.databinding.EditableFileInfoDialogListItemBinding
|
import org.autojs.autojs6.databinding.EditableFileInfoDialogItemsBinding
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@@ -40,7 +40,7 @@ object EditableFileInfoDialogManager {
|
|||||||
.show()
|
.show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val binding = EditableFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context))
|
val binding = EditableFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
val textUnknown = context.getString(R.string.text_unknown)
|
val textUnknown = context.getString(R.string.text_unknown)
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ object EditableFileInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGuidelines(binding: EditableFileInfoDialogListItemBinding) {
|
private fun updateGuidelines(binding: EditableFileInfoDialogItemsBinding) {
|
||||||
val bindings = listOf(
|
val bindings = listOf(
|
||||||
binding.filePathLabel to binding.filePathGuideline,
|
binding.filePathLabel to binding.filePathGuideline,
|
||||||
binding.fileSizeLabel to binding.fileSizeGuideline,
|
binding.fileSizeLabel to binding.fileSizeGuideline,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import org.autojs.autojs.extension.MaterialDialogExtensions.setCopyableText
|
|||||||
import org.autojs.autojs.model.explorer.ExplorerItem
|
import org.autojs.autojs.model.explorer.ExplorerItem
|
||||||
import org.autojs.autojs.util.ViewUtils
|
import org.autojs.autojs.util.ViewUtils
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
import org.autojs.autojs6.databinding.MediaFileInfoDialogListItemBinding
|
import org.autojs.autojs6.databinding.MediaFileInfoDialogItemsBinding
|
||||||
import org.mediainfo.android.MediaInfo
|
import org.mediainfo.android.MediaInfo
|
||||||
import org.mediainfo.android.MediaInfo.StreamKind.AUDIO
|
import org.mediainfo.android.MediaInfo.StreamKind.AUDIO
|
||||||
import org.mediainfo.android.MediaInfo.StreamKind.GENERAL
|
import org.mediainfo.android.MediaInfo.StreamKind.GENERAL
|
||||||
@@ -34,7 +34,7 @@ object MediaInfoDialogManager {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) {
|
fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) {
|
||||||
val binding = MediaFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context))
|
val binding = MediaFileInfoDialogItemsBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
|
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
|
||||||
// zh-CN: 针对 Dialog 独立创建一个 Scope, 生命周期与 Dialog 绑定.
|
// zh-CN: 针对 Dialog 独立创建一个 Scope, 生命周期与 Dialog 绑定.
|
||||||
@@ -154,7 +154,7 @@ object MediaInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setViewsAsVideoPlaceholder(binding: MediaFileInfoDialogListItemBinding) {
|
private fun setViewsAsVideoPlaceholder(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
binding.videoFormatParent.isVisible = true
|
binding.videoFormatParent.isVisible = true
|
||||||
binding.bitRateForVideoParent.isVisible = true
|
binding.bitRateForVideoParent.isVisible = true
|
||||||
binding.resolutionParent.isVisible = true
|
binding.resolutionParent.isVisible = true
|
||||||
@@ -162,7 +162,7 @@ object MediaInfoDialogManager {
|
|||||||
binding.frameRateParent.isVisible = true
|
binding.frameRateParent.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setViewsAsMediaPlaceholder(binding: MediaFileInfoDialogListItemBinding) {
|
private fun setViewsAsMediaPlaceholder(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
binding.audioFormatParent.isVisible = true
|
binding.audioFormatParent.isVisible = true
|
||||||
binding.bitRateForAudioParent.isVisible = true
|
binding.bitRateForAudioParent.isVisible = true
|
||||||
binding.albumParent.isVisible = true
|
binding.albumParent.isVisible = true
|
||||||
@@ -171,16 +171,16 @@ object MediaInfoDialogManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER", "unused")
|
@Suppress("UNUSED_PARAMETER", "unused")
|
||||||
private fun setViewsAsMediaMenuPlaceholder(binding: MediaFileInfoDialogListItemBinding) {
|
private fun setViewsAsMediaMenuPlaceholder(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
/* Nothing to do yet. */
|
/* Nothing to do yet. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER", "unused")
|
@Suppress("UNUSED_PARAMETER", "unused")
|
||||||
private fun setViewsAsLeastPlaceholder(binding: MediaFileInfoDialogListItemBinding) {
|
private fun setViewsAsLeastPlaceholder(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
/* Nothing to do yet. */
|
/* Nothing to do yet. */
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreEssentialViews(binding: MediaFileInfoDialogListItemBinding, context: Context) {
|
private fun restoreEssentialViews(binding: MediaFileInfoDialogItemsBinding, context: Context) {
|
||||||
binding.containerFormatLabel.text = context.getString(R.string.media_info_container_format_label)
|
binding.containerFormatLabel.text = context.getString(R.string.media_info_container_format_label)
|
||||||
binding.containerFormatColon.isVisible = true
|
binding.containerFormatColon.isVisible = true
|
||||||
binding.containerFormatValue.isVisible = true
|
binding.containerFormatValue.isVisible = true
|
||||||
@@ -201,7 +201,7 @@ object MediaInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGuidelines(binding: MediaFileInfoDialogListItemBinding) {
|
private fun updateGuidelines(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
val filteredBindings = listOf(
|
val filteredBindings = listOf(
|
||||||
binding.containerFormatLabel to binding.containerFormatGuideline,
|
binding.containerFormatLabel to binding.containerFormatGuideline,
|
||||||
binding.videoFormatLabel to binding.videoFormatGuideline,
|
binding.videoFormatLabel to binding.videoFormatGuideline,
|
||||||
@@ -228,7 +228,7 @@ object MediaInfoDialogManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSplitLineVisibility(binding: MediaFileInfoDialogListItemBinding) {
|
private fun updateSplitLineVisibility(binding: MediaFileInfoDialogItemsBinding) {
|
||||||
binding.splitLine.isVisible = listOf(
|
binding.splitLine.isVisible = listOf(
|
||||||
binding.bitRateForVideoParent,
|
binding.bitRateForVideoParent,
|
||||||
binding.resolutionParent,
|
binding.resolutionParent,
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ object IntentUtils {
|
|||||||
context.startActivity(launchIntent)
|
context.startActivity(launchIntent)
|
||||||
} else {
|
} else {
|
||||||
// All scripts will call the scheduleAppLaunch method.
|
// All scripts will call the scheduleAppLaunch method.
|
||||||
// zh-CM: 脚本一律调用 scheduleAppLaunch 方法.
|
// zh-CN: 脚本一律调用 scheduleAppLaunch 方法.
|
||||||
scheduleAppLaunch(context, launchIntent)
|
scheduleAppLaunch(context, launchIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ object IntentUtils {
|
|||||||
// zh-CN: 主页抽屉 "重启" 按钮点击时, 如果启用了 "快速重启", 则不调用 finishAllAppTasksSafely 方法.
|
// zh-CN: 主页抽屉 "重启" 按钮点击时, 如果启用了 "快速重启", 则不调用 finishAllAppTasksSafely 方法.
|
||||||
} else {
|
} else {
|
||||||
// All scripts will call the finishAllAppTasksSafely method.
|
// All scripts will call the finishAllAppTasksSafely method.
|
||||||
// zh-CM: 脚本一律调用 finishAllAppTasksSafely 方法.
|
// zh-CN: 脚本一律调用 finishAllAppTasksSafely 方法.
|
||||||
finishAllAppTasksSafely(context)
|
finishAllAppTasksSafely(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ class MediaInfo {
|
|||||||
getMediaInfoOption(param)
|
getMediaInfoOption(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getIsCanceled() = mIsCanceled
|
||||||
|
|
||||||
fun getMediaInfoTrimmed(filename: String): String = checkAvailability {
|
fun getMediaInfoTrimmed(filename: String): String = checkAvailability {
|
||||||
var result = getMediaInfo(filename)
|
var result = getMediaInfo(filename)
|
||||||
|
|
||||||
@@ -141,7 +143,7 @@ class MediaInfo {
|
|||||||
|
|
||||||
private fun countSpacesBeforeColon(input: String): Int {
|
private fun countSpacesBeforeColon(input: String): Int {
|
||||||
val index = input.indexOf(':')
|
val index = input.indexOf(':')
|
||||||
if (index == -1) return 0 // 如果没有冒号, 则返回0
|
if (index == -1) return 0
|
||||||
|
|
||||||
var count = 0
|
var count = 0
|
||||||
for (i in index - 1 downTo 0) {
|
for (i in index - 1 downTo 0) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Sat Nov 15 12:31:16 GMT+8 2025
|
#Sun Dec 07 19:51:46 GMT+8 2025
|
||||||
9.0.0-beta01
|
9.0.0-beta03
|
||||||
8.13.1
|
8.13.1
|
||||||
8.12.3
|
8.12.3
|
||||||
8.11.2
|
8.11.2
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#Fri Oct 31 23:54:17 GMT+8 2025
|
#Sun Dec 07 19:51:17 GMT+8 2025
|
||||||
|
2025.2.2=8.13
|
||||||
2025.2.1=8.13
|
2025.2.1=8.13
|
||||||
2025.1.4=8.13
|
2025.1.4=8.13
|
||||||
2025.1.3=8.13
|
2025.1.3=8.13
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
#Wed Nov 19 13:38:14 GMT+8 2025
|
#Sun Dec 07 19:51:05 GMT+8 2025
|
||||||
|
252.28238.7.2523.14499447=2025.2.3.3
|
||||||
|
252.27397.103.2523.14473358=2025.2.3.2
|
||||||
252.27397.103.2523.14431943=2025.2.3.1
|
252.27397.103.2523.14431943=2025.2.3.1
|
||||||
|
252.27397.103.2522.14514259=2025.2.2.7
|
||||||
|
252.27397.103.2522.14468004=2025.2.2.6
|
||||||
252.27397.103.2522.14425743=2025.2.2.5
|
252.27397.103.2522.14425743=2025.2.2.5
|
||||||
252.27397.103.2522.14395761=2025.2.2.4
|
252.27397.103.2522.14395761=2025.2.2.4
|
||||||
252.25557.131.2522.14357309=2025.2.2.3
|
252.25557.131.2522.14357309=2025.2.2.3
|
||||||
|
|||||||
Reference in New Issue
Block a user