diff --git a/app/src/main/java/eu/faircode/email/EditTextCompose.java b/app/src/main/java/eu/faircode/email/EditTextCompose.java
index 799eab4971..61a1837fb8 100644
--- a/app/src/main/java/eu/faircode/email/EditTextCompose.java
+++ b/app/src/main/java/eu/faircode/email/EditTextCompose.java
@@ -36,7 +36,8 @@ import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat;
public class EditTextCompose extends AppCompatEditText {
- private IInputContentListener listener = null;
+ private ISelection selectionListener = null;
+ private IInputContentListener inputContentListener = null;
public EditTextCompose(Context context) {
super(context);
@@ -50,6 +51,13 @@ public class EditTextCompose extends AppCompatEditText {
super(context, attrs, defStyleAttr);
}
+ @Override
+ protected void onSelectionChanged(int selStart, int selEnd) {
+ super.onSelectionChanged(selStart, selEnd);
+ if (selectionListener != null)
+ selectionListener.onSelected(hasSelection());
+ }
+
@Override
public boolean onTextContextMenuItem(int id) {
try {
@@ -117,14 +125,14 @@ public class EditTextCompose extends AppCompatEditText {
public boolean onCommitContent(InputContentInfoCompat info, int flags, Bundle opts) {
Log.i("Uri=" + info.getContentUri());
try {
- if (listener == null)
+ if (inputContentListener == null)
throw new IllegalArgumentException("InputContent listener not set");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 &&
(flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0)
info.requestPermission();
- listener.onInputContent(info.getContentUri());
+ inputContentListener.onInputContent(info.getContentUri());
return true;
} catch (Throwable ex) {
Log.w(ex);
@@ -135,10 +143,18 @@ public class EditTextCompose extends AppCompatEditText {
}
void setInputContentListener(IInputContentListener listener) {
- this.listener = listener;
+ this.inputContentListener = listener;
}
interface IInputContentListener {
void onInputContent(Uri uri);
}
+
+ void setSelectionListener(ISelection listener) {
+ this.selectionListener = listener;
+ }
+
+ interface ISelection {
+ void onSelected(boolean selection);
+ }
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java
index 5bfd2073b5..5873c1ffa6 100644
--- a/app/src/main/java/eu/faircode/email/FragmentCompose.java
+++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java
@@ -74,7 +74,6 @@ import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import android.util.DisplayMetrics;
import android.util.TypedValue;
-import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -183,6 +182,7 @@ public class FragmentCompose extends FragmentBase {
private ImageButton ibReferenceDelete;
private ImageButton ibReferenceEdit;
private ImageButton ibReferenceImages;
+ private BottomNavigationView style_bar;
private BottomNavigationView media_bar;
private BottomNavigationView bottom_navigation;
private ContentLoadingProgressBar pbWait;
@@ -278,6 +278,7 @@ public class FragmentCompose extends FragmentBase {
ibReferenceDelete = view.findViewById(R.id.ibReferenceDelete);
ibReferenceEdit = view.findViewById(R.id.ibReferenceEdit);
ibReferenceImages = view.findViewById(R.id.ibReferenceImages);
+ style_bar = view.findViewById(R.id.style_bar);
media_bar = view.findViewById(R.id.media_bar);
bottom_navigation = view.findViewById(R.id.bottom_navigation);
@@ -346,8 +347,6 @@ public class FragmentCompose extends FragmentBase {
setZoom();
- etBody.setCustomSelectionActionModeCallback(actionCallback);
-
etBody.setInputContentListener(new EditTextCompose.IInputContentListener() {
@Override
public void onInputContent(Uri uri) {
@@ -355,6 +354,13 @@ public class FragmentCompose extends FragmentBase {
}
});
+ etBody.setSelectionListener(new EditTextCompose.ISelection() {
+ @Override
+ public void onSelected(boolean selection) {
+ style_bar.setVisibility(selection ? View.VISIBLE : View.GONE);
+ }
+ });
+
cbSignature.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@@ -422,6 +428,13 @@ public class FragmentCompose extends FragmentBase {
etBody.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT);
tvReference.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT);
+ style_bar.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ return onActionStyle(item.getItemId());
+ }
+ });
+
PackageManager pm = getContext().getPackageManager();
Intent take_photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent record_audio = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
@@ -497,6 +510,7 @@ public class FragmentCompose extends FragmentBase {
ibReferenceEdit.setVisibility(View.GONE);
ibReferenceImages.setVisibility(View.GONE);
tvReference.setVisibility(View.GONE);
+ style_bar.setVisibility(View.GONE);
media_bar.setVisibility(View.GONE);
bottom_navigation.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
@@ -1048,6 +1062,106 @@ public class FragmentCompose extends FragmentBase {
fragment.show(getFragmentManager(), "compose:answer");
}
+ private boolean onActionStyle(int action) {
+ Log.i("Style action=" + action);
+
+ int start = etBody.getSelectionStart();
+ int end = etBody.getSelectionEnd();
+
+ if (start < 0)
+ start = 0;
+ if (end < 0)
+ end = 0;
+
+ if (start > end) {
+ int tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ SpannableString ss = new SpannableString(etBody.getText());
+
+ switch (action) {
+ case R.id.menu_bold:
+ case R.id.menu_italic: {
+ int style = (action == R.id.menu_bold ? Typeface.BOLD : Typeface.ITALIC);
+ boolean has = false;
+ for (StyleSpan span : ss.getSpans(start, end, StyleSpan.class))
+ if (span.getStyle() == style) {
+ has = true;
+ ss.removeSpan(span);
+ }
+
+ if (!has)
+ ss.setSpan(new StyleSpan(style), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ etBody.setText(ss);
+ etBody.setSelection(start, end);
+
+ return true;
+ }
+
+ case R.id.menu_underline: {
+ boolean has = false;
+ for (UnderlineSpan span : ss.getSpans(start, end, UnderlineSpan.class)) {
+ has = true;
+ ss.removeSpan(span);
+ }
+
+ if (!has)
+ ss.setSpan(new UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ etBody.setText(ss);
+ etBody.setSelection(start, end);
+
+ return true;
+ }
+
+ case R.id.menu_size: {
+ RelativeSizeSpan[] spans = ss.getSpans(start, end, RelativeSizeSpan.class);
+ float size = (spans.length > 0 ? spans[0].getSizeChange() : 1.0f);
+
+ // Match small/big
+ if (size == 0.8f)
+ size = 1.0f;
+ else if (size == 1.0)
+ size = 1.25f;
+ else
+ size = 0.8f;
+
+ for (RelativeSizeSpan span : spans)
+ ss.removeSpan(span);
+
+ if (size != 1.0f)
+ ss.setSpan(new RelativeSizeSpan(size), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ etBody.setText(ss);
+ etBody.setSelection(start, end);
+
+ return true;
+ }
+
+ case R.id.menu_color: {
+ Bundle args = new Bundle();
+ args.putInt("start", start);
+ args.putInt("end", end);
+
+ ForegroundColorSpan[] spans = ss.getSpans(start, end, ForegroundColorSpan.class);
+ int color = (spans.length > 0 ? spans[0].getForegroundColor() : Color.TRANSPARENT);
+
+ FragmentDialogColor fragment = new FragmentDialogColor();
+ fragment.initialize(R.string.title_style_color, color, args, getContext());
+ fragment.setTargetFragment(FragmentCompose.this, REQUEST_COLOR);
+ fragment.show(getFragmentManager(), "account:color");
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
private void onActionRecordAudio() {
Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, REQUEST_RECORD_AUDIO);
@@ -1607,8 +1721,9 @@ public class FragmentCompose extends FragmentBase {
for (ForegroundColorSpan span : ss.getSpans(start, end, ForegroundColorSpan.class))
ss.removeSpan(span);
ss.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
etBody.setText(ss);
- etBody.setSelection(end, end);
+ etBody.setSelection(start, end);
}
private void onContactGroupSelected(Bundle args) {
@@ -3349,129 +3464,6 @@ public class FragmentCompose extends FragmentBase {
}
};
- private ActionMode.Callback actionCallback = new ActionMode.Callback() {
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- menu.add(1, R.string.title_style_bold, 1, R.string.title_style_bold).setIcon(R.drawable.baseline_format_bold_24);
- menu.add(1, R.string.title_style_italic, 2, R.string.title_style_italic).setIcon(R.drawable.baseline_format_italic_24);
- menu.add(1, R.string.title_style_underline, 3, R.string.title_style_underline).setIcon(R.drawable.baseline_format_underlined_24);
- menu.add(1, R.string.title_style_size, 4, R.string.title_style_size).setIcon(R.drawable.baseline_format_size_24);
- menu.add(1, R.string.title_style_color, 5, R.string.title_style_color).setIcon(R.drawable.baseline_format_color_text_24);
- return true;
- }
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return false;
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- Log.i("Action=" + item.getGroupId() + ":" + item.getItemId());
-
- if (item.getGroupId() != 1)
- return false;
-
- int start = etBody.getSelectionStart();
- int end = etBody.getSelectionEnd();
-
- if (start < 0)
- start = 0;
- if (end < 0)
- end = 0;
-
- if (start > end) {
- int tmp = start;
- start = end;
- end = tmp;
- }
-
- SpannableString ss = new SpannableString(etBody.getText());
-
- switch (item.getItemId()) {
- case R.string.title_style_bold:
- case R.string.title_style_italic: {
- int style = (item.getItemId() == R.string.title_style_bold ? Typeface.BOLD : Typeface.ITALIC);
- boolean has = false;
- for (StyleSpan span : ss.getSpans(start, end, StyleSpan.class))
- if (span.getStyle() == style) {
- has = true;
- ss.removeSpan(span);
- }
-
- if (!has)
- ss.setSpan(new StyleSpan(style), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- etBody.setText(ss);
- etBody.setSelection(end, end);
- return true;
- }
-
- case R.string.title_style_underline: {
- boolean has = false;
- for (UnderlineSpan span : ss.getSpans(start, end, UnderlineSpan.class)) {
- has = true;
- ss.removeSpan(span);
- }
-
- if (!has)
- ss.setSpan(new UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- etBody.setText(ss);
- etBody.setSelection(end, end);
- return true;
- }
-
- case R.string.title_style_size: {
- RelativeSizeSpan[] spans = ss.getSpans(start, end, RelativeSizeSpan.class);
- float size = (spans.length > 0 ? spans[0].getSizeChange() : 1.0f);
-
- // Match small/big
- if (size == 0.8f)
- size = 1.0f;
- else if (size == 1.0)
- size = 1.25f;
- else
- size = 0.8f;
-
- for (RelativeSizeSpan span : spans)
- ss.removeSpan(span);
-
- if (size != 1.0f)
- ss.setSpan(new RelativeSizeSpan(size), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-
- etBody.setText(ss);
- etBody.setSelection(end, end);
- return true;
- }
-
- case R.string.title_style_color: {
- Bundle args = new Bundle();
- args.putInt("start", start);
- args.putInt("end", end);
-
- ForegroundColorSpan[] spans = ss.getSpans(start, end, ForegroundColorSpan.class);
- int color = (spans.length > 0 ? spans[0].getForegroundColor() : Color.TRANSPARENT);
-
- FragmentDialogColor fragment = new FragmentDialogColor();
- fragment.initialize(R.string.title_style_color, color, args, getContext());
- fragment.setTargetFragment(FragmentCompose.this, REQUEST_COLOR);
- fragment.show(getFragmentManager(), "account:color");
-
- etBody.setSelection(end, end);
- return true;
- }
-
- default:
- return false;
- }
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- }
- };
-
private ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
diff --git a/app/src/main/res/layout/fragment_compose.xml b/app/src/main/res/layout/fragment_compose.xml
index 49fa6f4bc0..f0c78bad2f 100644
--- a/app/src/main/res/layout/fragment_compose.xml
+++ b/app/src/main/res/layout/fragment_compose.xml
@@ -14,7 +14,7 @@
@@ -417,6 +417,19 @@
+
+
+ app:menu="@menu/action_compose_media" />
+