Coder Social home page Coder Social logo

maxence-charriere / go-app Goto Github PK

View Code? Open in Web Editor NEW
7.7K 153.0 352.0 232.27 MB

A package to build progressive web apps with Go programming language and WebAssembly.

Home Page: https://go-app.dev

License: MIT License

Go 97.06% JavaScript 2.26% CSS 0.34% Makefile 0.34%
go golang ui gui wasm awesome-go pwa

go-app's Introduction

GitHub actions Go Report Card GitHub release pkg.go.dev docs Twitter URL

Go-app is a package for building progressive web apps (PWA) with the Go programming language (Golang) and WebAssembly (Wasm).

Shaping a UI is done by using a declarative syntax that creates and compose HTML elements only by using the Go programing language.

It uses Go HTTP standard model.

An app created with go-app can out of the box runs in its own window, supports offline mode, and is SEO friendly.

Documentation (built with go-app)

go-app documentation

Install

go-app requirements:

go mod init
go get -u github.com/maxence-charriere/go-app/v9/pkg/app

Declarative syntax

Go-app uses a declarative syntax so you can write reusable component-based UI elements just by using the Go programming language.

Here is a Hello World component that takes an input and displays its value in its title:

type hello struct {
	app.Compo

	name string
}

func (h *hello) Render() app.UI {
	return app.Div().Body(
		app.H1().Body(
			app.Text("Hello, "),
			app.If(h.name != "",
				app.Text(h.name),
			).Else(
				app.Text("World!"),
			),
		),
		app.P().Body(
			app.Input().
				Type("text").
				Value(h.name).
				Placeholder("What is your name?").
				AutoFocus(true).
				OnChange(h.ValueTo(&h.name)),
		),
	)
}

Standard HTTP

Apps created with go-app complies with Go standard HTTP package interfaces.

func main() {
	// Components routing:
	app.Route("/", &hello{})
	app.Route("/hello", &hello{})
	app.RunWhenOnBrowser()

	// HTTP routing:
	http.Handle("/", &app.Handler{
		Name:        "Hello",
		Description: "An Hello World! example",
	})

	if err := http.ListenAndServe(":8000", nil); err != nil {
		log.Fatal(err)
	}
}

Getting started

Read the Getting Started document.

Built with go-app

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain go-app development. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

go-app's People

Contributors

a4913994 avatar azr avatar brittonhayes avatar cv avatar erickhun avatar haraldnordgren avatar jacktuck avatar kiyonlin avatar koddr avatar lijianying10 avatar maxence-charriere avatar mlctrez avatar mtausig avatar oderwat avatar pelly-ryu avatar ruanwenfeng avatar sg0hsmt avatar shanamaid avatar stevelr avatar talentlessguy avatar tcmits avatar tectiv3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-app's Issues

[Propose] View concept and navigations between views.

I proposed make a view concept. There are already window and component, but there is no view. A view likes the similar concept on MFC/android/IOS.
A view is the current render display layer of a window, a window should mount a view but not a component. A view interface will include component interface but should have more method i.e. Title() string. You can defines many views on a window but always only 1 will be rendered. A window has a navigation, a navigation is a stack of views. you can push a new view or pop a view or return to any the old view.

For example:

Suppose we have two views: LoginView, MainView.
When the window open, I mounted LoginView, and user could input name and password. When click the login button, we can switch it to MainView if he submit the correct name and password.

Handle keyboard event

I have a component whose content is supposed to change upon a event.
<div class = "MainScore MainCurrentScore" onclick = "UpdateScore">{{ .Current}}</div>
The following is the function:
func (s *Score) UpdateScore() {
s.Current = 5
app.Render(s)
}
I'm sure the rest of the go file works since the component actually can change upon mouse click. But if I change the element to
<div class = "MainScore MainCurrentScore" onkeydown = "UpdateScore">{{ .Current}}</div>
the component won't change upon keyboard press.
How to handle a keyboard event?

how can i call some Hello method from the main app menu (based on Hello example)

Hello, i would like to ask (based on your Hello example) how can i call some Hello method from the main app menu.
Let me illustrate this:

If i'll add a new menu item called "Reset" and also a struct method to call into the menu.go:

