Skip to content

Commit

Permalink
feat(admin): add the option to enable or disable GUI when installing …
Browse files Browse the repository at this point in the history
…the script to an instance using the installer (#24)

* feat(admin): add the option to enable or disable GUI when installing the script to an instance using the installer
  • Loading branch information
EchoEllet committed Jul 8, 2024
1 parent a78277c commit 7e255ed
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 37 deletions.
18 changes: 18 additions & 0 deletions admin/src/main/kotlin/gui/tabs/SyncScriptInstallerTab.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gui.tabs

import constants.ProjectInfoConstants
import constants.SharedConstants
import gui.Tab
import gui.components.instanceDirectoryInputField
import gui.components.labeledInputField
Expand All @@ -24,6 +25,7 @@ import services.syncScriptInstaller.SyncScriptInstallationResult
import services.syncScriptInstaller.SyncScriptInstallerInstance
import utils.buildHtml
import javax.swing.JButton
import javax.swing.JCheckBox
import javax.swing.JComboBox
import javax.swing.JComponent
import javax.swing.JFileChooser
Expand All @@ -36,6 +38,7 @@ class SyncScriptInstallerTab : Tab() {

private val launcherInstanceDirectoryComboBox: JComboBox<ComboItem<Instance>> = JComboBox()
private val launcherComboBox: JComboBox<MinecraftLauncher> = JComboBox()
private val shouldEnableGuiCheckBox: JCheckBox = JCheckBox()

init {
setupTabContent()
Expand Down Expand Up @@ -72,6 +75,20 @@ class SyncScriptInstallerTab : Tab() {
launcherComboBox = launcherComboBox,
preferredLabelWidth = PREFERRED_LABEL_WIDTH,
parentComponent = this@SyncScriptInstallerTab,
),
labeledInputField(
labelText = "Enable GUI",
tooltipText =
buildHtml {
text("Check to enable the graphical user interface (GUI) version of the script.")
newLine()
text("The GUI mode will be automatically disabled if the system doesn't support it.")
}.buildAsText(),
inputComponent =
shouldEnableGuiCheckBox.apply {
isSelected = SharedConstants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT
},
preferredLabelWidth = PREFERRED_LABEL_WIDTH,
).padding(bottom = 24),
row(
JButton("Install").onClick {
Expand Down Expand Up @@ -121,6 +138,7 @@ class SyncScriptInstallerTab : Tab() {
(launcherInstanceDirectoryComboBox.selectedItem as? String).orEmpty(),
launcher = launcherComboBox.getSelectedItemOrThrow(),
confirmReplaceExistingPreLaunchCommand = confirmReplaceExistingPreLaunchCommand,
shouldEnableGui = shouldEnableGuiCheckBox.isSelected,
)
when (result) {
is SyncScriptInstallationResult.Failure -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ interface SyncScriptInstaller {
launcher: MinecraftLauncher,
launcherInstanceDirectoryPathString: String,
confirmReplaceExistingPreLaunchCommand: Boolean,
shouldEnableGui: Boolean,
): SyncScriptInstallationResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package services.syncScriptInstaller

import constants.DotMinecraftFileNames
import constants.ProjectInfoConstants
import constants.SharedConstants
import launchers.LauncherDataSource
import launchers.LauncherDataSourceFactory
import launchers.MinecraftLauncher
Expand All @@ -17,6 +18,7 @@ class SyncScriptInstallerImpl : SyncScriptInstaller {
launcher: MinecraftLauncher,
launcherInstanceDirectoryPathString: String,
confirmReplaceExistingPreLaunchCommand: Boolean,
shouldEnableGui: Boolean,
): SyncScriptInstallationResult {
return try {
if (launcherInstanceDirectoryPathString.isBlank()) {
Expand Down Expand Up @@ -99,28 +101,42 @@ class SyncScriptInstallerImpl : SyncScriptInstaller {
}
}

val newCommand =
// Without arguments
val newLaunchCommand =
when (launcher) {
MinecraftLauncher.Official -> throw NotImplementedError()
MinecraftLauncher.MultiMc, MinecraftLauncher.PrismLauncher, MinecraftLauncher.ATLauncher ->
"\$INST_JAVA -jar \$INST_MC_DIR/$newSyncScriptJarFileName"

MinecraftLauncher.ModrinthApp -> TODO()
MinecraftLauncher.ModrinthApp -> TODO() // TODO: https://github.com/modrinth/code/pull/1254
MinecraftLauncher.GDLauncher -> TODO()
}

val newCommandToSet = if (installationConfig is SyncScriptInstallationConfig.Install) newCommand else null
// With arguments
val newFullCommandWithArgs =
buildString {
append(newLaunchCommand)
if (!shouldEnableGui) {
append(" ${SharedConstants.DISABLE_GUI_ARG_NAME}")
}
}

val newCommandToSet = if (installationConfig is SyncScriptInstallationConfig.Install) newFullCommandWithArgs else null

val currentCommand =
launcherDataSource
.getPreLaunchCommand(launcherInstanceDirectoryPath = launcherInstanceDirectoryPath)
.getOrThrow()

if ((currentCommand != null && currentCommand != newCommand) && !confirmReplaceExistingPreLaunchCommand) {
return SyncScriptInstallationResult.RequiresUserConfirmationToReplacePreLaunchCommand(
existingCommand = currentCommand,
newCommand = newCommandToSet.toString(),
)
if (!confirmReplaceExistingPreLaunchCommand) {
// If there is already a command exists, confirm if the user wants to replace the current
// unless if the command is used to launch the script that the user trying to install
if ((currentCommand != null && !currentCommand.startsWith(newLaunchCommand))) {
return SyncScriptInstallationResult.RequiresUserConfirmationToReplacePreLaunchCommand(
existingCommand = currentCommand,
newCommand = newCommandToSet.toString(),
)
}
}

launcherDataSource
Expand Down
19 changes: 19 additions & 0 deletions common/src/main/kotlin/constants/SharedConstants.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package constants

/**
* General shared constants
* */
object SharedConstants {
/**
* Enable GUI mode when available (error messages, download loading indicator, etc...) for the sync script.
* */
const val GUI_ENABLED_WHEN_AVAILABLE_DEFAULT = true

/**
* The argument name that will be used in the launch args in order to not use the GUI
* will use `nogui` because it's the same as
* [Minecraft Java Server](https://minecraft.fandom.com/wiki/Tutorials/Setting_up_a_server)
* TODO: Might rename it to `--disable-gui`, also add a shorter version and better way to parse it
* */
const val DISABLE_GUI_ARG_NAME = "nogui"
}
7 changes: 4 additions & 3 deletions sync-script/src/main/kotlin/config/models/ScriptConfig.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config.models

import constants.Constants
import constants.SharedConstants
import constants.SyncScriptDotMinecraftFiles
import gui.theme.Theme
import gui.theme.ThemeMode
Expand All @@ -22,14 +23,14 @@ data class ScriptConfig(
val syncInfoUrl: String,
/**
* Override the value set using launch arguments, by default,
* the script will use [Constants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT] if GUI mode supported.
* the script will use [SharedConstants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT] if GUI mode supported.
*
* If not, then will automatically disable the GUI mode.
*
* If you want to explicit disable the GUI mode, use [Constants.DISABLE_GUI_ARG_NAME] instead of overriding it
* If you want to explicit disable the GUI mode, use [SharedConstants.DISABLE_GUI_ARG_NAME] instead of overriding it
* in here because if an error occurred while loading [ScriptConfig] from the file,
* we will fall back to use the one from application arguments if set,
* if not then will use [Constants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT]
* if not then will use [SharedConstants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT]
* if GUI is supported, otherwise will disable the GUI.
*
* This will **only take effect** after loading the [ScriptConfig].
Expand Down
13 changes: 0 additions & 13 deletions sync-script/src/main/kotlin/constants/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,6 @@ package constants
import config.models.ScriptConfig

object Constants {
/**
* Should we by default use GUI for the (error messages, download loading indicator, etc...) as default value?
* */
const val GUI_ENABLED_WHEN_AVAILABLE_DEFAULT = true

/**
* The argument name that will be used in the launch args in order to not use the gui
* will use `nogui` because it's the same as
* [Minecraft Java Server](https://minecraft.fandom.com/wiki/Tutorials/Setting_up_a_server)
* TODO: Might rename it to `--disable-gui`, also add a shorter version and better way to parse it
* */
const val DISABLE_GUI_ARG_NAME = "nogui"

/**
* Should we tell the launcher to launch the game anyway when error during the sync process?
* read [ScriptConfig.launchOnError] for more info
Expand Down
8 changes: 4 additions & 4 deletions sync-script/src/main/kotlin/gui/GuiState.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package gui

import config.models.ScriptConfig
import constants.Constants
import constants.SharedConstants
import passedArgs
import java.awt.GraphicsEnvironment

object GuiState {
/**
* By default, will load it from the program arguments by [Constants.DISABLE_GUI_ARG_NAME]
* By default, will load it from the program arguments by [SharedConstants.DISABLE_GUI_ARG_NAME]
* the value can be overridden using [ScriptConfig.guiEnabled] when the [ScriptConfig] is initialized
* */
var isGuiEnabled: Boolean = Constants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT
var isGuiEnabled: Boolean = SharedConstants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT
private set

/**
Expand All @@ -25,7 +25,7 @@ object GuiState {
return
}
// Check if the user overrides the default value in the launch arguments
val isDisableGuiArgumentPassed = passedArgs.isNotEmpty() && passedArgs[0] == Constants.DISABLE_GUI_ARG_NAME
val isDisableGuiArgumentPassed = passedArgs.isNotEmpty() && passedArgs[0] == SharedConstants.DISABLE_GUI_ARG_NAME
if (isDisableGuiArgumentPassed) {
isGuiEnabled = false
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gui.dialogs

import config.models.ScriptConfig
import constants.Constants
import constants.SharedConstants
import gui.GuiState
import gui.components.labeledInputField
import gui.theme.Theme
Expand Down Expand Up @@ -86,14 +86,14 @@ class QuickPreferencesDialog : JDialog() {
text("Check to enable the graphical user interface (GUI) version of the script.")
newLines(2)
text("Consider using ")
boldText(Constants.DISABLE_GUI_ARG_NAME)
boldText(SharedConstants.DISABLE_GUI_ARG_NAME)
text(" as a launch argument to disable the GUI. This ensures smooth execution, ")
text("avoiding potential unexpected behavior during configuration file loading.")
newLines(2)
text("Because this property will be stored in the config file, if an error happened while loading the ")
text("config file and your system support GUI,")
newLine()
if (Constants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT) {
if (SharedConstants.GUI_ENABLED_WHEN_AVAILABLE_DEFAULT) {
text("will use GUI mode even if you specified to not use it in the config file.")
} else {
text("will not GUI mode even if you specified to use it in the config file.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,24 @@ class SystemScriptPreferencesDataSource : ScriptPreferencesDataSource {

private val preferences = Preferences.userRoot()

override suspend fun doesUserTrustSource(sourceUrl: String): Result<Boolean> {
return try {
override suspend fun doesUserTrustSource(sourceUrl: String): Result<Boolean> =
try {
val result = preferences.getBoolean(getDoesUserTrustSourceOfUrl(sourceUrl), false)
Result.success(result)
} catch (e: Exception) {
e.printStackTrace()
Result.failure(e)
}
}

override suspend fun updateDoesUserTrustSource(
sourceUrl: String,
newValue: Boolean,
): Result<Unit> {
return try {
): Result<Unit> =
try {
val result = preferences.putBoolean(getDoesUserTrustSourceOfUrl(sourceUrl), newValue)
Result.success(result)
} catch (e: Exception) {
e.printStackTrace()
Result.failure(e)
}
}
}

0 comments on commit 7e255ed

Please sign in to comment.