Add option to automatically close after a user-supplied amount of time (#42)

* Add option to automatically close after a user-specific amount of time

Add the -t/--timeout command line option to specific a number of seconds to
wait before automatically closing if there is no update or user-interactivity
required.

* Also use timeout setting when prompting about optional mods after/during an update

Additionally, clears the TODO comment.

* Change default timeout to 10 seconds
This commit is contained in:
Eric Richter 2023-01-16 20:30:05 -06:00 committed by GitHub
parent 84bbbe0770
commit 4e415c1e1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 8 deletions

View File

@ -103,10 +103,13 @@ class Main(args: Array<String>) {
val manifestFile = ui.wrap("Invalid manifest file path") { val manifestFile = ui.wrap("Invalid manifest file path") {
packFolder / (cmd.getOptionValue("meta-file") ?: "packwiz.json") packFolder / (cmd.getOptionValue("meta-file") ?: "packwiz.json")
} }
val timeout = ui.wrap("Invalid timeout value") {
cmd.getOptionValue("timeout")?.toLong() ?: 10
}
// Start update process! // Start update process!
try { try {
UpdateManager(UpdateManager.Options(packFile, manifestFile, packFolder, multimcFolder, side), ui) UpdateManager(UpdateManager.Options(packFile, manifestFile, packFolder, multimcFolder, side, timeout), ui)
} catch (e: Exception) { } catch (e: Exception) {
ui.showErrorAndExit("Update process failed", e) ui.showErrorAndExit("Update process failed", e)
} }
@ -123,6 +126,7 @@ class Main(args: Array<String>) {
options.addOption(null, "pack-folder", true, "Folder to install the pack to (defaults to the JAR directory)") options.addOption(null, "pack-folder", true, "Folder to install the pack to (defaults to the JAR directory)")
options.addOption(null, "multimc-folder", true, "The MultiMC pack folder (defaults to the parent of the pack directory)") options.addOption(null, "multimc-folder", true, "The MultiMC pack folder (defaults to the parent of the pack directory)")
options.addOption(null, "meta-file", true, "JSON file to store pack metadata, relative to the pack folder (defaults to packwiz.json)") options.addOption(null, "meta-file", true, "JSON file to store pack metadata, relative to the pack folder (defaults to packwiz.json)")
options.addOption("t", "timeout", true, "Seconds to wait before automatically launching when asking about optional mods (defaults to 10)")
} }
// TODO: link these somehow so they're only defined once? // TODO: link these somehow so they're only defined once?

View File

@ -48,7 +48,8 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
val manifestFile: PackwizFilePath, val manifestFile: PackwizFilePath,
val packFolder: PackwizFilePath, val packFolder: PackwizFilePath,
val multimcFolder: PackwizFilePath, val multimcFolder: PackwizFilePath,
val side: Side val side: Side,
val timeout: Long,
) )
// TODO: make this return a value based on results? // TODO: make this return a value based on results?
@ -157,7 +158,7 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
// todo: --force? // todo: --force?
ui.submitProgress(InstallProgress("Modpack is already up to date!", 1, 1)) ui.submitProgress(InstallProgress("Modpack is already up to date!", 1, 1))
if (manifest.cachedFiles.any { it.value.isOptional }) { if (manifest.cachedFiles.any { it.value.isOptional }) {
ui.awaitOptionalButton(false) ui.awaitOptionalButton(false, opts.timeout)
} }
if (!ui.optionsButtonPressed) { if (!ui.optionsButtonPressed) {
return return
@ -206,7 +207,7 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
if (manifest.indexFileHash == indexHash && invalidatedFiles.isEmpty()) { if (manifest.indexFileHash == indexHash && invalidatedFiles.isEmpty()) {
ui.submitProgress(InstallProgress("Modpack files are already up to date!", 1, 1)) ui.submitProgress(InstallProgress("Modpack files are already up to date!", 1, 1))
if (manifest.cachedFiles.any { it.value.isOptional }) { if (manifest.cachedFiles.any { it.value.isOptional }) {
ui.awaitOptionalButton(false) ui.awaitOptionalButton(false, opts.timeout)
} }
if (!ui.optionsButtonPressed) { if (!ui.optionsButtonPressed) {
return return
@ -338,7 +339,7 @@ class UpdateManager internal constructor(private val opts: Options, val ui: IUse
if (!ui.optionsButtonPressed) { if (!ui.optionsButtonPressed) {
// TODO: this is so ugly // TODO: this is so ugly
ui.submitProgress(InstallProgress("Reconfigure optional mods?", 0,1)) ui.submitProgress(InstallProgress("Reconfigure optional mods?", 0,1))
ui.awaitOptionalButton(true) ui.awaitOptionalButton(true, opts.timeout)
if (ui.cancelButtonPressed) { if (ui.cancelButtonPressed) {
showCancellationDialog() showCancellationDialog()
return return

View File

@ -25,7 +25,7 @@ interface IUserInterface {
fun showUpdateConfirmationDialog(oldVersions: List<Pair<String, String?>>, newVersions: List<Pair<String, String?>>): UpdateConfirmationResult = UpdateConfirmationResult.CANCELLED fun showUpdateConfirmationDialog(oldVersions: List<Pair<String, String?>>, newVersions: List<Pair<String, String?>>): UpdateConfirmationResult = UpdateConfirmationResult.CANCELLED
fun awaitOptionalButton(showCancel: Boolean) fun awaitOptionalButton(showCancel: Boolean, timeout: Long)
enum class ExceptionListResult { enum class ExceptionListResult {
CONTINUE, CANCEL, IGNORE CONTINUE, CANCEL, IGNORE

View File

@ -63,7 +63,7 @@ class CLIHandler : IUserInterface {
return ExceptionListResult.CANCEL return ExceptionListResult.CANCEL
} }
override fun awaitOptionalButton(showCancel: Boolean) { override fun awaitOptionalButton(showCancel: Boolean, timeout: Long) {
// Do nothing // Do nothing
} }
} }

View File

@ -7,11 +7,13 @@ import link.infra.packwiz.installer.ui.data.IOptionDetails
import link.infra.packwiz.installer.ui.data.InstallProgress import link.infra.packwiz.installer.ui.data.InstallProgress
import link.infra.packwiz.installer.util.Log import link.infra.packwiz.installer.util.Log
import java.awt.EventQueue import java.awt.EventQueue
import java.util.Timer
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import javax.swing.JDialog import javax.swing.JDialog
import javax.swing.JOptionPane import javax.swing.JOptionPane
import javax.swing.UIManager import javax.swing.UIManager
import kotlin.concurrent.timer
import kotlin.system.exitProcess import kotlin.system.exitProcess
class GUIHandler : IUserInterface { class GUIHandler : IUserInterface {
@ -220,12 +222,28 @@ class GUIHandler : IUserInterface {
return future.get() return future.get()
} }
override fun awaitOptionalButton(showCancel: Boolean) { override fun awaitOptionalButton(showCancel: Boolean, timeout: Long) {
EventQueue.invokeAndWait { EventQueue.invokeAndWait {
frmPackwizlauncher.showOk(!showCancel) frmPackwizlauncher.showOk(!showCancel)
} }
visibleCountdownLatch.await() visibleCountdownLatch.await()
var closeTimer: Timer? = null
if (timeout >= 0) {
var count = 0
closeTimer = timer("timeout", true, 0, 1000) {
if (count >= timeout) {
optionalSelectedLatch.countDown()
cancel()
} else {
frmPackwizlauncher.timeoutOk(timeout - count)
count += 1
}
};
}
optionalSelectedLatch.await() optionalSelectedLatch.await()
closeTimer?.cancel()
EventQueue.invokeLater { EventQueue.invokeLater {
frmPackwizlauncher.hideOk() frmPackwizlauncher.hideOk()
} }

View File

@ -121,4 +121,8 @@ class InstallWindow(private val handler: GUIHandler) : JFrame() {
} }
buttonsPanel.revalidate() buttonsPanel.revalidate()
} }
fun timeoutOk(remaining: Long) {
btnOk.text = "Continue ($remaining)"
}
} }