func (m *AppMainMenu) Render() string {
	return `
<menu>
    <menu label="app">
        <menuitem label="{{if .CustomTitle}}{{.CustomTitle}}{{else}}Custom item{{end}}" 
                  shortcut="ctrl+c" 
                  onclick="OnCustomMenuClick" 
                  icon="star.png"
                  separator="true"
                  disabled="{{.Disabled}}" />
        <menuitem label="Reset" 
                  shortcut="meta+r" 
                  onclick="OnReset" 
                  icon="star.png"
                  separator="true"
                  disabled="{{.Disabled}}" />
        <menuitem label="Quit" shortcut="meta+q" selector="terminate:" />        
    </menu>
    <WindowMenu />
</menu>
    `
}

func (m *AppMainMenu) OnReset() {
  log.Info("OnReset")
  hello.Reset()   // doesn't work
}

and also add a method to the Hello struct into Hello.go:


func (h *Hello) Reset() {
  h.Greeting = ""
  app.Render(h)
}

The code above wouldn't work.

I've tried to modify the app in a manner that i instantiate Hello struct into global var and try to call method of that instance directly, but alas, still no worky:


// hello.go

var obj Hello

...

func (h *Hello) Reset() {
  h.Greeting = ""
  app.Render(h)
}

...

func init() {
	// Registers the Hello component.
	// Allows the app to create a Hello component when it finds its declaration
	// into a HTML markup.
	app.RegisterComponent(&obj)
}


// menu.go

func (m *AppMainMenu) Render() string {
	return `
<menu>
    <menu label="app">
        <menuitem label="{{if .CustomTitle}}{{.CustomTitle}}{{else}}Custom item{{end}}" 
                  shortcut="ctrl+c" 
                  onclick="OnCustomMenuClick" 
                  icon="star.png"
                  separator="true"
                  disabled="{{.Disabled}}" />
        <menuitem label="Reset" 
                  shortcut="meta+r" 
                  onclick="OnReset" 
                  icon="star.png"
                  separator="true"
                  disabled="{{.Disabled}}" />
        <menuitem label="Quit" shortcut="meta+q" selector="terminate:" />        
    </menu>
    <WindowMenu />
</menu>
    `
}

...

func (m *AppMainMenu) OnReset() {
  log.Info("OnReset")
  obj.Reset()
}

So, can you give me an advice on how to just that?
Sorry if the question is lame, but it's not so obvious to me and maybe someone else will help this useful.

Application fail without logs

Hi,

I've made a small app using this (great) tool, and I get a strange bug.
If I build the app and start the executable (go build && ./client-macos), there's a prompt that open, with all the log in, and the real app (with nice macos UI). Application work well and logs are also stored in log file.

Troubles start when I start using macpack (go build && macpack build). App doesn't start and I get no logs in my logfile. I don't understand why.
Is there a special tricks to have logs? Many thanks!

GO-ENV

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/thomasp/Golang"
GORACE=""
GOROOT="/usr/local/opt/go/libexec"
GOTOOLDIR="/usr/local/opt/go/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/2n/1p_pny6x2p180gcj7kkbwz0c0000gn/T/go-build479332264=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
![Uploading Capture d’écran 2017-02-28 à 21.26.59.png…]()

DOM Access

Is it possible to get DOM access though w3c/standard APIs activeElement or any kind of low level API (i.e. like golang.org/x/net/html ) ?

Mobile performance?

I'm wondering how this will perform on iOS and Android once it's possible to build for those platforms. Is there any way to get a development build on mobile to see performance there, what parts are required if I wanted to try and work on it?

How to get a component as a composition

I have a big component with several compositions. As these small components are declared inside, how can I get one of them and modify the field as I want?
As I noticed, only one component can be mounted onto a window right? I tried to mount multiple components and only one of they showed up.

Example crashing right away after go build or go run

I tried to just go build the example project then execute the binary, but it crashes right after it starts. The weird thing is if I use macpack to build it then it doesn't crash. I'm guessing the app wrapper provides data where the raw build does not.

Go ENV

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/euforic/go"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.7.5/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.7.5/libexec/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/3x/0rnfwj_x1jz2p0gzh_gg7_600000gn/T/go-build912724629=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"

Crash Output

INFO  2017/01/30 14:00:47 driver.go:31: driver *mac.Driver is loaded
INFO  2017/01/30 14:00:47 component.go:62: main.Hello has been registered under the tag Hello
INFO  2017/01/30 14:00:47 component.go:62: main.AppMainMenu has been registered under the tag AppMainMenu
INFO  2017/01/30 14:00:47 component.go:62: main.WindowMenu has been registered under the tag WindowMenu
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7fffb3c24b52]

