Build cross platform GUI apps with GO and HTML/JS/CSS (powered by Electron)

Overview

GoReportCard GoDoc Travis Coveralls

Thanks to go-astilectron build cross platform GUI apps with GO and HTML/JS/CSS. It is the official GO bindings of astilectron and is powered by Electron.

Demo

To see a minimal Astilectron app, checkout out the demo.

It uses the bootstrap and the bundler.

If you're looking for a minimalistic example, run go run example/main.go -v.

Real-life examples

Here's a list of awesome projects using go-astilectron (if you're using go-astilectron and want your project to be listed here please submit a PR):

  • go-astivid Video tools written in GO
  • GroupMatcher Program to allocate persons to groups while trying to fulfill all the given wishes as good as possible
  • ipeye-onvif ONVIF Search Tool
  • Stellite GUI Miner An easy to use GUI cryptocurrency miner for Stellite

Bootstrap

For convenience purposes, a bootstrap has been implemented.

The bootstrap allows you to quickly create a one-window application.

There's no obligation to use it, but it's strongly recommended.

If you decide to use it, read thoroughly the documentation as you'll have to structure your project in a specific way.

Bundler

Still for convenience purposes, a bundler has been implemented.

The bundler allows you to bundle your app for every os/arch combinations and get a nice set of files to send your users.

Quick start

WARNING: the code below doesn't handle errors for readibility purposes. However you SHOULD!

Import go-astilectron

To import go-astilectron run:

$ go get -u github.com/asticode/go-astilectron

Start go-astilectron

// Initialize astilectron
var a, _ = astilectron.New(log.New(os.Stderr, "", 0), astilectron.Options{
    AppName: "<your app name>",
    AppIconDefaultPath: "<your .png icon>", // If path is relative, it must be relative to the data directory
    AppIconDarwinPath:  "<your .icns icon>", // Same here
    BaseDirectoryPath: "<where you want the provisioner to install the dependencies>",
    VersionAstilectron: "<version of Astilectron to utilize such as `0.33.0`>",
    VersionElectron: "<version of Electron to utilize such as `4.0.1` | `6.1.2`>",
})
defer a.Close()

// Start astilectron
a.Start()

// Blocking pattern
a.Wait()

For everything to work properly we need to fetch 2 dependencies : astilectron and Electron. .Start() takes care of it by downloading the sources and setting them up properly.

In case you want to embed the sources in the binary to keep a unique binary you can use the NewDisembedderProvisioner function to get the proper Provisioner and attach it to go-astilectron with .SetProvisioner(p Provisioner). Or you can use the bootstrap and the bundler. Check out the demo to see how to use them.

Beware when trying to add your own app icon as you'll need 2 icons : one compatible with MacOSX (.icns) and one compatible with the rest (.png for instance).

If no BaseDirectoryPath is provided, it defaults to the executable's directory path.

The majority of methods are asynchronous which means that when executing them go-astilectron will block until it receives a specific Electron event or until the overall context is cancelled. This is the case of .Start() which will block until it receives the app.event.ready astilectron event or until the overall context is cancelled.

HTML paths

NB! All paths in HTML (and Javascript) must be relative, otherwise the files will not be found. To make this happen in React for example, just set the homepage property of your package.json to "./".

{ "homepage": "./" }

Create a window

// Create a new window
var w, _ = a.NewWindow("http://127.0.0.1:4000", &astilectron.WindowOptions{
    Center: astikit.BoolPtr(true),
    Height: astikit.IntPtr(600),
    Width:  astikit.IntPtr(600),
})
w.Create()

When creating a window you need to indicate a URL as well as options such as position, size, etc.

This is pretty straightforward except the astilectron.Ptr* methods so let me explain: GO doesn't do optional fields when json encoding unless you use pointers whereas Electron does handle optional fields. Therefore I added helper methods to convert int, bool and string into pointers and used pointers in structs sent to Electron.

Open the dev tools

When developing in JS, it's very convenient to debug your code using the browser window's dev tools:

// Open dev tools
w.OpenDevTools()

// Close dev tools
w.CloseDevTools()

Add listeners

// Add a listener on Astilectron
a.On(astilectron.EventNameAppCrash, func(e astilectron.Event) (deleteListener bool) {
    log.Println("App has crashed")
    return
})

