diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 6d440339b..1a6c3ad74 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -845,7 +845,13 @@ msgctxt "#30216"
msgid "Color of the titles marked as \"Remind me\""
msgstr ""
-#. Unused 30217 to 30218
+msgctxt "#30217"
+msgid "Color of the title of the current episode in a season"
+msgstr "
+
+msgctxt "#30218"
+msgid "Show the current episode in the season list"
+msgstr "
msgctxt "#30219"
msgid "Disable notification for synchronization completed"
diff --git a/resources/lib/kodi/infolabels.py b/resources/lib/kodi/infolabels.py
index d207d466c..2d47a31f1 100644
--- a/resources/lib/kodi/infolabels.py
+++ b/resources/lib/kodi/infolabels.py
@@ -69,11 +69,14 @@ def get_info(videoid, item, raw_data, profile_language_code='', delayed_db_op=Fa
def add_info_list_item(list_item: ListItemW, videoid, item, raw_data, is_in_mylist, common_data, art_item=None,
- is_in_remind_me=False):
+ is_in_remind_me=False, is_current_episode=False):
"""Add infolabels and art to a ListItem"""
infos, quality_infos = get_info(videoid, item, raw_data, delayed_db_op=True, common_data=common_data)
list_item.addStreamInfoFromDict(quality_infos)
- if is_in_mylist and common_data.get('mylist_titles_color'):
+ if is_current_episode and common_data.get('current_episode_titles_color'):
+ # Highlight ListItem title when it is the current episode of the season
+ list_item.setLabel(_colorize_text(common_data['current_episode_titles_color'], list_item.getLabel()))
+ elif is_in_mylist and common_data.get('mylist_titles_color'):
# Highlight ListItem title when the videoid is contained in "My list"
list_item.setLabel(_colorize_text(common_data['mylist_titles_color'], list_item.getLabel()))
elif is_in_remind_me:
diff --git a/resources/lib/services/nfsession/directorybuilder/dir_builder.py b/resources/lib/services/nfsession/directorybuilder/dir_builder.py
index 67e9c8165..434c30dfa 100644
--- a/resources/lib/services/nfsession/directorybuilder/dir_builder.py
+++ b/resources/lib/services/nfsession/directorybuilder/dir_builder.py
@@ -66,13 +66,21 @@ def get_profiles(self, request_update, preselect_guid=None, detailed_info=True):
def get_seasons(self, pathitems, tvshowid_dict, perpetual_range_start):
tvshowid = VideoId.from_dict(tvshowid_dict)
season_list = self.req_seasons(tvshowid, perpetual_range_start=perpetual_range_start)
- return build_season_listing(season_list, tvshowid, pathitems)
+ if len(season_list.seasons) > 1 and G.ADDON.getSettingBool('show_current_episode'):
+ current_episode = self.req_current_episode(season_list.current_seasonid)
+ else:
+ current_episode = None
+ return build_season_listing(season_list, tvshowid, current_episode, pathitems)
@measure_exec_time_decorator(is_immediate=True)
def get_episodes(self, pathitems, seasonid_dict, perpetual_range_start):
seasonid = VideoId.from_dict(seasonid_dict)
episodes_list = self.req_episodes(seasonid, perpetual_range_start=perpetual_range_start)
- return build_episode_listing(episodes_list, seasonid, pathitems)
+ if G.ADDON.getSettingInt('current_episode_titles_color') > 0:
+ current_episode = self.req_current_episode(seasonid)
+ else:
+ current_episode = None
+ return build_episode_listing(episodes_list, seasonid, current_episode, pathitems)
@measure_exec_time_decorator(is_immediate=True)
def get_video_list(self, list_id, menu_data, is_dynamic_id):
diff --git a/resources/lib/services/nfsession/directorybuilder/dir_builder_items.py b/resources/lib/services/nfsession/directorybuilder/dir_builder_items.py
index 36ce64324..147d61522 100644
--- a/resources/lib/services/nfsession/directorybuilder/dir_builder_items.py
+++ b/resources/lib/services/nfsession/directorybuilder/dir_builder_items.py
@@ -129,11 +129,32 @@ def _create_profile_item(profile_guid, is_selected, is_autoselect, is_autoselect
@measure_exec_time_decorator(is_immediate=True)
-def build_season_listing(season_list, tvshowid, pathitems=None):
+def build_season_listing(season_list, tvshowid, current_episode=None, pathitems=None):
"""Build a season listing"""
common_data = get_common_data()
directory_items = [_create_season_item(tvshowid, seasonid_value, season, season_list, common_data)
for seasonid_value, season in season_list.seasons.items()]
+
+ if current_episode:
+ common_data_episode = get_common_data()
+ common_data_episode['params'] = get_param_watched_status_by_profile()
+ common_data_episode['set_watched_status'] = G.ADDON.getSettingBool('sync_watched_status')
+ common_data_episode['active_profile_guid'] = G.LOCAL_DB.get_active_profile_guid()
+
+ episodeid_value, episode_data = current_episode.episode
+ current_episode_item = _create_episode_item(season_list.current_seasonid, episodeid_value, episode_data, current_episode, common_data_episode)
+ list_item = current_episode_item[1]
+
+ if list_item.getProperty('isPlayable') == 'true':
+ episode_summary = episode_data['summary']['value']
+ label = f"{episode_summary['season']}x{episode_summary['episode']:02d}. {episode_data['title']['value']}"
+ list_item.setLabel(label)
+
+ episodeid = season_list.current_seasonid.derive_episode(episodeid_value)
+ add_info_list_item(list_item, episodeid, episode_data, current_episode.data, False, common_data_episode)
+
+ directory_items.insert(0, current_episode_item)
+
# add_items_previous_next_page use the new value of perpetual_range_selector
add_items_previous_next_page(directory_items, pathitems, season_list.perpetual_range_selector, tvshowid)
G.CACHE_MANAGEMENT.execute_pending_db_ops()
@@ -151,14 +172,20 @@ def _create_season_item(tvshowid, seasonid_value, season, season_list, common_da
@measure_exec_time_decorator(is_immediate=True)
-def build_episode_listing(episodes_list, seasonid, pathitems=None):
+def build_episode_listing(episodes_list, seasonid, current_episode=None, pathitems=None):
"""Build a episodes listing of a season"""
common_data = get_common_data()
common_data['params'] = get_param_watched_status_by_profile()
common_data['set_watched_status'] = G.ADDON.getSettingBool('sync_watched_status')
common_data['active_profile_guid'] = G.LOCAL_DB.get_active_profile_guid()
- directory_items = [_create_episode_item(seasonid, episodeid_value, episode, episodes_list, common_data)
+ if current_episode:
+ common_data['current_episode_titles_color'] = get_color_name(G.ADDON.getSettingInt('current_episode_titles_color'))
+ current_episodeid_value = current_episode.episode[0]
+ else:
+ current_episodeid_value = None
+
+ directory_items = [_create_episode_item(seasonid, episodeid_value, episode, episodes_list, common_data, current_episodeid_value == episodeid_value)
for episodeid_value, episode
in episodes_list.episodes.items()]
# add_items_previous_next_page use the new value of perpetual_range_selector
@@ -168,7 +195,7 @@ def build_episode_listing(episodes_list, seasonid, pathitems=None):
'title': f'{episodes_list.tvshow["title"]["value"]} - {episodes_list.season["summary"]["value"]["name"]}'}
-def _create_episode_item(seasonid, episodeid_value, episode, episodes_list, common_data):
+def _create_episode_item(seasonid, episodeid_value, episode, episodes_list, common_data, is_current_episode=False):
is_playable = episode['availability'].get('value', {}).get('isPlayable', False)
episodeid = seasonid.derive_episode(episodeid_value)
list_item = ListItemW(label=episode['title']['value'])
@@ -176,7 +203,7 @@ def _create_episode_item(seasonid, episodeid_value, episode, episodes_list, comm
'isPlayable': str(is_playable).lower(),
'nf_videoid': episodeid.to_string()
})
- add_info_list_item(list_item, episodeid, episode, episodes_list.data, False, common_data)
+ add_info_list_item(list_item, episodeid, episode, episodes_list.data, False, common_data, None, False, is_current_episode)
set_watched_status(list_item, episode, common_data)
if is_playable:
url = common.build_url(videoid=episodeid, mode=G.MODE_PLAY, params=common_data['params'])
diff --git a/resources/lib/services/nfsession/directorybuilder/dir_path_requests.py b/resources/lib/services/nfsession/directorybuilder/dir_path_requests.py
index 628cb0749..9a7592001 100644
--- a/resources/lib/services/nfsession/directorybuilder/dir_path_requests.py
+++ b/resources/lib/services/nfsession/directorybuilder/dir_path_requests.py
@@ -12,7 +12,7 @@
from resources.lib import common
from resources.lib.utils.data_types import (VideoListSorted, SubgenreList, SeasonList, EpisodeList, LoCo, VideoList,
SearchVideoList, CustomVideoList, LoLoMoCategory, VideoListSupplemental,
- VideosList)
+ VideosList, CurrentEpisode)
from resources.lib.common.exceptions import InvalidVideoListTypeError, InvalidVideoId
from resources.lib.utils.api_paths import (VIDEO_LIST_PARTIAL_PATHS, RANGE_PLACEHOLDER, VIDEO_LIST_BASIC_PARTIAL_PATHS,
SEASONS_PARTIAL_PATHS, EPISODES_PARTIAL_PATHS, ART_PARTIAL_PATHS,
@@ -141,6 +141,24 @@ def req_episodes(self, videoid, perpetual_range_start=None):
path_response = self.nfsession.perpetual_path_request(**call_args)
return EpisodeList(videoid, path_response)
+ def req_current_episode(self, videoid):
+ """Retrieve the current episode of a season"""
+ if videoid.mediatype != common.VideoId.SEASON:
+ raise InvalidVideoId(f'Cannot request episode list for {videoid}')
+ LOG.debug('Requesting current episode for {}', videoid)
+ paths = ([['seasons', videoid.seasonid, 'summary']] +
+ [['seasons', videoid.seasonid, 'componentSummary']] +
+ build_paths(['seasons', videoid.seasonid, 'episodes', 'current'], EPISODES_PARTIAL_PATHS) +
+ build_paths(['videos', videoid.tvshowid], ART_PARTIAL_PATHS + [[['title', 'delivery']]]))
+
+ call_args = {
+ 'paths': paths,
+ 'length_params': ['stdlist_wid', ['seasons', videoid.seasonid, 'episodes']]
+ }
+ path_response = self.nfsession.perpetual_path_request(**call_args)
+
+ return CurrentEpisode(videoid, path_response)
+
@cache_utils.cache_output(cache_utils.CACHE_COMMON, identify_append_from_kwarg_name='perpetual_range_start',
ignore_self_class=True)
def req_video_list(self, list_id, perpetual_range_start=None):
diff --git a/resources/lib/utils/api_paths.py b/resources/lib/utils/api_paths.py
index 762c66261..0b80f50b5 100644
--- a/resources/lib/utils/api_paths.py
+++ b/resources/lib/utils/api_paths.py
@@ -69,7 +69,8 @@
SEASONS_PARTIAL_PATHS = [
['seasonList', RANGE_PLACEHOLDER, 'summary'],
- ['title']
+ ['title'],
+ ["seasonList","current"]
] + ART_PARTIAL_PATHS
EPISODES_PARTIAL_PATHS = [
@@ -174,6 +175,10 @@ def iterate_references(source):
continue
yield (index, path)
+ if 'current' in source:
+ path = reference_path(source['current'])
+ if path is not None:
+ yield ('current', path)
def count_references(source):
counter = 0
diff --git a/resources/lib/utils/data_types.py b/resources/lib/utils/data_types.py
index 914e3be5c..2d9c5410a 100644
--- a/resources/lib/utils/data_types.py
+++ b/resources/lib/utils/data_types.py
@@ -255,6 +255,8 @@ def __init__(self, videoid, path_response):
self.tvshow = self.data['videos'][self.videoid.tvshowid]
self.seasons = OrderedDict(
resolve_refs(self.tvshow['seasonList'], self.data))
+ if 'current' in self.tvshow['seasonList']:
+ self.current_seasonid = videoid.derive_season(self.tvshow['seasonList']['current']['value'][1])
class EpisodeList:
@@ -269,6 +271,13 @@ def __init__(self, videoid, path_response):
self.episodes = OrderedDict(
resolve_refs(self.season['episodes'], self.data))
+class CurrentEpisode:
+ def __init__(self, videoid, path_response):
+ self.data = path_response
+ self.videoid = videoid
+ self.tvshow = self.data['videos'][self.videoid.tvshowid]
+ self.season = self.data['seasons'][self.videoid.seasonid]
+ self.episode = next(resolve_refs(self.season['episodes'], self.data))
class SubgenreList:
"""A list of subgenre."""
diff --git a/resources/settings.xml b/resources/settings.xml
index 3f889c214..4b04cfa67 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -64,6 +64,11 @@
false
+
+ 0
+ true
+
+
0
1
@@ -115,6 +120,23 @@
+
+ 0
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+