|
16 | 16 | import android.graphics.drawable.Drawable; |
17 | 17 | import android.graphics.drawable.ShapeDrawable; |
18 | 18 | import android.graphics.drawable.shapes.RectShape; |
19 | | -import android.os.Bundle; |
20 | 19 | import android.text.TextUtils; |
21 | 20 | import android.util.DisplayMetrics; |
22 | 21 | import android.util.Log; |
@@ -142,18 +141,64 @@ public void doHook() throws Throwable { |
142 | 141 | filter_itens += "\n" + custom_css; |
143 | 142 | cacheImages = new DrawableCache(Utils.getApplication(), 100 * 1024 * 1024); |
144 | 143 | var sheet = CSSFactory.parseString(filter_itens, new URL("https://base.url/")); |
| 144 | + registerView(sheet); |
145 | 145 |
|
146 | | - XposedHelpers.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() { |
147 | | - @Override |
148 | | - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { |
149 | | - var activity = (Activity) param.thisObject; |
150 | | - View rootView = activity.getWindow().getDecorView().getRootView(); |
151 | | - rootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> CompletableFuture.runAsync(() -> registerCssRules(activity, (ViewGroup) rootView, sheet), Utils.getExecutor())); |
| 146 | + } |
152 | 147 |
|
| 148 | + public void registerView(StyleSheet sheet) { |
| 149 | + var mapIds = new HashMap<Integer, ArrayList<RuleItem>>(); |
153 | 150 |
|
| 151 | + try { |
| 152 | + for (var selector : sheet) { |
| 153 | + var ruleSet = (RuleSet) selector; |
| 154 | + for (var selectorItem : ruleSet.getSelectors()) { |
| 155 | + var item = selectorItem.get(0); |
| 156 | + String className; |
| 157 | + String name; |
| 158 | + if ((className = item.getClassName()) != null) { |
| 159 | + className = className.replaceAll("_", ".").trim(); |
| 160 | + var clazz = XposedHelpers.findClass(className, classLoader); |
| 161 | + if (clazz == null || !clazz.isInstance(WppCore.getCurrentActivity())) |
| 162 | + continue; |
| 163 | + name = selectorItem.get(1).getIDName().trim(); |
| 164 | + } else { |
| 165 | + name = selectorItem.get(0).getIDName().trim(); |
| 166 | + } |
| 167 | + int id = 0; |
| 168 | + if (name.contains("android_")) { |
| 169 | + try { |
| 170 | + id = android.R.id.class.getField(name.substring(8)).getInt(null); |
| 171 | + } catch (NoSuchFieldException | IllegalAccessException ignored) { |
| 172 | + } |
| 173 | + } else { |
| 174 | + id = Utils.getID(name, "id"); |
| 175 | + } |
| 176 | + if (id <= 0) continue; |
| 177 | + var list = mapIds.getOrDefault(id, new ArrayList<>()); |
| 178 | + list.add(new RuleItem(selectorItem, ruleSet)); |
| 179 | + mapIds.put(id, list); |
| 180 | + } |
| 181 | + } |
| 182 | + } catch (Throwable ignored) { |
| 183 | + } |
| 184 | + XposedHelpers.findAndHookMethod(View.class, "invalidate", boolean.class, new XC_MethodHook() { |
| 185 | + @Override |
| 186 | + protected void afterHookedMethod(MethodHookParam param) throws Throwable { |
| 187 | + if (ReflectionUtils.isCalledFromClass(CustomView.class)) return; |
| 188 | + var view = (View) param.thisObject; |
| 189 | + var id = view.getId(); |
| 190 | + var list = mapIds.get(id); |
| 191 | + if (list == null) return; |
| 192 | + CompletableFuture.runAsync(() -> { |
| 193 | + for (var item : list) { |
| 194 | + try { |
| 195 | + setCssRule(view, item); |
| 196 | + } catch (Throwable ignored) { |
| 197 | + } |
| 198 | + } |
| 199 | + }, Utils.getExecutor()); |
154 | 200 | } |
155 | 201 | }); |
156 | | - |
157 | 202 | } |
158 | 203 |
|
159 | 204 |
|
@@ -192,44 +237,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { |
192 | 237 |
|
193 | 238 | } |
194 | 239 |
|
195 | | - |
196 | | - private void registerCssRules(Activity activity, ViewGroup currenView, StyleSheet sheet) { |
197 | | - try { |
198 | | - for (var selector : sheet) { |
199 | | - var ruleSet = (RuleSet) selector; |
200 | | - for (var selectorItem : ruleSet.getSelectors()) { |
201 | | - var item = selectorItem.get(0); |
202 | | - String className; |
203 | | - String name; |
204 | | - if ((className = item.getClassName()) != null) { |
205 | | - className = className.replaceAll("_", ".").trim(); |
206 | | - var clazz = XposedHelpers.findClass(className, classLoader); |
207 | | - if (clazz == null || !clazz.isInstance(activity)) continue; |
208 | | - name = selectorItem.get(1).getIDName().trim(); |
209 | | - } else { |
210 | | - name = selectorItem.get(0).getIDName().trim(); |
211 | | - } |
212 | | - int id = 0; |
213 | | - if (name.contains("android_")) { |
214 | | - try { |
215 | | - id = android.R.id.class.getField(name.substring(8)).getInt(null); |
216 | | - } catch (NoSuchFieldException | IllegalAccessException ignored) { |
217 | | - } |
218 | | - } else { |
219 | | - id = Utils.getID(name, "id"); |
220 | | - } |
221 | | - if (id <= 0) continue; |
222 | | - var view = currenView.findViewById(id); |
223 | | - if (view == null || !view.isShown() || view.getVisibility() != View.VISIBLE || !view.isAttachedToWindow()) |
224 | | - continue; |
225 | | - var ruleItem = new RuleItem(selectorItem, ruleSet); |
226 | | - setCssRule(view, ruleItem); |
227 | | - } |
228 | | - } |
229 | | - } catch (Throwable ignored) { |
230 | | - } |
231 | | - } |
232 | | - |
233 | 240 | private void setCssRule(View currentView, RuleItem ruleItem) { |
234 | 241 | var resultViews = new ArrayList<View>(); |
235 | 242 | captureSelector(currentView, ruleItem.selector, 0, resultViews); |
@@ -364,20 +371,22 @@ private void setRuleInView(RuleItem ruleItem, View view) { |
364 | 371 | if (value.equals("cover")) { |
365 | 372 | if (view instanceof ImageView imageView) { |
366 | 373 | imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); |
| 374 | + XposedBridge.log("resize ImageView to cover"); |
367 | 375 | } else { |
368 | 376 | var drawable = view.getBackground(); |
369 | 377 | if (!(drawable instanceof BitmapDrawable)) continue; |
370 | 378 | Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); |
371 | 379 | var widthObj = XposedHelpers.getAdditionalInstanceField(view, "mWidth"); |
372 | 380 | var heightObj = XposedHelpers.getAdditionalInstanceField(view, "mHeight"); |
373 | 381 | if (widthObj != null && heightObj != null) { |
374 | | - if ((int) widthObj == view.getWidth() && (int) heightObj == view.getHeight()) |
| 382 | + if (Math.abs((int) widthObj - view.getWidth()) <= 20 && Math.abs((int) heightObj - view.getHeight()) <= 20) { |
375 | 383 | continue; |
| 384 | + } |
376 | 385 | } |
377 | 386 | var resizeDrawable = new BitmapDrawable(view.getContext().getResources(), Bitmap.createScaledBitmap(bitmap, view.getWidth(), view.getHeight(), true)); |
| 387 | + view.setBackground(resizeDrawable); |
378 | 388 | XposedHelpers.setAdditionalInstanceField(view, "mHeight", view.getHeight()); |
379 | 389 | XposedHelpers.setAdditionalInstanceField(view, "mWidth", view.getWidth()); |
380 | | - view.setBackground(resizeDrawable); |
381 | 390 | } |
382 | 391 | } |
383 | 392 | } |
@@ -567,13 +576,16 @@ private static ColorStateList getColorStateList(Declaration declaration) { |
567 | 576 | ); |
568 | 577 | } |
569 | 578 |
|
570 | | - private int getRealValue(TermLength value, int size) { |
571 | | - if (value.getUnit() == TermNumeric.Unit.px) { |
572 | | - return Utils.dipToPixels(value.getValue().intValue()); |
573 | | - } else if (value.isPercentage()) { |
574 | | - return size * value.getValue().intValue() / 100; |
| 579 | + private int getRealValue(TermLength pValue, int size) { |
| 580 | + int value; |
| 581 | + if (pValue.getUnit() == TermNumeric.Unit.px) { |
| 582 | + value = Utils.dipToPixels(pValue.getValue().intValue()); |
| 583 | + } else if (pValue.isPercentage()) { |
| 584 | + value = size * pValue.getValue().intValue() / 100; |
| 585 | + } else { |
| 586 | + value = pValue.getValue().intValue(); |
575 | 587 | } |
576 | | - return value.getValue().intValue(); |
| 588 | + return value > 0 ? value : 1; |
577 | 589 | } |
578 | 590 |
|
579 | 591 | private void captureSelector(View currentView, CombinedSelector selector, int position, ArrayList<View> resultViews) { |
@@ -669,13 +681,14 @@ private Drawable loadDrawableFromFile(String filePath, int reqWidth, int reqHeig |
669 | 681 | File file = new File(filePath); |
670 | 682 | Bitmap bitmap; |
671 | 683 | if (!file.canRead()) { |
672 | | - var parcelFile = WppCore.getClientBridge().openFile(filePath, false); |
673 | | - bitmap = BitmapFactory.decodeStream(new FileInputStream(parcelFile.getFileDescriptor())); |
| 684 | + try (var parcelFile = WppCore.getClientBridge().openFile(filePath, false)) { |
| 685 | + bitmap = BitmapFactory.decodeStream(new FileInputStream(parcelFile.getFileDescriptor())); |
| 686 | + } |
674 | 687 | } else { |
675 | 688 | bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); |
676 | 689 | } |
677 | | - var newHeight = reqHeight < 10 ? bitmap.getHeight() : Math.min(bitmap.getHeight(), reqHeight); |
678 | | - var newWidth = reqWidth < 10 ? bitmap.getWidth() : Math.min(bitmap.getWidth(), reqWidth); |
| 690 | + var newHeight = reqHeight < 1 ? bitmap.getHeight() : Math.min(bitmap.getHeight(), reqHeight); |
| 691 | + var newWidth = reqWidth < 1 ? bitmap.getWidth() : Math.min(bitmap.getWidth(), reqWidth); |
679 | 692 | bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); |
680 | 693 | return new BitmapDrawable(context.getResources(), bitmap); |
681 | 694 | } catch (Exception e) { |
|
0 commit comments