{% endblock %}
diff --git a/src/ytplom/http.py b/src/ytplom/http.py
index d61b75c..b0aea64 100644
--- a/src/ytplom/http.py
+++ b/src/ytplom/http.py
@@ -28,7 +28,7 @@ _TemplateContext: TypeAlias = dict[
None | bool
| FilesWithIndex | _PageNames | _FilterStr | Path | PlayerUpdateId
| QueryText | QuotaCost | UrlStr | 'VideoFile' | YoutubeId
- | 'YoutubeVideo' | list[FlagName] | list['Tag'] | list['VideoFile']
+ | 'YoutubeVideo' | list[FlagName] | set['Tag'] | list['VideoFile']
| list['YoutubeVideo'] | list['YoutubeQuery']
]
@@ -151,9 +151,7 @@ class _TaskHandler(BaseHTTPRequestHandler):
file.save(conn)
conn.commit()
file.ensure_absence_if_deleted()
- self._redirect(Path('/')
- .joinpath(PAGE_NAMES['file'])
- .joinpath(digest.b64))
+ self._redirect(Path(postvars['redir'][0]))
def _receive_yt_query(self, query_txt: QueryText) -> None:
with DbConn() as conn:
@@ -273,11 +271,11 @@ class _TaskHandler(BaseHTTPRequestHandler):
def _send_file_data(self, digest: Hash) -> None:
with DbConn() as conn:
file = VideoFile.get_one(conn, digest)
- all_tags = VideoFile.get_all_tags(conn)
- self._send_rendered_template(
- _NAME_TEMPLATE_FILE_DATA,
- {'file': file, 'flag_names': list(FILE_FLAGS),
- 'unused_tags': [t for t in all_tags if t not in file.tags]})
+ unused_tags = file.unused_tags(conn)
+ 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: dict[str, list[str]]) -> None:
filter_path = _FilterStr(params.get('filter_path', [''])[0])
@@ -312,11 +310,18 @@ class _TaskHandler(BaseHTTPRequestHandler):
def _send_playlist(self) -> None:
if self.server.player.empty:
self.server.player.load_files()
+ current_file, unused_tags = None, set()
+ if self.server.player.current_file_digest:
+ with DbConn() as conn:
+ current_file = VideoFile.get_one(
+ conn, self.server.player.current_file_digest)
+ unused_tags = current_file.unused_tags(conn)
self._send_rendered_template(
_NAME_TEMPLATE_PLAYLIST,
{'last_update': self.server.player.last_update,
'running': self.server.player.is_running,
'paused': self.server.player.is_paused,
- 'current_video': self.server.player.current_file,
- 'prev_files_w_idx': self.server.player.prev_files_w_idx,
- 'next_files_w_idx': self.server.player.next_files_w_idx})
+ 'current_file': current_file,
+ '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 d0b55e8..438a8cd 100644
--- a/src/ytplom/misc.py
+++ b/src/ytplom/misc.py
@@ -278,7 +278,6 @@ class VideoFile(DbData):
f'{self.yt_id}|{self.last_update}|{self.tags_str}')
def _renew_last_update(self):
- print("DEBUG calling_renew_last_update", self.rel_path)
self.last_update = DatetimeStr(datetime.now().strftime(TIMESTAMP_FMT))
self._hash_on_last_update = hash(self)
@@ -297,12 +296,11 @@ class VideoFile(DbData):
raise NotFoundException(f'no entry for file to Youtube ID {yt_id}')
return cls._from_table_row(row)
- @classmethod
- def get_all_tags(cls, conn: BaseDbConn) -> set[Tag]:
- """Return all tags used among VideoFiles."""
+ def unused_tags(self, conn: BaseDbConn) -> set[Tag]:
+ """Return tags used among other VideoFiles, not in self."""
tags = set()
- for file in cls.get_all(conn):
- for tag in file.tags:
+ for file in self.get_all(conn):
+ for tag in [t for t in file.tags if t not in self.tags]:
tags.add(tag)
return tags
@@ -423,11 +421,11 @@ class Player:
"""Collect files in PATH_DOWNLOADS DB-known and of legal extension."""
with DbConn() as conn:
known_files = {f.full_path: f for f in VideoFile.get_all(conn)}
- self._files = [known_files[p] for p in PATH_DOWNLOADS.iterdir()
- if p in known_files
- and p.is_file()
- and p.suffix[1:] in LEGAL_EXTENSIONS]
- shuffle(self._files)
+ self.files = [known_files[p] for p in PATH_DOWNLOADS.iterdir()
+ if p in known_files
+ and p.is_file()
+ and p.suffix[1:] in LEGAL_EXTENSIONS]
+ shuffle(self.files)
self._idx = 0
def _signal_update(self) -> None:
@@ -439,7 +437,7 @@ class Player:
config=True)
self._monitor_kill()
self._mpv.observe_property('pause', lambda a, b: self._signal_update())
- for path in [f.full_path for f in self._files]:
+ for path in [f.full_path for f in self.files]:
self._mpv.command('loadfile', path, 'append')
@self._mpv.event_callback('start-file')
@@ -471,28 +469,18 @@ class Player:
@property
def empty(self) -> bool:
"""Return if playlist empty."""
- return 0 == len(self._files)
+ return 0 == len(self.files)
@property
- def current_file(self) -> Optional[VideoFile]:
- """Return what we assume is the currently playing file."""
- if not self._files:
- return None
- return self._files[self._idx]
+ def current_file_digest(self) -> Optional[Hash]:
+ """Return .digest of what we assume is the currently playing file.
- @property
- def _files_w_idx(self) -> FilesWithIndex:
- return list(enumerate(self._files))
-
- @property
- def prev_files_w_idx(self) -> FilesWithIndex:
- """List 'past' files of playlist."""
- return list(reversed(self._files_w_idx[:self._idx]))
-
- @property
- def next_files_w_idx(self) -> FilesWithIndex:
- """List 'coming' files of playlist."""
- return self._files_w_idx[self._idx + 1:]
+ 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.
+ """
+ if not self.files:
+ return None
+ return self.files[self._idx].digest
@property
def is_running(self) -> bool:
@@ -528,7 +516,7 @@ class Player:
def next(self) -> None:
"""Move player to next item in playlist."""
- if self._idx < len(self._files) - 1:
+ if self._idx < len(self.files) - 1:
self._idx += 1
self._play_at_index()
@@ -543,16 +531,16 @@ class Player:
or (upwards and start_idx == self._idx + 1)
or ((not upwards) and start_idx == self._idx - 1)
or (upwards and start_idx < 1)
- or ((not upwards) and start_idx > len(self._files) - 2)):
+ or ((not upwards) and start_idx > len(self.files) - 2)):
return
i0, i1 = start_idx, start_idx + (-1 if upwards else 1)
if self._mpv:
# NB: a functional playlist-move would do this in a single step,
# but for some reason I don't seem to get it to do anything
- path = self._files[i1].full_path
+ path = self.files[i1].full_path
self._mpv.command('playlist-remove', i1)
self._mpv.command('loadfile', path, 'insert-at', i0)
- self._files[i0], self._files[i1] = self._files[i1], self._files[i0]
+ self.files[i0], self.files[i1] = self.files[i1], self.files[i0]
def reload(self) -> None:
"""Close MPV, re-read (and re-shuffle) filenames, then re-start MPV."""
@@ -563,9 +551,9 @@ class Player:
def inject_and_play(self, file: VideoFile) -> None:
"""Inject file after current title, then jump to it."""
- if self._files:
+ if self.files:
self._idx += 1
- self._files.insert(self._idx, file)
+ self.files.insert(self._idx, file)
if self._mpv:
self._mpv.command('loadfile', file.full_path,
'insert-at', self._idx)