runtime stack:
runtime.throw(0x41a1554, 0x2a)
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/panic.go:566 +0x95
runtime.sigpanic()
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/sigpanic_unix.go:12 +0x2cc

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4141160, 0xc42004df20, 0x0)
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/cgocall.go:131 +0x110 fp=0xc42004def0 sp=0xc42004deb0
github.com/murlokswarm/mac._Cfunc_Driver_Run()
	??:0 +0x41 fp=0xc42004df20 sp=0xc42004def0
github.com/murlokswarm/mac.(*Driver).Run(0xc420010280)
	/Users/euforic/go/src/github.com/murlokswarm/mac/driver.go:56 +0x14 fp=0xc42004df28 sp=0xc42004df20
github.com/murlokswarm/app.Run()
	/Users/euforic/go/src/github.com/murlokswarm/app/app.go:43 +0x35 fp=0xc42004df40 sp=0xc42004df28
main.main()
	/Users/euforic/go/src/github.com/blevein/play/examples/mac/hello/main.go:31 +0x30 fp=0xc42004df48 sp=0xc42004df40
runtime.main()
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/proc.go:183 +0x1f4 fp=0xc42004dfa0 sp=0xc42004df48
runtime.goexit()
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc42004dfa8 sp=0xc42004dfa0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
	/usr/local/Cellar/go/1.7.5/libexec/src/runtime/asm_amd64.s:2086 +0x1

goroutine 5 [chan receive]:
github.com/murlokswarm/app.startUIScheduler()
	/Users/euforic/go/src/github.com/murlokswarm/app/ui.go:11 +0x51
created by github.com/murlokswarm/app.init.1
	/Users/euforic/go/src/github.com/murlokswarm/app/ui.go:17 +0x35

Show a second window

I implemented a second window as the following function. The following function will be called, and supposedly a window will show, when I clicked a menu item in menu bar. ScoreBoard is a component that has already been declared as global variable. When I click menu item, no window showed up. If I click a second up, an error will show as following:

1512240119312

This is the function:
func (m *MainMenu) OpenScoreBoard() {
ScoreWindow = app.NewWindow(app.Window{
Title: "Score Board",
MinWidth: 497,
MinHeight: 405,
MaxWidth: 497,
MaxHeight: 405,
BackgroundColor: "#EDC22F",
})
ScoreWindow.Mount(ScoreBoard)
}

Is there anything else I need to do in order to show a second window?

fatal error: unexpected signal during runtime execution

Hi,

I try to test the Hello example by myself:
image

And in the main() function, I add

win.Mount(&Hello{})

When I finish building and run it, I got this error below and the app exit automatically when clicking the text box. I also got the same error when testing the menu example in the /examples folder. Could you please help me find our the reason? Thanks!

image

SIGSEGV in conjunction with Http/TLS

It seems that calling the FilePicker in conjunction with the http.Client may sometimes cause a SIGSEGV. I have not found the cause of this problem, but here is a stack trace.


runtime stack:
runtime.throw(0x43c764f, 0x2a)
	/usr/local/opt/go/libexec/src/runtime/panic.go:605 +0x95
runtime.sigpanic()
	/usr/local/opt/go/libexec/src/runtime/signal_unix.go:351 +0x2b8

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x42fd5a0, 0xc42006be78, 0x40e609c)
	/usr/local/opt/go/libexec/src/runtime/cgocall.go:132 +0xe4 fp=0xc42006be48 sp=0xc42006be08 pc=0x4003fb4
github.com/murlokswarm/mac._Cfunc_Driver_Run()
	github.com/murlokswarm/mac/_obj/_cgo_gotypes.go:157 +0x41 fp=0xc42006be78 sp=0xc42006be48 pc=0x42e3461
github.com/murlokswarm/mac.(*Driver).Run(0xc420098ff0)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/mac/driver.go:54 +0x29 fp=0xc42006be88 sp=0xc42006be78 pc=0x42e5db9
github.com/murlokswarm/app.Run()
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/app/app.go:49 +0x35 fp=0xc42006bea0 sp=0xc42006be88 pc=0x41cd505
main.main()
	/Users/carl/Utveckling/Go/src/pass/main.go:99 +0x1e9 fp=0xc42006bf80 sp=0xc42006bea0 pc=0x42fa159
