├── .idea ├── .name ├── .gitignore ├── compiler.xml ├── kotlinc.xml ├── vcs.xml ├── AndroidProjectSystem.xml ├── migrations.xml ├── deploymentTargetDropDown.xml ├── deploymentTargetSelector.xml ├── gradle.xml ├── runConfigurations.xml ├── appInsightsSettings.xml └── inspectionProfiles │ └── Project_Default.xml ├── app ├── .gitignore ├── src │ ├── main │ │ ├── assets │ │ │ ├── xposed_init │ │ │ ├── www │ │ │ │ ├── src │ │ │ │ │ ├── env.js │ │ │ │ │ ├── defaults.js │ │ │ │ │ ├── languages │ │ │ │ │ │ ├── javascript.mjs │ │ │ │ │ │ ├── css.mjs │ │ │ │ │ │ └── markup.mjs │ │ │ │ │ ├── prism-live.js │ │ │ │ │ ├── dom.js │ │ │ │ │ ├── util.js │ │ │ │ │ └── editing.js │ │ │ │ ├── index.js │ │ │ │ ├── prism-live.css │ │ │ │ └── prism.css │ │ │ └── css_editor.html │ │ ├── res │ │ │ ├── mipmap │ │ │ │ └── launcher.png │ │ │ ├── drawable │ │ │ │ ├── ic_reload.png │ │ │ │ ├── ic_home_black_24dp.xml │ │ │ │ ├── border_background.xml │ │ │ │ ├── ic_dashboard_black_24dp.xml │ │ │ │ ├── diagonal_line.xml │ │ │ │ ├── refresh.xml │ │ │ │ ├── ic_notifications_black_24dp.xml │ │ │ │ ├── download.xml │ │ │ │ ├── about.xml │ │ │ │ ├── ic_media.xml │ │ │ │ ├── ic_privacy.xml │ │ │ │ ├── eye_enabled.xml │ │ │ │ ├── deleted.xml │ │ │ │ ├── online.xml │ │ │ │ ├── ic_telegram.xml │ │ │ │ ├── ic_github.xml │ │ │ │ ├── edit2.xml │ │ │ │ ├── ic_baseline_arrow_back_24.xml │ │ │ │ ├── eye_disabled.xml │ │ │ │ ├── preview_eye.xml │ │ │ │ ├── ic_round_warning_24.xml │ │ │ │ ├── ic_round_error_outline_24.xml │ │ │ │ ├── ic_round_check_circle_24.xml │ │ │ │ ├── ic_round_update_24.xml │ │ │ │ ├── ic_launcher_foreground.xml │ │ │ │ ├── ic_round_bug_report_24.xml │ │ │ │ ├── ic_round_settings_24.xml │ │ │ │ ├── camera.xml │ │ │ │ ├── ic_donate.xml │ │ │ │ ├── ic_general.xml │ │ │ │ ├── ghost_enabled.xml │ │ │ │ ├── edit.xml │ │ │ │ ├── ghost_disabled.xml │ │ │ │ ├── airplane_enabled.xml │ │ │ │ └── airplane_disabled.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── launcher.png │ │ │ ├── values │ │ │ │ ├── theme_customs.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── integer.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── themes_overlay.xml │ │ │ │ ├── themes.xml │ │ │ │ └── styles.xml │ │ │ ├── values-night │ │ │ │ ├── theme.xml │ │ │ │ └── colors.xml │ │ │ ├── menu │ │ │ │ ├── header_menu.xml │ │ │ │ ├── css_editor_menu.xml │ │ │ │ └── bottom_nav_menu.xml │ │ │ ├── values-zh │ │ │ │ └── arrays.xml │ │ │ ├── layout │ │ │ │ ├── list_item_suggestion.xml │ │ │ │ ├── pref_float_seekbar.xml │ │ │ │ ├── base_fragment.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── preference_theme.xml │ │ │ │ ├── activity_contact_picker.xml │ │ │ │ └── item_folder.xml │ │ │ └── xml │ │ │ │ ├── fragment_general.xml │ │ │ │ └── preference_general_home.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── wmods │ │ │ │ └── wppenhacer │ │ │ │ ├── xposed │ │ │ │ ├── utils │ │ │ │ │ ├── HKDFv3.java │ │ │ │ │ ├── MimeTypeUtils.java │ │ │ │ │ ├── RunCatchingUtil.java │ │ │ │ │ ├── TimeoutUtil.java │ │ │ │ │ └── HKDF.java │ │ │ │ ├── bridge │ │ │ │ │ ├── client │ │ │ │ │ │ └── BaseClient.java │ │ │ │ │ ├── service │ │ │ │ │ │ ├── BridgeService.java │ │ │ │ │ │ └── HookBinder.java │ │ │ │ │ └── providers │ │ │ │ │ │ └── HookProvider.java │ │ │ │ ├── features │ │ │ │ │ ├── others │ │ │ │ │ │ ├── DebugFeature.java │ │ │ │ │ │ ├── ChatFilters.java │ │ │ │ │ │ └── CopyStatus.java │ │ │ │ │ ├── privacy │ │ │ │ │ │ ├── DndMode.java │ │ │ │ │ │ ├── FreezeLastSeen.java │ │ │ │ │ │ ├── ViewOnce.java │ │ │ │ │ │ ├── TypingPrivacy.java │ │ │ │ │ │ ├── AntiWa.java │ │ │ │ │ │ └── TagMessage.java │ │ │ │ │ ├── customization │ │ │ │ │ │ └── CustomTime.java │ │ │ │ │ ├── general │ │ │ │ │ │ ├── ShareLimit.java │ │ │ │ │ │ └── DeleteStatus.java │ │ │ │ │ └── media │ │ │ │ │ │ └── DownloadProfile.java │ │ │ │ ├── AntiUpdater.java │ │ │ │ └── core │ │ │ │ │ ├── Feature.java │ │ │ │ │ ├── WaCallback.java │ │ │ │ │ ├── components │ │ │ │ │ └── WaContactWpp.java │ │ │ │ │ └── db │ │ │ │ │ └── DelMessageStore.java │ │ │ │ ├── receivers │ │ │ │ └── WAFReceiver.java │ │ │ │ ├── views │ │ │ │ ├── NoScrollListView.java │ │ │ │ ├── dialog │ │ │ │ │ └── BottomDialogWpp.java │ │ │ │ └── IGStatusView.java │ │ │ │ ├── activities │ │ │ │ ├── base │ │ │ │ │ └── BaseActivity.java │ │ │ │ ├── ForceStartActivity.java │ │ │ │ └── AboutActivity.java │ │ │ │ ├── ui │ │ │ │ └── fragments │ │ │ │ │ ├── CustomizationFragment.java │ │ │ │ │ ├── MediaFragment.java │ │ │ │ │ ├── PrivacyFragment.java │ │ │ │ │ └── GeneralFragment.java │ │ │ │ ├── listeners │ │ │ │ └── OnMultiClickListener.java │ │ │ │ ├── adapter │ │ │ │ ├── MainPagerAdapter.java │ │ │ │ └── MessageAdapter.java │ │ │ │ ├── preference │ │ │ │ └── LimitedEditTextPreference.java │ │ │ │ ├── utils │ │ │ │ ├── StateListDrawableCompact.java │ │ │ │ ├── IColors.java │ │ │ │ ├── FilePicker.java │ │ │ │ └── ColorReplacement.java │ │ │ │ └── UpdateChecker.java │ │ └── aidl │ │ │ └── com │ │ │ └── wmods │ │ │ └── wppenhacer │ │ │ └── xposed │ │ │ └── bridge │ │ │ └── WaeIIFace.aidl │ └── business │ │ └── res │ │ └── values │ │ └── arrays.xml └── proguard-rules.pro ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── changelog.txt ├── .gitignore ├── .claude └── settings.local.json ├── crowdin.yml ├── .github ├── dependabot.yml └── workflows │ └── android.yml ├── settings.gradle.kts ├── gradle.properties └── gradlew.bat /.idea/.name: -------------------------------------------------------------------------------- 1 | Wa Enhancer -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.wmods.wppenhacer.WppXposed -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | /CrowdinSettingsPlugin.xml 5 | -------------------------------------------------------------------------------- /app/src/main/assets/www/src/env.js: -------------------------------------------------------------------------------- 1 | export const superKey = navigator.platform.indexOf("Mac") === 0? "metaKey" : "ctrlKey"; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/assets/www/src/defaults.js: -------------------------------------------------------------------------------- 1 | export const indent = "\t"; 2 | 3 | export const caretIndicator = /(^|[^\\])\$(\d+)/g; -------------------------------------------------------------------------------- /app/src/main/res/mipmap/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/drawable/ic_reload.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap-hdpi/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap-mdpi/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap-xhdpi/launcher.png -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | [WHATSAPP] 2 | * Added support for version 2.25.35.XX (Thanks to frknkrc44) 3 | * Added support for version 2.25.36.XX 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap-xxhdpi/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev4Mod/WaEnhancer/HEAD/app/src/main/res/mipmap-xxxhdpi/launcher.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | key.jks 12 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/theme_customs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 | 21 | 22 | CSS Editor 23 | 24 | 25 | 26 | 28 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /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 22 | -dontwarn * 23 | 24 | -keepclasseswithmembers class com.wmods.** { 25 | *; 26 | } 27 | 28 | -keepclasseswithmembernames class com.wmods.** 29 | 30 | -keepclasseswithmembers class cz.vutbr.** { 31 | *; 32 | } 33 | 34 | -keepclasseswithmembers class com.assemblyai.api.** { 35 | *; 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/features/privacy/DndMode.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.features.privacy; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.wmods.wppenhacer.xposed.core.Feature; 6 | import com.wmods.wppenhacer.xposed.core.WppCore; 7 | import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator; 8 | 9 | import de.robv.android.xposed.XC_MethodReplacement; 10 | import de.robv.android.xposed.XSharedPreferences; 11 | import de.robv.android.xposed.XposedBridge; 12 | 13 | public class DndMode extends Feature { 14 | public DndMode(ClassLoader loader, XSharedPreferences preferences) { 15 | super(loader, preferences); 16 | } 17 | 18 | @Override 19 | public void doHook() throws Exception { 20 | if (!WppCore.getPrivBoolean("dndmode",false)) return; 21 | var dndMethod = Unobfuscator.loadDndModeMethod(classLoader); 22 | logDebug(Unobfuscator.getMethodDescriptor(dndMethod)); 23 | XposedBridge.hookMethod(dndMethod, XC_MethodReplacement.DO_NOTHING); 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public String getPluginName() { 29 | return "Dnd Mode"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_github.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit2.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/listeners/OnMultiClickListener.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.listeners; 2 | 3 | import android.view.View; 4 | 5 | public abstract class OnMultiClickListener implements View.OnClickListener { 6 | 7 | private final int targetClicks; 8 | private final long delay; 9 | private long lastClick = 0; 10 | private int clicks = 0; 11 | 12 | public OnMultiClickListener(int targetClicks, long delay) { 13 | if (targetClicks < 2) { 14 | throw new IllegalArgumentException("targetClicks must be greater than 1"); 15 | } 16 | this.targetClicks = targetClicks; 17 | this.delay = delay; 18 | } 19 | 20 | @Override 21 | public void onClick(View v) { 22 | if (this.lastClick == 0 || System.currentTimeMillis() - this.lastClick < this.delay) { 23 | this.lastClick = System.currentTimeMillis(); 24 | this.clicks++; 25 | } else { 26 | this.lastClick = 0; 27 | this.clicks = 0; 28 | } 29 | if (this.clicks >= this.targetClicks) { 30 | this.clicks = 0; 31 | this.lastClick = 0; 32 | onMultiClick(v); 33 | } 34 | } 35 | 36 | abstract public void onMultiClick(View v); 37 | 38 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @color/abc_primary_text_material_dark 4 | 5 | @color/abc_primary_text_material_light 6 | 7 | #FFFFFF 8 | #F48FB1 9 | 10 | @color/material_yellow_A400 11 | @color/material_green_A400 12 | @color/material_red_A400 13 | 14 | #282C34 15 | #61aeee 16 | #d19a66 17 | #d19a66 18 | #56b6c2 19 | #757875 20 | #FFFFFF 21 | #cc7832 22 | #e0c46c 23 | @color/background_light 24 | #24D52B 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes_overlay.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 26 | 27 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_arrow_back_24.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/AntiUpdater.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed; 2 | 3 | import android.content.pm.PackageInstaller; 4 | 5 | import com.wmods.wppenhacer.xposed.core.FeatureLoader; 6 | 7 | import java.io.IOException; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XposedBridge; 11 | import de.robv.android.xposed.XposedHelpers; 12 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 13 | 14 | public class AntiUpdater { 15 | 16 | public static void hookSession(XC_LoadPackage.LoadPackageParam lpparam) { 17 | if (lpparam.packageName.equals("android")) return; 18 | XposedBridge.hookAllMethods(PackageInstaller.class, "createSession", new XC_MethodHook() { 19 | @Override 20 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 21 | var session = (PackageInstaller.SessionParams) param.args[0]; 22 | var packageName = XposedHelpers.getObjectField(session, "mPackageName"); 23 | if (packageName.equals(FeatureLoader.PACKAGE_WPP) || packageName.equals(FeatureLoader.PACKAGE_BUSINESS)) { 24 | param.setThrowable(new IOException("UPDATE LOCKED BY WAENHANCER")); 25 | } 26 | } 27 | }); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/adapter/MainPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.adapter; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.fragment.app.Fragment; 5 | import androidx.fragment.app.FragmentActivity; 6 | import androidx.viewpager2.adapter.FragmentStateAdapter; 7 | 8 | import com.wmods.wppenhacer.ui.fragments.CustomizationFragment; 9 | import com.wmods.wppenhacer.ui.fragments.GeneralFragment; 10 | import com.wmods.wppenhacer.ui.fragments.HomeFragment; 11 | import com.wmods.wppenhacer.ui.fragments.MediaFragment; 12 | import com.wmods.wppenhacer.ui.fragments.PrivacyFragment; 13 | 14 | public class MainPagerAdapter extends FragmentStateAdapter { 15 | 16 | public MainPagerAdapter(@NonNull FragmentActivity fragmentActivity) { 17 | super(fragmentActivity); 18 | } 19 | 20 | @NonNull 21 | @Override 22 | public Fragment createFragment(int position) { 23 | return switch (position) { 24 | case 0 -> new GeneralFragment(); 25 | case 1 -> new PrivacyFragment(); 26 | case 3 -> new MediaFragment(); 27 | case 4 -> new CustomizationFragment(); 28 | default -> new HomeFragment(); 29 | }; 30 | } 31 | 32 | @Override 33 | public int getItemCount() { 34 | return 5; // Number of fragments 35 | } 36 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. For more details, visit 12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects 13 | org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true 22 | android.nonFinalResIds=false 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/eye_disabled.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/views/dialog/BottomDialogWpp.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.views.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.graphics.Color; 5 | import android.view.View; 6 | import android.view.WindowManager; 7 | 8 | import androidx.annotation.NonNull; 9 | 10 | import com.wmods.wppenhacer.xposed.utils.Utils; 11 | 12 | public class BottomDialogWpp { 13 | 14 | private final Dialog dialog; 15 | 16 | public BottomDialogWpp(@NonNull Dialog dialog) { 17 | this.dialog = dialog; 18 | } 19 | 20 | public void dismissDialog() { 21 | dialog.dismiss(); 22 | } 23 | 24 | public void showDialog() { 25 | dialog.show(); 26 | if (dialog.getWindow() != null) { 27 | dialog.getWindow().setBackgroundDrawable(null); 28 | dialog.getWindow().setDimAmount(0); 29 | var view = dialog.getWindow().getDecorView(); 30 | view.findViewById(Utils.getID("design_bottom_sheet", "id")).setBackgroundColor(Color.TRANSPARENT); 31 | dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); 32 | } 33 | } 34 | 35 | public void setContentView(View view) { 36 | dialog.setContentView(view); 37 | } 38 | 39 | 40 | public void setCanceledOnTouchOutside(boolean b) { 41 | dialog.setCanceledOnTouchOutside(b); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/preview_eye.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_warning_24.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_error_outline_24.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_check_circle_24.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/utils/RunCatchingUtil.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.utils; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Supplier; 5 | 6 | public class RunCatchingUtil { 7 | 8 | public static Result runCatching(Supplier block) { 9 | try { 10 | return Result.success(block.get()); 11 | } catch (Throwable e) { 12 | return Result.failure(e); 13 | } 14 | } 15 | 16 | public static class Result { 17 | private final T value; 18 | private final Throwable exception; 19 | 20 | private Result(T value, Throwable exception) { 21 | this.value = value; 22 | this.exception = exception; 23 | } 24 | 25 | public static Result success(T value) { 26 | return new Result<>(value, null); 27 | } 28 | 29 | public static Result failure(Throwable exception) { 30 | return new Result<>(null, exception); 31 | } 32 | 33 | public Optional getValue() { 34 | return Optional.ofNullable(value); 35 | } 36 | 37 | public Optional getException() { 38 | return Optional.ofNullable(exception); 39 | } 40 | 41 | public boolean isSuccess() { 42 | return exception == null; 43 | } 44 | 45 | public boolean isFailure() { 46 | return exception != null; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/features/privacy/FreezeLastSeen.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.features.privacy; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.wmods.wppenhacer.xposed.core.Feature; 6 | import com.wmods.wppenhacer.xposed.core.WppCore; 7 | import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator; 8 | 9 | import de.robv.android.xposed.XC_MethodReplacement; 10 | import de.robv.android.xposed.XSharedPreferences; 11 | import de.robv.android.xposed.XposedBridge; 12 | 13 | public class FreezeLastSeen extends Feature { 14 | public FreezeLastSeen(ClassLoader loader, XSharedPreferences preferences) { 15 | super(loader, preferences); 16 | } 17 | 18 | @Override 19 | public void doHook() throws Exception { 20 | var freezeLastSeen = prefs.getBoolean("freezelastseen", false); 21 | var freezeLastSeenOption = WppCore.getPrivBoolean("freezelastseen", false); 22 | var ghostmode = WppCore.getPrivBoolean("ghostmode", false) && prefs.getBoolean("ghostmode", false); 23 | 24 | if (freezeLastSeen || freezeLastSeenOption || ghostmode) { 25 | var method = Unobfuscator.loadFreezeSeenMethod(classLoader); 26 | logDebug(Unobfuscator.getMethodDescriptor(method)); 27 | XposedBridge.hookMethod(method, XC_MethodReplacement.DO_NOTHING); 28 | } 29 | } 30 | 31 | @NonNull 32 | @Override 33 | public String getPluginName() { 34 | return "Freeze Last Seen"; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/assets/www/src/util.js: -------------------------------------------------------------------------------- 1 | import $ from "https://v2.blissfuljs.com/src/$.js"; 2 | import $$ from "https://v2.blissfuljs.com/src/$$.js"; 3 | import create from "https://v2.blissfuljs.com/src/dom/create.js"; 4 | import bind from "https://v2.blissfuljs.com/src/events/bind.js"; 5 | import load from "https://v2.blissfuljs.com/src/async/load.js"; 6 | 7 | Object.assign($, {create, bind, load}); 8 | export { $, $$, create, bind, load}; 9 | 10 | /** 11 | * Utility for regexp construction 12 | * @param {*} s 13 | * @returns 14 | */ 15 | let escape = s => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); 16 | let _regexp = (flags, strings, ...values) => { 17 | let pattern = strings[0] + values.map((v, i) => escape(v) + strings[i + 1]).join(""); 18 | return RegExp(pattern, flags); 19 | }; 20 | let cache = {}; 21 | 22 | export const regexp = new Proxy(_regexp.bind(this, ""), { 23 | get: (t, property) => { 24 | return t[property] || cache[property] 25 | || (cache[property] = _regexp.bind(this, property)); 26 | } 27 | }); 28 | 29 | export function loadLanguages (ids, PrismLive) { 30 | ids = Array.isArray(ids) ? ids : ids.split(/,/); 31 | return ids.map(c => import(`./languages/${c}.mjs`).then(m => { 32 | if (m.default) { 33 | PrismLive.registerLanguage(m.default.id, m.default); 34 | } 35 | else { 36 | // Many languages 37 | for (let id in m) { 38 | if (PrismLive.languages[id]) { 39 | // Already registered, augment it 40 | Object.assign(PrismLive.languages[id], m[id]); 41 | } 42 | else { 43 | PrismLive.registerLanguage(id, m[id]); 44 | } 45 | 46 | } 47 | } 48 | })); 49 | } -------------------------------------------------------------------------------- /app/src/main/assets/www/prism-live.css: -------------------------------------------------------------------------------- 1 | div.prism-live { 2 | position: relative; 3 | box-sizing: border-box; 4 | display: flex; 5 | flex-flow: column; 6 | } 7 | 8 | textarea.prism-live, 9 | pre.prism-live { 10 | padding: .2rem .5rem; 11 | box-sizing: border-box; 12 | margin: 0; 13 | } 14 | 15 | textarea.prism-live { 16 | position: absolute; 17 | top: 0; 18 | right: 0; 19 | width: 100%; 20 | height: 100%; 21 | z-index: 1; 22 | color: transparent; 23 | /* color: hsla(0,0%,50%,.4); */ 24 | cursor: text; 25 | white-space: pre; 26 | border: 0; 27 | outline: none; 28 | background: transparent; 29 | resize: none; 30 | --selection-background: hsl(320, 80%, 25%); 31 | --selection-color: hsla(0, 0%, 100%, .8); 32 | } 33 | 34 | @supports (not (caret-color: black)) and (-webkit-text-fill-color: black) { 35 | textarea.prism-live { 36 | color: inherit; 37 | -webkit-text-fill-color: transparent; 38 | } 39 | } 40 | 41 | /* Setting specific colors is needed 42 | * because otherwise Firefox shows blank text */ 43 | textarea.prism-live::-moz-selection { 44 | background: var(--selection-background); 45 | color: var(--selection-color); 46 | } 47 | 48 | textarea.prism-live::selection { 49 | background: var(--selection-background); 50 | color: var(--selection-color); 51 | } 52 | 53 | pre.prism-live { 54 | flex: 1; 55 | position: relative; 56 | pointer-events: none; 57 | overflow: hidden; 58 | max-height: 100%; 59 | --scrollbar-width: 17px; 60 | padding-bottom: var(--scrollbar-width); 61 | padding-right: var(--scrollbar-width); 62 | } 63 | 64 | pre.prism-live > code:empty::before { 65 | content: " " 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/activities/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.activities; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import com.wmods.wppenhacer.activities.base.BaseActivity; 10 | import com.wmods.wppenhacer.databinding.ActivityAboutBinding; 11 | 12 | public class AboutActivity extends BaseActivity { 13 | 14 | 15 | @Override 16 | protected void onCreate(@Nullable Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | com.wmods.wppenhacer.databinding.ActivityAboutBinding binding = ActivityAboutBinding.inflate(getLayoutInflater()); 19 | setContentView(binding.getRoot()); 20 | binding.btnTelegram.setOnClickListener(v -> { 21 | Intent intent = new Intent(); 22 | intent.setAction(Intent.ACTION_VIEW); 23 | intent.setData(Uri.parse("https://t.me/waenhancer")); 24 | startActivity(intent); 25 | }); 26 | binding.btnGithub.setOnClickListener(view -> { 27 | Intent intent = new Intent(); 28 | intent.setAction(Intent.ACTION_VIEW); 29 | intent.setData(Uri.parse("https://github.com/Dev4Mod/waenhancer")); 30 | startActivity(intent); 31 | }); 32 | binding.btnDonate.setOnClickListener(view -> { 33 | Intent intent = new Intent(); 34 | intent.setAction(Intent.ACTION_VIEW); 35 | intent.setData(Uri.parse("https://coindrop.to/dev4mod")); 36 | startActivity(intent); 37 | }); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/preference/LimitedEditTextPreference.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.preference; 2 | 3 | import android.content.Context; 4 | import android.text.InputFilter; 5 | import android.util.AttributeSet; 6 | import android.widget.EditText; 7 | 8 | import androidx.preference.EditTextPreference; 9 | 10 | import com.wmods.wppenhacer.R; 11 | 12 | public class LimitedEditTextPreference extends EditTextPreference { 13 | 14 | private static final int DEFAULT_MAX_LENGTH = 10; // Limite padrão de caracteres 15 | private int maxLength; 16 | 17 | public LimitedEditTextPreference(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | init(attrs); 20 | } 21 | 22 | public LimitedEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) { 23 | super(context, attrs, defStyleAttr); 24 | init(attrs); 25 | } 26 | 27 | private void init(AttributeSet attrs) { 28 | if (attrs != null) { 29 | var a = getContext().obtainStyledAttributes(attrs, com.wmods.wppenhacer.R.styleable.LimitedEditTextPreference); 30 | maxLength = a.getInt(R.styleable.LimitedEditTextPreference_maxLength, DEFAULT_MAX_LENGTH); 31 | a.recycle(); 32 | } else { 33 | maxLength = DEFAULT_MAX_LENGTH; 34 | } 35 | 36 | setOnBindEditTextListener(this::setMaxLength); 37 | } 38 | 39 | private void setMaxLength(EditText editText) { 40 | InputFilter[] filters = new InputFilter[1]; 41 | filters[0] = new InputFilter.LengthFilter(maxLength); 42 | editText.setFilters(filters); 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/res/xml/fragment_general.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 18 | 19 | 22 | 23 | 27 | 28 | 32 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/features/privacy/ViewOnce.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.features.privacy; 2 | 3 | 4 | import androidx.annotation.NonNull; 5 | 6 | import com.wmods.wppenhacer.xposed.core.Feature; 7 | import com.wmods.wppenhacer.xposed.core.components.FMessageWpp; 8 | import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator; 9 | 10 | import de.robv.android.xposed.XC_MethodHook; 11 | import de.robv.android.xposed.XSharedPreferences; 12 | import de.robv.android.xposed.XposedBridge; 13 | 14 | public class ViewOnce extends Feature { 15 | 16 | public ViewOnce(ClassLoader loader, XSharedPreferences preferences) { 17 | super(loader, preferences); 18 | } 19 | 20 | @Override 21 | public void doHook() throws Exception { 22 | if (!prefs.getBoolean("viewonce", false)) return; 23 | 24 | var methods = Unobfuscator.loadViewOnceMethod(classLoader); 25 | 26 | for (var method : methods) { 27 | logDebug(Unobfuscator.getMethodDescriptor(method)); 28 | XposedBridge.hookMethod(method, new XC_MethodHook() { 29 | @Override 30 | protected void beforeHookedMethod(MethodHookParam param) { 31 | int returnValue = (int) param.args[0]; 32 | var fMessage = new FMessageWpp(param.thisObject); 33 | if (returnValue == 1 && !fMessage.getKey().isFromMe) { 34 | param.args[0] = 0; 35 | } 36 | } 37 | }); 38 | } 39 | } 40 | 41 | @NonNull 42 | @Override 43 | public String getPluginName() { 44 | return "View Once"; 45 | } 46 | 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/utils/TimeoutUtil.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.utils; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.ScheduledThreadPoolExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class TimeoutUtil { 9 | 10 | private static final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); 11 | 12 | /** 13 | * Adds a timeout to a CompletableFuture 14 | * @param future The original CompletableFuture 15 | * @param timeout Timeout duration 16 | * @param unit Time unit 17 | * @param Type of the result 18 | * @return New CompletableFuture with timeout 19 | */ 20 | public static CompletableFuture withTimeout(CompletableFuture future, long timeout, TimeUnit unit) { 21 | CompletableFuture timeoutFuture = new CompletableFuture<>(); 22 | 23 | // Schedules a task to complete the future with an exception after the timeout 24 | scheduler.schedule(() -> { 25 | timeoutFuture.completeExceptionally( 26 | new java.util.concurrent.TimeoutException("Operation exceeded the time limit of " + timeout + " " + unit)); 27 | }, timeout, unit); 28 | 29 | // Returns the first to complete (either the original or the timeout) 30 | return CompletableFuture.anyOf(future, timeoutFuture) 31 | .thenApply(result -> (T) result) 32 | .exceptionally(ex -> { 33 | // Cancels the original future if a timeout occurs 34 | future.cancel(true); 35 | throw new RuntimeException(ex); 36 | }); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_update_24.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wmods/wppenhacer/xposed/bridge/service/HookBinder.java: -------------------------------------------------------------------------------- 1 | package com.wmods.wppenhacer.xposed.bridge.service; 2 | 3 | import android.os.ParcelFileDescriptor; 4 | import android.os.RemoteException; 5 | 6 | import com.wmods.wppenhacer.xposed.bridge.WaeIIFace; 7 | 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class HookBinder extends WaeIIFace.Stub { 15 | 16 | private static HookBinder mInstance; 17 | 18 | public static HookBinder getInstance() { 19 | if (mInstance == null) { 20 | mInstance = new HookBinder(); 21 | } 22 | return mInstance; 23 | } 24 | 25 | @Override 26 | public ParcelFileDescriptor openFile(String path, boolean create) throws RemoteException { 27 | File file = new File(path); 28 | if (!file.exists() && create) { 29 | try { 30 | file.createNewFile(); 31 | } catch (Exception ignored) { 32 | return null; 33 | } 34 | } 35 | try { 36 | return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE); 37 | } catch (FileNotFoundException e) { 38 | return null; 39 | } 40 | } 41 | 42 | @Override 43 | public boolean createDir(String path) throws RemoteException { 44 | File file = new File(path); 45 | return file.mkdirs(); 46 | } 47 | 48 | @Override 49 | public List listFiles(String path) throws RemoteException { 50 | var files = new File(path).listFiles(); 51 | if (files == null) { 52 | return Collections.emptyList(); 53 | } 54 | return Arrays.asList(files); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 17 | 18 | 19 | 20 | 24 | 25 | 34 | 35 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/assets/www/src/languages/markup.mjs: -------------------------------------------------------------------------------- 1 | const selfClosing = ["input", "img", "link", "meta", "base", "br", "hr"]; 2 | 3 | export default { 4 | id: "markup", 5 | comments: { 6 | multiline: [""] 7 | }, 8 | selfClosing, 9 | snippets: { 10 | "submit": '', 11 | custom: function (selector) { 12 | var isName = /^[\w:-]+$/.test(selector); 13 | var isSnippet = isName || selector.match(/^[.#\w:-]+(\{.+?\})?(\*\d+)?$/); 14 | var node = this.getNode(); 15 | var inTag = node.parentNode.closest(".token.tag"); 16 | 17 | if (isName && inTag) { 18 | // Attribute 19 | return `${selector}="$1"`; 20 | } 21 | else if (isSnippet) { 22 | var times = 1; 23 | var content = ""; 24 | 25 | if (isSnippet[1]) { 26 | // Content 27 | content = isSnippet[1].slice(1, -1); 28 | } 29 | 30 | if (isSnippet[2]) { // Times 31 | times = isSnippet[2].slice(1); 32 | } 33 | 34 | var tag = selector.match(/^[\w:-]+/)?.[0] ?? "div"; 35 | var html = `<${tag}`; 36 | var id = selector.match(/#([\w-]+)/)?.[1]; 37 | 38 | if (id) { 39 | html += ` id="${id}"`; 40 | } 41 | 42 | var classes = selector.match(/\.[\w-]+/g); 43 | 44 | if (classes) { 45 | classes = classes.map(x => x.slice(1)); 46 | html += ` class="${classes.join(" ")}"`; 47 | } 48 | 49 | var selfClosing = selfClosing.indexOf(tag) > -1; 50 | 51 | html += selfClosing? "$1 />$2" : ">$1"; 52 | 53 | var tagLength = html.length; 54 | var ret = ""; 55 | 56 | for (var i=0; i`; 63 | } 64 | 65 | if (times > 1 && i + 1 < times) { 66 | ret += "\n"; 67 | } 68 | } 69 | 70 | return ret; 71 | } 72 | } 73 | } 74 | }; -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_contact_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 21 | 22 | 25 | 26 |