Skip to content
This repository has been archived by the owner on Aug 28, 2022. It is now read-only.

Commit

Permalink
removing prepare stage
Browse files Browse the repository at this point in the history
post treating rendered
messages to session being generated in session
  • Loading branch information
brendonmatos committed Jan 6, 2021
1 parent a3aff32 commit 43b83f8
Show file tree
Hide file tree
Showing 10 changed files with 304 additions and 234 deletions.
255 changes: 98 additions & 157 deletions component.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package golive

import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"reflect"
"regexp"
"strconv"
"strings"

"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)

//
type ComponentLifeTime interface {
Prepare(component *LiveComponent)
Create(component *LiveComponent)
TemplateHandler(component *LiveComponent) string
Mounted(component *LiveComponent)
BeforeMount(component *LiveComponent)
Expand All @@ -28,15 +24,14 @@ type ChildLiveComponent interface{}
type LiveComponent struct {
Name string

IsMounted bool
IsPrepared bool
IsCreated bool
Exited bool
IsMounted bool
IsCreated bool
Exited bool

log Log
updatesChannel *ComponentLifeCycle
component ComponentLifeTime
renderer LiveRenderer
log Log
life *ComponentLifeCycle
component ComponentLifeTime
renderer LiveRenderer
}

// NewLiveComponent ...
Expand All @@ -45,76 +40,70 @@ func NewLiveComponent(name string, time ComponentLifeTime) *LiveComponent {
Name: name,
component: time,
renderer: LiveRenderer{
state: LiveState{},
state: &LiveState{},
template: nil,
},
}
}

