├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── copyright │ ├── git.xml │ └── profiles_settings.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── README_CN.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hhvvg │ │ └── anydebug │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── hhvvg │ │ │ └── anydebug │ │ │ ├── App.kt │ │ │ ├── InjectHookEntry.kt │ │ │ ├── Instance.kt │ │ │ ├── MainActivity.kt │ │ │ ├── Module.kt │ │ │ ├── ModuleContext.kt │ │ │ ├── TileControlService.kt │ │ │ ├── configurations │ │ │ ├── ConfigChangedReceiver.kt │ │ │ └── ModuleSettings.kt │ │ │ ├── fragment │ │ │ ├── ActivitylessFragmentContainer.kt │ │ │ ├── ActivitylessFragmentManager.kt │ │ │ ├── MainPanelFragment.kt │ │ │ └── ViewPropertiesFragment.kt │ │ │ ├── instances │ │ │ └── ActivityInstance.kt │ │ │ ├── modules │ │ │ └── ActivityModule.kt │ │ │ ├── utils │ │ │ ├── Animations.kt │ │ │ ├── Extensions.kt │ │ │ ├── Logger.kt │ │ │ ├── OverScroll.java │ │ │ ├── SpringAnimationBuilder.java │ │ │ └── ViewExportedProperty.kt │ │ │ └── view │ │ │ ├── ActivityPreviewWindow.kt │ │ │ ├── DecorView.kt │ │ │ ├── OnBackInvokedCallback.kt │ │ │ ├── PreviewAdapter.kt │ │ │ ├── PreviewList.kt │ │ │ ├── PreviewView.kt │ │ │ ├── SettingsFactory.kt │ │ │ ├── SettingsFactoryManager.kt │ │ │ ├── WindowClient.kt │ │ │ ├── WindowController.kt │ │ │ ├── factory │ │ │ ├── BasicViewFactory.kt │ │ │ ├── ImageViewFactory.kt │ │ │ ├── TextViewFactory.kt │ │ │ └── command │ │ │ │ ├── AlphaCommand.kt │ │ │ │ ├── BaseCommand.kt │ │ │ │ ├── FactoryCommand.kt │ │ │ │ ├── HeightCommand.kt │ │ │ │ ├── ImageScaleTypeCommand.kt │ │ │ │ ├── ImageUrlCommand.kt │ │ │ │ ├── MarginLtrbCommand.kt │ │ │ │ ├── PaddingLtrbCommand.kt │ │ │ │ ├── RotationCommand.kt │ │ │ │ ├── RotationXCommand.kt │ │ │ │ ├── RotationYCommand.kt │ │ │ │ ├── ScaleXCommand.kt │ │ │ │ ├── ScaleYCommand.kt │ │ │ │ ├── ScrollXCommand.kt │ │ │ │ ├── ScrollYCommand.kt │ │ │ │ ├── TextCommand.kt │ │ │ │ ├── TextMaxLinesCommand.kt │ │ │ │ ├── TextSizeCommand.kt │ │ │ │ ├── TranXCommand.kt │ │ │ │ ├── TranYCommand.kt │ │ │ │ ├── TranZCommand.kt │ │ │ │ ├── VisibilityCommand.kt │ │ │ │ └── WidthCommand.kt │ │ │ ├── preference │ │ │ ├── InputPreferenceView.kt │ │ │ ├── OptionsPreferenceView.kt │ │ │ └── PreferenceView.kt │ │ │ └── remote │ │ │ ├── RemoteFactory.kt │ │ │ └── RemoteFactoryImpl.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── button_radio.xml │ │ ├── display_card_background.xml │ │ ├── display_window_background.xml │ │ ├── drawable_bottom_bar.xml │ │ ├── fab_background.xml │ │ ├── floating_button_background.xml │ │ ├── ic_arrow_circle_up_24.xml │ │ ├── ic_arrow_right_24.xml │ │ ├── ic_arrow_up_24.xml │ │ ├── ic_check_24.xml │ │ ├── ic_check_primary_24.xml │ │ ├── ic_edit_pen_24.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_remove_circle_24.xml │ │ ├── ic_search_24.xml │ │ ├── ic_touch_app_24.xml │ │ ├── search_input_background.xml │ │ ├── switch_selector_thumb.xml │ │ └── switch_selector_tracker.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_main_panel.xml │ │ ├── fragment_view_properties.xml │ │ ├── layout_basic_view_settings.xml │ │ ├── layout_display_window.xml │ │ ├── layout_image_view_settings.xml │ │ ├── layout_input_preference_view.xml │ │ ├── layout_options_preference_view.xml │ │ ├── layout_preference_view.xml │ │ ├── layout_preview_item.xml │ │ ├── layout_radio_button.xml │ │ ├── layout_text_view_settings.xml │ │ ├── layout_title.xml │ │ └── layout_view_property_item.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── configs.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── hhvvg │ └── anydebug │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── raw ├── sample0.png ├── sample1.png ├── sample2.png └── sample3.png └── settings.gradle.kts /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | /.idea/.name 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | /app/src/main/assets/xposed_init 18 | /app/src/main/resources/META-INF/yukihookapi_init 19 | /app/release/* 20 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | GETTERS_AND_SETTERS 11 | KEEP 12 | 13 | 14 | OVERRIDDEN_METHODS 15 | BY_NAME 16 | 17 | 18 | DEPENDENT_METHODS 19 | BREADTH_FIRST 20 | 21 | 22 | 23 | 24 | 25 | 137 | 138 | 141 | 142 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/git.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AnyDebug 2 | 3 | English | [简体中文](README_CN.md) 4 | 5 | [![GitHub all releases](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.hhvvg.anydebug/total?label=Downloads)](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 | | ![sample0.png](raw/sample0.png) | ![sample1.png](raw/sample1.png) | ![sample1.png](raw/sample2.png) | ![sample1.png](raw/sample3.png) | 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 | [![Stargazers over time](https://starchart.cc/gitofleonardo/AnyDebug.svg)](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 | [![GitHub all releases](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.hhvvg.anydebug/total?label=Downloads)](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 | | ![sample0.png](raw/sample0.png) | ![sample1.png](raw/sample1.png) | ![sample1.png](raw/sample2.png) | ![sample1.png](raw/sample3.png) | 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 |