// Add a listener on the window
w.On(astilectron.EventNameWindowEventResize, func(e astilectron.Event) (deleteListener bool) {
    log.Println("Window resized")
    return
})

Nothing much to say here either except that you can add listeners to Astilectron as well.

Play with the window

// Play with the window
w.Resize(200, 200)
time.Sleep(time.Second)
w.Maximize()

Check out the Window doc for a list of all exported methods

Send messages from GO to Javascript

Javascript

// This will wait for the astilectron namespace to be ready
document.addEventListener('astilectron-ready', function() {
    // This will listen to messages sent by GO
    astilectron.onMessage(function(message) {
        // Process message
        if (message === "hello") {
            return "world";
        }
    });
})

GO

// This will send a message and execute a callback
// Callbacks are optional
w.SendMessage("hello", func(m *astilectron.EventMessage) {
        // Unmarshal
        var s string
        m.Unmarshal(&s)

        // Process message
        log.Printf("received %s\n", s)
})

This will print received world in the GO output

Send messages from Javascript to GO

GO

// This will listen to messages sent by Javascript
w.OnMessage(func(m *astilectron.EventMessage) interface{} {
        // Unmarshal
        var s string
        m.Unmarshal(&s)

        // Process message
        if s == "hello" {
                return "world"
        }
        return nil
})

Javascript

// This will wait for the astilectron namespace to be ready
document.addEventListener('astilectron-ready', function() {
    // This will send a message to GO
    astilectron.sendMessage("hello", function(message) {
        console.log("received " + message)
    });
})

This will print "received world" in the Javascript output

Play with the window's session

// Clear window's HTTP cache
w.Session.ClearCache()

Handle several screens/displays

// If several displays, move the window to the second display
var displays = a.Displays()
if len(displays) > 1 {
    time.Sleep(time.Second)
    w.MoveInDisplay(displays[1], 50, 50)
}

Menus

// Init a new app menu
// You can do the same thing with a window
var m = a.NewMenu([]*astilectron.MenuItemOptions{
    {
        Label: astikit.StrPtr("Separator"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Normal 1")},
            {
                Label: astikit.StrPtr("Normal 2"),
                OnClick: func(e astilectron.Event) (deleteListener bool) {
                    log.Println("Normal 2 item has been clicked")
                    return
                },
            },
            {Type: astilectron.MenuItemTypeSeparator},
            {Label: astikit.StrPtr("Normal 3")},
        },
    },
    {
        Label: astikit.StrPtr("Checkbox"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Checked: astikit.BoolPtr(true), Label: astikit.StrPtr("Checkbox 1"), Type: astilectron.MenuItemTypeCheckbox},
            {Label: astikit.StrPtr("Checkbox 2"), Type: astilectron.MenuItemTypeCheckbox},
            {Label: astikit.StrPtr("Checkbox 3"), Type: astilectron.MenuItemTypeCheckbox},
        },
    },
    {
        Label: astikit.StrPtr("Radio"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Checked: astikit.BoolPtr(true), Label: astikit.StrPtr("Radio 1"), Type: astilectron.MenuItemTypeRadio},
            {Label: astikit.StrPtr("Radio 2"), Type: astilectron.MenuItemTypeRadio},
            {Label: astikit.StrPtr("Radio 3"), Type: astilectron.MenuItemTypeRadio},
        },
    },
    {
        Label: astikit.StrPtr("Roles"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Minimize"), Role: astilectron.MenuItemRoleMinimize},
            {Label: astikit.StrPtr("Close"), Role: astilectron.MenuItemRoleClose},
        },
    },
})

// Retrieve a menu item
// This will retrieve the "Checkbox 1" item
mi, _ := m.Item(1, 0)

// Add listener manually
// An OnClick listener has already been added in the options directly for another menu item
mi.On(astilectron.EventNameMenuItemEventClicked, func(e astilectron.Event) bool {
    log.Printf("Menu item has been clicked. 'Checked' status is now %t\n", *e.MenuItemOptions.Checked)
    return false
})

// Create the menu
m.Create()

// Manipulate a menu item
mi.SetChecked(true)

