mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-14 09:48:12 +07:00
Fix and improve real time autofix while typing on multipleServer URL (#6772)
Sometime `TextField.cursorPosition` becomes greater than `TextField.text.length` for unknown reasons
In those cases we need to bring the cursor down to its maximum possible position which is `TextField.text.length`
Otherwise we will get `java.lang.StringIndexOutOfBoundsException` thrown from `kotlin.text.substring`
Not knowing the reason why it happens, I followed the libGDX implementation from here:
e03b757cae/gdx/src/com/badlogic/gdx/scenes/scene2d/ui/TextField.java (L689)
And it seems to have fixed the errors we were getting
This commit is contained in:

committed by
GitHub

parent
b5a2aa59b6
commit
96780be1d2
@ -43,6 +43,7 @@ import com.unciv.ui.worldscreen.WorldScreen
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
import kotlin.text.Regex
|
import kotlin.text.Regex
|
||||||
|
import kotlin.text.substring
|
||||||
import com.badlogic.gdx.utils.Array as GdxArray
|
import com.badlogic.gdx.utils.Array as GdxArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -275,6 +276,7 @@ class OptionsPopup(
|
|||||||
if (settings.multiplayerServer != Constants.dropboxMultiplayerServer) settings.multiplayerServer
|
if (settings.multiplayerServer != Constants.dropboxMultiplayerServer) settings.multiplayerServer
|
||||||
else "https://..."
|
else "https://..."
|
||||||
val multiplayerServerTextField = TextField(textToShowForMultiplayerAddress, BaseScreen.skin)
|
val multiplayerServerTextField = TextField(textToShowForMultiplayerAddress, BaseScreen.skin)
|
||||||
|
multiplayerServerTextField.setTextFieldFilter { _, c -> c !in " \r\n\t\\" }
|
||||||
multiplayerServerTextField.programmaticChangeEvents = true
|
multiplayerServerTextField.programmaticChangeEvents = true
|
||||||
val serverIpTable = Table()
|
val serverIpTable = Table()
|
||||||
|
|
||||||
@ -282,10 +284,15 @@ class OptionsPopup(
|
|||||||
multiplayerServerTextField.text = Gdx.app.clipboard.contents
|
multiplayerServerTextField.text = Gdx.app.clipboard.contents
|
||||||
}).row()
|
}).row()
|
||||||
multiplayerServerTextField.onChange {
|
multiplayerServerTextField.onChange {
|
||||||
multiplayerServerTextField.text = formatMultiplayerUrlInput(multiplayerServerTextField.text)
|
|
||||||
settings.multiplayerServer = multiplayerServerTextField.text
|
|
||||||
settings.save()
|
|
||||||
connectionToServerButton.isEnabled = multiplayerServerTextField.text != Constants.dropboxMultiplayerServer
|
connectionToServerButton.isEnabled = multiplayerServerTextField.text != Constants.dropboxMultiplayerServer
|
||||||
|
if (connectionToServerButton.isEnabled) {
|
||||||
|
fixTextFieldUrlOnType(multiplayerServerTextField)
|
||||||
|
// we can't trim on 'fixTextFieldUrlOnType' for reasons
|
||||||
|
settings.multiplayerServer = multiplayerServerTextField.text.trimEnd('/')
|
||||||
|
} else {
|
||||||
|
settings.multiplayerServer = multiplayerServerTextField.text
|
||||||
|
}
|
||||||
|
settings.save()
|
||||||
}
|
}
|
||||||
serverIpTable.add(multiplayerServerTextField).minWidth(screen.stage.width / 2).growX()
|
serverIpTable.add(multiplayerServerTextField).minWidth(screen.stage.width / 2).growX()
|
||||||
add(serverIpTable).fillX().row()
|
add(serverIpTable).fillX().row()
|
||||||
@ -962,20 +969,38 @@ class OptionsPopup(
|
|||||||
add(checkbox).colspan(2).left().row()
|
add(checkbox).colspan(2).left().row()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatMultiplayerUrlInput(input: String): String {
|
private fun fixTextFieldUrlOnType(TextField: TextField) {
|
||||||
var result : String
|
var text: String = TextField.text
|
||||||
|
var cursor: Int = minOf(TextField.cursorPosition, text.length)
|
||||||
|
|
||||||
// remove all whitespaces
|
// if text is 'http:' or 'https:' auto append '//'
|
||||||
result = Regex("\\s+").replace(input, "")
|
if (Regex("^https?:$").containsMatchIn(text)) {
|
||||||
|
TextField.appendText("//")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val textBeforeCursor: String = text.substring(0, cursor)
|
||||||
|
|
||||||
// replace multiple slash with a single one
|
// replace multiple slash with a single one
|
||||||
result = Regex("/{2,}").replace(result, "/")
|
val multipleSlashes = Regex("/{2,}")
|
||||||
|
text = multipleSlashes.replace(text, "/")
|
||||||
|
|
||||||
// remove trailing slash, reinstate protocol & return
|
// calculate updated cursor
|
||||||
// all the formatting above makes "https://" -> "http:/"
|
cursor = multipleSlashes.replace(textBeforeCursor, "/").length
|
||||||
// also people might leave a slash at end my mistake
|
|
||||||
// so we need to fix those before returning
|
// operations above makes 'https://' -> 'https:/'
|
||||||
return result.trimEnd('/').replaceFirst(":/", "://")
|
// fix that if available and update cursor
|
||||||
|
val i: Int = text.indexOf(":/")
|
||||||
|
if (i > -1) {
|
||||||
|
text = text.replaceRange(i..i+1, "://")
|
||||||
|
if (cursor > i + 1) ++cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
// update TextField
|
||||||
|
if (text != TextField.text) {
|
||||||
|
TextField.text = text
|
||||||
|
TextField.cursorPosition = cursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
Reference in New Issue
Block a user