fixup! wip: refactor: API
This commit is contained in:
parent
c6f21b194a
commit
888ac7d67d
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
@ -90,7 +89,7 @@ func run() error {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ui, err := terminal.StartUI(ctx, terminal.StartParams{
|
ui, err := terminal.NewUI(ctx, terminal.Params{
|
||||||
EventBus: bus,
|
EventBus: bus,
|
||||||
Dispatcher: func(cmd event.Command) {
|
Dispatcher: func(cmd event.Command) {
|
||||||
logger.Info("Command dispatched", "cmd", cmd.Name())
|
logger.Info("Command dispatched", "cmd", cmd.Name())
|
||||||
@ -112,18 +111,11 @@ func run() error {
|
|||||||
}
|
}
|
||||||
defer ui.Close()
|
defer ui.Close()
|
||||||
|
|
||||||
errUIClosed := errors.New("UI closed")
|
g.Go(func() error { return ui.Run(ctx) })
|
||||||
g.Go(func() error {
|
|
||||||
ui.Wait()
|
|
||||||
logger.Info("UI closed!")
|
|
||||||
return errUIClosed
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := g.Wait(); err == errUIClosed {
|
if err := g.Wait(); err == terminal.ErrUserClosed {
|
||||||
logger.Info("UI closed, exiting")
|
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
logger.Error("UI closed with error", "err", err)
|
|
||||||
return fmt.Errorf("errgroup.Wait: %w", err)
|
return fmt.Errorf("errgroup.Wait: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package terminal
|
|||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"maps"
|
"maps"
|
||||||
@ -46,7 +47,7 @@ type UI struct {
|
|||||||
clipboardAvailable bool
|
clipboardAvailable bool
|
||||||
rtmpURL, rtmpsURL string
|
rtmpURL, rtmpsURL string
|
||||||
buildInfo domain.BuildInfo
|
buildInfo domain.BuildInfo
|
||||||
doneC chan struct{}
|
appExitC chan error
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
|
|
||||||
// tview state
|
// tview state
|
||||||
@ -92,9 +93,9 @@ type ScreenCapture struct {
|
|||||||
Width, Height int
|
Width, Height int
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartParams contains the parameters for starting a new terminal user
|
// Params contains the parameters for starting a new terminal user
|
||||||
// interface.
|
// interface.
|
||||||
type StartParams struct {
|
type Params struct {
|
||||||
EventBus *event.Bus
|
EventBus *event.Bus
|
||||||
Dispatcher func(event.Command)
|
Dispatcher func(event.Command)
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
@ -103,8 +104,9 @@ type StartParams struct {
|
|||||||
Screen *Screen // Screen may be nil.
|
Screen *Screen // Screen may be nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartUI starts the terminal user interface.
|
// NewUI creates the user interface. Call [Run] on the *UI instance to block
|
||||||
func StartUI(ctx context.Context, params StartParams) (*UI, error) {
|
// until it is completed.
|
||||||
|
func NewUI(ctx context.Context, params Params) (*UI, error) {
|
||||||
app := tview.NewApplication()
|
app := tview.NewApplication()
|
||||||
|
|
||||||
var screen tcell.Screen
|
var screen tcell.Screen
|
||||||
@ -210,7 +212,7 @@ func StartUI(ctx context.Context, params StartParams) (*UI, error) {
|
|||||||
eventBus: params.EventBus,
|
eventBus: params.EventBus,
|
||||||
dispatch: params.Dispatcher,
|
dispatch: params.Dispatcher,
|
||||||
clipboardAvailable: params.ClipboardAvailable,
|
clipboardAvailable: params.ClipboardAvailable,
|
||||||
doneC: make(chan struct{}, 1),
|
appExitC: make(chan error, 1),
|
||||||
buildInfo: params.BuildInfo,
|
buildInfo: params.BuildInfo,
|
||||||
logger: params.Logger,
|
logger: params.Logger,
|
||||||
app: app,
|
app: app,
|
||||||
@ -236,8 +238,6 @@ func StartUI(ctx context.Context, params StartParams) (*UI, error) {
|
|||||||
app.SetInputCapture(ui.inputCaptureHandler)
|
app.SetInputCapture(ui.inputCaptureHandler)
|
||||||
app.SetAfterDrawFunc(ui.afterDrawHandler)
|
app.SetAfterDrawFunc(ui.afterDrawHandler)
|
||||||
|
|
||||||
go ui.run(ctx)
|
|
||||||
|
|
||||||
return ui, nil
|
return ui, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,23 +264,28 @@ func (ui *UI) renderAboutView() {
|
|||||||
ui.aboutView.AddItem(tview.NewTextView().SetDynamicColors(true).SetText("[grey]?[-] About"), 1, 0, false)
|
ui.aboutView.AddItem(tview.NewTextView().SetDynamicColors(true).SetText("[grey]?[-] About"), 1, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) run(ctx context.Context) {
|
var ErrUserClosed = errors.New("user closed UI")
|
||||||
|
|
||||||
|
// Run runs the user interface. It always returns a non-nil error, which will
|
||||||
|
// be [ErrUserClosed] if the user voluntarily closed the UI.
|
||||||
|
func (ui *UI) Run(ctx context.Context) error {
|
||||||
eventC := ui.eventBus.Register()
|
eventC := ui.eventBus.Register()
|
||||||
defer ui.eventBus.Deregister(eventC)
|
defer ui.eventBus.Deregister(eventC)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(ui.doneC)
|
err := ui.app.Run()
|
||||||
|
if err != nil {
|
||||||
if err := ui.app.Run(); err != nil {
|
|
||||||
ui.logger.Error("Error in UI run loop, exiting", "err", err)
|
ui.logger.Error("Error in UI run loop, exiting", "err", err)
|
||||||
}
|
}
|
||||||
|
ui.appExitC <- err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case evt, ok := <-eventC:
|
case evt, ok := <-eventC:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
// should never happen
|
||||||
|
return errors.New("event channel closed")
|
||||||
}
|
}
|
||||||
ui.app.QueueUpdateDraw(func() {
|
ui.app.QueueUpdateDraw(func() {
|
||||||
switch evt := evt.(type) {
|
switch evt := evt.(type) {
|
||||||
@ -307,12 +312,11 @@ func (ui *UI) run(ctx context.Context) {
|
|||||||
default:
|
default:
|
||||||
ui.logger.Warn("unhandled event", "event", evt)
|
ui.logger.Warn("unhandled event", "event", evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return ctx.Err()
|
||||||
case <-ui.doneC:
|
case err := <-ui.appExitC:
|
||||||
return
|
return cmp.Or(err, ErrUserClosed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -819,7 +823,7 @@ func (ui *UI) Close() {
|
|||||||
|
|
||||||
// Wait waits for the terminal user interface to finish.
|
// Wait waits for the terminal user interface to finish.
|
||||||
func (ui *UI) Wait() {
|
func (ui *UI) Wait() {
|
||||||
<-ui.doneC
|
<-ui.appExitC
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) addDestination() {
|
func (ui *UI) addDestination() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user