// Init a new menu item
var ni = m.NewItem(&astilectron.MenuItemOptions{
    Label: astikit.StrPtr("Inserted"),
    SubMenu: []*astilectron.MenuItemOptions{
        {Label: astikit.StrPtr("Inserted 1")},
        {Label: astikit.StrPtr("Inserted 2")},
    },
})

// Insert the menu item at position "1"
m.Insert(1, ni)

// Fetch a sub menu
s, _ := m.SubMenu(0)

// Init a new menu item
ni = s.NewItem(&astilectron.MenuItemOptions{
    Label: astikit.StrPtr("Appended"),
    SubMenu: []*astilectron.MenuItemOptions{
        {Label: astikit.StrPtr("Appended 1")},
        {Label: astikit.StrPtr("Appended 2")},
    },
})

// Append menu item dynamically
s.Append(ni)

// Pop up sub menu as a context menu
s.Popup(&astilectron.MenuPopupOptions{PositionOptions: astilectron.PositionOptions{X: astikit.IntPtr(50), Y: astikit.IntPtr(50)}})

// Close popup
s.ClosePopup()

// Destroy the menu
m.Destroy()

A few things to know:

  • when assigning a role to a menu item, go-astilectron won't be able to capture its click event
  • on MacOS there's no such thing as a window menu, only app menus therefore my advice is to stick to one global app menu instead of creating separate window menus

Tray

// New tray
var t = a.NewTray(&astilectron.TrayOptions{
    Image:   astikit.StrPtr("/path/to/image.png"),
    Tooltip: astikit.StrPtr("Tray's tooltip"),
})

// Create tray
t.Create()

// New tray menu
var m = t.NewMenu([]*astilectron.MenuItemOptions{
    {
        Label: astikit.StrPtr("Root 1"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Item 1")},
            {Label: astikit.StrPtr("Item 2")},
            {Type: astilectron.MenuItemTypeSeparator},
            {Label: astikit.StrPtr("Item 3")},
        },
    },
    {
        Label: astikit.StrPtr("Root 2"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Item 1")},
            {Label: astikit.StrPtr("Item 2")},
        },
    },
})

// Create the menu
m.Create()

// Change tray's image
time.Sleep(time.Second)
t.SetImage("/path/to/image-2.png")

Notifications

// Create the notification
var n = a.NewNotification(&astilectron.NotificationOptions{
	Body: "My Body",
	HasReply: astikit.BoolPtr(true), // Only MacOSX
	Icon: "/path/to/icon",
	ReplyPlaceholder: "type your reply here", // Only MacOSX
	Title: "My title",
})

// Add listeners
n.On(astilectron.EventNameNotificationEventClicked, func(e astilectron.Event) (deleteListener bool) {
	log.Println("the notification has been clicked!")
	return
})
// Only for MacOSX
n.On(astilectron.EventNameNotificationEventReplied, func(e astilectron.Event) (deleteListener bool) {
	log.Printf("the user has replied to the notification: %s\n", e.Reply)
	return
})

// Create notification
n.Create()

// Show notification
n.Show()

Dock (MacOSX only)

// Get the dock
var d = a.Dock()

// Hide and show the dock
d.Hide()
d.Show()

// Make the Dock bounce
id, _ := d.Bounce(astilectron.DockBounceTypeCritical)

// Cancel the bounce
d.CancelBounce(id)

// Update badge and icon
d.SetBadge("test")
d.SetIcon("/path/to/icon")

// New dock menu
var m = d.NewMenu([]*astilectron.MenuItemOptions{
    {
        Label: astikit.StrPtr("Root 1"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Item 1")},
            {Label: astikit.StrPtr("Item 2")},
            {Type: astilectron.MenuItemTypeSeparator},
            {Label: astikit.StrPtr("Item 3")},
        },
    },
        {
        Label: astikit.StrPtr("Root 2"),
        SubMenu: []*astilectron.MenuItemOptions{
            {Label: astikit.StrPtr("Item 1")},
            {Label: astikit.StrPtr("Item 2")},
        },
    },
})

// Create the menu
m.Create()

Dialogs

Add the following line at the top of your javascript file :

const { dialog } = require('electron').remote

Use the available methods.

Basic auth