runtime.main()
	/usr/local/opt/go/libexec/src/runtime/proc.go:185 +0x20d fp=0xc42006bfe0 sp=0xc42006bf80 pc=0x402dbcd
runtime.goexit()
	/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42006bfe8 sp=0xc42006bfe0 pc=0x40595d1

goroutine 5 [syscall, locked to thread]:
github.com/murlokswarm/mac._Cfunc_Picker_NewFilePicker(0x5e1f710, 0x100)
	github.com/murlokswarm/mac/_obj/_cgo_gotypes.go:336 +0x45
github.com/murlokswarm/mac.newFilePicker(0xc420000100, 0xc420166010, 0x0)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/mac/picker.go:38 +0x198
github.com/murlokswarm/mac.(*Driver).NewElement(0xc420098ff0, 0x43869e0, 0xc420166020, 0xc420166020, 0x4013418)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/mac/driver.go:72 +0x231
github.com/murlokswarm/app.NewFilePicker(0x4000100, 0xc420166010, 0xc4222f3940, 0x4061aab)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/app/picker.go:15 +0xa0
main.(*File).ReadFile(0xc4203b0070)
	/Users/carl/Utveckling/Go/src/pass/file.go:141 +0x6e
reflect.Value.call(0x438a060, 0xc4203b0070, 0x1613, 0x43b6ab4, 0x4, 0xc4222f3cd8, 0x0, 0x0, 0x43381c0, 0x5, ...)
	/usr/local/opt/go/libexec/src/reflect/value.go:434 +0x906
reflect.Value.Call(0x438a060, 0xc4203b0070, 0x1613, 0xc4222f3cd8, 0x0, 0x0, 0xc42000e008, 0x13, 0x5)
	/usr/local/opt/go/libexec/src/reflect/value.go:302 +0xa4
github.com/murlokswarm/markup.callComponentMethod(0x438a060, 0xc4203b0070, 0x1613, 0xc422224300, 0xfb, 0x438a060, 0xc4203b0070)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/markup/handler.go:61 +0x3b3
github.com/murlokswarm/markup.HandleEvent(0xe811740889ae153f, 0x39789a14aafc6aa6, 0xc4201760b8, 0x8, 0xc422224300, 0xfb)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/markup/handler.go:33 +0x140
github.com/murlokswarm/app.HandleEvent(0xc4202b4000, 0x16d)
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/app/js.go:186 +0x12e
github.com/murlokswarm/mac.onJSCall.func1()
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/mac/js.go:14 +0x33
github.com/murlokswarm/app.startUIGoroutine()
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/app/ui.go:110 +0x47
created by github.com/murlokswarm/app.init.0
	/Users/carl/Utveckling/Go/src/github.com/murlokswarm/app/ui.go:103 +0xa0

goroutine 125 [IO wait]:
internal/poll.runtime_pollWait(0x479ff70, 0x72, 0x0)
	/usr/local/opt/go/libexec/src/runtime/netpoll.go:173 +0x57
