-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgui.go
168 lines (154 loc) · 5.01 KB
/
gui.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//go:build !clionly
package main
import (
_ "embed"
"log"
"os"
"strings"
"sync"
"github.com/sqweek/dialog"
"github.com/webview/webview"
)
var w webview.WebView
// LOW-TODO: Bundle Roboto font, don't depend on the internet for this?
const html = `
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- Use minimum-scale=1 to enable GPU rasterization -->
<meta
name='viewport'
content='user-scalable=0, initial-scale=1, minimum-scale=1, width=device-width, height=device-height'
/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@200;300;400;500;700;900&display=swap">
<style>
body {
margin: 0;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",
Ubuntu,Cantarell,Oxygen-Sans,"Helvetica Neue",Arial,Roboto,sans-serif;
}
</style>
</head>
<body><div id="app"></div><script>initiateReact()</script></body>
</html>
`
//go:embed ui/dist/main.js
var js string
var guiDialogQueryResponse bool
var guiDialogQueryResponseMutex sync.Mutex
func runGui() {
debug := false
if val, exists := os.LookupEnv("DEBUG"); exists {
debug = val == "true"
}
w = webview.New(debug)
defer w.Destroy()
w.SetSize(640, 480, webview.HintNone) // 540/360
w.SetTitle("ibu's mod installer " + modpackVersion)
// Bind a function to initiate React via webview.Eval.
w.Bind("initiateReact", func() { w.Eval(js) })
w.Bind("changeVersion", func(name string) {
selectedVersionMutex.Lock()
minecraftFolderMutex.Lock()
defer selectedVersionMutex.Unlock()
defer minecraftFolderMutex.Unlock()
selectedVersion = name
})
w.Bind("toggleInstallFabric", func() {
installFabricOptMutex.Lock()
defer installFabricOptMutex.Unlock()
installFabricOpt = !installFabricOpt
})
w.Bind("respondQuery", func(response bool) {
guiDialogQueryResponse = response
guiDialogQueryResponseMutex.Unlock()
})
w.Bind("updateMinecraftFolder", func(directory string) {
selectedVersionMutex.Lock()
minecraftFolderMutex.Lock()
defer selectedVersionMutex.Unlock()
defer minecraftFolderMutex.Unlock()
minecraftFolder = directory
checkUpdatableAndUpdateVersion()
})
w.Bind("promptForFolder", func() {
directory, err := dialog.Directory().Title("Select Minecraft game directory").Browse()
if err != nil {
setError(err.Error())
return
}
selectedVersionMutex.Lock()
minecraftFolderMutex.Lock()
defer selectedVersionMutex.Unlock()
defer minecraftFolderMutex.Unlock()
minecraftFolder = directory
checkUpdatableAndUpdateVersion()
folder := strings.ReplaceAll(strings.ReplaceAll(directory, "\\", "\\\\"), "\"", "\\\"")
w.Eval("window.setMinecraftFolderState(\"" + folder + "\")")
})
w.Bind("installMods", func() { go initiateInstall() })
w.Navigate("data:text/html," + strings.ReplaceAll(string(html), "+", "%2B"))
w.Run()
}
func initiateInstall() {
selectedVersionMutex.Lock()
installFabricOptMutex.Lock()
minecraftFolderMutex.Lock()
defer selectedVersionMutex.Unlock()
defer installFabricOptMutex.Unlock()
defer minecraftFolderMutex.Unlock()
defer w.Dispatch(checkUpdatableAndUpdateVersion)
w.Dispatch(func() {
setError("") // This is already set in the JavaScript on mount, but whatever.
setMessage("Working...") // This is already set in the JavaScript on mount, but whatever.
setInProgress(true)
})
// TODO: If there was an upgrade, then it should show what mods were updated and what mods weren't
err := installMods(func(msg string) { w.Dispatch(func() { setMessage(msg) }) }, queryUser)
w.Dispatch(func() {
if err != nil && err.Error() != "Cancelled" {
log.Println(err)
setError(err.Error())
} else if installFabricOpt {
setMessage("Done! You can now launch Minecraft, select the latest \"ibu\\'s modpack\" profile," +
" and enjoy! See the FAQ if you need any more information.")
} else {
setMessage("Done! You can now launch Minecraft, select the latest fabric-loader or quilt-loader" +
" version, and enjoy! See the FAQ if you need any more information.")
}
setInProgress(false)
})
}
func queryUser(query string) bool {
guiDialogQueryResponseMutex.Lock()
w.Dispatch(func() { w.Eval("window.setQueryState(`" + query + "`)") })
// This waits for the mutex to unlock.
guiDialogQueryResponseMutex.Lock()
defer guiDialogQueryResponseMutex.Unlock()
return guiDialogQueryResponse
}
func checkUpdatableAndUpdateVersion() {
updatable := getUpdatableVersions()
versionArrayJson := ""
for _, version := range updatable {
versionArrayJson += "\"" + version + "\","
}
w.Eval("setUpdatableVersionsState([" + versionArrayJson + "])")
w.Eval("setMinecraftVersionState(\"" + selectedVersion + "\")")
}
func setMessage(content string) {
w.Dispatch(func() { w.Eval("window.setMessageState('" + content + "')") })
}
func setError(content string) {
w.Dispatch(func() { w.Eval("window.setErrorState('" + content + "')") })
}
// setInProgress disables buttons and shows the progress bar.
func setInProgress(inProgress bool) {
w.Dispatch(func() {
if inProgress {
w.Eval("window.setInProgressState(true)")
} else {
w.Eval("window.setInProgressState(false)")
}
})
}