2014-07-01 17:13:50 -05:00
|
|
|
package main
|
2014-04-29 18:44:02 -05:00
|
|
|
|
|
|
|
import (
|
2014-08-14 17:24:14 -05:00
|
|
|
"encoding/json"
|
2014-04-29 18:44:02 -05:00
|
|
|
"errors"
|
2014-07-29 17:17:23 -05:00
|
|
|
"io/ioutil"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
|
|
|
|
2014-04-29 18:44:02 -05:00
|
|
|
"github.com/ethereum/eth-go/ethchain"
|
2014-08-15 18:38:24 -05:00
|
|
|
"github.com/ethereum/eth-go/ethpipe"
|
2014-07-24 05:30:41 -05:00
|
|
|
"github.com/ethereum/eth-go/ethstate"
|
2014-04-29 18:44:02 -05:00
|
|
|
"github.com/ethereum/eth-go/ethutil"
|
2014-08-14 17:24:14 -05:00
|
|
|
"github.com/ethereum/go-ethereum/javascript"
|
2014-05-20 09:58:13 -05:00
|
|
|
"github.com/howeyc/fsnotify"
|
2014-08-15 06:27:43 -05:00
|
|
|
"gopkg.in/qml.v1"
|
2014-04-29 18:44:02 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type HtmlApplication struct {
|
|
|
|
win *qml.Window
|
|
|
|
webView qml.Object
|
|
|
|
engine *qml.Engine
|
|
|
|
lib *UiLib
|
|
|
|
path string
|
2014-05-20 09:58:13 -05:00
|
|
|
watcher *fsnotify.Watcher
|
2014-04-29 18:44:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewHtmlApplication(path string, lib *UiLib) *HtmlApplication {
|
|
|
|
engine := qml.NewEngine()
|
|
|
|
|
|
|
|
return &HtmlApplication{engine: engine, lib: lib, path: path}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *HtmlApplication) Create() error {
|
|
|
|
component, err := app.engine.LoadFile(app.lib.AssetPath("qml/webapp.qml"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if filepath.Ext(app.path) == "eth" {
|
|
|
|
return errors.New("Ethereum package not yet supported")
|
|
|
|
|
|
|
|
// TODO
|
2014-07-29 17:17:23 -05:00
|
|
|
//ethutil.OpenPackage(app.path)
|
2014-04-29 18:44:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
win := component.CreateWindow(nil)
|
|
|
|
win.Set("url", app.path)
|
|
|
|
webView := win.ObjectByName("webView")
|
|
|
|
|
|
|
|
app.win = win
|
|
|
|
app.webView = webView
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-05-20 09:58:13 -05:00
|
|
|
func (app *HtmlApplication) RootFolder() string {
|
|
|
|
folder, err := url.Parse(app.path)
|
|
|
|
if err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
2014-07-14 08:25:01 -05:00
|
|
|
return path.Dir(ethutil.WindonizePath(folder.RequestURI()))
|
2014-05-20 09:58:13 -05:00
|
|
|
}
|
|
|
|
func (app *HtmlApplication) RecursiveFolders() []os.FileInfo {
|
|
|
|
files, _ := ioutil.ReadDir(app.RootFolder())
|
|
|
|
var folders []os.FileInfo
|
|
|
|
for _, file := range files {
|
|
|
|
if file.IsDir() {
|
|
|
|
folders = append(folders, file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return folders
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *HtmlApplication) NewWatcher(quitChan chan bool) {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
app.watcher, err = fsnotify.NewWatcher()
|
|
|
|
if err != nil {
|
2014-07-14 08:29:02 -05:00
|
|
|
logger.Infoln("Could not create new auto-reload watcher:", err)
|
2014-05-20 09:58:13 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
err = app.watcher.Watch(app.RootFolder())
|
|
|
|
if err != nil {
|
2014-07-14 08:29:02 -05:00
|
|
|
logger.Infoln("Could not start auto-reload watcher:", err)
|
|
|
|
return
|
2014-05-20 09:58:13 -05:00
|
|
|
}
|
|
|
|
for _, folder := range app.RecursiveFolders() {
|
|
|
|
fullPath := app.RootFolder() + "/" + folder.Name()
|
|
|
|
app.watcher.Watch(fullPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
out:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-quitChan:
|
|
|
|
app.watcher.Close()
|
|
|
|
break out
|
|
|
|
case <-app.watcher.Event:
|
2014-06-23 05:41:11 -05:00
|
|
|
//logger.Debugln("Got event:", ev)
|
2014-05-20 09:58:13 -05:00
|
|
|
app.webView.Call("reload")
|
|
|
|
case err := <-app.watcher.Error:
|
|
|
|
// TODO: Do something here
|
2014-06-23 05:41:11 -05:00
|
|
|
logger.Infoln("Watcher error:", err)
|
2014-05-20 09:58:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-04-29 18:44:02 -05:00
|
|
|
func (app *HtmlApplication) Engine() *qml.Engine {
|
|
|
|
return app.engine
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *HtmlApplication) Window() *qml.Window {
|
|
|
|
return app.win
|
|
|
|
}
|
|
|
|
|
|
|
|
func (app *HtmlApplication) NewBlock(block *ethchain.Block) {
|
2014-08-15 18:38:24 -05:00
|
|
|
b := ðpipe.JSBlock{Number: int(block.BlockInfo().Number), Hash: ethutil.Bytes2Hex(block.Hash())}
|
2014-04-29 18:44:02 -05:00
|
|
|
app.webView.Call("onNewBlockCb", b)
|
|
|
|
}
|
|
|
|
|
2014-08-14 17:24:14 -05:00
|
|
|
func (self *HtmlApplication) Messages(messages ethstate.Messages, id string) {
|
|
|
|
var msgs []javascript.JSMessage
|
|
|
|
for _, m := range messages {
|
|
|
|
msgs = append(msgs, javascript.NewJSMessage(m))
|
|
|
|
}
|
|
|
|
|
|
|
|
b, _ := json.Marshal(msgs)
|
|
|
|
|
|
|
|
self.webView.Call("onWatchedCb", string(b), id)
|
|
|
|
}
|
|
|
|
|
2014-04-29 18:44:02 -05:00
|
|
|
func (app *HtmlApplication) Destroy() {
|
|
|
|
app.engine.Destroy()
|
|
|
|
}
|