Random small improvements
This commit is contained in:
parent
d738b133d0
commit
17ba07deef
5 changed files with 164 additions and 19 deletions
94
.gitea/issue_template/bug_report.yaml
Normal file
94
.gitea/issue_template/bug_report.yaml
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
name: Bug Report
|
||||||
|
about: Something not working right? Let us know so we can fix it!
|
||||||
|
title: "[Bug] "
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to report this! The more detail you can give, the faster we can track it down.
|
||||||
|
Don't worry about being too technical — just describe what happened in your own words.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: Tell us what went wrong. What did you see or experience?
|
||||||
|
placeholder: "e.g. The app froze after I clicked Save, and my backup never ran."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: What did you expect to happen?
|
||||||
|
placeholder: "e.g. I expected my settings to save and the backup to start at the scheduled time."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: steps
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: |
|
||||||
|
Walk us through exactly what you did before the problem showed up.
|
||||||
|
Try to be specific — even small details can help! Number each step.
|
||||||
|
placeholder: |
|
||||||
|
1. Opened WoW Backup
|
||||||
|
2. Went to Settings
|
||||||
|
3. Changed the backup time to 5:00 PM
|
||||||
|
4. Clicked Save
|
||||||
|
5. The app froze and stopped responding
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: frequency
|
||||||
|
attributes:
|
||||||
|
label: How often does this happen?
|
||||||
|
options:
|
||||||
|
- Every time
|
||||||
|
- Sometimes
|
||||||
|
- It only happened once
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: Operating system
|
||||||
|
options:
|
||||||
|
- macOS
|
||||||
|
- Windows
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: app-version
|
||||||
|
attributes:
|
||||||
|
label: App version
|
||||||
|
description: You can find this in the app's title bar or About screen.
|
||||||
|
placeholder: "e.g. 1.0.0"
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Log file
|
||||||
|
description: |
|
||||||
|
Logs help us understand what went wrong behind the scenes. Here's how to find them:
|
||||||
|
|
||||||
|
**macOS:** Open Finder, press **Cmd+Shift+G**, and paste: `~/Library/Application Support/WoWBackup/logs`
|
||||||
|
**Windows:** Press **Win+R**, and paste: `%APPDATA%\WoWBackup\logs`
|
||||||
|
|
||||||
|
You can also open this folder from the app: go to **Settings** and click the **Open Logs** button at the bottom.
|
||||||
|
|
||||||
|
Attach the most recent `wowbackup.log` file by dragging it into this text box.
|
||||||
|
placeholder: Drag your log file here, or paste any relevant log lines.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: extra
|
||||||
|
attributes:
|
||||||
|
label: Anything else?
|
||||||
|
description: Screenshots, screen recordings, or any other context that might help.
|
||||||
|
|
@ -34,6 +34,33 @@ kotlin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val appVersion = "0.1.0"
|
||||||
|
|
||||||
|
val generatedSrcDir = layout.buildDirectory.dir("generated/src/jvmMain/kotlin")
|
||||||
|
|
||||||
|
val generateBuildConfig by tasks.registering {
|
||||||
|
val outputDir = generatedSrcDir
|
||||||
|
val version = appVersion
|
||||||
|
outputs.dir(outputDir)
|
||||||
|
doLast {
|
||||||
|
val dir = outputDir.get().asFile.resolve("com/rukira/wowbackup")
|
||||||
|
dir.mkdirs()
|
||||||
|
dir.resolve("BuildConfig.kt").writeText(
|
||||||
|
"""
|
||||||
|
|package com.rukira.wowbackup
|
||||||
|
|
|
||||||
|
|object BuildConfig {
|
||||||
|
| const val VERSION = "$version"
|
||||||
|
|}
|
||||||
|
""".trimMargin()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin.sourceSets.named("jvmMain") {
|
||||||
|
kotlin.srcDir(generateBuildConfig)
|
||||||
|
}
|
||||||
|
|
||||||
compose.desktop {
|
compose.desktop {
|
||||||
application {
|
application {
|
||||||
mainClass = "com.rukira.wowbackup.MainKt"
|
mainClass = "com.rukira.wowbackup.MainKt"
|
||||||
|
|
@ -43,7 +70,7 @@ compose.desktop {
|
||||||
nativeDistributions {
|
nativeDistributions {
|
||||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||||
packageName = "com.rukira.wowbackup"
|
packageName = "com.rukira.wowbackup"
|
||||||
packageVersion = "1.0.0"
|
packageVersion = appVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import androidx.compose.ui.window.Window
|
||||||
import androidx.compose.ui.window.WindowPosition
|
import androidx.compose.ui.window.WindowPosition
|
||||||
import androidx.compose.ui.window.WindowState
|
import androidx.compose.ui.window.WindowState
|
||||||
import androidx.compose.ui.window.application
|
import androidx.compose.ui.window.application
|
||||||
import androidx.compose.ui.window.TrayState
|
|
||||||
import androidx.compose.ui.window.rememberTrayState
|
import androidx.compose.ui.window.rememberTrayState
|
||||||
import com.rukira.wowbackup.backup.BackupNotifier
|
import com.rukira.wowbackup.backup.BackupNotifier
|
||||||
import com.rukira.wowbackup.backup.BackupScheduler
|
import com.rukira.wowbackup.backup.BackupScheduler
|
||||||
|
|
@ -43,14 +42,13 @@ fun main() {
|
||||||
logger.info { "Auto-detected WoW at: $detectedWoW" }
|
logger.info { "Auto-detected WoW at: $detectedWoW" }
|
||||||
}
|
}
|
||||||
|
|
||||||
val startScreen = if (ConfigManager.isConfigured) Screen.STATUS else Screen.CONFIG
|
val isConfigured = ConfigManager.isConfigured
|
||||||
|
|
||||||
// Start backup scheduler
|
// Start backup scheduler
|
||||||
BackupScheduler.start()
|
BackupScheduler.start()
|
||||||
|
|
||||||
application {
|
application {
|
||||||
var isWindowVisible by remember { mutableStateOf(true) }
|
var currentScreen by remember { mutableStateOf(if (isConfigured) null else Screen.CONFIG) }
|
||||||
var currentScreen by remember { mutableStateOf(startScreen) }
|
|
||||||
val trayState = rememberTrayState()
|
val trayState = rememberTrayState()
|
||||||
|
|
||||||
// Wire up notifications
|
// Wire up notifications
|
||||||
|
|
@ -60,16 +58,10 @@ fun main() {
|
||||||
state = trayState,
|
state = trayState,
|
||||||
icon = trayIconPainter(),
|
icon = trayIconPainter(),
|
||||||
tooltip = "WoW Backup",
|
tooltip = "WoW Backup",
|
||||||
onAction = { isWindowVisible = true },
|
onAction = { currentScreen = Screen.STATUS },
|
||||||
menu = {
|
menu = {
|
||||||
Item("Status", onClick = {
|
Item("Status", onClick = { currentScreen = Screen.STATUS })
|
||||||
currentScreen = Screen.STATUS
|
Item("Settings", onClick = { currentScreen = Screen.CONFIG })
|
||||||
isWindowVisible = true
|
|
||||||
})
|
|
||||||
Item("Settings", onClick = {
|
|
||||||
currentScreen = Screen.CONFIG
|
|
||||||
isWindowVisible = true
|
|
||||||
})
|
|
||||||
Separator()
|
Separator()
|
||||||
Item("Quit", onClick = {
|
Item("Quit", onClick = {
|
||||||
BackupScheduler.stop()
|
BackupScheduler.stop()
|
||||||
|
|
@ -78,8 +70,9 @@ fun main() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isWindowVisible) {
|
val activeScreen = currentScreen
|
||||||
val windowState = remember(isWindowVisible) {
|
if (activeScreen != null) {
|
||||||
|
val windowState = remember(activeScreen) {
|
||||||
WindowState(
|
WindowState(
|
||||||
size = DpSize(480.dp, 620.dp),
|
size = DpSize(480.dp, 620.dp),
|
||||||
position = trayAlignedPosition(),
|
position = trayAlignedPosition(),
|
||||||
|
|
@ -87,13 +80,13 @@ fun main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Window(
|
Window(
|
||||||
onCloseRequest = { isWindowVisible = false },
|
onCloseRequest = { currentScreen = null },
|
||||||
title = "WoW Backup",
|
title = "WoW Backup",
|
||||||
state = windowState,
|
state = windowState,
|
||||||
resizable = true,
|
resizable = true,
|
||||||
) {
|
) {
|
||||||
App(
|
App(
|
||||||
currentScreen = currentScreen,
|
currentScreen = activeScreen,
|
||||||
onNavigate = { currentScreen = it },
|
onNavigate = { currentScreen = it },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,19 @@ import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.ScrollbarStyle
|
||||||
|
import androidx.compose.foundation.VerticalScrollbar
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.rememberScrollbarAdapter
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
|
|
@ -56,11 +61,13 @@ fun ConfigScreen(
|
||||||
val config = uiState.config
|
val config = uiState.config
|
||||||
val errors = uiState.errors
|
val errors = uiState.errors
|
||||||
var showForceBackupDialog by remember { mutableStateOf(false) }
|
var showForceBackupDialog by remember { mutableStateOf(false) }
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(scrollState)
|
||||||
.padding(24.dp),
|
.padding(24.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
) {
|
) {
|
||||||
|
|
@ -296,6 +303,20 @@ fun ConfigScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VerticalScrollbar(
|
||||||
|
modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
|
||||||
|
adapter = rememberScrollbarAdapter(scrollState),
|
||||||
|
style = ScrollbarStyle(
|
||||||
|
minimalHeight = 48.dp,
|
||||||
|
thickness = 8.dp,
|
||||||
|
shape = RoundedCornerShape(4.dp),
|
||||||
|
hoverDurationMillis = 300,
|
||||||
|
unhoverColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.3f),
|
||||||
|
hoverColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Force backup confirmation dialog
|
// Force backup confirmation dialog
|
||||||
if (showForceBackupDialog) {
|
if (showForceBackupDialog) {
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.rukira.wowbackup.BuildConfig
|
||||||
import com.rukira.wowbackup.backup.BackupScheduler
|
import com.rukira.wowbackup.backup.BackupScheduler
|
||||||
import com.rukira.wowbackup.platform.DesktopActions
|
import com.rukira.wowbackup.platform.DesktopActions
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -211,5 +212,14 @@ fun StatusScreen(
|
||||||
Text("Restore (Coming Soon)")
|
Text("Restore (Coming Soon)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
Text(
|
||||||
|
"WoW Backup v${BuildConfig.VERSION}",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
textAlign = androidx.compose.ui.text.style.TextAlign.Center,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue