mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 11:24:56 -04:00
improve eros error dialog, chat: url parsing
This commit is contained in:
parent
5d0d194ed2
commit
407019dadb
@ -43,7 +43,7 @@ class BaseComponent : ChatComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(parent: TextComponent? = null, legacy: String = "") {
|
constructor(parent: TextComponent? = null, legacy: String = "", restrictedMode: Boolean = false) {
|
||||||
val currentText = StringBuilder()
|
val currentText = StringBuilder()
|
||||||
var currentColor = parent?.color
|
var currentColor = parent?.color
|
||||||
val currentFormatting: MutableSet<ChatFormattingCode> = parent?.formatting?.toMutableSet() ?: mutableSetOf()
|
val currentFormatting: MutableSet<ChatFormattingCode> = parent?.formatting?.toMutableSet() ?: mutableSetOf()
|
||||||
@ -54,15 +54,34 @@ class BaseComponent : ChatComponent {
|
|||||||
|
|
||||||
|
|
||||||
fun push() {
|
fun push() {
|
||||||
if (currentText.isNotEmpty()) {
|
if (currentText.isEmpty()) {
|
||||||
parts += TextComponent(message = currentText.toString(), color = currentColor, formatting = currentFormatting.toMutableSet())
|
return
|
||||||
currentColor = null
|
}
|
||||||
currentText.clear()
|
val spaceSplit = currentText.split(' ')
|
||||||
|
for ((index, split) in spaceSplit.withIndex()) {
|
||||||
|
var clickEvent: ClickEvent? = null
|
||||||
|
for (protocol in URLProtocols.VALUES) {
|
||||||
|
if (!split.startsWith(protocol.prefix)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (protocol.restricted && restrictedMode) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
clickEvent = ClickEvent(ClickEvent.ClickEventActions.OPEN_URL, split)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
parts += TextComponent(message = split, color = currentColor, formatting = currentFormatting.toMutableSet(), clickEvent = clickEvent)
|
||||||
|
if (index != spaceSplit.size - 1) {
|
||||||
|
parts += TextComponent(message = " ", color = currentColor, formatting = currentFormatting.toMutableSet())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currentFormatting.clear()
|
currentFormatting.clear()
|
||||||
|
currentColor = null
|
||||||
|
currentText.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
while (char != CharacterIterator.DONE) {
|
while (char != CharacterIterator.DONE) {
|
||||||
|
// ToDo: Parse urls with click event (and respect restrictedMode)
|
||||||
if (char != ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) {
|
if (char != ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) {
|
||||||
currentText.append(char)
|
currentText.append(char)
|
||||||
char = iterator.next()
|
char = iterator.next()
|
||||||
@ -94,7 +113,7 @@ class BaseComponent : ChatComponent {
|
|||||||
push()
|
push()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(translator: Translator? = null, parent: TextComponent? = null, json: Map<String, Any>) {
|
constructor(translator: Translator? = null, parent: TextComponent? = null, json: Map<String, Any>, restrictedMode: Boolean = false) {
|
||||||
val currentParent: TextComponent?
|
val currentParent: TextComponent?
|
||||||
var currentText = ""
|
var currentText = ""
|
||||||
json["text"]?.nullCast<String>()?.let {
|
json["text"]?.nullCast<String>()?.let {
|
||||||
@ -121,10 +140,10 @@ class BaseComponent : ChatComponent {
|
|||||||
formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, json["strikethrough"]?.toBoolean())
|
formatting.addOrRemove(PreChatFormattingCodes.STRIKETHROUGH, json["strikethrough"]?.toBoolean())
|
||||||
formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json["obfuscated"]?.toBoolean())
|
formatting.addOrRemove(PreChatFormattingCodes.OBFUSCATED, json["obfuscated"]?.toBoolean())
|
||||||
|
|
||||||
val clickEvent = json["clickEvent"]?.compoundCast()?.let { click -> ClickEvent(click) }
|
val clickEvent = json["clickEvent"]?.compoundCast()?.let { click -> ClickEvent(click, restrictedMode) }
|
||||||
val hoverEvent = json["hoverEvent"]?.compoundCast()?.let { hover -> HoverEvent(hover) }
|
val hoverEvent = json["hoverEvent"]?.compoundCast()?.let { hover -> HoverEvent(hover) }
|
||||||
|
|
||||||
val textComponent = MultiChatComponent(
|
val textComponent = TextComponent(
|
||||||
message = currentText,
|
message = currentText,
|
||||||
color = color,
|
color = color,
|
||||||
formatting = formatting,
|
formatting = formatting,
|
||||||
|
@ -76,7 +76,7 @@ interface ChatComponent {
|
|||||||
val EMPTY = ChatComponent.of("")
|
val EMPTY = ChatComponent.of("")
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun of(raw: Any? = null, translator: Translator? = null, parent: TextComponent? = null, ignoreJson: Boolean = false): ChatComponent {
|
fun of(raw: Any? = null, translator: Translator? = null, parent: TextComponent? = null, ignoreJson: Boolean = false, restrictedMode: Boolean = false): ChatComponent {
|
||||||
// ToDo: Remove gson, replace with maps
|
// ToDo: Remove gson, replace with maps
|
||||||
if (raw == null) {
|
if (raw == null) {
|
||||||
return BaseComponent()
|
return BaseComponent()
|
||||||
@ -85,13 +85,13 @@ interface ChatComponent {
|
|||||||
return raw
|
return raw
|
||||||
}
|
}
|
||||||
if (raw is Map<*, *>) {
|
if (raw is Map<*, *>) {
|
||||||
return BaseComponent(translator, parent, raw.unsafeCast())
|
return BaseComponent(translator, parent, raw.unsafeCast(), restrictedMode)
|
||||||
}
|
}
|
||||||
val string = when (raw) {
|
val string = when (raw) {
|
||||||
is List<*> -> {
|
is List<*> -> {
|
||||||
val component = BaseComponent()
|
val component = BaseComponent()
|
||||||
for (part in raw) {
|
for (part in raw) {
|
||||||
component += of(part, translator, parent)
|
component += of(part, translator, parent, restrictedMode = restrictedMode)
|
||||||
}
|
}
|
||||||
return component
|
return component
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ interface ChatComponent {
|
|||||||
}
|
}
|
||||||
if (!ignoreJson && string.startsWith('{')) {
|
if (!ignoreJson && string.startsWith('{')) {
|
||||||
try {
|
try {
|
||||||
return BaseComponent(translator, parent, JSONSerializer.MAP_ADAPTER.fromJson(string)!!)
|
return BaseComponent(translator, parent, JSONSerializer.MAP_ADAPTER.fromJson(string)!!, restrictedMode)
|
||||||
} catch (ignored: JsonEncodingException) {
|
} catch (ignored: JsonEncodingException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
package de.bixilon.minosoft.data.text
|
package de.bixilon.minosoft.data.text
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
import de.bixilon.minosoft.Minosoft
|
||||||
|
import de.bixilon.minosoft.data.text.events.ClickEvent
|
||||||
|
import de.bixilon.minosoft.data.text.events.HoverEvent
|
||||||
|
import de.bixilon.minosoft.gui.eros.dialog.ErosErrorReport.Companion.report
|
||||||
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.hyperlink
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||||
@ -38,6 +42,8 @@ open class TextComponent(
|
|||||||
message: Any? = "",
|
message: Any? = "",
|
||||||
var color: RGBColor? = null,
|
var color: RGBColor? = null,
|
||||||
var formatting: MutableSet<ChatFormattingCode> = mutableSetOf(),
|
var formatting: MutableSet<ChatFormattingCode> = mutableSetOf(),
|
||||||
|
var clickEvent: ClickEvent? = null,
|
||||||
|
var hoverEvent: HoverEvent? = null,
|
||||||
) : ChatComponent {
|
) : ChatComponent {
|
||||||
override var message: String = message?.toString() ?: "null"
|
override var message: String = message?.toString() ?: "null"
|
||||||
|
|
||||||
@ -160,6 +166,26 @@ open class TextComponent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodes.add(text)
|
nodes.add(text)
|
||||||
|
|
||||||
|
clickEvent?.let { event ->
|
||||||
|
when (event.action) {
|
||||||
|
ClickEvent.ClickEventActions.OPEN_URL -> text.hyperlink(event.value.toString())
|
||||||
|
else -> {
|
||||||
|
NotImplementedError("Unknown action ${event.action}").report()
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hoverEvent?.let {
|
||||||
|
when (it.action) {
|
||||||
|
HoverEvent.HoverEventActions.SHOW_TEXT -> text.accessibleText = it.value.toString() // ToDo
|
||||||
|
else -> {
|
||||||
|
NotImplementedError("Unknown action ${it.action}").report()
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2020 Moritz Zwerger
|
* Copyright (C) 2021 Moritz Zwerger
|
||||||
*
|
*
|
||||||
* This program 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.
|
* This program 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.
|
||||||
*
|
*
|
||||||
@ -10,15 +10,20 @@
|
|||||||
*
|
*
|
||||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.bixilon.minosoft.data.text
|
package de.bixilon.minosoft.data.text
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.text.events.ClickEvent
|
import de.bixilon.minosoft.util.KUtil
|
||||||
import de.bixilon.minosoft.data.text.events.HoverEvent
|
import de.bixilon.minosoft.util.enum.ValuesEnum
|
||||||
|
|
||||||
class MultiChatComponent(
|
enum class URLProtocols(val prefix: String, val restricted: Boolean = false) {
|
||||||
message: String = "",
|
HTTP("http://"),
|
||||||
color: RGBColor? = null,
|
HTTPS("https://"),
|
||||||
formatting: MutableSet<ChatFormattingCode> = mutableSetOf(),
|
FILE("file:", true),
|
||||||
var clickEvent: ClickEvent? = null,
|
;
|
||||||
var hoverEvent: HoverEvent? = null,
|
|
||||||
) : TextComponent(message, color, formatting)
|
companion object : ValuesEnum<URLProtocols> {
|
||||||
|
override val VALUES: Array<URLProtocols> = values()
|
||||||
|
override val NAME_MAP: Map<String, URLProtocols> = KUtil.getEnumValues(VALUES)
|
||||||
|
}
|
||||||
|
}
|
@ -13,15 +13,23 @@
|
|||||||
package de.bixilon.minosoft.data.text.events
|
package de.bixilon.minosoft.data.text.events
|
||||||
|
|
||||||
import de.bixilon.minosoft.util.KUtil
|
import de.bixilon.minosoft.util.KUtil
|
||||||
|
import de.bixilon.minosoft.util.Util
|
||||||
import de.bixilon.minosoft.util.enum.ValuesEnum
|
import de.bixilon.minosoft.util.enum.ValuesEnum
|
||||||
|
|
||||||
class ClickEvent {
|
class ClickEvent {
|
||||||
val action: ClickEventActions
|
val action: ClickEventActions
|
||||||
val value: Any
|
val value: Any
|
||||||
|
|
||||||
constructor(json: Map<String, Any>) {
|
constructor(json: Map<String, Any>, restrictedMode: Boolean = false) {
|
||||||
action = ClickEventActions[json["action"].toString().lowercase()]
|
action = ClickEventActions[json["action"].toString().lowercase()]
|
||||||
this.value = json["value"]!!
|
this.value = json["value"]!!
|
||||||
|
|
||||||
|
if (!restrictedMode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (action == ClickEventActions.OPEN_URL) {
|
||||||
|
Util.checkURL(value.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(action: ClickEventActions, value: Any) {
|
constructor(action: ClickEventActions, value: Any) {
|
||||||
|
@ -13,19 +13,29 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.eros.dialog
|
package de.bixilon.minosoft.gui.eros.dialog
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.Minosoft
|
||||||
import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
||||||
import de.bixilon.minosoft.gui.eros.crash.ErosCrashReport.Companion.crash
|
import de.bixilon.minosoft.gui.eros.crash.ErosCrashReport.Companion.crash
|
||||||
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
|
||||||
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.ctext
|
||||||
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.text
|
||||||
import de.bixilon.minosoft.terminal.RunConfiguration
|
import de.bixilon.minosoft.terminal.RunConfiguration
|
||||||
import de.bixilon.minosoft.util.KUtil.asResourceLocation
|
import de.bixilon.minosoft.util.KUtil.asResourceLocation
|
||||||
|
import de.bixilon.minosoft.util.KUtil.realName
|
||||||
import de.bixilon.minosoft.util.KUtil.toStackTrace
|
import de.bixilon.minosoft.util.KUtil.toStackTrace
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
|
import javafx.scene.control.Button
|
||||||
import javafx.scene.control.TextArea
|
import javafx.scene.control.TextArea
|
||||||
|
import javafx.scene.text.TextFlow
|
||||||
|
|
||||||
|
|
||||||
class ErosErrorReport : JavaFXWindowController() {
|
class ErosErrorReport : JavaFXWindowController() {
|
||||||
|
@FXML private lateinit var headerFX: TextFlow
|
||||||
|
@FXML private lateinit var descriptionFX: TextFlow
|
||||||
@FXML private lateinit var detailsFX: TextArea
|
@FXML private lateinit var detailsFX: TextArea
|
||||||
|
@FXML private lateinit var ignoreFX: Button
|
||||||
|
@FXML private lateinit var fatalCrashFX: Button
|
||||||
|
|
||||||
var exception: Throwable? = null
|
var exception: Throwable? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -45,9 +55,23 @@ class ErosErrorReport : JavaFXWindowController() {
|
|||||||
exception?.crash()
|
exception?.crash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun init() {
|
||||||
|
super.init()
|
||||||
|
headerFX.text = HEADER
|
||||||
|
descriptionFX.text = DESCRIPTION
|
||||||
|
|
||||||
|
ignoreFX.ctext = IGNORE
|
||||||
|
fatalCrashFX.ctext = FATAL_CRASH
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LAYOUT = "minosoft:eros/dialog/error.fxml".asResourceLocation()
|
private val LAYOUT = "minosoft:eros/dialog/error.fxml".asResourceLocation()
|
||||||
|
private val TITLE = { exception: Throwable? -> Minosoft.LANGUAGE_MANAGER.translate("minosoft:error.title".asResourceLocation(), null, exception?.let { it::class.java.realName }) }
|
||||||
|
private val HEADER = "minosoft:error.header".asResourceLocation()
|
||||||
|
private val DESCRIPTION = "minosoft:error.description".asResourceLocation()
|
||||||
|
private val IGNORE = "minosoft:error.ignore".asResourceLocation()
|
||||||
|
private val FATAL_CRASH = "minosoft:error.fatal_crash".asResourceLocation()
|
||||||
|
|
||||||
fun Throwable?.report() {
|
fun Throwable?.report() {
|
||||||
if (RunConfiguration.DISABLE_EROS) {
|
if (RunConfiguration.DISABLE_EROS) {
|
||||||
@ -55,7 +79,7 @@ class ErosErrorReport : JavaFXWindowController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
val controller = JavaFXUtil.openModal<ErosErrorReport>("", LAYOUT)
|
val controller = JavaFXUtil.openModal<ErosErrorReport>(TITLE(this), LAYOUT)
|
||||||
controller.exception = this
|
controller.exception = this
|
||||||
controller.stage.show()
|
controller.stage.show()
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
|||||||
import de.bixilon.minosoft.gui.eros.modding.invoker.JavaFXEventInvoker
|
import de.bixilon.minosoft.gui.eros.modding.invoker.JavaFXEventInvoker
|
||||||
import de.bixilon.minosoft.gui.eros.util.JavaFXAccountUtil.avatar
|
import de.bixilon.minosoft.gui.eros.util.JavaFXAccountUtil.avatar
|
||||||
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil
|
||||||
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.clickable
|
||||||
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.ctext
|
import de.bixilon.minosoft.gui.eros.util.JavaFXUtil.ctext
|
||||||
import de.bixilon.minosoft.modding.event.events.account.AccountSelectEvent
|
import de.bixilon.minosoft.modding.event.events.account.AccountSelectEvent
|
||||||
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
|
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
|
||||||
@ -90,6 +91,10 @@ class MainErosController : JavaFXWindowController() {
|
|||||||
ErosMainActivities.ABOUT to aboutIconFX,
|
ErosMainActivities.ABOUT to aboutIconFX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for (icon in iconMap) {
|
||||||
|
icon.value.clickable()
|
||||||
|
}
|
||||||
|
|
||||||
highlightIcon(playIconFX)
|
highlightIcon(playIconFX)
|
||||||
|
|
||||||
playIconFX.setOnMouseClicked {
|
playIconFX.setOnMouseClicked {
|
||||||
@ -104,14 +109,19 @@ class MainErosController : JavaFXWindowController() {
|
|||||||
aboutIconFX.setOnMouseClicked {
|
aboutIconFX.setOnMouseClicked {
|
||||||
activity = ErosMainActivities.ABOUT
|
activity = ErosMainActivities.ABOUT
|
||||||
}
|
}
|
||||||
exitIconFX.setOnMouseClicked {
|
exitIconFX.apply {
|
||||||
ShutdownManager.shutdown(reason = ShutdownReasons.REQUESTED_BY_USER)
|
clickable()
|
||||||
|
setOnMouseClicked {
|
||||||
|
ShutdownManager.shutdown(reason = ShutdownReasons.REQUESTED_BY_USER)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalEventMaster.registerEvent(JavaFXEventInvoker.of<AccountSelectEvent> {
|
GlobalEventMaster.registerEvent(JavaFXEventInvoker.of<AccountSelectEvent> {
|
||||||
accountImageFX.image = it.account?.avatar
|
accountImageFX.image = it.account?.avatar
|
||||||
accountNameFX.ctext = it.account?.username ?: NO_ACCOUNT_SELECTED
|
accountNameFX.ctext = it.account?.username ?: NO_ACCOUNT_SELECTED
|
||||||
})
|
})
|
||||||
|
accountImageFX.clickable()
|
||||||
|
accountNameFX.clickable()
|
||||||
|
|
||||||
activity = ErosMainActivities.PlAY
|
activity = ErosMainActivities.PlAY
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ import de.bixilon.minosoft.gui.eros.controller.EmbeddedJavaFXController
|
|||||||
import de.bixilon.minosoft.gui.eros.controller.JavaFXController
|
import de.bixilon.minosoft.gui.eros.controller.JavaFXController
|
||||||
import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController
|
||||||
import de.bixilon.minosoft.util.KUtil.setValue
|
import de.bixilon.minosoft.util.KUtil.setValue
|
||||||
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
|
import javafx.css.StyleableProperty
|
||||||
import javafx.fxml.FXMLLoader
|
import javafx.fxml.FXMLLoader
|
||||||
import javafx.scene.Parent
|
import javafx.scene.*
|
||||||
import javafx.scene.Scene
|
|
||||||
import javafx.scene.control.Labeled
|
import javafx.scene.control.Labeled
|
||||||
import javafx.scene.control.TextField
|
import javafx.scene.control.TextField
|
||||||
import javafx.scene.image.Image
|
import javafx.scene.image.Image
|
||||||
@ -92,4 +93,15 @@ object JavaFXUtil {
|
|||||||
set(value) {
|
set(value) {
|
||||||
this.text = Minosoft.LANGUAGE_MANAGER.translate(value).message
|
this.text = Minosoft.LANGUAGE_MANAGER.translate(value).message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Text.hyperlink(link: String) {
|
||||||
|
this.setOnMouseClicked { HOST_SERVICES.showDocument(link) }
|
||||||
|
this.accessibleRole = AccessibleRole.HYPERLINK
|
||||||
|
this.styleClass.setAll("hyperlink")
|
||||||
|
this.clickable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Node.clickable() {
|
||||||
|
this.cursorProperty().unsafeCast<StyleableProperty<Cursor>>().applyStyle(null, Cursor.HAND)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ open class InByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun readChatComponent(): ChatComponent {
|
open fun readChatComponent(): ChatComponent {
|
||||||
return ChatComponent.of(readString())
|
return ChatComponent.of(readString(), restrictedMode = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readChatComponentArray(length: Int = readVarInt()): Array<ChatComponent> {
|
fun readChatComponentArray(length: Int = readVarInt()): Array<ChatComponent> {
|
||||||
|
@ -17,12 +17,10 @@
|
|||||||
<RowConstraints maxHeight="Infinity" vgrow="ALWAYS"/>
|
<RowConstraints maxHeight="Infinity" vgrow="ALWAYS"/>
|
||||||
<RowConstraints maxHeight="Infinity" vgrow="NEVER"/>
|
<RowConstraints maxHeight="Infinity" vgrow="NEVER"/>
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<Text strokeWidth="0.0" text="An error occurred">
|
<TextFlow fx:id="headerFX" style="-fx-font-size: 30; -fx-font-weight: bold;">
|
||||||
<font>
|
<Text text="An error occurred"/>
|
||||||
<Font name="System Bold" size="19.0"/>
|
</TextFlow>
|
||||||
</font>
|
<TextFlow fx:id="descriptionFX" GridPane.rowIndex="1">
|
||||||
</Text>
|
|
||||||
<TextFlow GridPane.rowIndex="1">
|
|
||||||
<Label text="An error in minosoft occurred. You can continue like before, but the behavior might not be the expected one. If this error persists, feel free to open an issue here: " wrapText="true"/>
|
<Label text="An error in minosoft occurred. You can continue like before, but the behavior might not be the expected one. If this error persists, feel free to open an issue here: " wrapText="true"/>
|
||||||
<Hyperlink onAction="#openURL" text="https://gitlab.bixilon.de/bixilon/minosoft/-/issues/" wrapText="true"/>
|
<Hyperlink onAction="#openURL" text="https://gitlab.bixilon.de/bixilon/minosoft/-/issues/" wrapText="true"/>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
@ -51,8 +49,8 @@
|
|||||||
<padding>
|
<padding>
|
||||||
<Insets top="5.0"/>
|
<Insets top="5.0"/>
|
||||||
</padding>
|
</padding>
|
||||||
<Button maxWidth="Infinity" onAction="#ignore" text="Ignore" GridPane.columnIndex="2"/>
|
<Button fx:id="ignoreFX" maxWidth="Infinity" onAction="#ignore" text="Ignore" GridPane.columnIndex="2"/>
|
||||||
<Button maxWidth="Infinity" onAction="#fatalCrash" text="Fatal crash"/>
|
<Button fx:id="fatalCrashFX" maxWidth="Infinity" onAction="#fatalCrash" text="Fatal crash"/>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -98,3 +98,9 @@ minosoft:connection.kick.close_button=Close
|
|||||||
minosoft:connection.login_kick.title=Kicked from server
|
minosoft:connection.login_kick.title=Kicked from server
|
||||||
minosoft:connection.login_kick.header=You got kicked
|
minosoft:connection.login_kick.header=You got kicked
|
||||||
minosoft:connection.login_kick.description=You got kicked while logging in from %1$s (connected with: %2$s)
|
minosoft:connection.login_kick.description=You got kicked while logging in from %1$s (connected with: %2$s)
|
||||||
|
|
||||||
|
minosoft:error.title=%1$s - Minosoft
|
||||||
|
minosoft:error.header=An error occurred!
|
||||||
|
minosoft:error.description=An error in minosoft occurred. You can continue like before, but the behavior might not be the expected one. If this error persists, feel free to open an issue here: https://gitlab.bixilon.de/bixilon/minosoft/-/issues/
|
||||||
|
minosoft:error.ignore=Ignore
|
||||||
|
minosoft:error.fatal_crash=Fatal crash
|
||||||
|
Loading…
x
Reference in New Issue
Block a user