feat: add splashless option to suppress splash screen on start (#3110)

* Add splashless option to suppress splash screen

Fixes #1911

* Add tests for splashless option

* Update docs for splashless option
mine
Jason Tackaberry 2025-03-30 15:37:57 +00:00 committed by GitHub
parent 7b7e1b5b91
commit 88e04217a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 46 additions and 5 deletions

View File

@ -427,6 +427,8 @@ You can now override the context portForward default address configuration by se
logoless: false
# Set to true to hide K9s crumbs. Default false
crumbsless: false
# Set to true to suppress the K9s splash screen on start. Default false. Note that for larger clusters or higher latency connections, there may be no resources visible initially until local caches have finished populating.
splashless: false
noIcons: false
# Toggles reactive UI. This option provide for watching on disk artifacts changes and update the UI live Defaults to false.
reactive: false
@ -1055,6 +1057,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
noIcons: false
# Toggles reactive UI. This option provide for watching on disk artifacts changes and update the UI live Defaults to false.
reactive: false

View File

@ -218,6 +218,12 @@ func initK9sFlags() {
false,
"Turn K9s crumbs off",
)
rootCmd.Flags().BoolVar(
k9sFlags.Splashless,
"splashless",
false,
"Turn K9s splash screen off",
)
rootCmd.Flags().BoolVarP(
k9sFlags.AllNamespaces,
"all-namespaces", "A",

View File

@ -26,6 +26,7 @@ type Flags struct {
ReadOnly *bool
Write *bool
Crumbsless *bool
Splashless *bool
ScreenDumpDir *string
}
@ -42,6 +43,7 @@ func NewFlags() *Flags {
ReadOnly: boolPtr(false),
Write: boolPtr(false),
Crumbsless: boolPtr(false),
Splashless: boolPtr(false),
ScreenDumpDir: strPtr(AppDumpsDir),
}
}

View File

@ -26,4 +26,5 @@ func TestNewFlags(t *testing.T) {
assert.False(t, *f.ReadOnly)
assert.False(t, *f.Write)
assert.False(t, *f.Crumbsless)
assert.False(t, *f.Splashless)
}

View File

@ -24,6 +24,7 @@
"headless": {"type": "boolean"},
"logoless": {"type": "boolean"},
"crumbsless": {"type": "boolean"},
"splashless": {"type": "boolean"},
"noIcons": {"type": "boolean"},
"reactive": {"type": "boolean"},
"skin": {"type": "string"},

View File

@ -10,6 +10,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
noIcons: false
skipLatestRevCheck: false
disablePodCounting: false

View File

@ -293,6 +293,7 @@ func (k *K9s) Override(k9sFlags *Flags) {
k.UI.manualHeadless = k9sFlags.Headless
k.UI.manualLogoless = k9sFlags.Logoless
k.UI.manualCrumbsless = k9sFlags.Crumbsless
k.UI.manualSplashless = k9sFlags.Splashless
if k9sFlags.ReadOnly != nil && *k9sFlags.ReadOnly {
k.manualReadOnly = k9sFlags.ReadOnly
}
@ -331,6 +332,15 @@ func (k *K9s) IsCrumbsless() bool {
return k.UI.Crumbsless
}
// IsSplashless returns splashless setting.
func (k *K9s) IsSplashless() bool {
if IsBoolSet(k.UI.manualSplashless) {
return true
}
return k.UI.Splashless
}
// GetRefreshRate returns the current refresh rate.
func (k *K9s) GetRefreshRate() int {
if k.manualRefreshRate != 0 {

View File

@ -17,9 +17,9 @@ func Test_k9sOverrides(t *testing.T) {
)
uu := map[string]struct {
k *K9s
rate int
ro, hl, cl, ll bool
k *K9s
rate int
ro, hl, cl, sl, ll bool
}{
"plain": {
k: &K9s{
@ -47,6 +47,7 @@ func Test_k9sOverrides(t *testing.T) {
Headless: true,
Logoless: true,
Crumbsless: true,
Splashless: true,
},
SkipLatestRevCheck: false,
DisablePodCounting: false,
@ -56,6 +57,7 @@ func Test_k9sOverrides(t *testing.T) {
hl: true,
ll: true,
cl: true,
sl: true,
},
"overrides": {
k: &K9s{
@ -72,6 +74,7 @@ func Test_k9sOverrides(t *testing.T) {
manualHeadless: &true,
manualLogoless: &true,
manualCrumbsless: &true,
manualSplashless: &true,
},
SkipLatestRevCheck: false,
DisablePodCounting: false,
@ -85,6 +88,7 @@ func Test_k9sOverrides(t *testing.T) {
hl: true,
ll: true,
cl: true,
sl: true,
},
}
@ -94,6 +98,7 @@ func Test_k9sOverrides(t *testing.T) {
assert.Equal(t, u.rate, u.k.GetRefreshRate())
assert.Equal(t, u.ro, u.k.IsReadOnly())
assert.Equal(t, u.cl, u.k.IsCrumbsless())
assert.Equal(t, u.sl, u.k.IsSplashless())
assert.Equal(t, u.hl, u.k.IsHeadless())
assert.Equal(t, u.ll, u.k.IsLogoless())

View File

@ -11,6 +11,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
reactive: false
noIcons: false
defaultsToFullScreen: false

View File

@ -11,6 +11,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
reactive: false
noIcons: false
defaultsToFullScreen: false

View File

@ -11,6 +11,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
reactive: false
noIcons: false
defaultsToFullScreen: false

View File

@ -10,6 +10,7 @@ k9s:
headless: false
logoless: false
crumbsless: false
splashless: false
noIcons: false
skipLatestRevCheck: yes
disablePodCounts: false

View File

@ -22,6 +22,9 @@ type UI struct {
// Crumbsless toggles nav crumb display.
Crumbsless bool `json:"crumbsless" yaml:"crumbsless"`
// Splashless disables the splash screen on startup.
Splashless bool `json:"splashless" yaml:"splashless"`
// Reactive toggles reactive ui changes.
Reactive bool `json:"reactive" yaml:"reactive"`
@ -38,4 +41,5 @@ type UI struct {
manualHeadless *bool
manualLogoless *bool
manualCrumbsless *bool
manualSplashless *bool
}

View File

@ -167,8 +167,10 @@ func (a *App) layout(ctx context.Context) {
main.AddItem(flash, 1, 1, false)
a.Main.AddPage("main", main, true, false)
a.Main.AddPage("splash", ui.NewSplash(a.Styles, a.version), true, true)
a.toggleHeader(!a.Config.K9s.IsHeadless(), !a.Config.K9s.IsLogoless())
if !a.Config.K9s.IsSplashless() {
a.Main.AddPage("splash", ui.NewSplash(a.Styles, a.version), true, true)
}
}
func (a *App) initSignals() {
@ -523,7 +525,9 @@ func (a *App) Run() error {
a.Resume()
go func() {
<-time.After(splashDelay)
if !a.Config.K9s.IsSplashless() {
<-time.After(splashDelay)
}
a.QueueUpdateDraw(func() {
a.Main.SwitchToPage("main")
// if command bar is already active, focus it