improved send by enter feature - you can input line breaks while pressing modifier keys (ctrl, alt, shift etc)
This commit is contained in:
parent
5073d1d26e
commit
0e44a7cc51
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
|
@ -31,11 +32,13 @@ import android.content.DialogInterface;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -336,11 +339,25 @@ public class SettingsWizardActivity extends Activity implements Constants {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void gotoNextPage() {
|
||||
// Try getting location, some custom rom will popup requirement dialog
|
||||
Utils.getCachedLocation(getActivity());
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
super.gotoNextPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoNextPage() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
final String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
requestPermissions(permissions, REQUEST_REQUEST_PERMISSIONS);
|
||||
} else {
|
||||
// Try getting location, some custom rom will popup requirement dialog
|
||||
Utils.getCachedLocation(getActivity());
|
||||
super.gotoNextPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class WizardPageTabsFragment extends BaseWizardPageFragment {
|
||||
|
|
|
@ -200,6 +200,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
|||
private boolean mTextChanged;
|
||||
private SetProgressVisibleRunnable mSetProgressVisibleRunnable;
|
||||
private boolean mFragmentResumed;
|
||||
private int mKeyMetaState;
|
||||
|
||||
@Override
|
||||
public int getThemeColor() {
|
||||
|
@ -311,12 +312,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
|||
public void onClick(final View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.send: {
|
||||
if (isQuotingProtectedStatus()) {
|
||||
new RetweetProtectedStatusWarnFragment().show(getSupportFragmentManager(),
|
||||
"retweet_protected_status_warning_message");
|
||||
} else {
|
||||
updateStatus();
|
||||
}
|
||||
confirmAndUpdateStatus();
|
||||
break;
|
||||
}
|
||||
case R.id.account_selector_container: {
|
||||
|
@ -335,6 +331,15 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
|||
}
|
||||
}
|
||||
|
||||
private void confirmAndUpdateStatus() {
|
||||
if (isQuotingProtectedStatus()) {
|
||||
new RetweetProtectedStatusWarnFragment().show(getSupportFragmentManager(),
|
||||
"retweet_protected_status_warning_message");
|
||||
} else {
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
final Window window = getWindow();
|
||||
|
@ -717,12 +722,32 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
|
|||
mTextChanged = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
final int keyCode = event.getKeyCode();
|
||||
if (KeyEvent.isModifierKey(keyCode)) {
|
||||
final int action = event.getAction();
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mKeyMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
|
||||
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||
mKeyMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
|
||||
}
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
private void setupEditText() {
|
||||
final boolean sendByEnter = mPreferences.getBoolean(KEY_QUICK_SEND);
|
||||
EditTextEnterHandler.attach(mEditText, new EnterListener() {
|
||||
@Override
|
||||
public void onHitEnter() {
|
||||
updateStatus();
|
||||
public boolean shouldCallListener() {
|
||||
return mKeyMetaState == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHitEnter() {
|
||||
confirmAndUpdateStatus();
|
||||
return true;
|
||||
}
|
||||
}, sendByEnter);
|
||||
mEditText.addTextChangedListener(new TextWatcher() {
|
||||
|
|
|
@ -233,8 +233,14 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
|
|||
|
||||
EditTextEnterHandler.attach(mSearchQuery, new EnterListener() {
|
||||
@Override
|
||||
public void onHitEnter() {
|
||||
public boolean shouldCallListener() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHitEnter() {
|
||||
doSearch();
|
||||
return true;
|
||||
}
|
||||
}, true);
|
||||
mSearchQuery.addTextChangedListener(new TextWatcher() {
|
||||
|
|
|
@ -654,11 +654,17 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
|
|||
private void setupEditQuery() {
|
||||
final EditTextEnterHandler queryEnterHandler = EditTextEnterHandler.attach(mEditUserQuery, new EnterListener() {
|
||||
@Override
|
||||
public void onHitEnter() {
|
||||
public boolean shouldCallListener() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHitEnter() {
|
||||
final ParcelableCredentials account = (ParcelableCredentials) mAccountSpinner.getSelectedItem();
|
||||
if (account == null) return;
|
||||
if (account == null) return false;
|
||||
mEditText.setAccountId(account.account_id);
|
||||
searchUsers(account.account_id, ParseUtils.parseString(mEditUserQuery.getText()), false);
|
||||
return true;
|
||||
}
|
||||
}, true);
|
||||
queryEnterHandler.addTextChangedListener(new TextWatcher() {
|
||||
|
@ -701,8 +707,14 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
|
|||
private void setupEditText() {
|
||||
EditTextEnterHandler.attach(mEditText, new EnterListener() {
|
||||
@Override
|
||||
public void onHitEnter() {
|
||||
public boolean shouldCallListener() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHitEnter() {
|
||||
sendDirectMessage();
|
||||
return true;
|
||||
}
|
||||
}, mPreferences.getBoolean(KEY_QUICK_SEND, false));
|
||||
mEditText.addTextChangedListener(new TextWatcher() {
|
||||
|
|
|
@ -130,12 +130,18 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
|
|||
final boolean sendByEnter = mPreferences.getBoolean(KEY_QUICK_SEND);
|
||||
final EditTextEnterHandler enterHandler = EditTextEnterHandler.attach(mEditComment, new EditTextEnterHandler.EnterListener() {
|
||||
@Override
|
||||
public void onHitEnter() {
|
||||
public boolean shouldCallListener() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHitEnter() {
|
||||
final AsyncTwitterWrapper twitter = mTwitterWrapper;
|
||||
final ParcelableStatus status = getStatus();
|
||||
if (twitter == null || status == null) return;
|
||||
if (twitter == null || status == null) return false;
|
||||
retweetOrQuote(twitter, status);
|
||||
dismiss();
|
||||
return true;
|
||||
}
|
||||
}, sendByEnter);
|
||||
enterHandler.addTextChangedListener(new TextWatcher() {
|
||||
|
|
|
@ -41,6 +41,7 @@ public class EditTextEnterHandler implements View.OnKeyListener, OnEditorActionL
|
|||
private EnterListener listener;
|
||||
private boolean enabled;
|
||||
private ArrayList<TextWatcher> textWatchers;
|
||||
private boolean appendText;
|
||||
|
||||
public EditTextEnterHandler(@Nullable EnterListener listener, boolean enabled) {
|
||||
this.listener = listener;
|
||||
|
@ -64,27 +65,30 @@ public class EditTextEnterHandler implements View.OnKeyListener, OnEditorActionL
|
|||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
if (textWatchers == null) return;
|
||||
for (TextWatcher textWatcher : textWatchers) {
|
||||
textWatcher.beforeTextChanged(s, start, count, after);
|
||||
if (textWatchers != null) {
|
||||
for (TextWatcher textWatcher : textWatchers) {
|
||||
textWatcher.beforeTextChanged(s, start, count, after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (textWatchers == null) return;
|
||||
for (TextWatcher textWatcher : textWatchers) {
|
||||
textWatcher.onTextChanged(s, start, before, count);
|
||||
if (textWatchers != null) {
|
||||
for (TextWatcher textWatcher : textWatchers) {
|
||||
textWatcher.onTextChanged(s, start, before, count);
|
||||
}
|
||||
}
|
||||
appendText = count > before;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
final int length = s.length();
|
||||
if (enabled && length > 0 && s.charAt(length - 1) == '\n') {
|
||||
s.delete(length - 1, length);
|
||||
if (listener != null) {
|
||||
listener.onHitEnter();
|
||||
if (enabled && length > 0 && s.charAt(length - 1) == '\n' && appendText) {
|
||||
if (shouldCallListener()) {
|
||||
s.delete(length - 1, length);
|
||||
dispatchHitEnter();
|
||||
}
|
||||
} else if (textWatchers != null) {
|
||||
for (TextWatcher textWatcher : textWatchers) {
|
||||
|
@ -97,10 +101,7 @@ public class EditTextEnterHandler implements View.OnKeyListener, OnEditorActionL
|
|||
public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) {
|
||||
if (!enabled) return false;
|
||||
if (event != null && actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (listener != null) {
|
||||
listener.onHitEnter();
|
||||
}
|
||||
return true;
|
||||
if (shouldCallListener()) return dispatchHitEnter();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -108,14 +109,19 @@ public class EditTextEnterHandler implements View.OnKeyListener, OnEditorActionL
|
|||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER && enabled && event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (listener != null) {
|
||||
listener.onHitEnter();
|
||||
}
|
||||
return true;
|
||||
if (shouldCallListener()) return dispatchHitEnter();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean dispatchHitEnter() {
|
||||
return listener != null && listener.onHitEnter();
|
||||
}
|
||||
|
||||
private boolean shouldCallListener() {
|
||||
return listener != null && listener.shouldCallListener();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
@ -125,7 +131,9 @@ public class EditTextEnterHandler implements View.OnKeyListener, OnEditorActionL
|
|||
}
|
||||
|
||||
public interface EnterListener {
|
||||
void onHitEnter();
|
||||
boolean shouldCallListener();
|
||||
|
||||
boolean onHitEnter();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -768,6 +768,8 @@
|
|||
<string name="dark_theme">Dark theme</string>
|
||||
<string name="wizard_hint_title_location_requirement">Location permission</string>
|
||||
<string name="wizard_hint_summary_location_requirement">Twidere needs location permission when you send tweet containing location.</string>
|
||||
<string name="wizard_hint_title_storage_requirement">Storage permission</string>
|
||||
<string name="wizard_hint_summary_storage_requirement">Twidere needs storage permission when you access documents.</string>
|
||||
<string name="scrapyard">Scrapyard</string>
|
||||
<string name="crop_image">Crop image</string>
|
||||
<string name="usage_label_sent">Sent</string>
|
||||
|
|
|
@ -1,27 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/hints">
|
||||
|
||||
<org.mariotaku.twidere.preference.ForegroundColorIconPreference
|
||||
android:icon="@drawable/ic_action_location"
|
||||
android:order="11"
|
||||
android:summary="@string/wizard_hint_summary_location_requirement"
|
||||
android:title="@string/wizard_hint_title_location_requirement"/>
|
||||
android:title="@string/wizard_hint_title_location_requirement" />
|
||||
<org.mariotaku.twidere.preference.ForegroundColorIconPreference
|
||||
android:icon="@drawable/ic_action_storage"
|
||||
android:order="12"
|
||||
android:summary="@string/wizard_hint_summary_storage_requirement"
|
||||
android:title="@string/wizard_hint_title_storage_requirement" />
|
||||
<org.mariotaku.twidere.preference.ForegroundColorIconPreference
|
||||
android:icon="@drawable/ic_action_accounts"
|
||||
android:order="12"
|
||||
android:order="13"
|
||||
android:summary="@string/wizard_hint_compose_select_account"
|
||||
android:title="@string/select_account"/>
|
||||
android:title="@string/select_account" />
|
||||
<org.mariotaku.twidere.preference.ForegroundColorIconPreference
|
||||
android:icon="@drawable/ic_action_speaker_muted"
|
||||
android:order="13"
|
||||
android:order="14"
|
||||
android:summary="@string/wizard_hint_filters"
|
||||
android:title="@string/filters"/>
|
||||
android:title="@string/filters" />
|
||||
<org.mariotaku.twidere.preference.ForegroundColorIconPreference
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:order="14"
|
||||
android:order="15"
|
||||
android:summary="@string/wizard_hint_rate_limit"
|
||||
android:title="@string/rate_limit"/>
|
||||
android:title="@string/rate_limit" />
|
||||
|
||||
</PreferenceScreen>
|
Loading…
Reference in New Issue