mirror of
https://github.com/M66B/FairEmail.git
synced 2025-02-21 05:37:07 +00:00
Use FAB for compose/translate
This commit is contained in:
parent
eca6a97f3e
commit
21923526bc
2 changed files with 135 additions and 127 deletions
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue