diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle index c6a364eac..b79a444d4 100644 --- a/bramble-android/build.gradle +++ b/bramble-android/build.gradle @@ -10,7 +10,7 @@ android { defaultConfig { minSdkVersion 16 - targetSdkVersion 26 + targetSdkVersion 28 versionCode 10109 versionName "1.1.9" consumerProguardFiles 'proguard-rules.txt' diff --git a/briar-android/build.gradle b/briar-android/build.gradle index 915248827..0badc68a8 100644 --- a/briar-android/build.gradle +++ b/briar-android/build.gradle @@ -21,7 +21,7 @@ android { defaultConfig { minSdkVersion 16 - targetSdkVersion 26 + targetSdkVersion 28 versionCode 10109 versionName "1.1.9" applicationId "org.briarproject.briar.android" @@ -117,7 +117,7 @@ dependencies { implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.google.zxing:core:3.3.3' implementation 'uk.co.samuelwall:material-tap-target-prompt:2.14.0' - implementation 'com.vanniktech:emoji-google:0.5.1' + implementation 'com.vanniktech:emoji-google:0.6.0' // later versions already use androidx implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1' // later versions already use androidx def glideVersion = '4.9.0' implementation("com.github.bumptech.glide:glide:$glideVersion") { diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml index 0afef62b0..210a409ad 100644 --- a/briar-android/src/main/AndroidManifest.xml +++ b/briar-android/src/main/AndroidManifest.xml @@ -73,7 +73,7 @@ android:label="@string/crash_report_title" android:launchMode="singleInstance" android:theme="@style/BriarTheme.NoActionBar" - android:windowSoftInputMode="stateHidden"> + android:windowSoftInputMode="adjustResize|stateHidden"> + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> + android:windowSoftInputMode="adjustResize|stateUnchanged"> @@ -145,7 +145,7 @@ android:name="org.briarproject.briar.android.privategroup.creation.CreateGroupActivity" android:label="@string/groups_create_group_title" android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity" - android:windowSoftInputMode="adjustResize"> + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> @@ -174,8 +174,7 @@ + android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"> @@ -184,8 +183,7 @@ + android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"> @@ -223,7 +221,7 @@ android:name="org.briarproject.briar.android.forum.CreateForumActivity" android:label="@string/create_forum_title" android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity" - android:windowSoftInputMode="adjustResize"> + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> @@ -292,7 +290,7 @@ android:name="org.briarproject.briar.android.blog.WriteBlogPostActivity" android:label="@string/blogs_write_blog_post" android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity" - android:windowSoftInputMode="stateVisible|adjustResize"> + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> @@ -302,7 +300,7 @@ android:name="org.briarproject.briar.android.blog.ReblogActivity" android:label="@string/blogs_reblog_button" android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity" - android:windowSoftInputMode="stateHidden"> + android:windowSoftInputMode="adjustResize|stateHidden"> @@ -312,7 +310,7 @@ android:name="org.briarproject.briar.android.blog.RssFeedImportActivity" android:label="@string/blogs_rss_feeds_import" android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity" - android:windowSoftInputMode="stateVisible|adjustResize"> + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> @@ -341,7 +339,7 @@ android:name="org.briarproject.briar.android.introduction.IntroductionActivity" android:label="@string/introduction_activity_title" android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity" - android:windowSoftInputMode="stateHidden|adjustResize"> + android:windowSoftInputMode="adjustResize|stateHidden"> @@ -369,7 +367,8 @@ + android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity" + android:windowSoftInputMode="adjustResize|stateAlwaysVisible"> @@ -424,7 +423,7 @@ android:name=".android.contact.add.remote.AddContactActivity" android:label="@string/add_contact_remotely_title_case" android:theme="@style/BriarTheme" - android:windowSoftInputMode="stateHidden|adjustResize"/> + android:windowSoftInputMode="adjustResize|stateHidden"/> MAX_AUTHOR_NAME_LENGTH; setError(authorNameWrapper, getString(R.string.name_too_long), error); boolean enabled = authorNameLength > 0 && !error; - authorNameInput - .setImeOptions(enabled ? IME_ACTION_NEXT : IME_ACTION_NONE); authorNameInput.setOnEditorActionListener(enabled ? this : null); nextButton.setEnabled(enabled); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/account/SetPasswordFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/account/SetPasswordFragment.java index d9cd65966..9895530d1 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/account/SetPasswordFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/account/SetPasswordFragment.java @@ -61,7 +61,6 @@ public class SetPasswordFragment extends SetupFragment { strengthMeter = v.findViewById(R.id.strength_meter); passwordEntryWrapper = v.findViewById(R.id.password_entry_wrapper); passwordEntry = v.findViewById(R.id.password_entry); - passwordEntry.requestFocus(); passwordConfirmationWrapper = v.findViewById(R.id.password_confirm_wrapper); passwordConfirmation = v.findViewById(R.id.password_confirm); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java index 49e86c469..b56385c86 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java @@ -2,7 +2,6 @@ package org.briarproject.briar.android.activity; import android.content.Context; import android.os.Bundle; -import android.os.IBinder; import android.support.annotation.LayoutRes; import android.support.annotation.UiThread; import android.support.v4.app.Fragment; @@ -12,7 +11,6 @@ import android.support.v7.widget.Toolbar; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.inputmethod.InputMethodManager; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; @@ -44,10 +42,10 @@ import javax.inject.Inject; import static android.arch.lifecycle.Lifecycle.State.STARTED; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; -import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT; import static java.util.logging.Level.INFO; import static java.util.logging.Logger.getLogger; import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; /** * Warning: Some activities don't extend {@link BaseActivity}. @@ -217,17 +215,6 @@ public abstract class BaseActivity extends AppCompatActivity }); } - public void showSoftKeyboard(View view) { - Object o = getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).showSoftInput(view, SHOW_IMPLICIT); - } - - public void hideSoftKeyboard(View view) { - IBinder token = view.getWindowToken(); - Object o = getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).hideSoftInputFromWindow(token, 0); - } - @UiThread public void handleDbException(DbException e) { supportFinishAfterTransition(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java index 0a3ab6994..9b8db53ef 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/RssFeedImportActivity.java @@ -32,6 +32,7 @@ import static android.view.View.VISIBLE; import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; public class RssFeedImportActivity extends BriarActivity { @@ -77,7 +78,6 @@ public class RssFeedImportActivity extends BriarActivity { if (actionId == IME_ACTION_DONE && importButton.isEnabled() && importButton.getVisibility() == VISIBLE) { publish(); - hideSoftKeyboard(urlInput); return true; } return false; @@ -123,6 +123,7 @@ public class RssFeedImportActivity extends BriarActivity { // hide import button, show progress bar importButton.setVisibility(GONE); progressBar.setVisibility(VISIBLE); + hideSoftKeyboard(urlInput); String url = validateAndNormaliseUrl(urlInput.getText().toString()); if (url == null) throw new AssertionError(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java index 1ea824b79..6e535d263 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java @@ -3,11 +3,8 @@ package org.briarproject.briar.android.blog; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; -import android.view.KeyEvent; import android.view.MenuItem; import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.db.DbException; @@ -44,7 +41,7 @@ import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_TEXT_L @MethodsNotNullByDefault @ParametersNotNullByDefault public class WriteBlogPostActivity extends BriarActivity - implements OnEditorActionListener, SendListener { + implements SendListener { private static final Logger LOG = Logger.getLogger(WriteBlogPostActivity.class.getName()); @@ -113,12 +110,6 @@ public class WriteBlogPostActivity extends BriarActivity component.inject(this); } - @Override - public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { - input.requestFocus(); - return true; - } - @Override public void onSendClick(@Nullable String text, List headers) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/AliasDialogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/AliasDialogFragment.java index b91256bef..9502ba86a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/AliasDialogFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/AliasDialogFragment.java @@ -21,9 +21,12 @@ import org.briarproject.briar.android.activity.BaseActivity; import javax.inject.Inject; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE; import static java.util.Objects.requireNonNull; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.util.StringUtils.toUtf8; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; +import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -76,12 +79,13 @@ public class AliasDialogFragment extends AppCompatDialogFragment { setButton.setOnClickListener(v1 -> onSetButtonClicked()); Button cancelButton = v.findViewById(R.id.cancelButton); - cancelButton.setOnClickListener(v1 -> getDialog().cancel()); + cancelButton.setOnClickListener(v1 -> onCancelButtonClicked()); return v; } private void onSetButtonClicked() { + hideSoftKeyboard(aliasEditText); String alias = aliasEditText.getText().toString().trim(); if (toUtf8(alias).length > MAX_AUTHOR_NAME_LENGTH) { aliasEditLayout.setError(getString(R.string.name_too_long)); @@ -91,4 +95,17 @@ public class AliasDialogFragment extends AppCompatDialogFragment { } } + private void onCancelButtonClicked() { + hideSoftKeyboard(aliasEditText); + getDialog().cancel(); + } + + @Override + public void onStart() { + super.onStart(); + requireNonNull(getDialog().getWindow()) + .setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_VISIBLE); + showSoftKeyboard(aliasEditText); + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java index 01bc51c3e..9b89740e3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java @@ -276,7 +276,7 @@ public class ConversationActivity extends BriarActivity textInputView.setSendController(sendController); textInputView.setMaxTextLength(MAX_PRIVATE_MESSAGE_TEXT_LENGTH); textInputView.setReady(false); - textInputView.addOnKeyboardShownListener(this::scrollToBottom); + textInputView.setOnKeyboardShownListener(this::scrollToBottom); } private void scrollToBottom() { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java index 96574abbe..7d093a630 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/CreateForumActivity.java @@ -34,6 +34,8 @@ import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.briar.android.util.UiUtils.enterPressed; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; +import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH; @MethodsNotNullByDefault @@ -91,12 +93,6 @@ public class CreateForumActivity extends BriarActivity { progress = findViewById(R.id.createForumProgressBar); } - @Override - public void onStart() { - super.onStart(); - showSoftKeyboard(nameEntry); - } - @Override public void injectActivity(ActivityComponent component) { component.inject(this); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java index 70478b884..fd9b77592 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/introduction/IntroductionMessageFragment.java @@ -43,6 +43,7 @@ import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH; @MethodsNotNullByDefault @@ -184,7 +185,7 @@ public class IntroductionMessageFragment extends BaseFragment public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: - introductionActivity.hideSoftKeyboard(ui.message); + hideSoftKeyboard(ui.message); introductionActivity.onBackPressed(); return true; default: @@ -201,7 +202,7 @@ public class IntroductionMessageFragment extends BaseFragment makeIntroduction(contact1, contact2, text); // don't wait for the introduction to be made before finishing activity - introductionActivity.hideSoftKeyboard(ui.message); + hideSoftKeyboard(ui.message); introductionActivity.setResult(RESULT_OK); introductionActivity.supportFinishAfterTransition(); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java index 136e9e19d..0f0a91004 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java @@ -26,6 +26,8 @@ import javax.inject.Inject; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; +import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard; public class ChangePasswordActivity extends BriarActivity implements OnClickListener, OnEditorActionListener { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java index f4e1a2766..d4f872d5b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java @@ -83,12 +83,6 @@ public class PasswordFragment extends BaseFragment implements TextWatcher { return v; } - @Override - public void onResume() { - super.onResume(); - showSoftKeyboard(password); - } - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java index f36c749ef..373d6c3ea 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupFragment.java @@ -24,6 +24,7 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; import static org.briarproject.briar.android.util.UiUtils.enterPressed; +import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH; @MethodsNotNullByDefault @@ -91,12 +92,6 @@ public class CreateGroupFragment extends BaseFragment { return v; } - @Override - public void onStart() { - super.onStart(); - listener.showSoftKeyboard(nameEntry); - } - @Override public String getUniqueTag() { return TAG; @@ -120,7 +115,7 @@ public class CreateGroupFragment extends BaseFragment { private void createGroup() { if (!validateName()) return; - listener.hideSoftKeyboard(nameEntry); + hideSoftKeyboard(nameEntry); createGroupButton.setVisibility(GONE); progress.setVisibility(VISIBLE); listener.onGroupNameChosen(nameEntry.getText().toString()); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java index 7485acfe8..c02ede101 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/creation/CreateGroupListener.java @@ -1,15 +1,8 @@ package org.briarproject.briar.android.privategroup.creation; -import android.view.View; - import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener; interface CreateGroupListener extends BaseFragmentListener { void onGroupNameChosen(String name); - - void showSoftKeyboard(View view); - - void hideSoftKeyboard(View view); - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java index eaff51eb4..cb5a4b299 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/sharing/BaseMessageFragment.java @@ -64,12 +64,6 @@ public abstract class BaseMessageFragment extends BaseFragment @StringRes protected abstract int getHintText(); - @Override - public void onStart() { - super.onStart(); - message.showSoftKeyboard(); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index 80456c453..8ae9dd4c0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -27,7 +27,6 @@ import org.briarproject.briar.android.threaded.ThreadListController.ThreadListDa import org.briarproject.briar.android.threaded.ThreadListController.ThreadListListener; import org.briarproject.briar.android.util.BriarSnackbarBuilder; import org.briarproject.briar.android.view.BriarRecyclerView; -import org.briarproject.briar.android.view.KeyboardAwareLinearLayout; import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.android.view.TextSendController; import org.briarproject.briar.android.view.TextSendController.SendListener; @@ -284,14 +283,10 @@ public abstract class ThreadListActivity { + scrollToItemAtTop(item); + textInput.setOnKeyboardShownListener(null); + }); } } @@ -332,7 +327,6 @@ public abstract class ThreadListActivity emojiPopup.toggle()); } @@ -231,6 +245,10 @@ public class EmojiTextInputView extends KeyboardAwareLinearLayout implements editText.setHint(hint); } + boolean isKeyboardOpen() { + return keyboardOpen || imm.isFullscreenMode(); + } + private void showEmojiIcon() { emojiToggle.setImageResource(R.drawable.ic_emoji_toggle); } @@ -240,23 +258,43 @@ public class EmojiTextInputView extends KeyboardAwareLinearLayout implements } void showSoftKeyboard() { - Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); - InputMethodManager imm = (InputMethodManager) requireNonNull(o); - imm.showSoftInput(editText, SHOW_IMPLICIT); + if (editText.requestFocus()) imm.showSoftInput(editText, SHOW_IMPLICIT); } void hideSoftKeyboard() { if (emojiPopup.isShowing()) emojiPopup.dismiss(); IBinder token = editText.getWindowToken(); - Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); - InputMethodManager imm = (InputMethodManager) requireNonNull(o); imm.hideSoftInputFromWindow(token, 0); } + private void onKeyboardOpened( + @SuppressWarnings("unused") int keyboardHeight) { + keyboardOpen = true; + if (keyboardShownListener != null) + keyboardShownListener.onKeyboardShown(); + } + + private void onKeyboardClosed() { + if (imm.isFullscreenMode()) { + onKeyboardOpened(0); + return; + } + keyboardOpen = false; + } + + void setOnKeyboardShownListener( + @Nullable OnKeyboardShownListener listener) { + keyboardShownListener = listener; + } + interface TextInputListener { void onTextIsEmptyChanged(boolean isEmpty); void onSendEvent(); } + public interface OnKeyboardShownListener { + void onKeyboardShown(); + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/KeyboardAwareLinearLayout.java b/briar-android/src/main/java/org/briarproject/briar/android/view/KeyboardAwareLinearLayout.java deleted file mode 100644 index fa4028aeb..000000000 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/KeyboardAwareLinearLayout.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - Taken from Signal, licences under GPLv3 - */ - -package org.briarproject.briar.android.view; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Rect; -import android.os.Build; -import android.preference.PreferenceManager; -import android.support.annotation.UiThread; -import android.util.AttributeSet; -import android.view.View; -import android.view.WindowManager; -import android.widget.LinearLayout; - -import org.briarproject.briar.R; - -import java.lang.reflect.Field; -import java.util.HashSet; -import java.util.Set; -import java.util.logging.Logger; - -import javax.annotation.Nullable; - -import static android.content.Context.WINDOW_SERVICE; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; -import static java.util.Objects.requireNonNull; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; - -/** - * RelativeLayout that, when a view container, will report back when it thinks - * a soft keyboard has been opened and what its height would be. - */ -@UiThread -public class KeyboardAwareLinearLayout extends LinearLayout { - - private static final Logger LOG = - Logger.getLogger(KeyboardAwareLinearLayout.class.getName()); - - private final Rect rect = new Rect(); - private final Set shownListeners = new HashSet<>(); - private final int minKeyboardSize; - private final int minCustomKeyboardSize; - private final int defaultCustomKeyboardSize; - private final int minCustomKeyboardTopMargin; - private final int statusBarHeight; - - private int viewInset; - - private boolean keyboardOpen = false; - private int rotation = -1; - - public KeyboardAwareLinearLayout(Context context) { - this(context, null); - } - - public KeyboardAwareLinearLayout(Context context, - @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public KeyboardAwareLinearLayout(Context context, - @Nullable AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - rotation = getDeviceRotation(); - int statusBarRes = getResources() - .getIdentifier("status_bar_height", "dimen", "android"); - minKeyboardSize = - getResources().getDimensionPixelSize(R.dimen.min_keyboard_size); - minCustomKeyboardSize = getResources() - .getDimensionPixelSize(R.dimen.min_custom_keyboard_size); - defaultCustomKeyboardSize = getResources() - .getDimensionPixelSize(R.dimen.default_custom_keyboard_size); - minCustomKeyboardTopMargin = getResources() - .getDimensionPixelSize(R.dimen.min_custom_keyboard_top_margin); - statusBarHeight = statusBarRes > 0 ? - getResources().getDimensionPixelSize(statusBarRes) : 0; - viewInset = getViewInset(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - updateRotation(); - updateKeyboardState(); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - private void updateRotation() { - int oldRotation = rotation; - rotation = getDeviceRotation(); - if (oldRotation != rotation) { - LOG.info("Rotation changed"); - onKeyboardClose(); - } - } - - private void updateKeyboardState() { - if (isLandscape()) { - if (keyboardOpen) onKeyboardClose(); - return; - } - - if (viewInset == 0 && Build.VERSION.SDK_INT >= 21) - viewInset = getViewInset(); - int availableHeight = - getRootView().getHeight() - statusBarHeight - viewInset; - getWindowVisibleDisplayFrame(rect); - - int keyboardHeight = availableHeight - (rect.bottom - rect.top); - - if (keyboardHeight > minKeyboardSize) { - if (getKeyboardHeight() != keyboardHeight) - setKeyboardPortraitHeight(keyboardHeight); - if (!keyboardOpen) onKeyboardOpen(keyboardHeight); - } else if (keyboardOpen) { - onKeyboardClose(); - } - } - - @TargetApi(21) - private int getViewInset() { - try { - Field attachInfoField = View.class.getDeclaredField("mAttachInfo"); - attachInfoField.setAccessible(true); - Object attachInfo = attachInfoField.get(this); - if (attachInfo != null) { - Field stableInsetsField = - attachInfo.getClass().getDeclaredField("mStableInsets"); - stableInsetsField.setAccessible(true); - Rect insets = (Rect) stableInsetsField.get(attachInfo); - return insets.bottom; - } - } catch (NoSuchFieldException e) { - LOG.log(WARNING, - "field reflection error when measuring view inset", e); - } catch (IllegalAccessException e) { - LOG.log(WARNING, - "access reflection error when measuring view inset", e); - } - return 0; - } - - protected void onKeyboardOpen(int keyboardHeight) { - if (LOG.isLoggable(INFO)) - LOG.info("onKeyboardOpen(" + keyboardHeight + ")"); - keyboardOpen = true; - - notifyShownListeners(); - } - - protected void onKeyboardClose() { - LOG.info("onKeyboardClose()"); - keyboardOpen = false; - } - - public boolean isKeyboardOpen() { - return keyboardOpen; - } - - public int getKeyboardHeight() { - return isLandscape() ? getKeyboardLandscapeHeight() : - getKeyboardPortraitHeight(); - } - - public boolean isLandscape() { - int rotation = getDeviceRotation(); - return rotation == ROTATION_90 || rotation == ROTATION_270; - } - - private int getDeviceRotation() { - WindowManager windowManager = - (WindowManager) getContext().getSystemService(WINDOW_SERVICE); - return requireNonNull(windowManager).getDefaultDisplay().getRotation(); - } - - private int getKeyboardLandscapeHeight() { - return Math.max(getHeight(), getRootView().getHeight()) / 2; - } - - private int getKeyboardPortraitHeight() { - SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getContext()); - int keyboardHeight = prefs.getInt("keyboard_height_portrait", - defaultCustomKeyboardSize); - return clamp(keyboardHeight, minCustomKeyboardSize, - getRootView().getHeight() - minCustomKeyboardTopMargin); - } - - private int clamp(int value, int min, int max) { - return Math.min(Math.max(value, min), max); - } - - private void setKeyboardPortraitHeight(int height) { - SharedPreferences prefs = - PreferenceManager.getDefaultSharedPreferences(getContext()); - prefs.edit().putInt("keyboard_height_portrait", height).apply(); - } - - public void addOnKeyboardShownListener(OnKeyboardShownListener listener) { - shownListeners.add(listener); - } - - public void removeOnKeyboardShownListener( - OnKeyboardShownListener listener) { - shownListeners.remove(listener); - } - - private void notifyShownListeners() { - // Make a copy as listeners may remove themselves when called - Set listeners = new HashSet<>(shownListeners); - for (OnKeyboardShownListener listener : listeners) { - listener.onKeyboardShown(); - } - } - - public interface OnKeyboardShownListener { - void onKeyboardShown(); - } - -} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java index 89a32c1e4..1fbb4301d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java @@ -16,7 +16,7 @@ import android.widget.LinearLayout; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; -import org.briarproject.briar.android.view.KeyboardAwareLinearLayout.OnKeyboardShownListener; +import org.briarproject.briar.android.view.EmojiTextInputView.OnKeyboardShownListener; import static android.content.Context.LAYOUT_INFLATER_SERVICE; import static java.util.Objects.requireNonNull; @@ -139,13 +139,9 @@ public class TextInputView extends LinearLayout { textInput.hideSoftKeyboard(); } - public void addOnKeyboardShownListener(OnKeyboardShownListener listener) { - textInput.addOnKeyboardShownListener(listener); - } - - public void removeOnKeyboardShownListener( - OnKeyboardShownListener listener) { - textInput.removeOnKeyboardShownListener(listener); + public void setOnKeyboardShownListener( + @Nullable OnKeyboardShownListener listener) { + textInput.setOnKeyboardShownListener(listener); } } diff --git a/briar-android/src/main/res/layout/activity_change_password.xml b/briar-android/src/main/res/layout/activity_change_password.xml index fad60ccbc..94cdff0fb 100644 --- a/briar-android/src/main/res/layout/activity_change_password.xml +++ b/briar-android/src/main/res/layout/activity_change_password.xml @@ -29,13 +29,17 @@ app:layout_constraintTop_toTopOf="parent" app:passwordToggleEnabled="true"> - + + + - @@ -69,12 +74,13 @@ app:layout_constraintTop_toBottomOf="@id/new_password_entry_wrapper" app:passwordToggleEnabled="true"> - diff --git a/briar-android/src/main/res/layout/activity_create_forum.xml b/briar-android/src/main/res/layout/activity_create_forum.xml index e759e25c4..9608cb568 100644 --- a/briar-android/src/main/res/layout/activity_create_forum.xml +++ b/briar-android/src/main/res/layout/activity_create_forum.xml @@ -15,14 +15,17 @@ app:errorEnabled="true" app:hintEnabled="false"> - + +