Skip to content

Commit cf92602

Browse files
committed
fix bug in TextStatusComposer
1 parent a80c4a8 commit cf92602

File tree

3 files changed

+39
-156
lines changed

3 files changed

+39
-156
lines changed

app/src/main/java/com/wmods/wppenhacer/xposed/core/devkit/Unobfuscator.java

Lines changed: 10 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,6 @@ public synchronized static String getMethodDescriptor(Method method) {
150150
return method.getDeclaringClass().getName() + "->" + method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(Class::getName).collect(Collectors.joining(",")) + ")";
151151
}
152152

153-
154-
public synchronized static String getConstructorDescriptor(Constructor constructor) {
155-
if (constructor == null) return null;
156-
return constructor.getDeclaringClass().getName() + "->" + constructor.getName() + "(" + Arrays.stream(constructor.getParameterTypes()).map(Class::getName).collect(Collectors.joining(",")) + ")";
157-
}
158-
159153
public synchronized static String getFieldDescriptor(Field field) {
160154
return field.getDeclaringClass().getName() + "->" + field.getName() + ":" + field.getType().getName();
161155
}
@@ -488,16 +482,6 @@ public synchronized static Method loadDndModeMethod(ClassLoader classLoader) thr
488482
}
489483

490484
// TODO: Classes and methods to MediaQuality
491-
492-
private static Class<?> loadMediaQualityClass(ClassLoader classLoader) throws Exception {
493-
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> {
494-
var clazzMediaClass = findFirstClassUsingStrings(classLoader, StringMatchType.Contains, "getCorrectedResolution");
495-
if (clazzMediaClass == null) throw new Exception("MediaQuality class not found");
496-
return clazzMediaClass;
497-
});
498-
}
499-
500-
501485
public synchronized static Method loadMediaQualityVideoMethod2(ClassLoader classLoader) throws Exception {
502486
return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> {
503487
var method = findFirstMethodUsingStrings(classLoader, StringMatchType.Contains, "getCorrectedResolution");
@@ -655,14 +639,6 @@ public synchronized static Class<?> loadMaterialShapeDrawableClass(ClassLoader l
655639
});
656640
}
657641

