8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AnyDebug
2 |
3 | English | [简体中文](README_CN.md)
4 |
5 | [](https://github.com/Xposed-Modules-Repo/com.hhvvg.anydebug/releases)
6 |
7 | Change your view attributes without restarting your application.
8 |
9 | # About
10 |
11 | This software relies on the [Xposed Framework](https://github.com/rovo89/Xposed), For more API details, visit their [website](https://api.xposed.info/).
12 |
13 | # Features
14 |
15 | + Touch screen to select views, instead of clicking it, this is far more convenient
16 | + Remove view
17 | + Change views' visibility
18 | + Change views' sizes
19 | + Change views' layout margin/padding
20 | + Change text of a `TextView`
21 | + Change text size
22 | + Change image, but currently only supports image url.
23 | + Properties viewer.
24 | + May be more...
25 |
26 | # TODO
27 |
28 | + Extract as a libracy for integrating into apps for debugging purpose.
29 |
30 | # Usage
31 |
32 | ## Install this app
33 |
34 | Just download and install it from the latest [releases page](https://github.com/gitofleonardo/AnyDebug/releases/latest).
35 |
36 | ## Check apps
37 |
38 | Check apps you want to hook in `LSPosed` or other `xposed` framework. Don't forget to force stop it before using.
39 |
40 | ## Mini window
41 |
42 | A mini window shows the preview, selection switch, and the bottom drag bar inside.
43 |
44 | + Click the preview to enter details page.
45 | + Check the selection switch to start view selection. When this is on, touching on screen will select the nearest views from your touch point.
46 | + Press the bottom drag bar then you can move the mini window to other positions.
47 |
48 | ## Details page
49 |
50 | Details page shows basic information and modification control. After modifing views' attributes, click the floating button below to confirm.
51 |
52 | ## Properties page
53 |
54 | The entry is `Details page` -> `Properties`, which shows all exported properties in a view. These properties are annotated with `ViewDebug.ExportedProperty`.
55 |
56 | ## Quick setting
57 |
58 | Add the quick setting button to notification control panel, you can toggle the state of the hook.
59 |
60 | ## Max window
61 |
62 | When the window is maximized, just drag the bottom bar and fling it to turn it back into a mini window.
63 |
64 | # Sample
65 |
66 | |  |  |  |  |
67 | | -- | -- | -- | -- |
68 |
69 | # Sponsor
70 |
71 | Give a free star to be a sponsor if you like this project.
72 |
73 | # Stargazers over time
74 |
75 | [](https://starchart.cc/gitofleonardo/AnyDebug)
76 |
77 | # License
78 |
79 | ```
80 | Copyright (C) <2024>
81 |
82 | This program is free software: you can redistribute it and/or modify
83 | it under the terms of the GNU General Public License as published by
84 | the Free Software Foundation, either version 3 of the License, or
85 | (at your option) any later version.
86 |
87 | This program is distributed in the hope that it will be useful,
88 | but WITHOUT ANY WARRANTY; without even the implied warranty of
89 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90 | GNU General Public License for more details.
91 |
92 | You should have received a copy of the GNU General Public License
93 | along with this program. If not, see .
94 | ```
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # AnyDebug
2 |
3 | [English](README.md) | 简体中文
4 |
5 | [](https://github.com/Xposed-Modules-Repo/com.hhvvg.anydebug/releases)
6 |
7 | 不需要重启应用,就可以更改View的参数。
8 |
9 | # 关于
10 |
11 | 本应用依赖于[Xposed框架](https://github.com/rovo89/Xposed)。需要获取更多关于这个框架的信息,请访问他们的[官网](https://api.xposed.info/)。
12 |
13 | # 特性
14 |
15 | + 触摸屏幕来选择 `View`,而不是通过点击,这会更加方便
16 | + 删掉 `View`
17 | + 更改 `View` 的可见性
18 | + 更改 `View` 的大小
19 | + 更改 `View` 的边距/内边距
20 | + 更改 `TextView` 的文本内容
21 | + 更改文本大小
22 | + 更改 `ImageView` 的图片内容,但目前仅支持链接形式的图片
23 | + 属性查看器
24 | + 或许还有更多...
25 |
26 | # 待办
27 |
28 | + 提取为一个库,用来集成进应用里调试用于调试
29 |
30 | # 用法
31 |
32 | ## 安装此应用
33 |
34 | 只需要从[发行页面](https://github.com/gitofleonardo/AnyDebug/releases/latest)中获取最新的安装包,然后安装即可。
35 |
36 | ## 勾选应用
37 |
38 | 在 `LSPosed` 或者是其他的 `xposed` 框架中勾选你需要 hook 的应用。勾选完成后不要忘了强行停止应用以使 hook 生效。
39 |
40 | ## 迷你窗口
41 |
42 | 迷你窗口展示了 `View` 的预览, 选择开关, 以及底部的拖动条.
43 |
44 | + 点击预览以进入 `View` 的详情页
45 | + 打开选择开关来开始选择 `View`。当开关打开的时候,触摸屏幕可以获取距离触摸点最近的所有 `View`
46 | + 按住底部拖动条并拖动,就可以移动迷你窗口在屏幕上的位置
47 |
48 | ## 详情页
49 |
50 | 详情页展示了 `View` 的基础信息,以及编辑控制. 在编辑完成信息之后,点击下方的悬浮按钮即可应用变更。
51 |
52 | ## 属性页
53 |
54 | 入口在 `详情页` -> `Properties` 处, 显示了该 `View` 所有的对外属性. 这些属性通常是带了 `ViewDebug.ExportedProperty` 注解的。
55 |
56 | ## 最大化窗口
57 |
58 | 当窗口被最大化之后,只需要拖动底部的拖拽条并甩动,即可最小化窗口。
59 |
60 | ## 快速设置
61 |
62 | 通过在控制面板中添加快捷开关按钮,你可以控制 hook 的开关状态。
63 |
64 | # 示例
65 |
66 | |  |  |  |  |
67 | | -- | -- | -- | -- |
68 |
69 | # 捐赠
70 |
71 | 如果你喜欢本项目的话,给个star支持一下就可以了。
72 |
73 | # License
74 |
75 | ```
76 | Copyright (C) <2024>
77 |
78 | This program is free software: you can redistribute it and/or modify
79 | it under the terms of the GNU General Public License as published by
80 | the Free Software Foundation, either version 3 of the License, or
81 | (at your option) any later version.
82 |
83 | This program is distributed in the hope that it will be useful,
84 | but WITHOUT ANY WARRANTY; without even the implied warranty of
85 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86 | GNU General Public License for more details.
87 |
88 | You should have received a copy of the GNU General Public License
89 | along with this program. If not, see .
90 | ```
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("org.jetbrains.kotlin.android")
4 | id("org.jetbrains.kotlin.kapt")
5 | id("com.google.devtools.ksp") version "1.9.23-1.0.19"
6 | }
7 |
8 | android {
9 | namespace = "com.hhvvg.anydebug"
10 | compileSdk = 34
11 |
12 | defaultConfig {
13 | applicationId = "com.hhvvg.anydebug"
14 | minSdk = 29
15 | targetSdk = 34
16 | versionCode = 14
17 | versionName = "3.0.4"
18 |
19 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
20 | }
21 |
22 | buildTypes {
23 | release {
24 | isMinifyEnabled = false
25 | isShrinkResources = false
26 | isDebuggable = true
27 | proguardFiles(
28 | getDefaultProguardFile("proguard-android-optimize.txt"),
29 | "proguard-rules.pro"
30 | )
31 | }
32 | debug {
33 | isMinifyEnabled = false
34 | isShrinkResources = false
35 | isDebuggable = true
36 | proguardFiles(
37 | getDefaultProguardFile("proguard-android-optimize.txt"),
38 | "proguard-rules.pro"
39 | )
40 | }
41 | }
42 | compileOptions {
43 | sourceCompatibility = JavaVersion.VERSION_17
44 | targetCompatibility = JavaVersion.VERSION_17
45 | }
46 | kotlinOptions {
47 | jvmTarget = "17"
48 | }
49 | buildFeatures {
50 | buildConfig = true
51 | }
52 | }
53 |
54 | dependencies {
55 | implementation("androidx.core:core-ktx:1.12.0")
56 | implementation("androidx.appcompat:appcompat:1.6.1")
57 | implementation("com.google.android.material:material:1.11.0")
58 | implementation("androidx.constraintlayout:constraintlayout:2.1.4")
59 |
60 | implementation("com.github.wching:Android-Indefinite-Pager-Indicator:1.5")
61 | implementation("com.github.bumptech.glide:glide:4.16.0")
62 |
63 | // 基础依赖
64 | implementation("com.highcapable.yukihookapi:api:1.2.0")
65 | // 作为 Xposed 模块使用务必添加,其它情况可选
66 | compileOnly("de.robv.android.xposed:api:82")
67 | // 作为 Xposed 模块使用务必添加,其它情况可选
68 | ksp("com.highcapable.yukihookapi:ksp-xposed:1.2.0")
69 |
70 | testImplementation("junit:junit:4.13.2")
71 | androidTestImplementation("androidx.test.ext:junit:1.1.5")
72 | androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
73 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/hhvvg/anydebug/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.hhvvg.anydebug
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("com.hhvvg.anydebug", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
20 |
23 |
26 |
29 |
32 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
48 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/App.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | import android.app.Application
21 |
22 | class App : Application()
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/InjectHookEntry.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | import android.content.res.XModuleResources
21 | import com.hhvvg.anydebug.modules.ActivityModule
22 | import com.hhvvg.anydebug.utils.Logger
23 | import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
24 | import com.highcapable.yukihookapi.hook.xposed.bridge.event.YukiXposedEvent
25 | import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
26 | import kotlin.reflect.KClass
27 |
28 | @InjectYukiHookWithXposed
29 | object InjectHookEntry : IYukiHookXposedInit {
30 | lateinit var moduleRes: XModuleResources
31 | lateinit var modulePath: String
32 | private val modules = arrayOf>(
33 | ActivityModule::class,
34 | )
35 |
36 | override fun onHook() {
37 | }
38 |
39 | override fun onXposedEvent() {
40 | super.onXposedEvent()
41 | YukiXposedEvent.onHandleLoadPackage { params ->
42 | if (!params.isFirstApplication) {
43 | Logger.log("Process already loaded, skip init modules.")
44 | return@onHandleLoadPackage
45 | }
46 | modules.forEach {
47 | (it.java.constructors[0].newInstance() as Module).onHook(params)
48 | }
49 | }
50 | YukiXposedEvent.onInitZygote {
51 | modulePath = it.modulePath
52 | moduleRes = XModuleResources.createInstance(modulePath, null)
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/Instance.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | interface Instance {
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.hhvvg.anydebug
2 |
3 | import androidx.appcompat.app.AppCompatActivity
4 | import android.os.Bundle
5 |
6 | class MainActivity : AppCompatActivity() {
7 | override fun onCreate(savedInstanceState: Bundle?) {
8 | super.onCreate(savedInstanceState)
9 | setContentView(R.layout.activity_main)
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/Module.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | import android.app.AndroidAppHelper
21 | import android.content.Context
22 | import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam
23 |
24 | interface Module {
25 |
26 | val context: Context
27 | get() = AndroidAppHelper.currentApplication()
28 |
29 | fun onHook(param: LoadPackageParam)
30 |
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/ModuleContext.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | import android.content.Context
21 | import android.content.res.Resources
22 | import android.content.res.Resources.Theme
23 | import android.view.ContextThemeWrapper
24 | import android.view.LayoutInflater
25 | import com.hhvvg.anydebug.utils.moduleResources
26 | import com.highcapable.yukihookapi.YukiHookAPI
27 | import com.highcapable.yukihookapi.hook.factory.classOf
28 |
29 | /**
30 | * Context for loading module's resources
31 | */
32 | class ModuleContext(baseContext: Context, theme: Theme) : ContextThemeWrapper(baseContext, theme) {
33 |
34 | private val inflater by lazy {
35 | (super.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater).cloneInContext(this)
36 | }
37 |
38 | override fun getResources(): Resources {
39 | return moduleResources
40 | }
41 |
42 | override fun getClassLoader(): ClassLoader {
43 | return classOf().classLoader ?: error("Error loading lsp class loader.")
44 | }
45 |
46 | override fun getSystemService(name: String): Any {
47 | if (LAYOUT_INFLATER_SERVICE == name) {
48 | return inflater
49 | }
50 | return super.getSystemService(name)
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/TileControlService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug
19 |
20 | import android.annotation.SuppressLint
21 | import android.service.quicksettings.Tile
22 | import android.service.quicksettings.TileService
23 | import com.hhvvg.anydebug.configurations.ConfigChangedReceiver
24 | import com.hhvvg.anydebug.configurations.ModuleSettings.Companion.moduleSettings
25 |
26 | class TileControlService : TileService() {
27 |
28 | private var stateEnabled: Boolean
29 | get() = qsTile.state == Tile.STATE_ACTIVE
30 | set(value) {
31 | qsTile.state = if (value) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
32 | qsTile.updateTile()
33 | }
34 |
35 | private val settings by lazy {
36 | moduleSettings
37 | }
38 | private val configReceiver = ConfigChangedReceiver {
39 | stateEnabled = settings.editEnabled
40 | }
41 |
42 | @SuppressLint("UnspecifiedRegisterReceiverFlag")
43 | override fun onCreate() {
44 | super.onCreate()
45 | ConfigChangedReceiver.registerConfigReceiver(this, configReceiver)
46 | }
47 |
48 | override fun onDestroy() {
49 | super.onDestroy()
50 | unregisterReceiver(configReceiver)
51 | }
52 |
53 | override fun onTileAdded() {
54 | super.onTileAdded()
55 | stateEnabled = settings.editEnabled
56 | }
57 |
58 | override fun onClick() {
59 | super.onClick()
60 | settings.editEnabled = !settings.editEnabled
61 | ConfigChangedReceiver.sendConfigBroadcast(this, settings.editEnabled)
62 | }
63 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/configurations/ConfigChangedReceiver.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.configurations
19 |
20 | import android.annotation.SuppressLint
21 | import android.content.BroadcastReceiver
22 | import android.content.Context
23 | import android.content.Intent
24 | import android.content.IntentFilter
25 | import android.os.Build
26 | import android.service.quicksettings.TileService
27 | import java.util.function.Consumer
28 |
29 | const val ACTION_CONFIG_CHANGED = "com.hhvvg.anydebug.config_changed"
30 | const val ACTION_KEY_EDIT_ENABLED = "key_edit_enabled"
31 |
32 | class ConfigChangedReceiver(private val callback: Consumer) : BroadcastReceiver() {
33 |
34 | override fun onReceive(context: Context, intent: Intent?) {
35 | val action = intent?.action ?: return
36 | if (action == ACTION_CONFIG_CHANGED) {
37 | val enabled = intent.getBooleanExtra(ACTION_KEY_EDIT_ENABLED, false)
38 | callback.accept(enabled)
39 | }
40 | }
41 |
42 | companion object {
43 | @JvmStatic
44 | fun sendConfigBroadcast(context: Context, enabled: Boolean) {
45 | val intent = Intent(ACTION_CONFIG_CHANGED).apply {
46 | putExtra(ACTION_KEY_EDIT_ENABLED, enabled)
47 | }
48 | context.sendBroadcast(intent)
49 | }
50 |
51 | @JvmStatic
52 | fun getConfigIntentFilter(): IntentFilter {
53 | return IntentFilter(ACTION_CONFIG_CHANGED)
54 | }
55 |
56 | @SuppressLint("UnspecifiedRegisterReceiverFlag")
57 | @JvmStatic
58 | fun registerConfigReceiver(context: Context, receiver: ConfigChangedReceiver) {
59 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
60 | context.registerReceiver(
61 | receiver, getConfigIntentFilter(),
62 | TileService.RECEIVER_EXPORTED
63 | )
64 | } else {
65 | context.registerReceiver(receiver, getConfigIntentFilter())
66 | }
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/configurations/ModuleSettings.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.configurations
19 |
20 | import android.content.Context
21 | import com.highcapable.yukihookapi.hook.factory.prefs
22 | import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge
23 |
24 | private const val MODULE_SETTINGS_SP_NAME = "module_settings_shared_preferences.xml"
25 | private const val KEY_EDIT_ENABLED = "key_edit_enabled"
26 |
27 | class ModuleSettings private constructor(private val context: Context) {
28 | private val prefs: YukiHookPrefsBridge
29 | get() = context.prefs(MODULE_SETTINGS_SP_NAME)
30 |
31 | var editEnabled: Boolean
32 | get() = prefs.getBoolean(KEY_EDIT_ENABLED, true)
33 | set(value) {
34 | prefs.edit().putBoolean(KEY_EDIT_ENABLED, value).apply()
35 | }
36 |
37 | companion object {
38 | val Context.moduleSettings
39 | get() = ModuleSettings(this)
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/fragment/ActivitylessFragmentContainer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.fragment
19 |
20 | import android.content.Context
21 | import android.util.AttributeSet
22 | import android.widget.FrameLayout
23 |
24 | class ActivitylessFragmentContainer(
25 | context: Context,
26 | attrs: AttributeSet?,
27 | defStyleAttr: Int,
28 | defStyleRes: Int
29 | ) :
30 | FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
31 |
32 | constructor(context: Context)
33 | : this(context, null)
34 |
35 | constructor(context: Context, attrs: AttributeSet?)
36 |
37 | : this(context, attrs, 0)
38 |
39 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
40 | : this(context, attrs, defStyleAttr, 0)
41 |
42 | val fragmentManager by lazy {
43 | ActivitylessFragmentManager(this)
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/fragment/MainPanelFragment.kt:
--------------------------------------------------------------------------------
1 | package com.hhvvg.anydebug.fragment
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.TextView
9 | import androidx.fragment.app.Fragment
10 | import com.hhvvg.anydebug.R
11 | import com.hhvvg.anydebug.utils.createModuleContext
12 | import com.hhvvg.anydebug.utils.moduleLayoutInflater
13 | import com.hhvvg.anydebug.utils.startGithubPage
14 | import com.hhvvg.anydebug.view.ActivityPreviewWindow
15 | import com.hhvvg.anydebug.view.SettingContent
16 | import com.hhvvg.anydebug.view.SettingsFactory
17 | import com.hhvvg.anydebug.view.SettingsFactoryManager
18 | import java.util.function.Consumer
19 |
20 | class MainPanelFragment(private val window: ActivityPreviewWindow, private var targetView: View?) :
21 | Fragment() {
22 |
23 | private var factory: SettingsFactory? = null
24 | private var onCommitListener: Runnable? = null
25 | private var onViewRemoveListener: Consumer? = null
26 |
27 | private lateinit var okButton: View
28 | private lateinit var settingsContainer: ViewGroup
29 | private lateinit var githubLinkBtn: TextView
30 |
31 | override fun onCreateView(
32 | inflater: LayoutInflater, container: ViewGroup?,
33 | savedInstanceState: Bundle?
34 | ): View? {
35 | val view = inflater.inflate(R.layout.fragment_main_panel, container, false)
36 | okButton = view.findViewById(R.id.ok_button)
37 | settingsContainer = view.findViewById(R.id.settings_container)
38 | githubLinkBtn = view.findViewById(R.id.about_proj_link)
39 |
40 | okButton.setOnClickListener {
41 | factory?.commit()
42 | onCommitListener?.run()
43 | }
44 | githubLinkBtn.setOnClickListener {
45 | requireContext().startGithubPage()
46 | }
47 | return view
48 | }
49 |
50 | override fun getContext(): Context? {
51 | return targetView?.context?.createModuleContext()
52 | }
53 |
54 | fun removeTargetView() {
55 | targetView?.let { onViewRemoveListener?.accept(it) }
56 | targetView?.parent?.let {
57 | if (it is ViewGroup) {
58 | it.removeView(targetView)
59 | }
60 | }
61 | }
62 |
63 | fun setOnCommitListener(listener: Runnable) {
64 | onCommitListener = listener
65 | }
66 |
67 | fun setOnViewRemoveListener(listener: Consumer) {
68 | onViewRemoveListener = listener
69 | }
70 |
71 | fun setTargetView(target: View) {
72 | targetView = target
73 | recreateSettings()
74 | }
75 |
76 | private fun clearSettings() {
77 | settingsContainer.removeAllViews()
78 | }
79 |
80 | private fun createTitle(titleText: CharSequence): TextView {
81 | val title = requireContext().moduleLayoutInflater()
82 | .inflate(R.layout.layout_title, settingsContainer, false) as TextView
83 | title.text = titleText
84 | return title
85 | }
86 |
87 | private fun recreateSettings() {
88 | clearSettings()
89 | val target = targetView ?: return
90 | val views = mutableListOf()
91 | factory = SettingsFactoryManager.createFactory(window, target).apply {
92 | onCreate(target, settingsContainer, views)
93 | }
94 | views.forEach {
95 | settingsContainer.addView(createTitle(it.title))
96 | settingsContainer.addView(it.view)
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/fragment/ViewPropertiesFragment.kt:
--------------------------------------------------------------------------------
1 | package com.hhvvg.anydebug.fragment
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.os.Bundle
6 | import android.text.TextUtils
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.EditText
11 | import android.widget.TextView
12 | import androidx.core.widget.doOnTextChanged
13 | import androidx.fragment.app.Fragment
14 | import androidx.recyclerview.widget.LinearLayoutManager
15 | import androidx.recyclerview.widget.RecyclerView
16 | import androidx.recyclerview.widget.RecyclerView.Adapter
17 | import androidx.recyclerview.widget.RecyclerView.ViewHolder
18 | import com.hhvvg.anydebug.R
19 | import com.hhvvg.anydebug.utils.ViewExportedProperty
20 | import com.hhvvg.anydebug.utils.dumpView
21 | import com.hhvvg.anydebug.utils.formatToExportedProperties
22 |
23 | class ViewPropertiesFragment(private val targetView: View) : Fragment() {
24 |
25 | private lateinit var propertiesRv: RecyclerView
26 | private lateinit var propertiesSearchView: EditText
27 | private val items = mutableListOf()
28 | private val adapter = PropertiesAdapter(items)
29 |
30 | override fun onCreateView(
31 | inflater: LayoutInflater, container: ViewGroup?,
32 | savedInstanceState: Bundle?
33 | ): View {
34 | val view = inflater.inflate(R.layout.fragment_view_properties, container, false)
35 | propertiesRv = view.findViewById(R.id.properties_rv).apply {
36 | this.adapter = this@ViewPropertiesFragment.adapter
37 | layoutManager = LinearLayoutManager(requireContext())
38 | }
39 | propertiesSearchView = view.findViewById(R.id.type_to_search)
40 | propertiesSearchView.doOnTextChanged { text, _, _, _ ->
41 | updatePropertiesList(text)
42 | }
43 | updatePropertiesList()
44 | return view
45 | }
46 |
47 | override fun getContext(): Context? {
48 | return targetView.context
49 | }
50 |
51 | @SuppressLint("NotifyDataSetChanged")
52 | private fun updatePropertiesList(filter: CharSequence? = null) {
53 | val props = targetView
54 | .dumpView()
55 | .formatToExportedProperties().values.flatten()
56 | .filter {
57 | if (TextUtils.isEmpty(filter)) {
58 | true
59 | } else {
60 | it.name.contains(filter!!, true)
61 | }
62 | }
63 | .sortedBy { it.name }
64 | items.clear()
65 | items.addAll(props)
66 | adapter.notifyDataSetChanged()
67 | }
68 | }
69 |
70 | private class PropertiesAdapter(private val items: List) :
71 | Adapter() {
72 | override fun getItemCount(): Int {
73 | return items.size
74 | }
75 |
76 | override fun onBindViewHolder(holder: PropertiesHolder, position: Int) {
77 | val item = items[position]
78 | holder.name.text = item.name
79 | holder.value.text = item.value.toString()
80 | }
81 |
82 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PropertiesHolder {
83 | return PropertiesHolder(
84 | LayoutInflater.from(parent.context)
85 | .inflate(R.layout.layout_view_property_item, parent, false)
86 | )
87 | }
88 | }
89 |
90 | private class PropertiesHolder(view: View) : ViewHolder(view) {
91 | val name: TextView by lazy { view.findViewById(R.id.name_view) }
92 | val value: TextView by lazy { view.findViewById(R.id.value_view) }
93 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/instances/ActivityInstance.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.instances
19 |
20 | import android.app.Activity
21 | import android.app.Application.ActivityLifecycleCallbacks
22 | import android.os.Bundle
23 | import com.hhvvg.anydebug.Instance
24 | import com.hhvvg.anydebug.configurations.ConfigChangedReceiver
25 | import com.hhvvg.anydebug.configurations.ModuleSettings.Companion.moduleSettings
26 | import com.hhvvg.anydebug.utils.doAfter
27 | import com.hhvvg.anydebug.view.ActivityPreviewWindow
28 | import de.robv.android.xposed.XC_MethodHook.Unhook
29 |
30 | class ActivityInstance(private val activity: Activity) : Instance, ActivityLifecycleCallbacks {
31 |
32 | private var previewWindow: ActivityPreviewWindow? = null
33 |
34 | private val settings by lazy {
35 | activity.moduleSettings
36 | }
37 | private val shouldShowWindow: Boolean
38 | get() = settings.editEnabled
39 | private var windowFocusHook: Unhook? = null
40 | private val configReceiver by lazy {
41 | ConfigChangedReceiver {
42 | onDisplayWindowChanged(it)
43 | }
44 | }
45 |
46 | init {
47 | activity.registerActivityLifecycleCallbacks(this)
48 | ConfigChangedReceiver.registerConfigReceiver(activity, configReceiver)
49 | windowFocusHook = Activity::class.doAfter("onWindowFocusChanged", Boolean::class.java) {
50 | if (it.args[0] as Boolean) {
51 | onDisplayWindowChanged(shouldShowWindow)
52 | }
53 | }
54 | }
55 |
56 | override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
57 | }
58 |
59 | override fun onActivityDestroyed(activity: Activity) {
60 | }
61 |
62 | override fun onActivityPaused(activity: Activity) {
63 | }
64 |
65 | override fun onActivityPreDestroyed(activity: Activity) {
66 | super.onActivityPreDestroyed(activity)
67 | activity.unregisterReceiver(configReceiver)
68 | windowFocusHook?.unhook()
69 | onDisplayWindowChanged(false)
70 | }
71 |
72 | override fun onActivityResumed(activity: Activity) {
73 | }
74 |
75 | override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
76 | }
77 |
78 | override fun onActivityStarted(activity: Activity) {
79 | }
80 |
81 | override fun onActivityStopped(activity: Activity) {
82 | }
83 |
84 | private fun onDisplayWindowChanged(show: Boolean) {
85 | previewWindow = if (show) {
86 | val preview = previewWindow
87 | if (preview != null) {
88 | return
89 | }
90 | ActivityPreviewWindow(activity).apply {
91 | show()
92 | }
93 | } else {
94 | previewWindow?.dismiss()
95 | null
96 | }
97 | }
98 |
99 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/modules/ActivityModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.modules
19 |
20 | import android.app.Activity
21 | import android.os.Bundle
22 | import com.hhvvg.anydebug.Module
23 | import com.hhvvg.anydebug.instances.ActivityInstance
24 | import com.hhvvg.anydebug.utils.doAfter
25 | import de.robv.android.xposed.callbacks.XC_LoadPackage
26 |
27 | class ActivityModule : Module {
28 |
29 | override fun onHook(param: XC_LoadPackage.LoadPackageParam) {
30 | Activity::class.doAfter("onCreate", Bundle::class.java) {
31 | ActivityInstance(it.thisObject as Activity)
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/utils/Animations.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.utils
19 |
20 | import android.util.FloatProperty
21 | import android.view.View
22 |
23 | val SCALE = object : FloatProperty("scaleX") {
24 | override fun get(view: View): Float {
25 | return view.scaleX
26 | }
27 |
28 | override fun setValue(view: View, value: Float) {
29 | view.scaleX = value
30 | view.scaleY = value
31 | }
32 | }
33 |
34 | val TRANSLATION_X = object : FloatProperty("translationX") {
35 | override fun setValue(view: View, value: Float) {
36 | view.translationX = value
37 | }
38 |
39 | override fun get(view: View): Float {
40 | return view.translationX
41 | }
42 | }
43 |
44 | val ALPHA = object : FloatProperty("alpha") {
45 | override fun setValue(view: View, value: Float) {
46 | view.alpha = value
47 | }
48 |
49 | override fun get(view: View): Float {
50 | return view.alpha
51 | }
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/utils/Logger.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.utils
19 |
20 | import de.robv.android.xposed.XposedBridge
21 |
22 | class Logger {
23 | companion object {
24 | fun log(tag: String, log: String, t: Throwable? = null) {
25 | XposedBridge.log("${tag}: $log")
26 | t?.let { log(it) }
27 | }
28 |
29 | fun log(log: String) {
30 | XposedBridge.log(log)
31 | }
32 |
33 | fun log(t: Throwable) {
34 | XposedBridge.log(t)
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/utils/OverScroll.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hhvvg.anydebug.utils;
17 |
18 | /**
19 | * Utility methods for overscroll damping and related effect.
20 | */
21 | public class OverScroll {
22 |
23 | public static final float OVERSCROLL_DAMP_FACTOR = 0.07f;
24 |
25 | /**
26 | * This curve determines how the effect of scrolling over the limits of the page diminishes
27 | * as the user pulls further and further from the bounds
28 | *
29 | * @param f The percentage of how much the user has overscrolled.
30 | * @return A transformed percentage based on the influence curve.
31 | */
32 | private static float overScrollInfluenceCurve(float f) {
33 | f -= 1.0f;
34 | return f * f * f + 1.0f;
35 | }
36 |
37 | /**
38 | * @param amount The original amount overscrolled.
39 | * @param max The maximum amount that the View can overscroll.
40 | * @return The dampened overscroll amount.
41 | */
42 | public static int dampedScroll(float amount, int max) {
43 | if (Float.compare(amount, 0) == 0) return 0;
44 |
45 | float f = amount / max;
46 | f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
47 |
48 | // Clamp this factor, f, to -1 < f < 1
49 | if (Math.abs(f) >= 1) {
50 | f /= Math.abs(f);
51 | }
52 |
53 | return Math.round(OVERSCROLL_DAMP_FACTOR * f * max);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/utils/ViewExportedProperty.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.utils
19 |
20 | data class ViewExportedProperty(
21 | val category: String?,
22 | val name: String,
23 | val length: Int,
24 | val value: Any
25 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/DecorView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.content.Context
21 | import android.util.AttributeSet
22 | import android.view.KeyEvent
23 | import android.widget.FrameLayout
24 | import com.hhvvg.anydebug.utils.Logger
25 |
26 | class DecorView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
27 | FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
28 |
29 | constructor(context: Context)
30 | : this(context, null)
31 |
32 | constructor(context: Context, attrs: AttributeSet?)
33 |
34 | : this(context, attrs, 0)
35 |
36 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
37 | : this(context, attrs, defStyleAttr, 0)
38 |
39 | private var backInvokedCallback: OnBackInvokedCallback? = null
40 |
41 |
42 | fun setOnBackInvokedCallback(listener: OnBackInvokedCallback) {
43 | backInvokedCallback = listener
44 | }
45 |
46 | override fun dispatchKeyEvent(event: KeyEvent): Boolean {
47 | if (event.action == KeyEvent.ACTION_UP && event.keyCode == KeyEvent.KEYCODE_BACK) {
48 | backInvokedCallback?.onBackInvoked()
49 | return true
50 | }
51 | return super.dispatchKeyEvent(event)
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/OnBackInvokedCallback.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | @FunctionalInterface
21 | interface OnBackInvokedCallback {
22 |
23 | fun onBackInvoked()
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/PreviewAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.annotation.SuppressLint
21 | import android.content.Context
22 | import android.view.View
23 | import android.view.View.OnClickListener
24 | import android.view.ViewGroup
25 | import androidx.recyclerview.widget.RecyclerView.Adapter
26 | import androidx.recyclerview.widget.RecyclerView.ViewHolder
27 | import com.hhvvg.anydebug.R
28 | import com.hhvvg.anydebug.view.remote.RemoteFactoryImpl
29 |
30 | /**
31 | * Adapter for PreviewList
32 | */
33 | class PreviewAdapter(context: Context) : Adapter() {
34 |
35 | private var onPreviewClickListener: OnClickListener? = null
36 | private val previewItems = mutableListOf()
37 | private val remoteInflater = RemoteFactoryImpl()
38 |
39 | override fun getItemCount(): Int {
40 | return previewItems.size
41 | }
42 |
43 | override fun onBindViewHolder(holder: PreviewHolder, position: Int) {
44 | val item = previewItems[position]
45 | holder.previewView.setRenderer(item.view)
46 | holder.previewView.setOnClickListener {
47 | onPreviewClickListener?.onClick(holder.previewView.getRenderer())
48 | }
49 | }
50 |
51 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PreviewHolder {
52 | val view =
53 | remoteInflater.onInflateView(parent.context, "layout_preview_item", parent, false)
54 | return PreviewHolder(view)
55 | }
56 |
57 | @SuppressLint("NotifyDataSetChanged")
58 | fun removePreviewView(view: View) {
59 | previewItems.removeIf {
60 | it.view == view
61 | }
62 | notifyDataSetChanged()
63 | }
64 |
65 | fun setOnClickListener(listener: OnClickListener) {
66 | onPreviewClickListener = listener
67 | }
68 |
69 | @SuppressLint("NotifyDataSetChanged")
70 | fun updatePreviewItems(items: List) {
71 | previewItems.clear()
72 | previewItems.addAll(items)
73 | notifyDataSetChanged()
74 | }
75 |
76 | }
77 |
78 | class PreviewHolder(view: View) : ViewHolder(view) {
79 | val previewView: PreviewView by lazy {
80 | view.findViewById(R.id.preview_item)
81 | }
82 |
83 | }
84 |
85 | data class ViewItem(
86 | val view: View,
87 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/PreviewList.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.content.Context
21 | import android.util.AttributeSet
22 | import android.view.View
23 | import androidx.recyclerview.widget.LinearLayoutManager
24 | import androidx.recyclerview.widget.LinearSnapHelper
25 | import androidx.recyclerview.widget.RecyclerView
26 | import com.hhvvg.anydebug.R
27 | import com.rbrooks.indefinitepagerindicator.IndefinitePagerIndicator
28 |
29 | /**
30 | * Preview view for a set of views
31 | */
32 | class PreviewList(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
33 | RecyclerView(context, attrs, defStyleAttr) {
34 |
35 | private val indicatorView: IndefinitePagerIndicator?
36 | get() = (parent as View).findViewById(R.id.page_indicator)
37 |
38 | private val previewAdapter = PreviewAdapter(context)
39 |
40 | constructor(context: Context) : this(context, null)
41 |
42 | constructor(context: Context, attrs: AttributeSet?)
43 |
44 | : this(context, attrs, 0)
45 |
46 | init {
47 | adapter = previewAdapter
48 | layoutManager = LinearLayoutManager(context, HORIZONTAL, false)
49 | LinearSnapHelper().attachToRecyclerView(this)
50 | }
51 |
52 | override fun onAttachedToWindow() {
53 | super.onAttachedToWindow()
54 | indicatorView?.attachToRecyclerView(this)
55 | }
56 |
57 | fun removePreviewView(view: View) {
58 | previewAdapter.removePreviewView(view)
59 | indicatorView?.requestLayout()
60 | }
61 |
62 | fun setOnPreviewClickListener(listener: OnClickListener) {
63 | previewAdapter.setOnClickListener(listener)
64 | }
65 |
66 | fun updatePreviewItems(items: List) {
67 | previewAdapter.updatePreviewItems(items.map { ViewItem(it) })
68 | indicatorView?.requestLayout()
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/PreviewView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.content.Context
21 | import android.graphics.Canvas
22 | import android.graphics.RenderNode
23 | import android.util.AttributeSet
24 | import android.view.View
25 | import android.view.ViewDebug
26 | import com.hhvvg.anydebug.utils.call
27 | import com.hhvvg.anydebug.utils.dumpView
28 | import com.hhvvg.anydebug.utils.formatToExportedProperties
29 | import de.robv.android.xposed.XposedBridge
30 | import java.io.BufferedOutputStream
31 | import java.io.BufferedWriter
32 | import java.io.ByteArrayOutputStream
33 | import java.io.OutputStream
34 | import java.io.StringWriter
35 | import kotlin.math.min
36 |
37 | /**
38 | * Capture and render other View
39 | */
40 | class PreviewView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
41 | View(context, attrs, defStyleAttr, defStyleRes) {
42 |
43 | private var renderer: View? = null
44 | private val renderNode: RenderNode = RenderNode("PreviewViewNode")
45 |
46 | constructor(context: Context)
47 | : this(context, null)
48 |
49 | constructor(context: Context, attrs: AttributeSet?)
50 |
51 | : this(context, attrs, 0)
52 |
53 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
54 | : this(context, attrs, defStyleAttr, 0)
55 |
56 | override fun onDraw(canvas: Canvas) {
57 | renderer?.let { drawRenderer(canvas, it) }
58 | }
59 |
60 | fun getRenderer(): View? {
61 | return renderer
62 | }
63 |
64 | fun setRenderer(view: View?) {
65 | renderer = view
66 | renderNode.discardDisplayList()
67 | invalidate()
68 | }
69 |
70 | private fun buildDisplayList(renderer: View) {
71 | val canvas = renderNode.beginRecording(width, height)
72 | renderNode.setPosition(0, 0, width, height)
73 | val widthScale = width / renderer.width.toFloat()
74 | val heightScale = height / renderer.height.toFloat()
75 | val finalScale = min(widthScale, heightScale)
76 | val tranX = (width - renderer.width * finalScale) / 2
77 | val tranY = (height - renderer.height * finalScale) / 2
78 | try {
79 | canvas.save()
80 | canvas.translate(tranX, tranY)
81 | canvas.scale(finalScale, finalScale)
82 | renderer.draw(canvas)
83 | canvas.restore()
84 | } finally {
85 | renderNode.endRecording()
86 | }
87 | }
88 |
89 | private fun drawRenderer(canvas: Canvas, renderer: View) {
90 | if (!renderNode.hasDisplayList()) {
91 | buildDisplayList(renderer)
92 | }
93 | if (renderNode.hasDisplayList() && canvas.isHardwareAccelerated) {
94 | canvas.drawRenderNode(renderNode)
95 | }
96 | }
97 |
98 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/SettingsFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.view.View
21 | import android.view.ViewGroup
22 |
23 | /**
24 | * Basic factory for creating settings for a View
25 | */
26 | interface SettingsFactory {
27 |
28 | /**
29 | * Creating settings
30 | *
31 | * @param targetView target view for mod
32 | * @param parent parent view of settings
33 | * @param outViews all settings contents
34 | */
35 | fun onCreate(targetView: View, parent: ViewGroup, outViews: MutableList)
36 |
37 | /**
38 | * Commit all pending settings
39 | */
40 | fun commit()
41 |
42 | }
43 |
44 | /**
45 | * Settings identity
46 | */
47 | data class SettingContent(val view: View, val title: CharSequence)
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/SettingsFactoryManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.view.View
21 | import android.widget.ImageView
22 | import android.widget.TextView
23 | import com.hhvvg.anydebug.view.factory.BasicViewFactory
24 | import com.hhvvg.anydebug.view.factory.ImageViewFactory
25 | import com.hhvvg.anydebug.view.factory.TextViewFactory
26 |
27 | object SettingsFactoryManager {
28 |
29 | fun createFactory(window: ActivityPreviewWindow, target: View): SettingsFactory {
30 | return when (target) {
31 | is TextView -> TextViewFactory(window)
32 | is ImageView -> ImageViewFactory(window)
33 | else -> BasicViewFactory(window)
34 | }
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/WindowClient.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view
19 |
20 | import android.graphics.Insets
21 | import android.graphics.Rect
22 | import android.view.WindowManager
23 |
24 | interface WindowClient {
25 |
26 | fun getParentWindowFrame(): Rect
27 | fun onRequestMaxWindowSize(width: Int, height: Int)
28 | fun onStateSizeAnimationEnd(state: Int)
29 | fun onWindowHeightChanged(
30 | startHeight: Float,
31 | endHeight: Float,
32 | minHeight: Float,
33 | maxHeight: Float,
34 | height: Float
35 | )
36 |
37 | fun onWindowInsetsChanged(insets: Insets)
38 | fun onWindowStateChanged(state: Int)
39 |
40 | fun onWindowWidthChanged(
41 | startWidth: Float,
42 | endWidth: Float,
43 | minWidth: Float,
44 | maxWidth: Float,
45 | width: Float
46 | )
47 |
48 | fun updateWindowAttributes(attr: WindowManager.LayoutParams)
49 |
50 | fun updateWindowContent(
51 | width: Int,
52 | height: Int
53 | )
54 |
55 | fun onMinimize()
56 |
57 | fun onMaximize()
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/ImageViewFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory
19 |
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.widget.ImageView
24 | import android.widget.ImageView.ScaleType
25 | import com.hhvvg.anydebug.R
26 | import com.hhvvg.anydebug.utils.reverse
27 | import com.hhvvg.anydebug.view.ActivityPreviewWindow
28 | import com.hhvvg.anydebug.view.SettingContent
29 | import com.hhvvg.anydebug.view.factory.command.ImageScaleTypeCommand
30 | import com.hhvvg.anydebug.view.factory.command.ImageUrlCommand
31 | import com.hhvvg.anydebug.view.preference.InputPreferenceView
32 | import com.hhvvg.anydebug.view.preference.OptionsPreferenceView
33 |
34 | /**
35 | * Settings factory for a ImageView
36 | */
37 | class ImageViewFactory(window: ActivityPreviewWindow) : BasicViewFactory(window) {
38 |
39 | override fun onCreate(
40 | targetView: View,
41 | parent: ViewGroup,
42 | outViews: MutableList
43 | ) {
44 | super.onCreate(targetView, parent, outViews)
45 | if (targetView !is ImageView) {
46 | return
47 | }
48 | val view = LayoutInflater.from(parent.context)
49 | .inflate(R.layout.layout_image_view_settings, parent, false)
50 | val urlPref = view.findViewById(R.id.image_url_input)
51 | val scaleTypePref = view.findViewById(R.id.scale_type_preference)
52 |
53 | val scaleTypeIndexMapper = createScaleTypeMapper()
54 | val indexScaleTypeMapper = scaleTypeIndexMapper.reverse()
55 | scaleTypePref.selectedIndex = scaleTypeIndexMapper.getOrDefault(targetView.scaleType, -1)
56 | scaleTypePref.setOnCheckChangedListener { _, id ->
57 | indexScaleTypeMapper[id]?.let {
58 | addCommand(ImageScaleTypeCommand(targetView, it))
59 | }
60 | }
61 | urlPref.setOnTextChangedListener {
62 | if (it.isNotEmpty()) {
63 | addCommand(ImageUrlCommand(targetView, it.toString()))
64 | } else {
65 | removeCommand(ImageUrlCommand::class)
66 | }
67 | }
68 | outViews.add(
69 | SettingContent(view, parent.context.resources.getString(R.string.title_image_view))
70 | )
71 | }
72 |
73 | private fun createScaleTypeMapper(): Map {
74 | return mapOf(
75 | ScaleType.FIT_XY to 0,
76 | ScaleType.FIT_START to 1,
77 | ScaleType.FIT_CENTER to 2,
78 | ScaleType.FIT_END to 3,
79 | ScaleType.CENTER to 4,
80 | ScaleType.CENTER_CROP to 5,
81 | ScaleType.CENTER_INSIDE to 6
82 | )
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/TextViewFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory
19 |
20 | import android.view.LayoutInflater
21 | import android.view.View
22 | import android.view.ViewGroup
23 | import android.widget.TextView
24 | import com.hhvvg.anydebug.R
25 | import com.hhvvg.anydebug.view.ActivityPreviewWindow
26 | import com.hhvvg.anydebug.view.SettingContent
27 | import com.hhvvg.anydebug.view.factory.command.TextCommand
28 | import com.hhvvg.anydebug.view.factory.command.TextMaxLinesCommand
29 | import com.hhvvg.anydebug.view.factory.command.TextSizeCommand
30 | import com.hhvvg.anydebug.view.preference.InputPreferenceView
31 |
32 | /**
33 | * Settings factory for a TextView
34 | */
35 | class TextViewFactory(window: ActivityPreviewWindow) : BasicViewFactory(window) {
36 |
37 | override fun onCreate(
38 | targetView: View,
39 | parent: ViewGroup,
40 | outViews: MutableList
41 | ) {
42 | super.onCreate(targetView, parent, outViews)
43 | if (targetView !is TextView) {
44 | return
45 | }
46 | val view = LayoutInflater.from(parent.context)
47 | .inflate(R.layout.layout_text_view_settings, parent, false)
48 | val textInputPref = view.findViewById(R.id.text_input)
49 | val textSizeInputPref = view.findViewById(R.id.text_size_input)
50 | val maxLinesInputPref = view.findViewById(R.id.max_lines_input)
51 |
52 | maxLinesInputPref.text = targetView.maxLines.toString()
53 | maxLinesInputPref.setOnTextChangedListener {
54 | addCommand(TextMaxLinesCommand(targetView, it))
55 | }
56 | textInputPref.text = targetView.text
57 | textInputPref.setOnTextChangedListener {
58 | addCommand(TextCommand(targetView, it))
59 | }
60 | textSizeInputPref.text = (targetView.textSize / targetView.paint.density).toString()
61 | textSizeInputPref.setOnTextChangedListener {
62 | addCommand(TextSizeCommand(targetView, it))
63 | }
64 | outViews.add(
65 | SettingContent(
66 | view,
67 | parent.context.resources.getString(R.string.title_text_view)
68 | )
69 | )
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/AlphaCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class AlphaCommand(view: View, private val alpha: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.alpha = alpha
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/BaseCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | /**
23 | * A abstract command for changing views' attributes
24 | */
25 | abstract class BaseCommand(protected val targetView: T) : FactoryCommand
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/FactoryCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | /**
21 | * @see BaseCommand
22 | */
23 | interface FactoryCommand {
24 |
25 | /**
26 | * Called when this command is being applied
27 | */
28 | fun onApply()
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/HeightCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | /**
23 | * Command for setting height spec
24 | */
25 | class HeightCommand(view: View, private val height: Int) : BaseCommand(view) {
26 |
27 | override fun onApply() {
28 | targetView.layoutParams?.let {
29 | it.height = height
30 | targetView.layoutParams = it
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ImageScaleTypeCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.widget.ImageView
21 | import android.widget.ImageView.ScaleType
22 |
23 | class ImageScaleTypeCommand(view: ImageView, private val scaleType: ScaleType) :
24 | BaseCommand(view) {
25 |
26 | override fun onApply() {
27 | targetView.scaleType = scaleType
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ImageUrlCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.widget.ImageView
21 | import com.bumptech.glide.Glide
22 |
23 | /**
24 | * Command for loading url into a ImageView
25 | */
26 | class ImageUrlCommand(view: ImageView, private val url: String) : BaseCommand(view) {
27 |
28 | override fun onApply() {
29 | Glide.with(targetView)
30 | .load(url)
31 | .into(targetView)
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/MarginLtrbCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 | import android.view.ViewGroup.MarginLayoutParams
22 | import com.hhvvg.anydebug.utils.ltrbPattern
23 |
24 | /**
25 | * Command for settings margins
26 | */
27 | class MarginLtrbCommand(view: View, private val ltrb: CharSequence) : BaseCommand(view) {
28 |
29 | override fun onApply() {
30 | val params = targetView.layoutParams
31 | if (params !is MarginLayoutParams) {
32 | return
33 | }
34 | val matcher = ltrbPattern.matcher(ltrb)
35 | if (matcher.find()) {
36 | params.leftMargin = matcher.group(1)?.toInt() ?: 0
37 | params.topMargin = matcher.group(2)?.toInt() ?: 0
38 | params.rightMargin = matcher.group(3)?.toInt() ?: 0
39 | params.bottomMargin = matcher.group(4)?.toInt() ?: 0
40 | }
41 | targetView.layoutParams = params
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/PaddingLtrbCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 | import com.hhvvg.anydebug.utils.ltrbPattern
22 |
23 | /**
24 | * Command for setting paddings
25 | */
26 | class PaddingLtrbCommand(view: View, private val ltrb: CharSequence) : BaseCommand(view) {
27 |
28 | override fun onApply() {
29 | val matcher = ltrbPattern.matcher(ltrb)
30 | var l = 0
31 | var t = 0
32 | var r = 0
33 | var b = 0
34 | if (matcher.find()) {
35 | l = matcher.group(1)?.toInt() ?: 0
36 | t = matcher.group(2)?.toInt() ?: 0
37 | r = matcher.group(3)?.toInt() ?: 0
38 | b = matcher.group(4)?.toInt() ?: 0
39 | }
40 | targetView.setPadding(l, t, r, b)
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/RotationCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class RotationCommand(view: View, private val rotation: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.rotation = rotation
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/RotationXCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class RotationXCommand(view: View, private val rotation: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.rotationX = rotation
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/RotationYCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class RotationYCommand(view: View, private val rotation: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.rotationY = rotation
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ScaleXCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class ScaleXCommand(view: View, private val scaleX: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.scaleX = scaleX
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ScaleYCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class ScaleYCommand(view: View, private val scaleY: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.scaleY = scaleY
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ScrollXCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class ScrollXCommand(view: View, private val scroll: Int): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.scrollX = scroll
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/ScrollYCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class ScrollYCommand(view: View, private val scroll: Int): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.scrollY = scroll
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TextCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.widget.TextView
21 |
22 | /**
23 | * Command for setting text for a TextView
24 | */
25 | class TextCommand(view: TextView, private val text: CharSequence) : BaseCommand(view) {
26 |
27 | override fun onApply() {
28 | targetView.text = text
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TextMaxLinesCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.widget.TextView
21 |
22 | class TextMaxLinesCommand(view: TextView, private val maxLines: CharSequence) :
23 | BaseCommand(view) {
24 |
25 | override fun onApply() {
26 | maxLines.toString().toIntOrNull()?.let {
27 | targetView.maxLines = it
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TextSizeCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.widget.TextView
21 |
22 | /**
23 | * Command for setting text size
24 | */
25 | class TextSizeCommand(view: TextView, private val textSize: CharSequence) : BaseCommand(view) {
26 |
27 | override fun onApply() {
28 | textSize.toString().toFloatOrNull()?.let { targetView.textSize = it }
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TranXCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class TranXCommand(view: View, private val tranX: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.translationX = tranX
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TranYCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class TranYCommand(view: View, private val tranY: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.translationY = tranY
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/TranZCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | class TranZCommand(view: View, private val tranZ: Float): BaseCommand(view) {
23 |
24 | override fun onApply() {
25 | targetView.translationZ = tranZ
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/VisibilityCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | /**
23 | * Command for setting visibility
24 | */
25 | class VisibilityCommand(view: View, private val visibility: Int) : BaseCommand(view) {
26 |
27 | override fun onApply() {
28 | targetView.visibility = visibility
29 | }
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/factory/command/WidthCommand.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.factory.command
19 |
20 | import android.view.View
21 |
22 | /**
23 | * Command for setting height spec
24 | */
25 | class WidthCommand(view: View, private val width: Int) : BaseCommand(view) {
26 |
27 | override fun onApply() {
28 | targetView.layoutParams?.let {
29 | it.width = width
30 | targetView.layoutParams = it
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/preference/InputPreferenceView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.preference
19 |
20 | import android.content.Context
21 | import android.text.InputType
22 | import android.util.AttributeSet
23 | import android.widget.EditText
24 | import android.widget.TextView
25 | import androidx.constraintlayout.widget.ConstraintLayout
26 | import androidx.core.view.isVisible
27 | import androidx.core.widget.addTextChangedListener
28 | import com.hhvvg.anydebug.R
29 | import java.util.function.Consumer
30 |
31 | /**
32 | * Preference for text input
33 | */
34 | class InputPreferenceView(
35 | context: Context,
36 | attrs: AttributeSet?,
37 | defStyleAttr: Int,
38 | defStyleRes: Int
39 | ) :
40 | ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) {
41 |
42 | private var textListener: Consumer? = null
43 |
44 | private val inputView: EditText
45 | get() = findViewById(R.id.input_view)
46 |
47 | private val summaryView: TextView
48 | get() = findViewById(R.id.summary_view)
49 |
50 | private val titleView: TextView
51 | get() = findViewById(R.id.title_view)
52 |
53 | var hint: CharSequence?
54 | get() = inputView.hint
55 | set(value) {
56 | inputView.hint = value
57 | }
58 |
59 | var inputType: Int
60 | get() = inputView.inputType
61 | set(value) {
62 | inputView.inputType = value
63 | }
64 |
65 | var maxLines: Int
66 | get() = inputView.maxLines
67 | set(value) {
68 | inputView.maxLines = value
69 | }
70 |
71 | var summary: CharSequence?
72 | get() = summaryView.text
73 | set(value) {
74 | summaryView.text = value
75 | summaryView.isVisible = !value.isNullOrEmpty()
76 | }
77 |
78 | var text: CharSequence?
79 | get() = inputView.text
80 | set(value) {
81 | inputView.setText(value?.toString() ?: "")
82 | }
83 |
84 | var title: CharSequence?
85 | get() = titleView.text
86 | set(value) {
87 | titleView.text = value
88 | }
89 |
90 | constructor(context: Context)
91 | : this(context, null)
92 |
93 | constructor(context: Context, attrs: AttributeSet?)
94 |
95 | : this(context, attrs, 0)
96 |
97 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
98 | : this(context, attrs, defStyleAttr, 0)
99 |
100 | init {
101 | inflate(context, R.layout.layout_input_preference_view, this)
102 | val ta = context.obtainStyledAttributes(attrs, R.styleable.InputPreferenceView)
103 | title = ta.getString(R.styleable.InputPreferenceView_preference_title)
104 | hint = ta.getString(R.styleable.InputPreferenceView_preference_input_hint)
105 | inputType = ta.getInt(
106 | R.styleable.InputPreferenceView_android_inputType,
107 | InputType.TYPE_CLASS_TEXT
108 | )
109 | maxLines = ta.getInt(
110 | R.styleable.InputPreferenceView_android_maxLines,
111 | 1
112 | )
113 | summary = ta.getString(R.styleable.InputPreferenceView_preference_summary)
114 | ta.recycle()
115 |
116 | inputView.addTextChangedListener(afterTextChanged = {
117 | textListener?.accept(it ?: "")
118 | })
119 | }
120 |
121 | fun setOnTextChangedListener(listener: Consumer) {
122 | textListener = listener
123 | }
124 |
125 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/preference/OptionsPreferenceView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.preference
19 |
20 | import android.content.Context
21 | import android.util.AttributeSet
22 | import android.view.LayoutInflater
23 | import android.view.View
24 | import android.view.View.OnClickListener
25 | import android.widget.RadioButton
26 | import android.widget.RadioGroup
27 | import android.widget.RadioGroup.OnCheckedChangeListener
28 | import android.widget.TextView
29 | import androidx.constraintlayout.widget.ConstraintLayout
30 | import com.hhvvg.anydebug.R
31 |
32 | /**
33 | * Preference for options
34 | */
35 | class OptionsPreferenceView(
36 | context: Context,
37 | attrs: AttributeSet?,
38 | defStyleAttr: Int,
39 | defStyleRes: Int
40 | ) :
41 | ConstraintLayout(context, attrs, defStyleAttr, defStyleRes), OnClickListener {
42 |
43 | private var onRadioChangedListener: OnCheckedChangeListener? = null
44 | private val radioGroup: RadioGroup by lazy { findViewById(R.id.radio_group) }
45 |
46 | private val summaryView: TextView
47 | get() = findViewById(R.id.summary_view)
48 |
49 | private val titleView: TextView
50 | get() = findViewById(R.id.title_view)
51 |
52 | private val options: Array
53 |
54 | var selectedIndex: Int = -1
55 | set(value) {
56 | field = value
57 | summary = options[value]
58 | }
59 |
60 | var summary: CharSequence?
61 | get() = summaryView.text
62 | set(value) {
63 | summaryView.text = value
64 | }
65 |
66 | var title: CharSequence?
67 | get() = titleView.text
68 | set(value) {
69 | titleView.text = value
70 | }
71 |
72 | constructor(context: Context)
73 | : this(context, null)
74 |
75 | constructor(context: Context, attrs: AttributeSet?)
76 |
77 | : this(context, attrs, 0)
78 |
79 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
80 | : this(context, attrs, defStyleAttr, 0)
81 |
82 | init {
83 | inflate(context, R.layout.layout_options_preference_view, this)
84 | val ta = context.obtainStyledAttributes(attrs, R.styleable.OptionsPreferenceView)
85 | titleView.text = ta.getText(R.styleable.OptionsPreferenceView_preference_title)
86 | summaryView.text = ta.getText(R.styleable.OptionsPreferenceView_preference_summary)
87 | options = ta.getTextArray(R.styleable.OptionsPreferenceView_preference_options)
88 | ta.recycle()
89 | setOnClickListener(this)
90 | titleView.setOnClickListener(this)
91 | summaryView.setOnClickListener(this)
92 | }
93 |
94 | override fun onClick(v: View) {
95 | if (radioGroup.childCount == 0) {
96 | fillRadio()
97 | } else {
98 | radioGroup.removeAllViews()
99 | }
100 | }
101 |
102 | fun setOnCheckChangedListener(listener: OnCheckedChangeListener) {
103 | onRadioChangedListener = listener
104 | }
105 |
106 | private fun fillRadio() {
107 | options.forEachIndexed { index, charSequence ->
108 | val radio = LayoutInflater.from(context)
109 | .inflate(R.layout.layout_radio_button, this, false) as RadioButton
110 | radio.text = charSequence
111 | radio.id = index
112 | radio.isChecked = index == selectedIndex
113 | radioGroup.addView(radio)
114 | }
115 | radioGroup.setOnCheckedChangeListener { group, checkedId ->
116 | selectedIndex = checkedId
117 | onRadioChangedListener?.onCheckedChanged(group, checkedId)
118 | }
119 | }
120 |
121 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/preference/PreferenceView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.preference
19 |
20 | import android.content.Context
21 | import android.util.AttributeSet
22 | import android.widget.ImageView
23 | import android.widget.TextView
24 | import androidx.constraintlayout.widget.ConstraintLayout
25 | import androidx.core.view.isVisible
26 | import com.hhvvg.anydebug.R
27 |
28 | /**
29 | * Basic preference with a title and a summary
30 | */
31 | class PreferenceView(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
32 | ConstraintLayout(context, attrs, defStyleAttr, defStyleRes) {
33 |
34 | private val summaryView: TextView
35 | get() = findViewById(R.id.summary_view)
36 |
37 | private val titleView: TextView
38 | get() = findViewById(R.id.title_view)
39 |
40 | private val arrowImage: ImageView
41 | get() = findViewById(R.id.arrow)
42 |
43 | var summary: CharSequence?
44 | get() = summaryView.text
45 | set(value) {
46 | summaryView.text = value
47 | }
48 |
49 | var title: CharSequence?
50 | get() = titleView.text
51 | set(value) {
52 | titleView.text = value
53 | }
54 |
55 | constructor(context: Context)
56 | : this(context, null)
57 |
58 | constructor(context: Context, attrs: AttributeSet?)
59 |
60 | : this(context, attrs, 0)
61 |
62 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
63 | : this(context, attrs, defStyleAttr, 0)
64 |
65 | init {
66 | inflate(context, R.layout.layout_preference_view, this)
67 | val ta = context.obtainStyledAttributes(attrs, R.styleable.PreferenceView)
68 | titleView.text = ta.getText(R.styleable.PreferenceView_preference_title)
69 | summaryView.text = ta.getText(R.styleable.PreferenceView_preference_summary)
70 | arrowImage.isVisible = ta.getBoolean(R.styleable.PreferenceView_preference_arrow, false)
71 | ta.recycle()
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/remote/RemoteFactory.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.remote
19 |
20 | import android.content.Context
21 | import android.view.View
22 | import android.view.ViewGroup
23 |
24 | /**
25 | * Factory for invoking remote codes
26 | */
27 | interface RemoteFactory {
28 |
29 | /**
30 | * Inflate a layout from remote source
31 | */
32 | fun onInflateView(context: Context, name: String,
33 | root: ViewGroup? = null, attachToRoot: Boolean = false): View
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hhvvg/anydebug/view/remote/RemoteFactoryImpl.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) <2024>
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package com.hhvvg.anydebug.view.remote
19 |
20 | import android.annotation.SuppressLint
21 | import android.content.Context
22 | import android.view.LayoutInflater
23 | import android.view.View
24 | import android.view.ViewGroup
25 | import com.hhvvg.anydebug.BuildConfig.APPLICATION_ID
26 | import com.hhvvg.anydebug.utils.createModuleContext
27 | import com.hhvvg.anydebug.utils.moduleResources
28 | import com.hhvvg.anydebug.utils.topContext
29 |
30 | /**
31 | * Impl for RemoteFactory
32 | */
33 | class RemoteFactoryImpl : RemoteFactory {
34 |
35 | @SuppressLint("DiscouragedApi")
36 | override fun onInflateView(
37 | context: Context, name: String, root: ViewGroup?,
38 | attachToRoot: Boolean
39 | ): View {
40 | val layoutId = context.moduleResources.getIdentifier(name, "layout", APPLICATION_ID)
41 | val moduleContext = context.createModuleContext()
42 | val layout = context.moduleResources.getLayout(layoutId)
43 | if (layoutId > 0) {
44 | return LayoutInflater.from(moduleContext).inflate(layout, root, attachToRoot)
45 | }
46 | throw RuntimeException("Error inflating remote layout.")
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_radio.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/display_card_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/display_window_background.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/drawable_bottom_bar.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/fab_background.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_button_background.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_circle_up_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_right_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_up_24.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_24.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_primary_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_edit_pen_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_remove_circle_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_touch_app_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/search_input_background.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_selector_thumb.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/switch_selector_tracker.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_main_panel.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
25 |
30 |
31 |
36 |
37 |
44 |
45 |
54 |
55 |
56 |
57 |
58 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_view_properties.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
28 |
29 |
45 |
46 |
57 |
58 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_display_window.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
28 |
29 |
38 |
39 |
48 |
49 |
58 |
59 |
71 |
72 |
84 |
85 |
86 |
91 |
92 |
96 |
97 |
98 |
107 |
108 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_image_view_settings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
25 |
35 |
36 |
41 |
42 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_input_preference_view.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
26 |
27 |
38 |
39 |
47 |
48 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_options_preference_view.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
26 |
37 |
38 |
56 |
57 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_preference_view.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
27 |
28 |
39 |
40 |
57 |
58 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_preview_item.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_radio_button.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_text_view_settings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
25 |
35 |
36 |
41 |
42 |
49 |
50 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_title.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_view_property_item.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
25 |
32 |
33 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 | Visible
23 | Invisible
24 | Gone
25 |
26 |
27 |
28 | fitXY
29 | fitStart
30 | fitCenter
31 | fitEnd
32 | center
33 | centerCrop
34 | centerInside
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF000000
4 | #FFFFFFFF
5 |
6 | #00FFFFFF
7 | #F1F1F1
8 | #FFFFFF
9 | #216BDB
10 | #FF0000
11 | #101010
12 | #777777
13 | #F1F1F1
14 | #FFFFFF
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/configs.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 | 10dp
20 | 15dp
21 | 10dp
22 | 100dp
23 | 120dp
24 | 200dp
25 | 300dp
26 | 500dp
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AnyDebugV2
3 | EditControl
4 |
5 | TouchIndicator
6 | Hello world
7 | Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.Hello world.
8 | View
9 | Context
10 | Class
11 | Children
12 | Visibility
13 | Width
14 | Height
15 | Padding-L-T-R-B
16 | Margin-L-T-R-B
17 | -1 for match_parent, -2 for wrap_content
18 | Format: [left,top,right,bottom]
19 | TextView
20 | Text
21 | Notes: All span info will be lost.
22 | Text Size
23 | Max Lines
24 | ImageView
25 | Only supports http/https url now.
26 | Image Url
27 | Scale Type
28 | Properties
29 | About Project
30 | Scale X
31 | Scale Y
32 | Translation X
33 | Translation Y
34 | Translation Z
35 | Search Properties
36 | Alpha
37 | Scroll X
38 | Scroll Y
39 | Rotation
40 | Rotation X
41 | Rotation Y
42 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/com/hhvvg/anydebug/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.hhvvg.anydebug
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id("com.android.application") version "8.2.2" apply false
4 | id("org.jetbrains.kotlin.android") version "1.9.22" apply false
5 | id("com.android.library") version "8.2.2" apply false
6 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Feb 19 22:18:56 CST 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/raw/sample0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/raw/sample0.png
--------------------------------------------------------------------------------
/raw/sample1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/raw/sample1.png
--------------------------------------------------------------------------------
/raw/sample2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/raw/sample2.png
--------------------------------------------------------------------------------
/raw/sample3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gitofleonardo/AnyDebug/a10c050691aedb9ed7a69c51548397f7de3e7273/raw/sample3.png
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | gradlePluginPortal()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | maven("https://jitpack.io")
14 | // 作为 Xposed 模块使用务必添加,其它情况可选
15 | maven("https://api.xposed.info/" )
16 | // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
17 | maven( "https://s01.oss.sonatype.org/content/repositories/releases/" )
18 | }
19 | }
20 |
21 | rootProject.name = "AnyDebugV2"
22 | include(":app")
23 |
--------------------------------------------------------------------------------