func (l *LiveComponent) RenderChild(fn reflect.Value, _ ...reflect.Value) template.HTML {

child, ok := fn.Interface().(*LiveComponent)

if !ok {
l.log(LogError, "child not a *golive.LiveComponent", nil)
return ""
}

render, err := child.Render()
if err != nil {
l.log(LogError, "render child: render", logEx{"error": err})
}

return template.HTML(render)
}
func (l *LiveComponent) Create(life *ComponentLifeCycle) error {
var err error

func (l *LiveComponent) generateTemplate(ts string) (*template.Template, error) {
return template.New(l.Name).Funcs(template.FuncMap{
"render": l.RenderChild,
}).Parse(ts)
}
l.life = life

func (l *LiveComponent) Create() error {
var err error
// The first notification, will notify
// an component without unique name
l.notifyStage(WillCreate)

l.Name = l.createUniqueName()

templateString := l.component.TemplateHandler(l)
templateString = l.addWSConnectScript(templateString)
templateString = l.addGoLiveComponentIDAttribute(templateString)

templateDom, err := CreateDOMFromString(templateString)
sign(templateDom, l)
// Get the template defined on component
ts := l.component.TemplateHandler(l)

templateString, err = RenderNodeToString(templateDom)
// Prepare the template content adding
// golive specific
ts = l.addWSConnectScript(ts)
ts = l.addGoLiveComponentIDAttribute(ts)

componentTemplate, err := l.generateTemplate(templateString)
// Generate go std template
ct, err := l.generateTemplate(ts)
l.renderer.setTemplate(ct, ts)

l.renderer.setTemplate(componentTemplate)
// Calling component creation
l.component.Create(l)

// Creating children
l.CreateChildren()

l.IsCreated = true

l.notifyStage(Created)

return err
}

// Prepare 1.
func (l *LiveComponent) Prepare(updatesChannel *ComponentLifeCycle) error {
func (l *LiveComponent) CreateChildren() {
for _, child := range l.getChildrenComponents() {
_ = child.Create(l.life)
}
}

l.updatesChannel = updatesChannel
l.component.Prepare(l)
l.PrepareChildren()
// Mount 2. the component loading html
func (l *LiveComponent) Mount() error {

l.IsPrepared = true
if !l.IsCreated {
return fmt.Errorf("component need to be prepared")
}

return nil
}
l.notifyStage(WillMount)

func (l *LiveComponent) CreateChildren() {
for _, child := range l.getChildrenComponents() {
_ = child.Create()
}
l.component.BeforeMount(l)
l.component.Mounted(l)
l.MountChildren()
l.IsMounted = true

l.notifyStage(Mounted)

return nil
}

func (l *LiveComponent) MountChildren() {
Expand All @@ -125,29 +114,56 @@ func (l *LiveComponent) MountChildren() {
l.notifyStage(ChildrenMounted)
}

func (l *LiveComponent) PrepareChildren() {
l.notifyStage(WillPrepareChildren)
for _, child := range l.getChildrenComponents() {
_ = child.Prepare(l.updatesChannel)
// Render ...
func (l *LiveComponent) Render() (string, error) {
_, _, err := l.renderer.Render(l.component)

signPostRender(l.renderer.state.html, l)

_ = l.renderer.state.setHTML(l.renderer.state.html)

if err != nil {
return "", err
}
l.notifyStage(ChildrenPrepared)

return l.renderer.state.text, err
}

// Mount 2. the component loading html
func (l *LiveComponent) Mount() error {
func (l *LiveComponent) RenderChild(fn reflect.Value, _ ...reflect.Value) template.HTML {

if !l.IsPrepared {
return fmt.Errorf("component need to be prepared")
child, ok := fn.Interface().(*LiveComponent)

if !ok {
l.log(LogError, "child not a *golive.LiveComponent", nil)
return ""
}

l.notifyStage(WillMount)
render, err := child.Render()
if err != nil {
l.log(LogError, "render child: render", logEx{"error": err})
}

l.component.BeforeMount(l)
l.component.Mounted(l)
l.MountChildren()
l.IsMounted = true
return template.HTML(render)
}

l.notifyStage(Mounted)
// LiveRender render a new version of the component, and detect
// differences from the last render
// and sets the "new old" version of render
func (l *LiveComponent) LiveRender() (*Diff, error) {
return l.renderer.LiveRender(l)
}

// Kill ...
func (l *LiveComponent) Kill() error {

*l.life <- ComponentLifeTimeMessage{
Stage: WillUnmount,
Component: l,
}

l.Exited = true
l.component = nil
l.life = nil

return nil
}
Expand Down Expand Up @@ -204,62 +220,6 @@ func (l *LiveComponent) InvokeMethodInPath(path string, valuePath string) error
return nil
}

// Render ...
func (l *LiveComponent) Render() (string, error) {
text, _, err := l.renderer.Render(l.component)

if err != nil {
return "", err
}

return text, err
}

// LiveRender render a new version of the component, and detect
// differences from the last render
// and sets the "new old" version of render
func (l *LiveComponent) LiveRender() (*PatchBrowser, error) {
newRender, err := l.Render()

if err != nil {
return nil, err
}

om := NewPatchBrowser(l.Name)
om.Name = EventLiveDom

if l.renderer.state.text == newRender {
l.log(LogDebug, "render is identical with last", nil)
return om, nil
}

changeInstructions, err := GetDiffFromRawHTML(l.rendered, newRender)

if err != nil {
l.log(LogPanic, "there is a error in diff", logEx{"error": err})
}

for _, instruction := range changeInstructions {

selector, err := SelectorFromNode(instruction.Element)

if err != nil {
s, _ := RenderNodeToString(instruction.Element)
l.log(LogPanic, "there is a error in selector", logEx{"error": err, "element": s})
}

om.AddInstruction(PatchInstruction{
Name: EventLiveDom,
Type: strconv.Itoa(int(instruction.Type)),
Attr: instruction.Attr,
Content: instruction.Content,
Selector: selector,
})
}

return om, nil
}

var re = regexp.MustCompile(`<([a-z0-9]+)`)

func (l *LiveComponent) createUniqueName() string {
Expand All @@ -285,12 +245,10 @@ func (l *LiveComponent) getChildrenComponents() []*LiveComponent {
}

func (l *LiveComponent) notifyStage(ltu LifeTimeStage) {
go func() {
*l.updatesChannel <- ComponentLifeTimeMessage{
Stage: ltu,
Component: l,
}
}()
*l.life <- ComponentLifeTimeMessage{
Stage: ltu,
Component: l,
}
}

func (l *LiveComponent) addWSConnectScript(template string) string {
Expand All @@ -303,7 +261,6 @@ func (l *LiveComponent) addWSConnectScript(template string) string {
`
}

// TODO: improve this urgently
func (l *LiveComponent) addGoLiveComponentIDAttribute(template string) string {
found := re.FindString(template)
if found != "" {
Expand All @@ -313,24 +270,8 @@ func (l *LiveComponent) addGoLiveComponentIDAttribute(template string) string {
return template
}

// Kill ...
func (l *LiveComponent) Kill() error {

*l.updatesChannel <- ComponentLifeTimeMessage{
Stage: WillUnmount,
Component: l,
}

l.Exited = true
// Set all to nil to garbage collector act
l.component = nil
l.updatesChannel = nil
l.htmlTemplate = nil

// *l.updatesChannel <- ComponentLifeTimeMessage{
// Stage: Unmounted,
// Component: l,
// }

return nil
func (l *LiveComponent) generateTemplate(ts string) (*template.Template, error) {
return template.New(l.Name).Funcs(template.FuncMap{
"render": l.RenderChild,
}).Parse(ts)
}
17 changes: 10 additions & 7 deletions component_lifetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ package golive
type LifeTimeStage int

const (
WillMount LifeTimeStage = iota
WillCreate LifeTimeStage = iota
Created

WillMount

WillMountChildren
ChildrenMounted

Mounted

Rendered
Updated

WillUnmount
Unmounted

WillMountChildren
ChildrenMounted

WillPrepareChildren
ChildrenPrepared
)

type ComponentLifeTimeMessage struct {
Expand Down
Loading

0 comments on commit 43b83f8

Please sign in to comment.