From: Christian Heller Date: Fri, 6 Dec 2024 15:54:53 +0000 (+0100) Subject: Have basic player control as part of every page's head rather than only as playlist... X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%22https:/validator.w3.org/day?a=commitdiff_plain;h=50a56e0b37614ed92cb32f1002808fa447b2cb32;p=ytplom Have basic player control as part of every page's head rather than only as playlist page element. --- diff --git a/src/templates/_macros.tmpl b/src/templates/_macros.tmpl index 8b851f5..8c407c1 100644 --- a/src/templates/_macros.tmpl +++ b/src/templates/_macros.tmpl @@ -1,14 +1,21 @@ {% macro _link_if(cond, target, display_name = false ) %}{% if cond %}{% endif %}{% if display_name %}{{display_name}}{% else %}{{target}}{% endif %}{% if cond %}{% endif %}{% endmacro %} -{% macro nav_head(page_names, selected="") %} -

+{% macro nav_head(page_names, redir_target, player_state, selected="") %} +

+ {{ _link_if("playlist" != selected, page_names.playlist) }} · {{ _link_if("files" != selected, page_names.files) }} · {{ _link_if("yt_queries" != selected, page_names.yt_queries, "queries") }} -

+| + + + + +{% if player_state.running %}{% if player_state.paused %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %}: {{player_state.title}} +

{% endmacro %} @@ -17,6 +24,9 @@
+{% if playlist_view %} + +{% endif %} {% if not playlist_view %} diff --git a/src/templates/file_data.tmpl b/src/templates/file_data.tmpl index 8df4bf0..305d3e9 100644 --- a/src/templates/file_data.tmpl +++ b/src/templates/file_data.tmpl @@ -9,6 +9,6 @@ td.tag_checkboxes { width: 1em; } {% block body %} -{{ macros.nav_head(page_names) }} +{{ macros.nav_head(page_names, redir_target, player_state) }} {{ macros.file_data_form(file, unused_tags, page_names, redir_target, flag_names) }} {% endblock %} diff --git a/src/templates/files.tmpl b/src/templates/files.tmpl index 16ea4e2..2e5909c 100644 --- a/src/templates/files.tmpl +++ b/src/templates/files.tmpl @@ -2,7 +2,7 @@ {% block body %} -{{ macros.nav_head(page_names, "files") }} +{{ macros.nav_head(page_names, redir_target, player_state, "files") }} filter filename: filter tags: diff --git a/src/templates/playlist.tmpl b/src/templates/playlist.tmpl index 63671f7..6207c33 100644 --- a/src/templates/playlist.tmpl +++ b/src/templates/playlist.tmpl @@ -29,27 +29,16 @@ window.onload = keep_updated; {% block css %} -#status { font-weight: bold; } td.screen_half { width: 50%; } -tr.screen_half_titles>th { text-align: center; } +th.screen_half_titles { text-align: center; } td.entry_buttons { width: 5em; } td.tag_checkboxes { width: 1em; } {% endblock %} {% block body %} -{{ macros.nav_head(page_names, "playlist") }} +{{ macros.nav_head(page_names, redir_target, player_state, "playlist") }}
current selection
path:{% if playlist_view %}{% endif %}{{file.rel_path}}{% if playlist_view %}{% endif %}
present:{% if file.present %}yes{% else %}no{% endif %}
- -
- - - - - - -{% if running %}{% if pause %}PAUSED{% else %}PLAYING{% endif %}{% else %}STOPPED{% endif %} - -
filter filename: @@ -57,7 +46,6 @@ filter tags:
current selectionplaylist
{% if current_file %} @@ -67,6 +55,7 @@ filter tags:
+ {% for idx, file in files_w_idx %}
playlist
diff --git a/src/templates/yt_queries.tmpl b/src/templates/yt_queries.tmpl index 9ef271d..477b7b2 100644 --- a/src/templates/yt_queries.tmpl +++ b/src/templates/yt_queries.tmpl @@ -2,7 +2,7 @@ {% block body %} -{{ macros.nav_head(page_names, "yt_queries") }} +{{ macros.nav_head(page_names, redir_target, player_state, "yt_queries") }}

