Wrap video Next loop to start of bookmarks/library list at end of media

This commit is contained in:
pax 2026-04-07 11:41:26 -05:00
parent 6d3d27d9d5
commit 33293dfbae
2 changed files with 37 additions and 4 deletions

View File

@ -460,6 +460,7 @@ class BooruApp(QMainWindow):
self._preview.blacklist_tag_requested.connect(self._blacklist_tag_from_popout) self._preview.blacklist_tag_requested.connect(self._blacklist_tag_from_popout)
self._preview.blacklist_post_requested.connect(self._blacklist_post_from_popout) self._preview.blacklist_post_requested.connect(self._blacklist_post_from_popout)
self._preview.navigate.connect(self._navigate_preview) self._preview.navigate.connect(self._navigate_preview)
self._preview.play_next_requested.connect(self._on_video_end_next)
self._preview.fullscreen_requested.connect(self._open_fullscreen_preview) self._preview.fullscreen_requested.connect(self._open_fullscreen_preview)
self._preview.set_folders_callback(self._db.get_folders) self._preview.set_folders_callback(self._db.get_folders)
self._fullscreen_window = None self._fullscreen_window = None
@ -1667,8 +1668,13 @@ class BooruApp(QMainWindow):
if 0 <= idx < len(self._posts): if 0 <= idx < len(self._posts):
self._open_in_browser(self._posts[idx]) self._open_in_browser(self._posts[idx])
def _navigate_preview(self, direction: int) -> None: def _navigate_preview(self, direction: int, wrap: bool = False) -> None:
"""Navigate to prev/next post in the preview. direction: -1 or +1.""" """Navigate to prev/next post in the preview. direction: -1 or +1.
wrap=True wraps to the start (or end) of the bookmarks/library lists
when running off the edge used for the video-end "Next" auto-advance
on tabs that don't have pagination.
"""
if self._stack.currentIndex() == 1: if self._stack.currentIndex() == 1:
# Bookmarks view # Bookmarks view
grid = self._bookmarks_view._grid grid = self._bookmarks_view._grid
@ -1677,6 +1683,10 @@ class BooruApp(QMainWindow):
if 0 <= idx < len(favs): if 0 <= idx < len(favs):
grid._select(idx) grid._select(idx)
self._on_bookmark_activated(favs[idx]) self._on_bookmark_activated(favs[idx])
elif wrap and favs:
idx = 0 if direction > 0 else len(favs) - 1
grid._select(idx)
self._on_bookmark_activated(favs[idx])
elif self._stack.currentIndex() == 2: elif self._stack.currentIndex() == 2:
# Library view # Library view
grid = self._library_view._grid grid = self._library_view._grid
@ -1685,6 +1695,10 @@ class BooruApp(QMainWindow):
if 0 <= idx < len(files): if 0 <= idx < len(files):
grid._select(idx) grid._select(idx)
self._library_view.file_activated.emit(str(files[idx])) self._library_view.file_activated.emit(str(files[idx]))
elif wrap and files:
idx = 0 if direction > 0 else len(files) - 1
grid._select(idx)
self._library_view.file_activated.emit(str(files[idx]))
else: else:
idx = self._grid.selected_index + direction idx = self._grid.selected_index + direction
log.info(f"Navigate: direction={direction} current={self._grid.selected_index} next={idx} total={len(self._posts)}") log.info(f"Navigate: direction={direction} current={self._grid.selected_index} next={idx} total={len(self._posts)}")
@ -1698,6 +1712,22 @@ class BooruApp(QMainWindow):
self._search.nav_page_turn = "last" self._search.nav_page_turn = "last"
self._prev_page() self._prev_page()
def _on_video_end_next(self) -> None:
"""Auto-advance from end of video in 'Next' mode.
Wraps to start on bookmarks/library tabs (where there is no
pagination), so a single video looping with Next mode keeps moving
through the list indefinitely instead of stopping at the end. Browse
tab keeps its existing page-turn behaviour.
"""
self._navigate_preview(1, wrap=True)
# Sync popout if it's open
if self._fullscreen_window and self._preview._current_path:
self._update_fullscreen(
self._preview._current_path,
self._preview._info_label.text(),
)
def _is_post_saved(self, post_id: int) -> bool: def _is_post_saved(self, post_id: int) -> bool:
"""Check if a post is saved in the library (any folder).""" """Check if a post is saved in the library (any folder)."""
from ..core.config import saved_dir, saved_folder_dir, MEDIA_EXTENSIONS from ..core.config import saved_dir, saved_folder_dir, MEDIA_EXTENSIONS
@ -1880,6 +1910,7 @@ class BooruApp(QMainWindow):
monitor = self._db.get_setting("slideshow_monitor") monitor = self._db.get_setting("slideshow_monitor")
self._fullscreen_window = FullscreenPreview(grid_cols=cols, show_actions=show_actions, monitor=monitor, parent=self) self._fullscreen_window = FullscreenPreview(grid_cols=cols, show_actions=show_actions, monitor=monitor, parent=self)
self._fullscreen_window.navigate.connect(self._navigate_fullscreen) self._fullscreen_window.navigate.connect(self._navigate_fullscreen)
self._fullscreen_window.play_next_requested.connect(self._on_video_end_next)
if show_actions: if show_actions:
self._fullscreen_window.bookmark_requested.connect(self._bookmark_from_preview) self._fullscreen_window.bookmark_requested.connect(self._bookmark_from_preview)
self._fullscreen_window.save_toggle_requested.connect(self._save_toggle_from_popout) self._fullscreen_window.save_toggle_requested.connect(self._save_toggle_from_popout)

