mirror of
https://github.com/gotson/komga.git
synced 2026-05-09 05:10:19 +02:00
feat(komga-tray): display dialog with error detail on application startup failure
Closes: #1336
This commit is contained in:
parent
7a8d50ce7d
commit
0fdcb2a754
4 changed files with 125 additions and 4 deletions
|
|
@ -32,7 +32,7 @@ tasks {
|
|||
dependencies {
|
||||
implementation(project(":komga"))
|
||||
|
||||
implementation(compose.desktop.common)
|
||||
implementation(compose.desktop.currentOs)
|
||||
|
||||
linuxAmd64(compose.desktop.linux_x64)
|
||||
macAmd64(compose.desktop.macos_x64)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package org.gotson.komga
|
||||
|
||||
import org.gotson.komga.application.gui.showErrorDialog
|
||||
import org.gotson.komga.infrastructure.util.checkTempDirectory
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder
|
||||
import org.springframework.boot.web.server.PortInUseException
|
||||
import org.springframework.context.ApplicationContextException
|
||||
import org.springframework.scheduling.annotation.EnableAsync
|
||||
|
||||
@EnableAsync
|
||||
|
|
@ -14,8 +17,17 @@ fun main(args: Array<String>) {
|
|||
System.setProperty("org.jooq.no-logo", "true")
|
||||
System.setProperty("org.jooq.no-tips", "true")
|
||||
|
||||
SpringApplicationBuilder(DesktopApplication::class.java).apply {
|
||||
headless(false)
|
||||
run(*args)
|
||||
try {
|
||||
SpringApplicationBuilder(DesktopApplication::class.java).apply {
|
||||
headless(false)
|
||||
run(*args)
|
||||
}
|
||||
} catch (e: ApplicationContextException) {
|
||||
val (message, stackTrace) = when (e.cause) {
|
||||
is PortInUseException -> RB.getString("error_message.port_in_use", (e.cause as PortInUseException).port) to null
|
||||
else -> RB.getString("error_message.unexpected") to e.stackTraceToString()
|
||||
}
|
||||
|
||||
showErrorDialog(message, stackTrace)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,104 @@
|
|||
package org.gotson.komga.application.gui
|
||||
|
||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.loadSvgPainter
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.WindowPlacement
|
||||
import androidx.compose.ui.window.WindowPosition
|
||||
import androidx.compose.ui.window.WindowState
|
||||
import androidx.compose.ui.window.application
|
||||
import org.gotson.komga.RB
|
||||
import org.springframework.core.io.ClassPathResource
|
||||
|
||||
@Preview
|
||||
fun showErrorDialog(text: String, stackTrace: String? = null) {
|
||||
application {
|
||||
Window(
|
||||
title = RB.getString("dialog_error.title"),
|
||||
onCloseRequest = ::exitApplication,
|
||||
visible = true,
|
||||
resizable = false,
|
||||
state = WindowState(
|
||||
placement = WindowPlacement.Floating,
|
||||
position = WindowPosition(alignment = Alignment.Center),
|
||||
size = DpSize(
|
||||
if (stackTrace != null) 800.dp else Dp.Unspecified,
|
||||
Dp.Unspecified,
|
||||
),
|
||||
),
|
||||
icon = loadSvgPainter(ClassPathResource("icons/komga-color.svg").inputStream, LocalDensity.current),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(bottom = 16.dp),
|
||||
) {
|
||||
Image(
|
||||
painter = loadSvgPainter(ClassPathResource("icons/komga-color.svg").inputStream, LocalDensity.current),
|
||||
contentDescription = "Komga logo",
|
||||
modifier = Modifier
|
||||
.size(96.dp)
|
||||
.align(Alignment.Top),
|
||||
)
|
||||
Text(
|
||||
text,
|
||||
modifier = Modifier.padding(start = 32.dp),
|
||||
)
|
||||
}
|
||||
if (stackTrace != null)
|
||||
TextField(
|
||||
value = stackTrace,
|
||||
onValueChange = {},
|
||||
singleLine = false,
|
||||
maxLines = 15,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
Row(
|
||||
horizontalArrangement = if (stackTrace != null) Arrangement.SpaceBetween else Arrangement.End,
|
||||
modifier = if (stackTrace != null)
|
||||
Modifier.align(Alignment.End).fillMaxWidth()
|
||||
else
|
||||
Modifier.align(Alignment.End),
|
||||
) {
|
||||
if (stackTrace != null) {
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
TextButton(
|
||||
onClick = {
|
||||
clipboardManager.setText(AnnotatedString(stackTrace))
|
||||
},
|
||||
) {
|
||||
Text(RB.getString("dialog_error.copy_clipboard"))
|
||||
}
|
||||
}
|
||||
Button(
|
||||
onClick = { exitApplication() },
|
||||
) {
|
||||
Text(RB.getString("dialog_error.close"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
dialog_error.close=Close
|
||||
dialog_error.copy_clipboard=Copy to clipboard
|
||||
dialog_error.title=Komga failed to start
|
||||
error_message.port_in_use=Port {} is already in use.\nKomga is probably already running.\nCheck the tray icon or menu bar for the Komga icon.
|
||||
error_message.unexpected=An unexpected error occurred.
|
||||
menu.open_komga=Open Komga
|
||||
menu.quit=Quit Komga
|
||||
menu.show_conf_dir=Open configuration directory
|
||||
|
|
|
|||
Loading…
Reference in a new issue