658-
public synchronized static Class<?> loadCustomDrawableClass(ClassLoader loader) throws Exception {
659-
return UnobfuscatorCache.getInstance().getClass(loader, () -> {
660-
var clazz = findFirstClassUsingStrings(loader, StringMatchType.Contains, "closeIconEnabled");
661-
if (clazz == null) throw new Exception("CustomDrawable class not found");
662-
return clazz;
663-
});
664-
}
665-
666642
public synchronized static Method loadPropsBooleanMethod(ClassLoader loader) throws Exception {
667643
return UnobfuscatorCache.getInstance().getMethod(loader, () -> {
668644
var method = findFirstMethodUsingStrings(loader, StringMatchType.Contains, "Unknown BooleanField");
@@ -1614,36 +1590,18 @@ public synchronized static Class loadListChannelItemClass(ClassLoader classLoade
16141590
});
16151591
}
16161592

1617-
public synchronized static Method loadTextStatusComposer(ClassLoader classLoader) throws Exception {
1618-
return findFirstMethodUsingStrings(classLoader, StringMatchType.Contains, "Can't put value with type");
1619-
}
16201593

1621-
public synchronized static Method loadTextStatusComposer2(ClassLoader classLoader) throws Exception {
1622-
return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> {
1623-
Class<?> TextDataClass = classLoader.loadClass("com.whatsapp.TextData");
1624-
var result = dexkit.findClass(FindClass.create().matcher(
1625-
ClassMatcher.create().addUsingString("*").
1626-
addMethod(MethodMatcher.create().paramCount(1).addParamType(TextDataClass))
1627-
));
1628-
if (result.isEmpty()) {
1629-
var tscClazzData = dexkit.getClassData(WppCore.getTextStatusComposerFragmentClass(classLoader));
1630-
if (tscClazzData != null) {
1631-
for (var method : tscClazzData.getMethods()) {
1632-
var tdMethod = method.getInvokes().stream().filter(m -> m.isMethod() && m.getParamCount() == 1 && m.getParamTypes().get(0).equals(dexkit.getClassData(TextDataClass))).findFirst();
1633-
if (tdMethod.isPresent()) {
1634-
return tdMethod.get().getMethodInstance(classLoader);
1635-
}
1636-
}
1637-
}
1638-
1639-
throw new RuntimeException("TextStatusComposer2 class not found 1");
1640-
}
1594+
public synchronized static Method[] loadTextStatusData(ClassLoader classLoader) throws Exception {
1595+
return UnobfuscatorCache.getInstance().getMethods(classLoader, () -> {
1596+
var methods = dexkit.findMethod(
1597+
FindMethod.create().matcher(
1598+
MethodMatcher.create().addParamType("com.whatsapp.TextData")
1599+
)
1600+
);
1601+
if (methods.isEmpty())
1602+
throw new RuntimeException("loadTextStatusData method not found");
16411603

1642-
var foundClass = result.get(0).getInstance(classLoader);
1643-
var resultMethod = ReflectionUtils.findMethodUsingFilter(foundClass, method -> method.getParameterCount() == 1 && method.getParameterTypes()[0] == TextDataClass);
1644-
if (resultMethod != null)
1645-
return resultMethod;
1646-
throw new RuntimeException("TextStatusComposer2 method not found 2");
1604+
return methods.stream().filter(MethodData::isMethod).map(methodData -> convertRealMethod(methodData, classLoader)).toArray(Method[]::new);
16471605
});
16481606
}
16491607

@@ -1765,11 +1723,6 @@ public static synchronized Method loadCheckCustomRom(ClassLoader classLoader) th
17651723
return method;
17661724
}
17671725

1768-
// public static synchronized Class loadGetContactInfoClass(ClassLoader classLoader) throws Exception {
1769-
// return UnobfuscatorCache.getInstance().getClass(classLoader, () -> findFirstClassUsingStrings(classLoader, StringMatchType.Contains, "unknown@unknown"));
1770-
//
1771-
// }
1772-
17731726
public static synchronized Method loadTranscribeMethod(ClassLoader classLoader) throws Exception {
17741727
return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> findFirstMethodUsingStrings(classLoader, StringMatchType.Contains, "transcribe: starting transcription"));
17751728
}
@@ -1869,33 +1822,6 @@ public static Class<?> loadStatusDistributionClass(ClassLoader classLoader) thro
18691822
});
18701823
}
18711824

1872-
// public static Method loadChangeTitleLogoMethod(ClassLoader classLoader) throws Exception {
1873-
// return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> {
1874-
// var id = Utils.getID("toolbar_logo", "id");
1875-
// var methodData = dexkit.findMethod(
1876-
// FindMethod.create()
1877-
// .matcher(MethodMatcher.create().addUsingNumber(id))
1878-
// );
1879-
// if (methodData.isEmpty())
1880-
// throw new RuntimeException("ChangeTitleLogo method not found");
1881-
// return methodData.get(0).getMethodInstance(classLoader);
1882-
// });
1883-
// }
1884-
1885-
// public static Field loadChangeTitleLogoField(ClassLoader classLoader) throws Exception {
1886-
// return UnobfuscatorCache.getInstance().getField(classLoader, () -> {
1887-
// var methodData = dexkit.getMethodData(loadChangeTitleLogoMethod(classLoader));
1888-
// var clazz = WppCore.getHomeActivityClass(classLoader);
1889-
// var usingFields = methodData.getUsingFields();
1890-
// for (var uField : usingFields) {
1891-
// var field = uField.getField().getFieldInstance(classLoader);
1892-
// if (field.getDeclaringClass() == clazz && field.getType() == Integer.class) {
1893-
// return field;
1894-
// }
1895-
// }
1896-
// throw new RuntimeException("ChangeTitleLogo field not found");
1897-
// });
1898-
// }
18991825

19001826
public static Class<?> loadFilterItemClass(ClassLoader classLoader) throws Exception {
19011827
return UnobfuscatorCache.getInstance().getClass(classLoader, () -> {
@@ -1908,18 +1834,6 @@ public static Class<?> loadFilterItemClass(ClassLoader classLoader) throws Excep
19081834
});
19091835
}
19101836

