jellyfin-kodi/jellyfin_kodi/dialogs/skip.py
2026-02-11 00:26:24 +01:00

125 lines
3.7 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function, unicode_literals
import xbmcgui
from ..helper import LazyLogger
LOG = LazyLogger(__name__)
# Action IDs
ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92
ACTION_NAV_BACK = 92
# Control IDs
SKIP_BUTTON = 3012
CLOSE_BUTTON = 3013
# String IDs for segment types - using shorter labels
SEGMENT_LABELS = {
"Introduction": "Intro",
"Credits": "Outro",
"Recap": "Recap",
"Preview": "Preview",
"Commercial": "Ad",
}
class SkipDialog(xbmcgui.WindowXMLDialog):
"""
OSD overlay dialog for skipping intro/outro segments.
Based on service.upnext popup pattern for reliable non-modal display.
"""
def __init__(self, *args, **kwargs):
self._segment_type = kwargs.pop("segment_type", None)
self._duration = kwargs.pop("duration", 0)
# State flags
self.skip_requested = False
self.cancel_requested = False
# Set properties before super().__init__ to avoid flicker
# (like service.upnext does in set_info)
xbmcgui.WindowXMLDialog.__init__(self, *args)
def set_skip_info(self, segment_type, duration):
"""Set the skip segment information."""
self._segment_type = segment_type
self._duration = duration
# Format duration text
minutes = int(duration // 60)
seconds = int(duration % 60)
if minutes > 0:
duration_text = "{0}m {1}s".format(minutes, seconds)
else:
duration_text = "{0}s".format(seconds)
# Get short segment type label
segment_label = SEGMENT_LABELS.get(segment_type, segment_type or "Segment")
# Set button label: "Skip Intro (1m 40s)"
button_label = "Skip {0} ({1})".format(segment_label, duration_text)
# Use setProperty so it's available to the skin
self.setProperty("skip_label", button_label)
self.setProperty("segment_type", segment_type or "")
self.setProperty("duration", duration_text)
LOG.debug(
"SkipDialog: set_skip_info segment=%s, label=%s", segment_type, button_label
)
def onInit(self):
"""Initialize the dialog controls."""
LOG.debug("SkipDialog.onInit called")
# Try to set button label directly as well
try:
button = self.getControl(SKIP_BUTTON)
label = self.getProperty("skip_label")
if label:
button.setLabel(label)
LOG.debug("SkipDialog.onInit: set button label to '%s'", label)
except Exception as e:
LOG.debug("Could not set skip button label: %s", e)
def onAction(self, action):
"""Handle user actions."""
action_id = action.getId()
LOG.debug("SkipDialog.onAction: action_id=%s", action_id)
if action_id in (
ACTION_BACK,
ACTION_PARENT_DIR,
ACTION_PREVIOUS_MENU,
ACTION_NAV_BACK,
):
self.cancel_requested = True
self.close()
def onClick(self, control_id):
"""Handle control clicks."""
LOG.debug("SkipDialog.onClick: control_id=%s", control_id)
if control_id == SKIP_BUTTON:
LOG.debug("Skip button clicked for %s", self._segment_type)
self.skip_requested = True
self.close()
elif control_id == CLOSE_BUTTON:
LOG.debug("Close button clicked")
self.cancel_requested = True
self.close()
def is_skip(self):
"""Return whether the user requested to skip."""
return self.skip_requested
def is_cancel(self):
"""Return whether the user cancelled."""
return self.cancel_requested