diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java index 0c9d7a10bf..1dff5954bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -82,8 +82,11 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import xyz.nextalone.gen.Config; +import xyz.nextalone.nnngram.helpers.HyperOsHelper; import xyz.nextalone.nnngram.helpers.TranslateHelper; public abstract class TextSelectionHelper { @@ -1420,22 +1423,43 @@ public void invalidate() { private static final int TRANSLATE = 3; private static final int BLOCK = 4; + private static final Map menus = new HashMap<>(); + private int getMenuIndex(int id, int defaultIndex) { + if (menus.containsKey(id)) { + Integer index = menus.get(id); + if (index != null) { + return index; + } + } + return defaultIndex; + } + private ActionMode.Callback createActionCallback() { final ActionMode.Callback callback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { - menu.removeItem(R.id.hyperos_ai); - menu.add(Menu.NONE, android.R.id.copy, 0, android.R.string.copy); - menu.add(Menu.NONE, R.id.menu_quote, 1, LocaleController.getString(R.string.Quote)); - menu.add(Menu.NONE, android.R.id.selectAll, 2, android.R.string.selectAll); - menu.add(Menu.NONE, TRANSLATE, 3, LocaleController.getString(R.string.TranslateMessage)); - menu.add(Menu.NONE, BLOCK, 4, LocaleController.getString(R.string.block)); + menus.clear(); + int index = 0; + if (HyperOsHelper.INSTANCE.isHyperAiAvailable(textSelectionOverlay.getContext())) { + menus.put(R.id.hyperos_ai, index); + menu.add(Menu.NONE, R.id.hyperos_ai, index++, "AI"); + } + menus.put(android.R.id.copy, index); + menu.add(Menu.NONE, android.R.id.copy, index++, android.R.string.copy); + menus.put(R.id.menu_quote, index); + menu.add(Menu.NONE, R.id.menu_quote, index++, LocaleController.getString(R.string.Quote)); + menus.put(android.R.id.selectAll, index); + menu.add(Menu.NONE, android.R.id.selectAll, index++, android.R.string.selectAll); + menus.put(TRANSLATE, index); + menu.add(Menu.NONE, TRANSLATE, index++, LocaleController.getString(R.string.TranslateMessage)); + menus.put(BLOCK, index); + menu.add(Menu.NONE, BLOCK, index, LocaleController.getString(R.string.block)); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - menu.getItem(1).setVisible(canShowQuote()); + menu.getItem(getMenuIndex(R.id.menu_quote, 0)).setVisible(canShowQuote()); MenuItem copyItem = menu.findItem(android.R.id.copy); if (copyItem != null) { copyItem.setVisible(canCopy()); @@ -1443,11 +1467,11 @@ public boolean onPrepareActionMode(ActionMode mode, Menu menu) { if (selectedView != null) { CharSequence charSequence = getText(selectedView, false); if (!canCopy()) { - menu.getItem(2).setVisible(false); + menu.getItem(getMenuIndex(android.R.id.selectAll, 2)).setVisible(false); } else if (multiselect || selectionStart <= 0 && selectionEnd >= charSequence.length() - 1) { - menu.getItem(2).setVisible(false); + menu.getItem(getMenuIndex(android.R.id.selectAll, 2)).setVisible(false); } else { - menu.getItem(2).setVisible(true); + menu.getItem(getMenuIndex(android.R.id.selectAll, 2)).setVisible(true); } } if (onTranslateListener != null && LanguageDetector.hasSupport() && getSelectedText() != null) { @@ -1469,7 +1493,7 @@ public boolean onPrepareActionMode(ActionMode mode, Menu menu) { private String translateFromLanguage = null; private void updateTranslateButton(Menu menu) { - menu.getItem(3).setVisible(!LanguageDetector.hasSupport() || translateFromLanguage == null || !TranslateHelper.isLanguageRestricted(translateFromLanguage)); + menu.getItem(getMenuIndex(TRANSLATE, 3)).setVisible(!LanguageDetector.hasSupport() || translateFromLanguage == null || !TranslateHelper.isLanguageRestricted(translateFromLanguage)); } @Override @@ -1517,6 +1541,15 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) { hideActions(); clear(true); return true; + } else if (itemId == R.id.hyperos_ai) { + CharSequence str = getSelectedText(); + if (str == null) { + return true; + } + HyperOsHelper.INSTANCE.startHyperOsAiService(textSelectionOverlay, str.toString()); + hideActions(); + clear(true); + return true; } else { clear(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index a85b9d7306..50bb07b3c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -20,18 +20,12 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.messenger.AndroidUtilities.getSystemProperty; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.app.Activity; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; @@ -87,7 +81,7 @@ import java.util.List; import xyz.nextalone.gen.Config; -import xyz.nextalone.nnngram.utils.Log; +import xyz.nextalone.nnngram.helpers.HyperOsHelper; public class EditTextBoldCursor extends EditTextEffects { @@ -190,9 +184,6 @@ public void run() { public static boolean disableMarkdown = Config.markdownDisabled; private boolean showDisableMarkdown = false; - public static boolean IS_HYPEROS = getSystemProperty("ro.mi.os.version.name") != null; - private static final String HYPEROS_NOTES_PKG = "com.miui.notes"; - private static final String HYPEROS_AI_SERVICE = "com.miui.notes.ai.AiTextWidgetService"; static { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { @@ -1256,24 +1247,7 @@ private void addUndoRedo(Menu menu) { private void addHyperOsAi(Menu menu) { // Check if is HyperOS - if (!IS_HYPEROS || !Config.enableXiaomiHyperAi) { - return; - } - - PackageManager packageManager = getContext().getPackageManager(); - if (packageManager == null) { - return; - } - - try { - // Retrieve package information for HyperOS Notes - PackageInfo packageInfo = packageManager.getPackageInfo(HYPEROS_NOTES_PKG, 0); - - if (packageInfo.versionCode < 1100) { - return; - } - } catch (PackageManager.NameNotFoundException e) { - // Package not found, exit gracefully + if (!HyperOsHelper.INSTANCE.isHyperAiAvailable(getContext())) { return; } @@ -1292,67 +1266,12 @@ public boolean onTextContextMenuItem(int id) { floatingActionMode.finish(); return true; } else if (id == R.id.hyperos_ai) { - startHyperOsAiService(); + HyperOsHelper.INSTANCE.startHyperOsAiService(this); return true; } return super.onTextContextMenuItem(id); } - private void startHyperOsAiService() { - try { - String currentPackage = getContext().getPackageName(); - Intent serviceIntent = new Intent(); - - // Pass the package name - serviceIntent.putExtra("packageName", currentPackage); - - // Handle selection logic - String selectedText = ""; - if (hasSelection()) { - int selectionStart = getSelectionStart(); - int selectionEnd = getSelectionEnd(); - if (selectionStart != selectionEnd) { - selectedText = getText().subSequence(selectionStart, selectionEnd).toString(); - } - } - serviceIntent.putExtra("selectedText", selectedText); - - // Store original view bounds - serviceIntent.putExtra("originalViewLeft", getLeft()); - serviceIntent.putExtra("originalViewTop", getTop()); - serviceIntent.putExtra("originalViewRight", getRight()); - serviceIntent.putExtra("originalViewBottom", getBottom()); - serviceIntent.putExtra("originalViewName", getClass().getName()); - serviceIntent.putExtra("isEditor", true); - - // Get the active screen location - int[] screenCoordinates = new int[2]; - Rect focusedRect = new Rect(); - getLocationOnScreen(screenCoordinates); - getFocusedRect(focusedRect); - focusedRect.offset(screenCoordinates[0], screenCoordinates[1]); - - Activity currentActivity = (Activity) getContext(); - if (currentActivity != null) { - Rect windowFrame = new Rect(); - currentActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(windowFrame); - - // Putting the visible window bounds into the Intent - serviceIntent.putExtra("left", windowFrame.left); - serviceIntent.putExtra("top", windowFrame.top); - serviceIntent.putExtra("right", windowFrame.right); - serviceIntent.putExtra("bottom", windowFrame.bottom); - serviceIntent.putExtra("taskId", currentActivity.getTaskId()); - } - - // Prepare and start the service - serviceIntent.setComponent(new ComponentName(HYPEROS_NOTES_PKG, HYPEROS_AI_SERVICE)); - getContext().startForegroundService(serviceIntent); - } catch (Exception e) { - Log.e("Failed to start HyperOS AI service", e); - } - } - private boolean shouldShowQuoteButton() { if (!hasSelection() || getSelectionStart() < 0 || getSelectionEnd() < 0 || getSelectionStart() == getSelectionEnd()) { return false; diff --git a/TMessagesProj/src/main/java/xyz/nextalone/nnngram/helpers/HyperOsHelper.kt b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/helpers/HyperOsHelper.kt new file mode 100644 index 0000000000..9b472e2482 --- /dev/null +++ b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/helpers/HyperOsHelper.kt @@ -0,0 +1,109 @@ +package xyz.nextalone.nnngram.helpers + +import android.app.Activity +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.Rect +import android.view.View +import android.widget.EditText +import org.telegram.messenger.AndroidUtilities +import xyz.nextalone.gen.Config +import xyz.nextalone.nnngram.utils.Log.e + +object HyperOsHelper { + private var IS_HYPEROS: Boolean = + AndroidUtilities.getSystemProperty("ro.mi.os.version.name") != null + private const val HYPEROS_NOTES_PKG: String = "com.miui.notes" + private const val HYPEROS_AI_SERVICE: String = "com.miui.notes.ai.AiTextWidgetService" + + + fun isHyperAiAvailable(context: Context): Boolean { + // Check if is HyperOS + if (!IS_HYPEROS || !Config.enableXiaomiHyperAi) { + return false + } + + val packageManager: PackageManager = context.packageManager ?: return false + + try { + // Retrieve package information for HyperOS Notes + val packageInfo = packageManager.getPackageInfo(HYPEROS_NOTES_PKG, 0) + + if (packageInfo.versionCode < 1100) { + return false + } + } catch (e: PackageManager.NameNotFoundException) { + // Package not found, exit gracefully + return false + } + return true + } + + @JvmOverloads + fun startHyperOsAiService(view: View, text: String = "") { + try { + val currentPackage: String = view.context.packageName + val serviceIntent = Intent() + + // Pass the package name + serviceIntent.putExtra("packageName", currentPackage) + + // Handle selection logic + var selectedText = "" + if (view is EditText) { + if (view.hasSelection()) { + val selectionStart: Int = view.selectionStart + val selectionEnd: Int = view.selectionEnd + if (selectionStart != selectionEnd) { + selectedText = + view.getText().subSequence(selectionStart, selectionEnd).toString() + } + } + } else { + selectedText = text + } + serviceIntent.putExtra("selectedText", selectedText) + + // Store original view bounds + serviceIntent.putExtra("originalViewLeft", view.left) + serviceIntent.putExtra("originalViewTop", view.top) + serviceIntent.putExtra("originalViewRight", view.right) + serviceIntent.putExtra("originalViewBottom", view.bottom) + serviceIntent.putExtra("originalViewName", javaClass.name) + serviceIntent.putExtra("isEditor", true) + + // Get the active screen location + val screenCoordinates = IntArray(2) + val focusedRect = Rect() + view.getLocationOnScreen(screenCoordinates) + view.getFocusedRect(focusedRect) + focusedRect.offset(screenCoordinates[0], screenCoordinates[1]) + + val currentActivity = view.context as Activity? + if (currentActivity != null) { + val windowFrame = Rect() + currentActivity.window.decorView.getWindowVisibleDisplayFrame(windowFrame) + + // Putting the visible window bounds into the Intent + serviceIntent.putExtra("left", windowFrame.left) + serviceIntent.putExtra("top", windowFrame.top) + serviceIntent.putExtra("right", windowFrame.right) + serviceIntent.putExtra("bottom", windowFrame.bottom) + serviceIntent.putExtra("taskId", currentActivity.taskId) + } + + // Prepare and start the service + serviceIntent.setComponent( + ComponentName( + HYPEROS_NOTES_PKG, + HYPEROS_AI_SERVICE + ) + ) + view.context.startForegroundService(serviceIntent) + } catch (e: Exception) { + e("Failed to start HyperOS AI service", e) + } + } +}