Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
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;
Expand All @@ -14,7 +12,6 @@
import java.io.FileOutputStream;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import de.robv.android.xposed.XposedBridge;
import ps.reso.instaeclipse.utils.feature.FeatureFlags;
Expand All @@ -23,62 +20,57 @@ public class ConfigManager {

// Import meta config from clipboard
public static void importConfigFromClipboard(Context context) {
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();
});

android.app.ProgressDialog progress = new android.app.ProgressDialog(context);
progress.setMessage("Importing config...");
progress.setCancelable(false);
progress.show();

new Thread(() -> {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
try {
if (clipboard == null || !clipboard.hasPrimaryClip()) throw new IllegalStateException("Empty clipboard");

ClipData clipData = clipboard.getPrimaryClip();
if (clipData == null || clipData.getItemCount() == 0) throw new IllegalStateException("Empty clipboard");

CharSequence clipText = clipData.getItemAt(0).getText();
if (clipText == null || clipText.length() == 0) throw new IllegalStateException("Empty clipboard");

String json = clipText.toString().trim();
if (!json.startsWith("{") || !json.endsWith("}")) throw new IllegalArgumentException("Clipboard is not valid JSON");

File dest = new File(context.getFilesDir(), "mobileconfig/mc_overrides.json");
File parent = dest.getParentFile();
if (parent != null && !parent.exists()) parent.mkdirs();

try (FileOutputStream fos = new FileOutputStream(dest, false)) {
fos.write(json.getBytes(StandardCharsets.UTF_8));
fos.flush();
}
}).start();
}

// (Optional) clear clipboard to avoid stale re-imports later
try { clipboard.setPrimaryClip(ClipData.newPlainText("", "")); } catch (Exception ignored) {}

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();
});
} finally {
// 100% guarantee the flag is OFF after an attempt
FeatureFlags.isImportingConfig = false;
}
}).start();
}


// Export meta config to Device
public static void exportCurrentDevConfig(Context context) {
if (!FeatureFlags.isExportingConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

import ps.reso.instaeclipse.utils.feature.FeatureFlags;

public class JsonImportActivity extends Activity {

private static final int PICK_JSON_FILE = 1234;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FeatureFlags.isImportingConfig = false;
openJsonPicker();
}

Expand All @@ -30,21 +33,34 @@ private void openJsonPicker() {
startActivityForResult(Intent.createChooser(intent, "Select JSON Config"), PICK_JSON_FILE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_JSON_FILE && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
String json = readStream(inputStream);
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("json", json);
clipboard.setPrimaryClip(clip);

} catch (Exception e) {
Toast.makeText(this, "❌ Failed to read file: " + e.getMessage(), Toast.LENGTH_LONG).show();
if (requestCode == PICK_JSON_FILE) {
if (resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
String json = readStream(inputStream).trim();

// Validate before enabling the flag
if (json.startsWith("{") && json.endsWith("}")) {
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("json", json);
clipboard.setPrimaryClip(clip);

FeatureFlags.isImportingConfig = true; // <- only now turn it ON
//Toast.makeText(this, "Config copied, returning to import…", Toast.LENGTH_SHORT).show();
} else {
FeatureFlags.isImportingConfig = false;
Toast.makeText(this, "❌ Not a valid JSON file", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
FeatureFlags.isImportingConfig = false; // <- make sure we reset on error
Toast.makeText(this, "❌ Failed to read file: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
} else {
// User pressed back / cancelled
FeatureFlags.isImportingConfig = false; // <- ensure OFF on cancel
Toast.makeText(this, "Cancelled or no file selected", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Cancelled or no file selected", Toast.LENGTH_SHORT).show();
}
finish(); // Done, return to Instagram
}
Expand Down
42 changes: 24 additions & 18 deletions app/src/main/java/ps/reso/instaeclipse/mods/ui/UIHookManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,31 @@ protected void afterHookedMethod(MethodHookParam param) {
});

// Hook onResume - Instagram Main
XposedHelpers.findAndHookMethod("com.instagram.mainactivity.InstagramMainActivity", classLoader, "onResume", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
final Activity activity = (Activity) param.thisObject;
currentActivity = activity;
activity.runOnUiThread(() -> {
try {
setupHooks(activity);
addGhostEmojiNextToInbox(activity, isAnyGhostOptionEnabled());
if (FeatureFlags.isImportingConfig) {
FeatureFlags.isImportingConfig = false;
ConfigManager.importConfigFromClipboard(activity);
}

} catch (Exception ignored) {
XposedHelpers.findAndHookMethod(
"com.instagram.mainactivity.InstagramMainActivity",
classLoader,
"onResume",
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
final Activity activity = (Activity) param.thisObject;
currentActivity = activity;
activity.runOnUiThread(() -> {
try {
setupHooks(activity);
addGhostEmojiNextToInbox(activity, isAnyGhostOptionEnabled());

if (FeatureFlags.isImportingConfig) {
// De-bounce: flip it off first so it won't re-trigger on next onResume
FeatureFlags.isImportingConfig = false;
ConfigManager.importConfigFromClipboard(activity);
}
} catch (Exception ignored) {}
});
}
});
}
});
}
);


// Hook getBottomSheetNavigator - Instagram Main
BottomSheetHookUtil.hookBottomSheetNavigator(Module.dexKitBridge);
Expand Down