6.3.1 - 新增发布通知权限 / WS 实例创建; 修复 floaty 模块异常 / 安卓 7.x 异常; UI 模式增强; 迁移至 View Binding
This commit is contained in:
1 parent
31ebd5b854
commit
1755ae3271
511 files changed
+12567
-11063
No files matched your search
@@ -110,6 +110,38 @@
|
|||||||
|
|
||||||
[comment]: <> "Version history only shows last 3 versions"
|
[comment]: <> "Version history only shows last 3 versions"
|
||||||
|
|
||||||
|
# v6.3.1
|
||||||
|
|
||||||
|
###### 2023/05/26
|
||||||
|
|
||||||
|
* `新增` 发布通知权限及主页抽屉开关 _[`issue #55`](http://issues.autojs6.com/55)_
|
||||||
|
* `新增` UI 模式支持简单的 Android 布局解析 (参阅 示例代码 > 布局 > 简单安卓布局)
|
||||||
|
* `新增` UI 模式增加 console / imagebutton / ratingbar / switch / textclock / togglebutton 等控件
|
||||||
|
* `新增` UI 模式控件的颜色色值支持 [OmniColor](https://docs.autojs6.com/#/omniTypes?id=omnicolor) 类型 (如 color="orange")
|
||||||
|
* `新增` UI 模式的控件完全支持 attr 方法设置控件属性 (如 ui.text.attr('color', 'blue'))
|
||||||
|
* `新增` UI 模式控件支持布尔类型属性值的缺省形式 (如 clickable="true" 可简写为 clickable 或 isClickable)
|
||||||
|
* `新增` button 控件支持 isColored 及 isBorderless 布尔类型属性
|
||||||
|
* `新增` console.resetGlobalLogConfig 方法用于重置全局日志配置
|
||||||
|
* `新增` web.newWebSocket 方法用于创建 Web Socket 实例 (参阅 项目文档 > [万维网](https://docs.autojs6.com/#/web?id=m-newwebsocket))
|
||||||
|
* `修复` 文件管理器的文件夹排序异常
|
||||||
|
* `修复` floaty 模块构建的浮动窗口无法调节样式及位置的问题 _[`issue #60`](http://issues.autojs6.com/60)_
|
||||||
|
* `修复` floaty 模块构建的浮动窗口与系统状态栏重叠的问题
|
||||||
|
* `修复` http.postMultipart 方法功能异常 _[`issue #56`](http://issues.autojs6.com/56)_
|
||||||
|
* `修复` Android 7.x 无法运行任何脚本的问题 _[`issue #61`](http://issues.autojs6.com/61)_
|
||||||
|
* `修复` sign.property 文件不存在时无法构建项目的问题
|
||||||
|
* `修复` 高版本系统 AutoJs6 置于后台时可能因无前台通知权限而崩溃的问题 (API >= 33)
|
||||||
|
* `修复` 调用 console.show 方法后日志窗口点击 FAB 按钮无法清空日志的问题
|
||||||
|
* `修复` 脚本编辑器调试时出现的 prototype 空指针异常
|
||||||
|
* `修复` 脚本编辑器运行脚本时在缓存文件夹运行临时脚本而非先保存再在原始位置运行以避免可能的脚本内容丢失问题
|
||||||
|
* `修复` 调整布局层次分析的层级色条宽度避免层级过多时控件名称无法显示的问题 _[`issue #46`](http://issues.autojs6.com/46)_
|
||||||
|
* `优化` 布局分析浮动窗口增加退出按钮以关闭窗口 _[`issue #63`](http://issues.autojs6.com/63)_
|
||||||
|
* `优化` 脚本绝对路径使用简称形式以缩减文本长度并增加可读性
|
||||||
|
* `优化` 将 Error 替换为 Exception 避免出现异常时 AutoJs6 应用崩溃
|
||||||
|
* `优化` 视图 (View) 绑定方式由 ButterKnife 迁移至 View Binding _[`issue #48`](http://issues.autojs6.com/48)_
|
||||||
|
* `优化` 服务端模式非正常关闭时将于 AutoJs6 启动时自动开启 _[`issue #64`](http://issues.autojs6.com/64)_
|
||||||
|
* `优化` 客户端模式非正常关闭时将于 AutoJs6 启动时按最近一次的历史地址自动连接
|
||||||
|
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](http://project.autojs6.com/blob/master/app/src/main/assets/doc/CHANGELOG.md#v631)_
|
||||||
|
|
||||||
# v6.3.0
|
# v6.3.0
|
||||||
|
|
||||||
###### 2023/04/29
|
###### 2023/04/29
|
||||||
@@ -259,19 +291,6 @@
|
|||||||
* `优化` 重新设计 colors 全局对象并增加 HSV / HSL 等色彩模式支持 (参阅 项目文档 > [颜色](https://docs.autojs6.com/#/color))
|
* `优化` 重新设计 colors 全局对象并增加 HSV / HSL 等色彩模式支持 (参阅 项目文档 > [颜色](https://docs.autojs6.com/#/color))
|
||||||
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](http://project.autojs6.com/blob/master/app/src/main/assets/doc/CHANGELOG.md#v620)_
|
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](http://project.autojs6.com/blob/master/app/src/main/assets/doc/CHANGELOG.md#v620)_
|
||||||
|
|
||||||
# v6.1.1
|
|
||||||
|
|
||||||
###### 2022/05/31
|
|
||||||
|
|
||||||
* `新增` 检查更新/下载更新/更新提示功能 (参阅 设置页面) (暂不支持安卓 7.x 系统)
|
|
||||||
* `修复` 应用在安卓 10 系统无法读写外部存储的问题 _[`issue #17`](http://issues.autojs6.com/17)_
|
|
||||||
* `修复` 编辑器页面长按时可能导致应用崩溃的问题 _[`issue #18`](http://issues.autojs6.com/18)_
|
|
||||||
* `修复` 编辑器页面长按菜单 "删除行" 和 "复制行" 功能无效的问题
|
|
||||||
* `修复` 编辑器页面选项菜单中 "粘贴" 功能缺失的问题
|
|
||||||
* `优化` 部分异常消息字符串资源化 (en / zh)
|
|
||||||
* `优化` 调整内容未保存对话框的按钮布局并增加颜色区分
|
|
||||||
* `优化` 部分依赖或本地库版本调整 _[`CHANGELOG.md`](http://project.autojs6.com/blob/master/app/src/main/assets/doc/CHANGELOG.md#v611)_
|
|
||||||
|
|
||||||
##### 更多版本历史可参阅
|
##### 更多版本历史可参阅
|
||||||
|
|
||||||
* [CHANGELOG.md](http://changelog.autojs6.com)
|
* [CHANGELOG.md](http://changelog.autojs6.com)
|
||||||
@@ -297,12 +316,12 @@
|
|||||||
|
|
||||||
#### Android Studio 准备
|
#### Android Studio 准备
|
||||||
|
|
||||||
下载 `Android Studio Flamingo | 2022.2.1` 版本 (按需选择其一):
|
下载 `Android Studio Flamingo | 2022.2.1 Patch 2` 版本 (按需选择其一):
|
||||||
|
|
||||||
- [android-studio-2022.2.1.18-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2022.2.1.18/android-studio-2022.2.1.18-windows.exe) (1.0 GB)
|
- [android-studio-2022.2.1.20-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2022.2.1.20/android-studio-2022.2.1.20-windows.exe) (1.0 GB)
|
||||||
- [android-studio-2022.2.1.18-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2022.2.1.18/android-studio-2022.2.1.18-windows.zip) (1.0 GB)
|
- [android-studio-2022.2.1.20-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2022.2.1.20/android-studio-2022.2.1.20-windows.zip) (1.0 GB)
|
||||||
|
|
||||||
> 注: 如需下载其他版本, 或上述链接已失效, 可前往 [Android Studio 发行版本归档](https://developer.android.com/studio/archive) 页面.
|
> 注: 上述版本发布时间为 2023 年 5 月 24 日. 如需下载其他版本, 或上述链接已失效, 可访问 [Android Studio 发行版本归档](https://developer.android.com/studio/archive) 页面.
|
||||||
|
|
||||||
安装或解压上述文件, 运行 Android Studio 软件 (如 `"D:\android-studio\bin\studio64.exe"`).
|
安装或解压上述文件, 运行 Android Studio 软件 (如 `"D:\android-studio\bin\studio64.exe"`).
|
||||||
|
|
||||||
|
|||||||
+25
-22
@@ -21,12 +21,12 @@ plugins {
|
|||||||
|
|
||||||
dependencies /* Unclassified */ {
|
dependencies /* Unclassified */ {
|
||||||
// LeakCanary
|
// LeakCanary
|
||||||
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.10")
|
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.11")
|
||||||
|
|
||||||
// Android supports
|
// Android supports
|
||||||
implementation("androidx.cardview:cardview:1.0.0")
|
implementation("androidx.cardview:cardview:1.0.0")
|
||||||
implementation("androidx.multidex:multidex:2.0.1")
|
implementation("androidx.multidex:multidex:2.0.1")
|
||||||
implementation("com.google.android.material:material:1.8.0")
|
implementation("com.google.android.material:material:1.9.0")
|
||||||
|
|
||||||
// SwipeRefreshLayout
|
// SwipeRefreshLayout
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
@@ -60,10 +60,10 @@ dependencies /* Unclassified */ {
|
|||||||
implementation(project(":libs:com.tencent.bugly.crashreport-4.0.4"))
|
implementation(project(":libs:com.tencent.bugly.crashreport-4.0.4"))
|
||||||
|
|
||||||
// OkHttp
|
// OkHttp
|
||||||
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.9")
|
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.11")
|
||||||
|
|
||||||
// Webkit
|
// Webkit
|
||||||
implementation("androidx.webkit:webkit:1.6.1")
|
implementation("androidx.webkit:webkit:1.7.0")
|
||||||
|
|
||||||
// Gson
|
// Gson
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
@@ -76,6 +76,7 @@ dependencies /* Unclassified */ {
|
|||||||
implementation("log4j:log4j:1.2.17")
|
implementation("log4j:log4j:1.2.17")
|
||||||
|
|
||||||
// Preference
|
// Preference
|
||||||
|
implementation("androidx.preference:preference:1.2.0")
|
||||||
implementation("androidx.preference:preference-ktx:1.2.0")
|
implementation("androidx.preference:preference-ktx:1.2.0")
|
||||||
|
|
||||||
// RootShell
|
// RootShell
|
||||||
@@ -138,10 +139,6 @@ dependencies /* Annotations */ {
|
|||||||
// JCIP Annotations
|
// JCIP Annotations
|
||||||
implementation("net.jcip:jcip-annotations:1.0")
|
implementation("net.jcip:jcip-annotations:1.0")
|
||||||
|
|
||||||
// ButterKnife
|
|
||||||
kapt("com.jakewharton:butterknife-compiler:10.2.3")
|
|
||||||
implementation("com.jakewharton:butterknife:10.2.3")
|
|
||||||
|
|
||||||
// EventBus
|
// EventBus
|
||||||
implementation("org.greenrobot:eventbus:3.3.1")
|
implementation("org.greenrobot:eventbus:3.3.1")
|
||||||
}
|
}
|
||||||
@@ -218,7 +215,7 @@ dependencies /* GitHub API */ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies /* MLKit */ {
|
dependencies /* MLKit */ {
|
||||||
implementation("com.google.mlkit:text-recognition-chinese:16.0.0-beta6")
|
implementation("com.google.mlkit:text-recognition-chinese:16.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies /* Auto.js Extensions */ {
|
dependencies /* Auto.js Extensions */ {
|
||||||
@@ -319,21 +316,27 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
arrayOf(
|
val proguardFiles = arrayOf(
|
||||||
getDefaultProguardFile("proguard-android.txt"),
|
getDefaultProguardFile("proguard-android.txt"),
|
||||||
"proguard-rules.pro",
|
"proguard-rules.pro",
|
||||||
).let { proguardFiles ->
|
)
|
||||||
getByName("release") {
|
val niceSigningConfig = takeIf { sign.isValid }?.let {
|
||||||
isMinifyEnabled = false
|
signingConfigs.getByName("release")
|
||||||
proguardFiles(*proguardFiles)
|
|
||||||
signingConfig = takeIf { sign.isValid }?.let { signingConfigs.getByName("release") }
|
|
||||||
}
|
|
||||||
getByName("debug") {
|
|
||||||
isMinifyEnabled = getByName("release").isMinifyEnabled
|
|
||||||
proguardFiles(*proguardFiles)
|
|
||||||
signingConfig = getByName("release").signingConfig
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
getByName("release") {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(*proguardFiles)
|
||||||
|
niceSigningConfig?.let { signingConfig = it }
|
||||||
|
}
|
||||||
|
getByName("debug") {
|
||||||
|
isMinifyEnabled = getByName("release").isMinifyEnabled
|
||||||
|
proguardFiles(*proguardFiles)
|
||||||
|
niceSigningConfig?.let { signingConfig = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding = true
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@@ -348,7 +351,7 @@ android {
|
|||||||
).let { arguments(it) }
|
).let { arguments(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buildConfigField("String", "VERSION_DATE", "\"${Utils.getDateString("MMM dd, yyyy", "GMT+08:00")}\"")
|
buildConfigField("String", "VERSION_DATE", "\"${Utils.getDateString("MMM d, yyyy", "GMT+08:00")}\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationVariants.all {
|
applicationVariants.all {
|
||||||
|
|||||||
Vendored
+2
@@ -35,6 +35,7 @@
|
|||||||
-keep class org.greenrobot.eventbus.** { *; }
|
-keep class org.greenrobot.eventbus.** { *; }
|
||||||
-keep class * extends c
|
-keep class * extends c
|
||||||
-keepattributes *Annotation*
|
-keepattributes *Annotation*
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
# Event bus
|
# Event bus
|
||||||
-keepclassmembers class ** {
|
-keepclassmembers class ** {
|
||||||
@org.greenrobot.eventbus.Subscribe <methods>;
|
@org.greenrobot.eventbus.Subscribe <methods>;
|
||||||
@@ -108,6 +109,7 @@
|
|||||||
|
|
||||||
-keepclasseswithmembers class * {
|
-keepclasseswithmembers class * {
|
||||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int, int);
|
||||||
}
|
}
|
||||||
# Google Play Services library
|
# Google Play Services library
|
||||||
-keep class * extends java.util.ListResourceBundle {
|
-keep class * extends java.util.ListResourceBundle {
|
||||||
|
|||||||
@@ -61,6 +61,9 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
|
<!-- To allow posting notifications on Android 13. -->
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
@@ -122,7 +125,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.main.MainActivity_"
|
android:name="org.autojs.autojs.ui.main.MainActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/AppTheme.FullScreen" />
|
android:theme="@style/AppTheme.FullScreen" />
|
||||||
|
|
||||||
@@ -151,7 +154,7 @@
|
|||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.edit.EditActivity_"
|
android:name="org.autojs.autojs.ui.edit.EditActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|locale"
|
android:configChanges="orientation|keyboardHidden|screenSize|locale"
|
||||||
android:launchMode="standard"
|
android:launchMode="standard"
|
||||||
android:multiprocess="true"
|
android:multiprocess="true"
|
||||||
@@ -159,36 +162,36 @@
|
|||||||
android:theme="@style/EditorTheme" />
|
android:theme="@style/EditorTheme" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.settings.AboutActivity_"
|
android:name="org.autojs.autojs.ui.settings.AboutActivity"
|
||||||
android:theme="@style/AppTheme.Settings" />
|
android:theme="@style/AppTheme.Settings" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.settings.SettingsActivity_"
|
android:name="org.autojs.autojs.ui.settings.PreferencesActivity"
|
||||||
android:theme="@style/AppTheme.Settings" />
|
android:theme="@style/AppTheme.Settings" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.settings.DeveloperOptionsActivity_"
|
android:name="org.autojs.autojs.ui.settings.DeveloperOptionsActivity"
|
||||||
android:theme="@style/AppTheme.Settings" />
|
android:theme="@style/AppTheme.Settings" />
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.ui.error.ErrorReportActivity" />
|
<activity android:name="org.autojs.autojs.ui.error.ErrorReportActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.external.tasker.TaskerScriptEditActivity_"
|
android:name="org.autojs.autojs.external.tasker.TaskerScriptEditActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|locale" />
|
android:configChanges="orientation|keyboardHidden|screenSize|locale" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.project.BuildActivity_"
|
android:name="org.autojs.autojs.ui.project.BuildActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize|locale" />
|
android:configChanges="orientation|keyboardHidden|screenSize|locale" />
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.ui.project.ProjectConfigActivity_" />
|
<activity android:name="org.autojs.autojs.ui.project.ProjectConfigActivity" />
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.ui.log.LogActivity_" />
|
<activity android:name="org.autojs.autojs.ui.log.LogActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.doc.DocumentationActivity_"
|
android:name="org.autojs.autojs.ui.doc.DocumentationActivity"
|
||||||
android:label="@string/docs_app_name"
|
android:label="@string/docs_app_name"
|
||||||
android:icon="@drawable/ic_docs_app"
|
android:icon="@drawable/ic_docs_app"
|
||||||
android:taskAffinity="org.autojs.autojs.ui.doc.DocumentationActivity_"
|
android:taskAffinity="org.autojs.autojs.ui.doc.DocumentationActivity"
|
||||||
android:theme="@style/AppTheme.FullScreen"
|
android:theme="@style/AppTheme.FullScreen"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
||||||
@@ -202,16 +205,16 @@
|
|||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.ui.shortcut.AppsIconSelectActivity_" />
|
<activity android:name="org.autojs.autojs.ui.shortcut.AppsIconSelectActivity" />
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.ui.timing.TimedTaskSettingActivity_" />
|
<activity android:name="org.autojs.autojs.ui.timing.TimedTaskSettingActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.ui.shortcut.ShortcutCreateActivity"
|
android:name="org.autojs.autojs.ui.shortcut.ShortcutCreateActivity"
|
||||||
android:theme="@style/AppTheme.Transparent" />
|
android:theme="@style/AppTheme.Transparent" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.autojs.autojs.external.widget.ScriptWidgetSettingsActivity_"
|
android:name="org.autojs.autojs.external.widget.ScriptWidgetSettingsActivity"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -234,7 +237,7 @@
|
|||||||
|
|
||||||
<service android:name="org.autojs.autojs.external.ScriptExecutionIntentService" />
|
<service android:name="org.autojs.autojs.external.ScriptExecutionIntentService" />
|
||||||
|
|
||||||
<activity android:name="org.autojs.autojs.external.tasker.TaskPrefEditActivity_" />
|
<activity android:name="org.autojs.autojs.external.tasker.TaskPrefEditActivity" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="org.autojs.autojs.external.tile.LayoutBoundsTile"
|
android:name="org.autojs.autojs.external.tile.LayoutBoundsTile"
|
||||||
@@ -275,7 +278,7 @@
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:icon="@drawable/autojs6_material"
|
android:icon="@drawable/autojs6_material"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:targetActivity="org.autojs.autojs.external.tasker.TaskPrefEditActivity_"
|
android:targetActivity="org.autojs.autojs.external.tasker.TaskPrefEditActivity"
|
||||||
tools:ignore="ExportedActivity">
|
tools:ignore="ExportedActivity">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
@@ -4,6 +4,42 @@
|
|||||||
|
|
||||||
******
|
******
|
||||||
|
|
||||||
|
# v6.3.1
|
||||||
|
|
||||||
|
###### 2023/05/26
|
||||||
|
|
||||||
|
* `新增` 发布通知权限及主页抽屉开关 _[`issue #55`](http://issues.autojs6.com/55)_
|
||||||
|
* `新增` UI 模式支持简单的 Android 布局解析 (参阅 示例代码 > 布局 > 简单安卓布局)
|
||||||
|
* `新增` UI 模式增加 console / imagebutton / ratingbar / switch / textclock / togglebutton 等控件
|
||||||
|
* `新增` UI 模式控件的颜色色值支持 [OmniColor](https://docs.autojs6.com/#/omniTypes?id=omnicolor) 类型 (如 color="orange")
|
||||||
|
* `新增` UI 模式的控件完全支持 attr 方法设置控件属性 (如 ui.text.attr('color', 'blue'))
|
||||||
|
* `新增` UI 模式控件支持布尔类型属性值的缺省形式 (如 clickable="true" 可简写为 clickable 或 isClickable)
|
||||||
|
* `新增` button 控件支持 isColored 及 isBorderless 布尔类型属性
|
||||||
|
* `新增` console.resetGlobalLogConfig 方法用于重置全局日志配置
|
||||||
|
* `新增` web.newWebSocket 方法用于创建 Web Socket 实例 (参阅 项目文档 > [万维网](https://docs.autojs6.com/#/web?id=m-newwebsocket))
|
||||||
|
* `修复` 文件管理器的文件夹排序异常
|
||||||
|
* `修复` floaty 模块构建的浮动窗口无法调节样式及位置的问题 _[`issue #60`](http://issues.autojs6.com/60)_
|
||||||
|
* `修复` floaty 模块构建的浮动窗口与系统状态栏重叠的问题
|
||||||
|
* `修复` http.postMultipart 方法功能异常 _[`issue #56`](http://issues.autojs6.com/56)_
|
||||||
|
* `修复` Android 7.x 无法运行任何脚本的问题 _[`issue #61`](http://issues.autojs6.com/61)_
|
||||||
|
* `修复` sign.property 文件不存在时无法构建项目的问题
|
||||||
|
* `修复` 高版本系统 AutoJs6 置于后台时可能因无前台通知权限而崩溃的问题 (API >= 33)
|
||||||
|
* `修复` 调用 console.show 方法后日志窗口点击 FAB 按钮无法清空日志的问题
|
||||||
|
* `修复` 脚本编辑器调试时出现的 prototype 空指针异常
|
||||||
|
* `修复` 脚本编辑器运行脚本时在缓存文件夹运行临时脚本而非先保存再在原始位置运行以避免可能的脚本内容丢失问题
|
||||||
|
* `修复` 调整布局层次分析的层级色条宽度避免层级过多时控件名称无法显示的问题 _[`issue #46`](http://issues.autojs6.com/46)_
|
||||||
|
* `优化` 布局分析浮动窗口增加退出按钮以关闭窗口 _[`issue #63`](http://issues.autojs6.com/63)_
|
||||||
|
* `优化` 脚本绝对路径使用简称形式以缩减文本长度并增加可读性
|
||||||
|
* `优化` 将 Error 替换为 Exception 避免出现异常时 AutoJs6 应用崩溃
|
||||||
|
* `优化` 视图 (View) 绑定方式由 ButterKnife 迁移至 View Binding _[`issue #48`](http://issues.autojs6.com/48)_
|
||||||
|
* `优化` 服务端模式非正常关闭时将于 AutoJs6 启动时自动开启 _[`issue #64`](http://issues.autojs6.com/64)_
|
||||||
|
* `优化` 客户端模式非正常关闭时将于 AutoJs6 启动时按最近一次的历史地址自动连接
|
||||||
|
* `优化` 升级 Leakcanary 版本 2.10 -> 2.11
|
||||||
|
* `优化` 升级 Android Material 版本 1.8.0 -> 1.9.0
|
||||||
|
* `优化` 升级 Androidx WebKit 版本 1.6.1 -> 1.7.0
|
||||||
|
* `优化` 升级 Okhttp3 版本 3.10.0 -> 5.0.0-alpha.9 -> 5.0.0-alpha.11
|
||||||
|
* `优化` 升级 MLKit Text Recognition Chinese 版本 16.0.0-beta6 -> 16.0.0
|
||||||
|
|
||||||
# v6.3.0
|
# v6.3.0
|
||||||
|
|
||||||
###### 2023/04/29
|
###### 2023/04/29
|
||||||
@@ -347,7 +383,7 @@
|
|||||||
* `新增` 主页抽屉底部增加重启应用按钮
|
* `新增` 主页抽屉底部增加重启应用按钮
|
||||||
* `新增` 主页抽屉增加忽略电池优化/显示在其他应用上层等开关
|
* `新增` 主页抽屉增加忽略电池优化/显示在其他应用上层等开关
|
||||||
* `修复` 应用初始安装后部分区域主题颜色渲染异常的问题
|
* `修复` 应用初始安装后部分区域主题颜色渲染异常的问题
|
||||||
* `修复` sign.property 不存在时无法 build 的问题
|
* `修复` sign.property 文件不存在时无法构建项目的问题
|
||||||
* `修复` 定时任务面板一次性任务的月份存取错误
|
* `修复` 定时任务面板一次性任务的月份存取错误
|
||||||
* `修复` 应用设置页面开关颜色不随主题变更的问题
|
* `修复` 应用设置页面开关颜色不随主题变更的问题
|
||||||
* `修复` 无法识别打包插件及打包插件下载地址无效的问题
|
* `修复` 无法识别打包插件及打包插件下载地址无效的问题
|
||||||
|
|||||||
@@ -1532,6 +1532,10 @@
|
|||||||
<li><span class="stability_undefined"><a href="#console_setgloballogconfig_config">setGlobalLogConfig(config)</a></span></li>
|
<li><span class="stability_undefined"><a href="#console_setgloballogconfig_config">setGlobalLogConfig(config)</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li><span class="stability_undefined"><a href="#console_m_resetgloballogconfig">[m] resetGlobalLogConfig</a></span><ul>
|
||||||
|
<li><span class="stability_undefined"><a href="#console_resetgloballogconfig">resetGlobalLogConfig()</a></span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li><span class="stability_undefined"><a href="#console_m_input">[m] input</a></span><ul>
|
<li><span class="stability_undefined"><a href="#console_m_input">[m] input</a></span><ul>
|
||||||
<li><span class="stability_undefined"><a href="#console_input_data_args">input(data, ...args)</a></span></li>
|
<li><span class="stability_undefined"><a href="#console_input_data_args">input(data, ...args)</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -2017,6 +2021,10 @@
|
|||||||
<li><span class="stability_undefined"><a href="#web_newinjectablewebclient">newInjectableWebClient()</a></span></li>
|
<li><span class="stability_undefined"><a href="#web_newinjectablewebclient">newInjectableWebClient()</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li><span class="stability_undefined"><a href="#web_m_newwebsocket">[m] newWebSocket</a></span><ul>
|
||||||
|
<li><span class="stability_undefined"><a href="#web_newwebsocket_url">newWebSocket(url)</a></span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li><span class="stability_undefined"><a href="#http_http">HTTP</a></span><ul>
|
<li><span class="stability_undefined"><a href="#http_http">HTTP</a></span><ul>
|
||||||
@@ -2541,7 +2549,7 @@ console.log(UiObject.bounds()); /* 访问的是类 UiObject 的静态方法 boun
|
|||||||
<h3>OCR 特性<span><a class="mark" href="#qa_ocr" id="qa_ocr">#</a></span></h3>
|
<h3>OCR 特性<span><a class="mark" href="#qa_ocr" id="qa_ocr">#</a></span></h3>
|
||||||
<p>AutoJs6 的 OCR 特性是基于 <a href="https://developers.google.com/ml-kit?hl=zh-cn">Google ML Kit</a> 的 <a href="https://developers.google.com/ml-kit/vision/text-recognition/android?hl=zh-cn">文字识别 API</a> 实现的.</p>
|
<p>AutoJs6 的 OCR 特性是基于 <a href="https://developers.google.com/ml-kit?hl=zh-cn">Google ML Kit</a> 的 <a href="https://developers.google.com/ml-kit/vision/text-recognition/android?hl=zh-cn">文字识别 API</a> 实现的.</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: AutoJs6 的 <a href="http://project.autojs6.com/blob/master/app/src/main/java/org/autojs/autojs/runtime/api/MlKitOCR.kt">OCR 实现源码</a> 参考自 <a href="https://github.com/TonyJiangWJ">TonyJiangWJ</a> 的开源项目.</p>
|
<p>注: AutoJs6 的 <a href="http://project.autojs6.com/blob/master/app/src/main/java/org/autojs/autojs/runtime/api/MlKitOCR.kt">OCR 实现源码</a> 参考自 <a href="https://github.com/TonyJiangWJ">TonyJiangWJ</a> 的 <a href="https://github.com/TonyJiangWJ/Auto.js">开源项目</a>.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>参阅: <a href="ocr.html">光学字符识别 (OCR)</a> 模块</p>
|
<p>参阅: <a href="ocr.html">光学字符识别 (OCR)</a> 模块</p>
|
||||||
@@ -7615,7 +7623,7 @@ ocr.recognizeText(img, [ 0, 0, 100, 150 ]).filter(text => text.includes('
|
|||||||
<pre><code class="lang-js">ocr.recognizeText('./picture.jpg'); /* 获取本地图像文件中的所有文本. */
|
<pre><code class="lang-js">ocr.recognizeText('./picture.jpg'); /* 获取本地图像文件中的所有文本. */
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3>recognizeText(imgPath, region)<span><a class="mark" href="#ocr_recognizetext_imgpath_region" id="ocr_recognizetext_imgpath_region">#</a></span></h3>
|
<h3>recognizeText(imgPath, region)<span><a class="mark" href="#ocr_recognizetext_imgpath_region" id="ocr_recognizetext_imgpath_region">#</a></span></h3>
|
||||||
<p><strong><code>6.3.0</code></strong> <strong><code>Overload [4-5]/6</code></strong></p>
|
<p><strong><code>6.3.0</code></strong> <strong><code>Overload 6/6</code></strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>imgPath</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> } - 图像路径</li>
|
<li><strong>imgPath</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> } - 图像路径</li>
|
||||||
<li><strong>region</strong> { <span class="type"><a href="omniTypes.html#omnitypes_omniregion">OmniRegion</a></span> } - OCR 识别区域</li>
|
<li><strong>region</strong> { <span class="type"><a href="omniTypes.html#omnitypes_omniregion">OmniRegion</a></span> } - OCR 识别区域</li>
|
||||||
@@ -10278,6 +10286,14 @@ console.timeEnd('fruit');
|
|||||||
maxFileSize: 384 << 10, /* 384 KB. */
|
maxFileSize: 384 << 10, /* 384 KB. */
|
||||||
});
|
});
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<h2>[m] resetGlobalLogConfig<span><a class="mark" href="#console_m_resetgloballogconfig" id="console_m_resetgloballogconfig">#</a></span></h2>
|
||||||
|
<h3>resetGlobalLogConfig()<span><a class="mark" href="#console_resetgloballogconfig" id="console_resetgloballogconfig">#</a></span></h3>
|
||||||
|
<p><strong><code>6.3.1</code></strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
|
</ul>
|
||||||
|
<p>重置全局日志写入配置.</p>
|
||||||
|
<p>此方法可重置 <a href="#all_m_setgloballogconfig">setGlobalLogConfig</a> 的全部选项配置.</p>
|
||||||
<h2>[m] input<span><a class="mark" href="#console_m_input" id="console_m_input">#</a></span></h2>
|
<h2>[m] input<span><a class="mark" href="#console_m_input" id="console_m_input">#</a></span></h2>
|
||||||
<h3>input(data, ...args)<span><a class="mark" href="#console_input_data_args" id="console_input_data_args">#</a></span></h3>
|
<h3>input(data, ...args)<span><a class="mark" href="#console_input_data_args" id="console_input_data_args">#</a></span></h3>
|
||||||
<p><strong><code>ABANDONED</code></strong></p>
|
<p><strong><code>ABANDONED</code></strong></p>
|
||||||
@@ -10286,7 +10302,7 @@ console.timeEnd('fruit');
|
|||||||
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
||||||
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>此方法已于 <code>6.3.0</code> 版本被废弃, 使用后将无任何效果.</p>
|
<p>此方法已于 <code>6.3.1</code> 版本被废弃, 使用后将无任何效果.</p>
|
||||||
<h2>[m] rawInput<span><a class="mark" href="#console_m_rawinput" id="console_m_rawinput">#</a></span></h2>
|
<h2>[m] rawInput<span><a class="mark" href="#console_m_rawinput" id="console_m_rawinput">#</a></span></h2>
|
||||||
<h3>rawInput(data, ...args)<span><a class="mark" href="#console_rawinput_data_args" id="console_rawinput_data_args">#</a></span></h3>
|
<h3>rawInput(data, ...args)<span><a class="mark" href="#console_rawinput_data_args" id="console_rawinput_data_args">#</a></span></h3>
|
||||||
<p><strong><code>ABANDONED</code></strong></p>
|
<p><strong><code>ABANDONED</code></strong></p>
|
||||||
@@ -10295,7 +10311,7 @@ console.timeEnd('fruit');
|
|||||||
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
||||||
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>此方法已于 <code>6.3.0</code> 版本被废弃, 使用后将无任何效果.
|
<p>此方法已于 <code>6.3.1</code> 版本被废弃, 使用后将无任何效果.
|
||||||
<!-- [end-include:console.md] --></p>
|
<!-- [end-include:console.md] --></p>
|
||||||
<!-- [start-include:shell.md] -->
|
<!-- [start-include:shell.md] -->
|
||||||
<h1>Shell<span><a class="mark" href="#shell_shell" id="shell_shell">#</a></span></h1>
|
<h1>Shell<span><a class="mark" href="#shell_shell" id="shell_shell">#</a></span></h1>
|
||||||
@@ -13433,6 +13449,73 @@ settings.setDisplayZoomControls(false);
|
|||||||
<pre><code class="lang-js">/* 为 webView 对象重新设置一个新的客户端. */
|
<pre><code class="lang-js">/* 为 webView 对象重新设置一个新的客户端. */
|
||||||
webView.setWebViewClient(newInjectableWebClient());
|
webView.setWebViewClient(newInjectableWebClient());
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<h2>[m] newWebSocket<span><a class="mark" href="#web_m_newwebsocket" id="web_m_newwebsocket">#</a></span></h2>
|
||||||
|
<h3>newWebSocket(url)<span><a class="mark" href="#web_newwebsocket_url" id="web_newwebsocket_url">#</a></span></h3>
|
||||||
|
<p><strong><code>6.3.1</code></strong> <strong><code>Global</code></strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>url</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
|
||||||
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="webSocketType.html">WebSocket</a></span> }</li>
|
||||||
|
</ul>
|
||||||
|
<p>新建并返回一个 <a href="webSocketType.html">WebSocket</a> 实例.</p>
|
||||||
|
<pre><code class="lang-js">console.setExitOnClose(7e3).show();
|
||||||
|
|
||||||
|
let ws = web.newWebSocket('wss://echo.websocket.events');
|
||||||
|
|
||||||
|
ws
|
||||||
|
.on('open', (res, ws) => {
|
||||||
|
console.log('WebSocket 已连接');
|
||||||
|
})
|
||||||
|
.on('message', (message, ws) => {
|
||||||
|
console.log('接收到消息');
|
||||||
|
// if (message instanceof okio.ByteString) {
|
||||||
|
// console.log(`消息类型: ByteString`);
|
||||||
|
// } else if (typeof message === 'string') {
|
||||||
|
// console.log(`消息类型: String`);
|
||||||
|
// } else {
|
||||||
|
// throw TypeError('Should never happen');
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
.on('text', (text, ws) => {
|
||||||
|
console.info('接收到文本消息:');
|
||||||
|
console.info(`text: ${text}`);
|
||||||
|
})
|
||||||
|
.on('bytes', (bytes, ws) => {
|
||||||
|
console.info('接收到字节数组消息:');
|
||||||
|
console.info(`utf8: ${bytes.utf8()}`);
|
||||||
|
console.info(`base64: ${bytes.base64()}`);
|
||||||
|
console.info(`md5: ${bytes.md5()}`);
|
||||||
|
console.info(`hex: ${bytes.hex()}`);
|
||||||
|
})
|
||||||
|
.on('closing', (code, reason, ws) => {
|
||||||
|
console.log('WebSocket 关闭中');
|
||||||
|
})
|
||||||
|
.on('closed', (code, reason, ws) => {
|
||||||
|
console.log('WebSocket 已关闭');
|
||||||
|
console.log(`code: ${code}`);
|
||||||
|
if (reason) console.log(`reason: ${reason}`);
|
||||||
|
})
|
||||||
|
.on('failure', (err, res, ws) => {
|
||||||
|
console.error('WebSocket 连接失败');
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 发送文本消息. */
|
||||||
|
ws.send('Hello WebSocket');
|
||||||
|
|
||||||
|
/* 发送字节数组消息. */
|
||||||
|
ws.send(new okio.ByteString(new java.lang.String('Hello WebSocket').getBytes()));
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('断开 WebSocket');
|
||||||
|
|
||||||
|
/* code 支持的范围 [1000,5000). */
|
||||||
|
/* 1000 表示成功操作或常规的 Socket 关闭操作. */
|
||||||
|
/* 参阅 https://github.com/Luka967/websocket-close-codes */
|
||||||
|
ws.close(1000, 'Closed by user');
|
||||||
|
}, 8e3);
|
||||||
|
|
||||||
|
setTimeout(() => console.log('Exit'), 9e3);
|
||||||
|
</code></pre>
|
||||||
<!-- [end-include:web.md] -->
|
<!-- [end-include:web.md] -->
|
||||||
<!-- [start-include:http.md] -->
|
<!-- [start-include:http.md] -->
|
||||||
<h1>HTTP<span><a class="mark" href="#http_http" id="http_http">#</a></span></h1>
|
<h1>HTTP<span><a class="mark" href="#http_http" id="http_http">#</a></span></h1>
|
||||||
@@ -13441,7 +13524,7 @@ webView.setWebViewClient(newInjectableWebClient());
|
|||||||
<p style="font: italic 1em sans-serif; color: #78909C">Marked by SuperMonster003 on Mar 21, 2023.</p>
|
<p style="font: italic 1em sans-serif; color: #78909C">Marked by SuperMonster003 on Mar 21, 2023.</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>http模块提供一些进行http请求的函数.</p>
|
<p>http 模块主要用于发送 HTTP 请求, 获取并解析 HTTP 响应.</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: 与 <a href="web.html">web</a> 模块不同, web 模块主要用于 WebView 网页的注入及客户端构建.</p>
|
<p>注: 与 <a href="web.html">web</a> 模块不同, web 模块主要用于 WebView 网页的注入及客户端构建.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@@ -13578,11 +13661,11 @@ log(res.body.string());
|
|||||||
<p>选项options可以包含以下属性:</p>
|
<p>选项options可以包含以下属性:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>headers</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">Object</a> } 键值对形式的HTTP头部信息. 有关HTTP头部信息, 参见<a href="http://www.runoob.com/http/http-header-fields.html">菜鸟教程:HTTP响应头信息</a>.</li>
|
<li><code>headers</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">Object</a> } 键值对形式的HTTP头部信息. 有关HTTP头部信息, 参见<a href="http://www.runoob.com/http/http-header-fields.html">菜鸟教程:HTTP响应头信息</a>.</li>
|
||||||
<li><code>method</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP请求方法. 包括"GET", "POST", "PUT", "DELET", "PATCH".</li>
|
<li><code>method</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP请求方法. 包括"GET", "POST", "PUT", "DELETE", "PATCH".</li>
|
||||||
<li><code>contentType</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型. 例如"text/plain", "application/json". 更多信息参见<a href="http://www.runoob.com/http/http-content-type.html">菜鸟教程:HTTP contentType</a>.</li>
|
<li><code>contentType</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型. 例如"text/plain", "application/json". 更多信息参见<a href="http://www.runoob.com/http/http-content-type.html">菜鸟教程:HTTP contentType</a>.</li>
|
||||||
<li><code>body</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">Array</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">Function</a> } HTTP请求的内容. 可以是一个字符串, 也可以是一个字节数组;或者是一个以<a href="https://github.com/square/okio/blob/master/okio/src/main/java/okio/BufferedSink.java/">BufferedSink</a>为参数的函数.</li>
|
<li><code>body</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">Array</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">Function</a> } HTTP请求的内容. 可以是一个字符串, 也可以是一个字节数组;或者是一个以<a href="https://github.com/square/okio/blob/master/okio/src/main/java/okio/BufferedSink.java/">BufferedSink</a>为参数的函数.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>该函数是get, post, postJson等函数的基础函数. 因此除非是PUT, DELET等请求, 或者需要更高定制的HTTP请求, 否则直接使用get, post, postJson等函数会更加方便.</p>
|
<p>该函数是get, post, postJson等函数的基础函数. 因此除非是PUT, DELETE等请求, 或者需要更高定制的HTTP请求, 否则直接使用get, post, postJson等函数会更加方便.</p>
|
||||||
<h2>[m] buildRequest<span><a class="mark" href="#http_m_buildrequest" id="http_m_buildrequest">#</a></span></h2>
|
<h2>[m] buildRequest<span><a class="mark" href="#http_m_buildrequest" id="http_m_buildrequest">#</a></span></h2>
|
||||||
<h3>buildRequest(url, options)<span><a class="mark" href="#http_buildrequest_url_options" id="http_buildrequest_url_options">#</a></span></h3>
|
<h3>buildRequest(url, options)<span><a class="mark" href="#http_buildrequest_url_options" id="http_buildrequest_url_options">#</a></span></h3>
|
||||||
<p>... ...
|
<p>... ...
|
||||||
|
|||||||
@@ -189,12 +189,20 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td style="text-align:left">35 (?)</td>
|
||||||
|
<td style="text-align:left">Android 15</td>
|
||||||
|
<td style="text-align:left">VANILLA_ICE_CREAM</td>
|
||||||
|
<td style="text-align:left">15</td>
|
||||||
|
<td style="text-align:left">Vanilla Ice Cream</td>
|
||||||
|
<td style="text-align:left">Q3, 2024 (?)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
<td style="text-align:left">34</td>
|
<td style="text-align:left">34</td>
|
||||||
<td style="text-align:left">Android 14</td>
|
<td style="text-align:left">Android 14</td>
|
||||||
<td style="text-align:left">?</td>
|
<td style="text-align:left">UPSIDE_DOWN_CAKE</td>
|
||||||
<td style="text-align:left">14</td>
|
<td style="text-align:left">14</td>
|
||||||
<td style="text-align:left">Upside Down Cake</td>
|
<td style="text-align:left">Upside Down Cake</td>
|
||||||
<td style="text-align:left">Feb 8, 2023</td>
|
<td style="text-align:left">Q3, 2023 (?)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align:left">33</td>
|
<td style="text-align:left">33</td>
|
||||||
@@ -475,6 +483,7 @@
|
|||||||
<p>要求设备 API 级别不低于指定值:</p>
|
<p>要求设备 API 级别不低于指定值:</p>
|
||||||
<pre><code class="lang-js">/* 在 API 级别低于 30 的设备上将抛出异常. */
|
<pre><code class="lang-js">/* 在 API 级别低于 30 的设备上将抛出异常. */
|
||||||
runtime.requiresApi(30);
|
runtime.requiresApi(30);
|
||||||
|
runtime.requiresApi(util.versionCodes.R); /* 效果同上. */
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: AutoJs6 安装及使用需满足的最低 API 级别为 24 (7.0) [N].</p>
|
<p>注: AutoJs6 安装及使用需满足的最低 API 级别为 24 (7.0) [N].</p>
|
||||||
|
|||||||
@@ -166,6 +166,7 @@
|
|||||||
<h2>目录</h2>
|
<h2>目录</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><span class="stability_undefined"><a href="#changelog_changelog">文档更新日志 (Changelog)</a></span><ul>
|
<li><span class="stability_undefined"><a href="#changelog_changelog">文档更新日志 (Changelog)</a></span><ul>
|
||||||
|
<li><span class="stability_undefined"><a href="#changelog_v1_1_4">v1.1.4</a></span></li>
|
||||||
<li><span class="stability_undefined"><a href="#changelog_v1_1_3">v1.1.3</a></span></li>
|
<li><span class="stability_undefined"><a href="#changelog_v1_1_3">v1.1.3</a></span></li>
|
||||||
<li><span class="stability_undefined"><a href="#changelog_v1_1_2">v1.1.2</a></span></li>
|
<li><span class="stability_undefined"><a href="#changelog_v1_1_2">v1.1.2</a></span></li>
|
||||||
<li><span class="stability_undefined"><a href="#changelog_v1_1_1">v1.1.1</a></span></li>
|
<li><span class="stability_undefined"><a href="#changelog_v1_1_1">v1.1.1</a></span></li>
|
||||||
@@ -183,6 +184,15 @@
|
|||||||
|
|
||||||
<div id="apicontent">
|
<div id="apicontent">
|
||||||
<h1>文档更新日志 (Changelog)<span><a class="mark" href="#changelog_changelog" id="changelog_changelog">#</a></span></h1>
|
<h1>文档更新日志 (Changelog)<span><a class="mark" href="#changelog_changelog" id="changelog_changelog">#</a></span></h1>
|
||||||
|
<h2>v1.1.4<span><a class="mark" href="#changelog_v1_1_4" id="changelog_v1_1_4">#</a></span></h2>
|
||||||
|
<p style="font: bold 0.8em sans-serif; color: #888888">2023/05/26</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/console?id=m-resetgloballogconfig">console.resetGlobalLogConfig</a> 文档</li>
|
||||||
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/web?id=m-newwebsocket">web.newWebSocket</a> 文档</li>
|
||||||
|
<li><code>优化</code> 完善 <a href="https://docs.autojs6.com/#/omniTypes">全能类型 (Omnipotent Types)</a> 章节</li>
|
||||||
|
<li><code>优化</code> 完善 <a href="https://docs.autojs6.com/#/apiLevel">安卓 API 级别 (Android API Level)</a> 章节</li>
|
||||||
|
</ul>
|
||||||
<h2>v1.1.3<span><a class="mark" href="#changelog_v1_1_3" id="changelog_v1_1_3">#</a></span></h2>
|
<h2>v1.1.3<span><a class="mark" href="#changelog_v1_1_3" id="changelog_v1_1_3">#</a></span></h2>
|
||||||
<p style="font: bold 0.8em sans-serif; color: #888888">2023/04/29</p>
|
<p style="font: bold 0.8em sans-serif; color: #888888">2023/04/29</p>
|
||||||
|
|
||||||
@@ -211,7 +221,7 @@
|
|||||||
<li><code>新增</code> <a href="https://docs.autojs6.com/#/notice">消息通知 (Notice)</a> 文档</li>
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/notice">消息通知 (Notice)</a> 文档</li>
|
||||||
<li><code>新增</code> <a href="https://docs.autojs6.com/#/httpRequestHeadersType">HttpRequestHeaders</a> / <a href="https://docs.autojs6.com/#/httpResponseHeadersType">HttpResponseHeaders</a> / <a href="https://docs.autojs6.com/#/opencvRectType">OpencvRect</a> 等类型</li>
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/httpRequestHeadersType">HttpRequestHeaders</a> / <a href="https://docs.autojs6.com/#/httpResponseHeadersType">HttpResponseHeaders</a> / <a href="https://docs.autojs6.com/#/opencvRectType">OpencvRect</a> 等类型</li>
|
||||||
<li><code>新增</code> <a href="https://docs.autojs6.com/#/glossaries?id=通知渠道">通知渠道</a> / <a href="https://docs.autojs6.com/#/glossaries?id=HTTP-标头">HTTP 标头</a> / <a href="https://docs.autojs6.com/#/glossaries?id=MIME-类型">MIME 类型</a> / <a href="https://docs.autojs6.com/#/glossaries?id=HTTP-请求方法">HTTP 请求方法</a> 等术语</li>
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/glossaries?id=通知渠道">通知渠道</a> / <a href="https://docs.autojs6.com/#/glossaries?id=HTTP-标头">HTTP 标头</a> / <a href="https://docs.autojs6.com/#/glossaries?id=MIME-类型">MIME 类型</a> / <a href="https://docs.autojs6.com/#/glossaries?id=HTTP-请求方法">HTTP 请求方法</a> 等术语</li>
|
||||||
<li><code>新增</code> <a href="https://docs.autojs6.com/#/color">颜色 (Color)</a> 章节增加 <a href="https://docs.autojs6.com/#/color?id=m-toColorStateList">toColorStateList</a> 及 <a href="https://docs.autojs6.com/#/color?id=m-setPaintColor">setPaintColor</a> 条目</li>
|
<li><code>新增</code> <a href="https://docs.autojs6.com/#/color">颜色 (Color)</a> 章节增加 <a href="https://docs.autojs6.com/#/color?id=m-tocolorstatelist">toColorStateList</a> 及 <a href="https://docs.autojs6.com/#/color?id=m-setpaintcolor">setPaintColor</a> 条目</li>
|
||||||
<li><code>修复</code> 文档更新日志条目中的链接无效的问题</li>
|
<li><code>修复</code> 文档更新日志条目中的链接无效的问题</li>
|
||||||
<li><code>优化</code> 完善 <a href="https://docs.autojs6.com/#/qa">疑难解答 (Q & A)</a> 章节</li>
|
<li><code>优化</code> 完善 <a href="https://docs.autojs6.com/#/qa">疑难解答 (Q & A)</a> 章节</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ c.getRed(); // 255
|
|||||||
c.getRedDouble(); // 1
|
c.getRedDouble(); // 1
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>Color 类是对 <a href="color.html">colors</a> 模块的一种变式封装, 用于解决 colors 模块冗余嵌套的难题.</p>
|
<p>Color 类是对 <a href="color.html">colors</a> 模块的一种变式封装, 用于解决 colors 模块冗余嵌套的难题.</p>
|
||||||
<p>如需对颜色 <code>hsv(174,100,59)</code> 设置 <code>80%</code> 透明度然后返回其 Hex 代码:</p>
|
<p>例如需要对颜色 <code>hsv(174,100,59)</code> 设置 <code>80%</code> 透明度然后返回其 Hex 代码:</p>
|
||||||
<pre><code class="lang-js">colors.toHex(colors.setAlpha(colors.hsv(174, 100, 59), 0.8));
|
<pre><code class="lang-js">colors.toHex(colors.setAlpha(colors.hsv(174, 100, 59), 0.8));
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>或使用变量拆写形式以增加可读性:</p>
|
<p>或使用变量拆写形式以增加可读性:</p>
|
||||||
@@ -422,7 +422,7 @@ colors.toHex(colorWithAlpha);
|
|||||||
.toHex();
|
.toHex();
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: 上述示例仅用于演示, 否则可使用 colors.hsva 或 Color#setHsva 同时设置 HSV 分量与 A 分量.</p>
|
<p>注: 上述示例仅用于演示, 实际可使用 colors.hsva 或 Color#setHsva 同时设置 HSV 分量与 A 分量.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p>Color 实例方法的使用方式与 colors 模块对应方法多数情况是类似的, 因此某些情况下可用于替代 colors 模块.</p>
|
<p>Color 实例方法的使用方式与 colors 模块对应方法多数情况是类似的, 因此某些情况下可用于替代 colors 模块.</p>
|
||||||
<p>以 <code>set</code> 或 <code>remove</code> 为前缀的方法, 通常都会返回 Color 自身类型, 从而支持链式调用, 如 <a href="#colortype_m_setalpha">setAlpha</a>, <a href="#colortype_m_removealpha">removeAlpha</a>, <a href="#colortype_m_setred">setRed</a>, <a href="#colortype_m_removered">removeRed</a>, <a href="#colortype_m_sethsv">setHsv</a>, <a href="#colortype_m_setrgba">setRgba</a> 等.</p>
|
<p>以 <code>set</code> 或 <code>remove</code> 为前缀的方法, 通常都会返回 Color 自身类型, 从而支持链式调用, 如 <a href="#colortype_m_setalpha">setAlpha</a>, <a href="#colortype_m_removealpha">removeAlpha</a>, <a href="#colortype_m_setred">setRed</a>, <a href="#colortype_m_removered">removeRed</a>, <a href="#colortype_m_sethsv">setHsv</a>, <a href="#colortype_m_setrgba">setRgba</a> 等.</p>
|
||||||
|
|||||||
@@ -324,6 +324,10 @@
|
|||||||
<li><span class="stability_undefined"><a href="#console_setgloballogconfig_config">setGlobalLogConfig(config)</a></span></li>
|
<li><span class="stability_undefined"><a href="#console_setgloballogconfig_config">setGlobalLogConfig(config)</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li><span class="stability_undefined"><a href="#console_m_resetgloballogconfig">[m] resetGlobalLogConfig</a></span><ul>
|
||||||
|
<li><span class="stability_undefined"><a href="#console_resetgloballogconfig">resetGlobalLogConfig()</a></span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li><span class="stability_undefined"><a href="#console_m_input">[m] input</a></span><ul>
|
<li><span class="stability_undefined"><a href="#console_m_input">[m] input</a></span><ul>
|
||||||
<li><span class="stability_undefined"><a href="#console_input_data_args">input(data, ...args)</a></span></li>
|
<li><span class="stability_undefined"><a href="#console_input_data_args">input(data, ...args)</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -1174,6 +1178,14 @@ console.timeEnd('fruit');
|
|||||||
maxFileSize: 384 << 10, /* 384 KB. */
|
maxFileSize: 384 << 10, /* 384 KB. */
|
||||||
});
|
});
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
<h2>[m] resetGlobalLogConfig<span><a class="mark" href="#console_m_resetgloballogconfig" id="console_m_resetgloballogconfig">#</a></span></h2>
|
||||||
|
<h3>resetGlobalLogConfig()<span><a class="mark" href="#console_resetgloballogconfig" id="console_resetgloballogconfig">#</a></span></h3>
|
||||||
|
<p><strong><code>6.3.1</code></strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
|
</ul>
|
||||||
|
<p>重置全局日志写入配置.</p>
|
||||||
|
<p>此方法可重置 <a href="#console_m_setgloballogconfig">setGlobalLogConfig</a> 的全部选项配置.</p>
|
||||||
<h2>[m] input<span><a class="mark" href="#console_m_input" id="console_m_input">#</a></span></h2>
|
<h2>[m] input<span><a class="mark" href="#console_m_input" id="console_m_input">#</a></span></h2>
|
||||||
<h3>input(data, ...args)<span><a class="mark" href="#console_input_data_args" id="console_input_data_args">#</a></span></h3>
|
<h3>input(data, ...args)<span><a class="mark" href="#console_input_data_args" id="console_input_data_args">#</a></span></h3>
|
||||||
<p><strong><code>ABANDONED</code></strong></p>
|
<p><strong><code>ABANDONED</code></strong></p>
|
||||||
@@ -1182,7 +1194,7 @@ console.timeEnd('fruit');
|
|||||||
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
||||||
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>此方法已于 <code>6.3.0</code> 版本被废弃, 使用后将无任何效果.</p>
|
<p>此方法已于 <code>6.3.1</code> 版本被废弃, 使用后将无任何效果.</p>
|
||||||
<h2>[m] rawInput<span><a class="mark" href="#console_m_rawinput" id="console_m_rawinput">#</a></span></h2>
|
<h2>[m] rawInput<span><a class="mark" href="#console_m_rawinput" id="console_m_rawinput">#</a></span></h2>
|
||||||
<h3>rawInput(data, ...args)<span><a class="mark" href="#console_rawinput_data_args" id="console_rawinput_data_args">#</a></span></h3>
|
<h3>rawInput(data, ...args)<span><a class="mark" href="#console_rawinput_data_args" id="console_rawinput_data_args">#</a></span></h3>
|
||||||
<p><strong><code>ABANDONED</code></strong></p>
|
<p><strong><code>ABANDONED</code></strong></p>
|
||||||
@@ -1191,7 +1203,7 @@ console.timeEnd('fruit');
|
|||||||
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
<li><strong>args</strong> { <span class="type"><a href="documentation.html#documentation_可变参数">...</a><a href="dataTypes.html#datatypes_any">any</a><a href="documentation.html#documentation_可变参数">[]</a></span> } - <a href="glossaries.html#glossaries_占位符替换参数">占位符替换参数</a></li>
|
||||||
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="dataTypes.html#datatypes_void">void</a></span> }</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>此方法已于 <code>6.3.0</code> 版本被废弃, 使用后将无任何效果.</p>
|
<p>此方法已于 <code>6.3.1</code> 版本被废弃, 使用后将无任何效果.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -309,7 +309,8 @@ console.build({ titleIconsTint: 'green' }).show();
|
|||||||
console.build({ contentTextSize: 18 }).show();
|
console.build({ contentTextSize: 18 }).show();
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h2>[p?] contentTextColor<span><a class="mark" href="#consolebuildoptionstype_p_contenttextcolor" id="consolebuildoptionstype_p_contenttextcolor">#</a></span></h2>
|
<h2>[p?] contentTextColor<span><a class="mark" href="#consolebuildoptionstype_p_contenttextcolor" id="consolebuildoptionstype_p_contenttextcolor">#</a></span></h2>
|
||||||
<div class="signature"><ul>
|
<p><strong><code>Overload 1/2</code></strong></p>
|
||||||
|
<ul>
|
||||||
<li>{{<ul>
|
<li>{{<ul>
|
||||||
<li>verbose?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
<li>verbose?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
||||||
<li>log?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
<li>log?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
||||||
@@ -319,9 +320,9 @@ console.build({ contentTextSize: 18 }).show();
|
|||||||
<li>assert?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
<li>assert?: <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a>;</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>} | <a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a> } - 浮动窗口日志文本字体颜色</li>
|
<li>}} - 浮动窗口日志文本字体颜色</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div><p>设置控制台浮动窗口的日志文本字体颜色, 按日志等级设置一个或多个不同的字体颜色.</p>
|
<p>设置控制台浮动窗口的日志文本字体颜色, 按日志等级设置一个或多个不同的字体颜色.</p>
|
||||||
<pre><code class="lang-js">/* 设置 LOG 等级日志字体颜色为深橙色. */
|
<pre><code class="lang-js">/* 设置 LOG 等级日志字体颜色为深橙色. */
|
||||||
console.build({ contentTextColor: { log: 'dark-orange' } }).show();
|
console.build({ contentTextColor: { log: 'dark-orange' } }).show();
|
||||||
console.log('content text color test for console.log');
|
console.log('content text color test for console.log');
|
||||||
@@ -344,7 +345,11 @@ console.build({
|
|||||||
console[fName].call(console, `content text color test for console.${fName}`);
|
console[fName].call(console, `content text color test for console.${fName}`);
|
||||||
});
|
});
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<p>如果希望不区分日志等级, 统一设置所有日志的文本颜色, 可参考下述示例:</p>
|
<p><strong><code>Overload 2/2</code></strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>{ <span class="type"><a href="omniTypes.html#omnitypes_omnicolor">OmniColor</a></span> } - 浮动窗口日志文本统一字体颜色</li>
|
||||||
|
</ul>
|
||||||
|
<p>使用 <code>{ contentTextColor: OmniColor }</code> 时, 不区分日志等级, 统一设置所有日志的文本颜色:</p>
|
||||||
<pre><code class="lang-js">/* 所有日志本文的颜色统一设置为深绿色. */
|
<pre><code class="lang-js">/* 所有日志本文的颜色统一设置为深绿色. */
|
||||||
console.build({
|
console.build({
|
||||||
contentTextColor: 'dark-green',
|
contentTextColor: 'dark-green',
|
||||||
|
|||||||
@@ -203,7 +203,7 @@
|
|||||||
<p style="font: italic 1em sans-serif; color: #78909C">Marked by SuperMonster003 on Mar 21, 2023.</p>
|
<p style="font: italic 1em sans-serif; color: #78909C">Marked by SuperMonster003 on Mar 21, 2023.</p>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>http模块提供一些进行http请求的函数.</p>
|
<p>http 模块主要用于发送 HTTP 请求, 获取并解析 HTTP 响应.</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: 与 <a href="web.html">web</a> 模块不同, web 模块主要用于 WebView 网页的注入及客户端构建.</p>
|
<p>注: 与 <a href="web.html">web</a> 模块不同, web 模块主要用于 WebView 网页的注入及客户端构建.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@@ -340,11 +340,11 @@ log(res.body.string());
|
|||||||
<p>选项options可以包含以下属性:</p>
|
<p>选项options可以包含以下属性:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>headers</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">Object</a> } 键值对形式的HTTP头部信息. 有关HTTP头部信息, 参见<a href="http://www.runoob.com/http/http-header-fields.html">菜鸟教程:HTTP响应头信息</a>.</li>
|
<li><code>headers</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">Object</a> } 键值对形式的HTTP头部信息. 有关HTTP头部信息, 参见<a href="http://www.runoob.com/http/http-header-fields.html">菜鸟教程:HTTP响应头信息</a>.</li>
|
||||||
<li><code>method</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP请求方法. 包括"GET", "POST", "PUT", "DELET", "PATCH".</li>
|
<li><code>method</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP请求方法. 包括"GET", "POST", "PUT", "DELETE", "PATCH".</li>
|
||||||
<li><code>contentType</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型. 例如"text/plain", "application/json". 更多信息参见<a href="http://www.runoob.com/http/http-content-type.html">菜鸟教程:HTTP contentType</a>.</li>
|
<li><code>contentType</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型. 例如"text/plain", "application/json". 更多信息参见<a href="http://www.runoob.com/http/http-content-type.html">菜鸟教程:HTTP contentType</a>.</li>
|
||||||
<li><code>body</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">Array</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">Function</a> } HTTP请求的内容. 可以是一个字符串, 也可以是一个字节数组;或者是一个以<a href="https://github.com/square/okio/blob/master/okio/src/main/java/okio/BufferedSink.java/">BufferedSink</a>为参数的函数.</li>
|
<li><code>body</code> { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">string</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" class="type">Array</a> } | { <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">Function</a> } HTTP请求的内容. 可以是一个字符串, 也可以是一个字节数组;或者是一个以<a href="https://github.com/square/okio/blob/master/okio/src/main/java/okio/BufferedSink.java/">BufferedSink</a>为参数的函数.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>该函数是get, post, postJson等函数的基础函数. 因此除非是PUT, DELET等请求, 或者需要更高定制的HTTP请求, 否则直接使用get, post, postJson等函数会更加方便.</p>
|
<p>该函数是get, post, postJson等函数的基础函数. 因此除非是PUT, DELETE等请求, 或者需要更高定制的HTTP请求, 否则直接使用get, post, postJson等函数会更加方便.</p>
|
||||||
<h2>[m] buildRequest<span><a class="mark" href="#http_m_buildrequest" id="http_m_buildrequest">#</a></span></h2>
|
<h2>[m] buildRequest<span><a class="mark" href="#http_m_buildrequest" id="http_m_buildrequest">#</a></span></h2>
|
||||||
<h3>buildRequest(url, options)<span><a class="mark" href="#http_buildrequest_url_options" id="http_buildrequest_url_options">#</a></span></h3>
|
<h3>buildRequest(url, options)<span><a class="mark" href="#http_buildrequest_url_options" id="http_buildrequest_url_options">#</a></span></h3>
|
||||||
<p>... ...</p>
|
<p>... ...</p>
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ ocr.recognizeText(img, [ 0, 0, 100, 150 ]).filter(text => text.includes('
|
|||||||
<pre><code class="lang-js">ocr.recognizeText('./picture.jpg'); /* 获取本地图像文件中的所有文本. */
|
<pre><code class="lang-js">ocr.recognizeText('./picture.jpg'); /* 获取本地图像文件中的所有文本. */
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3>recognizeText(imgPath, region)<span><a class="mark" href="#ocr_recognizetext_imgpath_region" id="ocr_recognizetext_imgpath_region">#</a></span></h3>
|
<h3>recognizeText(imgPath, region)<span><a class="mark" href="#ocr_recognizetext_imgpath_region" id="ocr_recognizetext_imgpath_region">#</a></span></h3>
|
||||||
<p><strong><code>6.3.0</code></strong> <strong><code>Overload [4-5]/6</code></strong></p>
|
<p><strong><code>6.3.0</code></strong> <strong><code>Overload 6/6</code></strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>imgPath</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> } - 图像路径</li>
|
<li><strong>imgPath</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> } - 图像路径</li>
|
||||||
<li><strong>region</strong> { <span class="type"><a href="omniTypes.html#omnitypes_omniregion">OmniRegion</a></span> } - OCR 识别区域</li>
|
<li><strong>region</strong> { <span class="type"><a href="omniTypes.html#omnitypes_omniregion">OmniRegion</a></span> } - OCR 识别区域</li>
|
||||||
|
|||||||
@@ -240,6 +240,35 @@ console.show(); /* 显示控制台悬浮窗. */
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<p><code>OmniColor</code> 不仅可用于参数传入方法中, 还可以作为 XML 元素的属性值:</p>
|
||||||
|
<pre><code class="lang-js">'ui';
|
||||||
|
|
||||||
|
ui.layout(<vertical>
|
||||||
|
<button text="click to start" color="#006400"/>
|
||||||
|
</vertical>);
|
||||||
|
</code></pre>
|
||||||
|
<p>上述示例设置按钮布局的文字颜色为深绿色, 使用了 <a href="dataTypes.html#datatypes_colorhex">ColorHex</a> 作为颜色值.</p>
|
||||||
|
<p>使用 <a href="dataTypes.html#datatypes_colorname">ColorName</a> 作为颜色值也可达到相同的效果:</p>
|
||||||
|
<pre><code class="lang-js">'ui';
|
||||||
|
|
||||||
|
ui.layout(<vertical>
|
||||||
|
<button text="click to start" color="dark-green"/>
|
||||||
|
</vertical>);
|
||||||
|
</code></pre>
|
||||||
|
<p>使用 <a href="dataTypes.html#datatypes_colorint">ColorInt</a> 作为颜色值同样可以达到相同的效果:</p>
|
||||||
|
<pre><code class="lang-js">'ui';
|
||||||
|
|
||||||
|
ui.layout(<vertical>
|
||||||
|
<button text="click to start" color="-16751616"/>
|
||||||
|
</vertical>);
|
||||||
|
</code></pre>
|
||||||
|
<p>如需使用主题色作为颜色值, 需要使用一对花括号以及绑定全局作用域的表达式:</p>
|
||||||
|
<pre><code class="lang-js">'ui';
|
||||||
|
|
||||||
|
ui.layout(<vertical>
|
||||||
|
<button text="click to start" color="{{autojs.themeColor}}"/>
|
||||||
|
</vertical>);
|
||||||
|
</code></pre>
|
||||||
<h2>OmniIntent<span><a class="mark" href="#omnitypes_omniintent" id="omnitypes_omniintent">#</a></span></h2>
|
<h2>OmniIntent<span><a class="mark" href="#omnitypes_omniintent" id="omnitypes_omniintent">#</a></span></h2>
|
||||||
<p>Intent 聚合类型.</p>
|
<p>Intent 聚合类型.</p>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -275,7 +275,7 @@
|
|||||||
<h3>OCR 特性<span><a class="mark" href="#qa_ocr" id="qa_ocr">#</a></span></h3>
|
<h3>OCR 特性<span><a class="mark" href="#qa_ocr" id="qa_ocr">#</a></span></h3>
|
||||||
<p>AutoJs6 的 OCR 特性是基于 <a href="https://developers.google.com/ml-kit?hl=zh-cn">Google ML Kit</a> 的 <a href="https://developers.google.com/ml-kit/vision/text-recognition/android?hl=zh-cn">文字识别 API</a> 实现的.</p>
|
<p>AutoJs6 的 OCR 特性是基于 <a href="https://developers.google.com/ml-kit?hl=zh-cn">Google ML Kit</a> 的 <a href="https://developers.google.com/ml-kit/vision/text-recognition/android?hl=zh-cn">文字识别 API</a> 实现的.</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>注: AutoJs6 的 <a href="http://project.autojs6.com/blob/master/app/src/main/java/org/autojs/autojs/runtime/api/MlKitOCR.kt">OCR 实现源码</a> 参考自 <a href="https://github.com/TonyJiangWJ">TonyJiangWJ</a> 的开源项目.</p>
|
<p>注: AutoJs6 的 <a href="http://project.autojs6.com/blob/master/app/src/main/java/org/autojs/autojs/runtime/api/MlKitOCR.kt">OCR 实现源码</a> 参考自 <a href="https://github.com/TonyJiangWJ">TonyJiangWJ</a> 的 <a href="https://github.com/TonyJiangWJ/Auto.js">开源项目</a>.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>参阅: <a href="ocr.html">光学字符识别 (OCR)</a> 模块</p>
|
<p>参阅: <a href="ocr.html">光学字符识别 (OCR)</a> 模块</p>
|
||||||
|
|||||||
@@ -175,6 +175,10 @@
|
|||||||
<li><span class="stability_undefined"><a href="#web_newinjectablewebclient">newInjectableWebClient()</a></span></li>
|
<li><span class="stability_undefined"><a href="#web_newinjectablewebclient">newInjectableWebClient()</a></span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li><span class="stability_undefined"><a href="#web_m_newwebsocket">[m] newWebSocket</a></span><ul>
|
||||||
|
<li><span class="stability_undefined"><a href="#web_newwebsocket_url">newWebSocket(url)</a></span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -287,6 +291,73 @@ settings.setDisplayZoomControls(false);
|
|||||||
<p>新建并返回一个 <a href="injectableWebClientType.html">InjectableWebClient</a> (可 <a href="glossaries.html#glossaries_注入">注入</a> 的 <a href="https://developer.android.com/reference/android/webkit/WebViewClient">WebViewClient</a>) 实例.</p>
|
<p>新建并返回一个 <a href="injectableWebClientType.html">InjectableWebClient</a> (可 <a href="glossaries.html#glossaries_注入">注入</a> 的 <a href="https://developer.android.com/reference/android/webkit/WebViewClient">WebViewClient</a>) 实例.</p>
|
||||||
<pre><code class="lang-js">/* 为 webView 对象重新设置一个新的客户端. */
|
<pre><code class="lang-js">/* 为 webView 对象重新设置一个新的客户端. */
|
||||||
webView.setWebViewClient(newInjectableWebClient());
|
webView.setWebViewClient(newInjectableWebClient());
|
||||||
|
</code></pre>
|
||||||
|
<h2>[m] newWebSocket<span><a class="mark" href="#web_m_newwebsocket" id="web_m_newwebsocket">#</a></span></h2>
|
||||||
|
<h3>newWebSocket(url)<span><a class="mark" href="#web_newwebsocket_url" id="web_newwebsocket_url">#</a></span></h3>
|
||||||
|
<p><strong><code>6.3.1</code></strong> <strong><code>Global</code></strong></p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>url</strong> { <span class="type"><a href="dataTypes.html#datatypes_string">string</a></span> }</li>
|
||||||
|
<li><ins><strong>returns</strong></ins> { <span class="type"><a href="webSocketType.html">WebSocket</a></span> }</li>
|
||||||
|
</ul>
|
||||||
|
<p>新建并返回一个 <a href="webSocketType.html">WebSocket</a> 实例.</p>
|
||||||
|
<pre><code class="lang-js">console.setExitOnClose(7e3).show();
|
||||||
|
|
||||||
|
let ws = web.newWebSocket('wss://echo.websocket.events');
|
||||||
|
|
||||||
|
ws
|
||||||
|
.on('open', (res, ws) => {
|
||||||
|
console.log('WebSocket 已连接');
|
||||||
|
})
|
||||||
|
.on('message', (message, ws) => {
|
||||||
|
console.log('接收到消息');
|
||||||
|
// if (message instanceof okio.ByteString) {
|
||||||
|
// console.log(`消息类型: ByteString`);
|
||||||
|
// } else if (typeof message === 'string') {
|
||||||
|
// console.log(`消息类型: String`);
|
||||||
|
// } else {
|
||||||
|
// throw TypeError('Should never happen');
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
.on('text', (text, ws) => {
|
||||||
|
console.info('接收到文本消息:');
|
||||||
|
console.info(`text: ${text}`);
|
||||||
|
})
|
||||||
|
.on('bytes', (bytes, ws) => {
|
||||||
|
console.info('接收到字节数组消息:');
|
||||||
|
console.info(`utf8: ${bytes.utf8()}`);
|
||||||
|
console.info(`base64: ${bytes.base64()}`);
|
||||||
|
console.info(`md5: ${bytes.md5()}`);
|
||||||
|
console.info(`hex: ${bytes.hex()}`);
|
||||||
|
})
|
||||||
|
.on('closing', (code, reason, ws) => {
|
||||||
|
console.log('WebSocket 关闭中');
|
||||||
|
})
|
||||||
|
.on('closed', (code, reason, ws) => {
|
||||||
|
console.log('WebSocket 已关闭');
|
||||||
|
console.log(`code: ${code}`);
|
||||||
|
if (reason) console.log(`reason: ${reason}`);
|
||||||
|
})
|
||||||
|
.on('failure', (err, res, ws) => {
|
||||||
|
console.error('WebSocket 连接失败');
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 发送文本消息. */
|
||||||
|
ws.send('Hello WebSocket');
|
||||||
|
|
||||||
|
/* 发送字节数组消息. */
|
||||||
|
ws.send(new okio.ByteString(new java.lang.String('Hello WebSocket').getBytes()));
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('断开 WebSocket');
|
||||||
|
|
||||||
|
/* code 支持的范围 [1000,5000). */
|
||||||
|
/* 1000 表示成功操作或常规的 Socket 关闭操作. */
|
||||||
|
/* 参阅 https://github.com/Luka967/websocket-close-codes */
|
||||||
|
ws.close(1000, 'Closed by user');
|
||||||
|
}, 8e3);
|
||||||
|
|
||||||
|
setTimeout(() => console.log('Exit'), 9e3);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// noinspection JSUnusedGlobalSymbols,NpmUsedModulesInstalled,JSUnusedLocalSymbols
|
// noinspection JSUnusedGlobalSymbols,NpmUsedModulesInstalled,JSUnusedLocalSymbols
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// @Caution by SuperMonster003 on Apr 19, 2022.
|
// @Caution by SuperMonster003 on Apr 19, 2022.
|
||||||
// ! Do not declare with const because variable has already
|
// ! Do not declare with const because variable has already
|
||||||
// ! declared globally in RhinoJavaScriptEngine.kt.
|
// ! declared globally in RhinoJavaScriptEngine.kt.
|
||||||
@@ -15,9 +13,11 @@ let RootMode = org.autojs.autojs.util.RootUtils.RootMode;
|
|||||||
let Pref = org.autojs.autojs.pref.Pref;
|
let Pref = org.autojs.autojs.pref.Pref;
|
||||||
let Shell = org.autojs.autojs.runtime.api.Shell;
|
let Shell = org.autojs.autojs.runtime.api.Shell;
|
||||||
let Intent = global.Intent = android.content.Intent;
|
let Intent = global.Intent = android.content.Intent;
|
||||||
|
let Context = global.Context = android.content.Context;
|
||||||
let PendingIntent = android.app.PendingIntent;
|
let PendingIntent = android.app.PendingIntent;
|
||||||
let Toast = android.widget.Toast;
|
let Toast = android.widget.Toast;
|
||||||
let KeyEvent = android.view.KeyEvent;
|
let KeyEvent = android.view.KeyEvent;
|
||||||
|
let MotionEvent = android.view.MotionEvent;
|
||||||
let Version = Packages.io.github.g00fy2.versioncompare.Version;
|
let Version = Packages.io.github.g00fy2.versioncompare.Version;
|
||||||
let Image = org.autojs.autojs.core.image.ImageWrapper;
|
let Image = org.autojs.autojs.core.image.ImageWrapper;
|
||||||
let ColorTable = org.autojs.autojs.core.image.ColorTable;
|
let ColorTable = org.autojs.autojs.core.image.ColorTable;
|
||||||
@@ -40,17 +40,59 @@ let GlobalAppContext = org.autojs.autojs.app.GlobalAppContext;
|
|||||||
let DisplayUtils = org.autojs.autojs.util.DisplayUtils;
|
let DisplayUtils = org.autojs.autojs.util.DisplayUtils;
|
||||||
let StringUtils = org.autojs.autojs.util.StringUtils;
|
let StringUtils = org.autojs.autojs.util.StringUtils;
|
||||||
let ColorUtils = org.autojs.autojs.util.ColorUtils;
|
let ColorUtils = org.autojs.autojs.util.ColorUtils;
|
||||||
|
let TextUtils = org.autojs.autojs.util.TextUtils;
|
||||||
let ProxyObject = org.autojs.autojs.rhino.ProxyObject;
|
let ProxyObject = org.autojs.autojs.rhino.ProxyObject;
|
||||||
let ProxyJavaObject = org.autojs.autojs.rhino.ProxyJavaObject;
|
let ProxyJavaObject = org.autojs.autojs.rhino.ProxyJavaObject;
|
||||||
let NotificationManager = android.app.NotificationManager;
|
let NotificationManager = android.app.NotificationManager;
|
||||||
let NotificationCompat = Packages.androidx.core.app.NotificationCompat;
|
let NotificationCompat = Packages.androidx.core.app.NotificationCompat;
|
||||||
|
let SecurityException = java.lang.SecurityException;
|
||||||
|
let Locale = java.util.Locale;
|
||||||
let URI = java.net.URI;
|
let URI = java.net.URI;
|
||||||
let File = java.io.File;
|
let File = java.io.File;
|
||||||
|
|
||||||
|
/* Global View classes. */
|
||||||
|
|
||||||
|
let JsAppBarLayout = org.autojs.autojs.core.ui.widget.JsAppBarLayout;
|
||||||
|
let JsButton = org.autojs.autojs.core.ui.widget.JsButton;
|
||||||
|
let JsCanvasView = org.autojs.autojs.core.ui.widget.JsCanvasView;
|
||||||
|
let JsCardView = org.autojs.autojs.core.ui.widget.JsCardView;
|
||||||
|
let JsCheckBox = org.autojs.autojs.core.ui.widget.JsCheckBox;
|
||||||
|
let JsConsoleView = org.autojs.autojs.core.ui.widget.JsConsoleView;
|
||||||
|
let JsDatePicker = org.autojs.autojs.core.ui.widget.JsDatePicker;
|
||||||
|
let JsDrawerLayout = org.autojs.autojs.core.ui.widget.JsDrawerLayout;
|
||||||
|
let JsEditText = org.autojs.autojs.core.ui.widget.JsEditText;
|
||||||
|
let JsFloatingActionButton = org.autojs.autojs.core.ui.widget.JsFloatingActionButton;
|
||||||
|
let JsFrameLayout = org.autojs.autojs.core.ui.widget.JsFrameLayout;
|
||||||
|
let JsGridView = org.autojs.autojs.core.ui.widget.JsGridView;
|
||||||
|
let JsImageButton = org.autojs.autojs.core.ui.widget.JsImageButton;
|
||||||
|
let JsImageView = org.autojs.autojs.core.ui.widget.JsImageView;
|
||||||
|
let JsLinearLayout = org.autojs.autojs.core.ui.widget.JsLinearLayout;
|
||||||
|
let JsListView = org.autojs.autojs.core.ui.widget.JsListView;
|
||||||
|
let JsProgressBar = org.autojs.autojs.core.ui.widget.JsProgressBar;
|
||||||
|
let JsRadioButton = org.autojs.autojs.core.ui.widget.JsRadioButton;
|
||||||
|
let JsRadioGroup = org.autojs.autojs.core.ui.widget.JsRadioGroup;
|
||||||
|
let JsRatingBar = org.autojs.autojs.core.ui.widget.JsRatingBar;
|
||||||
|
let JsRelativeLayout = org.autojs.autojs.core.ui.widget.JsRelativeLayout;
|
||||||
|
let JsScrollView = org.autojs.autojs.core.ui.widget.JsScrollView;
|
||||||
|
let JsSeekBar = org.autojs.autojs.core.ui.widget.JsSeekBar;
|
||||||
|
let JsSpinner = org.autojs.autojs.core.ui.widget.JsSpinner;
|
||||||
|
let JsSwitch = org.autojs.autojs.core.ui.widget.JsSwitch;
|
||||||
|
let JsTabLayout = org.autojs.autojs.core.ui.widget.JsTabLayout;
|
||||||
|
let JsTextClock = org.autojs.autojs.core.ui.widget.JsTextClock;
|
||||||
|
let JsTextView = android.os.Build.VERSION.SDK_INT < 26 /* Android API 26 (8.0) [O] */
|
||||||
|
? org.autojs.autojs.core.ui.widget.JsTextViewLegacy
|
||||||
|
: org.autojs.autojs.core.ui.widget.JsTextView;
|
||||||
|
let JsTimePicker = org.autojs.autojs.core.ui.widget.JsTimePicker;
|
||||||
|
let JsToggleButton = org.autojs.autojs.core.ui.widget.JsToggleButton;
|
||||||
|
let JsToolbar = org.autojs.autojs.core.ui.widget.JsToolbar;
|
||||||
|
let JsViewPager = org.autojs.autojs.core.ui.widget.JsViewPager;
|
||||||
|
let JsWebView = org.autojs.autojs.core.ui.widget.JsWebView;
|
||||||
|
|
||||||
/* Global assignment. */
|
/* Global assignment. */
|
||||||
|
|
||||||
Object.assign(this, {
|
Object.assign(this, {
|
||||||
io: Packages.io,
|
io: Packages.io,
|
||||||
|
okio: Packages.okio,
|
||||||
de: Packages.de,
|
de: Packages.de,
|
||||||
ezy: Packages.ezy,
|
ezy: Packages.ezy,
|
||||||
kotlin: Packages.kotlin,
|
kotlin: Packages.kotlin,
|
||||||
@@ -264,8 +306,11 @@ Object.assign(this, {
|
|||||||
if (typeof global[module] === 'object') {
|
if (typeof global[module] === 'object') {
|
||||||
if (!(Object.hasOwn(global[module], 'toString'))) {
|
if (!(Object.hasOwn(global[module], 'toString'))) {
|
||||||
// noinspection JSPotentiallyInvalidConstructorUsage
|
// noinspection JSPotentiallyInvalidConstructorUsage
|
||||||
if (typeof global[module].constructor.prototype.toString !== 'function') {
|
let prototype = global[module].constructor.prototype;
|
||||||
global[module].toString = () => module;
|
if (prototype !== undefined) /* For AutoJs6 debugger. */ {
|
||||||
|
if (typeof prototype.toString !== 'function') {
|
||||||
|
global[module].toString = () => module;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,6 +460,9 @@ Object.assign(this, {
|
|||||||
[ 'engines', 'continuation', 'http' ],
|
[ 'engines', 'continuation', 'http' ],
|
||||||
[ 'images', 'colors', 'dialogs' ],
|
[ 'images', 'colors', 'dialogs' ],
|
||||||
|
|
||||||
|
/* ! http < web */
|
||||||
|
[ 'web' ],
|
||||||
|
|
||||||
/* ! files < i18n */
|
/* ! files < i18n */
|
||||||
/* ! i18n < selector */
|
/* ! i18n < selector */
|
||||||
[ 'i18n', 'selector' ],
|
[ 'i18n', 'selector' ],
|
||||||
@@ -438,7 +486,7 @@ Object.assign(this, {
|
|||||||
|
|
||||||
/* Safe to put last regardless of the order, no guarantee ;). */
|
/* Safe to put last regardless of the order, no guarantee ;). */
|
||||||
[ 'floaty', 'storages', 'device', 'recorder', 'toast' ],
|
[ 'floaty', 'storages', 'device', 'recorder', 'toast' ],
|
||||||
[ 'media', 'sensors', 'web', 'events', 'base64', 'notice' ],
|
[ 'media', 'sensors', 'events', 'base64', 'notice' ],
|
||||||
|
|
||||||
/* Last but not the least */
|
/* Last but not the least */
|
||||||
[ 'globals' ],
|
[ 'globals' ],
|
||||||
|
|||||||
@@ -350,7 +350,6 @@ var MODE = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function Beautifier(js_source_text, options) {
|
function Beautifier(js_source_text, options) {
|
||||||
"use strict";
|
|
||||||
var output;
|
var output;
|
||||||
var tokens = [],
|
var tokens = [],
|
||||||
token_pos;
|
token_pos;
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
|
|
||||||
Color.prototype = {
|
Color.prototype = {
|
||||||
constructor: Color,
|
constructor: Color,
|
||||||
|
toString() {
|
||||||
|
return this.digest();
|
||||||
|
},
|
||||||
digest() {
|
digest() {
|
||||||
return colors.digest.apply(colors, [ this.color ].concat(Array.from(arguments)));
|
return colors.digest.apply(colors, [ this.color ].concat(Array.from(arguments)));
|
||||||
},
|
},
|
||||||
@@ -78,6 +81,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
this.color = colors.setAlpha(this.color, alpha);
|
this.color = colors.setAlpha(this.color, alpha);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
setAlphaRelative(percentage) {
|
||||||
|
return this.setAlpha(this.getAlpha() * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
getAlpha() {
|
getAlpha() {
|
||||||
return colors.alpha(this.color);
|
return colors.alpha(this.color);
|
||||||
},
|
},
|
||||||
@@ -98,6 +104,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
this.color = colors.setRed(this.color, red);
|
this.color = colors.setRed(this.color, red);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
setRedRelative(percentage) {
|
||||||
|
return this.setRed(this.getRed() * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
getRed() {
|
getRed() {
|
||||||
return colors.red(this.color);
|
return colors.red(this.color);
|
||||||
},
|
},
|
||||||
@@ -118,6 +127,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
this.color = colors.setGreen(this.color, green);
|
this.color = colors.setGreen(this.color, green);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
setGreenRelative(percentage) {
|
||||||
|
return this.setGreen(this.getGreen() * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
getGreen() {
|
getGreen() {
|
||||||
return colors.green(this.color);
|
return colors.green(this.color);
|
||||||
},
|
},
|
||||||
@@ -138,6 +150,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
this.color = colors.setBlue(this.color, blue);
|
this.color = colors.setBlue(this.color, blue);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
setBlueRelative(percentage) {
|
||||||
|
return this.setBlue(this.getBlue() * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
getBlue() {
|
getBlue() {
|
||||||
return colors.blue(this.color);
|
return colors.blue(this.color);
|
||||||
},
|
},
|
||||||
@@ -267,6 +282,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
let [ r, g, b ] = this.toRgb(color);
|
let [ r, g, b ] = this.toRgb(color);
|
||||||
return this.toInt(this.argb(alpha, r, g, b));
|
return this.toInt(this.argb(alpha, r, g, b));
|
||||||
},
|
},
|
||||||
|
setAlphaRelative(color, percentage) {
|
||||||
|
return this.setAlpha(color, this.getAlpha(color) * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
removeAlpha(color) {
|
removeAlpha(color) {
|
||||||
return this.setAlpha(color, 0);
|
return this.setAlpha(color, 0);
|
||||||
},
|
},
|
||||||
@@ -293,6 +311,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
let [ a, , g, b ] = this.toArgb(color);
|
let [ a, , g, b ] = this.toArgb(color);
|
||||||
return this.toInt(this.argb(a, red, g, b));
|
return this.toInt(this.argb(a, red, g, b));
|
||||||
},
|
},
|
||||||
|
setRedRelative(color, percentage) {
|
||||||
|
return this.setRed(color, this.getRed(color) * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
removeRed(color) {
|
removeRed(color) {
|
||||||
return this.setRed(color, 0);
|
return this.setRed(color, 0);
|
||||||
},
|
},
|
||||||
@@ -319,6 +340,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
let [ a, r, , b ] = this.toArgb(color);
|
let [ a, r, , b ] = this.toArgb(color);
|
||||||
return this.toInt(this.argb(a, r, green, b));
|
return this.toInt(this.argb(a, r, green, b));
|
||||||
},
|
},
|
||||||
|
setGreenRelative(color, percentage) {
|
||||||
|
return this.getGreen(color, this.getGreen(color) * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
removeGreen(color) {
|
removeGreen(color) {
|
||||||
return this.setGreen(color, 0);
|
return this.setGreen(color, 0);
|
||||||
},
|
},
|
||||||
@@ -345,75 +369,27 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
let [ a, r, g ] = this.toArgb(color);
|
let [ a, r, g ] = this.toArgb(color);
|
||||||
return this.toInt(this.argb(a, r, g, blue));
|
return this.toInt(this.argb(a, r, g, blue));
|
||||||
},
|
},
|
||||||
|
setBlueRelative(color, percentage) {
|
||||||
|
return this.setBlue(color, this.getBlue(color) * _.parseRelativePercentage(percentage));
|
||||||
|
},
|
||||||
removeBlue(color) {
|
removeBlue(color) {
|
||||||
return this.setBlue(color, 0);
|
return this.setBlue(color, 0);
|
||||||
},
|
},
|
||||||
toInt(color) {
|
toInt(color) {
|
||||||
try {
|
if (color instanceof _.Color) {
|
||||||
return _.parseColor(typeof color === 'number' ? _.toJavaIntegerRange(color) : this.toFullHex(color));
|
color = color.color;
|
||||||
} catch (e) {
|
|
||||||
scriptRuntime.console.error(`Passed color: ${color}`);
|
|
||||||
throw Error(e + '\n' + e.stack);
|
|
||||||
}
|
}
|
||||||
|
return ColorUtils.toInt.apply(ColorUtils, [ color ]);
|
||||||
},
|
},
|
||||||
toHex(color, alphaOrLength) {
|
toHex(color, alphaOrLength) {
|
||||||
let [ _ignoredArg0, arg1 /* alpha | length */ ] = arguments;
|
if (isNullish(alphaOrLength)) {
|
||||||
|
return ColorUtils.toHex.apply(ColorUtils, [ color ]);
|
||||||
if (color instanceof _.Color) {
|
|
||||||
return this.toHex.apply(this, [ color.color ].concat(Array.from(arguments).slice(1)));
|
|
||||||
}
|
|
||||||
if (color instanceof ThemeColor) {
|
|
||||||
return this.toHex.apply(this, [ color.getColorPrimary() ].concat(Array.from(arguments).slice(1)));
|
|
||||||
}
|
|
||||||
if (typeof color === 'number') {
|
|
||||||
color = rtColors.toString(_.toJavaIntegerRange(color));
|
|
||||||
} else {
|
} else {
|
||||||
color = String(color);
|
return ColorUtils.toHex.apply(ColorUtils, [ color, alphaOrLength ]);
|
||||||
}
|
}
|
||||||
if (color.startsWith('#')) {
|
|
||||||
if (color.length === 4) {
|
|
||||||
color = color.replace(/(#)(\w)(\w)(\w)/, '$1$2$2$3$3$4$4');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (color === parseInt(color).toString()) {
|
|
||||||
return this.toHex.apply(this, [ parseInt(color) ].concat(Array.from(arguments).slice(1)));
|
|
||||||
}
|
|
||||||
let colorByName = ColorTable.getColorByName(color, true);
|
|
||||||
if (colorByName !== null) {
|
|
||||||
return this.toHex.apply(this, [ colorByName.intValue() ].concat(Array.from(arguments).slice(1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!/^#[A-F\d]{3}([A-F\d]{3}([A-F\d]{2})?)?$/i.test(color)) {
|
|
||||||
throw TypeError(`Invalid color string format: ${color}`);
|
|
||||||
}
|
|
||||||
return ( /* @IIFE(toColorHex) */ () => {
|
|
||||||
if (arg1 /* alpha */ === true || arg1 /* alpha */ === 'keep' || arg1 /* length */ === 8) {
|
|
||||||
if (color.length === 7) {
|
|
||||||
color = `#FF${color.slice(1)}`;
|
|
||||||
}
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
if (arg1 /* alpha */ === false || arg1 /* alpha */ === 'none' || arg1 /* length */ === 6) {
|
|
||||||
return `#${color.slice(-6)}`;
|
|
||||||
}
|
|
||||||
if (arg1 /* length */ === 3) {
|
|
||||||
if (!/^#(?:([A-F\d]){2})?([A-F\d])\2([A-F\d])\3([A-F\d])\4$/i.test(color)) {
|
|
||||||
throw TypeError(`Can't convert color ${color} to #RGB with unexpected color format.`);
|
|
||||||
}
|
|
||||||
let [ r, g, b ] = [ color.slice(-6, -5), color.slice(-4, -3), color.slice(-2, -1) ];
|
|
||||||
return `#${r}${g}${b}`;
|
|
||||||
}
|
|
||||||
if (arg1 /* alpha */ === undefined || arg1 /* alpha */ === 'auto') {
|
|
||||||
return /^#FF([A-F\d]){6}$/i.test(color) ? `#${color.slice(3)}` : color;
|
|
||||||
}
|
|
||||||
throw TypeError('Unknown type of alpha for colors.toString()');
|
|
||||||
})().toUpperCase();
|
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* Color to full hex like '#BF110523'.
|
|
||||||
*/
|
|
||||||
toFullHex(color) {
|
toFullHex(color) {
|
||||||
return this.toHex(color, 8);
|
return ColorUtils.toFullHex.apply(ColorUtils, [ color ]);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Get hex code string of a color.
|
* Get hex code string of a color.
|
||||||
@@ -870,15 +846,12 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
parseNumber(num, def) {
|
parseNumber(num, def) {
|
||||||
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
|
return typeof num === 'number' ? num : typeof def === 'function' ? def() : def || 0;
|
||||||
},
|
},
|
||||||
/**
|
parseRelativePercentage(percentage) {
|
||||||
* @param {number|string} color
|
let p = Numberx.parseAny(percentage);
|
||||||
* @returns {number}
|
if (isNaN(p) || p < 0) {
|
||||||
*/
|
throw TypeError(`Relative percentage must be in range 0..255, instead of ${percentage}`)
|
||||||
parseColor(color) {
|
|
||||||
if (typeof color === 'string') {
|
|
||||||
return rtColors.parseColor(color);
|
|
||||||
}
|
}
|
||||||
return color;
|
return p;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ let { files, util, s13n } = global;
|
|||||||
module.exports = function (scriptRuntime, scope) {
|
module.exports = function (scriptRuntime, scope) {
|
||||||
const Log = android.util.Log;
|
const Log = android.util.Log;
|
||||||
const Level = org.apache.log4j.Level;
|
const Level = org.apache.log4j.Level;
|
||||||
const ConsoleUtils = org.autojs.autojs.util.ConsoleUtils;
|
const LogManager = org.apache.log4j.LogManager;
|
||||||
const LogConfigurator = de.mindpipe.android.logging.log4j.LogConfigurator;
|
const LogConfigurator = de.mindpipe.android.logging.log4j.LogConfigurator;
|
||||||
|
const ConsoleUtils = org.autojs.autojs.util.ConsoleUtils;
|
||||||
|
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
/** @type {org.autojs.autojs.core.console.GlobalConsole} */
|
/** @type {org.autojs.autojs.core.console.GlobalConsole} */
|
||||||
@@ -92,8 +93,14 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
Boolean(typeof value === 'function' ? value() : value),
|
Boolean(typeof value === 'function' ? value() : value),
|
||||||
message || util.getClassName(java.lang.AssertionError));
|
message || util.getClassName(java.lang.AssertionError));
|
||||||
},
|
},
|
||||||
input(data, param) {
|
input() {
|
||||||
return eval(String(this.rawInput(data, param)));
|
// @Abandoned by SuperMonster003 as of May 3, 2023.
|
||||||
|
// return eval(String(this.rawInput(data, param)));
|
||||||
|
throw Error(context.getString(R.strings.error_abandoned_method, 'console.input'));
|
||||||
|
},
|
||||||
|
rawInput() {
|
||||||
|
// @Abandoned by SuperMonster003 as of May 3, 2023.
|
||||||
|
throw Error(context.getString(R.strings.error_abandoned_method, 'console.rawInput'));
|
||||||
},
|
},
|
||||||
log() {
|
log() {
|
||||||
rtConsole.log(util.format.apply(util, arguments));
|
rtConsole.log(util.format.apply(util, arguments));
|
||||||
@@ -247,6 +254,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
configurator.setResetConfiguration(_.parseOption(config.resetConfiguration, true));
|
configurator.setResetConfiguration(_.parseOption(config.resetConfiguration, true));
|
||||||
configurator.configure();
|
configurator.configure();
|
||||||
},
|
},
|
||||||
|
resetGlobalLogConfig() {
|
||||||
|
LogManager.getLoggerRepository().resetConfiguration();
|
||||||
|
},
|
||||||
launch() {
|
launch() {
|
||||||
ConsoleUtils.launch();
|
ConsoleUtils.launch();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -484,6 +484,11 @@ module.exports = function (runtime, scope) {
|
|||||||
delete this.$appropriateProtect;
|
delete this.$appropriateProtect;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
legacies: {
|
||||||
|
isObjectSpecies(o) {
|
||||||
|
return species.isObject(o);
|
||||||
|
},
|
||||||
|
},
|
||||||
ensureNonUiThread() {
|
ensureNonUiThread() {
|
||||||
if (ui.isUiThread()) {
|
if (ui.isUiThread()) {
|
||||||
throw Error('不能在ui线程执行阻塞操作,请在子线程或子脚本执行,或者使用setInterval循环检测当前activity和package.');
|
throw Error('不能在ui线程执行阻塞操作,请在子线程或子脚本执行,或者使用setInterval循环检测当前activity和package.');
|
||||||
@@ -533,7 +538,7 @@ module.exports = function (runtime, scope) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.assign(scope, _.extensions);
|
Object.assign(scope, _.extensions, _.legacies);
|
||||||
|
|
||||||
// Object.keys(_.extensions)
|
// Object.keys(_.extensions)
|
||||||
// .filter(key => !key.startsWith('$'))
|
// .filter(key => !key.startsWith('$'))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols,UnnecessaryLocalVariableJS
|
||||||
|
|
||||||
/* Overwritten protection. */
|
/* Overwritten protection. */
|
||||||
|
|
||||||
@@ -10,7 +10,8 @@ let { ui } = global;
|
|||||||
* @return {Internal.Http}
|
* @return {Internal.Http}
|
||||||
*/
|
*/
|
||||||
module.exports = function (scriptRuntime, scope) {
|
module.exports = function (scriptRuntime, scope) {
|
||||||
const PFile = org.autojs.pio.PFile;
|
|
||||||
|
const PFile = org.autojs.autojs.pio.PFile;
|
||||||
const Request = okhttp3.Request;
|
const Request = okhttp3.Request;
|
||||||
const RequestBody = okhttp3.RequestBody;
|
const RequestBody = okhttp3.RequestBody;
|
||||||
const MultipartBody = okhttp3.MultipartBody;
|
const MultipartBody = okhttp3.MultipartBody;
|
||||||
@@ -31,6 +32,13 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
Http.prototype = {
|
Http.prototype = {
|
||||||
constructor: Http,
|
constructor: Http,
|
||||||
__okhttp__: new MutableOkHttp(),
|
__okhttp__: new MutableOkHttp(),
|
||||||
|
/**
|
||||||
|
* @example
|
||||||
|
* http.client() === http.client(); // true
|
||||||
|
*/
|
||||||
|
client() {
|
||||||
|
return this.__okhttp__.client();
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
* @param {Http.RequestBuilderOptions} [options]
|
* @param {Http.RequestBuilderOptions} [options]
|
||||||
@@ -83,6 +91,7 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
if (typeof body === 'string') {
|
if (typeof body === 'string') {
|
||||||
|
// noinspection JSDeprecatedSymbols
|
||||||
return RequestBody.create(MediaType.parse(this.options.contentType), body);
|
return RequestBody.create(MediaType.parse(this.options.contentType), body);
|
||||||
}
|
}
|
||||||
if (typeof body === 'function') {
|
if (typeof body === 'function') {
|
||||||
@@ -119,6 +128,7 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
let file = new PFile(path);
|
let file = new PFile(path);
|
||||||
fileName = fileName || file.getName();
|
fileName = fileName || file.getName();
|
||||||
mimeType = mimeType || this.parseMimeType(file.getExtension());
|
mimeType = mimeType || this.parseMimeType(file.getExtension());
|
||||||
|
// noinspection JSDeprecatedSymbols
|
||||||
let requestBody = RequestBody.create(MediaType.parse(mimeType), file);
|
let requestBody = RequestBody.create(MediaType.parse(mimeType), file);
|
||||||
builder.addFormDataPart(key, fileName, requestBody);
|
builder.addFormDataPart(key, fileName, requestBody);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,13 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
const BigTextStyle = androidx.core.app.NotificationCompat.BigTextStyle;
|
const BigTextStyle = androidx.core.app.NotificationCompat.BigTextStyle;
|
||||||
const Notification = android.app.Notification;
|
const Notification = android.app.Notification;
|
||||||
const NotificationManager = android.app.NotificationManager;
|
const NotificationManager = android.app.NotificationManager;
|
||||||
const NotificationManagerCompat = androidx.core.app.NotificationManagerCompat;
|
|
||||||
|
// @Caution by SuperMonster003 on May 6, 2023.
|
||||||
|
// ! On device running with Android 7.x,
|
||||||
|
// ! importing NotificationManagerCompat will cause java.lang.ClassNotFoundException:
|
||||||
|
// ! Didn't find class "android.app.NotificationChannel" on path: DexPathList ...
|
||||||
|
|
||||||
|
// const NotificationManagerCompat = androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
const configDefaults = {
|
const configDefaults = {
|
||||||
/**
|
/**
|
||||||
@@ -511,7 +517,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
if (!isNullish(id)) {
|
if (!isNullish(id)) {
|
||||||
let niceId = Number(id);
|
let niceId = Number(id);
|
||||||
if (!isNaN(niceId)) {
|
if (!isNaN(niceId)) {
|
||||||
NotificationManagerCompat.from(context).cancel(niceId);
|
if (util.version.sdkInt >= util.versionCodes.O) {
|
||||||
|
androidx.core.app.NotificationManagerCompat.from(context).cancel(niceId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
__asGlobal__(scriptRuntime.timers, methods, scope);
|
__asGlobal__(scriptRuntime.timers, methods, scope);
|
||||||
|
|
||||||
Object.assign(scope, {
|
Object.assign(scope, {
|
||||||
/**
|
/** @global */
|
||||||
* @global
|
|
||||||
*/
|
|
||||||
loop() {
|
loop() {
|
||||||
return scriptRuntime.console.warn('Method loop() is deprecated and has no effect.');
|
// @Abandoned by SuperMonster003 as of May 3, 2023.
|
||||||
|
// scriptRuntime.console.warn('Method loop() is deprecated and has no effect.');
|
||||||
|
throw Error(context.getString(R.strings.error_abandoned_method, 'global.loop'));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,17 +12,20 @@ let { files } = global;
|
|||||||
module.exports = function (scriptRuntime, scope) {
|
module.exports = function (scriptRuntime, scope) {
|
||||||
const Looper = android.os.Looper;
|
const Looper = android.os.Looper;
|
||||||
const Runnable = java.lang.Runnable;
|
const Runnable = java.lang.Runnable;
|
||||||
const Color = android.graphics.Color;
|
|
||||||
const ContextThemeWrapper = android.view.ContextThemeWrapper;
|
const ContextThemeWrapper = android.view.ContextThemeWrapper;
|
||||||
const ViewExtras = org.autojs.autojs.core.ui.ViewExtras;
|
const ViewExtras = org.autojs.autojs.core.ui.ViewExtras;
|
||||||
const JsListView = org.autojs.autojs.core.ui.widget.JsListView;
|
const JsListView = org.autojs.autojs.core.ui.widget.JsListView;
|
||||||
const JsGridView = org.autojs.autojs.core.ui.widget.JsGridView;
|
const JsGridView = org.autojs.autojs.core.ui.widget.JsGridView;
|
||||||
const JsViewHelper = org.autojs.autojs.core.ui.JsViewHelper;
|
const JsViewHelper = org.autojs.autojs.core.ui.JsViewHelper;
|
||||||
|
const ThemeColor = org.autojs.autojs.theme.ThemeColor;
|
||||||
const DynamicLayoutInflater = org.autojs.autojs.core.ui.inflater.DynamicLayoutInflater;
|
const DynamicLayoutInflater = org.autojs.autojs.core.ui.inflater.DynamicLayoutInflater;
|
||||||
|
const ColorDrawable = android.graphics.drawable.ColorDrawable;
|
||||||
|
|
||||||
require('object-observe-lite.min').call(scope);
|
require('object-observe-lite.min').call(scope);
|
||||||
require('array-observe.min').call(scope);
|
require('array-observe.min').call(scope);
|
||||||
|
|
||||||
|
let isAndroidLayout = null;
|
||||||
|
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
let _ = {
|
let _ = {
|
||||||
// @Coerce by SuperMonster003 on Nov 9, 2022.
|
// @Coerce by SuperMonster003 on Nov 9, 2022.
|
||||||
@@ -142,6 +145,15 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
: activity);
|
: activity);
|
||||||
return layoutInflater.inflate(_.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
|
return layoutInflater.inflate(_.toXMLString(xml), parent || null, Boolean(isAttachedToParent));
|
||||||
},
|
},
|
||||||
|
useAndroidLayout(b) {
|
||||||
|
if (typeof b === 'boolean') {
|
||||||
|
isAndroidLayout = b;
|
||||||
|
} else if (b === undefined) {
|
||||||
|
isAndroidLayout = true;
|
||||||
|
} else {
|
||||||
|
isAndroidLayout = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
run(action) {
|
run(action) {
|
||||||
if (this.isUiThread()) {
|
if (this.isUiThread()) {
|
||||||
return action();
|
return action();
|
||||||
@@ -175,11 +187,16 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
scriptRuntime.getUiHandler().postDelayed(_.wrapUiAction(action), delay);
|
scriptRuntime.getUiHandler().postDelayed(_.wrapUiAction(action), delay);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layout(layout) {
|
layout(xml) {
|
||||||
_.ensureActivity();
|
_.ensureActivity();
|
||||||
layoutInflater.setContext(activity);
|
|
||||||
// noinspection JSCheckFunctionSignatures
|
// noinspection JSCheckFunctionSignatures
|
||||||
this.setContentView(layoutInflater.inflate(layout, activity.window.decorView, false));
|
layoutInflater.setContext(activity);
|
||||||
|
// noinspection JSCheckFunctionSignatures,JSTypeOfValues
|
||||||
|
this.setContentView(layoutInflater.inflate(
|
||||||
|
typeof xml === 'xml' ? xml.toXMLString() : String(xml),
|
||||||
|
activity.window.decorView,
|
||||||
|
false,
|
||||||
|
));
|
||||||
},
|
},
|
||||||
layoutFile(path) {
|
layoutFile(path) {
|
||||||
this.layout(files.read(path));
|
this.layout(files.read(path));
|
||||||
@@ -200,18 +217,13 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
},
|
},
|
||||||
statusBarColor(color) {
|
statusBarColor(color) {
|
||||||
_.ensureActivity();
|
_.ensureActivity();
|
||||||
let colorInt = (/* @IIFE */ () => {
|
this.run(() => activity.window.setStatusBarColor(colors.toInt(color)));
|
||||||
if (typeof color === 'string') {
|
},
|
||||||
if (Number(color).toString() === color) {
|
backgroundColor(color) {
|
||||||
color = Number(color);
|
_.ensureActivity();
|
||||||
}
|
this.run(() => activity.window.setBackgroundDrawable(new ColorDrawable(
|
||||||
}
|
Color(color).setAlpha(1.0).toInt(),
|
||||||
if (typeof color === 'number') {
|
)));
|
||||||
return color;
|
|
||||||
}
|
|
||||||
return scriptRuntime.colors.parseColor(String(color));
|
|
||||||
})();
|
|
||||||
this.run(() => activity.window.setStatusBarColor(colorInt));
|
|
||||||
},
|
},
|
||||||
findById(id) {
|
findById(id) {
|
||||||
return this.view ? this.findByStringId(this.view, id) : null;
|
return this.view ? this.findByStringId(this.view, id) : null;
|
||||||
@@ -235,28 +247,19 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
*/
|
*/
|
||||||
layoutInflaterDelegate: {
|
layoutInflaterDelegate: {
|
||||||
beforeConvertXml(context, xml) {
|
beforeConvertXml(context, xml) {
|
||||||
|
if (isAndroidLayout === true || isAndroidLayout === null && /\bxmlns:\w+="\w+:\/\/|\b(android|app):\w+=".+"/.test(xml)) {
|
||||||
|
// noinspection JSTypeOfValues
|
||||||
|
return typeof xml === 'xml' ? xml.toXMLString() : String(xml);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
afterConvertXml(context, xml) {
|
afterConvertXml(context, xml) {
|
||||||
return xml;
|
return xml;
|
||||||
},
|
},
|
||||||
beforeInflation(context, xml, parent) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
afterInflation(context, result, xml, parent) {
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
beforeInflateView(context, node, parent, attachToParent) {
|
beforeInflateView(context, node, parent, attachToParent) {
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
afterInflateView(context, view, node, parent, attachToParent) {
|
beforeCreateView(context, node, viewName, parent) {
|
||||||
let { widget } = view;
|
|
||||||
if (widget && context.get('root') !== widget) {
|
|
||||||
widget.notifyAfterInflation(view);
|
|
||||||
}
|
|
||||||
return view;
|
|
||||||
},
|
|
||||||
beforeCreateView(context, node, viewName, parent, attrs) {
|
|
||||||
if (uiProxy.__widgets__.hasOwnProperty(viewName)) {
|
if (uiProxy.__widgets__.hasOwnProperty(viewName)) {
|
||||||
let Widget = uiProxy.__widgets__[viewName];
|
let Widget = uiProxy.__widgets__[viewName];
|
||||||
let widget = new Widget();
|
let widget = new Widget();
|
||||||
@@ -267,7 +270,13 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
afterCreateView(context, view, node, viewName, parent, attrs) {
|
beforeInflation(context, xml, parent) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
afterInflation(context, result, xml, parent) {
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
afterCreateView(context, view, node, viewName, parent) {
|
||||||
if (view instanceof JsListView || view instanceof JsGridView) {
|
if (view instanceof JsListView || view instanceof JsGridView) {
|
||||||
_.initListView(view);
|
_.initListView(view);
|
||||||
}
|
}
|
||||||
@@ -275,11 +284,13 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
if (widget !== null) {
|
if (widget !== null) {
|
||||||
widget.view = view;
|
widget.view = view;
|
||||||
view.widget = widget;
|
view.widget = widget;
|
||||||
ViewExtras.getViewAttributes(view, layoutInflater.getResourceParser()).setViewAttributeDelegate({
|
ViewExtras
|
||||||
has: name => widget.hasAttr(name),
|
.getViewAttributes(view, layoutInflater.getResourceParser())
|
||||||
get: (view, name, getter) => widget.getAttr(view, name, getter),
|
.setViewAttributeDelegate({
|
||||||
set: (view, name, value, setter) => widget.setAttr(view, name, value, setter),
|
has: name => widget.hasAttr(name),
|
||||||
});
|
get: (view, name, getter) => widget.getAttr(view, name, getter),
|
||||||
|
set: (view, name, value, setter) => widget.setAttr(view, name, value, setter),
|
||||||
|
});
|
||||||
widget.notifyViewCreated(view);
|
widget.notifyViewCreated(view);
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
@@ -287,6 +298,27 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
beforeApplyAttributes(context, view, inflater, attrs, parent) {
|
beforeApplyAttributes(context, view, inflater, attrs, parent) {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
beforeApplyAttribute(context, inflater, view, ns, attrName, value, parent) {
|
||||||
|
let isDynamic = layoutInflater.isDynamicValue(value);
|
||||||
|
return isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS
|
||||||
|
|| !isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_JUST_DYNAMIC_ATTRS
|
||||||
|
|| (/* @IIFE */ () => {
|
||||||
|
value = _.bind(value);
|
||||||
|
let widget = context.get('widget');
|
||||||
|
if (widget !== null && widget.hasAttr(attrName)) {
|
||||||
|
widget.setAttr(view, attrName, value, (view, attrName, value) => {
|
||||||
|
inflater.setAttr(view, ns, attrName, value, parent);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
inflater.setAttr(view, ns, attrName, value, parent);
|
||||||
|
}
|
||||||
|
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent);
|
||||||
|
return true;
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
afterApplyAttribute(context, inflater, view, ns, attrName, value, parent) {
|
||||||
|
// Empty method body
|
||||||
|
},
|
||||||
afterApplyAttributes(context, view, inflater, attrs, parent) {
|
afterApplyAttributes(context, view, inflater, attrs, parent) {
|
||||||
context.remove('widget');
|
context.remove('widget');
|
||||||
},
|
},
|
||||||
@@ -302,26 +334,12 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
afterApplyPendingAttributesOfChildren(context, inflater, view) {
|
afterApplyPendingAttributesOfChildren(context, inflater, view) {
|
||||||
// Empty method body
|
// Empty method body
|
||||||
},
|
},
|
||||||
beforeApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
|
afterInflateView(context, view, node, parent, attachToParent) {
|
||||||
let isDynamic = layoutInflater.isDynamicValue(value);
|
let { widget } = view;
|
||||||
return isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS
|
if (widget && context.get('root') !== widget) {
|
||||||
|| !isDynamic && layoutInflater.getInflateFlags() === DynamicLayoutInflater.FLAG_JUST_DYNAMIC_ATTRS
|
widget.notifyAfterInflation(view);
|
||||||
|| (/* @IIFE */ () => {
|
}
|
||||||
value = _.bind(value);
|
return view;
|
||||||
let widget = context.get('widget');
|
|
||||||
if (widget !== null && widget.hasAttr(attrName)) {
|
|
||||||
widget.setAttr(view, attrName, value, (view, attrName, value) => {
|
|
||||||
inflater.setAttr(view, ns, attrName, value, parent, attrs);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
inflater.setAttr(view, ns, attrName, value, parent, attrs);
|
|
||||||
}
|
|
||||||
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
|
|
||||||
return true;
|
|
||||||
})();
|
|
||||||
},
|
|
||||||
afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs) {
|
|
||||||
// Empty method body
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bind(value) {
|
bind(value) {
|
||||||
@@ -333,7 +351,8 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
if (j < 0) {
|
if (j < 0) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
value = value.slice(0, i) + _.evalInContext(value.slice(i + 2, j), ctx) + value.slice(j + 2);
|
let evaluated = _.evalInContext(value.slice(i + 2, j), ctx);
|
||||||
|
value = value.slice(0, i) + _.attrValueConvert(evaluated) + value.slice(j + 2);
|
||||||
i = j + 1;
|
i = j + 1;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@@ -401,6 +420,18 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
setLayoutInflaterDelegate() {
|
setLayoutInflaterDelegate() {
|
||||||
layoutInflater.setLayoutInflaterDelegate(this.layoutInflaterDelegate);
|
layoutInflater.setLayoutInflaterDelegate(this.layoutInflaterDelegate);
|
||||||
},
|
},
|
||||||
|
attrValueConvert(o) {
|
||||||
|
if (typeof o === 'string') {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
if (o instanceof scope.Color) {
|
||||||
|
return o.toHex();
|
||||||
|
}
|
||||||
|
if (o instanceof ThemeColor) {
|
||||||
|
return o.getColorPrimary();
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
|
||||||
|
/* Overwritten protection. */
|
||||||
|
|
||||||
|
let { http } = global;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
* @param {org.autojs.autojs.runtime.ScriptRuntime} scriptRuntime
|
||||||
* @param {org.mozilla.javascript.Scriptable | global} scope
|
* @param {org.mozilla.javascript.Scriptable | global} scope
|
||||||
@@ -38,6 +42,9 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
newInjectableWebClient() {
|
newInjectableWebClient() {
|
||||||
return new InjectableWebClient(Context.getCurrentContext(), scope);
|
return new InjectableWebClient(Context.getCurrentContext(), scope);
|
||||||
},
|
},
|
||||||
|
newWebSocket(url) {
|
||||||
|
return new org.autojs.autojs.core.web.WebSocket(http.__okhttp__, url);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return Web;
|
return Web;
|
||||||
@@ -46,7 +53,7 @@ module.exports = function (scriptRuntime, scope) {
|
|||||||
/**
|
/**
|
||||||
* @type {(keyof Internal.Web)[]}
|
* @type {(keyof Internal.Web)[]}
|
||||||
*/
|
*/
|
||||||
let methods = [ 'newInjectableWebView', 'newInjectableWebClient' ];
|
let methods = [ 'newInjectableWebView', 'newInjectableWebClient', 'newWebSocket' ];
|
||||||
__asGlobal__(web, methods, scope);
|
__asGlobal__(web, methods, scope);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
module.exports = function(){
|
module.exports = function(){
|
||||||
Object.observe&&!Array.observe&&function(t,e){"use strict";var n=t.getNotifier,r="performChange",i="_original",o="splice";var u={push:function h(t){var e=arguments,u=h[i].apply(this,e);n(this)[r](o,function(){return{index:u-e.length,addedCount:e.length,removed:[]}});return u},unshift:function d(t){var e=arguments,u=d[i].apply(this,e);n(this)[r](o,function(){return{index:0,addedCount:e.length,removed:[]}});return u},pop:function a(){var t=this.length,e=a[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:this.length,addedCount:0,removed:[e]}},this);return e},shift:function l(){var t=this.length,e=l[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:0,addedCount:0,removed:[e]}},this);return e},splice:function f(t,e){var u=arguments,s=f[i].apply(this,u);if(s.length||u.length>2)n(this)[r](o,function(){return{index:t,addedCount:u.length-2,removed:s}},this);return s}};for(var s in u){u[s][i]=e.prototype[s];e.prototype[s]=u[s]}e.observe=function(e,n){return t.observe(e,n,["add","update","delete",o])};e.unobserve=t.unobserve}(Object,Array);
|
Object.observe&&!Array.observe&&function(t,e){var n=t.getNotifier,r="performChange",i="_original",o="splice";var u={push:function h(t){var e=arguments,u=h[i].apply(this,e);n(this)[r](o,function(){return{index:u-e.length,addedCount:e.length,removed:[]}});return u},unshift:function d(t){var e=arguments,u=d[i].apply(this,e);n(this)[r](o,function(){return{index:0,addedCount:e.length,removed:[]}});return u},pop:function a(){var t=this.length,e=a[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:this.length,addedCount:0,removed:[e]}},this);return e},shift:function l(){var t=this.length,e=l[i].call(this);if(this.length!==t)n(this)[r](o,function(){return{index:0,addedCount:0,removed:[e]}},this);return e},splice:function f(t,e){var u=arguments,s=f[i].apply(this,u);if(s.length||u.length>2)n(this)[r](o,function(){return{index:t,addedCount:u.length-2,removed:s}},this);return s}};for(var s in u){u[s][i]=e.prototype[s];e.prototype[s]=u[s]}e.observe=function(e,n){return t.observe(e,n,["add","update","delete",o])};e.unobserve=t.unobserve}(Object,Array);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
( /* @ModuleIIFE */ () => {
|
( /* @ModuleIIFE */ () => {
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var _createClass = function () {
|
var _createClass = function () {
|
||||||
function defineProperties(target, props) {
|
function defineProperties(target, props) {
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
* @see https://raw.githubusercontent.com/taylorhakes/promise-polyfill/master/dist/polyfill.js
|
* @see https://raw.githubusercontent.com/taylorhakes/promise-polyfill/master/dist/polyfill.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {PromiseConstructorLike}
|
* @type {PromiseConstructorLike}
|
||||||
*/
|
*/
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,142 @@
|
|||||||
|
'ui';
|
||||||
|
|
||||||
|
let themeColor = 'orange-800';
|
||||||
|
|
||||||
|
let materialColors = [
|
||||||
|
'amber-500',
|
||||||
|
'blue-500',
|
||||||
|
'blue-grey-500',
|
||||||
|
'brown-500',
|
||||||
|
'cyan-500',
|
||||||
|
'deep-orange-500',
|
||||||
|
'deep-purple-500',
|
||||||
|
'green-500',
|
||||||
|
'grey-500',
|
||||||
|
'indigo-500',
|
||||||
|
'light-blue-500',
|
||||||
|
'light-green-500',
|
||||||
|
'lime-500',
|
||||||
|
'orange-500',
|
||||||
|
'pink-500',
|
||||||
|
'purple-500',
|
||||||
|
'red-500',
|
||||||
|
'teal-500',
|
||||||
|
'yellow-500',
|
||||||
|
];
|
||||||
|
|
||||||
|
let storage = storages.create('todoList');
|
||||||
|
|
||||||
|
storage.clear();
|
||||||
|
|
||||||
|
ui.layout(
|
||||||
|
<frame>
|
||||||
|
<vertical>
|
||||||
|
<appbar>
|
||||||
|
<toolbar id="toolbar" title="TODO" />
|
||||||
|
</appbar>
|
||||||
|
<button id="selectAll" text="全部完成" isColored margin="6 4" />
|
||||||
|
<list id="todoList">
|
||||||
|
<card w="*" h="70" margin="10 5" cardCornerRadius="2dp"
|
||||||
|
cardElevation="1dp" foreground="?selectableItemBackground">
|
||||||
|
<horizontal gravity="center_vertical">
|
||||||
|
<view bg="{{this.color}}" h="*" w="10" />
|
||||||
|
<vertical padding="10 8" h="auto" w="0" layout_weight="1">
|
||||||
|
<text id="title" text="{{this.title}}" textColor="blue-grey-900" textSize="16sp" maxLines="1" paddingBottom="4dp" />
|
||||||
|
<text text="{{this.summary}}" textColor="blue-grey-300" textSize="14sp" maxLines="1" />
|
||||||
|
</vertical>
|
||||||
|
<checkbox id="done" marginLeft="4" marginRight="6" checked="{{this.done}}" tint="blue-grey-500,pink-300" />
|
||||||
|
</horizontal>
|
||||||
|
</card>
|
||||||
|
</list>
|
||||||
|
</vertical>
|
||||||
|
<fab id="add" w="auto" h="auto" src="@drawable/ic_add_black_48dp"
|
||||||
|
margin="16" layout_gravity="bottom|right" tint="white" backgroundTint="orange-800" />
|
||||||
|
</frame>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 从 storage 获取待办事项列表
|
||||||
|
let todoList = storage.get('items', [{
|
||||||
|
title: '写操作系统作业',
|
||||||
|
summary: '明天第 1 - 2 节',
|
||||||
|
color: 'red-500',
|
||||||
|
done: false,
|
||||||
|
}, {
|
||||||
|
title: '给 ui 模式增加若干 bug',
|
||||||
|
summary: '无限期',
|
||||||
|
color: 'orange-500',
|
||||||
|
done: false,
|
||||||
|
}, {
|
||||||
|
title: '发布 AutoJs6 v6.6.6',
|
||||||
|
summary: '2066 年 6 月',
|
||||||
|
color: 'teal-500',
|
||||||
|
done: false,
|
||||||
|
}, {
|
||||||
|
title: '完成 AutoJs6 文档撰写',
|
||||||
|
summary: '2031 年 5 月',
|
||||||
|
color: '#2196f3',
|
||||||
|
done: false,
|
||||||
|
}]);
|
||||||
|
|
||||||
|
ui.statusBarColor(themeColor);
|
||||||
|
ui['toolbar'].attr('bg', themeColor);
|
||||||
|
ui['selectAll'].attr('backgroundTint', 'pink-300');
|
||||||
|
|
||||||
|
ui['todoList'].setDataSource(todoList);
|
||||||
|
|
||||||
|
ui['selectAll'].on('click', function () {
|
||||||
|
todoList.forEach(item => {
|
||||||
|
item.done = true;
|
||||||
|
});
|
||||||
|
// 通知数据全部更新
|
||||||
|
ui['todoList'].adapter.notifyDataSetChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
ui['todoList'].on('item_bind', function (itemView, itemHolder) {
|
||||||
|
// 绑定勾选框事件
|
||||||
|
itemView.done.on('check', function (checked) {
|
||||||
|
let item = itemHolder.item;
|
||||||
|
item.done = checked;
|
||||||
|
let paint = itemView.title.paint;
|
||||||
|
// 设置或取消中划线效果
|
||||||
|
if (checked) {
|
||||||
|
paint.flags |= Paint.STRIKE_THRU_TEXT_FLAG;
|
||||||
|
} else {
|
||||||
|
paint.flags &= ~Paint.STRIKE_THRU_TEXT_FLAG;
|
||||||
|
}
|
||||||
|
itemView.title.invalidate();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ui['todoList'].on('item_click', function (item, i, itemView) {
|
||||||
|
itemView.done.checked = !itemView.done.checked;
|
||||||
|
});
|
||||||
|
|
||||||
|
ui['todoList'].on('item_long_click', function (e, item, i) {
|
||||||
|
confirm(`确定要删除 "${item.title}" 吗?`)
|
||||||
|
.then(ok => {
|
||||||
|
if (ok) {
|
||||||
|
todoList.splice(i, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
e.consumed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 当离开本界面时保存 todoList
|
||||||
|
ui.emitter.on('pause', () => storage.put('items', todoList));
|
||||||
|
|
||||||
|
ui['add'].on('click', () => {
|
||||||
|
dialogs.rawInput('请输入标题')
|
||||||
|
.then((title) => {
|
||||||
|
if (!title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialogs.rawInput('请输入期限', '明天')
|
||||||
|
.then(summary => {
|
||||||
|
todoList.push({
|
||||||
|
title: title,
|
||||||
|
summary: summary,
|
||||||
|
color: materialColors[random(0, materialColors.length - 1)],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,34 @@
|
|||||||
|
'ui';
|
||||||
|
|
||||||
|
const themeColor = Color(autojs.themeColor);
|
||||||
|
const colorRelativeRate = 1.8;
|
||||||
|
|
||||||
|
ui.layout(
|
||||||
|
<org.autojs.autojs.core.ui.widget.JsTextClock
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/text_clock"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:format24Hour="HH:mm"
|
||||||
|
android:textSize="36sp"/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
/* 1 秒钟后应用自定义样式. */
|
||||||
|
setTimeout(() => {
|
||||||
|
ui.statusBarColor(themeColor);
|
||||||
|
ui.backgroundColor(
|
||||||
|
Color(themeColor)
|
||||||
|
.setRedRelative(colorRelativeRate)
|
||||||
|
.setGreenRelative(colorRelativeRate)
|
||||||
|
.setBlueRelative(colorRelativeRate)
|
||||||
|
.toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
/** @type {JsTextClock} */
|
||||||
|
let textClockView = ui.text_clock;
|
||||||
|
|
||||||
|
textClockView.attr('color', themeColor.toInt());
|
||||||
|
textClockView.attr('size', '56');
|
||||||
|
textClockView.attr('layout_gravity', 'center');
|
||||||
|
textClockView.attr('format24Hour', 'HH:mm:ss');
|
||||||
|
}, 1e3);
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-2
@@ -4,12 +4,12 @@ ui.layout(
|
|||||||
<vertical padding="16">
|
<vertical padding="16">
|
||||||
<checkbox id="cb1" text="复选框"/>
|
<checkbox id="cb1" text="复选框"/>
|
||||||
<checkbox id="cb2" checked="true" text="勾选的复选框"/>
|
<checkbox id="cb2" checked="true" text="勾选的复选框"/>
|
||||||
<radiogroup>
|
<radiogroup marginTop="16">
|
||||||
<radio text="单选框1"/>
|
<radio text="单选框1"/>
|
||||||
<radio text="单选框2"/>
|
<radio text="单选框2"/>
|
||||||
<radio text="单选框3"/>
|
<radio text="单选框3"/>
|
||||||
</radiogroup>
|
</radiogroup>
|
||||||
<radiogroup mariginTop="16">
|
<radiogroup marginTop="16">
|
||||||
<radio text="单选框1"/>
|
<radio text="单选框1"/>
|
||||||
<radio text="单选框2"/>
|
<radio text="单选框2"/>
|
||||||
<radio text="勾选的单选框3" checked="true"/>
|
<radio text="勾选的单选框3" checked="true"/>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
'ui';
|
||||||
|
|
||||||
|
ui.layout(<vertical gravity="center">
|
||||||
|
<horizontal width="-1" gravity="center" margin="16">
|
||||||
|
<text text="滑块单色/轨道单色" size="16" marginEnd="32"/>
|
||||||
|
<switch checked="false" thumbTint="orange-800" trackTint="orange-200" marginEnd="16"></switch>
|
||||||
|
<switch checked="true" thumbTint="orange-800" trackTint="orange-200"></switch>
|
||||||
|
</horizontal>
|
||||||
|
<horizontal width="-1" gravity="center" margin="16">
|
||||||
|
<text text="滑块单色/轨道双色" size="16" marginEnd="32"/>
|
||||||
|
<switch checked="false" thumbTint="orange-800" trackTint="light-gray/orange-200" marginEnd="16"></switch>
|
||||||
|
<switch checked="true" thumbTint="orange-800" trackTint="light-gray/orange-200"></switch>
|
||||||
|
</horizontal>
|
||||||
|
<horizontal width="-1" gravity="center" margin="16">
|
||||||
|
<text text="滑块双色/轨道单色" size="16" marginEnd="32"/>
|
||||||
|
<switch checked="false" thumbTint="gray/orange-800" trackTint="light-gray" marginEnd="16"></switch>
|
||||||
|
<switch checked="true" thumbTint="gray/orange-800" trackTint="light-gray"></switch>
|
||||||
|
</horizontal>
|
||||||
|
<horizontal width="-1" gravity="center" margin="16">
|
||||||
|
<text text="滑块双色/轨道双色" size="16" marginEnd="32"/>
|
||||||
|
<switch checked="false" thumbTint="gray/orange-800" trackTint="light-gray/orange-200" marginEnd="16"></switch>
|
||||||
|
<switch checked="true" thumbTint="gray/orange-800" trackTint="light-gray/orange-200"></switch>
|
||||||
|
</horizontal>
|
||||||
|
</vertical>);
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-2
@@ -13,10 +13,8 @@ const assert = (value, message) => {
|
|||||||
message && console.verbose(`${message} passed`);
|
message && console.verbose(`${message} passed`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const SecurityException = java.lang.SecurityException;
|
|
||||||
const AtomicLong = java.util.concurrent.atomic.AtomicLong;
|
const AtomicLong = java.util.concurrent.atomic.AtomicLong;
|
||||||
const JavaScriptEngine = org.autojs.autojs.engine.JavaScriptEngine;
|
const JavaScriptEngine = org.autojs.autojs.engine.JavaScriptEngine;
|
||||||
const JsLinearLayout = org.autojs.autojs.core.ui.widget.JsLinearLayout;
|
|
||||||
|
|
||||||
// @Test Rhino basic
|
// @Test Rhino basic
|
||||||
|
|
||||||
-1
@@ -16,7 +16,6 @@ const assert = (value, message) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const JavaScriptEngine = org.autojs.autojs.engine.JavaScriptEngine;
|
const JavaScriptEngine = org.autojs.autojs.engine.JavaScriptEngine;
|
||||||
const JsLinearLayout = org.autojs.autojs.core.ui.widget.JsLinearLayout;
|
|
||||||
|
|
||||||
// @Test auto
|
// @Test auto
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,46 @@
|
|||||||
|
// noinspection HtmlUnknownAttribute
|
||||||
|
|
||||||
|
let win = floaty.window(
|
||||||
|
<vertical bg="white" padding="24">
|
||||||
|
<input id="input" hint="请输入任意内容" textSize="16sp" margin="0 12"/>
|
||||||
|
<view h="1" w="180" layout_weight="1"/>
|
||||||
|
<button id="ok" text="确定" bgTint="light-blue-600" color="white" layout_gravity="bottom"/>
|
||||||
|
</vertical>,
|
||||||
|
);
|
||||||
|
|
||||||
|
win.exitOnClose();
|
||||||
|
|
||||||
|
/** @type {JsButton} */
|
||||||
|
let buttonView = win['ok'];
|
||||||
|
|
||||||
|
/** @type {JsEditText} */
|
||||||
|
let inputView = win['input'];
|
||||||
|
|
||||||
|
toast(`长按 "${buttonView.attr('text')}" 键可调整浮动窗口样式`, 'long');
|
||||||
|
|
||||||
|
inputView.on('click', () => {
|
||||||
|
win.requestFocus();
|
||||||
|
});
|
||||||
|
|
||||||
|
inputView.on('key_up', function (keyCode, event) {
|
||||||
|
if (keyCode === keys.back) {
|
||||||
|
win.disableFocus();
|
||||||
|
event.consumed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonView.on('click', () => {
|
||||||
|
let text = inputView.text();
|
||||||
|
text
|
||||||
|
? toast('输入内容: ' + text)
|
||||||
|
: toast('未输入任何内容');
|
||||||
|
win.disableFocus();
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonView.on('long_click', (event) => {
|
||||||
|
toast.dismissAll();
|
||||||
|
win.setAdjustEnabled(!win.isAdjustEnabled());
|
||||||
|
event.consumed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(() => null, 1000);
|
||||||
File renamed without changes.
File renamed without changes.
@@ -20,16 +20,16 @@ import org.autojs.autojs.runtime.api.AppUtils.Companion.ActivityShortForm
|
|||||||
import org.autojs.autojs.runtime.api.AppUtils.Companion.BroadcastShortForm
|
import org.autojs.autojs.runtime.api.AppUtils.Companion.BroadcastShortForm
|
||||||
import org.autojs.autojs.runtime.exception.ScriptException
|
import org.autojs.autojs.runtime.exception.ScriptException
|
||||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
||||||
import org.autojs.autojs.ui.doc.DocumentationActivity_
|
import org.autojs.autojs.ui.doc.DocumentationActivity
|
||||||
import org.autojs.autojs.ui.floating.FloatyWindowManger
|
import org.autojs.autojs.ui.floating.FloatyWindowManger
|
||||||
import org.autojs.autojs.ui.floating.FullScreenFloatyWindow
|
import org.autojs.autojs.ui.floating.FullScreenFloatyWindow
|
||||||
import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow
|
import org.autojs.autojs.ui.floating.layoutinspector.LayoutBoundsFloatyWindow
|
||||||
import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow
|
import org.autojs.autojs.ui.floating.layoutinspector.LayoutHierarchyFloatyWindow
|
||||||
import org.autojs.autojs.ui.log.LogActivity_
|
import org.autojs.autojs.ui.log.LogActivity
|
||||||
import org.autojs.autojs.ui.main.MainActivity_
|
import org.autojs.autojs.ui.main.MainActivity
|
||||||
import org.autojs.autojs.ui.project.BuildActivity_
|
import org.autojs.autojs.ui.project.BuildActivity
|
||||||
import org.autojs.autojs.ui.settings.AboutActivity_
|
import org.autojs.autojs.ui.settings.AboutActivity
|
||||||
import org.autojs.autojs.ui.settings.SettingsActivity_
|
import org.autojs.autojs.ui.settings.PreferencesActivity
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
@@ -141,23 +141,23 @@ class AutoJs private constructor(private val appContext: Application) : Abstract
|
|||||||
|
|
||||||
/* Activities. */
|
/* Activities. */
|
||||||
|
|
||||||
putProperty(ActivityShortForm.SETTINGS.fullName, SettingsActivity_::class.java)
|
putProperty(ActivityShortForm.SETTINGS.fullName, PreferencesActivity::class.java)
|
||||||
putProperty(ActivityShortForm.PREFERENCES.fullName, SettingsActivity_::class.java)
|
putProperty(ActivityShortForm.PREFERENCES.fullName, PreferencesActivity::class.java)
|
||||||
putProperty(ActivityShortForm.PREF.fullName, SettingsActivity_::class.java)
|
putProperty(ActivityShortForm.PREF.fullName, PreferencesActivity::class.java)
|
||||||
|
|
||||||
putProperty(ActivityShortForm.CONSOLE.fullName, LogActivity_::class.java)
|
putProperty(ActivityShortForm.CONSOLE.fullName, LogActivity::class.java)
|
||||||
putProperty(ActivityShortForm.LOG.fullName, LogActivity_::class.java)
|
putProperty(ActivityShortForm.LOG.fullName, LogActivity::class.java)
|
||||||
|
|
||||||
putProperty(ActivityShortForm.HOMEPAGE.fullName, MainActivity_::class.java)
|
putProperty(ActivityShortForm.HOMEPAGE.fullName, MainActivity::class.java)
|
||||||
putProperty(ActivityShortForm.HOME.fullName, MainActivity_::class.java)
|
putProperty(ActivityShortForm.HOME.fullName, MainActivity::class.java)
|
||||||
|
|
||||||
putProperty(ActivityShortForm.ABOUT.fullName, AboutActivity_::class.java)
|
putProperty(ActivityShortForm.ABOUT.fullName, AboutActivity::class.java)
|
||||||
|
|
||||||
putProperty(ActivityShortForm.BUILD.fullName, BuildActivity_::class.java)
|
putProperty(ActivityShortForm.BUILD.fullName, BuildActivity::class.java)
|
||||||
|
|
||||||
putProperty(ActivityShortForm.DOCUMENTATION.fullName, DocumentationActivity_::class.java)
|
putProperty(ActivityShortForm.DOCUMENTATION.fullName, DocumentationActivity::class.java)
|
||||||
putProperty(ActivityShortForm.DOC.fullName, DocumentationActivity_::class.java)
|
putProperty(ActivityShortForm.DOC.fullName, DocumentationActivity::class.java)
|
||||||
putProperty(ActivityShortForm.DOCS.fullName, DocumentationActivity_::class.java)
|
putProperty(ActivityShortForm.DOCS.fullName, DocumentationActivity::class.java)
|
||||||
|
|
||||||
/* Broadcasts. */
|
/* Broadcasts. */
|
||||||
|
|
||||||
|
|||||||
@@ -6,36 +6,30 @@ import android.view.ContextThemeWrapper;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.autojs.autojs6.R;
|
import org.autojs.autojs6.R;
|
||||||
|
import org.autojs.autojs6.databinding.OperationDialogItemBinding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/6/26.
|
* Created by Stardust on 2017/6/26.
|
||||||
*/
|
*/
|
||||||
public class CircularMenuOperationDialogBuilder extends AppLevelThemeDialogBuilder {
|
public class CircularMenuOperationDialogBuilder extends AppLevelThemeDialogBuilder {
|
||||||
|
|
||||||
private final RecyclerView mOperations;
|
private final ArrayList<View.OnClickListener> mOnClickListeners = new ArrayList<>();
|
||||||
private final ArrayList<Integer> mIds = new ArrayList<>();
|
|
||||||
private final ArrayList<Integer> mIcons = new ArrayList<>();
|
private final ArrayList<Integer> mIcons = new ArrayList<>();
|
||||||
private final ArrayList<String> mTexts = new ArrayList<>();
|
private final ArrayList<String> mTexts = new ArrayList<>();
|
||||||
private Object mOnItemClickTarget;
|
|
||||||
|
|
||||||
public CircularMenuOperationDialogBuilder(@NonNull Context context) {
|
public CircularMenuOperationDialogBuilder(@NonNull Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
mOperations = new RecyclerView(context);
|
RecyclerView operations = new RecyclerView(context);
|
||||||
mOperations.setLayoutManager(new LinearLayoutManager(context));
|
operations.setLayoutManager(new LinearLayoutManager(context));
|
||||||
mOperations.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
|
operations.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
@@ -44,51 +38,48 @@ public class CircularMenuOperationDialogBuilder extends AppLevelThemeDialogBuild
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
holder.itemView.setId(mIds.get(position));
|
holder.itemView.setOnClickListener(mOnClickListeners.get(position));
|
||||||
holder.text.setText(mTexts.get(position));
|
holder.binding.text.setText(mTexts.get(position));
|
||||||
holder.text.setTextColor(context.getColor(R.color.day_night));
|
holder.binding.text.setTextColor(context.getColor(R.color.day_night));
|
||||||
holder.icon.setImageResource(mIcons.get(position));
|
holder.binding.icon.setImageResource(mIcons.get(position));
|
||||||
holder.icon.setImageTintList(ColorStateList.valueOf(context.getColor(R.color.day_night)));
|
holder.binding.icon.setImageTintList(ColorStateList.valueOf(context.getColor(R.color.day_night)));
|
||||||
if (mOnItemClickTarget != null) {
|
|
||||||
//// TODO: 2017/6/26 效率
|
|
||||||
ButterKnife.bind(mOnItemClickTarget, holder.itemView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mIds.size();
|
return mOnClickListeners.size();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
customView(mOperations, false);
|
customView(operations, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CircularMenuOperationDialogBuilder item(int id, int iconRes, int textRes) {
|
public CircularMenuOperationDialogBuilder item(int iconRes, int textRes) {
|
||||||
return item(id, iconRes, getContext().getString(textRes));
|
return item(iconRes, textRes, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CircularMenuOperationDialogBuilder item(int id, int iconRes, String text) {
|
public CircularMenuOperationDialogBuilder item(int iconRes, int textRes, View.OnClickListener l) {
|
||||||
mIds.add(id);
|
return item(iconRes, getContext().getString(textRes), l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircularMenuOperationDialogBuilder item(int iconRes, String text) {
|
||||||
|
return item(iconRes, text, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircularMenuOperationDialogBuilder item(int iconRes, String text, View.OnClickListener l) {
|
||||||
|
mOnClickListeners.add(l);
|
||||||
mIcons.add(iconRes);
|
mIcons.add(iconRes);
|
||||||
mTexts.add(text);
|
mTexts.add(text);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CircularMenuOperationDialogBuilder bindItemClick(Object target) {
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
mOnItemClickTarget = target;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
@NonNull
|
||||||
|
public final OperationDialogItemBinding binding;
|
||||||
@BindView(R.id.icon)
|
|
||||||
ImageView icon;
|
|
||||||
@BindView(R.id.text)
|
|
||||||
TextView text;
|
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
binding = OperationDialogItemBinding.bind(itemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,19 +14,40 @@ class JsonSocketClientTool(context: Context) : AbstractJsonSocketTool(context) {
|
|||||||
override val isConnected
|
override val isConnected
|
||||||
get() = devPlugin.isJsonSocketClientConnected
|
get() = devPlugin.isJsonSocketClientConnected
|
||||||
|
|
||||||
|
private var isNormallyClosed
|
||||||
|
get() = devPlugin.isClientSocketNormallyClosed
|
||||||
|
set(state) {
|
||||||
|
devPlugin.isClientSocketNormallyClosed = state
|
||||||
|
}
|
||||||
|
|
||||||
override val isInMainThread = true
|
override val isInMainThread = true
|
||||||
|
|
||||||
override fun connect() = inputRemoteHost()
|
override fun connect() {
|
||||||
|
inputRemoteHost(isAutoConnect = !isNormallyClosed)
|
||||||
|
}
|
||||||
|
|
||||||
override fun disconnect() = devPlugin.disconnectJsonSocketClient()
|
internal fun connectIfNotNormallyClosed() {
|
||||||
|
if (!isNormallyClosed) connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun disconnect() {
|
||||||
|
devPlugin.disconnectJsonSocketClient()
|
||||||
|
isNormallyClosed = true
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
stateDisposable?.dispose()
|
stateDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
private fun inputRemoteHost() {
|
private fun inputRemoteHost(isAutoConnect: Boolean) {
|
||||||
val host = Pref.getServerAddress()
|
val host = Pref.getServerAddress()
|
||||||
|
if (isAutoConnect) {
|
||||||
|
devPlugin
|
||||||
|
.connectToRemoteServer(host, true)
|
||||||
|
.subscribe(Observers.emptyConsumer(), Observers.emptyConsumer())
|
||||||
|
return
|
||||||
|
}
|
||||||
MaterialDialog.Builder(context)
|
MaterialDialog.Builder(context)
|
||||||
.title(R.string.text_pc_server_address)
|
.title(R.string.text_pc_server_address)
|
||||||
.input(context.getString(R.string.text_pc_server_address), host) { _, input ->
|
.input(context.getString(R.string.text_pc_server_address), host) { _, input ->
|
||||||
|
|||||||
@@ -9,14 +9,28 @@ class JsonSocketServerTool(context: Context) : AbstractJsonSocketTool(context) {
|
|||||||
override val isConnected
|
override val isConnected
|
||||||
get() = devPlugin.isServerSocketConnected
|
get() = devPlugin.isServerSocketConnected
|
||||||
|
|
||||||
|
private var isNormallyClosed
|
||||||
|
get() = devPlugin.isServerSocketNormallyClosed
|
||||||
|
set(state) {
|
||||||
|
devPlugin.isServerSocketNormallyClosed = state
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
override fun connect() {
|
override fun connect() {
|
||||||
devPlugin
|
devPlugin
|
||||||
.enableLocalServer()
|
.enableLocalServer()
|
||||||
.subscribe(Observers.emptyConsumer(), onConnectionException)
|
.subscribe(Observers.emptyConsumer(), onConnectionException)
|
||||||
|
isNormallyClosed = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun disconnect() = devPlugin.disconnectJsonSocketServer()
|
internal fun connectIfNotNormallyClosed() {
|
||||||
|
if (!isNormallyClosed) connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun disconnect() {
|
||||||
|
devPlugin.disconnectJsonSocketServer()
|
||||||
|
isNormallyClosed = true
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
stateDisposable?.dispose()
|
stateDisposable?.dispose()
|
||||||
|
|||||||
@@ -54,9 +54,6 @@ import org.mozilla.javascript.BaseFunction
|
|||||||
import org.mozilla.javascript.NativeArray
|
import org.mozilla.javascript.NativeArray
|
||||||
import org.mozilla.javascript.NativeJavaMethod
|
import org.mozilla.javascript.NativeJavaMethod
|
||||||
import org.mozilla.javascript.regexp.NativeRegExp
|
import org.mozilla.javascript.regexp.NativeRegExp
|
||||||
import java.lang.Boolean.parseBoolean
|
|
||||||
import java.lang.Float.parseFloat
|
|
||||||
import java.lang.Integer.parseInt
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -993,43 +990,43 @@ open class UiSelector : UiObjectActions {
|
|||||||
doubleTypes.containsKey(key) -> when (val types = doubleTypes.getValue(key)) {
|
doubleTypes.containsKey(key) -> when (val types = doubleTypes.getValue(key)) {
|
||||||
cDouble -> tmp::class.java
|
cDouble -> tmp::class.java
|
||||||
.getMethod(key, cDouble)
|
.getMethod(key, cDouble)
|
||||||
.invoke(tmp, *value.map { parseFloat(it.toString()).toDouble() }.toTypedArray())
|
.invoke(tmp, *value.map { it.toString().toDouble() }.toTypedArray())
|
||||||
is Array<*> -> when ( /* isOverloaded */ types.any { it is Array<*> }) {
|
is Array<*> -> when ( /* isOverloaded */ types.any { it is Array<*> }) {
|
||||||
true -> when (value.size) {
|
true -> when (value.size) {
|
||||||
1 -> types.find { it == cDouble }?.let {
|
1 -> types.find { it == cDouble }?.let {
|
||||||
tmp::class.java
|
tmp::class.java
|
||||||
.getMethod(key, cDouble)
|
.getMethod(key, cDouble)
|
||||||
.invoke(tmp, parseFloat(value[0].toString()).toDouble())
|
.invoke(tmp, value[0].toString().toDouble())
|
||||||
} ?: throw Error()
|
} ?: throw Exception("UiSelector: $key($value)")
|
||||||
2 -> types.find { it is Array<*> }?.let { type: Any ->
|
2 -> types.find { it is Array<*> }?.let { type: Any ->
|
||||||
val t = type as Array<*>
|
val t = type as Array<*>
|
||||||
when {
|
when {
|
||||||
t[0] == cDouble && t[1] == cDouble -> tmp::class.java
|
t[0] == cDouble && t[1] == cDouble -> tmp::class.java
|
||||||
.getMethod(key, cDouble, cDouble)
|
.getMethod(key, cDouble, cDouble)
|
||||||
.invoke(tmp, *value.map { parseFloat(it.toString()).toDouble() }.toTypedArray())
|
.invoke(tmp, *value.map { it.toString().toDouble() }.toTypedArray())
|
||||||
t[0] == cBoolean && t[1] == cDouble -> tmp::class.java
|
t[0] == cBoolean && t[1] == cDouble -> tmp::class.java
|
||||||
.getMethod(key, cBoolean, cDouble)
|
.getMethod(key, cBoolean, cDouble)
|
||||||
.invoke(tmp, *value.mapIndexed { index, any ->
|
.invoke(tmp, *value.mapIndexed { index, any ->
|
||||||
when (index) {
|
when (index) {
|
||||||
0 -> parseBoolean(any.toString())
|
0 -> any.toString().toBoolean()
|
||||||
1 -> parseFloat(any.toString()).toDouble()
|
1 -> any.toString().toDouble()
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
}.toTypedArray())
|
}.toTypedArray())
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
} ?: throw Error()
|
} ?: throw Exception("UiSelector: $key($value)")
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
else -> @Suppress("UNCHECKED_CAST") tmp::class.java
|
else -> @Suppress("UNCHECKED_CAST") tmp::class.java
|
||||||
.getMethod(key, *(types as Array<out Class<*>>))
|
.getMethod(key, *(types as Array<out Class<*>>))
|
||||||
.invoke(tmp, *value.map { parseFloat(it.toString()).toDouble() }.toTypedArray())
|
.invoke(tmp, *value.map { it.toString().toDouble() }.toTypedArray())
|
||||||
}
|
}
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
intTypes.contains(key) -> tmp::class.java
|
intTypes.contains(key) -> tmp::class.java
|
||||||
.getMethod(key, cInt)
|
.getMethod(key, cInt)
|
||||||
.invoke(tmp, parseInt(value[0].toString()))
|
.invoke(tmp, value[0].toString().toInt())
|
||||||
stringTypes.contains(key) -> tmp::class.java
|
stringTypes.contains(key) -> tmp::class.java
|
||||||
.getMethod(key, cString)
|
.getMethod(key, cString)
|
||||||
.invoke(tmp, value[0])
|
.invoke(tmp, value[0])
|
||||||
@@ -1040,7 +1037,7 @@ open class UiSelector : UiObjectActions {
|
|||||||
is String -> tmp::class.java
|
is String -> tmp::class.java
|
||||||
.getMethod(key, cString)
|
.getMethod(key, cString)
|
||||||
.invoke(tmp, value[0])
|
.invoke(tmp, value[0])
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
appTypes.contains(key) -> when (value[0]) {
|
appTypes.contains(key) -> when (value[0]) {
|
||||||
is App -> tmp::class.java
|
is App -> tmp::class.java
|
||||||
@@ -1049,7 +1046,7 @@ open class UiSelector : UiObjectActions {
|
|||||||
is String -> tmp::class.java
|
is String -> tmp::class.java
|
||||||
.getMethod(key, cString)
|
.getMethod(key, cString)
|
||||||
.invoke(tmp, value[0])
|
.invoke(tmp, value[0])
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
nullableBoolTypes.contains(key) -> when (value.size) {
|
nullableBoolTypes.contains(key) -> when (value.size) {
|
||||||
0 -> tmp::class.java
|
0 -> tmp::class.java
|
||||||
@@ -1057,12 +1054,12 @@ open class UiSelector : UiObjectActions {
|
|||||||
.invoke(tmp)
|
.invoke(tmp)
|
||||||
1 -> tmp::class.java
|
1 -> tmp::class.java
|
||||||
.getMethod(key, cBoolean)
|
.getMethod(key, cBoolean)
|
||||||
.invoke(tmp, parseBoolean(value[0].toString()))
|
.invoke(tmp, value[0].toString().toBoolean())
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
else -> throw Error()
|
else -> throw Exception("UiSelector: $key($value)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: NoSuchMethodException) {
|
} catch (e: NoSuchMethodException) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
@@ -17,12 +18,17 @@ import org.autojs.autojs.ui.enhancedfloaty.ResizableExpandableFloaty.AbstractRes
|
|||||||
import org.autojs.autojs.ui.enhancedfloaty.ResizableExpandableFloatyWindow
|
import org.autojs.autojs.ui.enhancedfloaty.ResizableExpandableFloatyWindow
|
||||||
import org.autojs.autojs.util.ViewUtils.setViewMeasure
|
import org.autojs.autojs.util.ViewUtils.setViewMeasure
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
|
import org.autojs.autojs6.databinding.FloatingConsoleExpandBinding
|
||||||
|
import org.autojs.autojs6.databinding.FloatingWindowCollapseBinding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/4/20.
|
* Created by Stardust on 2017/4/20.
|
||||||
*/
|
*/
|
||||||
class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpandableFloaty() {
|
class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpandableFloaty() {
|
||||||
|
|
||||||
|
private lateinit var expandedBinding: FloatingConsoleExpandBinding
|
||||||
|
private lateinit var collapsedBinding: FloatingWindowCollapseBinding
|
||||||
|
|
||||||
private var mContextWrapper: ContextWrapper? = null
|
private var mContextWrapper: ContextWrapper? = null
|
||||||
private var mResizer: View? = null
|
private var mResizer: View? = null
|
||||||
private var mMoveCursor: View? = null
|
private var mMoveCursor: View? = null
|
||||||
@@ -58,7 +64,7 @@ class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpand
|
|||||||
|
|
||||||
override fun inflateCollapsedView(service: FloatyService, window: ResizableExpandableFloatyWindow): View {
|
override fun inflateCollapsedView(service: FloatyService, window: ResizableExpandableFloatyWindow): View {
|
||||||
ensureContextWrapper(service)
|
ensureContextWrapper(service)
|
||||||
return View.inflate(mContextWrapper, R.layout.floating_window_collapse, null)
|
return FloatingWindowCollapseBinding.inflate(LayoutInflater.from(mContextWrapper)).also { collapsedBinding = it }.root
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureContextWrapper(context: Context) {
|
private fun ensureContextWrapper(context: Context) {
|
||||||
@@ -67,9 +73,9 @@ class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpand
|
|||||||
|
|
||||||
override fun inflateExpandedView(service: FloatyService, window: ResizableExpandableFloatyWindow): View {
|
override fun inflateExpandedView(service: FloatyService, window: ResizableExpandableFloatyWindow): View {
|
||||||
ensureContextWrapper(service)
|
ensureContextWrapper(service)
|
||||||
return View.inflate(mContextWrapper, R.layout.floating_console_expand, null).also { view ->
|
return FloatingConsoleExpandBinding.inflate(LayoutInflater.from(mContextWrapper)).also { expandedBinding = it }.root.also { view ->
|
||||||
expandedView = view
|
expandedView = view
|
||||||
setUpConsole(view, window)
|
setUpConsole(window)
|
||||||
setInitialMeasure(service)
|
setInitialMeasure(service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,20 +100,20 @@ class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initConsoleTitleBar(view: View, window: ResizableExpandableFloatyWindow) {
|
private fun initConsoleTitleBar(window: ResizableExpandableFloatyWindow) {
|
||||||
mTitleView = view.findViewById<TextView?>(R.id.title)?.apply {
|
mTitleView = expandedBinding.title.apply {
|
||||||
text = mTitleText
|
text = mTitleText
|
||||||
}
|
}
|
||||||
titleBarView = view.findViewById<LinearLayout?>(R.id.title_bar).apply {
|
titleBarView = expandedBinding.titleBar.apply {
|
||||||
mTitleBackgroundColor?.let { setBackgroundColor(it) }
|
mTitleBackgroundColor?.let { setBackgroundColor(it) }
|
||||||
mTitleBackgroundAlpha?.let { background.alpha = it }
|
mTitleBackgroundAlpha?.let { background.alpha = it }
|
||||||
}
|
}
|
||||||
view.findViewById<ImageView>(R.id.close).let {
|
expandedBinding.close.let {
|
||||||
it.setOnClickListener { mConsole.hide() }
|
it.setOnClickListener { mConsole.hide() }
|
||||||
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
||||||
mCloseButton = it
|
mCloseButton = it
|
||||||
}
|
}
|
||||||
view.findViewById<ImageView>(R.id.move_or_resize).let {
|
expandedBinding.moveOrResize.let {
|
||||||
it.setOnClickListener {
|
it.setOnClickListener {
|
||||||
mMoveCursor?.run {
|
mMoveCursor?.run {
|
||||||
if (visibility == View.VISIBLE) {
|
if (visibility == View.VISIBLE) {
|
||||||
@@ -122,27 +128,27 @@ class ConsoleFloaty(private val mConsole: ConsoleImpl) : AbstractResizableExpand
|
|||||||
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
||||||
mControllingButton = it
|
mControllingButton = it
|
||||||
}
|
}
|
||||||
view.findViewById<ImageView>(R.id.minimize).let {
|
expandedBinding.minimize.let {
|
||||||
it.setOnClickListener { window.collapse() }
|
it.setOnClickListener { window.collapse() }
|
||||||
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
mtTitleIconsTint?.let { color -> it.imageTintList = ColorStateList.valueOf(color) }
|
||||||
mMinimizeButton = it
|
mMinimizeButton = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpConsole(view: View, window: ResizableExpandableFloatyWindow) {
|
private fun setUpConsole(window: ResizableExpandableFloatyWindow) {
|
||||||
view.findViewById<FloatingConsoleView>(R.id.console).apply {
|
expandedBinding.console.apply {
|
||||||
setConsole(mConsole)
|
setConsole(mConsole)
|
||||||
setWindow(window)
|
setWindow(window)
|
||||||
}
|
}
|
||||||
initConsoleTitleBar(view, window)
|
initConsoleTitleBar(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getResizerView(expandedView: View): View? {
|
override fun getResizerView(expandedView: View): View {
|
||||||
return expandedView.findViewById<View?>(R.id.resizer).also { mResizer = it }
|
return expandedBinding.resizer.also { mResizer = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMoveCursorView(expandedView: View): View? {
|
override fun getMoveCursorView(expandedView: View): View {
|
||||||
return expandedView.findViewById<View?>(R.id.move_cursor).also { mMoveCursor = it }
|
return expandedBinding.moveCursor.also { mMoveCursor = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTitle(title: CharSequence?) {
|
fun setTitle(title: CharSequence?) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
|
|||||||
|
|
||||||
private val mDefaultSafeDelay: Long = 360
|
private val mDefaultSafeDelay: Long = 360
|
||||||
|
|
||||||
private var mLogListener: WeakReference<LogListener?>? = null
|
private var mLogListeners = ArrayList<WeakReference<LogListener?>>()
|
||||||
private var mConsoleView: WeakReference<ConsoleView?>? = null
|
private var mConsoleView: WeakReference<ConsoleView?>? = null
|
||||||
|
|
||||||
@get:Synchronized
|
@get:Synchronized
|
||||||
@@ -67,7 +67,6 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
synchronized(mLockWindowCreated) {
|
synchronized(mLockWindowCreated) {
|
||||||
startFloatyService()
|
|
||||||
mConsoleFloaty = ConsoleFloaty(this)
|
mConsoleFloaty = ConsoleFloaty(this)
|
||||||
mFloatyWindow = ResizableExpandableFloatyWindow(mConsoleFloaty)
|
mFloatyWindow = ResizableExpandableFloatyWindow(mConsoleFloaty)
|
||||||
mLockWindowCreated.notify()
|
mLockWindowCreated.notify()
|
||||||
@@ -86,13 +85,13 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
|
|||||||
fun setConsoleView(consoleView: ConsoleView?) {
|
fun setConsoleView(consoleView: ConsoleView?) {
|
||||||
consoleView.let {
|
consoleView.let {
|
||||||
mConsoleView = WeakReference(it)
|
mConsoleView = WeakReference(it)
|
||||||
setLogListener(it)
|
addLogListener(it)
|
||||||
}
|
}
|
||||||
synchronized(mLockConsoleView) { mLockConsoleView.notify() }
|
synchronized(mLockConsoleView) { mLockConsoleView.notify() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setLogListener(logListener: LogListener?) {
|
private fun addLogListener(logListener: LogListener?) {
|
||||||
mLogListener = WeakReference(logListener)
|
mLogListeners.add(WeakReference(logListener))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printAllStackTrace(t: Throwable?) {
|
fun printAllStackTrace(t: Throwable?) {
|
||||||
@@ -104,7 +103,7 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
|
|||||||
override fun println(level: Int, charSequence: CharSequence): String? {
|
override fun println(level: Int, charSequence: CharSequence): String? {
|
||||||
val logEntry = LogEntry(mIdCounter.getAndIncrement(), level, charSequence)
|
val logEntry = LogEntry(mIdCounter.getAndIncrement(), level, charSequence)
|
||||||
synchronized(logEntries) { logEntries.add(logEntry) }
|
synchronized(logEntries) { logEntries.add(logEntry) }
|
||||||
mLogListener?.get()?.onNewLog(logEntry)
|
mLogListeners.forEach { it.get()?.onNewLog(logEntry) }
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +114,7 @@ open class ConsoleImpl(val uiHandler: UiHandler) : AbstractConsole() {
|
|||||||
@ScriptInterface
|
@ScriptInterface
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
synchronized(logEntries) { logEntries.clear() }
|
synchronized(logEntries) { logEntries.clear() }
|
||||||
mLogListener?.get()?.onLogClear()
|
mLogListeners.forEach { it.get()?.onLogClear() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() = show(false)
|
override fun show() = show(false)
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
|
|
||||||
private final float mMinTextSize = 8.0f;
|
private final float mMinTextSize = 8.0f;
|
||||||
private final float mMaxTextSize = 56.0f;
|
private final float mMaxTextSize = 56.0f;
|
||||||
|
private boolean mIsPinchToZoomEnabled;
|
||||||
|
|
||||||
public ConsoleView(Context context) {
|
public ConsoleView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -84,6 +85,9 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
mLogListRecyclerView.setAdapter(new Adapter());
|
mLogListRecyclerView.setAdapter(new Adapter());
|
||||||
|
|
||||||
mLogListRecyclerView.setOnTouchListener((v, event) -> {
|
mLogListRecyclerView.setOnTouchListener((v, event) -> {
|
||||||
|
if (!mIsPinchToZoomEnabled) {
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
mScaleGestureDetector.onTouchEvent(event);
|
mScaleGestureDetector.onTouchEvent(event);
|
||||||
return !mScaleGestureDetector.isInProgress() && super.onTouchEvent(event);
|
return !mScaleGestureDetector.isInProgress() && super.onTouchEvent(event);
|
||||||
});
|
});
|
||||||
@@ -147,6 +151,48 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVerboseTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setVerboseTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setDebugTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setInfoTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setInfoTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setWarnTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setWarnTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setErrorTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setErrorTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void setAssertTextColor(int color) {
|
||||||
|
Adapter adapter = (Adapter) mLogListRecyclerView.getAdapter();
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setAssertTextColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPinchToZoomEnabled(boolean enabled) {
|
||||||
|
mIsPinchToZoomEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
protected Map<Integer, Integer> getLogLevelMap() {
|
protected Map<Integer, Integer> getLogLevelMap() {
|
||||||
return new MapBuilder<Integer, Integer>()
|
return new MapBuilder<Integer, Integer>()
|
||||||
.put(Log.VERBOSE, R.color.console_view_verbose)
|
.put(Log.VERBOSE, R.color.console_view_verbose)
|
||||||
@@ -331,6 +377,36 @@ public class ConsoleView extends FrameLayout implements ConsoleImpl.LogListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVerboseTextColor(int color) {
|
||||||
|
mColors.replace(Log.VERBOSE, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugTextColor(int color) {
|
||||||
|
mColors.replace(Log.DEBUG, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfoTextColor(int color) {
|
||||||
|
mColors.replace(Log.INFO, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWarnTextColor(int color) {
|
||||||
|
mColors.replace(Log.WARN, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorTextColor(int color) {
|
||||||
|
mColors.replace(Log.ERROR, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssertTextColor(int color) {
|
||||||
|
mColors.replace(Log.ASSERT, color);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mLogEntries.size();
|
return mLogEntries.size();
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class FloatingConsoleView : ConsoleView {
|
|||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||||
|
|
||||||
|
init {
|
||||||
|
setPinchToZoomEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getLogLevelMap(): MutableMap<Int, Int> = MapBuilder<Int, Int>()
|
override fun getLogLevelMap(): MutableMap<Int, Int> = MapBuilder<Int, Int>()
|
||||||
.put(Log.VERBOSE,R.color.floating_console_view_verbose)
|
.put(Log.VERBOSE,R.color.floating_console_view_verbose)
|
||||||
.put(Log.DEBUG,R.color.floating_console_view_debug)
|
.put(Log.DEBUG,R.color.floating_console_view_debug)
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.autojs.autojs.core.console
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import org.autojs.autojs.AutoJs
|
||||||
|
|
||||||
|
class JsConsoleView : ConsoleView {
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||||
|
|
||||||
|
init {
|
||||||
|
setConsole(AutoJs.instance.globalConsole)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,20 +3,26 @@ package org.autojs.autojs.core.floaty
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.PixelFormat
|
import android.graphics.PixelFormat
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.FrameLayout
|
import android.view.WindowManager.LayoutParams
|
||||||
|
import android.widget.ImageView
|
||||||
|
import org.autojs.autojs.concurrent.VolatileDispose
|
||||||
|
import org.autojs.autojs.core.ui.inflater.Exceptions
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.FloatyService
|
import org.autojs.autojs.ui.enhancedfloaty.FloatyService
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
|
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloaty
|
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloaty
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloatyWindow
|
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloatyWindow
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge
|
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge.DefaultImpl
|
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge.DefaultImpl
|
||||||
|
import org.autojs.autojs.ui.enhancedfloaty.gesture.DragGesture
|
||||||
|
import org.autojs.autojs.ui.enhancedfloaty.gesture.ResizeGesture
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
|
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
|
||||||
import org.autojs.autojs.concurrent.VolatileDispose
|
|
||||||
import org.autojs.autojs.core.ui.inflater.inflaters.Exceptions
|
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
|
import org.autojs.autojs6.databinding.FloatyWindowBinding
|
||||||
|
import org.autojs.autojs6.databinding.RawWindowBinding
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,47 +36,45 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
|
|||||||
fun inflate(context: Context?, parent: ViewGroup?): View
|
fun inflate(context: Context?, parent: ViewGroup?): View
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var rawWindowBinding: RawWindowBinding
|
||||||
|
|
||||||
private val mInflateException = VolatileDispose<RuntimeException>()
|
private val mInflateException = VolatileDispose<RuntimeException>()
|
||||||
private var mCloseButton: View
|
|
||||||
private var mOffset = context.resources.getDimensionPixelSize(R.dimen.floaty_window_offset)
|
private var mOffset = context.resources.getDimensionPixelSize(R.dimen.floaty_window_offset)
|
||||||
private val mFloaty = MyFloaty(context, viewSupplier)
|
private val mFloaty = MyFloaty(context, viewSupplier)
|
||||||
val rootView = mFloaty.rootView
|
val rootView = mFloaty.rootView
|
||||||
private var mMoveCursor = mFloaty.getMoveCursorView(rootView)!!
|
private var mCloseButton = mFloaty.getCloseButtonView(rootView)
|
||||||
private var mResizer = mFloaty.getResizerView(rootView)!!
|
private var mMoveCursor = mFloaty.getMoveCursorView(rootView)
|
||||||
|
private var mResizer = mFloaty.getResizerView(rootView)
|
||||||
|
|
||||||
|
|
||||||
// @Reference to aiselp (https://github.com/aiselp) on Mar 27, 2023.
|
// @Reference to aiselp (https://github.com/aiselp) on Mar 27, 2023.
|
||||||
// ! https://github.com/kkevsekk1/AutoX/pull/529/commits/782f1c3c12dee64d9b1ad70aba462afaf60313a4#diff-b8e544bc658140f04a7fa7171cc938032f18c92495ca25bb08e2d2eb546b70f5
|
// ! https://github.com/kkevsekk1/AutoX/pull/529/commits/782f1c3c12dee64d9b1ad70aba462afaf60313a4#diff-b8e544bc658140f04a7fa7171cc938032f18c92495ca25bb08e2d2eb546b70f5
|
||||||
init {
|
init {
|
||||||
val layoutParams = createWindowLayoutParams()
|
val layoutParams = createWindowLayoutParams()
|
||||||
val windowView = View.inflate(context, R.layout.raw_window, null as ViewGroup?) as ViewGroup
|
|
||||||
|
rawWindowBinding = RawWindowBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
|
val windowView = rawWindowBinding.root
|
||||||
val params = ViewGroup.LayoutParams(-2, -2)
|
val params = ViewGroup.LayoutParams(-2, -2)
|
||||||
windowView.addView(rootView, params)
|
windowView.addView(rootView, params)
|
||||||
windowView.isFocusableInTouchMode = true
|
windowView.isFocusableInTouchMode = true
|
||||||
mCloseButton = windowView.findViewById(R.id.close)
|
|
||||||
super.setWindowLayoutParams(layoutParams)
|
super.setWindowLayoutParams(layoutParams)
|
||||||
super.setWindowView(windowView)
|
super.setWindowView(windowView)
|
||||||
super.setWindowManager(context.getSystemService(FloatyService.WINDOW_SERVICE) as WindowManager)
|
super.setWindowManager(context.getSystemService(FloatyService.WINDOW_SERVICE) as WindowManager)
|
||||||
super.setWindowBridge(super.onCreateWindowBridge(layoutParams))
|
super.setWindowBridge(super.onCreateWindowBridge(layoutParams))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
private fun createWindowLayoutParams() = LayoutParams(
|
||||||
private fun createWindowLayoutParams() = WindowManager
|
LayoutParams.WRAP_CONTENT,
|
||||||
.LayoutParams(
|
LayoutParams.WRAP_CONTENT,
|
||||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
WindowTypeCompat.getPhoneWindowType(),
|
||||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
LayoutParams.FLAG_LAYOUT_NO_LIMITS or LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||||
WindowTypeCompat.getWindowType(),
|
PixelFormat.TRANSLUCENT
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
).apply { gravity = Gravity.TOP or Gravity.START }
|
||||||
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
|
||||||
or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
|
||||||
or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
|
||||||
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
|
|
||||||
PixelFormat.TRANSLUCENT
|
|
||||||
).apply { gravity = Gravity.TOP or Gravity.START }
|
|
||||||
|
|
||||||
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
|
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
|
||||||
|
|
||||||
override fun onCreateWindowBridge(params: WindowManager.LayoutParams): WindowBridge {
|
override fun onCreateWindowBridge(params: LayoutParams): WindowBridge {
|
||||||
return object : DefaultImpl(params, windowManager, windowView) {
|
return object : DefaultImpl(params, windowManager, windowView) {
|
||||||
override fun getX() = super.getX() + mOffset
|
override fun getX() = super.getX() + mOffset
|
||||||
|
|
||||||
@@ -80,7 +84,7 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateWindowLayoutParams(): WindowManager.LayoutParams {
|
override fun onCreateWindowLayoutParams(): LayoutParams {
|
||||||
return super.getWindowLayoutParams()
|
return super.getWindowLayoutParams()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +98,24 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
|
|||||||
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION)
|
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View?) {
|
||||||
|
super.onViewCreated(view)
|
||||||
|
initGesture()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initGesture() {
|
||||||
|
enableResize()
|
||||||
|
enableMove()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enableResize() {
|
||||||
|
ResizeGesture.enableResize(mResizer, rootView, windowBridge)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enableMove() {
|
||||||
|
DragGesture(windowBridge, mMoveCursor).apply { pressedAlpha = 1.0f }
|
||||||
|
}
|
||||||
|
|
||||||
fun setOnCloseButtonClickListener(listener: View.OnClickListener?) {
|
fun setOnCloseButtonClickListener(listener: View.OnClickListener?) {
|
||||||
mCloseButton.setOnClickListener(listener)
|
mCloseButton.setOnClickListener(listener)
|
||||||
}
|
}
|
||||||
@@ -115,34 +137,37 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
|
|||||||
override fun onCreateView(floatyService: FloatyService?): View = super.getWindowView()
|
override fun onCreateView(floatyService: FloatyService?): View = super.getWindowView()
|
||||||
|
|
||||||
fun disableWindowFocus() {
|
fun disableWindowFocus() {
|
||||||
val windowLayoutParams = windowLayoutParams
|
windowLayoutParams.apply {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
flags = flags or LayoutParams.FLAG_NOT_FOCUSABLE
|
||||||
updateWindowLayoutParams(windowLayoutParams)
|
updateWindowLayoutParams(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestWindowFocus() {
|
fun requestWindowFocus() {
|
||||||
val windowLayoutParams = windowLayoutParams
|
windowLayoutParams.apply {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv()
|
flags = flags and LayoutParams.FLAG_NOT_FOCUSABLE.inv()
|
||||||
updateWindowLayoutParams(windowLayoutParams)
|
updateWindowLayoutParams(this)
|
||||||
|
}
|
||||||
windowView.requestLayout()
|
windowView.requestLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyFloaty(context: Context, contentViewSupplier: ViewSupplier) : ResizableFloaty {
|
private class MyFloaty(context: Context, contentViewSupplier: ViewSupplier) : ResizableFloaty {
|
||||||
val rootView: View = View.inflate(context, R.layout.floaty_window, null)
|
|
||||||
val container: FrameLayout = rootView.findViewById(R.id.container)
|
private val floatyWindowBinding = FloatyWindowBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
|
val rootView = floatyWindowBinding.root
|
||||||
|
|
||||||
init {
|
init {
|
||||||
contentViewSupplier.inflate(context, container)
|
contentViewSupplier.inflate(context, floatyWindowBinding.container)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun inflateView(floatyService: FloatyService, resizableFloatyWindow: ResizableFloatyWindow) = rootView
|
override fun inflateView(floatyService: FloatyService, resizableFloatyWindow: ResizableFloatyWindow) = rootView
|
||||||
|
|
||||||
override fun getResizerView(view: View): View? {
|
override fun getResizerView(view: View): ImageView = floatyWindowBinding.resizer
|
||||||
return view.findViewById(R.id.resizer)
|
|
||||||
}
|
override fun getMoveCursorView(view: View): ImageView = floatyWindowBinding.moveCursor
|
||||||
|
|
||||||
|
override fun getCloseButtonView(view: View): ImageView = floatyWindowBinding.close
|
||||||
|
|
||||||
override fun getMoveCursorView(view: View): View? {
|
|
||||||
return view.findViewById(R.id.move_cursor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ import org.autojs.autojs.ui.enhancedfloaty.FloatyService
|
|||||||
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
|
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
|
||||||
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
|
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
|
||||||
import org.autojs.autojs.concurrent.VolatileDispose
|
import org.autojs.autojs.concurrent.VolatileDispose
|
||||||
import org.autojs.autojs.core.ui.inflater.inflaters.Exceptions
|
import org.autojs.autojs.core.ui.inflater.Exceptions
|
||||||
import org.autojs.autojs6.R
|
import org.autojs.autojs6.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,39 +57,37 @@ class RawWindow(rawFloaty: RawFloaty, context: Context) : FloatyWindow() {
|
|||||||
|
|
||||||
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
|
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
private fun createWindowLayoutParams() = LayoutParams(
|
private fun createWindowLayoutParams() = LayoutParams(
|
||||||
LayoutParams.WRAP_CONTENT,
|
LayoutParams.WRAP_CONTENT,
|
||||||
LayoutParams.WRAP_CONTENT,
|
LayoutParams.WRAP_CONTENT,
|
||||||
WindowTypeCompat.getWindowType(),
|
WindowTypeCompat.getWindowType(),
|
||||||
LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
LayoutParams.FLAG_LAYOUT_NO_LIMITS or LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||||
or LayoutParams.FLAG_NOT_TOUCH_MODAL
|
|
||||||
or LayoutParams.FLAG_FULLSCREEN
|
|
||||||
or LayoutParams.FLAG_NOT_FOCUSABLE
|
|
||||||
or LayoutParams.FLAG_TRANSLUCENT_STATUS,
|
|
||||||
PixelFormat.TRANSLUCENT
|
PixelFormat.TRANSLUCENT
|
||||||
).apply { gravity = Gravity.TOP or Gravity.START }
|
).apply { gravity = Gravity.TOP or Gravity.START }
|
||||||
|
|
||||||
fun disableWindowFocus() {
|
fun disableWindowFocus() {
|
||||||
val windowLayoutParams = windowLayoutParams
|
windowLayoutParams.apply {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags or LayoutParams.FLAG_NOT_FOCUSABLE
|
flags = flags or LayoutParams.FLAG_NOT_FOCUSABLE
|
||||||
updateWindowLayoutParams(windowLayoutParams)
|
updateWindowLayoutParams(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestWindowFocus() {
|
fun requestWindowFocus() {
|
||||||
val windowLayoutParams = windowLayoutParams
|
windowLayoutParams.apply {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags and LayoutParams.FLAG_NOT_FOCUSABLE.inv()
|
flags = flags and LayoutParams.FLAG_NOT_FOCUSABLE.inv()
|
||||||
updateWindowLayoutParams(windowLayoutParams)
|
updateWindowLayoutParams(this)
|
||||||
|
}
|
||||||
windowView.requestLayout()
|
windowView.requestLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTouchable(touchable: Boolean) {
|
fun setTouchable(touchable: Boolean) {
|
||||||
val windowLayoutParams = windowLayoutParams
|
windowLayoutParams.apply {
|
||||||
if (touchable) {
|
flags = if (touchable) {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags and LayoutParams.FLAG_NOT_TOUCHABLE.inv()
|
flags and LayoutParams.FLAG_NOT_TOUCHABLE.inv()
|
||||||
} else {
|
} else {
|
||||||
windowLayoutParams.flags = windowLayoutParams.flags or LayoutParams.FLAG_NOT_TOUCHABLE
|
flags or LayoutParams.FLAG_NOT_TOUCHABLE
|
||||||
|
}
|
||||||
|
updateWindowLayoutParams(this)
|
||||||
}
|
}
|
||||||
updateWindowLayoutParams(windowLayoutParams)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+15
-10
@@ -5,11 +5,12 @@ import android.content.Context
|
|||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.SurfaceTexture
|
import android.graphics.SurfaceTexture
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.TextureView
|
import android.view.TextureView
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import org.autojs.autojs.AutoJs
|
||||||
import org.autojs.autojs.core.eventloop.EventEmitter
|
import org.autojs.autojs.core.eventloop.EventEmitter
|
||||||
import org.autojs.autojs.runtime.ScriptRuntime
|
|
||||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
|
||||||
import org.autojs.autojs.util.KotlinUtils.ifNull
|
import org.autojs.autojs.util.KotlinUtils.ifNull
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
@@ -19,27 +20,31 @@ import java.util.concurrent.Executors
|
|||||||
* Created by Stardust on 2018/3/16.
|
* Created by Stardust on 2018/3/16.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
class ScriptCanvasView(context: Context, private val mScriptRuntime: ScriptRuntime) : TextureView(context), TextureView.SurfaceTextureListener {
|
class JsCanvasView : TextureView, TextureView.SurfaceTextureListener {
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var mDrawing = true
|
private var mDrawing = true
|
||||||
private val mEventEmitter: EventEmitter = EventEmitter(mScriptRuntime.bridges)
|
private val mRuntime by lazy { AutoJs.instance.runtime }
|
||||||
|
private val mEventEmitter: EventEmitter by lazy { EventEmitter(mRuntime.bridges) }
|
||||||
private var mDrawingThreadPool: ExecutorService? = null
|
private var mDrawingThreadPool: ExecutorService? = null
|
||||||
@Volatile
|
@Volatile
|
||||||
private var mTimePerDraw = (1000 / 30).toLong()
|
private var mTimePerDraw = (1000 / 30).toLong()
|
||||||
|
|
||||||
|
|
||||||
val maxListeners: Int
|
val maxListeners: Int
|
||||||
get() = mEventEmitter.maxListeners
|
get() = mEventEmitter.maxListeners
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
surfaceTextureListener = this
|
surfaceTextureListener = this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setMaxFps(maxFps: Int) {
|
fun setMaxFps(maxFps: Int) {
|
||||||
mTimePerDraw = if (maxFps <= 0) {
|
mTimePerDraw = (if (maxFps <= 0) 0L else 100L / maxFps)
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(100 / maxFps).toLong()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@@ -55,7 +60,7 @@ class ScriptCanvasView(context: Context, private val mScriptRuntime: ScriptRunti
|
|||||||
while (mDrawing) {
|
while (mDrawing) {
|
||||||
canvas = lockCanvas()
|
canvas = lockCanvas()
|
||||||
scriptCanvas.setCanvas(canvas)
|
scriptCanvas.setCanvas(canvas)
|
||||||
emit("draw", scriptCanvas, this@ScriptCanvasView)
|
emit("draw", scriptCanvas, this@JsCanvasView)
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
unlockCanvasAndPost(canvas)
|
unlockCanvasAndPost(canvas)
|
||||||
canvas = null
|
canvas = null
|
||||||
@@ -67,7 +72,7 @@ class ScriptCanvasView(context: Context, private val mScriptRuntime: ScriptRunti
|
|||||||
time = SystemClock.uptimeMillis()
|
time = SystemClock.uptimeMillis()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
mScriptRuntime.exit(e)
|
mRuntime.exit(e)
|
||||||
mDrawing = false
|
mDrawing = false
|
||||||
} finally {
|
} finally {
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
@@ -147,7 +147,7 @@ interface ColorDetector {
|
|||||||
"hs" -> HSDistanceDetector(color, threshold)
|
"hs" -> HSDistanceDetector(color, threshold)
|
||||||
"h" -> HDistanceDetector(color, threshold)
|
"h" -> HDistanceDetector(color, threshold)
|
||||||
"equal" -> EqualityDetector(color)
|
"equal" -> EqualityDetector(color)
|
||||||
else -> throw Error("Failed to get a color detector")
|
else -> throw Exception("Failed to get a color detector")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,243 +0,0 @@
|
|||||||
package org.autojs.autojs.core.image;
|
|
||||||
|
|
||||||
import static org.autojs.autojs.util.StringUtils.str;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.media.Image;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.autojs.autojs.AutoJs;
|
|
||||||
import org.autojs.autojs.core.opencv.Mat;
|
|
||||||
import org.autojs.autojs.core.opencv.OpenCVHelper;
|
|
||||||
import org.autojs.autojs.pio.UncheckedIOException;
|
|
||||||
import org.autojs.autojs.runtime.ScriptRuntime;
|
|
||||||
import org.autojs.autojs6.R;
|
|
||||||
import org.opencv.android.Utils;
|
|
||||||
import org.opencv.core.Size;
|
|
||||||
import org.opencv.imgcodecs.Imgcodecs;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Stardust on 2017/11/25.
|
|
||||||
*/
|
|
||||||
public class ImageWrapper implements Recyclable {
|
|
||||||
|
|
||||||
private Mat mMat;
|
|
||||||
private Bitmap mBitmap;
|
|
||||||
|
|
||||||
private final int mWidth;
|
|
||||||
private final int mHeight;
|
|
||||||
|
|
||||||
private final ScriptRuntime mScriptRuntime = AutoJs.getInstance().getRuntime();
|
|
||||||
|
|
||||||
private boolean isRecycled;
|
|
||||||
|
|
||||||
private final static ArrayList<WeakReference<Object>> imageList = new ArrayList<>();
|
|
||||||
private boolean mOneShot;
|
|
||||||
|
|
||||||
private void addToList(Object image) {
|
|
||||||
imageList.add(new WeakReference<>(image));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized void recycleAll() {
|
|
||||||
for (WeakReference<Object> reference : imageList) {
|
|
||||||
Object image = reference.get();
|
|
||||||
if (image instanceof Recyclable) {
|
|
||||||
((Recyclable) image).recycle();
|
|
||||||
} else if (image instanceof Bitmap) {
|
|
||||||
((Bitmap) image).recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ImageWrapper(Mat mat) {
|
|
||||||
this(null, mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ImageWrapper(Bitmap bitmap) {
|
|
||||||
this(bitmap, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ImageWrapper(int width, int height) {
|
|
||||||
this(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ImageWrapper(Bitmap bitmap, Mat mat) {
|
|
||||||
if (mat != null) {
|
|
||||||
mMat = mat;
|
|
||||||
}
|
|
||||||
if (bitmap != null) {
|
|
||||||
mBitmap = bitmap;
|
|
||||||
mWidth = bitmap.getWidth();
|
|
||||||
mHeight = bitmap.getHeight();
|
|
||||||
} else {
|
|
||||||
if (mat == null) {
|
|
||||||
throw new Error(str(R.string.error_both_bitmap_and_mat_are_null));
|
|
||||||
}
|
|
||||||
mWidth = mat.cols();
|
|
||||||
mHeight = mat.rows();
|
|
||||||
}
|
|
||||||
addToList(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImageWrapper ofImage(Image image) {
|
|
||||||
if (image == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ImageWrapper(toBitmap(image));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImageWrapper ofMat(Mat mat) {
|
|
||||||
if (mat == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ImageWrapper(mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImageWrapper ofBitmap(Bitmap bitmap) {
|
|
||||||
if (bitmap == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ImageWrapper(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap toBitmap(Image image) {
|
|
||||||
Image.Plane plane = image.getPlanes()[0];
|
|
||||||
ByteBuffer buffer = plane.getBuffer();
|
|
||||||
buffer.position(0);
|
|
||||||
int pixelStride = plane.getPixelStride();
|
|
||||||
int rowPadding = plane.getRowStride() - pixelStride * image.getWidth();
|
|
||||||
Bitmap bitmap = Bitmap.createBitmap(image.getWidth() + rowPadding / pixelStride, image.getHeight(), Bitmap.Config.ARGB_8888);
|
|
||||||
bitmap.copyPixelsFromBuffer(buffer);
|
|
||||||
if (rowPadding == 0) {
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return Bitmap.createBitmap(bitmap, 0, 0, image.getWidth(), image.getHeight());
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
// Wrapped java.lang.IllegalStateException: Image is already closed
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWidth() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
return mWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
return mHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size getSize() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
return new Size(mWidth, mHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mat getMat() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
if (mMat == null && mBitmap != null) {
|
|
||||||
mMat = new Mat();
|
|
||||||
Utils.bitmapToMat(mBitmap, mMat);
|
|
||||||
}
|
|
||||||
return mMat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveTo(String path) {
|
|
||||||
ensureNotRecycled();
|
|
||||||
path = mScriptRuntime.files.path(path);
|
|
||||||
if (mBitmap != null) {
|
|
||||||
try {
|
|
||||||
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(path));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new UncheckedIOException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Imgcodecs.imwrite(path, mMat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int pixel(int x, int y) {
|
|
||||||
ensureNotRecycled();
|
|
||||||
int result;
|
|
||||||
if (mBitmap != null) {
|
|
||||||
result = mBitmap.getPixel(x, y);
|
|
||||||
} else {
|
|
||||||
double[] channels = mMat.get(x, y);
|
|
||||||
result = Color.argb((int) channels[3], (int) channels[0], (int) channels[1], (int) channels[2]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitmap getBitmap() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
if (mBitmap == null && mMat != null) {
|
|
||||||
mBitmap = Bitmap.createBitmap(mMat.width(), mMat.height(), Bitmap.Config.ARGB_8888);
|
|
||||||
Utils.matToBitmap(mMat, mBitmap);
|
|
||||||
}
|
|
||||||
return mBitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recycle() {
|
|
||||||
if (mBitmap != null) {
|
|
||||||
mBitmap.recycle();
|
|
||||||
mBitmap = null;
|
|
||||||
}
|
|
||||||
if (mMat != null) {
|
|
||||||
OpenCVHelper.release(mMat);
|
|
||||||
mMat = null;
|
|
||||||
}
|
|
||||||
isRecycled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ImageWrapper setOneShot(boolean b) {
|
|
||||||
mOneShot = b;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shoot() {
|
|
||||||
if (mOneShot) {
|
|
||||||
recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRecycled() {
|
|
||||||
return isRecycled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ensureNotRecycled() {
|
|
||||||
if (isRecycled()) {
|
|
||||||
throw new IllegalStateException(str(R.string.error_image_has_been_recycled));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
|
||||||
@NonNull
|
|
||||||
public ImageWrapper clone() {
|
|
||||||
ensureNotRecycled();
|
|
||||||
ImageWrapper imageWrapper;
|
|
||||||
if (mBitmap == null) {
|
|
||||||
imageWrapper = ImageWrapper.ofMat(mMat.clone());
|
|
||||||
} else if (mMat == null) {
|
|
||||||
imageWrapper = ImageWrapper.ofBitmap(mBitmap.copy(mBitmap.getConfig(), true));
|
|
||||||
} else {
|
|
||||||
imageWrapper = new ImageWrapper(mBitmap.copy(mBitmap.getConfig(), true), mMat.clone());
|
|
||||||
}
|
|
||||||
return imageWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package org.autojs.autojs.core.image
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.media.Image
|
||||||
|
import org.autojs.autojs.AutoJs.Companion.instance
|
||||||
|
import org.autojs.autojs.annotation.ScriptInterface
|
||||||
|
import org.autojs.autojs.core.opencv.Mat
|
||||||
|
import org.autojs.autojs.core.opencv.OpenCVHelper
|
||||||
|
import org.autojs.autojs.pio.UncheckedIOException
|
||||||
|
import org.autojs.autojs.util.StringUtils.str
|
||||||
|
import org.autojs.autojs6.R
|
||||||
|
import org.opencv.android.Utils
|
||||||
|
import org.opencv.core.Size
|
||||||
|
import org.opencv.imgcodecs.Imgcodecs
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/11/25.
|
||||||
|
* Modified by SuperMonster003 as of May 16, 2023.
|
||||||
|
* Transformed by SuperMonster003 on May 16, 2023.
|
||||||
|
*/
|
||||||
|
class ImageWrapper constructor(bitmap: Bitmap?, mat: Mat?) : Recyclable {
|
||||||
|
|
||||||
|
// @Hint by SuperMonster003
|
||||||
|
// ! It is ensured that bitmap and mat will not be null at the same time.
|
||||||
|
|
||||||
|
private var mMat: Mat? = null
|
||||||
|
private var mBitmap: Bitmap? = null
|
||||||
|
|
||||||
|
private var mWidth = 0
|
||||||
|
private var mHeight = 0
|
||||||
|
private val mScriptRuntime = instance.runtime
|
||||||
|
private var mIsRecycled = false
|
||||||
|
private var mIsOneShot = false
|
||||||
|
|
||||||
|
constructor(mat: Mat) : this(null, mat)
|
||||||
|
|
||||||
|
constructor(bitmap: Bitmap) : this(bitmap, null)
|
||||||
|
|
||||||
|
constructor(width: Int, height: Int) : this(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888))
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (mat != null) {
|
||||||
|
mMat = mat
|
||||||
|
}
|
||||||
|
if (bitmap != null) {
|
||||||
|
mBitmap = bitmap
|
||||||
|
mWidth = bitmap.width
|
||||||
|
mHeight = bitmap.height
|
||||||
|
} else {
|
||||||
|
if (mat != null) {
|
||||||
|
mWidth = mat.cols()
|
||||||
|
mHeight = mat.rows()
|
||||||
|
} else {
|
||||||
|
throw Exception(str(R.string.error_both_bitmap_and_mat_are_null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addToList(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
val width
|
||||||
|
get() = mWidth.also { ensureNotRecycled() }
|
||||||
|
|
||||||
|
val height
|
||||||
|
get() = mHeight.also { ensureNotRecycled() }
|
||||||
|
|
||||||
|
val size
|
||||||
|
get() = Size(mWidth.toDouble(), mHeight.toDouble()).also { ensureNotRecycled() }
|
||||||
|
|
||||||
|
val bitmap: Bitmap
|
||||||
|
get() {
|
||||||
|
ensureNotRecycled()
|
||||||
|
if (mBitmap == null && mMat != null) {
|
||||||
|
mBitmap = Bitmap.createBitmap(mMat!!.width(), mMat!!.height(), Bitmap.Config.ARGB_8888)
|
||||||
|
Utils.matToBitmap(mMat, mBitmap)
|
||||||
|
}
|
||||||
|
return mBitmap!!
|
||||||
|
}
|
||||||
|
|
||||||
|
val mat: Mat
|
||||||
|
get() {
|
||||||
|
ensureNotRecycled()
|
||||||
|
if (mMat == null && mBitmap != null) {
|
||||||
|
mMat = Mat()
|
||||||
|
Utils.bitmapToMat(mBitmap, mMat)
|
||||||
|
}
|
||||||
|
return mMat!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addToList(image: Any) {
|
||||||
|
imageList.add(WeakReference(image))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveTo(path: String?) {
|
||||||
|
ensureNotRecycled()
|
||||||
|
val nicePath = mScriptRuntime.files.path(path)
|
||||||
|
if (mBitmap != null) {
|
||||||
|
try {
|
||||||
|
mBitmap!!.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(nicePath))
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
throw UncheckedIOException(e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Imgcodecs.imwrite(nicePath, mMat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pixel(x: Int, y: Int): Int {
|
||||||
|
ensureNotRecycled()
|
||||||
|
val result = if (mBitmap != null) {
|
||||||
|
mBitmap!!.getPixel(x, y)
|
||||||
|
} else {
|
||||||
|
val channels = mat[x, y]
|
||||||
|
Color.argb(channels[3].toInt(), channels[0].toInt(), channels[1].toInt(), channels[2].toInt())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recycle() {
|
||||||
|
mBitmap?.run { recycle().also { mBitmap = null } }
|
||||||
|
mMat?.run { OpenCVHelper.release(mMat).also { mMat = null } }
|
||||||
|
mIsRecycled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setOneShot(b: Boolean) = also { mIsOneShot = b }
|
||||||
|
|
||||||
|
override fun shoot() {
|
||||||
|
if (mIsOneShot) recycle()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isRecycled() = mIsRecycled
|
||||||
|
|
||||||
|
@ScriptInterface
|
||||||
|
fun ensureNotRecycled() {
|
||||||
|
check(!isRecycled) { str(R.string.error_image_has_been_recycled) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clone(): ImageWrapper {
|
||||||
|
ensureNotRecycled()
|
||||||
|
return if (mBitmap == null) {
|
||||||
|
ofMat(mMat!!.clone())!!
|
||||||
|
} else if (mMat == null) {
|
||||||
|
ofBitmap(mBitmap!!.copy(mBitmap!!.config, true))!!
|
||||||
|
} else {
|
||||||
|
ImageWrapper(mBitmap!!.copy(mBitmap!!.config, true), mMat!!.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val imageList = ArrayList<WeakReference<Any>>()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@Synchronized
|
||||||
|
fun recycleAll() {
|
||||||
|
imageList.forEach {
|
||||||
|
when (val i = it.get()) {
|
||||||
|
is Recyclable -> i.recycle()
|
||||||
|
is Bitmap -> i.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageList.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun ofImage(image: Image?) = image?.let { ImageWrapper(toBitmap(it)) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun ofMat(mat: Mat?) = mat?.let { ImageWrapper(it) }
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun ofBitmap(bitmap: Bitmap?) = bitmap?.let { ImageWrapper(it) }
|
||||||
|
|
||||||
|
@ScriptInterface
|
||||||
|
fun toBitmap(image: Image): Bitmap {
|
||||||
|
val plane = image.planes[0]
|
||||||
|
val buffer = plane.buffer.apply { position(0) }
|
||||||
|
val pixelStride = plane.pixelStride
|
||||||
|
val rowPadding = plane.rowStride - pixelStride * image.width
|
||||||
|
val bitmap = Bitmap.createBitmap(
|
||||||
|
image.width + rowPadding / pixelStride,
|
||||||
|
image.height,
|
||||||
|
Bitmap.Config.ARGB_8888,
|
||||||
|
).apply { copyPixelsFromBuffer(buffer) }
|
||||||
|
return when (rowPadding == 0) {
|
||||||
|
true -> bitmap
|
||||||
|
else -> Bitmap.createBitmap(bitmap, 0, 0, image.width, image.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,25 +1,37 @@
|
|||||||
package org.autojs.autojs.core.inputevent;
|
package org.autojs.autojs.core.inputevent;
|
||||||
|
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_POSITION_X;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_POSITION_Y;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_SLOT;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_TOUCH_MAJOR;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_TRACKING_ID;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.ABS_MT_WIDTH_MAJOR;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.BTN_TOUCH;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.DOWN;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.EV_ABS;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.EV_KEY;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.EV_SYN;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.SYN_MT_REPORT;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.SYN_REPORT;
|
||||||
|
import static org.autojs.autojs.core.inputevent.InputEventCodes.UP;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
import org.autojs.autojs.runtime.api.Shell;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.autojs.autojs.engine.RootAutomatorEngine;
|
import org.autojs.autojs.engine.RootAutomatorEngine;
|
||||||
import org.autojs.autojs.runtime.exception.ScriptInterruptedException;
|
|
||||||
import org.autojs.autojs.runtime.api.ScreenMetrics;
|
import org.autojs.autojs.runtime.api.ScreenMetrics;
|
||||||
|
import org.autojs.autojs.runtime.api.Shell;
|
||||||
|
import org.autojs.autojs.runtime.exception.ScriptInterruptedException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import static org.autojs.autojs.core.inputevent.InputEventCodes.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/7/16.
|
* Created by Stardust on 2017/7/16.
|
||||||
* Modified by SuperMonster003 as of May 12, 2022.
|
* Modified by SuperMonster003 as of May 12, 2022.
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public class ViewExtras {
|
|||||||
return extras;
|
return extras;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static ViewAttributes getViewAttributes(View view, ResourceParser parser) {
|
public static ViewAttributes getViewAttributes(View view, ResourceParser parser) {
|
||||||
ViewExtras extras = get(view);
|
ViewExtras extras = get(view);
|
||||||
ViewAttributes attributes = extras.getViewAttributes();
|
ViewAttributes attributes = extras.getViewAttributes();
|
||||||
@@ -42,7 +41,6 @@ public class ViewExtras {
|
|||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static NativeView getNativeView(Scriptable scope, View view, Class<?> staticType, ScriptRuntime runtime) {
|
public static NativeView getNativeView(Scriptable scope, View view, Class<?> staticType, ScriptRuntime runtime) {
|
||||||
ViewExtras extras = get(view);
|
ViewExtras extras = get(view);
|
||||||
NativeView nativeView = extras.getNativeView();
|
NativeView nativeView = extras.getNativeView();
|
||||||
@@ -73,4 +71,5 @@ public class ViewExtras {
|
|||||||
public final void setViewAttributes(ViewAttributes viewAttributes) {
|
public final void setViewAttributes(ViewAttributes viewAttributes) {
|
||||||
mViewAttributes = viewAttributes;
|
mViewAttributes = viewAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AbsSeekBar
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import org.autojs.autojs.util.ColorUtils
|
||||||
|
|
||||||
|
open class AbsSeekBarAttributes<V : AbsSeekBar>(resourceParser: ResourceParser, view: View) : ProgressBarAttributes<V>(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AbsSeekBar
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttr("keyProgressIncrement") { view.keyProgressIncrement = it.toInt() }
|
||||||
|
registerAttr("splitTrack") { view.splitTrack = it.toBoolean() }
|
||||||
|
registerAttr("thumb") { view.thumb = drawables.parse(view, it) }
|
||||||
|
registerAttr("thumbOffset") { view.thumbOffset = it.toInt() }
|
||||||
|
registerAttr("thumbTintList") { view.thumbTintList = ColorUtils.toColorStateList(view, it) }
|
||||||
|
registerAttr("thumbTintList") { view.thumbTintList = ColorUtils.toColorStateList(view, it) }
|
||||||
|
registerAttr("tickMark") { view.tickMark = drawables.parse(view, it) }
|
||||||
|
registerAttr("tickMarkTintList") { view.tickMarkTintList = ColorUtils.toColorStateList(view, it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AbsSpinner
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class AbsSpinnerAttributes(resourceParser: ResourceParser, view: View) : AdapterViewAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AbsSpinner
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class AdapterViewAttributes(resourceParser: ResourceParser, view: View) : ViewGroupAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AdapterView<*>
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttr("selection") { view.setSelection(it.toInt()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import org.autojs.autojs.core.ui.inflater.util.Dimensions
|
||||||
|
import org.autojs.autojs.util.ColorUtils
|
||||||
|
|
||||||
|
open class AppBarLayoutAttributes(resourceParser: ResourceParser, view: View) : LinearLayoutAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AppBarLayout
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttr("expanded") { view.setExpanded(it.toBoolean()) }
|
||||||
|
registerAttrs(arrayOf("isLifted", "lifted")) { view.isLifted = it.toBoolean() }
|
||||||
|
registerAttrs(arrayOf("statusBarForegroundColor", "statusBarFgColor")) { view.setStatusBarForegroundColor(ColorUtils.parse(view, it)) }
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
registerAttr("elevation") { view.targetElevation = Dimensions.parseToPixel(it, view) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.widget.AppCompatCheckBox
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class AppCompatCheckBoxAttributes(resourceParser: ResourceParser, view: View) : CheckBoxAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AppCompatCheckBox
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.widget.AppCompatSpinner
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class AppCompatSpinnerAttributes(resourceParser: ResourceParser, view: View) : SpinnerAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AppCompatSpinner
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class AppCompatTextViewAttributes(resourceParser: ResourceParser, view: View): TextViewAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AppCompatTextView
|
||||||
|
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import androidx.appcompatlegacy.widget.AppCompatTextView
|
||||||
|
|
||||||
|
open class AppCompatTextViewLegacyAttributes(resourceParser: ResourceParser, view: View) : TextViewAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as AppCompatTextView
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package org.autojs.autojs.core.ui.attribute;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.google.android.material.appbar.AppBarLayout;
|
|
||||||
import org.autojs.autojs.core.ui.inflater.ResourceParser;
|
|
||||||
|
|
||||||
public class AppbarAttributes extends ViewAttributes {
|
|
||||||
public AppbarAttributes(ResourceParser resourceParser, View view) {
|
|
||||||
super(resourceParser, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onRegisterAttrs() {
|
|
||||||
super.onRegisterAttrs();
|
|
||||||
registerPixelAttr("elevation", getView()::setTargetElevation);
|
|
||||||
registerBooleanAttr("expanded", getView()::setExpanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AppBarLayout getView() {
|
|
||||||
return (AppBarLayout) super.getView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class ButtonAttributes(resourceParser: ResourceParser, view: View) : TextViewAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as Button
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package org.autojs.autojs.core.ui.attribute;
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import org.autojs.autojs.core.ui.inflater.ResourceParser;
|
|
||||||
|
|
||||||
import androidx.cardview.widget.CardView;
|
|
||||||
|
|
||||||
import org.autojs.autojs.core.ui.inflater.util.Dimensions;
|
|
||||||
|
|
||||||
public class CardAttributes extends ViewAttributes {
|
|
||||||
|
|
||||||
public CardAttributes(ResourceParser resourceParser, View view) {
|
|
||||||
super(resourceParser, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onRegisterAttrs() {
|
|
||||||
super.onRegisterAttrs();
|
|
||||||
registerAttr("cardBackgroundColor", Color::parseColor, getView()::setCardBackgroundColor);
|
|
||||||
registerPixelAttr("cardCornerRadius", getView()::setRadius);
|
|
||||||
registerPixelAttr("cardElevation", getView()::setCardElevation);
|
|
||||||
registerPixelAttr("cardMaxElevation", getView()::setMaxCardElevation);
|
|
||||||
registerBooleanAttr("cardPreventCornerOverlap", getView()::setPreventCornerOverlap);
|
|
||||||
registerBooleanAttr("cardUseCompatPadding", getView()::setUseCompatPadding);
|
|
||||||
registerAttr("contentPadding", this::setContentPadding);
|
|
||||||
registerIntPixelAttr("contentPaddingBottom", this::setContentPaddingBottom);
|
|
||||||
registerIntPixelAttr("contentPaddingLeft", this::setContentPaddingLeft);
|
|
||||||
registerIntPixelAttr("contentPaddingTop", this::setContentPaddingTop);
|
|
||||||
registerIntPixelAttr("contentPaddingRight", this::setContentPaddingRight);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setContentPadding(String value) {
|
|
||||||
int[] pixels = Dimensions.parseToIntPixelArray(getView(), value);
|
|
||||||
getView().setContentPadding(pixels[0], pixels[1], pixels[2], pixels[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setContentPaddingBottom(int value) {
|
|
||||||
CardView cardView = getView();
|
|
||||||
cardView.setContentPadding(cardView.getContentPaddingLeft(), cardView.getContentPaddingTop(),
|
|
||||||
cardView.getContentPaddingRight(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setContentPaddingLeft(int value) {
|
|
||||||
CardView cardView = getView();
|
|
||||||
cardView.setContentPadding(value, cardView.getContentPaddingTop(),
|
|
||||||
cardView.getContentPaddingRight(), cardView.getContentPaddingBottom());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setContentPaddingTop(int value) {
|
|
||||||
CardView cardView = getView();
|
|
||||||
cardView.setContentPadding(cardView.getContentPaddingLeft(), value,
|
|
||||||
cardView.getContentPaddingRight(), cardView.getContentPaddingBottom());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setContentPaddingRight(int value) {
|
|
||||||
CardView cardView = getView();
|
|
||||||
cardView.setContentPadding(cardView.getContentPaddingLeft(), cardView.getContentPaddingTop(),
|
|
||||||
value, cardView.getContentPaddingBottom());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CardView getView() {
|
|
||||||
return (CardView) super.getView();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import org.autojs.autojs.core.ui.inflater.util.Dimensions
|
||||||
|
import org.autojs.autojs.util.ColorUtils
|
||||||
|
|
||||||
|
open class CardViewAttributes(resourceParser: ResourceParser, view: View) : FrameLayoutAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as CardView
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttrs(arrayOf("cardBackgroundColor", "cardBgColor", "cardBg")) { view.setCardBackgroundColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("radius", "cardCornerRadius", "cornerRadius")) { view.radius = parseDimensionToPixel(it) }
|
||||||
|
registerPixelAttr("cardElevation") { view.cardElevation = it }
|
||||||
|
registerAttrs(arrayOf("maxCardElevation", "cardMaxElevation")) { view.maxCardElevation = parseDimensionToPixel(it) }
|
||||||
|
registerAttrs(arrayOf("preventCornerOverlap", "cardPreventCornerOverlap")) { view.preventCornerOverlap = it.toBoolean() }
|
||||||
|
registerAttrs(arrayOf("useCompatPadding", "cardUseCompatPadding")) { view.useCompatPadding = it.toBoolean() }
|
||||||
|
registerAttr("contentPadding") { setContentPadding(it) }
|
||||||
|
registerIntPixelAttr("contentPaddingBottom") { setContentPaddingBottom(it) }
|
||||||
|
registerIntPixelAttr("contentPaddingLeft") { setContentPaddingLeft(it) }
|
||||||
|
registerIntPixelAttr("contentPaddingTop") { setContentPaddingTop(it) }
|
||||||
|
registerIntPixelAttr("contentPaddingRight") { setContentPaddingRight(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContentPadding(value: String) {
|
||||||
|
Dimensions.parseToIntPixelArray(view, value).let { (left, top, right, bottom) ->
|
||||||
|
view.setContentPadding(left, top, right, bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContentPaddingBottom(value: Int) {
|
||||||
|
view.apply { setContentPadding(contentPaddingLeft, contentPaddingTop, contentPaddingRight, value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContentPaddingLeft(value: Int) {
|
||||||
|
view.apply { setContentPadding(value, contentPaddingTop, contentPaddingRight, contentPaddingBottom) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContentPaddingTop(value: Int) {
|
||||||
|
view.apply { setContentPadding(contentPaddingLeft, value, contentPaddingRight, contentPaddingBottom) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setContentPaddingRight(value: Int) {
|
||||||
|
view.apply { setContentPadding(contentPaddingLeft, contentPaddingTop, value, contentPaddingBottom) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.CheckBox
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
|
||||||
|
open class CheckBoxAttributes(resourceParser: ResourceParser, view: View) : CompoundButtonAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as CheckBox
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.CompoundButton
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import org.autojs.autojs.util.ColorUtils
|
||||||
|
|
||||||
|
open class CompoundButtonAttributes(resourceParser: ResourceParser, view: View) : ButtonAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as CompoundButton
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttrs(arrayOf("checked", "check", "isChecked")) { setChecked(it.toBoolean()) }
|
||||||
|
registerAttr("buttonDrawable") { view.buttonDrawable = drawables.parse(view, it) }
|
||||||
|
registerAttrs(arrayOf("buttonTint", "tint")) { view.buttonTintList = parseTintList(view, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setChecked(checked: Boolean) {
|
||||||
|
view.isChecked = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val switchStates = arrayOf(
|
||||||
|
intArrayOf(-android.R.attr.state_checked),
|
||||||
|
intArrayOf(android.R.attr.state_checked),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun parseTintList(view: View, value: String): ColorStateList {
|
||||||
|
val colors = parseAttrValue(value)
|
||||||
|
return when (colors.size) {
|
||||||
|
2 -> ColorStateList(switchStates, colors.map { ColorUtils.parse(view, it) }.toIntArray())
|
||||||
|
else -> ColorUtils.parse(view, colors[0]).let { ColorStateList(switchStates, intArrayOf(it, it)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.autojs.autojs.core.ui.attribute
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import org.autojs.autojs.core.console.ConsoleView
|
||||||
|
import org.autojs.autojs.core.ui.inflater.ResourceParser
|
||||||
|
import org.autojs.autojs.util.ColorUtils
|
||||||
|
|
||||||
|
open class ConsoleViewAttributes(resourceParser: ResourceParser, view: View) : FrameLayoutAttributes(resourceParser, view) {
|
||||||
|
|
||||||
|
override val view = super.view as ConsoleView
|
||||||
|
|
||||||
|
override fun onRegisterAttrs() {
|
||||||
|
super.onRegisterAttrs()
|
||||||
|
|
||||||
|
registerAttr("textSize") { view.textSize = it.toFloat() }
|
||||||
|
registerAttr("textColors") { value -> view.setTextColors(parseAttrValue(value).map { ColorUtils.parse(view, it) }.toTypedArray()) }
|
||||||
|
registerAttrs(arrayOf("verboseTextColor", "verboseColor")) { view.setVerboseTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("debugTextColor", "debugColor")) { view.setDebugTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("infoTextColor", "infoColor")) { view.setInfoTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("warnTextColor", "warnColor")) { view.setWarnTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("errorTextColor", "errorColor")) { view.setErrorTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("assertTextColor", "assertColor")) { view.setAssertTextColor(ColorUtils.parse(view, it)) }
|
||||||
|
registerAttrs(arrayOf("isPinchToZoomEnabled", "pinchToZoomEnabled", "enablePinchToZoom")) { view.setPinchToZoomEnabled(it.toBoolean()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loaded 100 of 511 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user