Files
soft_quay/app-modern/cmd/softbox/main.go
T

166 lines
4.6 KiB
Go

package main
import (
"context"
"errors"
"log"
"os"
"gioui.org/app"
"gioui.org/op"
"gioui.org/unit"
"softbox.local/app-modern/platform/windows"
softboxgio "softbox.local/app-modern/ui/gio"
"softbox.local/core"
"softbox.local/core/application"
)
const applicationEventCapacity = 32
func main() {
if handled, err := acknowledgeInternalUpdateHealth(os.Args[1:]); handled {
if err != nil {
log.Printf("%s internal update health failed: %v", core.ProductName, err)
os.Exit(1)
}
}
go func() {
if err := run(); err != nil {
log.Printf("%s stopped: %v", core.ProductName, err)
}
os.Exit(0)
}()
app.Main()
}
func run() error {
return runWithLoaders(
application.UnconfiguredCatalogLoader{},
application.UnconfiguredAuthorizationLoader{},
)
}
func runWithCatalogLoader(loader application.CatalogSnapshotLoader) error {
return runWithLoaders(loader, application.UnconfiguredAuthorizationLoader{})
}
func runWithLoaders(
loader application.CatalogSnapshotLoader,
authorizationLoader application.AuthorizationSnapshotLoader,
) error {
return runWithCompositions(loader, authorizationLoader, nil)
}
func runWithCompositions(
loader application.CatalogSnapshotLoader,
authorizationLoader application.AuthorizationSnapshotLoader,
licenseImport *application.LicenseImport,
) error {
platform := windows.New()
window := new(app.Window)
window.Option(
app.Title(core.ProductName),
app.Size(unit.Dp(1080), unit.Dp(720)),
)
theme := softboxgio.NewTheme()
shell := softboxgio.NewAppShell(string(platform.Edition()))
runtime := application.NewRuntime(applicationEventCapacity)
relay, err := application.NewEventRelay(applicationEventCapacity)
if err != nil {
return err
}
eventContext, cancelEvents := context.WithCancel(context.Background())
pumpDone := make(chan error, 1)
go func() {
pumpDone <- application.PumpEvents(
eventContext,
runtime.Events(),
relay,
window.Invalidate,
)
}()
catalogDone := startCatalogBootstrap(eventContext, runtime, loader)
authorizationDone := startAuthorizationBootstrap(eventContext, runtime, authorizationLoader)
defer func() {
cancelEvents()
runtime.Close()
relay.Close()
if bootstrapErr := <-catalogDone; bootstrapErr != nil &&
!errors.Is(bootstrapErr, context.Canceled) &&
!errors.Is(bootstrapErr, application.ErrCatalogSourceUnconfigured) &&
!errors.Is(bootstrapErr, application.ErrRuntimeClosed) &&
!errors.Is(bootstrapErr, application.ErrEventRelayClosed) {
log.Printf("%s catalog bootstrap failed", core.ProductName)
}
if authorizationErr := <-authorizationDone; authorizationErr != nil &&
!errors.Is(authorizationErr, context.Canceled) &&
!errors.Is(authorizationErr, application.ErrAuthorizationSourceUnconfigured) &&
!errors.Is(authorizationErr, application.ErrRuntimeClosed) &&
!errors.Is(authorizationErr, application.ErrEventRelayClosed) {
log.Printf("%s authorization bootstrap failed", core.ProductName)
}
if pumpErr := <-pumpDone; pumpErr != nil &&
!errors.Is(pumpErr, context.Canceled) &&
!errors.Is(pumpErr, application.ErrEventRelayClosed) {
log.Printf("application event pump stopped: %v", pumpErr)
}
}()
var operations op.Ops
importing := make(chan struct{}, 1)
for {
switch event := window.Event().(type) {
case app.DestroyEvent:
return event.Err
case app.FrameEvent:
if err := relay.Drain(shell.ApplyEvent); err != nil {
log.Printf("apply application event: %v", err)
}
gtx := app.NewContext(&operations, event)
shell.Layout(gtx, theme)
if shell.TakeLicenseImportRequest() && licenseImport != nil {
select {
case importing <- struct{}{}:
go func() {
defer func() { <-importing }()
if importErr := licenseImport.Run(eventContext); importErr != nil &&
!errors.Is(importErr, context.Canceled) &&
!errors.Is(importErr, application.ErrRuntimeClosed) &&
!errors.Is(importErr, application.ErrEventRelayClosed) {
log.Printf("%s license import failed", core.ProductName)
}
}()
default:
}
}
event.Frame(gtx.Ops)
}
}
}
func startCatalogBootstrap(
ctx context.Context,
runtime *application.Runtime,
loader application.CatalogSnapshotLoader,
) <-chan error {
done := make(chan error, 1)
go func() {
done <- application.NewCatalogBootstrap(loader, runtime).Run(ctx)
}()
return done
}
func startAuthorizationBootstrap(
ctx context.Context,
runtime *application.Runtime,
loader application.AuthorizationSnapshotLoader,
) <-chan error {
done := make(chan error, 1)
go func() {
done <- application.NewAuthorizationBootstrap(loader, runtime).Run(ctx)
}()
return done
}