diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..7a4a3ea2424c09fbe48d455aed1eaa94d9124835 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 78ecd02275d47861a0319f3e952728ff0495b5ef..d0e5c480bf3e2417bee67812010c183a771c653f 100644 --- a/build.gradle +++ b/build.gradle @@ -15,23 +15,12 @@ android { namespace 'com.android.inputmethod.latin' - // Required if using classes in android.test.runner - useLibrary 'android.test.runner' - - // Required if using classes in android.test.base - useLibrary 'android.test.base' - - // Required if using classes in android.test.mock - useLibrary 'android.test.mock' - defaultConfig { minSdkVersion 30 targetSdkVersion 34 versionName "1.0" applicationId 'com.android.inputmethod.latin' - testApplicationId 'com.android.inputmethod.latin.tests' - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = false signingConfig signingConfigs.debug @@ -65,12 +54,6 @@ android { java.srcDirs = ['common/src', 'java/src'] manifest.srcFile 'java/AndroidManifest.xml' } - - androidTest { - res.srcDirs = ['tests/res'] - java.srcDirs = ['tests/src'] - manifest.srcFile "tests/AndroidManifest.xml" - } } @@ -90,6 +73,7 @@ android { repositories { maven { url "../../../prebuilts/fullsdk-darwin/extras/android/m2repository" } maven { url "../../../prebuilts/fullsdk-linux/extras/android/m2repository" } + maven { url "https://gitlab.e.foundation/api/v4/groups/9/-/packages/maven" } mavenCentral() google() jcenter() @@ -101,12 +85,5 @@ dependencies { implementation 'com.google.android.material:material:1.9.0' implementation 'androidx.preference:preference:1.2.1' - testImplementation 'junit:junit:4.12' - androidTestImplementation "org.mockito:mockito-core:1.9.5" - androidTestImplementation 'com.google.dexmaker:dexmaker:1.2' - androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test:rules:1.1.1' - androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' - androidTestImplementation 'androidx.annotation:annotation:1.0.0' + implementation("foundation.e:elib:0.0.1-alpha11") } diff --git a/java/Android.bp b/java/Android.bp index 054065ebf89a1d6b8ae1b80127368f346b40b7a7..895ac1cfa171e9fce7f327604cb14e4c6f5c5f2a 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -47,6 +47,7 @@ android_app { "androidx.legacy_legacy-support-v4", "androidx.recyclerview_recyclerview", "androidx.viewpager2_viewpager2", + "elib", ], // Do not compress dictionary files to mmap dict data runtime diff --git a/java/res/drawable/btn_keyboard_key_action_normal_you.xml b/java/res/drawable/btn_keyboard_key_action_normal_you.xml index ab61dafdfd5fed2341359d0326dd3120d17856c2..09f5b819e5bde36137980a6cf3e884d06ed77544 100644 --- a/java/res/drawable/btn_keyboard_key_action_normal_you.xml +++ b/java/res/drawable/btn_keyboard_key_action_normal_you.xml @@ -5,5 +5,11 @@ --> - + + + + diff --git a/java/res/drawable/btn_keyboard_key_action_pressed_you.xml b/java/res/drawable/btn_keyboard_key_action_pressed_you.xml index 6eb85b3d493e4f7331ab9c3e7d6e98fee3a46539..e3cada54c0f1115140e0743c5ba17543a720b9ed 100644 --- a/java/res/drawable/btn_keyboard_key_action_pressed_you.xml +++ b/java/res/drawable/btn_keyboard_key_action_pressed_you.xml @@ -5,5 +5,11 @@ --> - + + + + diff --git a/java/res/drawable/ic_ime_switch.xml b/java/res/drawable/ic_ime_switch.xml new file mode 100644 index 0000000000000000000000000000000000000000..128cd4451e48b59a197477b5f246d3c54a5dc0ee --- /dev/null +++ b/java/res/drawable/ic_ime_switch.xml @@ -0,0 +1,9 @@ + + + diff --git a/java/res/drawable/sym_keyboard_delete_you.xml b/java/res/drawable/sym_keyboard_delete_you.xml index e7ebb4cb63f9d86ab7c73e79966d83be22b0d774..022e71ca372998827816c790c46bdc0ec58726a8 100644 --- a/java/res/drawable/sym_keyboard_delete_you.xml +++ b/java/res/drawable/sym_keyboard_delete_you.xml @@ -10,6 +10,6 @@ android:viewportHeight="24" android:autoMirrored="true"> diff --git a/java/res/drawable/sym_keyboard_language_switch_you.xml b/java/res/drawable/sym_keyboard_language_switch_you.xml index 72be14325ea070efba77cf9b7411efd5a782d917..b3805d7547b2d8b72329449ba4a74b8a809f715e 100644 --- a/java/res/drawable/sym_keyboard_language_switch_you.xml +++ b/java/res/drawable/sym_keyboard_language_switch_you.xml @@ -9,6 +9,6 @@ android:viewportWidth="960" android:viewportHeight="960"> diff --git a/java/res/drawable/sym_keyboard_settings_you.xml b/java/res/drawable/sym_keyboard_settings_you.xml index 9e6b7a5bfa670671c46ce265ebb9615a475d71c2..88110c6f786823630818b42cf569b38bd4e99f5b 100644 --- a/java/res/drawable/sym_keyboard_settings_you.xml +++ b/java/res/drawable/sym_keyboard_settings_you.xml @@ -9,6 +9,6 @@ android:viewportWidth="960" android:viewportHeight="960"> diff --git a/java/res/drawable/sym_keyboard_smiley_you.xml b/java/res/drawable/sym_keyboard_smiley_you.xml index f176197048e59cb7c2307023106a57b8295845dc..f66538080d5c13f879cc5512ad9d5d1cddab8c3e 100644 --- a/java/res/drawable/sym_keyboard_smiley_you.xml +++ b/java/res/drawable/sym_keyboard_smiley_you.xml @@ -9,6 +9,6 @@ android:viewportWidth="960" android:viewportHeight="960"> diff --git a/java/res/layout/main_keyboard_frame.xml b/java/res/layout/main_keyboard_frame.xml index ebf746679c603d9899ed78f591c665bfcf1c806d..e27a993dda99d660f67c47ea9edd0caca57fb7fb 100644 --- a/java/res/layout/main_keyboard_frame.xml +++ b/java/res/layout/main_keyboard_frame.xml @@ -18,28 +18,46 @@ */ --> - + android:layout_gravity="bottom"> - - + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:orientation="vertical"> - - - + + + + + + + + + diff --git a/java/res/values-night/themes-you-colors.xml b/java/res/values-night/themes-you-colors.xml index a7c03065cd7765437509b52ca3437c22cfbcd881..059dee23c8b70abc9bb14b5c0eed0b428ae8fede 100644 --- a/java/res/values-night/themes-you-colors.xml +++ b/java/res/values-night/themes-you-colors.xml @@ -4,19 +4,6 @@ SPDX-License-Identifier: Apache-2.0 --> - @android:color/system_neutral1_900 - - @android:color/system_neutral1_800 - @android:color/system_neutral1_900 - @android:color/system_neutral1_50 - @android:color/system_neutral1_700 - @android:color/system_neutral2_300 - @android:color/system_neutral1_50 - @android:color/system_accent1_400 - @android:color/system_accent1_600 - @android:color/system_neutral1_50 - @android:color/system_neutral1_50 - @android:color/system_neutral1_50 @android:color/system_neutral1_400 @android:color/system_neutral1_50 diff --git a/java/res/values/e_strings.xml b/java/res/values/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..b4012e6a6c8db24c980ba6af44a8a61467c3bbe0 --- /dev/null +++ b/java/res/values/e_strings.xml @@ -0,0 +1,19 @@ + + + + Speech to text + diff --git a/java/res/values/themes-you-colors.xml b/java/res/values/themes-you-colors.xml index 0dc99259de30702e4c1121ca73aae6d5e9f0d2f4..02589ba914e481ece2322eec03551e298783652c 100644 --- a/java/res/values/themes-you-colors.xml +++ b/java/res/values/themes-you-colors.xml @@ -4,19 +4,19 @@ SPDX-License-Identifier: Apache-2.0 --> - @android:color/system_neutral1_50 + @color/e_keyboard_background - @android:color/system_neutral1_0 - @android:color/system_neutral1_100 - @android:color/system_neutral1_900 - @android:color/system_accent2_100 - @android:color/system_neutral2_200 - @android:color/system_neutral1_900 - @android:color/system_accent1_200 - @android:color/system_accent1_400 - @android:color/system_neutral1_900 - @android:color/system_neutral1_900 - @android:color/system_neutral1_900 + @color/e_keyboard_key_background + @color/e_keyboard_key_pressed_background + @color/e_keyboard_key_text + @color/e_keyboard_functional_background + @color/e_keyboard_functional_pressed_background + @color/keyboard_key_text_color_you + @color/e_keyboard_key_enter_background + @color/e_keyboard_key_enter_pressed_background + @color/keyboard_key_text_color_you + @color/keyboard_key_text_color_you + @color/keyboard_background_you @android:color/system_neutral1_400 @android:color/system_neutral1_900 diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index a1ce2ea320b71c42d5a9143f69c650bc920b1d0e..2ee5fddf7ff401a813c5ed111a9bbc0d2e733ee2 100644 --- a/java/res/xml/key_styles_common.xml +++ b/java/res/xml/key_styles_common.xml @@ -80,7 +80,8 @@ + latin:keyActionFlags="noKeyPreview" + latin:backgroundType="functional" /> diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 3c891716d9b8cc0d402869e86b8ee5b94a678dd6..f4972588702c4e23574c4bb93347b301121db686 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -33,6 +33,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.inputmethodservice.InputMethodService; @@ -51,12 +52,16 @@ import android.view.Display; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; +import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import android.widget.ImageButton; import androidx.annotation.NonNull; @@ -75,6 +80,7 @@ import com.android.inputmethod.event.InputTransaction; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.keyboard.KeyboardLayoutSet; import com.android.inputmethod.keyboard.KeyboardSwitcher; import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback; @@ -104,6 +110,8 @@ import com.android.inputmethod.latin.utils.StatsUtilsManager; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; import com.android.inputmethod.latin.utils.ViewLayoutUtils; +import foundation.e.stt.AccountInfoContentProvider; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -131,6 +139,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private static final int MAX_SPACESLIDE_CHARS = 32; + private static final String KEY_STT_KEYBOARD = "foundation.e.stt/.MurenaWhisperInputService"; + /** * A broadcast intent action to hide the software keyboard. */ @@ -210,6 +220,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public final UIHandler mHandler = new UIHandler(this); + private ImageButton mFloatingButton; + private final Rect mFloatingButtonTouchableBounds = new Rect(); + public static final class UIHandler extends LeakGuardHandlerWrapper { private static final int MSG_UPDATE_SHIFT_STATE = 0; private static final int MSG_PENDING_IMS_CALLBACK = 1; @@ -808,6 +821,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen cleanupInternalStateForFinishInput(); } } + KeyboardLayoutSet.onKeyboardThemeChanged(); super.onConfigurationChanged(conf); } @@ -856,6 +870,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mIsHardwareAcceleratedDrawingEnabled); } + private boolean isSttKeyboardActivated() { + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + List enabledImeList = inputMethodManager.getEnabledInputMethodList(); + for (InputMethodInfo inputMethodInfo : enabledImeList) { + if (inputMethodInfo.getId().equals(KEY_STT_KEYBOARD)) { + return true; + } + } + return false; + } + + private void switchToSttIme() { + if (isSttKeyboardActivated()) { + switchInputMethod(KEY_STT_KEYBOARD); + } + } + @Override public void setInputView(final View view) { super.setInputView(view); @@ -866,6 +897,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (hasSuggestionStripView()) { mSuggestionStripView.setListener(this, view); } + + mFloatingButton = mInputView.findViewById(R.id.floating_button); + mFloatingButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + switchToSttIme(); + } + }); + manageFloatingButtonVisibility(); + } + + private void manageFloatingButtonVisibility() { + final SettingsValues currentSettingsValues = mSettings.getCurrent(); + if (shouldShowFloatingButton() + && currentSettingsValues.mInputAttributes.mShouldShowSuggestions) { + mFloatingButton.setVisibility(View.VISIBLE); + } else { + mFloatingButton.setVisibility(View.GONE); + } + } + + private boolean shouldShowFloatingButton() { + return AccountInfoContentProvider.isPremiumAccount(getApplicationContext()) + && isSttKeyboardActivated() && hasSuggestionStripView(); } @Override @@ -882,6 +937,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void onStartInputView(final EditorInfo editorInfo, final boolean restarting) { mHandler.onStartInputView(editorInfo, restarting); mStatsUtilsManager.onStartInputView(); + + if (mFloatingButton != null) { + manageFloatingButtonVisibility(); + } } @Override @@ -1280,12 +1339,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int touchBottom = inputHeight; outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; outInsets.touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom); + extendTouchableRegionForFloatingButton(outInsets); } outInsets.contentTopInsets = visibleTopY; outInsets.visibleTopInsets = visibleTopY; mInsetsUpdater.setInsets(outInsets); } + private void extendTouchableRegionForFloatingButton(final InputMethodService.Insets outInsets) { + if (mFloatingButton == null || mFloatingButton.getVisibility() != View.VISIBLE) { + return; + } + if (!(mInputView instanceof ViewGroup)) { + return; + } + final int width = mFloatingButton.getWidth(); + final int height = mFloatingButton.getHeight(); + if (width <= 0 || height <= 0) { + return; + } + mFloatingButtonTouchableBounds.set(0, 0, width, height); + ((ViewGroup) mInputView).offsetDescendantRectToMyCoords( + mFloatingButton, mFloatingButtonTouchableBounds); + outInsets.touchableRegion.union(mFloatingButtonTouchableBounds); + } + public void startShowingInputView(final boolean needsToLoadKeyboard) { mIsExecutingStartShowingInputView = true; // This {@link #showWindow(boolean)} will eventually call back diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java index 90221512ffd752d2f6569e058d815b415ef84d53..109cace92f1c796b8ccea58606094416a22d8ae9 100644 --- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java +++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java @@ -86,6 +86,7 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) { Log.i(TAG, "Boot has been completed"); toggleAppIcon(context); + disableVoiceKey(context); } else if (Intent.ACTION_LOCALE_CHANGED.equals(intentAction)) { Log.i(TAG, "System locale changed"); KeyboardLayoutSet.onSystemLocaleChanged(); @@ -156,4 +157,15 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } + + public static void disableVoiceKey(final Context context) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, false) && + !prefs.getBoolean(Settings.PREF_FORCED_DISABLE_VOICE_INPUT_KEY, false)) { + prefs.edit() + .putBoolean(Settings.PREF_VOICE_INPUT_KEY, false) + .putBoolean(Settings.PREF_FORCED_DISABLE_VOICE_INPUT_KEY, true) + .apply(); + } + } } diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 803153e7b694d0d569c557c933c8b1fe4a20cca2..420b61a32c93cbf601511a1aa0c3c5cb8ec01735 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -58,6 +58,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang // PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead. public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode"; public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key"; + // Added by /e/ to disable old enabled voice key + public static final String PREF_FORCED_DISABLE_VOICE_INPUT_KEY = "pref_forced_disable_voice_input_key"; public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary"; public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key"; // PREF_AUTO_CORRECTION_THRESHOLD_OBSOLETE is obsolete. Use PREF_AUTO_CORRECTION instead. diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index c4219b9d50ab47922e933f614cb88dd60f3b52cc..6055b791602398bf42f0d6b6b1bf0587b584268e 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -377,7 +377,7 @@ public class SettingsValues { .remove(Settings.PREF_VOICE_MODE_OBSOLETE) .apply(); } - return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true); + return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, false); } public String dump() { diff --git a/java/src/foundation/e/stt/AccountInfoContentProvider.java b/java/src/foundation/e/stt/AccountInfoContentProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..a3344a3ebb31bb34d556b91f01a8a4c75e3e9381 --- /dev/null +++ b/java/src/foundation/e/stt/AccountInfoContentProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 MURENA SAS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package foundation.e.stt; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.net.Uri; +import android.content.Context; +import android.util.Log; + +public class AccountInfoContentProvider { + + private static final String TAG = "AccountInfoContentProvider"; + private static final Uri ACCOUNT_URI = Uri.parse("content://foundation.e.stt.provider/account"); + private static final String COLUMN_IS_PREMIUM = "is_premium"; + private static final int PREMIUM_VALUE = 1; + + public static boolean isPremiumAccount(Context context) { + Cursor cursor = null; + try { + ContentResolver resolver = context.getContentResolver(); + String[] projection = new String[] { COLUMN_IS_PREMIUM }; + cursor = resolver.query(ACCOUNT_URI, projection, null, null, null); + + if (cursor != null && cursor.moveToFirst()) { + int columnIndex = cursor.getColumnIndex(COLUMN_IS_PREMIUM); + if (columnIndex != -1) { + int value = cursor.getInt(columnIndex); + return value == PREMIUM_VALUE; + } + } + } catch (Exception e) { + Log.e(TAG, "Error failed to read status", e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + return false; + } +}