1911-
// public static Method loadActiveButtonNav(ClassLoader classLoader) throws Exception {
1912-
// return UnobfuscatorCache.getInstance().getMethod(classLoader, () -> {
1913-
// var methodList = dexkit.findClass(
1914-
// FindClass.create().matcher(ClassMatcher.create().addUsingString("NavigationBar", StringMatchType.Equals))
1915-
// ).findMethod(
1916-
// FindMethod.create().matcher(MethodMatcher.create().name("setActiveIndicatorDrawable"))
1917-
// );
1918-
// return methodList.get(0).getMethodInstance(classLoader);
1919-
// });
1920-
//
1921-
// }
1922-
19231837
public static Class[] loadProximitySensorListenerClasses(ClassLoader classLoader) throws Exception {
19241838
return UnobfuscatorCache.getInstance().getClasses(classLoader, () -> {
19251839
var classDataList = dexkit.findClass(

app/src/main/java/com/wmods/wppenhacer/xposed/features/general/Others.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public void doHook() throws Exception {
8282
propsBoolean.put(8013, Objects.equals(filterChats, "2")); // lupa sera removida e sera adicionado uma barra no lugar.
8383
propsBoolean.put(2889, floatingMenu);
8484

85+
// new text composer
86+
propsBoolean.put(15708, true);
87+
8588
// change page id
8689
propsBoolean.put(2358, false);
8790

app/src/main/java/com/wmods/wppenhacer/xposed/features/others/TextStatusComposer.java

Lines changed: 26 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,15 @@
1212
import com.wmods.wppenhacer.xposed.core.WppCore;
1313
import com.wmods.wppenhacer.xposed.core.devkit.Unobfuscator;
1414
import com.wmods.wppenhacer.xposed.utils.ReflectionUtils;
15-
import com.wmods.wppenhacer.xposed.utils.ResId;
1615
import com.wmods.wppenhacer.xposed.utils.Utils;
1716

18-
import java.lang.reflect.Field;
19-
import java.util.concurrent.atomic.AtomicReference;
20-
2117
import de.robv.android.xposed.XC_MethodHook;
2218
import de.robv.android.xposed.XSharedPreferences;
2319
import de.robv.android.xposed.XposedBridge;
2420
import de.robv.android.xposed.XposedHelpers;
2521

2622
public class TextStatusComposer extends Feature {
27-
private static final AtomicReference<ColorData> colorData = new AtomicReference<>();
28-
private static final AtomicReference<Object> textComposerModel = new AtomicReference<>();
23+
private static final ColorData colorData = new ColorData();
2924

3025
public TextStatusComposer(@NonNull ClassLoader classLoader, @NonNull XSharedPreferences preferences) {
3126
super(classLoader, preferences);
@@ -35,38 +30,14 @@ public TextStatusComposer(@NonNull ClassLoader classLoader, @NonNull XSharedPref
3530
public void doHook() throws Throwable {
3631
if (!prefs.getBoolean("statuscomposer", false)) return;
3732

38-
var setColorTextComposer = Unobfuscator.loadTextStatusComposer(classLoader);
39-
log("setColorTextComposer: " + Unobfuscator.getMethodDescriptor(setColorTextComposer));
40-
41-
var textModelClass = XposedHelpers.findClassIfExists("com.whatsapp.statuscomposer.composer.TextStatusComposerViewModel", classLoader);
42-
43-
if (textModelClass != null) {
44-
XposedBridge.hookAllConstructors(textModelClass, new XC_MethodHook() {
45-
@Override
46-
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
47-
textComposerModel.set(param.thisObject);
48-
}
49-
});
50-
var arrMethod = ReflectionUtils.findMethodUsingFilter(textModelClass, method -> method.getParameterCount() == 1 && method.getParameterTypes()[0] == int.class && method.getReturnType() == int.class);
51-
XposedBridge.hookMethod(arrMethod, new XC_MethodHook() {
52-
@Override
53-
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
54-
try {
55-
param.setResult(XposedBridge.invokeOriginalMethod(param.method, param.thisObject, param.args));
56-
} catch (Exception e) {
57-
param.setResult(ResId.string.app_name);
58-
}
59-
}
60-
});
61-
}
62-
6333
var clazz = WppCore.getTextStatusComposerFragmentClass(classLoader);
6434
var methodOnCreate = ReflectionUtils.findMethodUsingFilter(clazz, method -> method.getParameterCount() == 2 && method.getParameterTypes()[0] == Bundle.class && method.getParameterTypes()[1] == View.class);
6535
XposedBridge.hookMethod(methodOnCreate,
6636
new XC_MethodHook() {
6737

6838
@Override
6939
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
40+
logDebug("afterHookedMethod", "TextStatusComposer");
7041
var activity = WppCore.getCurrentActivity();
7142
var viewRoot = (View) param.args[1];
7243
var pickerColor = viewRoot.findViewById(Utils.getID("color_picker_btn", "id"));
@@ -75,19 +46,11 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
7546
pickerColor.setOnLongClickListener(v -> {
7647
var dialog = new SimpleColorPickerDialog(activity, color -> {
7748
try {
78-
if (textModelClass != null) {
79-
var textModel = textComposerModel.get();
80-
var mField = ReflectionUtils.getFieldsByType(textModel.getClass(), setColorTextComposer.getDeclaringClass()).get(0);
81-
var auxInstance = ReflectionUtils.getObjectField(mField, textModel);
82-
ReflectionUtils.callMethod(setColorTextComposer, auxInstance, "background_color_key", color);
83-
} else {
84-
Field fieldInt = ReflectionUtils.getFieldByType(param.thisObject.getClass(), int.class);
85-
fieldInt.setInt(param.thisObject, color);
86-
}
8749
activity.getWindow().setBackgroundDrawable(new ColorDrawable(color));
50+
viewRoot.findViewById(Utils.getID("background","id")).setBackgroundColor(color);
8851
var controls = viewRoot.findViewById(Utils.getID("controls", "id"));
8952
controls.setBackgroundColor(color);
90-
53+
colorData.backgroundColor = color;
9154
} catch (Exception e) {
9255
log(e);
9356
}
@@ -100,33 +63,36 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
10063
var textColor = viewRoot.findViewById(Utils.getID("font_picker_btn", "id"));
10164
textColor.setOnLongClickListener(v -> {
10265
var dialog = new SimpleColorPickerDialog(activity, color -> {
103-
var colorData = new ColorData();
104-
colorData.instance = param.thisObject;
105-
colorData.color = color;
106-
TextStatusComposer.colorData.set(colorData);
66+
colorData.textColor = color;
10767
entry.setTextColor(color);
10868
});
10969
dialog.create().setCanceledOnTouchOutside(false);
11070
dialog.show();
11171
return true;
11272
});
113-
114-
11573
}
11674
});
11775

118-
var setColorTextComposer2 = Unobfuscator.loadTextStatusComposer2(classLoader);
119-
log("setColorTextComposer2: " + Unobfuscator.getMethodDescriptor(setColorTextComposer2));
120-
XposedBridge.hookMethod(setColorTextComposer2, new XC_MethodHook() {
121-
@Override
122-
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
123-
if (colorData.get() != null) {
124-
var textData = param.args[0];
125-
XposedHelpers.setObjectField(textData, "textColor", colorData.get().color);
126-
colorData.set(null);
76+
77+
var methodsTextStatus = Unobfuscator.loadTextStatusData(classLoader);
78+
79+
for (var method : methodsTextStatus) {
80+
Class<?> textDataClass = classLoader.loadClass("com.whatsapp.TextData");
81+
logDebug("setColorTextComposer", Unobfuscator.getMethodDescriptor(method));
82+
XposedBridge.hookMethod(method, new XC_MethodHook() {
83+
@Override
84+
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
85+
var textData = ReflectionUtils.getArg(param.args, textDataClass, 0);
86+
if (textData == null) return;
87+
if (colorData.textColor != -1)
88+
XposedHelpers.setObjectField(textData, "textColor", colorData.textColor);
89+
if (colorData.backgroundColor != -1)
90+
XposedHelpers.setObjectField(textData, "backgroundColor", colorData.backgroundColor);
91+
colorData.textColor = -1;
92+
colorData.backgroundColor = -1;
12793
}
128-
}
129-
});
94+
});
95+
}
13096

13197
}
13298

@@ -137,7 +103,7 @@ public String getPluginName() {
137103
}
138104

139105
public static class ColorData {
140-
public Object instance;
141-
public int color;
106+
public int textColor = -1;
107+
public int backgroundColor = -1;
142108
}
143109
}

0 commit comments

Comments
 (0)