|
|
|
@@ -3,6 +3,8 @@ package ui
|
|
|
|
|
import (
|
|
|
|
|
"log"
|
|
|
|
|
"net/url"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"turtlesilicon/pkg/launcher"
|
|
|
|
|
"turtlesilicon/pkg/patching"
|
|
|
|
@@ -45,6 +47,9 @@ func createOptionsComponents() {
|
|
|
|
|
vanillaTweaksCheckbox.SetChecked(prefs.EnableVanillaTweaks)
|
|
|
|
|
launcher.EnableVanillaTweaks = prefs.EnableVanillaTweaks
|
|
|
|
|
|
|
|
|
|
// Create Wine registry Option-as-Alt buttons and status
|
|
|
|
|
createWineRegistryComponents()
|
|
|
|
|
|
|
|
|
|
// Load environment variables from preferences
|
|
|
|
|
if prefs.EnvironmentVariables != "" {
|
|
|
|
|
launcher.CustomEnvVars = prefs.EnvironmentVariables
|
|
|
|
@@ -158,3 +163,182 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
|
|
|
|
|
|
|
|
|
|
return container.NewPadded(bottomContainer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// createWineRegistryComponents creates Wine registry Option-as-Alt buttons and status
|
|
|
|
|
func createWineRegistryComponents() {
|
|
|
|
|
// Create status label to show current state
|
|
|
|
|
optionAsAltStatusLabel = widget.NewRichText()
|
|
|
|
|
|
|
|
|
|
// Create enable button
|
|
|
|
|
enableOptionAsAltButton = widget.NewButton("Enable", func() {
|
|
|
|
|
enableOptionAsAltButton.Disable()
|
|
|
|
|
disableOptionAsAltButton.Disable()
|
|
|
|
|
|
|
|
|
|
// Show loading state in status label
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabling...")
|
|
|
|
|
startPulsingEffect()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Run in goroutine to avoid blocking UI
|
|
|
|
|
go func() {
|
|
|
|
|
if err := utils.SetOptionAsAltEnabled(true); err != nil {
|
|
|
|
|
log.Printf("Failed to enable Option-as-Alt mapping: %v", err)
|
|
|
|
|
// Update UI on main thread
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
stopPulsingEffect()
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enable Failed")
|
|
|
|
|
})
|
|
|
|
|
time.Sleep(2 * time.Second) // Show error briefly
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("Successfully enabled Option-as-Alt mapping")
|
|
|
|
|
// Update preferences
|
|
|
|
|
prefs, _ := utils.LoadPrefs()
|
|
|
|
|
prefs.RemapOptionAsAlt = true
|
|
|
|
|
utils.SavePrefs(prefs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update UI on main thread
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
stopPulsingEffect()
|
|
|
|
|
updateWineRegistryStatusWithMethod(true) // Use Wine command for accurate check after modifications
|
|
|
|
|
})
|
|
|
|
|
}()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Create disable button
|
|
|
|
|
disableOptionAsAltButton = widget.NewButton("Disable", func() {
|
|
|
|
|
enableOptionAsAltButton.Disable()
|
|
|
|
|
disableOptionAsAltButton.Disable()
|
|
|
|
|
|
|
|
|
|
// Show loading state in status label
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabling...")
|
|
|
|
|
startPulsingEffect()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Run in goroutine to avoid blocking UI
|
|
|
|
|
go func() {
|
|
|
|
|
if err := utils.SetOptionAsAltEnabled(false); err != nil {
|
|
|
|
|
log.Printf("Failed to disable Option-as-Alt mapping: %v", err)
|
|
|
|
|
// Update UI on main thread
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
stopPulsingEffect()
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disable Failed")
|
|
|
|
|
})
|
|
|
|
|
time.Sleep(2 * time.Second) // Show error briefly
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf("Successfully disabled Option-as-Alt mapping")
|
|
|
|
|
// Update preferences
|
|
|
|
|
prefs, _ := utils.LoadPrefs()
|
|
|
|
|
prefs.RemapOptionAsAlt = false
|
|
|
|
|
utils.SavePrefs(prefs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update UI on main thread
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
stopPulsingEffect()
|
|
|
|
|
updateWineRegistryStatusWithMethod(true) // Use Wine command for accurate check after modifications
|
|
|
|
|
})
|
|
|
|
|
}()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Style the buttons similar to other action buttons
|
|
|
|
|
enableOptionAsAltButton.Importance = widget.MediumImportance
|
|
|
|
|
disableOptionAsAltButton.Importance = widget.MediumImportance
|
|
|
|
|
|
|
|
|
|
// Initialize status and button states
|
|
|
|
|
updateWineRegistryStatus()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// updateWineRegistryStatus updates the Wine registry status label and button states
|
|
|
|
|
func updateWineRegistryStatus() {
|
|
|
|
|
updateWineRegistryStatusWithMethod(false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// updateWineRegistryStatusWithMethod updates status with choice of checking method
|
|
|
|
|
func updateWineRegistryStatusWithMethod(useWineCommand bool) {
|
|
|
|
|
if useWineCommand {
|
|
|
|
|
// Use Wine command for accurate check after modifications
|
|
|
|
|
currentWineRegistryEnabled = utils.CheckOptionAsAltEnabled()
|
|
|
|
|
} else {
|
|
|
|
|
// Use fast file-based check for regular status updates
|
|
|
|
|
currentWineRegistryEnabled = utils.CheckOptionAsAltEnabledFast()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update UI with simple white text
|
|
|
|
|
if currentWineRegistryEnabled {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabled")
|
|
|
|
|
} else {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabled")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update button states based on current status
|
|
|
|
|
if currentWineRegistryEnabled {
|
|
|
|
|
// If enabled, only show disable button as clickable
|
|
|
|
|
enableOptionAsAltButton.Disable()
|
|
|
|
|
disableOptionAsAltButton.Enable()
|
|
|
|
|
} else {
|
|
|
|
|
// If disabled, only show enable button as clickable
|
|
|
|
|
enableOptionAsAltButton.Enable()
|
|
|
|
|
disableOptionAsAltButton.Disable()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// startPulsingEffect starts a pulsing animation for the status label during loading
|
|
|
|
|
func startPulsingEffect() {
|
|
|
|
|
if pulsingActive {
|
|
|
|
|
return // Already pulsing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pulsingActive = true
|
|
|
|
|
pulsingTicker = time.NewTicker(500 * time.Millisecond)
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
dots := ""
|
|
|
|
|
|
|
|
|
|
for pulsingActive {
|
|
|
|
|
select {
|
|
|
|
|
case <-pulsingTicker.C:
|
|
|
|
|
if pulsingActive {
|
|
|
|
|
// Cycle through different dot patterns for visual effect
|
|
|
|
|
switch len(dots) {
|
|
|
|
|
case 0:
|
|
|
|
|
dots = "."
|
|
|
|
|
case 1:
|
|
|
|
|
dots = ".."
|
|
|
|
|
case 2:
|
|
|
|
|
dots = "..."
|
|
|
|
|
default:
|
|
|
|
|
dots = ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the label with pulsing dots
|
|
|
|
|
fyne.Do(func() {
|
|
|
|
|
if pulsingActive && optionAsAltStatusLabel != nil {
|
|
|
|
|
// Use the dots directly in the status text
|
|
|
|
|
if strings.Contains(optionAsAltStatusLabel.String(), "Enabling") {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabling" + dots)
|
|
|
|
|
} else if strings.Contains(optionAsAltStatusLabel.String(), "Disabling") {
|
|
|
|
|
optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabling" + dots)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// stopPulsingEffect stops the pulsing animation
|
|
|
|
|
func stopPulsingEffect() {
|
|
|
|
|
if !pulsingActive {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pulsingActive = false
|
|
|
|
|
if pulsingTicker != nil {
|
|
|
|
|
pulsingTicker.Stop()
|
|
|
|
|
pulsingTicker = nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|