rastrillo / pwa Public

Clone
git clone https://amadan.net/rastrillo/pwa

Plain git — no account needed to clone.

Download

Download this file

1package main
2
3import (
4 "flag"
5 "fmt"
6 "image"
7 "image/color"
8 "image/png"
9 "log"
10 "net"
11 "net/http"
12 "strconv"
13
14 "amadan.net/rastrillo/aviso"
15 "amadan.net/rastrillo/pwa"
16)
17
18func main() {
19 addr := flag.String("addr", "127.0.0.1:8080", "listen address")
20 flag.Parse()
21 mux := http.NewServeMux()
22 manifest, err := (pwa.Manifest{ID: "/", Name: "PWA Example", StartURL: "/", Scope: "/",
23 ThemeColor: "#234d45", BackgroundColor: "#ffffff",
24 Icons: []pwa.Icon{
25 {Src: "/icon/192", Sizes: "192x192", Type: "image/png"},
26 {Src: "/icon/512", Sizes: "512x512", Type: "image/png"},
27 },
28 }).Handler()
29 if err != nil {
30 log.Fatal(err)
31 }
32 mux.Handle("/manifest.webmanifest", manifest)
33 mux.Handle("/pwa/", http.StripPrefix("/pwa", pwa.Assets()))
34 mux.HandleFunc("GET /aviso-sw.js", func(w http.ResponseWriter, r *http.Request) {
35 w.Header().Set("Content-Type", "text/javascript")
36 w.Header().Set("Cache-Control", "no-cache")
37 _, _ = w.Write(aviso.WorkerJS())
38 })
39 mux.HandleFunc("GET /sw.js", func(w http.ResponseWriter, r *http.Request) {
40 w.Header().Set("Content-Type", "text/javascript")
41 w.Header().Set("Cache-Control", "no-cache")
42 fmt.Fprint(w, `importScripts("/pwa/worker.js", "/aviso-sw.js");
43RastrilloPWA.install();
44self.addEventListener("push", e => e.waitUntil(AvisoSW.handlePush(e, {
45 fallback: () => ({title: "New activity", options: {data: {url: "/"}}})
46})));
47self.addEventListener("notificationclick", e => e.waitUntil(AvisoSW.handleClick(e, {fallbackURL: "/"})));
48`)
49 })
50 mux.HandleFunc("GET /icon/{size}", func(w http.ResponseWriter, r *http.Request) {
51 size, _ := strconv.Atoi(r.PathValue("size"))
52 if size != 180 && size != 192 && size != 512 {
53 http.NotFound(w, r)
54 return
55 }
56 im := image.NewRGBA(image.Rect(0, 0, size, size))
57 for y := 0; y < size; y++ {
58 for x := 0; x < size; x++ {
59 im.Set(x, y, color.RGBA{35, 77, 69, 255})
60 }
61 }
62 w.Header().Set("Content-Type", "image/png")
63 _ = png.Encode(w, im)
64 })
65 mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
66 w.Header().Set("Content-Type", "text/html; charset=utf-8")
67 w.Header().Set("Cache-Control", "no-store")
68 fmt.Fprint(w, `<!doctype html><html lang="en"><meta charset="utf-8">
69<meta name="viewport" content="width=device-width,initial-scale=1">
70<link rel="manifest" href="/manifest.webmanifest"><link rel="apple-touch-icon" href="/icon/180">
71<meta name="theme-color" content="#234d45"><title>PWA Example</title>
72<main><h1>PWA Example</h1><p>Add this app to your Home Screen or use your browser's install option.</p>
73<p>Open it once online. Then disconnect and reload to see the offline page.</p>
74<label>Try an unsaved edit <input id="draft"></label>
75<p id="update" hidden>An update is ready. Save your work in all tabs, then close and reopen the app.</p>
76<script type="module">
77import {register} from "/pwa/client.mjs";
78register({onUpdate: () => {document.querySelector("#update").hidden = false;}}).catch(console.error);
79</script></main></html>`)
80 })
81 listener, err := net.Listen("tcp", *addr)
82 if err != nil {
83 log.Fatal(err)
84 }
85 fmt.Printf("http://%s\n", listener.Addr())
86 log.Fatal(http.Serve(listener, mux))
87}
88