fix some issues with url detection

This commit is contained in:
Helium314 2023-10-16 19:52:06 +02:00
parent 3eba91e55c
commit 8abfe26411
5 changed files with 145 additions and 7 deletions

View file

@ -36,6 +36,7 @@ import androidx.annotation.Nullable;
import org.dslul.openboard.inputmethod.latin.common.Constants;
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
import org.dslul.openboard.inputmethod.latin.common.StringUtilsKt;
import org.dslul.openboard.inputmethod.latin.common.UnicodeSurrogate;
import org.dslul.openboard.inputmethod.latin.inputlogic.PrivateCommandPerformer;
import org.dslul.openboard.inputmethod.latin.settings.SpacingAndPunctuations;
@ -1001,10 +1002,18 @@ public final class RichInputConnection implements PrivateCommandPerformer {
return StringUtils.lastPartLooksLikeURL(mCommittedTextBeforeComposingText);
}
public boolean nonWordCodePointAndNoSpaceBeforeCursor(final SpacingAndPunctuations spacingAndPunctuations) {
return StringUtilsKt.nonWordCodePointAndNoSpaceBeforeCursor(mCommittedTextBeforeComposingText, spacingAndPunctuations);
}
public boolean spaceBeforeCursor() {
return mCommittedTextBeforeComposingText.indexOf(" ") != -1;
}
public boolean hasLetterBeforeLastSpaceBeforeCursor() {
return StringUtilsKt.hasLetterBeforeLastSpaceBeforeCursor(mCommittedTextBeforeComposingText);
}
public boolean wordBeforeCursorMayBeEmail() {
return mCommittedTextBeforeComposingText.lastIndexOf(" ") < mCommittedTextBeforeComposingText.lastIndexOf("@");
}

View file

@ -0,0 +1,49 @@
package org.dslul.openboard.inputmethod.latin.common
import org.dslul.openboard.inputmethod.latin.settings.SpacingAndPunctuations
fun loopOverCodePoints(s: CharSequence, run: (Int) -> Boolean) {
val text = if (s is String) s else s.toString()
var offset = 0
while (offset < text.length) {
val codepoint = text.codePointAt(offset)
if (run(codepoint)) return
offset += Character.charCount(codepoint)
}
}
fun loopOverCodePointsBackwards(s: CharSequence, run: (Int) -> Boolean) {
val text = if (s is String) s else s.toString()
var offset = text.length
while (offset > 0) {
val codepoint = text.codePointBefore(offset)
if (run(codepoint)) return
offset -= Character.charCount(codepoint)
}
}
fun nonWordCodePointAndNoSpaceBeforeCursor(s: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean {
var space = false
var nonWordCodePoint = false
loopOverCodePointsBackwards(s) {
if (!space && Character.isWhitespace(it))
space = true
if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(it))
nonWordCodePoint = true
space && nonWordCodePoint
}
return space && nonWordCodePoint
}
fun hasLetterBeforeLastSpaceBeforeCursor(s: CharSequence): Boolean {
var letter = false
loopOverCodePointsBackwards(s) {
if (Character.isWhitespace(it)) true
else if (Character.isLetter(it)) {
letter = true
true
}
else false
}
return letter
}

View file

@ -849,7 +849,7 @@ public final class InputLogic {
if (Character.getType(codePoint) == Character.OTHER_SYMBOL
|| (sv.isWordSeparator(codePoint)
&& (Character.isWhitespace(codePoint) // whitespace is always a separator
|| !textBeforeCursorMayBeUrlOrSimilar(sv) // if text before is not URL or similar, it's a separator
|| !textBeforeCursorMayBeUrlOrSimilar(sv, false) // if text before is not URL or similar, it's a separator
|| (codePoint == '/' && mWordComposer.lastChar() == '/') // break composing at 2 consecutive slashes
)
)
@ -894,6 +894,8 @@ public final class InputLogic {
&& settingsValues.mSpacingAndPunctuations.isSometimesWordConnector(mConnection.getCodePointBeforeCursor())
// but not if there are two consecutive sometimesWordConnectors (e.g. "...bla")
&& !settingsValues.mSpacingAndPunctuations.isSometimesWordConnector(mConnection.getCharBeforeBeforeCursor())
// and not if there is no letter before the separator
&& mConnection.hasLetterBeforeLastSpaceBeforeCursor()
) {
final CharSequence text = mConnection.textBeforeCursorUntilLastWhitespaceOrDoubleSlash();
final TextRange range = new TextRange(text, 0, text.length(), text.length(), false);
@ -2108,7 +2110,7 @@ public final class InputLogic {
private void insertAutomaticSpaceIfOptionsAndTextAllow(final SettingsValues settingsValues) {
if (settingsValues.shouldInsertSpacesAutomatically()
&& settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
&& !textBeforeCursorMayBeUrlOrSimilar(settingsValues)
&& !textBeforeCursorMayBeUrlOrSimilar(settingsValues, true)
&& !mConnection.textBeforeCursorLooksLikeURL() // adding this check to textBeforeCursorMayBeUrlOrSimilar might not be wanted for word continuation (see effect on unit tests)
&& !(mConnection.getCodePointBeforeCursor() == Constants.CODE_PERIOD && mConnection.wordBeforeCursorMayBeEmail())
) {
@ -2116,12 +2118,15 @@ public final class InputLogic {
}
}
private boolean textBeforeCursorMayBeUrlOrSimilar(final SettingsValues settingsValues) {
private boolean textBeforeCursorMayBeUrlOrSimilar(final SettingsValues settingsValues, final Boolean forAutoSpace) {
final EditorInfo ei = getCurrentInputEditorInfo();
// URL field and no space -> may be URL
// for whatever absurd reason long message, postal address and email subject have type values that return true when filtering for URI, see https://developer.android.com/reference/android/text/InputType
// so we really need to specifically require URI as only type variation
if (ei != null && (ei.inputType & 0x000000f0) == 0x00000010 && !mConnection.spaceBeforeCursor())
if (ei != null && (ei.inputType & 0x000000f0) == 0x00000010 &&
// we never want to commit the first part of the url, but we want to insert autospace if text might be a normal word
(forAutoSpace ? mConnection.nonWordCodePointAndNoSpaceBeforeCursor(settingsValues.mSpacingAndPunctuations) // avoid detecting URL if it could be a word
: !mConnection.spaceBeforeCursor()))
return true;
// already contains a SometimesWordConnector -> may be URL (not so sure, only do with detection enabled
if (settingsValues.mUrlDetectionEnabled && settingsValues.mSpacingAndPunctuations.containsSometimesWordConnector(mWordComposer.getTypedWord()))