@@ -2,6 +2,7 @@ package ui
22
33import (
44 "fmt"
5+ "sync"
56 "time"
67
78 "runtime/debug"
@@ -27,6 +28,7 @@ import (
2728
2829type App struct {
2930 TviewApp * tview.Application
31+ Screen tcell.Screen
3032 Docker * dao.DockerClient
3133
3234 // Components
@@ -44,6 +46,11 @@ type App struct {
4446 ActiveFilter string
4547 ActiveScope * common.Scope
4648 ActiveInspector common.Inspector
49+
50+ // Concurrency
51+ pauseMx sync.RWMutex
52+ paused bool
53+ stopTicker chan struct {}
4754}
4855
4956// Ensure App implements AppController interface
@@ -76,8 +83,19 @@ func NewApp() *App {
7683 panic (err )
7784 }
7885
86+ screen , err := tcell .NewScreen ()
87+ if err != nil {
88+ panic (err )
89+ }
90+ // We don't Init() here, tview does it on Run() if we set it?
91+ // Actually tview.Application.Run() calls screen.Init() if not initialized.
92+
93+ tviewApp := tview .NewApplication ()
94+ tviewApp .SetScreen (screen )
95+
7996 app := & App {
80- TviewApp : tview .NewApplication (),
97+ TviewApp : tviewApp ,
98+ Screen : screen ,
8199 Docker : docker ,
82100 Views : make (map [string ]* view.ResourceView ),
83101 Pages : tview .NewPages (),
@@ -95,21 +113,48 @@ func (a *App) Run() error {
95113 }
96114 }()
97115
116+ // Start auto-refresh
117+ a .StartAutoRefresh ()
118+
119+ return a .TviewApp .SetRoot (a .Layout , true ).Run ()
120+ }
121+
122+ func (a * App ) StartAutoRefresh () {
123+ if a .stopTicker != nil {
124+ return
125+ }
126+ a .stopTicker = make (chan struct {})
127+
98128 go func () {
99- // Initial Delay for UI setup
100- time .Sleep (100 * time .Millisecond )
129+ // Initial update
130+ // We use a small delay on first run to let UI settle if needed, but only for the first ever run
131+ // subsequent restarts of auto-refresh might want immediate effect or wait for next tick.
132+ // Let's rely on tick.
133+
134+ ticker := time .NewTicker (2 * time .Second )
135+ defer ticker .Stop ()
136+
137+ // Immediate update on start
101138 a .RefreshCurrentView ()
102139 a .updateHeader ()
103140
104- ticker := time .NewTicker (2 * time .Second )
105- defer ticker .Stop ()
106- for range ticker .C {
107- a .RefreshCurrentView ()
108- a .updateHeader ()
141+ for {
142+ select {
143+ case <- ticker .C :
144+ a .RefreshCurrentView ()
145+ a .updateHeader ()
146+ case <- a .stopTicker :
147+ return
148+ }
109149 }
110150 }()
151+ }
111152
112- return a .TviewApp .SetRoot (a .Layout , true ).Run ()
153+ func (a * App ) StopAutoRefresh () {
154+ if a .stopTicker != nil {
155+ close (a .stopTicker )
156+ a .stopTicker = nil
157+ }
113158}
114159
115160func (a * App ) initUI () {
@@ -308,6 +353,10 @@ func (a *App) GetTviewApp() *tview.Application {
308353 return a .TviewApp
309354}
310355
356+ func (a * App ) GetScreen () tcell.Screen {
357+ return a .Screen
358+ }
359+
311360func (a * App ) GetDocker () * dao.DockerClient {
312361 return a .Docker
313362}
@@ -419,3 +468,60 @@ func (a *App) CloseInspector() {
419468 a .RestoreFocus ()
420469 a .UpdateShortcuts ()
421470}
471+
472+ func (a * App ) ActionPause () {
473+ a .SetPaused (true )
474+ }
475+
476+ func (a * App ) ActionResume () {
477+ a .SetPaused (false )
478+ a .TviewApp .Draw () // Force redraw
479+ }
480+
481+ func (a * App ) SetPaused (paused bool ) {
482+ a .pauseMx .Lock ()
483+ defer a .pauseMx .Unlock ()
484+ a .paused = paused
485+ }
486+
487+ func (a * App ) IsPaused () bool {
488+ a .pauseMx .RLock ()
489+ defer a .pauseMx .RUnlock ()
490+ return a .paused
491+ }
492+
493+ func (a * App ) SafeQueueUpdateDraw (f func ()) {
494+ a .pauseMx .RLock ()
495+ isPaused := a .paused
496+ a .pauseMx .RUnlock ()
497+
498+ if isPaused {
499+ return
500+ }
501+
502+ a .TviewApp .QueueUpdateDraw (func () {
503+ a .pauseMx .RLock ()
504+ isPausedNow := a .paused
505+ a .pauseMx .RUnlock ()
506+
507+ if isPausedNow {
508+ return
509+ }
510+ f ()
511+ })
512+ }
513+
514+ func (a * App ) RunInBackground (task func ()) {
515+ go func () {
516+ defer func () {
517+ if r := recover (); r != nil {
518+ a .TviewApp .QueueUpdateDraw (func () {
519+ a .Flash .SetText (fmt .Sprintf ("[red]Background task panic: %v" , r ))
520+ // Also print to stdout for debugging if app is still running or logs are captured
521+ fmt .Printf ("Background task panic: %v\n Stack trace:\n %s\n " , r , string (debug .Stack ()))
522+ })
523+ }
524+ }()
525+ task ()
526+ }()
527+ }
0 commit comments