// Listen to login events
w.OnLogin(func(i astilectron.Event) (username, password string, err error) {
	// Process the request and auth info
	if i.Request.Method == "GET" && i.AuthInfo.Scheme == "http://" {
		username = "username"
		password = "password"
	}
    return
})

Features and roadmap

  • custom branding (custom app name, app icon, etc.)
  • window basic methods (create, show, close, resize, minimize, maximize, ...)
  • window basic events (close, blur, focus, unresponsive, crashed, ...)
  • remote messaging (messages between GO and Javascript)
  • single binary distribution
  • multi screens/displays
  • menu methods and events (create, insert, append, popup, clicked, ...)
  • bootstrap
  • dialogs (open or save file, alerts, ...)
  • tray
  • bundler
  • session
  • accelerators (shortcuts)
  • dock
  • notifications
  • loader
  • file methods (drag & drop, ...)
  • clipboard methods
  • power monitor events (suspend, resume, ...)
  • desktop capturer (audio and video)
  • window advanced options (add missing ones)
  • window advanced methods (add missing ones)
  • window advanced events (add missing ones)
  • child windows

Cheers to

go-thrust which is awesome but unfortunately not maintained anymore. It inspired this project.

Issues
  • Provide a way to ease building cross-platform single binary distribution

    Provide a way to ease building cross-platform single binary distribution

    Related comments:

    • https://github.com/asticode/go-astilectron/issues/11#issuecomment-303970242
    • https://github.com/asticode/go-astilectron/issues/10#issuecomment-303819875
    enhancement waiting for PR 
    opened by asticode 30
  • Integrating go-astilectron into existing Electron project

    Integrating go-astilectron into existing Electron project

    Hello! Love the project. I am wondering if there is any way to start go-astilectron from the javascript side (specifically the electron main process) so that I can integrate go-astilectron into my projects that already have a javascript backend.

    I'm looking for these two things:

    1. The ability to create event handlers in javascript that can communicate with windows created in go-astilectron (for services that don't have good go libraries yet, or have already been implemented in the project's js).
    2. The ability to run the project by calling $ electron ./electron.js rather than running go-astilectron directly. (that way any standard electron bundler can be used, e.g: electron-builder, electron-forge, etc.)

    I've provided below an example of the kind of API I'm thinking of.

    Is any of this possible? From what I understand, astilectron seems a little "all-or-nothing" in this regard, but perhaps I'm missing something.

    Thanks in advance.

    Example The javascript:
    // electron.js (entry point for the application)
    
    import { start, getWindowsSync } from "astilectron";
    import { exec } from "child_process";
    import { ipcMain } from "electron";
    
    // setup astilectron. (javascript side)
    const port = start();
    
    // Launch go-astilectron. (go side, see below)
    let go = exec("./go_astilectron_project_binary", port);
    
    // `main` same as `mainWindow` in main.go.
    // Sync blocks until window is created.
    const [ main ] = getWindowsSync();
    
    ipcMain.on("handle in js", (message) => {
      console.debug(`received ${message} in js`);
      main.webContents.send("reply");
    });
    

    And the go code:

    //main.go (entry point for go)
    
    /**
      * Package main is the go-astilectron bindings for this app
      */
    package main
    
    import (
        "github.com/asticode/astilog"
        "github.com/asticode/go-astilectron"
    )
    
    func main() {
        var app, _ := astilectron.New(&astilectron.WindowOptions{})
        var mainWindow, _ := app.newWindow("file://<working dir>/app/index.html", nil)
        mainWindow.create()
        mainWindow.On("handle in go", func(m *astilectron.Message) {
            // Unmarshal
            var s string
            m.Unmarshal(&s)
    
            // Process message
            astilog.Debugf("received %s in go", s)
        })
    }
    
    // package.json
    {
        "name": "project-name",
        "scripts": {
            "start:dev": "electron ./electron.js"
        },
        "dependencies": {
            "astilectron": "<version number>",
            "electron": "<version number>"
        }
    }
    

    To run the project (in development mode), one would simply call:

    $ electron ./electron.js
    

    or

    node run start:dev
    
    question 
    opened by sbrow 24
  • RestoreAssets undefined on example 9 (bootstrap)

    RestoreAssets undefined on example 9 (bootstrap)

    The line 45 in "examples/9.bootstrap/main.go" is:

    RestoreAssets: RestoreAssets,
    

    But need be something like this:

    RestoreAssets: func(dir, name string) error {
        return nil
    },
    
    opened by paulo-coutinho 24
  • Zombie child process after close if debug window was opened

    Zombie child process after close if debug window was opened

    I'd been running into a problem for a while with an electron process being left running after closing the main window.

    This process rockets up from ~2% CPU while the main process is running, to ~25% after the applicatoin has "closed", which has a very detremental effect on the computer after it happens a few times.

    After a bit of experimentation, it seems to reliably happen after opening the debug panel, and then closing the main window.

    The core process shuts down, but it seems the debug window remains orphaned.

    I'm relatively new to using astillectron with bootstrap, is there a way to find the list of active windows as it shuts down? Similarly, it would be nice to have an event handler for when new windows are created, so that if they are created from the window (by JavaScript or otherwise) that the Go backend can be updated with their creation.

    Ideally an end solution would be that on close, the application should clean up all active windows, so that it doesn't leave zombie children behind.

    bug 
    opened by killerpd 22
  • Standalone binary instructions?

    Standalone binary instructions?

    I see that example 5 concerns single binary distributions, but I'm not sure what these commands do exactly:

    $ go generate examples/5.single_binary_distribution/main.go
    $ go run examples/5.single_binary_distribution/main.go examples/5.single_binary_distribution/vendor.go -v
    

    Does this just apply to the last example you've run? Where does it put the binary? Also, the go generate command works on one of my machines, but on another machine I get:

    bindata: Failed to stat input path '..\vendor': GetFileAttributesEx ..\vendor: The system cannot find the file specified.
    examples\5.single_binary_distribution\main.go:12: running "go-bindata": exit status 1
    

    It seems as though this machine doesn't create the go-astilectron\examples\vendor directory when running the examples for some reason. Both are Windows 10, Go 1.8.3.

    Separate question: running go install on any of the examples seems to output a standalone binary in my go\bin directory. Are these true standalone binaries? If so, what is the purpose of example 5? Also, if someone could give me a clearer idea of what the go-astilectron-bundler is for I'd be very grateful. Thanks!

    question 
    opened by spieglt 22
  • Using astilectron-bundler to compile executable files, there is only one GO file and icns, plist file in output_path, what is the reason

    Using astilectron-bundler to compile executable files, there is only one GO file and icns, plist file in output_path, what is the reason

    Using astilectron-bundler to compile executable files, there is only one GO file and icns, plist file in output_path, what is the reason

    question 
    opened by lengnuan-v 18
  • Can't end an app

    Can't end an app

    While I create a window for a url like "https://wx.qq.com" .if I close the app but the program doesn't end up. I try to find out the reason.Then I find the program bolcked in a.Wait(). so If I modify the function a.Stop()

    func (a *Astilectron) Stop() {
    	astilog.Debug("Stopping...")
    	a.canceller.Cancel()
    	close(a.channelQuit)
    	//	if a.channelQuit != nil {
    	//		close(a.channelQuit)
    	//		a.channelQuit = nil
    	//	}
    }
    

    a.Wait()

    func (a *Astilectron) Wait() {
    	//for {
    	astilog.Debug("wait for quit")
    	// select {
    	// case <-a.channelQuit:
    	// 	return
    	// }
    	select {
    	case _, ok := <-a.channelQuit:
    		if !ok {
    			a.channelQuit = nil
    		}
    		return
    	}
    	//}
    }
    

    It will not blolck and end up right now.But I don't clearly understand why the website is blocked.Maybe the channel need to close ,not set value nil.

    question need more information 
    opened by tmacychen 17
  • App crashes in Ubuntu 17.10

    App crashes in Ubuntu 17.10

    2018/02/26 22:59:42 debugger.go:497: continuing
    FATA[0000] running bootstrap failed: creating window failed: canceller.cancelled
    
    opened by MiyamuraMiyako 17
  • Load local resources(html/js/css) ?

    Load local resources(html/js/css) ?

    I got an empty window.

    var w, _ = a.NewWindow("index.html", &astilectron.WindowOptions{
    
    ├── index.html
    └── main.exe
    
    question 
    opened by ghost 16
  • TCP Connection Stream destroyed

    TCP Connection Stream destroyed

    After running my application, then leaving it open and idle for roughly 1-2 hours. It will randomly crash within that time frame and give the following errors. I have tested this twice now, both tests had the same results.

    1d99bdfa0f44d7fe99149429ff60444f a1c562114461eb9fe6b257b03426fa96

    bug 
    opened by ghost 16
  • Question about amount of event listeners

    Question about amount of event listeners

    This is a general question and i think this is not an issue in go-astilectron.

    I have my go application and with go-astilectron a React Application for the UI.

    For the go part i created an eventHandler which receives all the JS Events and then distributes them to the corresponding implementations. Simplified this looks like this:

    window.OnMessage(func(m *astilectron.EventMessage) interface{} {
    		event := events.GuiEvent{}
    		_ := m.Unmarshal(&event)
    
    		output, _ := dispatcher.dispatch(ctx, logger, event) // here is a handler function invoked based on the event identifier
    
    		outputEvent := events.NewBackendEvent(event.Name, output)
    		jsonOutput, _ := json.Marshal(outputEvent)
    
    		_ = window.SendMessage(string(jsonOutput))
    
    		return nil
    	})
    

    Next to that the go application is able to directly send events to javascript.

    On the JavaScript side i implemented an EventListener where i register callbacks for given event identifiers. Simplyfied this looks like this:

    public registerEventListener = (eventKey: string, callback: ListenerCallback): string => {
        const uuid = uuidv4()
    
        if (!this.listeners[eventKey]) this.listeners[eventKey] = {}
        this.listeners[eventKey][uuid] = callback
    
        return uuid
      }
    
      public removeEventListener = (eventKey: string, uuid: string) => {
        delete this.listeners[eventKey][uuid]
      }
    
      public triggerListener = (eventKey: string, data: any) => {
        if (!this.listeners.hasOwnProperty(eventKey)) {
          return
        }
    
        const callbacks = Object.keys(this.listeners[eventKey]).map((key) => this.listeners[eventKey][key])
        
        callbacks.map((callback) => callback(data))
      }
    

    Everytime my JS Code receives an event it looks in this EventListener for the callbacks registered for the event and invokes them:

    astilectron.onMessage(function (message: string) {
        let event: BackendEvent = JSON.parse(message)
        eventManager.triggerListener(event.name, event.data)
      })
    

    Everything works fine. But imagine an application where you can start worker processes in the UI and each one of them is running in a separate go routine in the go application sending status information to the JS application.

    When i for example start 50 or more of those processes the whole application has hickups, sometimes freezes and other ui events are not fired anymore (for example i want to start another one via button click). It seems like those X go routines in the go application are flooding the JS application with events and the application is not able to handle this properly.

    So my actual question is, is this "issue" a design issue of my own implementation and my bottleneck is somewhere in my own code? Or is go-astilection just not designed to be used for such use cases. Maybe there is a best practice for my use case together with go-astilectron?

    opened by bogdanfinn 2
  • Were someone able to make astilectron work with React?

    Were someone able to make astilectron work with React?

    I'm new to React, have built a project already using astilectron but with just vanilla js, I tried to use

     componentDidMount() {
              var astilectron = {};
            document.addEventListener('astilectron-ready', function() {
                // This will listen to messages sent by GO
                astilectron.onMessage(function(message) {
                    // Process message
                    if (message === "hello") {
                        alert(message);
                    }
                });
            });
          }
    

    But I get this on devtools console:

    Uncaught TypeError: e.onMessage is not a function
        at HTMLDocument.<anonymous> (App.js:27)
        at <anonymous>:50:22
        at WebFrame.e.startsWith.e.startsWith.WebFrame.<computed> [as _executeJavaScript] (electron/js2c/renderer_init.js:87)
        at electron/js2c/renderer_init.js:115
        at electron/js2c/renderer_init.js:99
        at EventEmitter.<anonymous> (electron/js2c/renderer_init.js:103)
        at EventEmitter.emit (events.js:315)
        at Object.onMessage (electron/js2c/renderer_init.js:91)
    

    Without the var astilectron = {}; I get astilectron is not defined on npm build. I'm not using bundler. Would love an example for how to use astilectron with react <3

    opened by BoladoLimited 10
  • Position window?

    Position window?

    Hey i see there is an option to center the window but is there an option to position the window at the bottom right? or top right?

    question 
    opened by Dontmindmes 3
  • Hide Top?

    Hide Top?

    Hey is it possible to hide this? https://i.imgur.com/YaP4hE1.png

    question 
    opened by Dontmindmes 1
  • unable to get electron objects, such as session, browserWindow

    unable to get electron objects, such as session, browserWindow

    Hi Probably I'm doing something in the wrong way, but this is what I want to achieve:

    I want to get a session, cookie, and some other objects available from the electron for the client JS

    In order to do so I've added const electron = require('electron');

    into index.js of my app. When I log the object, it only shows the following properties/methods:

    clipboard: (...)
    contextBridge: (...)
    crashReporter: (...)
    desktopCapturer: (...)
    ipcRenderer: (...)
    nativeImage: (...)
    shell: (...)
    webFrame: (...)
    deprecate: (...)
    get clipboard: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get contextBridge: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get crashReporter: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get desktopCapturer: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get ipcRenderer: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get nativeImage: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get shell: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get webFrame: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    get deprecate: ()=>{const t=e();return t.__esModule&&t.default?t.default:t}
    __proto__: Object
    

    tried to do this too const { session } = require('session') with no luck - object is undefined

    in the same timeconst path = require('path') works.

    in general, it would be nice to get some instructions on how to get electron modules available for client js

    I see that you have a lot of objects imported in the compiled code: output/darwin-amd64/mytest.app/Contents/MacOS/vendor/astilectron/index.js but I can not understand how to make it work (get access to them) on my js.

    p.s. The main reason why I need this - it looks like cookies are not always refreshed when I close the app, so when I reopen it again I see that it uses an old one, so to prevent this I want to call cookies.flushStore(). That is why I want to get the cookie from electron

    opened by dmitry84 2
  • obsolete documentation

    obsolete documentation

    PS C:\Ivan\proyectos\go\src\astilectron> go run main.go astikit: starting worker... Starting... Provisioning... Provisioning Astilectron... Removing directory C:\Users\INFORM2\AppData\Roaming\dsfgsdf\vendor\astilectron Downloading https://github.com/asticode/astilectron/archive/v<version of Astilectron to utilize such as 0.33.0>.zip into C:\Users\INFORM2\AppData\Roaming\dsfgsdf\vendor\astilectron-v<version of Astilectron to utilize such as 0.33.0>.zip Removing C:\Users\INFORM2\AppData\Roaming\dsfgsdf\vendor\astilectron-v<version of Astilectron to utilize such as 0.33.0>.zip... astikit: worker is now waiting... fatal error: all goroutines are asleep - deadlock!

    sadly, this works more like a virus removing, installing god-knows where and why.... my $path is ok. imposible to start the examples. basic guide don't works. follow https://medium.com/@asticode/how-to-add-a-gui-to-your-golang-app-in-5-easy-steps-c25c99d4d8e0 and more of the same. probably obsolete to old Go versions or before go.mod exist

    question 
    opened by IvanTejo-ymas 5
  • BrowserView with go-astilectron

    BrowserView with go-astilectron

    Hi there,

    I wanted to try and use go-astilectron to create an application that loads another website and adds additional functionality for it - it's a website that allows downloading mods for a game. Now, when loading the website directly in a NewWindow, I can see some JavaScript errors which seem to stem from JS files being loaded out of order (it loads fine in a <webview>). From what info I could gather, it looks like I should be using a <webview> tag or a BrowserView. <webview> is discouraged, so I tried looking up how to create a BrowserView with this package, but was unable to find anything. Is there a way of creating a BrowserView with go-astilectron or another workaround?

    Cheers,

    need work 
    opened by Rukenshia 4
  • Chrome DevTools extensions e.g. React / Vue DevTools

    Chrome DevTools extensions e.g. React / Vue DevTools

    What's the best way to load a Chrome extension in the Electron window?

    I've found the guide for using extensions in the Electron docs

    How can I adapt this in go-astilectron... maybe via Window.ExecuteJavaScript?

    question 
    opened by wickedst 4
  • how to use dialog?

    how to use dialog?

    I see a lot of issues solved with Dialog, But when I try const {dialog} = require('electron').remote; in main.js , It will prompt me TypeError: fs.existsSync is not a function,
    Where is the correct quote. Thanks.

    bug need work 
    opened by cosse 2
Owner
Quentin Renard
Freelance | Senior backend developer (GO)
Quentin Renard
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by Electron)

Thanks to go-astilectron build cross platform GUI apps with GO and HTML/JS/CSS. It is the official GO bindings of astilectron and is powered by Electr

Quentin Renard 4k Sep 22, 2021
Native Go (golang) Graphical Interface system (2D and 3D), built on GoKi tree framework

GoGi is part of the GoKi Go language (golang) full strength tree structure system (ki = 木 = tree in Japanese) package gi is a scenegraph-based 2D and

GoKi 937 Sep 23, 2021
A cross-platform app-development module for Go.

The cross-platform Go module for building apps (pronounced klo-va-seed). Usecases As a lightweight alternative to Electron Write your frontend and nat

Qlova Limited 78 Sep 5, 2021
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)

