Skip to content

Commit

Permalink
handle reloads
Browse files Browse the repository at this point in the history
  • Loading branch information
gernest committed Apr 9, 2018
1 parent 696cfe7 commit df1c228
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 39 deletions.
23 changes: 21 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ func Server(path string) error {
return err
}
basePath := fmt.Sprintf("/%s/", filepath.Base(path))

cache.Store("/", dirDoc)
dirDoc.Cache(cache)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
t.ExecuteTemplate(w, "index.html", nil)
t.ExecuteTemplate(w, "index.html", dirDoc)
})
mux.HandleFunc("/context", func(w http.ResponseWriter, r *http.Request) {
WriteJson(w, dirDoc)
Expand All @@ -52,6 +52,25 @@ func Server(path string) error {
))
fileServer := http.FileServer(http.Dir(path))
mux.Handle(basePath, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u := r.URL.Path
if strings.HasSuffix(u, "/") {
// It is a directory listing.
dir := strings.TrimSuffix(u, "/")
if doc, ok := cache.Load(dir); ok {
t.ExecuteTemplate(w, "index.html", doc)
return
}
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
ext := filepath.Ext(u)
switch ext {
case "", ".article", ".slide":
if doc, ok := cache.Load(u); ok {
t.ExecuteTemplate(w, "index.html", doc)
return
}
}
http.StripPrefix(basePath, fileServer).ServeHTTP(w, r)
}))
mux.Handle("/files/", http.StripPrefix("/files", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
125 changes: 125 additions & 0 deletions static/spinner.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* Absolute Center Spinner */

.loading {
position: fixed;
z-index: 999;
height: 2em;
width: 2em;
overflow: show;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
}

/* Transparent Overlay */

.loading:before {
content: '';
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}

/* :not(:required) hides these rules from IE9 and below */

.loading:not(:required) {
/* hide "loading..." text */
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}

.loading:not(:required):after {
content: '';
display: block;
font-size: 10px;
width: 1em;
height: 1em;
margin-top: -0.5em;
-webkit-animation: spinner 1500ms infinite linear;
-moz-animation: spinner 1500ms infinite linear;
-ms-animation: spinner 1500ms infinite linear;
-o-animation: spinner 1500ms infinite linear;
animation: spinner 1500ms infinite linear;
border-radius: 0.5em;
-webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
}

/* Animation */

@-webkit-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@-moz-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@-o-keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}

@keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
7 changes: 5 additions & 2 deletions templates/present/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<title>{{.BaseName}}</title>
<link type="text/css" rel="stylesheet" id="dir" href="/static/spinner.css">
<link type="text/css" rel="stylesheet" id="dir" href="/static/dir.css">
<script>
window.localStorage.setItem("ACTIVE_ROUTE", "{{.URL}}")
</script>
</head>

<body>

</body>
<footer>
<script src="/static/ui.js"></script>
Expand Down
13 changes: 13 additions & 0 deletions ui/components/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,16 @@ func (c *Caption) Render() vecty.ComponentOrHTML {
vecty.Text(c.c.Text),
)
}

type Spinner struct {
vecty.Core
}

func (*Spinner) Render() vecty.ComponentOrHTML {
return elem.Body(
elem.Div(
vecty.Markup(vecty.Class("loading")),
vecty.Text("loading"),
),
)
}
37 changes: 6 additions & 31 deletions ui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

func main() {
r := router.NewRouter()

cache := &sync.Map{}
r.NotFound = func(ctx ...interface{}) vecty.ComponentOrHTML {
if len(ctx) > 0 {
Expand All @@ -43,22 +42,7 @@ func main() {
vecty.Text("404"),
)
}
r.Handle("/", func(ctx ...interface{}) vecty.ComponentOrHTML {
return &Home{cache: cache, router: r}
})
vecty.RenderBody(r)
}

type Home struct {
vecty.Core

dir *models.File
cache *sync.Map
router *router.Router
}

func (h *Home) Mount() {
go func() {
go func(done func()) {
data, err := xhr.Send("GET", "/context", nil)
if err != nil {
panic(err)
Expand All @@ -68,20 +52,11 @@ func (h *Home) Mount() {
if err != nil {
panic(err)
}
h.dir = dir
h.dir.Cache(h.cache)
vecty.SetTitle(dir.Name)
vecty.Rerender(h)
}()
}

func (h *Home) Render() vecty.ComponentOrHTML {
if h.dir != nil {
return elem.Body(
&dir.Dir{Dir: h.dir, Router: h.router},
)
}
return elem.Body()
cache.Store("/", dir)
dir.Cache(cache)
done()
}(r.BeforeRendering())
vecty.RenderBody(r)
}

type PlainText struct {
Expand Down
24 changes: 20 additions & 4 deletions ui/router/router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package router

import (
"github.com/gernest/locstor"
"github.com/gernest/vectypresent/ui/components"
"github.com/gopherjs/gopherjs/js"
"github.com/gopherjs/vecty"
"github.com/gopherjs/vecty/elem"
Expand All @@ -15,6 +17,7 @@ type Router struct {
active string
NotFound HandlerFunc
context []interface{}
ready bool
}

const ActiveRoute = "ACTIVE_ROUTE"
Expand All @@ -24,16 +27,25 @@ type HandlerFunc func(...interface{}) vecty.ComponentOrHTML
// NewRouter returns new Router instance.
func NewRouter() *Router {
active := "/"
// if a, err := locstor.GetItem(ActiveRoute); err == nil {
// active = a
// }
if a, err := locstor.GetItem(ActiveRoute); err == nil {
active = a
}
r := &Router{
active: active,
handlers: make(map[string]HandlerFunc),
}
return r
}

func (r *Router) BeforeRendering() func() {
return func() {
if !r.ready {
r.ready = true
vecty.Rerender(r)
}
}
}

// Mount registers event listener for onpopstate global event.
func (r *Router) Mount() {
js.Global.Set("onpopstate", func() {
Expand All @@ -50,13 +62,16 @@ func (r *Router) PushState(path string, ctx ...interface{}) {
js.Global.Get("history").Call("pushState", nil, "", path)
r.active = path
r.context = ctx
// locstor.SetItem(ActiveRoute, path)
locstor.SetItem(ActiveRoute, path)
vecty.Rerender(r)
}

// Render renders the active component register in the router. If there was any
// context supplied which calling pushState, it is passed to the handler.
func (r *Router) Render() vecty.ComponentOrHTML {
if !r.ready {
return &components.Spinner{}
}
if r.active == "" {
r.active = "/"
}
Expand Down Expand Up @@ -85,4 +100,5 @@ func (r *Router) Handle(pattern string, h HandlerFunc) {
// unmounted.
func (r *Router) Unmount() {
js.Global.Set("onpopstate", nil)
locstor.Clear()
}

0 comments on commit df1c228

Please sign in to comment.