added troubleshooting
This commit is contained in:
@@ -3,4 +3,4 @@
|
||||
Name = "TurtleSilicon"
|
||||
ID = "com.tairasu.turtlesilicon"
|
||||
Version = "1.2.2"
|
||||
Build = 58
|
||||
Build = 65
|
||||
|
1
go.mod
1
go.mod
@@ -42,4 +42,5 @@ require (
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.1 // indirect
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@@ -47,6 +47,7 @@ github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8
|
||||
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 h1:wMeVzrPO3mfHIWLZtDcSaGAe2I4PW9B/P5nMkRSwCAc=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -86,5 +87,8 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
|
@@ -142,6 +142,11 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
|
||||
showOptionsPopup()
|
||||
})
|
||||
|
||||
// Troubleshooting button
|
||||
troubleshootingButton = widget.NewButton("Troubleshooting", func() {
|
||||
showTroubleshootingPopup()
|
||||
})
|
||||
|
||||
// GitHub button
|
||||
githubButton := widget.NewButton("GitHub", func() {
|
||||
githubURL := "https://github.com/tairasu/TurtleSilicon"
|
||||
@@ -168,7 +173,7 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
|
||||
|
||||
leftButtons := container.NewHBox(
|
||||
optionsButton,
|
||||
widget.NewSeparator(), // Visual separator
|
||||
troubleshootingButton,
|
||||
githubButton,
|
||||
)
|
||||
|
||||
|
160
pkg/ui/popup.go
160
pkg/ui/popup.go
@@ -1,9 +1,20 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
"howett.net/plist"
|
||||
|
||||
"turtlesilicon/pkg/paths"
|
||||
"turtlesilicon/pkg/utils"
|
||||
)
|
||||
|
||||
// showOptionsPopup creates and shows an integrated popup window for options
|
||||
@@ -123,3 +134,152 @@ func showRemapWarningPopup() {
|
||||
|
||||
warningPopup.Show()
|
||||
}
|
||||
|
||||
// showTroubleshootingPopup creates and shows a popup window for troubleshooting actions
|
||||
func showTroubleshootingPopup() {
|
||||
if currentWindow == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// --- CrossOver Version Check ---
|
||||
crossoverVersion := getCrossoverVersion(paths.CrossoverPath)
|
||||
var crossoverStatusShort *widget.Label
|
||||
var crossoverStatusDetail *widget.Label
|
||||
if crossoverVersion == "" {
|
||||
crossoverStatusShort = widget.NewLabel("Not found")
|
||||
crossoverStatusDetail = widget.NewLabel("")
|
||||
} else if isCrossoverVersionRecommended(crossoverVersion) {
|
||||
crossoverStatusShort = widget.NewLabelWithStyle("✔ "+crossoverVersion, fyne.TextAlignTrailing, fyne.TextStyle{Bold: true})
|
||||
crossoverStatusDetail = widget.NewLabelWithStyle("✔ Recommended version of CrossOver installed", fyne.TextAlignLeading, fyne.TextStyle{Italic: true})
|
||||
} else {
|
||||
crossoverStatusShort = widget.NewLabelWithStyle("⚠️ "+crossoverVersion, fyne.TextAlignTrailing, fyne.TextStyle{Italic: true})
|
||||
crossoverStatusDetail = widget.NewLabelWithStyle("⚠️ Please update to CrossOver 25.0.1 or later!", fyne.TextAlignLeading, fyne.TextStyle{Italic: true})
|
||||
}
|
||||
crossoverStatusDetail.Wrapping = fyne.TextWrapWord
|
||||
|
||||
// --- Delete WDB Directory ---
|
||||
wdbDeleteButton = widget.NewButton("Delete", func() {
|
||||
wdbPath := filepath.Join(paths.TurtlewowPath, "WDB")
|
||||
if !utils.DirExists(wdbPath) {
|
||||
dialog.ShowInformation("WDB Not Found", "No WDB directory found in your TurtleWoW folder.", currentWindow)
|
||||
return
|
||||
}
|
||||
dialog.NewConfirm("Delete WDB Directory", "Are you sure you want to delete the WDB directory? This will remove all cached data. No important data will be lost.", func(confirm bool) {
|
||||
if confirm {
|
||||
err := os.RemoveAll(wdbPath)
|
||||
if err != nil {
|
||||
dialog.ShowError(fmt.Errorf("Failed to delete WDB: %v", err), currentWindow)
|
||||
} else {
|
||||
dialog.ShowInformation("WDB Deleted", "WDB directory deleted successfully.", currentWindow)
|
||||
}
|
||||
}
|
||||
}, currentWindow).Show()
|
||||
})
|
||||
|
||||
// --- Delete Wine Prefixes ---
|
||||
wineDeleteButton = widget.NewButton("Delete", func() {
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
userWine := filepath.Join(homeDir, ".wine")
|
||||
turtleWine := filepath.Join(paths.TurtlewowPath, ".wine")
|
||||
msg := "Are you sure you want to delete the following Wine prefixes?\n\n- " + userWine + "\n- " + turtleWine + "\n\nThis cannot be undone."
|
||||
dialog.NewConfirm("Delete Wine Prefixes", msg, func(confirm bool) {
|
||||
if confirm {
|
||||
err1 := os.RemoveAll(userWine)
|
||||
err2 := os.RemoveAll(turtleWine)
|
||||
if err1 != nil && !os.IsNotExist(err1) {
|
||||
dialog.ShowError(fmt.Errorf("Failed to delete ~/.wine: %v", err1), currentWindow)
|
||||
return
|
||||
}
|
||||
if err2 != nil && !os.IsNotExist(err2) {
|
||||
dialog.ShowError(fmt.Errorf("Failed to delete TurtleWoW/.wine: %v", err2), currentWindow)
|
||||
return
|
||||
}
|
||||
dialog.ShowInformation("Wine Prefixes Deleted", "Wine prefixes deleted successfully.", currentWindow)
|
||||
}
|
||||
}, currentWindow).Show()
|
||||
})
|
||||
|
||||
troubleshootingTitle := widget.NewLabel("Troubleshooting")
|
||||
troubleshootingTitle.TextStyle = fyne.TextStyle{Bold: true}
|
||||
|
||||
rowCrossover := container.NewBorder(nil, nil, widget.NewLabel("CrossOver version:"), crossoverStatusShort, nil)
|
||||
rowWDB := container.NewBorder(nil, nil, widget.NewLabel("Delete WDB directory (cache):"), wdbDeleteButton, nil)
|
||||
rowWine := container.NewBorder(nil, nil, widget.NewLabel("Delete Wine prefixes (~/.wine & TurtleWoW/.wine):"), wineDeleteButton, nil)
|
||||
appMgmtNote := widget.NewLabel("Please ensure TurtleSilicon is enabled in System Settings > Privacy & Security > App Management.")
|
||||
appMgmtNote.Wrapping = fyne.TextWrapWord
|
||||
appMgmtNote.TextStyle = fyne.TextStyle{Italic: true}
|
||||
|
||||
content := container.NewVBox(
|
||||
troubleshootingTitle,
|
||||
widget.NewSeparator(),
|
||||
rowCrossover,
|
||||
crossoverStatusDetail,
|
||||
rowWDB,
|
||||
rowWine,
|
||||
appMgmtNote,
|
||||
)
|
||||
|
||||
scrollContainer := container.NewScroll(content)
|
||||
|
||||
troubleshootingCloseButton = widget.NewButton("Close", func() {})
|
||||
|
||||
popupContent := container.NewBorder(
|
||||
nil, // top
|
||||
container.NewCenter(troubleshootingCloseButton), // bottom
|
||||
nil, // left
|
||||
nil, // right
|
||||
container.NewPadded(scrollContainer), // center
|
||||
)
|
||||
|
||||
windowSize := currentWindow.Content().Size()
|
||||
popupWidth := windowSize.Width * 5 / 6
|
||||
popupHeight := windowSize.Height * 5 / 6
|
||||
|
||||
popup := widget.NewModalPopUp(popupContent, currentWindow.Canvas())
|
||||
popup.Resize(fyne.NewSize(popupWidth, popupHeight))
|
||||
|
||||
troubleshootingCloseButton.OnTapped = func() {
|
||||
popup.Hide()
|
||||
}
|
||||
|
||||
popup.Show()
|
||||
}
|
||||
|
||||
// getCrossoverVersion reads the Info.plist and returns the version string, or "" if not found
|
||||
func getCrossoverVersion(appPath string) string {
|
||||
if appPath == "" {
|
||||
return ""
|
||||
}
|
||||
plistPath := filepath.Join(appPath, "Contents", "Info.plist")
|
||||
f, err := os.Open(plistPath)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
defer f.Close()
|
||||
var data struct {
|
||||
Version string `plist:"CFBundleShortVersionString"`
|
||||
}
|
||||
decoder := plist.NewDecoder(f)
|
||||
if err := decoder.Decode(&data); err != nil {
|
||||
return ""
|
||||
}
|
||||
return data.Version
|
||||
}
|
||||
|
||||
// isCrossoverVersionRecommended returns true if version >= 25.0.1
|
||||
func isCrossoverVersionRecommended(version string) bool {
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) < 3 {
|
||||
return false
|
||||
}
|
||||
major := parts[0]
|
||||
minor := parts[1]
|
||||
patch := parts[2]
|
||||
if major > "25" {
|
||||
return true
|
||||
}
|
||||
if major == "25" && minor >= "0" && patch >= "1" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@@ -53,4 +53,13 @@ var (
|
||||
|
||||
// Pulsing effect variables (pulsingActive is in status.go)
|
||||
pulsingTicker *time.Ticker
|
||||
|
||||
// Troubleshooting popup and controls
|
||||
troubleshootingButton *widget.Button
|
||||
troubleshootingPopupActive bool
|
||||
crossoverVersionStatusLabel *widget.RichText
|
||||
wdbDeleteButton *widget.Button
|
||||
wineDeleteButton *widget.Button
|
||||
appMgmtPermissionButton *widget.Button
|
||||
troubleshootingCloseButton *widget.Button
|
||||
)
|
||||
|
Reference in New Issue
Block a user