-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathgotron_methods.go
229 lines (178 loc) · 5.69 KB
/
gotron_methods.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// +build !gotronpack
package gotron
import (
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"github.com/Equanox/gotron/internal/file"
"github.com/pkg/errors"
"github.com/otiai10/copy"
"github.com/Benchkram/errz"
)
const (
templateApplicationDir = "templates/app"
gotronFileMode = os.FileMode(0755)
)
// Start starts an Instance of gotronbrowserwindow
func (gbw *BrowserWindow) Start(forceInstall ...bool) (isdone chan bool, err error) {
defer errz.Recover(&err)
var _forceInstall bool
for _, v := range forceInstall {
_forceInstall = v
break
}
isdone = done
// build up structure
err = gbw.CreateAppStructure(_forceInstall)
errz.Fatal(err)
// run sockets and electron
err = gbw.runApplication()
errz.Fatal(err)
return
}
// CreatAppStructure -
// Get electron and web files. Put them into gbw.AppFolder (default ".gotron")
func (gbw *BrowserWindow) CreateAppStructure(forceInstall ...bool) (err error) {
var _forceInstall bool
for _, v := range forceInstall {
_forceInstall = v
}
defer errz.Recover(&err)
err = os.MkdirAll(gbw.AppDirectory, 0777)
errz.Fatal(err)
// Copy Electron Files
err = gbw.copyElectronApplication(_forceInstall)
errz.Fatal(err)
// Run npm install
err = gbw.runNPM(_forceInstall)
errz.Fatal(err)
return nil
}
// runApplication starts websockets and runs the electron application
func (gbw *BrowserWindow) runApplication() (err error) {
//run websocket
gbw.runWebsocket()
//get electron start parameters
electronPath, args, err := gbw.createStartParameters()
errz.Fatal(err)
//run electron
electron := exec.Command(electronPath, args...)
electron.Stdout = os.Stdout
electron.Stderr = os.Stderr
err = electron.Start()
errz.Fatal(err)
gbw.Running = true
return
}
// copyElectronApplication from library package to defined app directory.
// copy app files (.js .css) to app directory
//
// forceInstall forces a reinstallation of electron
// and resets AppDirectory/assets if no UIFolder was set.
//
// On the first run we copy a default application
// into AppDirectory and install electronjs locally.
// When a ui directory was set we use the contents of those
// and copy it into AppDirectory/assets
func (gbw *BrowserWindow) copyElectronApplication(forceInstall bool) (err error) {
defer errz.Recover(&err)
// Copy app Directory
mainJS := filepath.Join(gbw.AppDirectory, "main.js")
firstRun := !file.Exists(mainJS)
_, filename, _, ok := runtime.Caller(0)
if !ok {
return errors.New("No caller information")
}
gbwDirectory := filepath.Dir(filename)
if firstRun || forceInstall {
templateDir := filepath.Join(gbwDirectory, templateApplicationDir)
err = copy.Copy(templateDir, gbw.AppDirectory)
errz.Fatal(err)
}
err = os.Chmod(gbw.AppDirectory, gotronFileMode)
errz.Fatal(err)
assetsDir := filepath.Join(gbw.AppDirectory, "assets")
err = os.Chmod(assetsDir, gotronFileMode)
errz.Fatal(err)
// If no UI folder is set use default ui files
if gbw.UIFolder == "" {
return
}
// UIFolder must contain a index.htm(l)
html := filepath.Join(gbw.UIFolder, "index.html")
htm := filepath.Join(gbw.UIFolder, "index.htm")
if !(file.Exists(html) || file.Exists(htm)) {
return fmt.Errorf("index.htm(l) missing in %s", gbw.UIFolder)
}
// No need to copy web application files
// when no ui folder is set.
// Also check for ".gotron/assets". This is the
// default directory when called from gotron-builder,
// avoids deleting asset dir by accident.
src, err := filepath.Abs(gbw.UIFolder)
errz.Fatal(err)
dst, err := filepath.Abs(filepath.Join(gbw.AppDirectory, "assets"))
errz.Fatal(err)
if src != dst {
err = os.RemoveAll(filepath.Join(gbw.AppDirectory, "assets"))
errz.Fatal(err)
err = copy.Copy(gbw.UIFolder, filepath.Join(gbw.AppDirectory, "assets"))
errz.Fatal(err)
}
return nil
}
//runNPM - run npm install if not done already or foced.
func (gbw *BrowserWindow) runNPM(forceinstall bool) (err error) {
defer errz.Recover(&err)
nodeModules := filepath.Join(gbw.AppDirectory, "node_modules/")
forceinstall = !file.Exists(nodeModules)
if forceinstall {
logger.Debug().Msgf("Installing npm packages...")
cmd := exec.Command("npm", "install")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = gbw.AppDirectory
err = cmd.Start()
errz.Fatal(err)
logger.Debug().Msgf("Waiting for batch")
err = cmd.Wait()
errz.Fatal(err)
logger.Debug().Msgf("Batch done")
}
return err
}
//runWebsocket with defined port or look for free port if taken
func (gbw *BrowserWindow) runWebsocket() {
var err error
errz.Recover(&err)
listener, err := net.Listen("tcp", ":"+strconv.Itoa(gbw.Port))
errz.Fatal(err)
logger.Debug().Msgf("Using port: %d", listener.Addr().(*net.TCPAddr).Port)
gbw.Port = listener.Addr().(*net.TCPAddr).Port
// Endpoint for Electron startup/teardown
// + browser window events to nodejs
http.HandleFunc("/browser/window/events", gbw.mainEventSocket)
// Endpoint for ipc like messages
// send from user web application
http.HandleFunc("/web/app/events", gbw.onSocket)
go http.Serve(listener, nil) // Start websockets in goroutine
}
//createStartParameters returns absolute electron path and list of arguments to be passed on electron run call.
func (gbw *BrowserWindow) createStartParameters() (electronPath string, arguments []string, err error) {
defer errz.Recover(&err)
electronPath, err = filepath.Abs(filepath.Join(gbw.AppDirectory + "/node_modules/.bin/electron"))
errz.Fatal(err)
appPath, err := filepath.Abs(gbw.AppDirectory + "main.js")
errz.Fatal(err)
logger.Debug().Msgf(appPath)
configString, err := json.Marshal(gbw.WindowOptions)
errz.Fatal(err)
arguments = []string{appPath, strconv.Itoa(gbw.Port), string(configString)}
return
}