From da679d619efbc459b782c6ad0fb85cfcd54ef1e7 Mon Sep 17 00:00:00 2001 From: Maksym H Date: Mon, 14 Nov 2022 23:53:15 +0100 Subject: [PATCH] Android: simplify input dialog --- .../java/com/multicraft/game/GameActivity.kt | 41 +++++++++++-------- src/client/game.cpp | 2 +- src/gui/guiConfirmRegistration.cpp | 2 +- src/gui/guiFormSpecMenu.cpp | 13 +++++- src/gui/modalMenu.cpp | 33 +-------------- src/gui/modalMenu.h | 1 - src/porting_android.cpp | 9 ++-- src/porting_android.h | 7 +--- 8 files changed, 44 insertions(+), 64 deletions(-) diff --git a/build/android/app/src/main/java/com/multicraft/game/GameActivity.kt b/build/android/app/src/main/java/com/multicraft/game/GameActivity.kt index 1952ed843..d859c1ac0 100644 --- a/build/android/app/src/main/java/com/multicraft/game/GameActivity.kt +++ b/build/android/app/src/main/java/com/multicraft/game/GameActivity.kt @@ -37,6 +37,7 @@ import com.multicraft.game.MainActivity.Companion.radius import com.multicraft.game.databinding.InputTextBinding import com.multicraft.game.databinding.MultilineInputBinding import com.multicraft.game.helpers.* +import com.multicraft.game.helpers.ApiLevelHelper.isOreo import org.libsdl.app.SDLActivity class GameActivity : SDLActivity() { @@ -65,7 +66,7 @@ class GameActivity : SDLActivity() { return getContext().applicationInfo.nativeLibraryDir + "/libMultiCraft.so" } - public override fun onCreate(savedInstanceState: Bundle?) { + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) hasKeyboard = resources.configuration.hardKeyboardHidden == HARDKEYBOARDHIDDEN_NO @@ -103,10 +104,9 @@ class GameActivity : SDLActivity() { } @Suppress("unused") - fun showDialog( - @Suppress("UNUSED_PARAMETER") s: String?, - hint: String?, current: String?, editType: Int - ) { + fun showDialog(hint: String?, current: String?, editType: Int) { + messageReturnValue = "" + messageReturnCode = -1 if (editType == 1) runOnUiThread { showMultiLineDialog(hint, current) } else @@ -117,9 +117,10 @@ class GameActivity : SDLActivity() { isInputActive = true val builder = AlertDialog.Builder(this, R.style.FullScreenDialogStyle) val binding = InputTextBinding.inflate(layoutInflater) - val hintText = hint?.ifEmpty { + var hintText: String = hint?.ifEmpty { resources.getString(if (editType == 3) R.string.input_password else R.string.input_text) - } + }.toString() + hintText = hintText.replace(":$".toRegex(), "") binding.input.hint = hintText builder.setView(binding.root) val alertDialog = builder.create() @@ -129,16 +130,19 @@ class GameActivity : SDLActivity() { editText.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager var inputType = InputType.TYPE_CLASS_TEXT - if (editType == 3) + if (editType == 3) { inputType = inputType or InputType.TYPE_TEXT_VARIATION_PASSWORD + if (isOreo()) + editText.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO + } editText.inputType = inputType editText.setSelection(editText.text?.length ?: 0) // for Android OS editText.setOnEditorActionListener { _: TextView?, KeyCode: Int, _: KeyEvent? -> if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false return@setOnEditorActionListener true @@ -149,8 +153,8 @@ class GameActivity : SDLActivity() { editText.setOnKeyListener { _: View?, KeyCode: Int, _: KeyEvent? -> if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false return@setOnKeyListener true @@ -159,15 +163,15 @@ class GameActivity : SDLActivity() { } binding.input.setEndIconOnClickListener { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false } binding.rl.setOnClickListener { window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN) messageReturnValue = current.toString() - messageReturnCode = -1 + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false } @@ -180,7 +184,7 @@ class GameActivity : SDLActivity() { alertDialog.setOnCancelListener { window.setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN) messageReturnValue = current.toString() - messageReturnCode = -1 + messageReturnCode = 0 isInputActive = false } } @@ -189,9 +193,10 @@ class GameActivity : SDLActivity() { isInputActive = true val builder = AlertDialog.Builder(this, R.style.FullScreenDialogStyle) val binding = MultilineInputBinding.inflate(layoutInflater) - val hintText = hint?.ifEmpty { + var hintText: String = hint?.ifEmpty { resources.getString(R.string.input_text) - } + }.toString() + hintText = hintText.replace(":$".toRegex(), "") binding.multiInput.hint = hintText builder.setView(binding.root) val alertDialog = builder.create() @@ -205,8 +210,8 @@ class GameActivity : SDLActivity() { editText.setOnEditorActionListener { _: TextView?, KeyCode: Int, _: KeyEvent? -> if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false return@setOnEditorActionListener true @@ -217,8 +222,8 @@ class GameActivity : SDLActivity() { editText.setOnKeyListener { _: View?, KeyCode: Int, _: KeyEvent? -> if (KeyCode == KeyEvent.KEYCODE_ENTER || KeyCode == KeyEvent.KEYCODE_ENDCALL) { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false return@setOnKeyListener true @@ -227,8 +232,8 @@ class GameActivity : SDLActivity() { } binding.multiInput.setEndIconOnClickListener { imm.hideSoftInputFromWindow(editText.windowToken, 0) - messageReturnCode = 0 messageReturnValue = editText.text.toString() + messageReturnCode = 0 alertDialog.dismiss() isInputActive = false } diff --git a/src/client/game.cpp b/src/client/game.cpp index 24faeeb5c..37643001f 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2141,7 +2141,7 @@ void Game::openConsole(float scale, const wchar_t *line) #if defined(__ANDROID__) || defined(__IOS__) if (!porting::hasRealKeyboard()) { - porting::showInputDialog(gettext("OK"), "", "", 2); + porting::showInputDialog("", "", 2); m_android_chat_open = true; } else { #endif diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 879ee593b..42ae8a106 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -261,7 +261,7 @@ bool GUIConfirmRegistration::OnEvent(const SEvent &event) #if defined(__ANDROID__) || defined(__IOS__) bool GUIConfirmRegistration::getAndroidUIInput() { - if (!hasAndroidUIInput() || m_jni_field_name != "password") + if (m_jni_field_name.empty() || m_jni_field_name != "password") return false; // still waiting diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 06c2ca200..94ad2ce16 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -3595,7 +3595,7 @@ void GUIFormSpecMenu::legacySortElements(core::list::Iterator fro #if defined(__ANDROID__) || defined(__IOS__) bool GUIFormSpecMenu::getAndroidUIInput() { - if (!hasAndroidUIInput()) + if (m_jni_field_name.empty()) return false; // still waiting @@ -3616,6 +3616,17 @@ bool GUIFormSpecMenu::getAndroidUIInput() std::string text = porting::getInputDialogValue(); ((gui::IGUIEditBox *)element)->setText(utf8_to_wide(text).c_str()); + + // Create event + gui::IGUIElement *focus = Environment->getFocus(); + if (focus) { + SEvent e; + e.EventType = EET_GUI_EVENT; + e.GUIEvent.Caller = focus; + e.GUIEvent.Element = 0; + e.GUIEvent.EventType = gui::EGET_EDITBOX_CHANGED; + element->OnEvent(e); + } } return false; } diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index 361d33104..43169ec91 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -39,7 +39,7 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, core::rect(0, 0, 100, 100)), #if defined(__ANDROID__) || defined(__IOS__) - m_jni_field_name(""), + m_jni_field_name(), #endif m_menumgr(menumgr), m_remap_dbl_click(remap_dbl_click) @@ -287,14 +287,6 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) return retval; m_jni_field_name = field_name; - /*~ Imperative, as in "Enter/type in text". - Don't forget the space. */ - std::string message = gettext("Enter "); - std::string label = wide_to_utf8(getLabelByID(hovered->getID())); - if (label.empty()) - label = "text"; - message += gettext(label.c_str()); - message += ":"; // single line text input int type = 2; @@ -307,7 +299,7 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) if (((gui::IGUIEditBox *)hovered)->isPasswordBox()) type = 3; - porting::showInputDialog(gettext("OK"), "", + porting::showInputDialog(wide_to_utf8(getLabelByID(hovered->getID())), wide_to_utf8(((gui::IGUIEditBox *)hovered)->getText()), type); return retval; } @@ -385,24 +377,3 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) } return false; } - -#if defined(__ANDROID__) || defined(__IOS__) -bool GUIModalMenu::hasAndroidUIInput() -{ - // no dialog shown - if (m_jni_field_name.empty()) - return false; - - // still waiting - if (porting::getInputDialogState() == -1) - return true; - - // no value abort dialog processing - if (porting::getInputDialogState() != 0) { - m_jni_field_name.clear(); - return false; - } - - return true; -} -#endif diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index 8a002b3ae..f7c7b5063 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -56,7 +56,6 @@ public: virtual bool pausesGame() { return false; } // Used for pause menu #if defined(__ANDROID__) || defined(__IOS__) virtual bool getAndroidUIInput() { return false; } - bool hasAndroidUIInput(); #endif protected: diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 80d90c2bd..850817d1b 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -211,22 +211,19 @@ void initializePathsAndroid() activityObj, mt_getAbsPath, "getCacheDir"); } -void showInputDialog(const std::string &acceptButton, const std::string &hint, - const std::string ¤t, int editType) +void showInputDialog(const std::string &hint, const std::string ¤t, int editType) { jmethodID showdialog = jnienv->GetMethodID(activityClass, "showDialog", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); + "(Ljava/lang/String;Ljava/lang/String;I)V"); FATAL_ERROR_IF(showdialog == nullptr, "porting::showInputDialog unable to find java show dialog method"); - jstring jacceptButton = jnienv->NewStringUTF(acceptButton.c_str()); jstring jhint = jnienv->NewStringUTF(hint.c_str()); jstring jcurrent = jnienv->NewStringUTF(current.c_str()); jint jeditType = editType; - jnienv->CallVoidMethod(activityObj, showdialog, - jacceptButton, jhint, jcurrent, jeditType); + jnienv->CallVoidMethod(activityObj, showdialog, jhint, jcurrent, jeditType); } void openURIAndroid(const std::string &url) diff --git a/src/porting_android.h b/src/porting_android.h index 65976b8d3..8a79ba8c9 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -41,20 +41,17 @@ void cleanupAndroid(); /** * Initializes path_* variables for Android - * @param env Android JNI environment */ void initializePathsAndroid(); /** * show text input dialog in java - * @param acceptButton text to display on accept button * @param hint hint to show * @param current initial value to display * @param editType type of texfield - * (1==multiline text input; 2==single line text input; 3=password field) + * (1 == multiline text input; 2 == single line text input; 3 == password field) */ -void showInputDialog(const std::string &acceptButton, - const std::string &hint, const std::string ¤t, int editType); +void showInputDialog(const std::string &hint, const std::string ¤t, int editType); void openURIAndroid(const std::string &url);