gowd Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs) How to use this library: Download and install nwjs Install this library g

Danny 325 Sep 19, 2021
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

webview 8.9k Sep 25, 2021
GPU based Electron on a diet

Muon is a lightweight alternative to Electron written in Golang in about ~300 LoC, using Ultralight instead of Chromium. Ultralight is a cross-platfor

V-X 2k Sep 19, 2021
Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

Terra Informatica Software, Inc 2.2k Sep 25, 2021
Cross-platform GUI for go is never this easy and clean.

gimu Strongly suggest NOT to use this project anymore, the auto-generated cgo wrapper of Nuklear has a random crash issue which is hard to fix (becaus

Allen Dang 64 Aug 25, 2021
Easy Go GUI wrapper for interactive manipulation of visual algorithms/backend code.

RenderView ================ Install: go get github.com/TheGrum/renderview Needs either Shiny (limited functionality), Gio, go-gtk, or gotk3. The latt

null 21 Sep 12, 2021
Platform-native GUI library for Go.

ui: platform-native GUI library for Go This is a library that aims to provide simple GUI software development in Go. It is based on my libui, a simple

Pietro Gagliardi 8k Sep 24, 2021
Go wrapper around the Iup GUI toolset

Iup Go Wrapper iup is a Go wrapper around the Iup GUI toolkit. The project was started on April 27, 2011. Fork https://github.com/grd/iup is a fork of

grd 24 Nov 27, 2020
An experimental Go cross platform UI library.

GXUI - A Go cross platform UI library. Notice: Unfortunately due to a shortage of hours in a day, GXUI is no longer maintained. If you're looking for

Google 4.4k Sep 16, 2021
Cross platform rapid GUI framework for golang based on Dear ImGui.

giu Cross platform rapid GUI framework for golang based on Dear ImGui and the great golang binding imgui-go. Any contribution (features, widgets, tuto

Allen Dang 1k Sep 17, 2021
Common library for Go GUI apps on Windows

winc Common library for Go GUI apps on Windows. It is for Windows OS only. This makes library smaller than some other UI libraries for Go.

Tad Vizbaras 104 Sep 19, 2021
Windows GUI framework for Go.

gform is an easy to use Windows GUI toolkit for Go It provides two approaches to create UI. 1. Pure code. gform.Init() mainWindow := gform.NewForm(ni

Allen Dang 263 Sep 9, 2021
Cross platform GUI in Go based on Material Design

About Fyne is an easy to use UI toolkit and app API written in Go. It is designed to build applications that run on desktop and mobile devices with a

Fyne.io 14.2k Sep 22, 2021
Build cross-platform modern desktop apps in Go + HTML5

Lorca A very small library to build modern HTML5 desktop apps in Go. It uses Chrome browser as a UI layer. Unlike Electron it doesn't bundle Chrome in

Serge Zaitsev 6.7k Sep 22, 2021
Flutter on Windows, MacOS and Linux - based on Flutter Embedding, Go and GLFW.

go-flutter - A package that brings Flutter to the desktop Purpose Flutter allows you to build beautiful native apps on iOS and Android from a single c

null 5k Sep 17, 2021
Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies

Dear ImGui (This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addit

omar 31.9k Sep 21, 2021