From a09d7bb63c1dfcaf1305d4a2420c7e012e62393c Mon Sep 17 00:00:00 2001
From: Next Alone <12210746+NextAlone@users.noreply.github.com>
Date: Sun, 3 Nov 2024 05:54:33 +0800
Subject: [PATCH] feat: [WIP] add HyperOS AI in editor
Signed-off-by: Next Alone <12210746+NextAlone@users.noreply.github.com>
---
.../ui/Cells/TextSelectionHelper.java | 3 +-
.../ui/Components/EditTextBoldCursor.java | 104 +++++++++++++++++-
.../activity/ExperimentSettingActivity.java | 13 +++
.../xyz/nextalone/nnngram/utils/Defines.kt | 1 +
.../main/res/values-zh/strings_nullgram.xml | 1 +
TMessagesProj/src/main/res/values/ids.xml | 1 +
.../src/main/res/values/strings_nullgram.xml | 1 +
7 files changed, 121 insertions(+), 3 deletions(-)
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 c5a015c80a..0c9d7a10bf 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java
@@ -1424,11 +1424,12 @@ 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));
+ menu.add(Menu.NONE, BLOCK, 4, LocaleController.getString(R.string.block));
return true;
}
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 9c8d180d27..a85b9d7306 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java
@@ -20,12 +20,18 @@
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;
@@ -81,6 +87,7 @@
import java.util.List;
import xyz.nextalone.gen.Config;
+import xyz.nextalone.nnngram.utils.Log;
public class EditTextBoldCursor extends EditTextEffects {
@@ -183,6 +190,9 @@ 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) {
@@ -230,7 +240,7 @@ public void setShowDisableMarkdown(boolean show) {
showDisableMarkdown = show;
}
-
+
public void setHintText2(CharSequence text, boolean animated) {
if (hintAnimatedDrawable2 != null) {
hintAnimatedDrawable2.setText(text, !LocaleController.isRTL && animated);
@@ -1220,6 +1230,7 @@ public ActionMode startActionMode(ActionMode.Callback callback) {
callback.onCreateActionMode(floatingActionMode, floatingActionMode.getMenu());
extendActionMode(floatingActionMode, floatingActionMode.getMenu());
addUndoRedo(floatingActionMode.getMenu());
+ addHyperOsAi(floatingActionMode.getMenu());
floatingActionMode.invalidate();
getViewTreeObserver().addOnPreDrawListener(floatingToolbarPreDrawListener);
invalidate();
@@ -1243,16 +1254,105 @@ 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
+ return;
+ }
+
+ // Add AI menu item if it doesn't already exist
+ if (menu.findItem(R.id.hyperos_ai) == null) {
+ menu.add(Menu.NONE, R.id.hyperos_ai, 0, "AI")
+ .setAlphabeticShortcut('s')
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
+ }
+
@Override
public boolean onTextContextMenuItem(int id) {
if (id == R.id.menu_markdown) {
disableMarkdown = !disableMarkdown;
floatingActionMode.finish();
return true;
+ } else if (id == R.id.hyperos_ai) {
+ startHyperOsAiService();
+ 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/activity/ExperimentSettingActivity.java b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/activity/ExperimentSettingActivity.java
index bee60679b9..8b89fb9c40 100644
--- a/TMessagesProj/src/main/java/xyz/nextalone/nnngram/activity/ExperimentSettingActivity.java
+++ b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/activity/ExperimentSettingActivity.java
@@ -19,6 +19,8 @@
package xyz.nextalone.nnngram.activity;
+import static org.telegram.messenger.AndroidUtilities.getSystemProperty;
+
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
@@ -64,6 +66,7 @@ public class ExperimentSettingActivity extends BaseActivity {
private int linkedUserRow;
private int overrideChannelAliasRow;
private int showRPCErrorRow;
+ private int enableXiaomiHyperAiRow;
private int specialRow;
private int special2Row;
@@ -219,6 +222,11 @@ protected void onItemClick(View view, int position, float x, float y) {
if (view instanceof TextCheckCell) {
((TextCheckCell) view).setChecked(Config.ignoreChatStrict);
}
+ } else if (position == enableXiaomiHyperAiRow) {
+ Config.toggleEnableXiaomiHyperAi();
+ if (view instanceof TextCheckCell) {
+ ((TextCheckCell) view).setChecked(Config.enableXiaomiHyperAi);
+ }
}
}
@@ -252,6 +260,9 @@ protected void updateRows() {
}
var user = UserConfig.getInstance(currentAccount).getCurrentUser();
showRPCErrorRow = user != null && user.developer() ? addRow("showRPCError") : -1;
+ if (getSystemProperty("ro.mi.os.version.name") != null) {
+ enableXiaomiHyperAiRow = addRow("enableXiaomiHyperAi");
+ }
experiment2Row = addRow();
if (Config.showHiddenSettings) {
@@ -391,6 +402,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, boole
textCell.setTextAndCheck(LocaleController.getString("enablePanguOnReceiving", R.string.enablePanguOnReceiving), Config.enablePanguOnReceiving, true);
} else if (position == ignoreChatStrictRow) {
textCell.setTextAndCheck("", Config.ignoreChatStrict, true);
+ } else if (position == enableXiaomiHyperAiRow) {
+ textCell.setTextAndCheck(LocaleController.getString(R.string.enableXiaomiHyperAi), Config.enableXiaomiHyperAi, true);
}
break;
}
diff --git a/TMessagesProj/src/main/java/xyz/nextalone/nnngram/utils/Defines.kt b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/utils/Defines.kt
index ee5e1f1cac..72e2352bb1 100644
--- a/TMessagesProj/src/main/java/xyz/nextalone/nnngram/utils/Defines.kt
+++ b/TMessagesProj/src/main/java/xyz/nextalone/nnngram/utils/Defines.kt
@@ -246,6 +246,7 @@ object Defines {
@BooleanConfig(true) const val showTextRegular = "showTextRegular"
@BooleanConfig(true) const val showTextQuote = "showTextQuote"
@BooleanConfig(true) const val showTextMonoCode = "showTextMonoCode"
+ @BooleanConfig(false) const val enableXiaomiHyperAi = "enableXiaomiHyperAi"
/**
* 数组中元素未找到的下标,值为-1
diff --git a/TMessagesProj/src/main/res/values-zh/strings_nullgram.xml b/TMessagesProj/src/main/res/values-zh/strings_nullgram.xml
index fede99fa7a..c25bcd0f3b 100644
--- a/TMessagesProj/src/main/res/values-zh/strings_nullgram.xml
+++ b/TMessagesProj/src/main/res/values-zh/strings_nullgram.xml
@@ -378,4 +378,5 @@
禁用视频重力检测
隐藏标题代理入口
加入频道后自动静音
+ 在输入框中显示小米澎湃AI
diff --git a/TMessagesProj/src/main/res/values/ids.xml b/TMessagesProj/src/main/res/values/ids.xml
index a14bae4357..d76b134795 100644
--- a/TMessagesProj/src/main/res/values/ids.xml
+++ b/TMessagesProj/src/main/res/values/ids.xml
@@ -79,4 +79,5 @@
+
diff --git a/TMessagesProj/src/main/res/values/strings_nullgram.xml b/TMessagesProj/src/main/res/values/strings_nullgram.xml
index b94cf90d58..afa45742a2 100644
--- a/TMessagesProj/src/main/res/values/strings_nullgram.xml
+++ b/TMessagesProj/src/main/res/values/strings_nullgram.xml
@@ -391,4 +391,5 @@
Disable gravity detection in video
Hide proxy entry in title
Auto mute after joining channel
+ Enable Xiaomi HyperAI in editor