1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

☢️ WTF-1031 Support multiple simultaneous configurations (#1032)

* WTF-1031 Rename WtfApp.app to WtfApp.tviewApp

Signed-off-by: Chris Cummer <chriscummer@me.com>

* WTF-1031 Add scaffolding for main to support multiple WtfApp instances

Signed-off-by: Chris Cummer <chriscummer@me.com>

* WTF-1031 WIP

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Remove common functionality from KeyboardWidget and into Base

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Augment with some descriptive comments

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Add full support for multiple app instances via the AppManager.

Still to do:

* Config support for multiple apps/multiple config files
* The ability to switch between apps

Signed-off-by: Chris Cummer <chriscummer@me.com>

* Move SetTerminal out of main and into its own file

Signed-off-by: Chris Cummer <chriscummer@me.com>
This commit is contained in:
Chris Cummer
2020-12-21 03:25:41 -08:00
committed by GitHub
parent 9ba22f656b
commit fd794707cd
122 changed files with 514 additions and 401 deletions

71
app/app_manager.go Normal file
View File

@@ -0,0 +1,71 @@
package app
import (
"errors"
"github.com/olebedev/config"
"github.com/rivo/tview"
)
// WtfAppManager handles the instances of WtfApp, ensuring that they're displayed as requested
type WtfAppManager struct {
WtfApps []*WtfApp
selected int
}
// NewAppManager creates and returns an instance of AppManager
func NewAppManager() WtfAppManager {
appMan := WtfAppManager{
WtfApps: []*WtfApp{},
}
return appMan
}
// MakeNewWtfApp creates and starts a new instance of WtfApp from a set of configuration params
func (appMan *WtfAppManager) MakeNewWtfApp(config *config.Config, configFilePath string) {
wtfApp := NewWtfApp(tview.NewApplication(), config, configFilePath)
appMan.Add(wtfApp)
wtfApp.Start()
}
// Add adds a WtfApp to the collection of apps that the AppManager manages.
// This app is then available for display onscreen.
func (appMan *WtfAppManager) Add(wtfApp *WtfApp) {
appMan.WtfApps = append(appMan.WtfApps, wtfApp)
}
// Current returns the currently-displaying instance of WtfApp
func (appMan *WtfAppManager) Current() (*WtfApp, error) {
if appMan.selected < 0 || appMan.selected >= len(appMan.WtfApps) {
return nil, errors.New("invalid app index selected")
}
return appMan.WtfApps[appMan.selected], nil
}
// Next cycles the WtfApps forward by one, making the next one in the list
// the current one. If there are none after the current one, it wraps around.
func (appMan *WtfAppManager) Next() (*WtfApp, error) {
appMan.selected++
if appMan.selected >= len(appMan.WtfApps) {
appMan.selected = 0
}
return appMan.Current()
}
// Prev cycles the WtfApps backwards by one, making the previous one in the
// list the current one. If there are none before the current one, it wraps around.
func (appMan *WtfAppManager) Prev() (*WtfApp, error) {
appMan.selected--
if appMan.selected < 0 {
appMan.selected = len(appMan.WtfApps) - 1
}
return appMan.Current()
}

View File

@@ -84,14 +84,14 @@ func readGitHubAPIKey(cfg *config.Config) string {
func (wtfApp *WtfApp) contributorThankYouMessage() string {
str := " On behalf of all the users of WTF, thank you for contributing to the source code."
str += fmt.Sprintf(" %s", aurora.Green("You rock."))
str += fmt.Sprintf(" %s", aurora.Green("\n\n You rock."))
return str
}
func (wtfApp *WtfApp) sponsorThankYouMessage() string {
str := " Your sponsorship of WTF makes a difference. Thank you for sponsoring and supporting WTF."
str += fmt.Sprintf(" %s", aurora.Green("You're awesome."))
str += fmt.Sprintf(" %s", aurora.Green("\n\n You're awesome."))
return str
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/wtfutil/wtf/wtf"
)
// FocusState is a custom type that differentiates focusable scopes
type FocusState int
const (
@@ -20,17 +21,18 @@ const (
// FocusTracker is used by the app to track which onscreen widget currently has focus,
// and to move focus between widgets.
type FocusTracker struct {
App *tview.Application
Idx int
IsFocused bool
Widgets []wtf.Wtfable
config *config.Config
config *config.Config
tviewApp *tview.Application
}
func NewFocusTracker(app *tview.Application, widgets []wtf.Wtfable, config *config.Config) FocusTracker {
// NewFocusTracker creates and returns an instance of FocusTracker
func NewFocusTracker(tviewApp *tview.Application, widgets []wtf.Wtfable, config *config.Config) FocusTracker {
focusTracker := FocusTracker{
App: app,
tviewApp: tviewApp,
Idx: -1,
IsFocused: false,
Widgets: widgets,
@@ -45,6 +47,7 @@ func NewFocusTracker(app *tview.Application, widgets []wtf.Wtfable, config *conf
/* -------------------- Exported Functions -------------------- */
// FocusOn puts the focus on the item that belongs to the focus character passed in
func (tracker *FocusTracker) FocusOn(char string) bool {
if !tracker.useNavShortcuts() {
return false
@@ -108,6 +111,7 @@ func (tracker *FocusTracker) Prev() {
tracker.IsFocused = true
}
// Refocus forces the focus back to the currently-selected item
func (tracker *FocusTracker) Refocus() {
tracker.focus(tracker.Idx)
}
@@ -196,7 +200,7 @@ func (tracker *FocusTracker) focus(idx int) {
widget.CommonSettings().Colors.BorderTheme.Focused,
),
)
tracker.App.SetFocus(view)
tracker.tviewApp.SetFocus(view)
}
func (tracker *FocusTracker) focusables() []wtf.Wtfable {
@@ -239,7 +243,7 @@ func (tracker *FocusTracker) focusState() FocusState {
}
for _, widget := range tracker.Widgets {
if widget.TextView() == tracker.App.GetFocus() {
if widget.TextView() == tracker.tviewApp.GetFocus() {
return widgetFocused
}
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/wtfutil/wtf/wtf"
)
// ModuleValidator is responsible for validating the state of a module's configuration
type ModuleValidator struct{}
type widgetError struct {
@@ -16,6 +17,7 @@ type widgetError struct {
validationErrors []cfg.Validatable
}
// NewModuleValidator creates and returns an instance of ModuleValidator
func NewModuleValidator() *ModuleValidator {
return &ModuleValidator{}
}

View File

@@ -80,7 +80,7 @@ import (
// MakeWidget creates and returns instances of widgets
func MakeWidget(
app *tview.Application,
tviewApp *tview.Application,
pages *tview.Pages,
moduleName string,
config *config.Config,
@@ -103,239 +103,239 @@ func MakeWidget(
switch moduleConfig.UString("type", moduleName) {
case "arpansagovau":
settings := arpansagovau.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = arpansagovau.NewWidget(app, settings)
widget = arpansagovau.NewWidget(tviewApp, settings)
case "azuredevops":
settings := azuredevops.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = azuredevops.NewWidget(app, pages, settings)
widget = azuredevops.NewWidget(tviewApp, pages, settings)
case "bamboohr":
settings := bamboohr.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = bamboohr.NewWidget(app, settings)
widget = bamboohr.NewWidget(tviewApp, settings)
case "bargraph":
settings := bargraph.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = bargraph.NewWidget(app, settings)
widget = bargraph.NewWidget(tviewApp, settings)
case "bittrex":
settings := bittrex.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = bittrex.NewWidget(app, settings)
widget = bittrex.NewWidget(tviewApp, settings)
case "blockfolio":
settings := blockfolio.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = blockfolio.NewWidget(app, settings)
widget = blockfolio.NewWidget(tviewApp, settings)
case "buildkite":
settings := buildkite.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = buildkite.NewWidget(app, pages, settings)
widget = buildkite.NewWidget(tviewApp, pages, settings)
case "cdsFavorites":
settings := cdsfavorites.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = cdsfavorites.NewWidget(app, pages, settings)
widget = cdsfavorites.NewWidget(tviewApp, pages, settings)
case "cdsQueue":
settings := cdsqueue.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = cdsqueue.NewWidget(app, pages, settings)
widget = cdsqueue.NewWidget(tviewApp, pages, settings)
case "cdsStatus":
settings := cdsstatus.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = cdsstatus.NewWidget(app, pages, settings)
widget = cdsstatus.NewWidget(tviewApp, pages, settings)
case "circleci":
settings := circleci.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = circleci.NewWidget(app, settings)
widget = circleci.NewWidget(tviewApp, settings)
case "clocks":
settings := clocks.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = clocks.NewWidget(app, settings)
widget = clocks.NewWidget(tviewApp, settings)
case "cmdrunner":
settings := cmdrunner.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = cmdrunner.NewWidget(app, settings)
widget = cmdrunner.NewWidget(tviewApp, settings)
case "cryptolive":
settings := cryptolive.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = cryptolive.NewWidget(app, settings)
widget = cryptolive.NewWidget(tviewApp, settings)
case "datadog":
settings := datadog.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = datadog.NewWidget(app, pages, settings)
widget = datadog.NewWidget(tviewApp, pages, settings)
case "devto":
settings := devto.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = devto.NewWidget(app, pages, settings)
widget = devto.NewWidget(tviewApp, pages, settings)
case "digitalclock":
settings := digitalclock.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = digitalclock.NewWidget(app, settings)
widget = digitalclock.NewWidget(tviewApp, settings)
case "digitalocean":
settings := digitalocean.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = digitalocean.NewWidget(app, pages, settings)
widget = digitalocean.NewWidget(tviewApp, pages, settings)
case "docker":
settings := docker.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = docker.NewWidget(app, pages, settings)
widget = docker.NewWidget(tviewApp, pages, settings)
case "feedreader":
settings := feedreader.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = feedreader.NewWidget(app, pages, settings)
widget = feedreader.NewWidget(tviewApp, pages, settings)
case "football":
settings := football.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = football.NewWidget(app, pages, settings)
widget = football.NewWidget(tviewApp, pages, settings)
case "gcal":
settings := gcal.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gcal.NewWidget(app, settings)
widget = gcal.NewWidget(tviewApp, settings)
case "gerrit":
settings := gerrit.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gerrit.NewWidget(app, pages, settings)
widget = gerrit.NewWidget(tviewApp, pages, settings)
case "git":
settings := git.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = git.NewWidget(app, pages, settings)
widget = git.NewWidget(tviewApp, pages, settings)
case "github":
settings := github.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = github.NewWidget(app, pages, settings)
widget = github.NewWidget(tviewApp, pages, settings)
case "gitlab":
settings := gitlab.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gitlab.NewWidget(app, pages, settings)
widget = gitlab.NewWidget(tviewApp, pages, settings)
case "gitlabtodo":
settings := gitlabtodo.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gitlabtodo.NewWidget(app, pages, settings)
widget = gitlabtodo.NewWidget(tviewApp, pages, settings)
case "gitter":
settings := gitter.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gitter.NewWidget(app, pages, settings)
widget = gitter.NewWidget(tviewApp, pages, settings)
case "googleanalytics":
settings := googleanalytics.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = googleanalytics.NewWidget(app, settings)
widget = googleanalytics.NewWidget(tviewApp, settings)
case "gspreadsheets":
settings := gspreadsheets.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = gspreadsheets.NewWidget(app, settings)
widget = gspreadsheets.NewWidget(tviewApp, settings)
case "grafana":
settings := grafana.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = grafana.NewWidget(app, pages, settings)
widget = grafana.NewWidget(tviewApp, pages, settings)
case "hackernews":
settings := hackernews.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = hackernews.NewWidget(app, pages, settings)
widget = hackernews.NewWidget(tviewApp, pages, settings)
case "hibp":
settings := hibp.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = hibp.NewWidget(app, settings)
widget = hibp.NewWidget(tviewApp, settings)
case "ipapi":
settings := ipapi.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = ipapi.NewWidget(app, settings)
widget = ipapi.NewWidget(tviewApp, settings)
case "ipinfo":
settings := ipinfo.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = ipinfo.NewWidget(app, settings)
widget = ipinfo.NewWidget(tviewApp, settings)
case "jenkins":
settings := jenkins.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = jenkins.NewWidget(app, pages, settings)
widget = jenkins.NewWidget(tviewApp, pages, settings)
case "jira":
settings := jira.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = jira.NewWidget(app, pages, settings)
widget = jira.NewWidget(tviewApp, pages, settings)
case "kubernetes":
settings := kubernetes.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = kubernetes.NewWidget(app, settings)
widget = kubernetes.NewWidget(tviewApp, settings)
case "krisinformation":
settings := krisinformation.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = krisinformation.NewWidget(app, settings)
widget = krisinformation.NewWidget(tviewApp, settings)
case "logger":
settings := logger.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = logger.NewWidget(app, settings)
widget = logger.NewWidget(tviewApp, settings)
case "mercurial":
settings := mercurial.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = mercurial.NewWidget(app, pages, settings)
widget = mercurial.NewWidget(tviewApp, pages, settings)
case "nbascore":
settings := nbascore.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = nbascore.NewWidget(app, pages, settings)
widget = nbascore.NewWidget(tviewApp, pages, settings)
case "newrelic":
settings := newrelic.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = newrelic.NewWidget(app, pages, settings)
widget = newrelic.NewWidget(tviewApp, pages, settings)
case "opsgenie":
settings := opsgenie.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = opsgenie.NewWidget(app, settings)
widget = opsgenie.NewWidget(tviewApp, settings)
case "pagerduty":
settings := pagerduty.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = pagerduty.NewWidget(app, settings)
widget = pagerduty.NewWidget(tviewApp, settings)
case "pihole":
settings := pihole.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = pihole.NewWidget(app, pages, settings)
widget = pihole.NewWidget(tviewApp, pages, settings)
case "power":
settings := power.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = power.NewWidget(app, settings)
widget = power.NewWidget(tviewApp, settings)
case "prettyweather":
settings := prettyweather.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = prettyweather.NewWidget(app, settings)
widget = prettyweather.NewWidget(tviewApp, settings)
case "pocket":
settings := pocket.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = pocket.NewWidget(app, pages, settings)
widget = pocket.NewWidget(tviewApp, pages, settings)
case "resourceusage":
settings := resourceusage.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = resourceusage.NewWidget(app, settings)
widget = resourceusage.NewWidget(tviewApp, settings)
case "rollbar":
settings := rollbar.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = rollbar.NewWidget(app, pages, settings)
widget = rollbar.NewWidget(tviewApp, pages, settings)
case "security":
settings := security.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = security.NewWidget(app, settings)
widget = security.NewWidget(tviewApp, settings)
case "spacex":
settings := spacex.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = spacex.NewWidget(app, settings)
widget = spacex.NewWidget(tviewApp, settings)
case "spotify":
settings := spotify.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = spotify.NewWidget(app, pages, settings)
widget = spotify.NewWidget(tviewApp, pages, settings)
case "spotifyweb":
settings := spotifyweb.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = spotifyweb.NewWidget(app, pages, settings)
widget = spotifyweb.NewWidget(tviewApp, pages, settings)
case "status":
settings := status.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = status.NewWidget(app, settings)
widget = status.NewWidget(tviewApp, settings)
case "subreddit":
settings := subreddit.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = subreddit.NewWidget(app, pages, settings)
widget = subreddit.NewWidget(tviewApp, pages, settings)
case "textfile":
settings := textfile.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = textfile.NewWidget(app, pages, settings)
widget = textfile.NewWidget(tviewApp, pages, settings)
case "todo":
settings := todo.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = todo.NewWidget(app, pages, settings)
widget = todo.NewWidget(tviewApp, pages, settings)
case "todo_plus":
settings := todo_plus.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = todo_plus.NewWidget(app, pages, settings)
widget = todo_plus.NewWidget(tviewApp, pages, settings)
case "todoist":
settings := todo_plus.FromTodoist(moduleName, moduleConfig, config)
widget = todo_plus.NewWidget(app, pages, settings)
widget = todo_plus.NewWidget(tviewApp, pages, settings)
case "transmission":
settings := transmission.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = transmission.NewWidget(app, pages, settings)
widget = transmission.NewWidget(tviewApp, pages, settings)
case "travisci":
settings := travisci.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = travisci.NewWidget(app, pages, settings)
widget = travisci.NewWidget(tviewApp, pages, settings)
case "trello":
settings := todo_plus.FromTrello(moduleName, moduleConfig, config)
widget = todo_plus.NewWidget(app, pages, settings)
widget = todo_plus.NewWidget(tviewApp, pages, settings)
case "twitch":
settings := twitch.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = twitch.NewWidget(app, pages, settings)
widget = twitch.NewWidget(tviewApp, pages, settings)
case "twitter":
settings := twitter.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = twitter.NewWidget(app, pages, settings)
widget = twitter.NewWidget(tviewApp, pages, settings)
case "twitterstats":
settings := twitterstats.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = twitterstats.NewWidget(app, pages, settings)
widget = twitterstats.NewWidget(tviewApp, pages, settings)
case "uptimerobot":
settings := uptimerobot.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = uptimerobot.NewWidget(app, pages, settings)
widget = uptimerobot.NewWidget(tviewApp, pages, settings)
case "victorops":
settings := victorops.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = victorops.NewWidget(app, settings)
widget = victorops.NewWidget(tviewApp, settings)
case "weather":
settings := weather.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = weather.NewWidget(app, pages, settings)
widget = weather.NewWidget(tviewApp, pages, settings)
case "zendesk":
settings := zendesk.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = zendesk.NewWidget(app, pages, settings)
widget = zendesk.NewWidget(tviewApp, pages, settings)
case "exchangerates":
settings := exchangerates.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = exchangerates.NewWidget(app, pages, settings)
widget = exchangerates.NewWidget(tviewApp, pages, settings)
case "finnhub":
settings := finnhub.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = finnhub.NewWidget(app, settings)
widget = finnhub.NewWidget(tviewApp, settings)
default:
settings := unknown.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = unknown.NewWidget(app, settings)
widget = unknown.NewWidget(tviewApp, settings)
}
return widget
}
// MakeWidgets creates and returns a collection of enabled widgets
func MakeWidgets(app *tview.Application, pages *tview.Pages, config *config.Config) []wtf.Wtfable {
func MakeWidgets(tviewApp *tview.Application, pages *tview.Pages, config *config.Config) []wtf.Wtfable {
widgets := []wtf.Wtfable{}
moduleNames, _ := config.Map("wtf.mods")
for moduleName := range moduleNames {
widget := MakeWidget(app, pages, moduleName, config)
widget := MakeWidget(tviewApp, pages, moduleName, config)
if widget != nil {
widgets = append(widgets, widget)

View File

@@ -1,11 +1,14 @@
package app
import (
"fmt"
"log"
"os"
"time"
"github.com/gdamore/tcell"
_ "github.com/gdamore/tcell/terminfo/extended"
"github.com/logrusorgru/aurora"
"github.com/olebedev/config"
"github.com/radovskyb/watcher"
"github.com/rivo/tview"
@@ -18,7 +21,8 @@ import (
// WtfApp is the container for a collection of widgets that are all constructed from a single
// configuration file and displayed together
type WtfApp struct {
app *tview.Application
TViewApp *tview.Application
config *config.Config
configFilePath string
display *Display
@@ -30,32 +34,29 @@ type WtfApp struct {
}
// NewWtfApp creates and returns an instance of WtfApp
func NewWtfApp(app *tview.Application, config *config.Config, configFilePath string) *WtfApp {
wtfApp := WtfApp{
app: app,
func NewWtfApp(tviewApp *tview.Application, config *config.Config, configFilePath string) *WtfApp {
wtfApp := &WtfApp{
TViewApp: tviewApp,
config: config,
configFilePath: configFilePath,
pages: tview.NewPages(),
}
wtfApp.app.SetBeforeDrawFunc(func(s tcell.Screen) bool {
wtfApp.TViewApp.SetBeforeDrawFunc(func(s tcell.Screen) bool {
s.Clear()
return false
})
wtfApp.app.SetInputCapture(wtfApp.keyboardIntercept)
wtfApp.widgets = MakeWidgets(wtfApp.app, wtfApp.pages, wtfApp.config)
wtfApp.widgets = MakeWidgets(wtfApp.TViewApp, wtfApp.pages, wtfApp.config)
wtfApp.display = NewDisplay(wtfApp.widgets, wtfApp.config)
wtfApp.focusTracker = NewFocusTracker(wtfApp.app, wtfApp.widgets, wtfApp.config)
wtfApp.focusTracker = NewFocusTracker(wtfApp.TViewApp, wtfApp.widgets, wtfApp.config)
wtfApp.validator = NewModuleValidator()
githubAPIKey := readGitHubAPIKey(wtfApp.config)
wtfApp.ghUser = support.NewGitHubUser(githubAPIKey)
wtfApp.validator = NewModuleValidator()
wtfApp.pages.AddPage("grid", wtfApp.display.Grid, true, true)
wtfApp.app.SetRoot(wtfApp.pages, true)
wtfApp.validator.Validate(wtfApp.widgets)
@@ -66,17 +67,28 @@ func NewWtfApp(app *tview.Application, config *config.Config, configFilePath str
),
)
return &wtfApp
wtfApp.TViewApp.SetInputCapture(wtfApp.keyboardIntercept)
wtfApp.TViewApp.SetRoot(wtfApp.pages, true)
return wtfApp
}
/* -------------------- Exported Functions -------------------- */
// Run starts the underlying tview app
func (wtfApp *WtfApp) Run() {
if err := wtfApp.TViewApp.Run(); err != nil {
fmt.Printf("\n%s %v\n", aurora.Red("ERROR"), err)
os.Exit(1)
}
}
// Start initializes the app
func (wtfApp *WtfApp) Start() {
go wtfApp.scheduleWidgets()
go wtfApp.watchForConfigChanges()
// FIXME: This should be moved to the AppManager
go func() { _ = wtfApp.ghUser.Load() }()
}
@@ -98,11 +110,16 @@ func (wtfApp *WtfApp) keyboardIntercept(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyCtrlC:
wtfApp.Stop()
wtfApp.app.Stop()
wtfApp.TViewApp.Stop()
wtfApp.DisplayExitMessage()
case tcell.KeyCtrlR:
wtfApp.refreshAllWidgets()
return nil
case tcell.KeyCtrlSpace:
// FIXME: This can't reside in the app, the app doesn't know about
// the AppManager. The AppManager needs to catch this one
fmt.Println("Next app")
return nil
case tcell.KeyTab:
wtfApp.focusTracker.Next()
case tcell.KeyBacktab:
@@ -154,7 +171,7 @@ func (wtfApp *WtfApp) watchForConfigChanges() {
wtfApp.Stop()
config := cfg.LoadWtfConfigFile(wtfApp.configFilePath)
newApp := NewWtfApp(wtfApp.app, config, wtfApp.configFilePath)
newApp := NewWtfApp(wtfApp.TViewApp, config, wtfApp.configFilePath)
openURLUtil := utils.ToStrs(config.UList("wtf.openUrlUtil", []interface{}{}))
utils.Init(config.UString("wtf.openFileUtil", "open"), openURLUtil)