View File

@ -63,6 +63,7 @@ class FullscreenPreview(QMainWindow):
"""Fullscreen media viewer with navigation — images, GIFs, and video.""" """Fullscreen media viewer with navigation — images, GIFs, and video."""
navigate = Signal(int) # direction: -1/+1 for left/right, -cols/+cols for up/down navigate = Signal(int) # direction: -1/+1 for left/right, -cols/+cols for up/down
play_next_requested = Signal() # video ended in "Next" mode (wrap-aware)
bookmark_requested = Signal() bookmark_requested = Signal()
save_toggle_requested = Signal() # save or unsave depending on state save_toggle_requested = Signal() # save or unsave depending on state
blacklist_tag_requested = Signal(str) # tag name blacklist_tag_requested = Signal(str) # tag name
@ -90,7 +91,7 @@ class FullscreenPreview(QMainWindow):
self._stack.addWidget(self._viewer) self._stack.addWidget(self._viewer)
self._video = VideoPlayer() self._video = VideoPlayer()
self._video.play_next.connect(lambda: self.navigate.emit(1)) self._video.play_next.connect(self.play_next_requested)
self._video.video_size.connect(self._on_video_size) self._video.video_size.connect(self._on_video_size)
self._stack.addWidget(self._video) self._stack.addWidget(self._video)
@ -1190,6 +1191,7 @@ class ImagePreview(QWidget):
blacklist_tag_requested = Signal(str) blacklist_tag_requested = Signal(str)
blacklist_post_requested = Signal() blacklist_post_requested = Signal()
navigate = Signal(int) # -1 = prev, +1 = next navigate = Signal(int) # -1 = prev, +1 = next
play_next_requested = Signal() # video ended in "Next" mode (wrap-aware)
fullscreen_requested = Signal() fullscreen_requested = Signal()
def __init__(self, parent: QWidget | None = None) -> None: def __init__(self, parent: QWidget | None = None) -> None:
@ -1257,7 +1259,7 @@ class ImagePreview(QWidget):
# Video player (index 1) # Video player (index 1)
self._video_player = VideoPlayer() self._video_player = VideoPlayer()
self._video_player.setFocusPolicy(Qt.FocusPolicy.NoFocus) self._video_player.setFocusPolicy(Qt.FocusPolicy.NoFocus)
self._video_player.play_next.connect(lambda: self.navigate.emit(1)) self._video_player.play_next.connect(self.play_next_requested)
self._stack.addWidget(self._video_player) self._stack.addWidget(self._video_player)
# Info label # Info label