diff --git a/internal/ui/tappable.go b/internal/ui/tappable.go new file mode 100644 index 0000000..8839e30 --- /dev/null +++ b/internal/ui/tappable.go @@ -0,0 +1,64 @@ +package ui + +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/widget" +) + +// TappableOverlay is an invisible widget that captures tap and double-tap events +type TappableOverlay struct { + widget.BaseWidget + OnTapped func() + OnDoubleTapped func() + OnSecondaryTapped func() +} + +// NewTappableOverlay creates a new tappable overlay +func NewTappableOverlay(onTapped, onDoubleTapped, onSecondaryTapped func()) *TappableOverlay { + t := &TappableOverlay{ + OnTapped: onTapped, + OnDoubleTapped: onDoubleTapped, + OnSecondaryTapped: onSecondaryTapped, + } + t.ExtendBaseWidget(t) + return t +} + +// Tapped handles single tap events +func (t *TappableOverlay) Tapped(*fyne.PointEvent) { + if t.OnTapped != nil { + t.OnTapped() + } +} + +// TappedSecondary handles right-click events +func (t *TappableOverlay) TappedSecondary(*fyne.PointEvent) { + if t.OnSecondaryTapped != nil { + t.OnSecondaryTapped() + } +} + +// DoubleTapped handles double-tap events +func (t *TappableOverlay) DoubleTapped(*fyne.PointEvent) { + if t.OnDoubleTapped != nil { + t.OnDoubleTapped() + } +} + +// CreateRenderer implements fyne.Widget +func (t *TappableOverlay) CreateRenderer() fyne.WidgetRenderer { + return &tappableRenderer{} +} + +// MinSize returns minimum size (should fill parent) +func (t *TappableOverlay) MinSize() fyne.Size { + return fyne.NewSize(1, 1) +} + +type tappableRenderer struct{} + +func (r *tappableRenderer) Layout(size fyne.Size) {} +func (r *tappableRenderer) MinSize() fyne.Size { return fyne.NewSize(1, 1) } +func (r *tappableRenderer) Refresh() {} +func (r *tappableRenderer) Objects() []fyne.CanvasObject { return nil } +func (r *tappableRenderer) Destroy() {} diff --git a/main.go b/main.go index 55c14bb..65e7137 100644 --- a/main.go +++ b/main.go @@ -1068,6 +1068,34 @@ func (s *appState) showPlayerView() { }) } + // Add tappable overlay to stage for video interactions + // Double-click toggles fullscreen, right-click plays/pauses + videoTapper := ui.NewTappableOverlay( + nil, // Single tap does nothing for now + func() { + // Double-tap: toggle fullscreen + s.toggleFullscreen() + }, + func() { + // Right-click: toggle play/pause + if !ensureSession() { + return + } + if s.playerPaused { + s.playSess.Play() + s.playerPaused = false + playBtn.SetText(ui.IconPause) + } else { + s.playSess.Pause() + s.playerPaused = true + playBtn.SetText(ui.IconPlayArrow) + } + }, + ) + + // Add tapper to stage + stage.Objects = append(stage.Objects, videoTapper) + playerArea = container.NewBorder( nil, container.NewVBox(container.NewPadded(progressBar), container.NewPadded(controlRow)),