diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java
index 746939aa..c178845e 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java
@@ -170,7 +170,7 @@ abstract public class CommandHandler extends TextEditingHandler {
protected void changeLang() {
suggestionOps.cancelDelayedAccept();
stopVoiceInput();
- ChangeLanguageDialog.show(this, mInputMode.getSequence(), textField.getComposingText());
+ new ChangeLanguageDialog(getFinalContext(), this::setLang).show();
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/TraditionalT9.java b/app/src/main/java/io/github/sspanak/tt9/ime/TraditionalT9.java
index 022be18e..1f3eeb60 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ime/TraditionalT9.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ime/TraditionalT9.java
@@ -11,7 +11,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.DataStore;
@@ -21,7 +20,6 @@ import io.github.sspanak.tt9.ime.modes.InputModeKind;
import io.github.sspanak.tt9.languages.LanguageCollection;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.UI;
-import io.github.sspanak.tt9.ui.dialogs.ChangeLanguageDialog;
import io.github.sspanak.tt9.ui.dialogs.PopupDialog;
import io.github.sspanak.tt9.ui.dialogs.RequestPermissionDialog;
import io.github.sspanak.tt9.util.Logger;
@@ -122,12 +120,6 @@ public class TraditionalT9 extends MainViewHandler {
if (!message.isEmpty()) {
UI.toastLong(this, message);
- } else if (ChangeLanguageDialog.INTENT_SET_LANGUAGE.equals(intent.getStringExtra(ChangeLanguageDialog.INTENT_SET_LANGUAGE))) {
- onResume(
- intent.getStringExtra(ChangeLanguageDialog.PARAMETER_LANGUAGE),
- intent.getStringExtra(ChangeLanguageDialog.PARAMETER_SEQUENCE),
- intent.getStringExtra(ChangeLanguageDialog.PARAMETER_WORD)
- );
}
return result;
@@ -184,24 +176,6 @@ public class TraditionalT9 extends MainViewHandler {
}
- private void onResume(@Nullable String langStringId, @Nullable String sequence, @Nullable String word) {
- int languageId;
- try {
- langStringId = langStringId == null ? "(null)" : langStringId;
- languageId = Integer.parseInt(langStringId);
- } catch (NumberFormatException e) {
- Logger.e(LOG_TAG, "Can not resume typing. Failed to parse language ID '" + langStringId + "'. " + e);
- return;
- }
-
- if (word != null && !word.isEmpty() && sequence != null && !sequence.isEmpty()) {
- mInputMode.setSequence(sequence);
- }
-
- setLang(languageId);
- }
-
-
@Override
protected void onStop() {
stopVoiceInput();
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/PopupBuilder.java b/app/src/main/java/io/github/sspanak/tt9/ui/PopupBuilder.java
index 214e29a2..9b803686 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/PopupBuilder.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/PopupBuilder.java
@@ -5,12 +5,18 @@ import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import io.github.sspanak.tt9.ui.main.MainView;
+import io.github.sspanak.tt9.util.Logger;
import io.github.sspanak.tt9.util.sys.DeviceInfo;
public class PopupBuilder {
+ private static final String LOG_TAG = PopupBuilder.class.getSimpleName();
+
private final Context context;
private MaterialAlertDialogBuilder builder12;
private AlertDialog.Builder builderLegacy;
@@ -112,4 +118,35 @@ public class PopupBuilder {
public Dialog show() {
return DeviceInfo.AT_LEAST_ANDROID_12 ? builder12.show() : builderLegacy.show();
}
+
+
+ /**
+ * In IME context, it is not that easy to show a popup dialog. We need to make it "valid" using
+ * the hacks below. Made possible thanks to:
+ * Philipp
+ * Maher Abuthraa
+ */
+ public Dialog showFromIme(MainView main) {
+ if (main == null || main.getView() == null) {
+ Logger.e(LOG_TAG, "Cannot show a popup dialog. Main view is null.");
+ return null;
+ }
+
+ Dialog dialog = DeviceInfo.AT_LEAST_ANDROID_12 ? builder12.create() : builderLegacy.create();
+
+ Window window = dialog.getWindow();
+ if (window == null) {
+ Logger.e(LOG_TAG, "Cannot show a popup dialog. AlertDialog generated a Dialog with NULL Window.");
+ return null;
+ }
+
+ WindowManager.LayoutParams layout = window.getAttributes();
+ layout.token = main.getView().getWindowToken();
+ layout.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+ window.setAttributes(layout);
+ window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ dialog.show();
+
+ return dialog;
+ }
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AddWordDialog.java b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AddWordDialog.java
index 3c2da68a..a4719d36 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AddWordDialog.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AddWordDialog.java
@@ -57,13 +57,13 @@ public class AddWordDialog extends ThemedPopupDialog {
@Override
- void render() {
+ void show() {
if (message == null || word == null || word.isEmpty()) {
close();
return;
}
- super.render(this::onOK);
+ super.show(this::onOK);
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AutoUpdateMonolog.java b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AutoUpdateMonolog.java
index 2ce110c9..ede485c1 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AutoUpdateMonolog.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/AutoUpdateMonolog.java
@@ -36,7 +36,7 @@ public class AutoUpdateMonolog extends PopupDialog {
@Override
- void render() {
+ void show() {
if (language != null) {
DictionaryLoader.load(context, language);
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/ChangeLanguageDialog.java b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/ChangeLanguageDialog.java
index 439d4ed9..a38de1fd 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/ChangeLanguageDialog.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/ChangeLanguageDialog.java
@@ -2,65 +2,55 @@ package io.github.sspanak.tt9.ui.dialogs;
import android.app.Dialog;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.inputmethodservice.InputMethodService;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.annotation.Nullable;
import java.util.ArrayList;
-import java.util.HashMap;
import io.github.sspanak.tt9.R;
+import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.ime.helpers.Key;
import io.github.sspanak.tt9.languages.Language;
import io.github.sspanak.tt9.languages.LanguageCollection;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.LanguageRadioButton;
import io.github.sspanak.tt9.ui.PopupBuilder;
+import io.github.sspanak.tt9.ui.main.MainView;
import io.github.sspanak.tt9.util.ConsumerCompat;
import io.github.sspanak.tt9.util.sys.DeviceInfo;
public class ChangeLanguageDialog extends ThemedPopupDialog {
- public static final String TYPE = "tt9.popup_dialog.change_language";
- public static final String INTENT_SET_LANGUAGE = "tt9.popup_dialog.command.set_language";
- public static final String PARAMETER_LANGUAGE = "tt9.popup_dialog.parameter.language";
- public static final String PARAMETER_SEQUENCE = "tt9.popup_dialog.parameter.sequence";
- public static final String PARAMETER_WORD = "tt9.popup_dialog.parameter.word";
-
- private final ConsumerCompat> activityFinisher;
- private final LayoutInflater inflater;
private final ArrayList languages;
+ private final MainView mainView;
private final SettingsStore settings;
- private final String currentSequence;
- private final String currentWord;
- private final ArrayList radioButtonsCache = new ArrayList<>();
+ private final ConsumerCompat onLanguageChanged;
private Dialog popup;
+ private final ArrayList radioButtonsCache = new ArrayList<>();
- ChangeLanguageDialog(@NonNull AppCompatActivity context, @NonNull Intent intent, ConsumerCompat> activityFinisher) {
- super(context, null, R.style.TTheme_AddWord);
+ public ChangeLanguageDialog(@NonNull TraditionalT9 tt9, @Nullable ConsumerCompat changeHandler) {
+ super(tt9, null, R.style.TTheme_AddWord);
- this.activityFinisher = activityFinisher;
- title = context.getResources().getString(R.string.language_popup_title);
+ title = tt9.getResources().getString(R.string.language_popup_title);
OKLabel = null;
- inflater = context.getLayoutInflater();
- settings = new SettingsStore(context);
+ mainView = tt9.getMainView();
+ settings = tt9.getSettings();
languages = LanguageCollection.getAll(settings.getEnabledLanguageIds(), true);
-
- currentSequence = intent.getStringExtra(PARAMETER_SEQUENCE);
- currentWord = intent.getStringExtra(PARAMETER_WORD);
+ onLanguageChanged = changeHandler;
}
private void onClick(View button) {
- changeLanguage(button.getId());
+ if (onLanguageChanged != null) {
+ onLanguageChanged.accept(button.getId());
+ }
+ close();
}
@@ -85,7 +75,10 @@ public class ChangeLanguageDialog extends ThemedPopupDialog {
return false;
}
- changeLanguage(languageId);
+ if (onLanguageChanged != null) {
+ onLanguageChanged.accept(languageId);
+ }
+ close();
return true;
}
@@ -113,25 +106,6 @@ public class ChangeLanguageDialog extends ThemedPopupDialog {
popup.dismiss();
popup = null;
}
- activityFinisher.accept(null);
- }
-
-
- private void changeLanguage(int languageId) {
- detachRadioButtons();
- if (popup != null) {
- popup.dismiss();
- popup = null;
- }
-
- if (activityFinisher != null) {
- HashMap messages = new HashMap<>();
- messages.put(INTENT_SET_LANGUAGE, INTENT_SET_LANGUAGE);
- messages.put(PARAMETER_LANGUAGE, String.valueOf(languageId));
- messages.put(PARAMETER_SEQUENCE, currentSequence);
- messages.put(PARAMETER_WORD, currentWord);
- activityFinisher.accept(messages);
- }
}
@@ -148,7 +122,7 @@ public class ChangeLanguageDialog extends ThemedPopupDialog {
private View generateRadioButtons() {
final int currentLanguageId = settings.getInputLanguage();
- final View view = inflater.inflate(R.layout.popup_language_select, null);
+ final View view = View.inflate(context, R.layout.popup_language_select, null);
final LinearLayout radioGroup = view.findViewById(R.id.language_select_list);
radioButtonsCache.clear();
@@ -169,31 +143,14 @@ public class ChangeLanguageDialog extends ThemedPopupDialog {
}
- @Override
- void render() {
+ public void show() {
popup = new PopupBuilder(context)
- .setCancelable(false)
+ .setCancelable(true)
.setTitle(title)
.setMessage(message)
.setNegativeButton(true, this::close)
.setOnKeyListener(this)
.setView(generateRadioButtons())
- .show();
- }
-
-
- /**
- * Open a popup dialog containing a list of the enabled languages. After a language is selected,
- * "currentSequence" and "currentWord" are passed back to the IME, in case it wants to recompose them.
- */
- public static void show(InputMethodService ims, String currentSequence, String currentWord) {
- Intent intent = new Intent(ims, PopupDialogActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- intent.putExtra(PARAMETER_DIALOG_TYPE, TYPE);
- intent.putExtra(PARAMETER_SEQUENCE, currentSequence);
- intent.putExtra(PARAMETER_WORD, currentWord);
- ims.startActivity(intent);
+ .showFromIme(mainView);
}
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialog.java b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialog.java
index 6e04e7e1..84e6adee 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialog.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialog.java
@@ -36,7 +36,7 @@ abstract public class PopupDialog implements DialogInterface.OnKeyListener {
return false;
}
- protected void render(Runnable OKAction) {
+ protected void show(Runnable OKAction) {
new PopupBuilder(context)
.setCancelable(false)
.setTitle(title)
@@ -47,5 +47,5 @@ abstract public class PopupDialog implements DialogInterface.OnKeyListener {
.show();
}
- abstract void render();
+ abstract void show();
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialogActivity.java b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialogActivity.java
index d93ae32d..59f7aa02 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialogActivity.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/dialogs/PopupDialogActivity.java
@@ -6,8 +6,6 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
-import java.util.HashMap;
-
import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.util.Logger;
@@ -20,7 +18,7 @@ public class PopupDialogActivity extends AppCompatActivity {
super.onCreate(savedData);
PopupDialog dialog = getDialog();
if (dialog != null) {
- dialog.render();
+ dialog.show();
} else {
onDialogClose("");
}
@@ -36,7 +34,6 @@ public class PopupDialogActivity extends AppCompatActivity {
return switch (popupType) {
case AddWordDialog.TYPE -> new AddWordDialog(this, i, this::onDialogClose);
case AutoUpdateMonolog.TYPE -> new AutoUpdateMonolog(this, i, this::onDialogClose);
- case ChangeLanguageDialog.TYPE -> new ChangeLanguageDialog(this, i, this::onDialogClose);
default -> {
Logger.w(LOG_TAG, "Unknown popup type: '" + popupType + "'. Not displaying anything.");
yield null;
@@ -53,23 +50,10 @@ public class PopupDialogActivity extends AppCompatActivity {
startService(intent);
}
- private void onDialogClose(HashMap messages) {
- finish();
- Intent intent = new Intent(this, TraditionalT9.class);
- if (messages != null) {
- intent.putExtra(PopupDialog.INTENT_CLOSE, "");
- for (String key : messages.keySet()) {
- intent.putExtra(key, messages.get(key));
- }
- }
-
- startService(intent);
- }
-
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- onDialogClose((String) null);
+ onDialogClose(null);
}
}
diff --git a/app/src/main/res/values-v31/styles.xml b/app/src/main/res/values-v31/styles.xml
index e4a3dbfd..5ce08f8e 100644
--- a/app/src/main/res/values-v31/styles.xml
+++ b/app/src/main/res/values-v31/styles.xml
@@ -37,8 +37,8 @@