Coalesce player view renders and schedule once

This commit is contained in:
Stu 2025-12-10 05:31:48 -05:00
parent 4929918d4b
commit 0ba248af4e

42
main.go
View File

@ -162,6 +162,21 @@ func (c convertConfig) CoverLabel() string {
return filepath.Base(c.CoverArtPath)
}
// requestPlayerView schedules a single player view render, coalescing rapid requests.
func (s *appState) requestPlayerView() {
s.playerViewPendingMu.Lock()
if s.playerViewPending {
s.playerViewPendingMu.Unlock()
return
}
s.playerViewPending = true
s.playerViewRefreshNeeded = true
s.playerViewPendingMu.Unlock()
fyne.Do(func() {
s.showPlayerView()
})
}
type appState struct {
window fyne.Window
active string
@ -187,6 +202,8 @@ type appState struct {
renderingPlayerView bool
playerViewRefreshNeeded bool
lastPlayerViewRender time.Time
playerViewPendingMu sync.Mutex
playerViewPending bool
progressQuit chan struct{}
convertCancel context.CancelFunc
playerSurf *playerSurface
@ -421,8 +438,7 @@ func (s *appState) showErrorWithCopy(title string, err error) {
func (s *appState) showMainMenu() {
fmt.Printf("🎬 showMainMenu called - going to player view\n")
// Minimal entry point: go straight to the player view.
s.playerViewRefreshNeeded = true
s.showPlayerView()
s.requestPlayerView()
}
func (s *appState) onClose() {
@ -583,6 +599,9 @@ func (s *appState) buildComparePane(src *videoSource, onStop func(), setSess fun
// showPlayerView renders the player-focused UI with a lightweight playlist.
func (s *appState) showPlayerView() {
fmt.Printf("🎬 showPlayerView called\n")
s.playerViewPendingMu.Lock()
s.playerViewPending = false
s.playerViewPendingMu.Unlock()
if s.renderingPlayerView {
fmt.Printf("⏳ player view render already in progress, skipping\n")
return
@ -596,7 +615,6 @@ func (s *appState) showPlayerView() {
fmt.Printf("⏳ throttle: rendered recently for %s\n", currentPath)
return
}
s.renderingPlayerView = true
defer func() { s.renderingPlayerView = false }()
@ -1429,7 +1447,7 @@ func (s *appState) batchAddToQueue(paths []string) {
}
}
s.loadVideos(combined)
s.showPlayerView()
s.requestPlayerView()
}
}, false)
}
@ -4045,8 +4063,10 @@ func (s *appState) handleDropPlayer(items []fyne.URI) {
if len(videoPaths) > 1 {
go s.loadVideos(videoPaths)
s.requestPlayerView()
} else {
go s.loadVideo(videoPaths[0])
s.requestPlayerView()
}
}
@ -4222,13 +4242,8 @@ func (s *appState) loadVideo(path string) {
logging.Debug(logging.CatModule, "video loaded %+v", src)
fmt.Printf("🔄 Switching to player view...\n")
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
s.playerViewRefreshNeeded = true
s.switchToVideo(s.currentIndex)
// Avoid immediate re-render storm; defer minimal trigger.
time.AfterFunc(10*time.Millisecond, func() {
s.playerViewRefreshNeeded = true
s.showPlayerView()
})
s.requestPlayerView()
}, false)
}
@ -4249,7 +4264,7 @@ func (s *appState) clearVideo() {
s.playerViewSource = ""
s.playerViewRefreshNeeded = true
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
s.showPlayerView()
s.requestPlayerView()
}, false)
}
@ -4355,10 +4370,7 @@ func (s *appState) loadVideos(paths []string) {
fyne.Do(func() {
s.playerViewRefreshNeeded = true
s.switchToVideo(0)
time.AfterFunc(10*time.Millisecond, func() {
s.playerViewRefreshNeeded = true
s.showPlayerView()
})
s.requestPlayerView()
})
}()
}