From a8048820a0128db20d33c652895b67a03f19b649 Mon Sep 17 00:00:00 2001 From: HalfManBear <89969229+halfmanbear@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:51:10 +0100 Subject: [PATCH 01/16] Update Interceptor.java --- .../ps/reso/instaeclipse/mods/network/Interceptor.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java index 0ada52f0..9e1c432a 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java @@ -95,6 +95,16 @@ protected void beforeHookedMethod(MethodHookParam param) { || uri.getPath().contains("mixed_media") || uri.getPath().contains("mixed_media/discover/stream/"); } + if (FeatureFlags.disableReelsExceptDM) { + if (uri.getPath().startsWith("/api/v1/direct_v2/")) { + return; + } + shouldDrop |= (uri.getPath().startsWith("/api/v1/clips/") && uri.getQuery() != null + && (uri.getQuery().contains("next_media_ids=") + || uri.getQuery().contains("max_id="))) + || uri.getPath().contains("/clips/discover/") + || uri.getPath().contains("/mixed_media/discover/stream/"); + } if (FeatureFlags.disableExplore) { shouldDrop |= uri.getPath().contains("/discover/topical_explore") || uri.getPath().contains("/discover/topical_explore_stream") From ef3618190aa65a09321fbede231fa989b48833b3 Mon Sep 17 00:00:00 2001 From: HalfManBear <89969229+halfmanbear@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:52:24 +0100 Subject: [PATCH 02/16] Update SettingsManager.java --- .../java/ps/reso/instaeclipse/utils/core/SettingsManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/core/SettingsManager.java b/app/src/main/java/ps/reso/instaeclipse/utils/core/SettingsManager.java index e81386da..97467576 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/core/SettingsManager.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/core/SettingsManager.java @@ -43,6 +43,7 @@ public static void saveAllFlags() { editor.putBoolean("disableStories", FeatureFlags.disableStories); editor.putBoolean("disableFeed", FeatureFlags.disableFeed); editor.putBoolean("disableReels", FeatureFlags.disableReels); + editor.putBoolean("disableReelsExceptDM", FeatureFlags.disableReelsExceptDM); editor.putBoolean("disableExplore", FeatureFlags.disableExplore); editor.putBoolean("disableComments", FeatureFlags.disableComments); @@ -92,6 +93,7 @@ public static void loadAllFlags(Context context) { FeatureFlags.disableStories = prefs.getBoolean("disableStories", false); FeatureFlags.disableFeed = prefs.getBoolean("disableFeed", false); FeatureFlags.disableReels = prefs.getBoolean("disableReels", false); + FeatureFlags.disableReelsExceptDM = prefs.getBoolean("disableReelsExceptDM", false); FeatureFlags.disableExplore = prefs.getBoolean("disableExplore", false); FeatureFlags.disableComments = prefs.getBoolean("disableComments", false); From a26cbb08517ada85bbe7de8b77aee9fca608b235 Mon Sep 17 00:00:00 2001 From: HalfManBear <89969229+halfmanbear@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:54:24 +0100 Subject: [PATCH 03/16] Update DialogUtils.java --- .../java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java index dbe6b380..57271799 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java @@ -505,6 +505,7 @@ private static void showDistractionOptions(Context context) { createSwitch(context, "Disable Stories", FeatureFlags.disableStories), createSwitch(context, "Disable Feed", FeatureFlags.disableFeed), createSwitch(context, "Disable Reels", FeatureFlags.disableReels), + createSwitch(context, "Disable Reels Except in DMs", FeatureFlags.disableReelsExceptDM), createSwitch(context, "Disable Explore", FeatureFlags.disableExplore), createSwitch(context, "Disable Comments", FeatureFlags.disableComments) }; @@ -548,8 +549,9 @@ private static void showDistractionOptions(Context context) { FeatureFlags.disableStories = switches[0].isChecked(); FeatureFlags.disableFeed = switches[1].isChecked(); FeatureFlags.disableReels = switches[2].isChecked(); - FeatureFlags.disableExplore = switches[3].isChecked(); - FeatureFlags.disableComments = switches[4].isChecked(); + FeatureFlags.disableReelsExceptDM = switches[3].isChecked(); + FeatureFlags.disableExplore = switches[4].isChecked(); + FeatureFlags.disableComments = switches[5].isChecked(); }); SettingsManager.saveAllFlags(); From 4b369d7ed3b5e9c69148418dc13e54f1cdefb618 Mon Sep 17 00:00:00 2001 From: HalfManBear <89969229+halfmanbear@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:55:16 +0100 Subject: [PATCH 04/16] Update FeatureFlags.java --- .../java/ps/reso/instaeclipse/utils/feature/FeatureFlags.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/feature/FeatureFlags.java b/app/src/main/java/ps/reso/instaeclipse/utils/feature/FeatureFlags.java index df81b6e2..1345ac4a 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/feature/FeatureFlags.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/feature/FeatureFlags.java @@ -30,6 +30,7 @@ public class FeatureFlags { public static boolean disableStories = false; public static boolean disableFeed = false; public static boolean disableReels = false; + public static boolean disableReelsExceptDM = false; public static boolean disableExplore = false; public static boolean disableComments = false; From c5727a63b66971a0e94f59505f757644d6a18f34 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 04:24:45 +0300 Subject: [PATCH 05/16] Fix Story Flipping Fixed stop story flipping on newer versions. --- .../reso/instaeclipse/mods/misc/StoryFlipping.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/misc/StoryFlipping.java b/app/src/main/java/ps/reso/instaeclipse/mods/misc/StoryFlipping.java index 6acc75f4..83e69e29 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/misc/StoryFlipping.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/misc/StoryFlipping.java @@ -25,11 +25,14 @@ public void handleStoryFlippingDisable(DexKitBridge bridge) { private void findAndHookMethod(DexKitBridge bridge) { try { - // Step 1: Find methods referencing the string "end_scene" - List methods = bridge.findMethod(FindMethod.create() - .matcher(MethodMatcher.create() - .declaredClass("instagram.features.stories.fragment.ReelViewerFragment") - .usingStrings("end_scene") + // Step 1: Find methods matching the targeted method structure + List methods = bridge.findMethod( + FindMethod.create().matcher( + MethodMatcher.create() + .declaredClass("instagram.features.stories.fragment.ReelViewerFragment") + .paramTypes("java.lang.Object") + .returnType("void") + .usingStrings("userSession") ) ); From 68fb09c41b9a9cfb88eada9ac2fb1d7e1b8282dc Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 14:03:34 +0300 Subject: [PATCH 06/16] Fix follower status toast Fixed follower status toast for newer versions. --- .../ps/reso/instaeclipse/Xposed/Module.java | 12 +- .../mods/misc/FollowerIndicator.java | 110 ++++++++++++------ 2 files changed, 80 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/Xposed/Module.java b/app/src/main/java/ps/reso/instaeclipse/Xposed/Module.java index d01efab5..0acf2a4a 100644 --- a/app/src/main/java/ps/reso/instaeclipse/Xposed/Module.java +++ b/app/src/main/java/ps/reso/instaeclipse/Xposed/Module.java @@ -227,10 +227,14 @@ protected void afterHookedMethod(MethodHookParam param) { } try { - FollowerIndicator followerIndicator = new FollowerIndicator(); // Follower Indicator - String bridge = followerIndicator.findFollowerStatusMethod(Module.dexKitBridge); - if (FeatureFlags.showFollowerToast) { - followerIndicator.checkFollow(hostClassLoader, bridge); + FollowerIndicator followerIndicator = new FollowerIndicator(); + FollowerIndicator.FollowMethodResult result = + followerIndicator.findFollowerStatusMethod(Module.dexKitBridge); + + if (result != null && FeatureFlags.showFollowerToast) { + followerIndicator.checkFollow(hostClassLoader, result.methodName, result.userClassName); + } else { + XposedBridge.log("(InstaEclipse | FollowerToast): ❌ Method not found"); } } catch (Throwable ignored) { XposedBridge.log("(InstaEclipse | FollowerToast): ❌ Failed to hook"); diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java b/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java index 6a8bed9e..422a9e58 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java @@ -14,64 +14,97 @@ import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; -import ps.reso.instaeclipse.utils.feature.FeatureStatusTracker; import ps.reso.instaeclipse.utils.toast.CustomToast; public class FollowerIndicator { - public String findFollowerStatusMethod(DexKitBridge bridge) { - try { - List methods = bridge.findMethod(FindMethod.create().matcher(MethodMatcher.create().usingStrings("", "", "") // Look for 3+ empty strings - .paramCount(2))); - for (MethodData method : methods) { - List paramTypes = new ArrayList<>(); - for (Object param : method.getParamTypes()) { - paramTypes.add(String.valueOf(param)); - } + public static class FollowMethodResult { + public final String methodName; + public final String userClassName; - // Match (UserSession, User) - if (paramTypes.size() == 2 && paramTypes.get(0).contains("com.instagram.common.session.UserSession") && paramTypes.get(1).contains("com.instagram.user.model.User")) { + public FollowMethodResult(String methodName, String userClassName) { + this.methodName = methodName; + this.userClassName = userClassName; + } + } + public FollowMethodResult findFollowerStatusMethod(DexKitBridge bridge) { + try { + // πŸ” Step 1: Try new method detection first (obfuscated User class) + String obfUserClass = null; + List errMethods = bridge.findMethod( + FindMethod.create().matcher( + MethodMatcher.create().usingStrings("ERROR_INSERT_EXPIRED_URL") + ) + ); + if (!errMethods.isEmpty()) { + obfUserClass = errMethods.get(0).getClassName(); + // XposedBridge.log("πŸ” Found obfuscated User class: " + obfUserClass); + } - XposedBridge.log("πŸ” Inspecting method: " + method.getClassName() + "." + method.getName()); + if (obfUserClass != null) { + List methods = bridge.findMethod( + FindMethod.create().matcher( + MethodMatcher.create() + .usingStrings("", "", "") + .paramTypes("com.instagram.common.session.UserSession", obfUserClass) + ) + ); + for (MethodData method : methods) { + // XposedBridge.log("πŸ“Œ Inspecting (new) method: " + method.getClassName() + "." + method.getName()); for (MethodData invoked : method.getInvokes()) { String className = invoked.getClassName(); - String methodName = invoked.getName(); String returnType = String.valueOf(invoked.getReturnType()); - for (Object param : invoked.getParamTypes()) { - paramTypes.add(String.valueOf(param)); + if (className.contains(obfUserClass) && returnType.contains("boolean")) { + XposedBridge.log("βœ… Found follower status method (new): " + invoked.getName()); + return new FollowMethodResult(invoked.getName(), obfUserClass); } + } + } + } - // βœ… Just find first method in User class with returnType boolean & no params - if (className.contains("com.instagram.user.model.User") && (returnType.contains("boolean"))) { + // πŸ”„ Step 2: Fallback to old detection + List methodsOld = bridge.findMethod( + FindMethod.create().matcher( + MethodMatcher.create().usingStrings("", "", "").paramCount(2) + ) + ); - // XposedBridge.log("🎯 Matched Method: " + className + "." + methodName); - return methodName; + for (MethodData method : methodsOld) { + List paramTypes = new ArrayList<>(); + for (Object param : method.getParamTypes()) { + paramTypes.add(String.valueOf(param)); + } + if (paramTypes.size() == 2 && + paramTypes.get(0).contains("com.instagram.common.session.UserSession") && + paramTypes.get(1).contains("com.instagram.user.model.User")) { + for (MethodData invoked : method.getInvokes()) { + if (invoked.getClassName().contains("com.instagram.user.model.User") && + String.valueOf(invoked.getReturnType()).contains("boolean")) { + XposedBridge.log("βœ… Found follower status method (old): " + invoked.getName()); + return new FollowMethodResult(invoked.getName(), "com.instagram.user.model.User"); } - FeatureStatusTracker.setHooked("ShowFollowerToast"); } - // inspectInvokedMethods(bridge, method); // your helper } } } catch (Throwable e) { - XposedBridge.log("❌ Error in method discovery: " + e.getMessage()); + XposedBridge.log("❌ Error in findFollowerStatusMethod: " + e.getMessage()); } return null; } - public void checkFollow(ClassLoader classLoader, String followerStatusMethod) { + public void checkFollow(ClassLoader classLoader, String followerStatusMethod, String userClassName) { try { - - if (followerStatusMethod == null) { - XposedBridge.log("❌ method name not found. Skipping hook."); + if (followerStatusMethod == null || userClassName == null) { + XposedBridge.log("❌ method or class name not found. Skipping hook."); return; } - XposedHelpers.findAndHookMethod("com.instagram.user.model.User", classLoader, followerStatusMethod, new XC_MethodHook() { + XposedHelpers.findAndHookMethod(userClassName, classLoader, followerStatusMethod, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Object user = param.thisObject; @@ -81,31 +114,32 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { try { username = (String) XposedHelpers.callMethod(user, "getUsername"); } catch (Throwable ignored) { - // Obfuscated or missing method β€” skip username - } Boolean followsMe = (Boolean) param.getResult(); + // skip username for now in obfuscated versions + } + Boolean followsMe = (Boolean) param.getResult(); String targetId = ps.reso.instaeclipse.utils.tracker.FollowIndicatorTracker.currentlyViewedUserId; if (userId != null && userId.equals(targetId)) { - Context context = AndroidAppHelper.currentApplication().getApplicationContext(); String message; if (username != null && !username.isEmpty()) { - message = "@" + username + " (" + userId + ") " + (followsMe ? "follows you βœ…" : "doesn’t follow you ❌"); + message = "@" + username + " (" + userId + ") " + + (followsMe ? "follows you βœ…" : "doesn’t follow you ❌"); } else { - message = " (" + userId + ") " + (followsMe ? "follows you βœ…" : "doesn’t follow you ❌"); + message = " (" + userId + ") " + + (followsMe ? "follows you βœ…" : "doesn’t follow you ❌"); } CustomToast.showCustomToast(context, message); - ps.reso.instaeclipse.utils.tracker.FollowIndicatorTracker.currentlyViewedUserId = null; - - } } }); + XposedBridge.log("βœ… Hooked follower status method in: " + userClassName + "." + followerStatusMethod); + } catch (Exception e) { - XposedBridge.log("❌ Error hooking User class: " + e.getMessage()); + XposedBridge.log("❌ Error hooking follower status: " + e.getMessage()); } } -} \ No newline at end of file +} From fb26ff18ba86e22b50a2e09f7246feec815172df Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 14:44:20 +0300 Subject: [PATCH 07/16] Fix ghost view once Fixed ghost view once feature for newer versions. --- .../instaeclipse/mods/ghost/ViewOnce.java | 46 ++++++++++--------- .../mods/network/Interceptor.java | 4 ++ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/ghost/ViewOnce.java b/app/src/main/java/ps/reso/instaeclipse/mods/ghost/ViewOnce.java index cb2596cf..bd0e4fd8 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/ghost/ViewOnce.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/ghost/ViewOnce.java @@ -51,36 +51,40 @@ public void handleViewOnceBlock(DexKitBridge bridge) { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (!FeatureFlags.isGhostViewOnce) { - // If Ghost View Once is disabled, allow normal execution + return; // Feature disabled β†’ skip + } + + Object rw = param.args[2]; // Third argument (visual item object) + if (rw == null) { return; } - Object rw = param.args[2]; // Third argument (likely visual item object) - - if (rw != null) { - Method[] allMethods = rw.getClass().getDeclaredMethods(); - - for (Method m : allMethods) { - if (m.getParameterTypes().length == 0 && - m.getReturnType() == String.class) { - try { - m.setAccessible(true); - String value = (String) m.invoke(rw); - - if (value != null && value.contains("send_visual_item_seen_marker")) { - // If it matches visual seen marker, block it - param.setResult(null); - return; - } - } catch (Throwable ignored) { - // Ignore reflection exceptions - } + for (Method m : rw.getClass().getDeclaredMethods()) { + // Only check methods with no params returning String + if (m.getParameterTypes().length != 0 || m.getReturnType() != String.class) { + continue; + } + + try { + m.setAccessible(true); + String value = (String) m.invoke(rw); + if (value == null) { + continue; } + + if (value.contains("visual_item_seen") || + value.contains("send_visual_item_seen_marker")) { + // XposedBridge.log("Blocked ViewOnce send: " + value); + param.setResult(null); // Block this call + } + } catch (Throwable ignored) { + // Ignore reflection errors } } } }); + XposedBridge.log("(InstaEclipse | ViewOnce): βœ… Hooked (dynamic check): " + method.getClassName() + "." + method.getName()); FeatureStatusTracker.setHooked("GhostViewOnce"); diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java index 0ada52f0..7372ea93 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java @@ -68,6 +68,7 @@ protected void beforeHookedMethod(MethodHookParam param) { } if (FeatureFlags.isGhostViewOnce) { shouldDrop |= uri.getPath().endsWith("/item_replayed/"); + shouldDrop |= (uri.getPath().contains("/direct") && uri.getPath().endsWith("/item_seen/")); } if (FeatureFlags.isGhostStory) { shouldDrop |= uri.getPath().contains("/api/v2/media/seen/"); @@ -130,6 +131,9 @@ protected void beforeHookedMethod(MethodHookParam param) { // XposedBridge.log("❌ [InstaEclipse] Failed to modify URI: " + e.getMessage()); } } + else { + XposedBridge.log("Logging: " + uri.getHost() + uri.getPath()); + } if (FeatureFlags.showFollowerToast) { if (uri.getPath() != null && uri.getPath().startsWith("/api/v1/friendships/show/")) { From 821b232a5b75c898e644b7461aa895a01da5537a Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 14:48:04 +0300 Subject: [PATCH 08/16] Follower Toast Status Added the removed tracker for the follower toast --- .../java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java b/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java index 422a9e58..c1285006 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/misc/FollowerIndicator.java @@ -14,6 +14,7 @@ import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; +import ps.reso.instaeclipse.utils.feature.FeatureStatusTracker; import ps.reso.instaeclipse.utils.toast.CustomToast; public class FollowerIndicator { @@ -137,6 +138,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { }); XposedBridge.log("βœ… Hooked follower status method in: " + userClassName + "." + followerStatusMethod); + FeatureStatusTracker.setHooked("ShowFollowerToast"); } catch (Exception e) { XposedBridge.log("❌ Error hooking follower status: " + e.getMessage()); From 2bc3098cc5f8dfdac819e62697daa03e94b64e92 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 15:20:29 +0300 Subject: [PATCH 09/16] Enhance disable tracking links Added new URL tracking parameters --- .../reso/instaeclipse/mods/ads/TrackingLinkDisable.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/ads/TrackingLinkDisable.java b/app/src/main/java/ps/reso/instaeclipse/mods/ads/TrackingLinkDisable.java index dc35ffb7..e843b6be 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/ads/TrackingLinkDisable.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/ads/TrackingLinkDisable.java @@ -22,14 +22,19 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { return; } String x = clipData.getItemAt(0).getText().toString(); - if (x.contains("https://www.instagram.com/") && x.contains("?igsh=")) { // Global - param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?igsh=.*", "")); + if (x.contains("https://www.instagram.com/") && (x.contains("igsh=") || (x.contains("ig_rid=")))) { // Global + param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?.*", "")); } else if (x.contains("https://www.instagram.com/") && x.contains("?utm_source=")) { // Stories param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?utm_source=.*", "")); } else if (x.contains("https://www.instagram.com/") && x.contains("?story_media_id=")){ // Highlights param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?story_media_id=.*", "")); } + // Saved-by rule: match saved-by or saved_by anywhere in query + else if (x.contains("https://www.instagram.com/") && + x.matches("(?i).*saved[-_]by.*")) { + param.args[0] = ClipData.newPlainText("URL", x.replaceAll("\\?.*", "")); + } } } From 4d8e9c79d5925992ea6d4f6f139122b0c081f2be Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 15:34:40 +0300 Subject: [PATCH 10/16] Clear cache while restarting Updated the restart function to clear Instagram's cache automatically. --- .../utils/dialog/DialogUtils.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java index dbe6b380..53a6f01e 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java @@ -22,6 +22,7 @@ import android.widget.TextView; import android.widget.Toast; +import java.io.File; import java.util.Objects; import de.robv.android.xposed.XposedBridge; @@ -255,9 +256,10 @@ private static View createDivider(Context context) { return divider; } - private static void restartInstagram(Context context) { + private static void restartInstagram(Context context) { // Restart Instagram and Remove its cache try { Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.instagram.android"); + clearInstagramCache(context); if (intent != null) { intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); @@ -271,6 +273,33 @@ private static void restartInstagram(Context context) { } } + private static void clearInstagramCache(Context context) { // Clear Instagram Cache + try { + File cacheDir = context.getCacheDir(); + if (cacheDir != null && cacheDir.exists()) { + XposedBridge.log(""); + deleteRecursive(cacheDir); + XposedBridge.log("InstaEclipse: Cache cleared"); + } else { + XposedBridge.log("InstaEclipse: Cache dir not found"); + } + } catch (Exception e) { + XposedBridge.log("InstaEclipse: Failed to clear cache - " + e.getMessage()); + } + } + + private static void deleteRecursive(File fileOrDirectory) { // Helper method + if (fileOrDirectory.isDirectory()) { + File[] children = fileOrDirectory.listFiles(); + if (children != null) { + for (File child : children) { + deleteRecursive(child); + } + } + } + fileOrDirectory.delete(); + } + // ==== SECTIONS ==== @SuppressLint("SetTextI18n") @@ -681,7 +710,7 @@ private static void showRestartSection(Context context) { layout.setGravity(Gravity.CENTER_HORIZONTAL); TextView message = new TextView(context); - message.setText("Restart Instagram to apply changes?"); + message.setText("⚠️ Restart Instagram and remove its cache?!"); message.setTextColor(Color.WHITE); message.setTextSize(18f); message.setGravity(Gravity.CENTER); From 7be1e2ac35d97def7943b87dec49791e8e0331f1 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 16:54:23 +0300 Subject: [PATCH 11/16] Update enable reels within DM Fixed the switches. --- .../mods/network/Interceptor.java | 2 +- .../utils/dialog/DialogUtils.java | 113 +++++++++++++----- 2 files changed, 81 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java index a6a8a940..453f4f09 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/network/Interceptor.java @@ -89,7 +89,7 @@ protected void beforeHookedMethod(MethodHookParam param) { if (FeatureFlags.disableFeed) { shouldDrop |= uri.getPath().endsWith("/feed/timeline/"); } - if (FeatureFlags.disableReels) { + if (FeatureFlags.disableReels && !FeatureFlags.disableReelsExceptDM) { shouldDrop |= uri.getPath().endsWith("/qp/batch_fetch/") || uri.getPath().contains("api/v1/clips") || uri.getPath().contains("clips") diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java index 75b7a71c..9fc4739f 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/dialog/DialogUtils.java @@ -529,42 +529,72 @@ private static void showAdOptions(Context context) { private static void showDistractionOptions(Context context) { LinearLayout layout = createSwitchLayout(context); - // Create all child switches + // Child switches + Switch disableStoriesSwitch = createSwitch(context, "Disable Stories", FeatureFlags.disableStories); + Switch disableFeedSwitch = createSwitch(context, "Disable Feed", FeatureFlags.disableFeed); + Switch disableReelsSwitch = createSwitch(context, "Disable Reels", FeatureFlags.disableReels); + Switch onlyInDMSwitch = createSwitch(context, "Disable Reels Except in DMs", FeatureFlags.disableReelsExceptDM); + Switch disableExploreSwitch = createSwitch(context, "Disable Explore", FeatureFlags.disableExplore); + Switch disableCommentsSwitch = createSwitch(context, "Disable Comments", FeatureFlags.disableComments); + Switch[] switches = new Switch[]{ - createSwitch(context, "Disable Stories", FeatureFlags.disableStories), - createSwitch(context, "Disable Feed", FeatureFlags.disableFeed), - createSwitch(context, "Disable Reels", FeatureFlags.disableReels), - createSwitch(context, "Disable Reels Except in DMs", FeatureFlags.disableReelsExceptDM), - createSwitch(context, "Disable Explore", FeatureFlags.disableExplore), - createSwitch(context, "Disable Comments", FeatureFlags.disableComments) + disableStoriesSwitch, + disableFeedSwitch, + disableReelsSwitch, + onlyInDMSwitch, + disableExploreSwitch, + disableCommentsSwitch }; - // Create Enable/Disable All switch + // Enable/Disable All @SuppressLint("UseSwitchCompatOrMaterialCode") Switch enableAllSwitch = createSwitch(context, "Enable/Disable All", areAllEnabled(switches)); - // Master listener + // Master switch listener enableAllSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { for (Switch s : switches) { s.setChecked(isChecked); + s.setEnabled(true); + } + if (!isChecked) { + onlyInDMSwitch.setChecked(false); + onlyInDMSwitch.setEnabled(false); } }); - // Individual child listeners - for (Switch s : switches) { + // Parent-child logic for Reels + disableReelsSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + onlyInDMSwitch.setEnabled(isChecked); + if (!isChecked) { + onlyInDMSwitch.setChecked(false); // turn off child immediately + onlyInDMSwitch.setEnabled(false); + } + updateMasterSwitch(enableAllSwitch, switches, disableReelsSwitch, onlyInDMSwitch); + SettingsManager.saveAllFlags(); + }); + + // Child logic for "Except in DMs" + onlyInDMSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (isChecked && !disableReelsSwitch.isChecked()) { + // Auto-enable parent if user enables child + disableReelsSwitch.setChecked(true); + } + updateMasterSwitch(enableAllSwitch, switches, disableReelsSwitch, onlyInDMSwitch); + SettingsManager.saveAllFlags(); + }); + + // All other switches + for (Switch s : new Switch[]{disableStoriesSwitch, disableFeedSwitch, disableExploreSwitch, disableCommentsSwitch}) { s.setOnCheckedChangeListener((buttonView, isChecked) -> { - enableAllSwitch.setOnCheckedChangeListener(null); - enableAllSwitch.setChecked(areAllEnabled(switches)); - enableAllSwitch.setOnCheckedChangeListener((buttonView2, isChecked2) -> { - for (Switch s2 : switches) { - s2.setChecked(isChecked2); - } - }); + updateMasterSwitch(enableAllSwitch, switches, disableReelsSwitch, onlyInDMSwitch); SettingsManager.saveAllFlags(); }); } - // Add to layout + // Init "Except in DMs" state + onlyInDMSwitch.setEnabled(disableReelsSwitch.isChecked()); + + // Layout building layout.addView(createDivider(context)); layout.addView(createEnableAllSwitch(context, enableAllSwitch)); layout.addView(createDivider(context)); @@ -573,20 +603,33 @@ private static void showDistractionOptions(Context context) { layout.addView(s); } - // Show the dialog showSectionDialog(context, "Distraction-Free Instagram 🧘", layout, () -> { - FeatureFlags.disableStories = switches[0].isChecked(); - FeatureFlags.disableFeed = switches[1].isChecked(); - FeatureFlags.disableReels = switches[2].isChecked(); - FeatureFlags.disableReelsExceptDM = switches[3].isChecked(); - FeatureFlags.disableExplore = switches[4].isChecked(); - FeatureFlags.disableComments = switches[5].isChecked(); + FeatureFlags.disableStories = disableStoriesSwitch.isChecked(); + FeatureFlags.disableFeed = disableFeedSwitch.isChecked(); + FeatureFlags.disableReels = disableReelsSwitch.isChecked(); + FeatureFlags.disableReelsExceptDM = onlyInDMSwitch.isChecked(); + FeatureFlags.disableExplore = disableExploreSwitch.isChecked(); + FeatureFlags.disableComments = disableCommentsSwitch.isChecked(); }); SettingsManager.saveAllFlags(); } + private static void updateMasterSwitch(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch enableAllSwitch, Switch[] switches, + @SuppressLint("UseSwitchCompatOrMaterialCode") Switch disableReelsSwitch, @SuppressLint("UseSwitchCompatOrMaterialCode") Switch onlyInDMSwitch) { + enableAllSwitch.setOnCheckedChangeListener(null); + enableAllSwitch.setChecked(areAllEnabled(switches)); + enableAllSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { + for (Switch s : switches) { + s.setChecked(isChecked); + } + onlyInDMSwitch.setEnabled(disableReelsSwitch.isChecked()); + }); + } + + + private static void showMiscOptions(Context context) { LinearLayout layout = createSwitchLayout(context); @@ -823,11 +866,13 @@ private static Switch createSwitch(Context context, String label, boolean defaul private static ColorStateList createThumbColor() { return new ColorStateList( new int[][]{ - new int[]{android.R.attr.state_checked}, // Checked - new int[]{-android.R.attr.state_checked} // Unchecked + new int[]{-android.R.attr.state_enabled}, // Disabled + new int[]{android.R.attr.state_checked}, // Checked + new int[]{-android.R.attr.state_checked} // Unchecked }, new int[]{ - Color.parseColor("#448AFF"), // ON + Color.parseColor("#555555"), // Disabled + Color.parseColor("#448AFF"), // ON Color.parseColor("#FFFFFF") // OFF } ); @@ -836,12 +881,14 @@ private static ColorStateList createThumbColor() { private static ColorStateList createTrackColor() { return new ColorStateList( new int[][]{ - new int[]{android.R.attr.state_checked}, - new int[]{-android.R.attr.state_checked} + new int[]{-android.R.attr.state_enabled}, // Disabled + new int[]{android.R.attr.state_checked}, // Checked + new int[]{-android.R.attr.state_checked} // Unchecked }, new int[]{ - Color.parseColor("#1C4C78"), // ON - Color.parseColor("#CFD8DC") // OFF + Color.parseColor("#777777"), // Disabled + Color.parseColor("#1C4C78"), // ON + Color.parseColor("#CFD8DC") // OFF } ); } From 7d2481a0c02554861357d538a8db28252c0f77b2 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 18:07:38 +0300 Subject: [PATCH 12/16] Fix a bug with import config Fixed a bug that caused an infinite loop --- .../mods/devops/config/ConfigManager.java | 103 +++++++++--------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/mods/devops/config/ConfigManager.java b/app/src/main/java/ps/reso/instaeclipse/mods/devops/config/ConfigManager.java index aed4f0c1..0242ff63 100644 --- a/app/src/main/java/ps/reso/instaeclipse/mods/devops/config/ConfigManager.java +++ b/app/src/main/java/ps/reso/instaeclipse/mods/devops/config/ConfigManager.java @@ -1,5 +1,7 @@ package ps.reso.instaeclipse.mods.devops.config; +import static ps.reso.instaeclipse.utils.feature.FeatureFlags.isImportingConfig; + import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -21,57 +23,60 @@ public class ConfigManager { // Import meta config from clipboard public static void importConfigFromClipboard(Context context) { - android.app.ProgressDialog progress = new android.app.ProgressDialog(context); - progress.setMessage("Importing config..."); - progress.setCancelable(false); - progress.show(); - - new Thread(() -> { - try { - ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - if (clipboard == null || !clipboard.hasPrimaryClip()) { - return; - } - - ClipData clipData = clipboard.getPrimaryClip(); - if (clipData == null || clipData.getItemCount() == 0) { - return; - } - - CharSequence clipText = clipData.getItemAt(0).getText(); - if (clipText == null || clipText.length() == 0) { - return; - } - - String json = clipText.toString().trim(); - if (!json.startsWith("{") || !json.endsWith("}")) { - return; - } - - File dest = new File(context.getFilesDir(), "mobileconfig/mc_overrides.json"); - if (!Objects.requireNonNull(dest.getParentFile()).exists()) { - dest.getParentFile().mkdirs(); - } - - try (FileOutputStream fos = new FileOutputStream(dest, false)) { - fos.write(json.getBytes(StandardCharsets.UTF_8)); - fos.flush(); + if (isImportingConfig) { + android.app.ProgressDialog progress = new android.app.ProgressDialog(context); + progress.setMessage("Importing config..."); + progress.setCancelable(false); + progress.show(); + + new Thread(() -> { + try { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboard == null || !clipboard.hasPrimaryClip()) { + return; + } + + ClipData clipData = clipboard.getPrimaryClip(); + if (clipData == null || clipData.getItemCount() == 0) { + return; + } + + CharSequence clipText = clipData.getItemAt(0).getText(); + if (clipText == null || clipText.length() == 0) { + return; + } + + String json = clipText.toString().trim(); + if (!json.startsWith("{") || !json.endsWith("}")) { + return; + } + + File dest = new File(context.getFilesDir(), "mobileconfig/mc_overrides.json"); + if (!Objects.requireNonNull(dest.getParentFile()).exists()) { + dest.getParentFile().mkdirs(); + } + + try (FileOutputStream fos = new FileOutputStream(dest, false)) { + fos.write(json.getBytes(StandardCharsets.UTF_8)); + fos.flush(); + } + + new Handler(Looper.getMainLooper()).post(() -> { + progress.dismiss(); + Toast.makeText(context, "βœ… Imported into mc_overrides.json", Toast.LENGTH_LONG).show(); + XposedBridge.log("InstaEclipse | βœ… JSON imported from clipboard into mc_overrides.json"); + }); + + } catch (Exception e) { + XposedBridge.log("InstaEclipse | ❌ Clipboard import failed: " + e.getMessage()); + new Handler(Looper.getMainLooper()).post(() -> { + progress.dismiss(); + Toast.makeText(context, "❌ Failed to import config", Toast.LENGTH_LONG).show(); + }); } + }).start(); + } - new Handler(Looper.getMainLooper()).post(() -> { - progress.dismiss(); - Toast.makeText(context, "βœ… Imported into mc_overrides.json", Toast.LENGTH_LONG).show(); - XposedBridge.log("InstaEclipse | βœ… JSON imported from clipboard into mc_overrides.json"); - }); - - } catch (Exception e) { - XposedBridge.log("InstaEclipse | ❌ Clipboard import failed: " + e.getMessage()); - new Handler(Looper.getMainLooper()).post(() -> { - progress.dismiss(); - Toast.makeText(context, "❌ Failed to import config", Toast.LENGTH_LONG).show(); - }); - } - }).start(); } // Export meta config to Device From c0c974d80d7b28bdc3539a3729b32678b75c32d1 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 19:33:08 +0300 Subject: [PATCH 13/16] Add the new contributors Added Oct and HalfManBear to the contributors list Co-Authored-By: HalfManBear <89969229+halfmanbear@users.noreply.github.com> Co-Authored-By: oct <142801165+oct888@users.noreply.github.com> --- .../java/ps/reso/instaeclipse/fragments/HomeFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ps/reso/instaeclipse/fragments/HomeFragment.java b/app/src/main/java/ps/reso/instaeclipse/fragments/HomeFragment.java index c2aa3dab..ebcc7acc 100644 --- a/app/src/main/java/ps/reso/instaeclipse/fragments/HomeFragment.java +++ b/app/src/main/java/ps/reso/instaeclipse/fragments/HomeFragment.java @@ -141,7 +141,9 @@ private void setupContributorsAndSpecialThanks(View rootView) { new Contributor("ReSo7200", "https://github.com/ReSo7200", "https://linkedin.com/in/abdalhaleem-altamimi", null), new Contributor("frknkrc44", "https://github.com/frknkrc44", null, null), new Contributor("BrianML", "https://github.com/brianml31", null, "https://t.me/instamoon_channel"), - new Contributor("silvzr", "https://github.com/silvzr", null, null) + new Contributor("silvzr", "https://github.com/silvzr", null, null), + new Contributor("oct", "https://github.com/oct888", null, null), + new Contributor("HalfManBear", "https://github.com/halfmanbear", null, null) ); List specialThanks = Arrays.asList( From 8ddbc5573d84714e3adf5b9389f41f906f659b20 Mon Sep 17 00:00:00 2001 From: Abdul Date: Fri, 15 Aug 2025 19:34:22 +0300 Subject: [PATCH 14/16] Version 0.4.3 Update module to version 0.4.3 --- app/build.gradle | 4 ++-- .../reso/instaeclipse/utils/version/VersionCheckUtility.java | 2 +- app/src/main/res/values/strings.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 08d08a5a..57f91d72 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "ps.reso.instaeclipse" minSdkVersion 28 targetSdk 34 - versionCode 9 - versionName '0.4.2' + versionCode 10 + versionName '0.4.3' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/ps/reso/instaeclipse/utils/version/VersionCheckUtility.java b/app/src/main/java/ps/reso/instaeclipse/utils/version/VersionCheckUtility.java index 8e83ec28..24736102 100644 --- a/app/src/main/java/ps/reso/instaeclipse/utils/version/VersionCheckUtility.java +++ b/app/src/main/java/ps/reso/instaeclipse/utils/version/VersionCheckUtility.java @@ -15,7 +15,7 @@ public class VersionCheckUtility { - private static final String CURRENT_VERSION = "0.4.2"; // Current version + private static final String CURRENT_VERSION = "0.4.3"; // Current version private static final String VERSION_CHECK_URL = "https://raw.githubusercontent.com/ReSo7200/InstaEclipse/refs/heads/main/version.json"; // JSON URL public static void checkForUpdates(Context context) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a5682709..d48125d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ InstaEclipse - v0.4.2 Beta + v0.4.3 Beta Home Features Help From d01e3f709aa654340ce282d150a4cec2b28b3d53 Mon Sep 17 00:00:00 2001 From: Abdul <47777771+ReSo7200@users.noreply.github.com> Date: Fri, 15 Aug 2025 19:37:54 +0300 Subject: [PATCH 15/16] Update version.json --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 1f99d2aa..69e92c8f 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "latest_version": "0.4.2", + "latest_version": "0.4.3", "update_url": "https://github.com/ReSo7200/InstaEclipse/releases/latest" } From 4f3ab389f0300d0f4919348f2034452589c6c5f5 Mon Sep 17 00:00:00 2001 From: Abdul <47777771+ReSo7200@users.noreply.github.com> Date: Fri, 15 Aug 2025 19:38:47 +0300 Subject: [PATCH 16/16] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a363fdb7..b2d369ca 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ Force stop Instagram and **clear its cache** to apply the changes properly. - [BrianML](https://github.com/brianml31) - [silvzr](https://github.com/silvzr) - [oct888](https://github.com/oct888) +- [HalfManBear](https://github.com/halfmanbear) ## πŸ™Œ Special Thanks - [xHookman](https://github.com/xHookman)