Add Progressive Web App support

provide manifest.json to enable PWA compatibilities
This commit is contained in:
Sebastian Haas 2020-10-01 22:30:07 +02:00
parent a080c85cbc
commit b685b8040a
7 changed files with 146 additions and 54 deletions

View File

@ -7,7 +7,7 @@ gotty: main.go server/*.go webtty/*.go backend/*.go Makefile
godep go build ${BUILD_OPTIONS} godep go build ${BUILD_OPTIONS}
.PHONY: asset .PHONY: asset
asset: bindata/static/js/gotty-bundle.js bindata/static/index.html bindata/static/favicon.png bindata/static/css/index.css bindata/static/css/xterm.css bindata/static/css/xterm_customize.css asset: bindata/static/js/gotty-bundle.js bindata/static/index.html bindata/static/favicon.png bindata/static/css/index.css bindata/static/css/xterm.css bindata/static/css/xterm_customize.css bindata/static/manifest.json bindata/static/icon_192.png
go-bindata -prefix bindata -pkg server -ignore=\\.gitkeep -o server/asset.go bindata/... go-bindata -prefix bindata -pkg server -ignore=\\.gitkeep -o server/asset.go bindata/...
gofmt -w server/asset.go gofmt -w server/asset.go
@ -23,9 +23,15 @@ bindata/static: bindata
bindata/static/index.html: bindata/static resources/index.html bindata/static/index.html: bindata/static resources/index.html
cp resources/index.html bindata/static/index.html cp resources/index.html bindata/static/index.html
bindata/static/manifest.json: bindata/static resources/manifest.json
cp resources/manifest.json bindata/static/manifest.json
bindata/static/favicon.png: bindata/static resources/favicon.png bindata/static/favicon.png: bindata/static resources/favicon.png
cp resources/favicon.png bindata/static/favicon.png cp resources/favicon.png bindata/static/favicon.png
bindata/static/icon_192.png: bindata/static resources/icon_192.png
cp resources/icon_192.png bindata/static/icon_192.png
bindata/static/js: bindata/static bindata/static/js: bindata/static
mkdir -p bindata/static/js mkdir -p bindata/static/js

BIN
resources/icon_192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -2,6 +2,7 @@
<html> <html>
<head> <head>
<title>{{ .title }}</title> <title>{{ .title }}</title>
<link rel="manifest" href="manifest.json">
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="./css/index.css" /> <link rel="stylesheet" href="./css/index.css" />
<link rel="stylesheet" href="./css/xterm.css" /> <link rel="stylesheet" href="./css/xterm.css" />

15
resources/manifest.json Normal file
View File

@ -0,0 +1,15 @@
{
"short_name": "{{ .title }}",
"name": "{{ .title }}",
"start_url": "./",
"icons": [
{
"src": "./icon_192.png",
"type": "image/png",
"sizes": "192x192"
}
],
"display": "minimal-ui",
"theme_color": "#000000",
"background_color": "#000000"
}

File diff suppressed because one or more lines are too long

View File

@ -169,6 +169,40 @@ func (server *Server) processWSConn(ctx context.Context, conn *websocket.Conn) e
} }
func (server *Server) handleIndex(w http.ResponseWriter, r *http.Request) { func (server *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
indexVars, err := server.indexVariables(r)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
indexBuf := new(bytes.Buffer)
err = server.indexTemplate.Execute(indexBuf, indexVars)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
w.Write(indexBuf.Bytes())
}
func (server *Server) handleManifest(w http.ResponseWriter, r *http.Request) {
indexVars, err := server.indexVariables(r)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
indexBuf := new(bytes.Buffer)
err = server.manifestTemplate.Execute(indexBuf, indexVars)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
w.Write(indexBuf.Bytes())
}
func (server *Server) indexVariables(r *http.Request) (map[string]interface{}, error) {
titleVars := server.titleVariables( titleVars := server.titleVariables(
[]string{"server", "master"}, []string{"server", "master"},
map[string]map[string]interface{}{ map[string]map[string]interface{}{
@ -182,22 +216,13 @@ func (server *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
titleBuf := new(bytes.Buffer) titleBuf := new(bytes.Buffer)
err := server.titleTemplate.Execute(titleBuf, titleVars) err := server.titleTemplate.Execute(titleBuf, titleVars)
if err != nil { if err != nil {
http.Error(w, "Internal Server Error", 500) return nil, err
return
} }
indexVars := map[string]interface{}{ indexVars := map[string]interface{}{
"title": titleBuf.String(), "title": titleBuf.String(),
} }
return indexVars, err
indexBuf := new(bytes.Buffer)
err = server.indexTemplate.Execute(indexBuf, indexVars)
if err != nil {
http.Error(w, "Internal Server Error", 500)
return
}
w.Write(indexBuf.Bytes())
} }
func (server *Server) handleAuthToken(w http.ResponseWriter, r *http.Request) { func (server *Server) handleAuthToken(w http.ResponseWriter, r *http.Request) {

View File

@ -28,9 +28,10 @@ type Server struct {
factory Factory factory Factory
options *Options options *Options
upgrader *websocket.Upgrader upgrader *websocket.Upgrader
indexTemplate *template.Template indexTemplate *template.Template
titleTemplate *noesctmpl.Template titleTemplate *noesctmpl.Template
manifestTemplate *template.Template
} }
// New creates a new instance of Server. // New creates a new instance of Server.
@ -52,6 +53,15 @@ func New(factory Factory, options *Options) (*Server, error) {
panic("index template parse failed") // must be valid panic("index template parse failed") // must be valid
} }
manifestData, err := Asset("static/manifest.json")
if err != nil {
panic("manifest not found") // must be in bindata
}
manifestTemplate, err := template.New("manifest").Parse(string(manifestData))
if err != nil {
panic("manifest template parse failed") // must be valid
}
titleTemplate, err := noesctmpl.New("title").Parse(options.TitleFormat) titleTemplate, err := noesctmpl.New("title").Parse(options.TitleFormat)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to parse window title format `%s`", options.TitleFormat) return nil, errors.Wrapf(err, "failed to parse window title format `%s`", options.TitleFormat)
@ -78,8 +88,9 @@ func New(factory Factory, options *Options) (*Server, error) {
Subprotocols: webtty.Protocols, Subprotocols: webtty.Protocols,
CheckOrigin: originChekcer, CheckOrigin: originChekcer,
}, },
indexTemplate: indexTemplate, indexTemplate: indexTemplate,
titleTemplate: titleTemplate, titleTemplate: titleTemplate,
manifestTemplate: manifestTemplate,
}, nil }, nil
} }
@ -190,7 +201,9 @@ func (server *Server) setupHandlers(ctx context.Context, cancel context.CancelFu
siteMux.Handle(pathPrefix+"js/", http.StripPrefix(pathPrefix, staticFileHandler)) siteMux.Handle(pathPrefix+"js/", http.StripPrefix(pathPrefix, staticFileHandler))
siteMux.Handle(pathPrefix+"favicon.png", http.StripPrefix(pathPrefix, staticFileHandler)) siteMux.Handle(pathPrefix+"favicon.png", http.StripPrefix(pathPrefix, staticFileHandler))
siteMux.Handle(pathPrefix+"css/", http.StripPrefix(pathPrefix, staticFileHandler)) siteMux.Handle(pathPrefix+"css/", http.StripPrefix(pathPrefix, staticFileHandler))
siteMux.Handle(pathPrefix+"icon_192.png", http.StripPrefix(pathPrefix, staticFileHandler))
siteMux.HandleFunc(pathPrefix+"manifest.json", server.handleManifest)
siteMux.HandleFunc(pathPrefix+"auth_token.js", server.handleAuthToken) siteMux.HandleFunc(pathPrefix+"auth_token.js", server.handleAuthToken)
siteMux.HandleFunc(pathPrefix+"config.js", server.handleConfig) siteMux.HandleFunc(pathPrefix+"config.js", server.handleConfig)