123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package naffg
- import (
- "embed"
- "net/http"
- "strconv"
- webview2 "github.com/jchv/go-webview2"
- )
- type Application struct {
- viewport webview2.WebView
- options *Options
- backendMutex *http.ServeMux
- terminate chan bool
- }
- type Options struct {
- //Basic Settings
- Title string
- Width int
- Height int
- Resizable bool //Default is true
- InitiateAtCenter bool //Initiate the window at the center of the screen
- //WebApp Settings
- StartURI string //URI to be loaded in the webview on start, support data://, default is "http://localhost:36850"
- //Local App Settings
- UiRes *embed.FS //Go embed filesystem for UI resources (e.g. res/), leave empty to use external URI (webApp)
- UiResPreix string //Prefix for the UI resources, will trim the prefix before serving the resources (e.g. res/)
- //Advance Settings
- EventExchangePort int //Port for which the UI events will be exchanged with backend, default is 36850
- IconId int //Icon resource id
- Debug bool
- }
- // Create a new Application Window with the given options
- func NewApplication(options *Options) *Application {
- //Fill in the default values if not provided
- if options.Title == "" {
- options.Title = "New Application"
- }
- if options.Width == 0 {
- options.Width = 800
- }
- if options.Height == 0 {
- options.Height = 600
- }
- if options.EventExchangePort == 0 {
- options.EventExchangePort = 36850
- }
- if options.UiRes == nil && options.StartURI == "" {
- //Use a missing resource page
- options.StartURI = "data:text/html,<html><body><h1>Invalid Usage</h1></body></html>"
- }
- //Create the webview
- w := webview2.NewWithOptions(webview2.WebViewOptions{
- Debug: true,
- AutoFocus: true,
- WindowOptions: webview2.WindowOptions{
- Title: options.Title,
- Width: uint(options.Width),
- Height: uint(options.Height),
- IconId: 203, // icon resource id
- Center: options.InitiateAtCenter,
- },
- })
- //Create a http mux for backend
- mux := http.NewServeMux()
- app := &Application{
- viewport: w,
- options: options,
- backendMutex: mux,
- terminate: make(chan bool),
- }
- //Register the UI resources bundle if provided
- if options.UiRes != nil {
- mux.Handle("/", app.embedFsPrefixMiddleware(http.FileServer(http.FS(options.UiRes))))
- }
- return app
- }
- // Run the application
- // Note that this cannot be run in a goroutine. It will block the main thread
- // until the application is terminated
- func (app *Application) Run() {
- app.viewport.SetTitle(app.options.Title)
- if app.options.Resizable {
- app.viewport.SetSize(app.options.Width, app.options.Height, webview2.HintNone)
- } else {
- app.viewport.SetSize(app.options.Width, app.options.Height, webview2.HintFixed)
- }
- if app.options.StartURI != "" {
- app.viewport.Navigate(app.options.StartURI)
- } else {
- app.viewport.Navigate("http://localhost:36850")
- }
- //Start the backend server
- go func() {
- if err := http.ListenAndServe("localhost:"+strconv.Itoa(app.options.EventExchangePort), app.backendMutex); err != nil {
- panic(err)
- }
- }()
- //Run the webview
- defer app.viewport.Destroy()
- app.viewport.Run()
- }
- // Terminate the application
- func (app *Application) Terminate() {
- app.viewport.Destroy()
- }
|