quota: {{quota_count}}/100000

diff --git a/src/templates/yt_result.tmpl b/src/templates/yt_result.tmpl index 73ffbab..6537246 100644 --- a/src/templates/yt_result.tmpl +++ b/src/templates/yt_result.tmpl @@ -2,7 +2,7 @@ {% block body %} -{{ macros.nav_head(page_names) }} +{{ macros.nav_head(page_names, redir_target, player_state) }} diff --git a/src/templates/yt_results.tmpl b/src/templates/yt_results.tmpl index 872d461..c3fa034 100644 --- a/src/templates/yt_results.tmpl +++ b/src/templates/yt_results.tmpl @@ -2,7 +2,7 @@ {% block body %} -{{ macros.nav_head(page_names) }} +{{ macros.nav_head(page_names, redir_target, player_state) }}

query: {{query}}

title:{{video_data.title}}
thumbnail:
{% for video in videos %} diff --git a/src/ytplom/http.py b/src/ytplom/http.py index 2b85490..1ea2bc2 100644 --- a/src/ytplom/http.py +++ b/src/ytplom/http.py @@ -25,11 +25,12 @@ from ytplom.primitives import NotFoundException, PATH_APP_DATA _ColorStr = NewType('_ColorStr', str) _PageNames: TypeAlias = dict[str, Path] _ReqDict: TypeAlias = dict[str, list[str]] +_PlayerState: TypeAlias = dict[str, bool | Path | str] _TemplateContext: TypeAlias = dict[ str, None | bool - | _ColorStr | FilesWithIndex | _PageNames | FilterStr | Path - | PlayerUpdateId | QueryText | QuotaCost | UrlStr | 'VideoFile' + | _ColorStr | FilesWithIndex | _PlayerState | _PageNames | FilterStr + | Path | PlayerUpdateId | QueryText | QuotaCost | UrlStr | 'VideoFile' | YoutubeId | 'YoutubeVideo' | list[FlagName] | set['Tag'] | list['VideoFile'] | list['YoutubeVideo'] | list['YoutubeQuery'] ] @@ -54,6 +55,7 @@ PAGE_NAMES: _PageNames = { 'files': Path('files'), 'last_update': Path('last_playlist_update.json'), 'missing': Path('missing.json'), + 'player': Path('player'), 'playlist': Path('playlist'), 'thumbnails': Path('thumbnails'), 'yt_result': Path('yt_result'), @@ -130,10 +132,11 @@ class _TaskHandler(BaseHTTPRequestHandler): page_name = Path(toks_url[1] if len(toks_url) > 1 else '') body_length = int(self.headers['content-length']) postvars = _ReqMap(self.rfile.read(body_length).decode()) - # postvars = parse_qs(self.rfile.read(body_length).decode()) - if PAGE_NAMES['playlist'] == page_name: - self._receive_player_command(postvars.single_key, url.query) - if PAGE_NAMES['files'] == page_name: + if PAGE_NAMES['player'] == page_name: + self._receive_player_command(postvars.as_dict) + elif PAGE_NAMES['playlist'] == page_name: + self._receive_playlist_command(postvars.single_key, url.query) + elif PAGE_NAMES['files'] == page_name: self._receive_files_command(postvars) elif PAGE_NAMES['file'] == page_name: self._receive_file_data(Hash.from_b64(toks_url[2]), @@ -141,16 +144,19 @@ class _TaskHandler(BaseHTTPRequestHandler): elif PAGE_NAMES['yt_queries'] == page_name: self._receive_yt_query(QueryText(postvars.single_value('query'))) - def _receive_player_command(self, command: str, params_str: str) -> None: - if 'pause' == command: + def _receive_player_command(self, postvars: _ReqDict) -> None: + if 'pause' in postvars.keys(): self.server.player.toggle_pause() - elif 'prev' == command: + elif 'prev' in postvars.keys(): self.server.player.prev() - elif 'next' == command: + elif 'next' in postvars.keys(): self.server.player.next() - elif 'stop' == command: + elif 'stop' in postvars.keys(): self.server.player.toggle_run() - elif 'reload' == command: + self._redirect(Path(postvars['redir_target'][0])) + + def _receive_playlist_command(self, command: str, params_str: str) -> None: + if 'reload' == command: self.server.player.clear() elif command.startswith('jump_'): self.server.player.jump_to(int(command.split('_')[1])) @@ -224,9 +230,16 @@ class _TaskHandler(BaseHTTPRequestHandler): tmpl_ctx: _TemplateContext ) -> None: tmpl = self.server.jinja.get_template(str(tmpl_name)) + tmpl_ctx['redir_target'] = Path(self.path) tmpl_ctx['background_color'] = _ColorStr( self.server.config.background_color) tmpl_ctx['page_names'] = PAGE_NAMES + tmpl_ctx['player_state'] = { + 'running': self.server.player.is_running, + 'paused': self.server.player.is_paused, + 'title': (self.server.player.current_file_cached.rel_path + if self.server.player.current_file_cached + else 'none')} html = tmpl.render(**tmpl_ctx) self._send_http(bytes(html, 'utf8')) @@ -302,13 +315,11 @@ class _TaskHandler(BaseHTTPRequestHandler): with DbConn() as conn: file = VideoFile.get_one(conn, digest) unused_tags = file.unused_tags(conn) - redir_target = Path('/').joinpath(PAGE_NAMES['file']).joinpath( - file.digest.b64) - self._send_rendered_template(_NAME_TEMPLATE_FILE_DATA, - {'file': file, - 'flag_names': list(FILE_FLAGS), - 'unused_tags': unused_tags, - 'redir_target': redir_target}) + self._send_rendered_template( + _NAME_TEMPLATE_FILE_DATA, + {'file': file, + 'flag_names': list(FILE_FLAGS), + 'unused_tags': unused_tags}) def _send_files_index(self, params: _ReqMap) -> None: filter_path = FilterStr(params.single_value('filter_path')) @@ -323,9 +334,7 @@ class _TaskHandler(BaseHTTPRequestHandler): {'files': files, 'filter_path': filter_path, 'filter_tags': filter_tags, - 'show_absent': show_absent, - 'redir_target': Path( - f'/{PAGE_NAMES["files"]}?{params.as_str}')}) + 'show_absent': show_absent}) def _send_missing_json(self) -> None: with DbConn() as conn: @@ -347,9 +356,9 @@ class _TaskHandler(BaseHTTPRequestHandler): self.server.player.load_files_and_start(filter_path, filter_tags) current_file, unused_tags = None, set() with DbConn() as conn: - if self.server.player.current_file_digest: + if self.server.player.current_file_cached: current_file = VideoFile.get_one( - conn, self.server.player.current_file_digest) + conn, self.server.player.current_file_cached.digest) unused_tags = current_file.unused_tags(conn) self._send_rendered_template( _NAME_TEMPLATE_PLAYLIST, @@ -359,8 +368,6 @@ class _TaskHandler(BaseHTTPRequestHandler): 'current_file': current_file, 'filter_path': filter_path, 'filter_tags': filter_tags, - 'redir_target': Path( - f'/{PAGE_NAMES["playlist"]}?{params.as_str}'), 'unused_tags': unused_tags, 'files_w_idx': list(enumerate(self.server.player.files)) }) diff --git a/src/ytplom/misc.py b/src/ytplom/misc.py index 45299bf..4bd492d 100644 --- a/src/ytplom/misc.py +++ b/src/ytplom/misc.py @@ -495,15 +495,11 @@ class Player: return 0 == len(self.files) @property - def current_file_digest(self) -> Optional[Hash]: - """Return .digest of what we assume is the currently playing file. - - We don't return the actual file object because we cannot guarantee its - data's up-to-date-ness, it being cached from the last .load_files call. - """ + def current_file_cached(self) -> Optional[VideoFile]: + """Return cached version of the currently playing file.""" if not self.files: return None - return self.files[self._idx].digest + return self.files[self._idx] @property def is_running(self) -> bool: