Show suggestion help

This commit is contained in:
M66B 2023-09-13 08:53:24 +02:00
parent bf1193d787
commit bd89910485
3 changed files with 116 additions and 40 deletions

View File

@ -114,6 +114,8 @@ public class EditTextCompose extends FixedEditText {
order++, context.getString(R.string.title_insert_brackets));
menu.add(Menu.CATEGORY_SECONDARY, R.string.title_insert_quotes,
order++, context.getString(R.string.title_insert_quotes));
menu.add(Menu.CATEGORY_SECONDARY, R.string.title_setup_help,
order++, context.getString(R.string.title_setup_help));
menu.add(Menu.CATEGORY_SECONDARY, R.string.title_lt_add,
order++, context.getString(R.string.title_lt_add));
menu.add(Menu.CATEGORY_SECONDARY, R.string.title_lt_delete,
@ -131,6 +133,10 @@ public class EditTextCompose extends FixedEditText {
boolean selection = (start >= 0 && start < end);
Context context = getContext();
Editable edit = getText();
SuggestionSpanEx[] suggestion = (edit == null ? null
: edit.getSpans(start, end, SuggestionSpanEx.class));
boolean hasSuggestions = (suggestion != null && suggestion.length > 0 &&
!TextUtils.isEmpty(suggestion[0].getDescription()));
boolean dictionary = (selection &&
context instanceof AppCompatActivity &&
LanguageTool.isPremium(context) &&
@ -138,6 +144,7 @@ public class EditTextCompose extends FixedEditText {
edit.subSequence(start, end).toString().indexOf(' ') < 0);
menu.findItem(R.string.title_insert_brackets).setVisible(selection);
menu.findItem(R.string.title_insert_quotes).setVisible(selection);
menu.findItem(R.string.title_setup_help).setVisible(hasSuggestions);
menu.findItem(R.string.title_lt_add).setVisible(dictionary);
menu.findItem(R.string.title_lt_delete).setVisible(dictionary);
return false;
@ -151,7 +158,12 @@ public class EditTextCompose extends FixedEditText {
return surround("(", ")");
else if (id == R.string.title_insert_quotes)
return surround("\"", "\"");
else if (id == R.string.title_lt_add)
else if (id == R.string.title_setup_help) {
if (showSuggestion()) {
mode.finish();
return true;
}
} else if (id == R.string.title_lt_add)
return modifyDictionary(true);
else if (id == R.string.title_lt_delete)
return modifyDictionary(false);
@ -228,6 +240,21 @@ public class EditTextCompose extends FixedEditText {
return true;
}
private boolean showSuggestion() {
Editable edit = getText();
if (edit == null)
return false;
int start = getSelectionStart();
int end = getSelectionEnd();
if (end <= start)
return false;
SuggestionSpanEx[] suggestions = edit.getSpans(start, end, SuggestionSpanEx.class);
if (suggestions == null || suggestions.length == 0)
return false;
ToastEx.makeText(getContext(), suggestions[0].getDescription(), Toast.LENGTH_LONG).show();
return true;
}
});
setCustomInsertionActionModeCallback(new ActionMode.Callback() {

View File

@ -22,13 +22,12 @@ package eu.faircode.email;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.LocaleList;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.Pair;
@ -43,7 +42,6 @@ import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
@ -425,7 +423,24 @@ public class LanguageTool {
boolean misspelled = ("misspelling".equals(suggestion.issueType) ||
"typographical".equals(suggestion.issueType) ||
"whitespace".equals(suggestion.issueType));
SpannableStringBuilder ssb = new SpannableStringBuilderEx();
if (!TextUtils.isEmpty(suggestion.title))
ssb.append(suggestion.title);
if (!TextUtils.isEmpty(suggestion.description)) {
if (ssb.length() > 0)
ssb.append(": ");
ssb.append(suggestion.description);
}
if (!TextUtils.isEmpty(suggestion.issueType)) {
int len = ssb.length();
if (len > 0)
ssb.append(" (");
ssb.append(suggestion.issueType);
if (len > 0)
ssb.append(")");
}
SuggestionSpan span = new SuggestionSpanEx(etBody.getContext(),
ssb.toString(),
suggestion.replacements.toArray(new String[0]), misspelled);
int s = start + suggestion.offset;
int e = s + suggestion.length;
@ -474,40 +489,4 @@ public class LanguageTool {
return issueType + " " + title + " " + description;
}
}
private static class SuggestionSpanEx extends SuggestionSpan {
private final int highlightColor;
private final int underlineColor;
private final int underlineThickness;
public SuggestionSpanEx(Context context, String[] suggestions, boolean misspelled) {
super(context, suggestions,
misspelled || Build.VERSION.SDK_INT < Build.VERSION_CODES.S
? SuggestionSpan.FLAG_MISSPELLED | SuggestionSpan.FLAG_EASY_CORRECT
: SuggestionSpan.FLAG_GRAMMAR_ERROR);
highlightColor = Helper.resolveColor(context, android.R.attr.textColorHighlight);
underlineColor = (misspelled ? Color.RED : highlightColor);
underlineThickness = Helper.dp2pixels(context, misspelled ? 2 : 2);
}
@Override
public void updateDrawState(TextPaint tp) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
try {
Field fUnderlineColor = tp.getClass().getDeclaredField("underlineColor");
Field fUnderlineThickness = tp.getClass().getDeclaredField("underlineThickness");
fUnderlineColor.setAccessible(true);
fUnderlineThickness.setAccessible(true);
fUnderlineColor.set(tp, underlineColor);
fUnderlineThickness.set(tp, underlineThickness);
} catch (Throwable ex) {
Log.i(ex);
tp.bgColor = highlightColor;
}
else {
tp.underlineColor = underlineColor;
tp.underlineThickness = underlineThickness;
}
}
}
}

View File

@ -0,0 +1,70 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2023 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.text.TextPaint;
import android.text.style.SuggestionSpan;
import java.lang.reflect.Field;
public class SuggestionSpanEx extends SuggestionSpan {
private String description;
private final int highlightColor;
private final int underlineColor;
private final int underlineThickness;
public SuggestionSpanEx(Context context, String description, String[] suggestions, boolean misspelled) {
super(context, suggestions,
misspelled || Build.VERSION.SDK_INT < Build.VERSION_CODES.S
? SuggestionSpan.FLAG_MISSPELLED | SuggestionSpan.FLAG_EASY_CORRECT
: SuggestionSpan.FLAG_GRAMMAR_ERROR);
this.description = description;
highlightColor = Helper.resolveColor(context, android.R.attr.textColorHighlight);
underlineColor = (misspelled ? Color.RED : highlightColor);
underlineThickness = Helper.dp2pixels(context, misspelled ? 2 : 2);
}
public String getDescription() {
return this.description;
}
@Override
public void updateDrawState(TextPaint tp) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
try {
Field fUnderlineColor = tp.getClass().getDeclaredField("underlineColor");
Field fUnderlineThickness = tp.getClass().getDeclaredField("underlineThickness");
fUnderlineColor.setAccessible(true);
fUnderlineThickness.setAccessible(true);
fUnderlineColor.set(tp, underlineColor);
fUnderlineThickness.set(tp, underlineThickness);
} catch (Throwable ex) {
Log.i(ex);
tp.bgColor = highlightColor;
}
else {
tp.underlineColor = underlineColor;
tp.underlineThickness = underlineThickness;
}
}
}