Implement new instance window, bump java and GTK

This commit is contained in:
Johannes Frohnmeyer 2023-06-30 14:02:31 +02:00
parent e9f8af5617
commit 1be0d68a56
Signed by: Johannes
GPG Key ID: E76429612C2929F4
21 changed files with 386 additions and 126 deletions

View File

@ -17,10 +17,7 @@ val jbAnnotationsVersion by extra("24.0.1")
val lwjglVersion by extra("3.3.2")
val imguiVersion by extra("1.86.10")
// launcher-gtk
val javagiVersion by extra("0.4")
val glibVersion by extra("1.2.10")
val gtkVersion by extra("4.8.3")
val adwaitaVersion by extra("1.2.0")
val javagiVersion by extra("v0.5.1")
val flavorProp: String by extra(prop("flavor", "custom"))
if (!setOf("custom", "maven", "fat", "windows", "linux", "macos").contains(flavorProp)) throw IllegalStateException("Unsupported flavor: $flavorProp")

View File

@ -10,5 +10,5 @@ repositories {
dependencies {
implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2")
implementation("de.undercouch:gradle-download-task:5.1.2")
implementation("io.gitlab.jfronny:convention:1.3-SNAPSHOT")
implementation("io.gitlab.jfronny:convention:1.4-SNAPSHOT")
}

View File

@ -3,6 +3,12 @@ plugins {
`maven-publish`
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(20))
}
}
repositories {
mavenCentral()
maven("https://maven.frohnmeyer-wds.de/artifacts")

View File

@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("inceptum.application")
id("com.github.johnrengelman.shadow")
kotlin("jvm") version "1.8.21"
kotlin("jvm") version "1.9.0-RC"
}
application {
@ -12,18 +12,19 @@ application {
repositories {
mavenLocal()
maven { url = uri("https://maven.frohnmeyer-wds.de/java-gi") }
maven("https://jitpack.io") {
content {
includeGroup("com.github.jwharm.java-gi")
}
}
}
dependencies {
val javagiVersion: String by rootProject.extra
val glibVersion: String by rootProject.extra
val gtkVersion: String by rootProject.extra
val adwaitaVersion: String by rootProject.extra
implementation("io.github.jwharm.javagi:glib:$glibVersion-$javagiVersion")
implementation("io.github.jwharm.javagi:gtk:$gtkVersion-$javagiVersion")
implementation("io.github.jwharm.javagi:adwaita:$adwaitaVersion-$javagiVersion")
implementation("com.github.jwharm.java-gi:glib:$javagiVersion")
implementation("com.github.jwharm.java-gi:gtk:$javagiVersion")
implementation("com.github.jwharm.java-gi:adwaita:$javagiVersion")
implementation(project(":launcher"))
}
@ -51,13 +52,4 @@ tasks.runShadow {
jvmArgs("--enable-preview", "--enable-native-access=ALL-UNNAMED")
}
kotlin {
sourceSets.all {
languageSettings {
languageVersion = "2.0"
progressiveMode = true
}
}
}
tasks.withType(KotlinCompile::class) { compilerOptions.freeCompilerArgs.addAll("-Xlambdas=indy") }

View File

@ -2,11 +2,11 @@ package io.gitlab.jfronny.inceptum.gtk
import io.gitlab.jfronny.commons.StringFormatter
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.util.markup
import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog
import io.gitlab.jfronny.inceptum.gtk.window.dialog.StringInputDialog
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv.EnvBackend
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount
import org.gnome.gio.Cancellable
import org.gnome.gtk.*
import java.util.function.Consumer
@ -16,21 +16,21 @@ object GtkEnvBackend : EnvBackend {
override fun showError(message: String, title: String) {
Utils.LOGGER.error(message)
simpleDialog(message, title, MessageType.ERROR, ButtonsType.CLOSE, null, null)
simpleDialog(message, title, null, null)
}
override fun showError(message: String, t: Throwable) {
simpleDialog(StringFormatter.toString(t), message, MessageType.ERROR, ButtonsType.CLOSE, null, null)
simpleDialog(StringFormatter.toString(t), message, null, null)
}
override fun showInfo(message: String, title: String) {
Utils.LOGGER.info(message)
simpleDialog(message, title, MessageType.INFO, ButtonsType.CLOSE, null, null)
simpleDialog(message, title, null, null)
}
override fun showOkCancel(message: String, title: String, ok: Runnable, cancel: Runnable, defaultCancel: Boolean) {
Utils.LOGGER.info(message)
simpleDialog(message, title, MessageType.QUESTION, ButtonsType.OK_CANCEL, ok, cancel)
simpleDialog(message, title, ok, cancel)
}
override fun getInput(
@ -52,37 +52,40 @@ object GtkEnvBackend : EnvBackend {
)
dialog.title = prompt
dialog.onResponse(processResponses(dialog, { ok.accept(dialog.input) }, cancel))
dialog.show()
dialog.visible = true
}
override fun showLoginRefreshPrompt(account: MicrosoftAccount) =
schedule { MicrosoftLoginDialog(dialogParent, account).show() }
schedule { MicrosoftLoginDialog(dialogParent, account).visible = true }
private fun simpleDialog(
markup: String,
title: String,
type: MessageType,
buttons: ButtonsType,
ok: Runnable?,
cancel: Runnable?
) = schedule { simpleDialog(dialogParent, markup, title, type, buttons, ok, cancel) }
) = schedule { simpleDialog(dialogParent, markup, title, ok, cancel) }
@JvmStatic
fun simpleDialog(
parent: Window?,
markup: String,
title: String,
type: MessageType?,
buttons: ButtonsType?,
ok: Runnable?,
cancel: Runnable?
) {
val dialog =
MessageDialog(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), type, buttons, null)
dialog.title = title
dialog.markup = markup
dialog.onResponse(processResponses(dialog, ok, cancel))
dialog.show()
run {
val dialog = AlertDialog("")
dialog.message = title
dialog.detail = markup
dialog.modal = true
dialog.choose(parent, Cancellable()) { _, res, _ ->
val result = dialog.chooseFinish(res)
val cancelIdx = dialog.cancelButton
val defaultIdx = dialog.defaultButton
if (result == cancelIdx) cancel?.run()
if (result == defaultIdx) ok?.run()
}
}
}
private fun processResponses(dialog: Dialog, ok: Runnable?, cancel: Runnable?): Dialog.Response {

View File

@ -1,12 +1,13 @@
package io.gitlab.jfronny.inceptum.gtk
import io.gitlab.jfronny.commons.OSUtils
import io.gitlab.jfronny.commons.io.JFiles
import io.gitlab.jfronny.inceptum.common.MetaHolder
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder
import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.window.AboutWindow
import io.gitlab.jfronny.inceptum.gtk.window.NewInstanceWindow
import io.gitlab.jfronny.inceptum.gtk.window.create.NewInstanceWindow
import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog
import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow
@ -20,6 +21,8 @@ import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher
import io.gitlab.jfronny.inceptum.launcher.system.launch.LaunchType
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
import org.gnome.gdk.Clipboard
import org.gnome.gio.Cancellable
import org.gnome.gtk.*
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor
@ -111,21 +114,34 @@ object GtkMenubar {
dialog.show()
}
newMenu!!.button("url") {
LauncherEnv.getInput(
I18n["menu.file.new.url"],
I18n["menu.file.new.url.details"],
Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor) as String,
{ s: String? ->
val state = ProcessState(Importers.MAX_STEPS, "Initializing")
ProcessStateWatcherDialog.show(
GtkEnvBackend.dialogParent,
I18n["menu.file.new.url"],
I18n["menu.file.new.url.error"],
state
) {
Importers.importPack(s, state)
}
}, {})
readClipboard { clipboard ->
LauncherEnv.getInput(
I18n["menu.file.new.url"],
I18n["menu.file.new.url.details"],
clipboard ?: "",
{ s: String? ->
val state = ProcessState(Importers.MAX_STEPS, "Initializing")
ProcessStateWatcherDialog.show(
GtkEnvBackend.dialogParent,
I18n["menu.file.new.url"],
I18n["menu.file.new.url.error"],
state
) {
Importers.importPack(s, state)
}
}, {})
}
}
}
private fun readClipboard(continuation: (String?) -> Unit) {
if (OSUtils.TYPE == OSUtils.Type.LINUX) {
val clipboard = GtkEnvBackend.dialogParent!!.display.clipboard
clipboard.readTextAsync(Cancellable()) { _, res, _ ->
continuation(clipboard.readTextFinish(res))
}
} else {
continuation(Toolkit.getDefaultToolkit().systemClipboard.getData(DataFlavor.stringFlavor) as String?)
}
}