internal/poll.(*pollDesc).wait(0xc42013a218, 0x72, 0xffffffffffffff00, 0x457c680, 0x45789f0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:85 +0xae
internal/poll.(*pollDesc).waitRead(0xc42013a218, 0xc420204000, 0x1000, 0x1000)
	/usr/local/opt/go/libexec/src/internal/poll/fd_poll_runtime.go:90 +0x3d
internal/poll.(*FD).Read(0xc42013a200, 0xc420204000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/internal/poll/fd_unix.go:125 +0x18a
net.(*netFD).Read(0xc42013a200, 0xc420204000, 0x1000, 0x1000, 0xc42013908b, 0xc420085180, 0x473b6c8)
	/usr/local/opt/go/libexec/src/net/fd_unix.go:202 +0x52
net.(*conn).Read(0xc42017c048, 0xc420204000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/net/net.go:176 +0x6d
crypto/tls.(*block).readFromUntil(0xc42015eba0, 0x5f083b0, 0xc42017c048, 0x5, 0xc42017c048, 0xc42224f9e0)
	/usr/local/opt/go/libexec/src/crypto/tls/conn.go:488 +0x95
crypto/tls.(*Conn).readRecord(0xc420084e00, 0x43d3a17, 0xc420084f20, 0x402e1bb)
	/usr/local/opt/go/libexec/src/crypto/tls/conn.go:590 +0xe0
crypto/tls.(*Conn).Read(0xc420084e00, 0xc420139000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
	/usr/local/opt/go/libexec/src/crypto/tls/conn.go:1134 +0x110
net/http.(*persistConn).Read(0xc420160000, 0xc420139000, 0x1000, 0x1000, 0xc42017e940, 0xc42019c058, 0x4053d30)
	/usr/local/opt/go/libexec/src/net/http/transport.go:1391 +0x140
bufio.(*Reader).fill(0xc4200e88a0)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:97 +0x11a
bufio.(*Reader).Peek(0xc4200e88a0, 0x1, 0x0, 0x0, 0x0, 0xc4200928a0, 0x0)
	/usr/local/opt/go/libexec/src/bufio/bufio.go:129 +0x3a
net/http.(*persistConn).readLoop(0xc420160000)
	/usr/local/opt/go/libexec/src/net/http/transport.go:1539 +0x185
created by net/http.(*Transport).dialConn
	/usr/local/opt/go/libexec/src/net/http/transport.go:1186 +0xa2e

goroutine 126 [select]:
net/http.(*persistConn).writeLoop(0xc420160000)
	/usr/local/opt/go/libexec/src/net/http/transport.go:1759 +0x165
created by net/http.(*Transport).dialConn
	/usr/local/opt/go/libexec/src/net/http/transport.go:1187 +0xa53```

onchange confusion

I've been playing with the sample app and it seems like the onchange event should fire each time the input field changes value not when enter is pressed. Would it make more sense to have an onsubmitor onconfirm event?

This is the awesome project, i'm looking forward to watching it evolve :)

Installation fails in OSX: error: use of undeclared identifier 'NSEventModifierFlagCommand'

Hello,
Thanks for the work and effort you have placed on developing this.
I am trying to use the software, but the installation fails.

$ go get github.com/murlokswarm/mac

github.com/murlokswarm/mac

../github.com/murlokswarm/mac/menu.m:138:41: error: use of undeclared identifier 'NSEventModifierFlagCommand'
../github.com/murlokswarm/mac/menu.m:140:41: error: use of undeclared identifier 'NSEventModifierFlagControl'
../github.com/murlokswarm/mac/menu.m:142:41: error: use of undeclared identifier 'NSEventModifierFlagOption'
../github.com/murlokswarm/mac/menu.m:144:41: error: use of undeclared identifier 'NSEventModifierFlagShift'
../github.com/murlokswarm/mac/menu.m:146:41: error: use of undeclared identifier 'NSEventModifierFlagFunction'

I do have OSX Version 10.11.6 (15G1421)

and Xcode Version 8.2.1 (8C1002)

Pass complex data through template?

So you can pass in simple values like strings to components through the tag attributes.
What if you want to pass in a map, or a struct?

For example:

type Data struct {
        FieldOne string
        FieldTwo int
        FieldThree []string
}

type Hello struct {
	ComplexData map[string]Data
}

func (h *Hello) Render() string {
	return `
<div>
    <h1>
        {{ range $key, $data := .ComplexData }}
            <span>{{ $key }}</span> 
            <World Data="{{ $data }}"></World>
        {{ end }}
    </h1>
</div>
    `
}

type World struct {
	Data Data
}

func (w *World) Render() string {
	return `
<span>
{{ range $field, $value := .Data }}
    <span>{{ $field }}: {{ $value }}</span>
{{ end }}
</span>
    `
}

func init() {
	app.RegisterComponent(&Hello{})
	app.RegisterComponent(&World{})
}

Am I missing something? Is it possible?
How can we pass composite structures to Components?
Thanks! :)

Arithmetic in Go templates

Hi,

I'd like to do some simple arithmetic calculations in html template. For example, {{.X}}+1. I googled about this and most people believe a new template function should be written and called whenever need to calculate. Here's a example link:

https://stackoverflow.com/questions/25689829/arithmetic-in-go-templates

However, since your code have this "Parse" process in the back. I don't know where to define a function like this. Could you please help me out?

Problem when drawing with dynamic parameter

Hi,

Sorry for the continuous questions. I have my struct Gobang here, where Board is the game board, and X,Y are the position of next step (where I will put chess on). I want to draw a circle as a chess on the position of (X, Y). So I use the template to dynamically draw it, since X and Y will change every time.

type Gobang struct {
  Board [16][16]int
  X, Y float64
}

I use the html code below: if .X and .Y are not 0, I will draw a circle on (.X, .Y).

{{if ne .X 0.0}}
      {{if ne .Y 0.0}}
          <h1>test</h1>
          <circle cx=".X" cy=".Y" r="12" fill="black" />
      {{end}}
{{end}}

But when I run it with setting g.X and g.Y to 45 in go function, I got nothing on my board. And when I change the html code into:
<circle cx="45" cy="45" r="12" fill="black" />
I can draw the circle normally on the right place.

I also tested below code:

      {{if eq .X 45.0}}
        {{if eq .Y 45.0}}
          <h1>RIGHT</h1>
        {{end}}
      {{end}}

And I can got the "RIGHT" on the app window.

So I cannot pass in a dynamic parameter when drawing a circle with svg in html? How could that be?

Thanks!

Traverse 2d array by template

UPDATE:
Fixed it. I should use
<h1>Equals 0</h1>
instead of
Equals 0.

Hi,

Another question here :) When I want to traverse the Board field in the struct, which is a 2d array, is the code below supposed to print out "Equals 0" or "Else" in terminal? But I got nothing. Could you please help me find out the reason? Thanks!

P.S. I tested this code in go playground, and it can print out normally.

{{$a := .Board}} {{range $a}} {{$elem := .}} {{range $elem}} {{if eq . 0}}Equals 0{{else}}Else{{end}} {{end}} {{end}}

handle applinks

I'm trying to handle application links but there doesn't seem to be any documentation on how to do it(i.e. capture the request and display a new scene/page). The app logs two errors:

Received an unexpected URL from the web process: 'file://www.w3schools.com/'
Received an invalid message "WebPageProxy.DecidePolicyForNavigationAction" from the web process.


package main

import "github.com/murlokswarm/app"

// Hello implements app.Componer interface.
type Hello struct {
	Greeting string
}

// Render returns the HTML markup that describes the appearance of the
// component.
// It supports standard HTML and extends it slightly to handle other component
// declaration or Golang callbacks.
// Can be templated following rules from https://golang.org/pkg/text/template.
func (h *Hello) Render() string {
	return `
<div class="WindowLayout" oncontextmenu="OnContextMenu">    
    <div class="HelloBox">
        <h1>
        <a href="//www.w3schools.com">Visit W3Schools</a>
Try it Yourself »

            Hello,
          <span>
                {{if .Greeting}}
                    {{html .Greeting}}
                {{else}}
                    World
                {{end}}
            </span>
        </h1>
        <input type="text"
               value="{{html .Greeting}}"
               placeholder="What is your name?"
               autofocus="true"
               onkeydown="Greeting"
               onkeyup="Greeting"
               onchange="OnInputChange" />
    </div>
</div>
    `
}

// OnInputChange is the handler called when an onchange event occurs.
func (h *Hello) OnInputChange(arg app.ChangeArg) {
	app.Render(h) // Tells the app to update the rendering of the component.
}

// OnContextMenu is the handler called when an oncontextmenu event occurs.
func (h *Hello) OnContextMenu() {
	ctxmenu := app.NewContextMenu()
	ctxmenu.Mount(&AppMainMenu{})
}

func init() {
	// Registers the Hello component.
	// Allows the app to create a Hello component when it finds its declaration
	// into a HTML markup.
	app.RegisterComponent(&Hello{})
}

[ Query for Ubuntu 16.04]

Is it available for Ubuntu 16.04 LTS ? Plus, in case you need UI/UX designing/development work, I am willing to contribute.

More examples

It would be great to include more links to tutorials/blog posts from people using murlok app to create desktop applications. Do you know of any more resources like that?

Same program with different performance in different directory

I'm working on MacOS High Sierra (10.13.1). Both two folders lie within $GOPATH/src, and $GOPATH is under my home directory. I write the code in one folder first and it runs perfectly normal (go build then ./foldername). Then I created a new folder in $GOPATH/src with different name. I copied all files in the original folder by control+c and pasted it into the new folder by control+v. The new folder can build but the window won't show up. Does you have any clue why this may happen?

This is the information in command line if I try to run the new folder:
Mengxins-MBP:tt zhangmengxin$ ./tt
INFO 2017/12/01 18:00:41 driver.go:57: driver *mac.Driver is loaded
INFO 2017/12/01 18:00:41 component.go:62: main.Game2048 has been registered under the tag
Game2048

This is the information in command line if I try to run the old folder:
Mengxins-MBP:test zhangmengxin$ ./test
INFO 2017/12/01 18:04:59 driver.go:57: driver *mac.Driver is loaded
INFO 2017/12/01 18:04:59 component.go:62: main.Game2048 has been registered under the tag Game2048

UPDATE: It turns out that I don't even need to move the file... The program performs differently even if I just change the folder name.

Running in a browser

It looks like the project is made specifically for native deployments, I'm wondering if it's feasible to support web deployments as well even if it's limited in which browsers would be supported. Would this be possible using something like gopherjs to run the go code in the browser?

Feature Proposal: Intents

We need a way to allow an App to communicate with another app.
This is because a good User Experience requires the ability for the User to see two windows at once.
But its also a good pattern of modularity, and also allows you to send things to Application outside of your Apps.

Url-scheme is a pretty good way to model this, because you can add an action and the data to the URL.

Use Cases:
Calling external Apps.
For example if you have a google maps URL in your app, when the user clicks it you want it to open Google Maps (if its installed) OR open the google maps web page.

Calling your own Apps.
Likewise, if a user is sent an email with a link, you want them pressing the link to either open your application (if its installed) or fallback to open the your web site.

If the called App is already open, it should it open a new Window ? Not sure..

All Golang based frameworks can use this. QT, WebViews, Shiny on Desktops and Mobiles.
I think it should be written as a package, so other golang GUI frameworks can leverage it.

I started to write IOS code for this here:
https://github.com/gu-io/gu-x/tree/master/_examples/gui-intents/osx

Writing implementations for Windows, IOS, Android, etc should not be too hard.
For a developer, it can be agnostic to OS and just work.

Is this something we want to use in murlok ?

DOMElement is incomplete

A dom element has sets/slices of attributes not just one. An attribute can have different keys than "id", "class" and value" (e.g. data-xyz, hidden, label etc..) along with other properties.

I would propose to bring it more in line with x/html to better represent the structure of a html node. We may exclude the relationships (Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node) if murlokswarm is not interested to serialize the html(though I think it would be quite handy).


type Node struct {
    Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
    Type      NodeType
    DataAtom  atom.Atom
    Data      string
    Namespace string
    Attr      []Attribute
}

type Attribute struct {
    Namespace, Key, Val string
}

Render was called before OnMount

I think OnMount should be called once on app.Mount called and before Render. And I think document the sequence of events is very useful.

Render keyboard events (KeyboardEvent)

I'm building an app that I would like to control remotely.Thus the question: Is it possible to inject/render keyboard events( KeyUp, KeyDown etc.) in the current context/page ? Basically once I render the page I also need to "navigate" using the keyboard but the commands are received through a separate Go routine by various means(i.e. tcp/ip>), not though direct input on the application itself(e.g. keyboard of the machine where the application is actually running).

Deregistering components

I noticed that that my applications memory goes incrementally up as I load components. Are the components kept in memory once loaded? Is there some way to free the memory if I know that I will use one component only at load?

Form markup

Hi,

I've made a small app available here https://github.com/updemia/client-macos but I've some strange thing.

On app startup, the updemia.app is open by the os browser, showing all assets files. I've find how to avoid this, removing the

markup. But then, app crash at startup.

Any idea ?

High Sierra Compatibility

First let me say thank you, this is a great project and I am very grateful for all the time you must have put into it.

Should this project be runnable on High Sierra? I can run it in Sierra but it crashes when I run it on High Sierra. I know your readme only lists Sierra but I'm hoping there is a way to make this work.

Please let me know if there is anything I can do to help or if you need any more info about my system.

(My machine has a TouchBar incase that is relevant but I tried the fix that worked in the previous crash on run issue #15 go build -ldflags -s)

Thank you,

System Info

screen shot 2017-10-24 at 1 02 19 pm

Go ENV

GOARCH="amd64"
GOBIN="/Users/charles/geeK/go/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/charles/geeK/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/wz/gvlmt8yx7vx3gcs_7c7m6bg80000gn/T/go-build782246593=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

To Replicate

pyrE:fenwickelliott charles$ git clone https://github.com/murlokswarm/examples.git
Cloning into 'examples'...
remote: Counting objects: 117, done.
remote: Total 117 (delta 0), reused 0 (delta 0), pack-reused 117
Receiving objects: 100% (117/117), 3.55 MiB | 1.20 MiB/s, done.
Resolving deltas: 100% (46/46), done.
pyrE:fenwickelliott charles$ cd examples/mac/hello
pyrE:hello charles$ go build
pyrE:hello charles$ ./hello

Output

INFO  2017/10/24 13:16:48 driver.go:57: driver *mac.Driver is loaded
INFO  2017/10/24 13:16:48 component.go:62: main.Hello has been registered under the tag Hello
INFO  2017/10/24 13:16:48 component.go:62: main.AppMainMenu has been registered under the tag AppMainMenu
INFO  2017/10/24 13:16:48 component.go:62: main.WindowMenu has been registered under the tag WindowMenu
SIGTRAP: trace trap
PC=0x7fff3aad95af m=4 sigcode=1
signal arrived during cgo execution

goroutine 5 [syscall, locked to thread]:
runtime.cgocall(0x4193b30, 0xc42010bcb0, 0xc42010bcd8)
	/usr/local/go/src/runtime/cgocall.go:132 +0xe4 fp=0xc42010bc80 sp=0xc42010bc40 pc=0x4004534
github.com/murlokswarm/mac._Cfunc_Window_CallJS(0x5f016f0, 0x4504b80)
	github.com/murlokswarm/mac/_obj/_cgo_gotypes.go:435 +0x41 fp=0xc42010bcb0 sp=0xc42010bc80 pc=0x4187fb1
github.com/murlokswarm/mac.(*window).Mount.func1(0x5f016f0, 0x4504b80)
	/Users/charles/geeK/go/src/github.com/murlokswarm/mac/window.go:124 +0x6a fp=0xc42010bce8 sp=0xc42010bcb0 pc=0x41908ba
github.com/murlokswarm/mac.(*window).Mount(0xc420140000, 0x43090c0, 0xc420010760)
	/Users/charles/geeK/go/src/github.com/murlokswarm/mac/window.go:124 +0x2f2 fp=0xc42010bdb0 sp=0xc42010bce8 pc=0x418e482
main.newMainWindow(0xc42000e038, 0x4309080)
	/Users/charles/geek/go/src/fenwickelliott/examples/mac/hello/main.go:52 +0xe6 fp=0xc42010bf60 sp=0xc42010bdb0 pc=0x4192a76
main.main.func1()
	/Users/charles/geek/go/src/fenwickelliott/examples/mac/hello/main.go:24 +0x8c fp=0xc42010bf98 sp=0xc42010bf60 pc=0x4192c9c
github.com/murlokswarm/mac.onLaunch.func1()
	/Users/charles/geeK/go/src/github.com/murlokswarm/mac/driver.go:120 +0x35 fp=0xc42010bfa8 sp=0xc42010bf98 pc=0x418fea5
github.com/murlokswarm/app.startUIGoroutine()
	/Users/charles/geeK/go/src/github.com/murlokswarm/app/ui.go:110 +0x47 fp=0xc42010bfe0 sp=0xc42010bfa8 pc=0x417f177
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42010bfe8 sp=0xc42010bfe0 pc=0x4058e21
created by github.com/murlokswarm/app.init.0
	/Users/charles/geeK/go/src/github.com/murlokswarm/app/ui.go:103 +0xa0

goroutine 1 [syscall, locked to thread]:
github.com/murlokswarm/mac._Cfunc_Driver_Run()
	github.com/murlokswarm/mac/_obj/_cgo_gotypes.go:157 +0x41
github.com/murlokswarm/mac.(*Driver).Run(0xc420080bd0)
	/Users/charles/geeK/go/src/github.com/murlokswarm/mac/driver.go:54 +0x29
github.com/murlokswarm/app.Run()
	/Users/charles/geeK/go/src/github.com/murlokswarm/app/app.go:49 +0x35
main.main()
	/Users/charles/geek/go/src/fenwickelliott/examples/mac/hello/main.go:35 +0x48

rax    0xd1b4000
rbx    0x70000247dd40
rcx    0x10000000000
rdx    0x103
rdi    0x12068
rsi    0x100
rbp    0x70000247dcf0
rsp    0x70000247dcc0
r8     0x4502bc0
r9     0x40
r10    0x4502bb8
r11    0xffffffffffffffff
r12    0x504a9b8
r13    0x70000247dda8
r14    0x70000247dd00
r15    0x504a9b8
rip    0x7fff3aad95af
rflags 0x246
cs     0x2b
fs     0x0
gs     0x0

Change class upon event

If it's possible to change a class of a div upon event?
`

2

As I tried this does not work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.