Use FAB for compose/translate

This commit is contained in:
M66B 2021-07-28 10:43:17 +02:00
parent eca6a97f3e
commit 21923526bc
2 changed files with 135 additions and 127 deletions

View File

@ -121,6 +121,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import org.bouncycastle.cert.jcajce.JcaCertStore;
@ -241,7 +242,6 @@ public class FragmentCompose extends FragmentBase {
private TextView tvDsn;
private TextView tvPlainTextOnly;
private EditTextCompose etBody;
private ImageButton ibTranslate;
private TextView tvNoInternet;
private TextView tvSignature;
private CheckBox cbSignature;
@ -250,6 +250,7 @@ public class FragmentCompose extends FragmentBase {
private ImageButton ibCloseRefHint;
private ImageButton ibReferenceEdit;
private ImageButton ibReferenceImages;
private FloatingActionButton fabTranslate;
private BottomNavigationView style_bar;
private BottomNavigationView media_bar;
private BottomNavigationView bottom_navigation;
@ -358,7 +359,6 @@ public class FragmentCompose extends FragmentBase {
tvDsn = view.findViewById(R.id.tvDsn);
tvPlainTextOnly = view.findViewById(R.id.tvPlainTextOnly);
etBody = view.findViewById(R.id.etBody);
ibTranslate = view.findViewById(R.id.ibTranslate);
tvNoInternet = view.findViewById(R.id.tvNoInternet);
tvSignature = view.findViewById(R.id.tvSignature);
cbSignature = view.findViewById(R.id.cbSignature);
@ -367,6 +367,7 @@ public class FragmentCompose extends FragmentBase {
ibCloseRefHint = view.findViewById(R.id.ibCloseRefHint);
ibReferenceEdit = view.findViewById(R.id.ibReferenceEdit);
ibReferenceImages = view.findViewById(R.id.ibReferenceImages);
fabTranslate = view.findViewById(R.id.fabTranslate);
style_bar = view.findViewById(R.id.style_bar);
media_bar = view.findViewById(R.id.media_bar);
bottom_navigation = view.findViewById(R.id.bottom_navigation);
@ -716,116 +717,6 @@ public class FragmentCompose extends FragmentBase {
}
});
ibTranslate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<DeepL.Language> languages = DeepL.getTargetLanguages(getContext());
if (languages == null)
return;
boolean canTranslate =
(DeepL.canTranslate(getContext()) &&
DeepL.getParagraph(etBody) != null);
PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(getContext(), getViewLifecycleOwner(), v);
popupMenu.getMenu().add(Menu.NONE, 1, 1, R.string.title_translate_configure);
for (int i = 0; i < languages.size(); i++) {
DeepL.Language lang = languages.get(i);
MenuItem item = popupMenu.getMenu().add(Menu.NONE, i + 2, i + 2, lang.name)
.setIntent(new Intent().putExtra("target", lang.target));
if (lang.icon != null)
item.setIcon(lang.icon);
item.setEnabled(canTranslate);
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == 1) {
DeepL.FragmentDialogDeepL fragment = new DeepL.FragmentDialogDeepL();
fragment.show(getParentFragmentManager(), "deepl:configure");
} else {
String target = item.getIntent().getStringExtra("target");
onMenuTranslate(target);
}
return true;
}
});
popupMenu.showWithIcons(getContext(), v);
}
private void onMenuTranslate(String target) {
final Pair<Integer, Integer> paragraph = DeepL.getParagraph(etBody);
if (paragraph == null)
return;
Editable edit = etBody.getText();
String text = edit.subSequence(paragraph.first, paragraph.second).toString();
Bundle args = new Bundle();
args.putString("target", target);
args.putString("text", text);
new SimpleTask<DeepL.Translation>() {
@Override
protected void onPreExecute(Bundle args) {
ToastEx.makeText(getContext(), R.string.title_translating, Toast.LENGTH_SHORT).show();
}
@Override
protected DeepL.Translation onExecute(Context context, Bundle args) throws Throwable {
String target = args.getString("target");
String text = args.getString("text");
return DeepL.translate(text, target, context);
}
@Override
protected void onExecuted(Bundle args, DeepL.Translation translation) {
if (paragraph.second > edit.length())
return;
FragmentActivity activity = getActivity();
if (activity == null)
return;
Context context = getContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Insert translated text
edit.insert(paragraph.second, "\n\n" + translation.translated_text);
etBody.setSelection(paragraph.second + 2 + translation.translated_text.length());
boolean small = prefs.getBoolean("deepl_small", false);
if (small) {
RelativeSizeSpan[] spans = edit.getSpans(
paragraph.first, paragraph.second, RelativeSizeSpan.class);
for (RelativeSizeSpan span : spans)
edit.removeSpan(span);
edit.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL),
paragraph.first, paragraph.second,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// Updated frequency
String key = "translated_" + args.getString("target");
int count = prefs.getInt(key, 0);
prefs.edit().putInt(key, count + 1).apply();
activity.invalidateOptionsMenu();
}
@Override
protected void onException(Bundle args, Throwable ex) {
Throwable exex = new Throwable("DeepL", ex);
Log.unexpectedError(getParentFragmentManager(), exex, false);
}
}.execute(FragmentCompose.this, args, "compose:translate");
}
});
tvSignature.setTypeface(monospaced ? Typeface.MONOSPACE : Typeface.DEFAULT);
cbSignature.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@ -924,6 +815,13 @@ public class FragmentCompose extends FragmentBase {
}
});
fabTranslate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onTranslate(v);
}
});
style_bar.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
@ -1006,13 +904,13 @@ public class FragmentCompose extends FragmentBase {
grpAttachments.setVisibility(View.GONE);
tvNoInternet.setVisibility(View.GONE);
grpBody.setVisibility(View.GONE);
ibTranslate.setVisibility(
DeepL.isAvailable(getContext()) ? View.VISIBLE : View.GONE);
grpSignature.setVisibility(View.GONE);
grpReferenceHint.setVisibility(View.GONE);
ibReferenceEdit.setVisibility(View.GONE);
ibReferenceImages.setVisibility(View.GONE);
tvReference.setVisibility(View.GONE);
fabTranslate.setVisibility(
DeepL.isAvailable(getContext()) ? View.VISIBLE : View.GONE);
style_bar.setVisibility(View.GONE);
media_bar.setVisibility(View.GONE);
bottom_navigation.setVisibility(View.GONE);
@ -2065,6 +1963,113 @@ public class FragmentCompose extends FragmentBase {
fragmentTransaction.commit();
}
private void onTranslate(View anchor) {
final Context context = anchor.getContext();
List<DeepL.Language> languages = DeepL.getTargetLanguages(context);
if (languages == null)
languages = new ArrayList<>();
Pair<Integer, Integer> paragraph = DeepL.getParagraph(etBody);
boolean canTranslate = (DeepL.canTranslate(context) && paragraph != null);
PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(context, getViewLifecycleOwner(), anchor);
popupMenu.getMenu().add(Menu.NONE, 1, 1, R.string.title_translate_configure);
for (int i = 0; i < languages.size(); i++) {
DeepL.Language lang = languages.get(i);
MenuItem item = popupMenu.getMenu().add(Menu.NONE, i + 2, i + 2, lang.name)
.setIntent(new Intent().putExtra("target", lang.target));
if (lang.icon != null)
item.setIcon(lang.icon);
item.setEnabled(canTranslate);
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == 1) {
DeepL.FragmentDialogDeepL fragment = new DeepL.FragmentDialogDeepL();
fragment.show(getParentFragmentManager(), "deepl:configure");
} else {
String target = item.getIntent().getStringExtra("target");
onMenuTranslate(target);
}
return true;
}
private void onMenuTranslate(String target) {
final Pair<Integer, Integer> paragraph = DeepL.getParagraph(etBody);
if (paragraph == null)
return;
Editable edit = etBody.getText();
String text = edit.subSequence(paragraph.first, paragraph.second).toString();
Bundle args = new Bundle();
args.putString("target", target);
args.putString("text", text);
new SimpleTask<DeepL.Translation>() {
@Override
protected void onPreExecute(Bundle args) {
ToastEx.makeText(context, R.string.title_translating, Toast.LENGTH_SHORT).show();
}
@Override
protected DeepL.Translation onExecute(Context context, Bundle args) throws Throwable {
String target = args.getString("target");
String text = args.getString("text");
return DeepL.translate(text, target, context);
}
@Override
protected void onExecuted(Bundle args, DeepL.Translation translation) {
if (paragraph.second > edit.length())
return;
FragmentActivity activity = getActivity();
if (activity == null)
return;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
// Insert translated text
edit.insert(paragraph.second, "\n\n" + translation.translated_text);
etBody.setSelection(paragraph.second + 2 + translation.translated_text.length());
boolean small = prefs.getBoolean("deepl_small", false);
if (small) {
RelativeSizeSpan[] spans = edit.getSpans(
paragraph.first, paragraph.second, RelativeSizeSpan.class);
for (RelativeSizeSpan span : spans)
edit.removeSpan(span);
edit.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL),
paragraph.first, paragraph.second,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// Updated frequency
String key = "translated_" + args.getString("target");
int count = prefs.getInt(key, 0);
prefs.edit().putInt(key, count + 1).apply();
activity.invalidateOptionsMenu();
}
@Override
protected void onException(Bundle args, Throwable ex) {
Throwable exex = new Throwable("DeepL", ex);
Log.unexpectedError(getParentFragmentManager(), exex, false);
}
}.execute(FragmentCompose.this, args, "compose:translate");
}
});
popupMenu.showWithIcons(context, anchor);
}
private boolean onActionStyle(int action, View anchor) {
Log.i("Style action=" + action);
return StyleHelper.apply(action, getViewLifecycleOwner(), anchor, etBody);

View File

@ -307,18 +307,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvPlainTextOnly" />
<ImageButton
android:id="@+id/ibTranslate"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginEnd="6dp"
android:background="?attr/selectableItemBackground"
android:padding="3dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/etBody"
app:srcCompat="@drawable/outline_translate_24"
app:tint="?attr/colorSeparator" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvNoInternet"
android:layout_width="wrap_content"
@ -340,7 +328,7 @@
android:background="?attr/colorSeparator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ibTranslate" />
app:layout_constraintTop_toBottomOf="@+id/etBody" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvSignature"
@ -512,6 +500,21 @@
app:layout_constraintBottom_toTopOf="@+id/style_bar"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabTranslate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_padding"
android:contentDescription="@string/title_translate"
app:backgroundTint="?attr/colorActionBackground"
app:fabSize="mini"
app:layout_constraintBottom_toTopOf="@+id/style_bar"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/outline_translate_24"
app:tint="@color/action_foreground"
app:tooltipText="@string/title_translate" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/style_bar"
android:layout_width="0dp"