View File

@ -26,7 +26,10 @@ class ILabel(str: @PropertyKey(resourceBundle = I18n.BUNDLE) String, mode: Mode,
val provider = CssProvider()
try {
GtkMain::class.java.classLoader.getResourceAsStream("inceptum.css")!!
.use { provider.loadFromData(it.readAllBytes()) }
.use {
val bytes = it.readAllBytes()
provider.loadFromData(String(bytes), bytes.size.toLong())
}
} catch (t: Throwable) {
throw RuntimeException(t)
}

View File

@ -4,10 +4,10 @@ import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance
import org.gnome.gtk.Image
import org.gnome.gtk.Spinner
import org.gnome.gtk.Stack
import java.lang.foreign.Addressable
import java.lang.foreign.MemorySegment
class InstanceThumbnail : Stack {
private constructor(address: Addressable) : super(address)
private constructor(address: MemorySegment) : super(address)
constructor() : super() {
val spinner = Spinner()

View File

@ -0,0 +1,32 @@
package io.gitlab.jfronny.inceptum.gtk.control
import org.gnome.gtk.DropDown
import org.gnome.gtk.PropertyExpression
import org.gnome.gtk.StringList
import org.gnome.gtk.StringObject
import java.util.ArrayList
import java.util.function.IntConsumer
class KDropDown<T>(options: Array<T>, private val stringify: (T) -> String, selected: Int): DropDown(options.toModel(stringify), null) {
private val onChange = ArrayList<IntConsumer>()
init {
this.selected = selected
onNotify("selected") { _ -> onChange.forEach { it.accept(this.selected) } }
expression = PropertyExpression(StringObject.getType(), null, "string")
}
fun onChange(changed: IntConsumer) {
onChange.add(changed)
}
fun updateOptions(newOptions: Array<T>, newSelected: Int) {
selected = 0
model = newOptions.toModel(stringify)
selected = newSelected
}
companion object {
private fun <T> Array<T>.toModel(stringify: (T) -> String) = StringList(map(stringify).toTypedArray())
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.inceptum.gtk.control
import org.gnome.gtk.Entry
import java.util.function.Consumer
class KEntry(value: String? = ""): Entry() {
private val onChange = ArrayList<Consumer<String>>()
init {
text = value ?: ""
onChanged { onChange.forEach { it.accept(text) } }
}
fun onChange(changed: Consumer<String>) {
onChange.add(changed)
}
}

View File

@ -0,0 +1,15 @@
package io.gitlab.jfronny.inceptum.gtk.control.assistant
import org.gnome.gtk.AssistantPageType
import org.gnome.gtk.Box
import org.gnome.gtk.Orientation
class AssistantPage(val title: String, val type: AssistantPageType): Box(Orientation.VERTICAL, 8) {
lateinit var setComplete: (Boolean) -> Unit
private val onOpen = ArrayList<Runnable>()
fun onOpen(action: Runnable) {
onOpen.add(action)
}
fun emitOpen() = onOpen.forEach { it.run() }
}

View File

@ -0,0 +1,33 @@
package io.gitlab.jfronny.inceptum.gtk.control.assistant
import io.gitlab.jfronny.inceptum.common.Utils
import org.gnome.gtk.Application
import org.gnome.gtk.Assistant
import org.gnome.gtk.AssistantPageType
open class KAssistant(app: Application) : Assistant() {
private val pages = ArrayList<AssistantPage>()
init {
application = app
onPrepare { next ->
val page = pages.firstOrNull { it.handle() == next.handle() }
if (page == null) {
Utils.LOGGER.error("Unknown page opened in assistant")
} else {
page.emitOpen()
}
}
}
fun page(title: String, type: AssistantPageType, setup: AssistantPage.() -> Unit): Int {
val page = AssistantPage(title, type)
val idx = appendPage(page)
pages.add(page)
page.setComplete = { setPageComplete(page, it) }
page.setup()
setPageType(page, page.type)
setPageTitle(page, page.title)
return idx
}
}

View File

@ -1,6 +1,8 @@
package io.gitlab.jfronny.inceptum.gtk.control.settings
import io.gitlab.jfronny.inceptum.gtk.control.ILabel
import io.gitlab.jfronny.inceptum.gtk.control.KDropDown
import io.gitlab.jfronny.inceptum.gtk.control.KEntry
import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.margin
import org.gnome.gtk.*
@ -41,12 +43,10 @@ class IRow(
}
}
fun setDropdown(options: Array<String>, defaultIndex: Int, changed: IntConsumer): DropDown {
return DropDown(StringList(options), null).apply {
fun setDropdown(options: Array<String>, defaultIndex: Int, changed: IntConsumer): KDropDown<String> {
return KDropDown(options, { it } , defaultIndex).apply {
onChange(changed)
packSmallEnd()
selected = defaultIndex
onNotify("selected") { _ -> changed.accept(selected) }
expression = PropertyExpression(StringObject.getType(), null, "string")
}
}
@ -69,13 +69,12 @@ class IRow(
}
}
fun setEntry(value: String?, changed: Consumer<String>): Entry {
return Entry().apply {
text = value ?: ""
fun setEntry(value: String?, changed: Consumer<String>): KEntry {
return KEntry(value).apply {
hexpand = true
valign = Align.CENTER
halign = Align.FILL
onChanged { changed.accept(text) }
onChange(changed)
append(this)
}
}

View File

@ -81,8 +81,6 @@ open class SettingsTab(window: Window?) : Box(Orientation.VERTICAL, 8) {
window,
StringFormatter.toString(t),
message,
MessageType.ERROR,
ButtonsType.CLOSE,
null,
null
)

View File

@ -1,15 +0,0 @@
package io.gitlab.jfronny.inceptum.gtk.window
import org.gnome.gtk.*
class NewInstanceWindow(app: Application) : Assistant() {
init {
application = app
run {
val initialPage = Box(Orientation.VERTICAL, 8)
initialPage.append(Label("Importing instances via this assistant is not yet supported, use the ImGUI"))
appendPage(initialPage)
setPageType(initialPage, AssistantPageType.INTRO)
}
}
}

View File

@ -0,0 +1,179 @@
package io.gitlab.jfronny.inceptum.gtk.window.create
import io.gitlab.jfronny.commons.StringFormatter
import io.gitlab.jfronny.commons.io.JFiles
import io.gitlab.jfronny.inceptum.common.InceptumConfig
import io.gitlab.jfronny.inceptum.common.MetaHolder
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.control.KDropDown
import io.gitlab.jfronny.inceptum.gtk.control.KEntry
import io.gitlab.jfronny.inceptum.gtk.control.assistant.KAssistant
import io.gitlab.jfronny.inceptum.gtk.schedule
import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi
import io.gitlab.jfronny.inceptum.launcher.api.McApi
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionsListInfo
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceNameTool
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps
import org.gnome.glib.GLib
import org.gnome.gtk.*
import java.io.IOException
class NewInstanceWindow(app: Application) : KAssistant(app) {
companion object {
private val VERSIONS = McApi.getVersions()
}
init {
var gameVersion: VersionsListInfo? = null
var useFabric = false
var fabricVersion: FabricVersionLoaderInfo? = null
var name = "New Instance"
var failureMessage = "Unknown error, please look at the log!"
var isFailure = false
page("Welcome", AssistantPageType.INTRO) {
append(Label("This assistant will guide you through the process of setting up a Minecraft instance.\nTo begin, please choose the game version you want to use"))
val versions = VERSIONS.versions.stream()
.filter { InceptumConfig.snapshots || it.type == "release" }
.toTypedArray()
val def = versions.withIndex().firstOrNull { it.value.id == VERSIONS.latest.release }?.index ?: 0
gameVersion = versions[def]
append(KDropDown(versions, { it.id }, def).apply {
onChange { gameVersion = versions[it] }
})
setComplete(true)
}
page("Loader", AssistantPageType.CONTENT) {
append(Label("Select a mod loader if you want to use mods in this instance. This can be changed later."))
var lastGameVersion: VersionsListInfo? = null
var versions = arrayOf<FabricVersionLoaderInfo>()
var def = 0
val none = CheckButton.newWithLabel("None")
val fabric = CheckButton.newWithLabel("Fabric")
none.onActivate { useFabric = false }
none.onActivate { useFabric = true }
append(none)
val fabricVersionDropdown = KDropDown(versions, { it.loader.version }, def)
fabricVersionDropdown.onChange { fabricVersion = versions[it] }
append(Box(Orientation.HORIZONTAL, 8).apply {
append(fabric)
append(fabricVersionDropdown)
})
onOpen {
if (lastGameVersion == null || lastGameVersion != gameVersion) {
versions = FabricMetaApi.getLoaderVersions(gameVersion!!).toTypedArray()
def = versions.withIndex().firstOrNull { it.value.loader.stable }?.index ?: 0
fabricVersionDropdown.updateOptions(versions, def)
lastGameVersion = gameVersion
none.active = true
fabric.active = false
useFabric = false
}
if (versions.isEmpty()) {
none.active = true
fabric.active = false
useFabric = false
fabric.sensitive = false
}
}
setComplete(true)
}
page("Name", AssistantPageType.CONTENT) {
append(Label(I18n["instance.settings.general.name.placeholder"]))
val entry = KEntry(name)
entry.placeholderText = I18n["instance.settings.general.name.placeholder"]
entry.valign
entry.onChange { name = InstanceNameTool.getNextValid(it) }
append(entry)
onOpen {
name = InstanceNameTool.getDefaultName(gameVersion!!.id, useFabric)
entry.text = name
}
setComplete(true)
}
page("Creating", AssistantPageType.PROGRESS) {
append(Label("Creating Instance"))
val progress = ProgressBar()
append(progress)
val stage = Label("")
append(stage)
onOpen {
commit()
val pState = Steps.createProcessState()
val state = SetupStepInfo(
McApi.getVersionInfo(gameVersion),
if (useFabric) LoaderInfo(fabricVersion!!.loader) else LoaderInfo.NONE,
name,
pState
)
var finished = false
var cachedState: ProcessStateWatcherDialog.State? = null
addTickCallback { widget, _ ->
if (finished) return@addTickCallback GLib.SOURCE_REMOVE
val nc = ProcessStateWatcherDialog.State(pState)
if (nc != cachedState) {
cachedState = nc
stage.setMarkup(cachedState!!.msg)
progress.fraction = cachedState!!.progress.coerceAtMost(1f).toDouble()
widget.queueDraw()
}
GLib.SOURCE_CONTINUE
}
onClose { pState.cancel() }
onCancel { pState.cancel() }
pState.updateStep("Starting install process")
Thread {
try {
for (step in Steps.STEPS) {
if (state.isCancelled) {
try {
JFiles.deleteRecursive(MetaHolder.INSTANCE_DIR.resolve(state.name))
} catch (e: IOException) {
Utils.LOGGER.error("Could not delete instance dir", e)
}
return@Thread
}
pState.incrementStep(step.name)
step.execute(state)
}
} catch (e: Throwable) {
pState.cancel()
Utils.LOGGER.error("Could not create instance")
failureMessage = StringFormatter.toString(e)
isFailure = true
} finally {
finished = true
schedule { setComplete(true) }
schedule { nextPage() }
}
}.start()
}
}
page("Done", AssistantPageType.SUMMARY) {
val status = Label("")
onOpen {
if (isFailure) {
status.setMarkup("Something went wrong while creating the instance.\n\n$failureMessage")
} else {
status.setMarkup("The instance was successfully created. You can now launch it using the main menu")
}
}
}
}
}

View File

@ -51,9 +51,7 @@ class ProcessStateWatcherDialog(
(messageArea as Box).append(progress)
addTickCallback { widget, _ ->
if (finished) return@addTickCallback GLib.SOURCE_REMOVE
val nc = State(
state
)
val nc = State(state)
if (nc != cachedState) {
cachedState = nc
setMarkup(cachedState!!.msg)
@ -72,8 +70,6 @@ class ProcessStateWatcherDialog(
parent,
StringFormatter.toString(e),
errorMessage,
MessageType.ERROR,
ButtonsType.CLOSE,
null,
null
)
@ -85,7 +81,7 @@ class ProcessStateWatcherDialog(
}
@JvmRecord
internal data class State(val msg: String, val progress: Float) {
data class State(val msg: String, val progress: Float) {
constructor(source: ProcessState) : this(source.currentStep, source.progress)
}

View File

@ -1,7 +1,6 @@
package io.gitlab.jfronny.inceptum.gtk.window.settings.instance
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend
import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab
import io.gitlab.jfronny.inceptum.gtk.schedule
import io.gitlab.jfronny.inceptum.gtk.util.I18n
@ -10,6 +9,7 @@ import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporter
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
import org.gnome.gio.Cancellable
import org.gnome.gtk.*
import java.nio.file.Path
@ -25,37 +25,20 @@ class ExportTab(private val instance: Instance, window: InstanceSettingsWindow?)
for (exporter in Exporters.EXPORTERS) {
row("instance.settings.export.title", "instance.settings.export.subtitle", exporter.name, exporter.fileExtension) {
setButton("instance.settings.export") {
val dialog = FileChooserNative(
I18n["instance.settings.export.dialog.title", exporter.name],
window,
FileChooserAction.SAVE,
"_" + I18n["save"],
"_" + I18n["cancel"]
)
val filter = FileFilter()
filter.name = exporter.name + " Pack"
filter.addPattern("*." + exporter.fileExtension)
dialog.addFilter(filter)
dialog.currentName = exporter.getDefaultFileName(instance)
dialog.onResponse { responseId: Int ->
if (responseId == ResponseType.ACCEPT.value) {
val file = dialog.file!!.path
if (file == null) {
GtkEnvBackend.simpleDialog(
window,
"The path returned by the file dialog is null",
"Could not export",
MessageType.ERROR,
ButtonsType.CLOSE,
null,
null
)
return@onResponse
}
export(exporter, Path.of(file))
run {
val dialog = FileDialog()
dialog.title = I18n["instance.settings.export.dialog.title", exporter.name]
val filters = AnyFilter()
val filter = FileFilter()
filter.name = exporter.name + " Pack"
filter.addPattern("*." + exporter.fileExtension)
filters.append(filter)
dialog.filters = filters
dialog.initialName = exporter.getDefaultFileName(instance)
dialog.save(window, Cancellable()) { _, res, _ ->
export(exporter, Path.of(dialog.saveFinish(res)?.path ?: return@save))
}
}
dialog.show()
}
}
}
@ -94,7 +77,7 @@ class ExportTab(private val instance: Instance, window: InstanceSettingsWindow?)
else -> {}
}
}
success.show()
success.visible = true
}
}
}

View File

@ -12,6 +12,7 @@ import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.Memory
import io.gitlab.jfronny.inceptum.gtk.util.markup
import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray
import io.gitlab.jfronny.inceptum.gtk.window.create.NewInstanceWindow
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi
import io.gitlab.jfronny.inceptum.launcher.api.McApi
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta
@ -65,8 +66,7 @@ class GeneralTab(instance: Instance, window: InstanceSettingsWindow) : SettingsT
.filter { InceptumConfig.snapshots || it.type == "release" }
.map { it.id }
.toTypedArray()
var def = 0
for (i in versions.indices) if (versions[i] == instance.gameVersion) def = i
val def = versions.withIndex().firstOrNull { it.value == instance.gameVersion }?.index ?: 0
row("instance.settings.general.game.version", "instance.settings.general.game.version.subtitle") {
setDropdown(versions, def) { i ->
@ -111,7 +111,7 @@ class GeneralTab(instance: Instance, window: InstanceSettingsWindow) : SettingsT
.map { it.loader.version }
.orElse(null)
fabricVersions = ver.map { Arrays.stream(it) }
.map{ it.map { l -> l.loader.version }.toTypedArray() }
.map { it.map { l -> l.loader.version }.toTypedArray() }
.orElse(null)
if (fabricVersions == null || fabricVersions!!.isEmpty()) {
fabricEnabled.active = false

View File

@ -24,7 +24,7 @@ class AccountsTab(window: Window?) : SettingsTab(window) {
clear()
build()
GtkMenubar.generateAccountsMenu(window!!.application!!)
}.show()
}.visible = true
}
}

View File

@ -4,6 +4,7 @@ import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
import io.gitlab.jfronny.inceptum.common.GsonPreset;
import java.util.Date;
import java.util.Objects;
@GSerializable(configure = GsonPreset.Api.class)
public class VersionsListInfo {
@ -24,4 +25,9 @@ public class VersionsListInfo {
this.sha1 = vli.sha1;
this.complianceLevel = vli.complianceLevel;
}
@Override
public boolean equals(Object obj) {
return obj instanceof VersionsListInfo li && Objects.equals(id, li.id);
}
}