feat: about
This commit is contained in:
parent
4e3a72893b
commit
f359dcaac5
49
app/app.go
49
app/app.go
@ -14,32 +14,34 @@ import (
|
||||
"git.netflux.io/rob/octoplex/terminal"
|
||||
)
|
||||
|
||||
const uiUpdateInterval = 2 * time.Second
|
||||
// RunParams holds the parameters for running the application.
|
||||
type RunParams struct {
|
||||
Config config.Config
|
||||
DockerClient container.DockerClient
|
||||
ClipboardAvailable bool
|
||||
BuildInfo domain.BuildInfo
|
||||
Logger *slog.Logger
|
||||
}
|
||||
|
||||
// Run starts the application, and blocks until it exits.
|
||||
func Run(
|
||||
ctx context.Context,
|
||||
cfg config.Config,
|
||||
dockerClient container.DockerClient,
|
||||
clipboardAvailable bool,
|
||||
logger *slog.Logger,
|
||||
) error {
|
||||
state := new(domain.AppState)
|
||||
applyConfig(cfg, state)
|
||||
func Run(ctx context.Context, params RunParams) error {
|
||||
state := newStateFromRunParams(params)
|
||||
logger := params.Logger
|
||||
|
||||
ui, err := terminal.StartActor(ctx, terminal.StartActorParams{
|
||||
ClipboardAvailable: clipboardAvailable,
|
||||
ClipboardAvailable: params.ClipboardAvailable,
|
||||
BuildInfo: params.BuildInfo,
|
||||
Logger: logger.With("component", "ui"),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("start tui: %w", err)
|
||||
return fmt.Errorf("start terminal user interface: %w", err)
|
||||
}
|
||||
defer ui.Close()
|
||||
|
||||
updateUI := func() { ui.SetState(*state) }
|
||||
updateUI()
|
||||
|
||||
containerClient, err := container.NewClient(ctx, dockerClient, logger.With("component", "container_client"))
|
||||
containerClient, err := container.NewClient(ctx, params.DockerClient, logger.With("component", "container_client"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("new container client: %w", err)
|
||||
}
|
||||
@ -70,8 +72,9 @@ func Run(
|
||||
})
|
||||
defer mp.Close()
|
||||
|
||||
uiTicker := time.NewTicker(uiUpdateInterval)
|
||||
defer uiTicker.Stop()
|
||||
const uiUpdateInterval = 2 * time.Second
|
||||
uiUpdateT := time.NewTicker(uiUpdateInterval)
|
||||
defer uiUpdateT.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
@ -89,7 +92,7 @@ func Run(
|
||||
case terminal.CommandQuit:
|
||||
return nil
|
||||
}
|
||||
case <-uiTicker.C:
|
||||
case <-uiUpdateT.C:
|
||||
updateUI()
|
||||
case serverState := <-srv.C():
|
||||
applyServerState(serverState, state)
|
||||
@ -120,13 +123,17 @@ func applyMultiplexerState(mpState multiplexer.State, appState *domain.AppState)
|
||||
}
|
||||
}
|
||||
|
||||
// applyConfig applies the configuration to the app state.
|
||||
func applyConfig(cfg config.Config, appState *domain.AppState) {
|
||||
appState.Destinations = make([]domain.Destination, 0, len(cfg.Destinations))
|
||||
for _, dest := range cfg.Destinations {
|
||||
appState.Destinations = append(appState.Destinations, domain.Destination{
|
||||
// newStateFromRunParams creates a new app state from the run parameters.
|
||||
func newStateFromRunParams(params RunParams) *domain.AppState {
|
||||
var state domain.AppState
|
||||
|
||||
state.Destinations = make([]domain.Destination, 0, len(params.Config.Destinations))
|
||||
for _, dest := range params.Config.Destinations {
|
||||
state.Destinations = append(state.Destinations, domain.Destination{
|
||||
Name: dest.Name,
|
||||
URL: dest.URL,
|
||||
})
|
||||
}
|
||||
|
||||
return &state
|
||||
}
|
||||
|
@ -6,6 +6,13 @@ import "time"
|
||||
type AppState struct {
|
||||
Source Source
|
||||
Destinations []Destination
|
||||
BuildInfo BuildInfo
|
||||
}
|
||||
|
||||
// BuildInfo holds information about the build.
|
||||
type BuildInfo struct {
|
||||
GoVersion string
|
||||
Version string
|
||||
}
|
||||
|
||||
// Source represents the source, currently always the mediaserver.
|
||||
|
20
main.go
20
main.go
@ -7,6 +7,7 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
|
||||
"git.netflux.io/rob/octoplex/app"
|
||||
@ -73,12 +74,23 @@ func run(ctx context.Context) error {
|
||||
return fmt.Errorf("new docker client: %w", err)
|
||||
}
|
||||
|
||||
buildInfo, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return fmt.Errorf("read build info: %w", err)
|
||||
}
|
||||
|
||||
return app.Run(
|
||||
ctx,
|
||||
cfg,
|
||||
dockerClient,
|
||||
clipboardAvailable,
|
||||
logger,
|
||||
app.RunParams{
|
||||
Config: cfg,
|
||||
DockerClient: dockerClient,
|
||||
ClipboardAvailable: clipboardAvailable,
|
||||
BuildInfo: domain.BuildInfo{
|
||||
GoVersion: buildInfo.GoVersion,
|
||||
Version: buildInfo.Main.Version,
|
||||
},
|
||||
Logger: logger,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ type Actor struct {
|
||||
pages *tview.Pages
|
||||
ch chan action
|
||||
commandCh chan Command
|
||||
buildInfo domain.BuildInfo
|
||||
logger *slog.Logger
|
||||
sourceViews sourceViews
|
||||
destView *tview.Table
|
||||
@ -45,6 +46,7 @@ type StartActorParams struct {
|
||||
ChanSize int
|
||||
Logger *slog.Logger
|
||||
ClipboardAvailable bool
|
||||
BuildInfo domain.BuildInfo
|
||||
}
|
||||
|
||||
// StartActor starts the terminal user interface actor.
|
||||
@ -110,7 +112,8 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
|
||||
aboutView.SetDirection(tview.FlexRow)
|
||||
aboutView.SetBorder(true)
|
||||
aboutView.SetTitle("Actions")
|
||||
aboutView.AddItem(tview.NewTextView().SetText("[C] Copy ingress URL"), 1, 0, false)
|
||||
aboutView.AddItem(tview.NewTextView().SetText("[C] Copy ingress RTMP URL"), 1, 0, false)
|
||||
aboutView.AddItem(tview.NewTextView().SetText("[?] About"), 1, 0, false)
|
||||
|
||||
sidebar.AddItem(aboutView, 0, 1, false)
|
||||
|
||||
@ -146,6 +149,7 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
|
||||
actor := &Actor{
|
||||
ch: ch,
|
||||
commandCh: commandCh,
|
||||
buildInfo: params.BuildInfo,
|
||||
logger: params.Logger,
|
||||
app: app,
|
||||
pages: pages,
|
||||
@ -167,6 +171,8 @@ func StartActor(ctx context.Context, params StartActorParams) (*Actor, error) {
|
||||
switch event.Rune() {
|
||||
case 'c', 'C':
|
||||
actor.copySourceURLToClipboard(params.ClipboardAvailable)
|
||||
case '?':
|
||||
actor.showAbout()
|
||||
}
|
||||
case tcell.KeyCtrlC:
|
||||
actor.confirmQuit()
|
||||
@ -437,6 +443,26 @@ func (a *Actor) confirmQuit() {
|
||||
a.pages.AddPage("modal", modal, true, true)
|
||||
}
|
||||
|
||||
func (a *Actor) showAbout() {
|
||||
modal := tview.NewModal()
|
||||
modal.SetText(fmt.Sprintf(
|
||||
"%s: live stream multiplexer\n\nv0.0.0 %s (%s)",
|
||||
domain.AppName,
|
||||
a.buildInfo.Version,
|
||||
a.buildInfo.GoVersion,
|
||||
)).
|
||||
AddButtons([]string{"Ok"}).
|
||||
SetBackgroundColor(tcell.ColorBlack).
|
||||
SetTextColor(tcell.ColorWhite).
|
||||
SetDoneFunc(func(buttonIndex int, _ string) {
|
||||
a.pages.RemovePage("modal")
|
||||
a.app.SetFocus(a.destView)
|
||||
})
|
||||
modal.SetBorderStyle(tcell.StyleDefault.Background(tcell.ColorBlack).Foreground(tcell.ColorWhite))
|
||||
|
||||
a.pages.AddPage("modal", modal, true, true)
|
||||
}
|
||||
|
||||
func rightPad(s string, n int) string {
|
||||
if s == "" {
|
||||
return s
|
||||
|
Loading…
x
Reference in New Issue
Block a user