<tr>
<th>present:</th>
-<td>{% if file.present %}<a href="/{{page_names.download}}/{{file.yt_id}}">yes</a> <input type="submit" name="play" value="play" />{% else %}no{% endif %}</td>
+<td>
+{% if file.present %}
+<a href="/{{page_names.download}}/{{file.yt_id}}">yes</a>
+<input type="button" onclick="player_command('inject_{{file.digest.b64}}');" value="inject" />
+{% else %}
+no
+{% endif %}
+</td>
</tr>
<tr>
const tr = new_child_to('tr', table);
tr.classList.add("file_row");
new_child_to('td', tr, file.size);
- const td_play = new_child_to('td', tr);
- const btn_play = new_child_to('input', td_play);
- btn_play.type = 'submit';
- btn_play.name = `play_${file.digest}`;
- btn_play.value = 'play';
- btn_play.disabled = !file.present;
+ const td_inject = new_child_to('td', tr);
+ const btn_inject = new_child_to('button', td_inject);
+ btn_inject.onclick = function() { player_command(`inject_${file.digest}`) };
+ btn_inject.disabled = !file.present;
+ btn_inject.textContent = 'inject';
new_child_to('td', tr, file.tags_showable.join(", "));
const td_link = new_child_to('td', tr);
const a = new_child_to('a', td_link, file.rel_path);
<span id="tags"></span><br />
<hr />
<p>known files (shown: <span id="files_count">?</span>):</p>
-<form action="/{{page_names.files}}" method="POST">
-<input type="hidden" name="redir_target" value="{{redir_target}}" />
<table id="files_table">
<tr><th>size</th><th>actions</th><th>tags</th><th>path</th></tr>
</table>
-</form>
{% endblock %}
{% extends '_base.tmpl' %}
+{% block css %}
+td.entry_control { width: 6em; }
+{% endblock %}
+
+
{% block script %}
{{ macros.js_new_child_to() }}
else {
for (const [symbol, prefix] of [['>', 'jump'],
['^', 'up'],
- ['v', 'down']]) {
+ ['v', 'down'],
+ ['x', 'rm']]) {
const btn = new_child_to('button', td_entry_control, symbol);
btn.onclick = function() { player_command(`${prefix}_${i}`) }; }}
const td_link = new_child_to('td', tr);
const a_file = new_child_to('a', td_link, file.rel_path);
a_file.href = `${PATH_PREFIX_FILE}${file.digest}`; }})
-function redo_playlist() {
- post_to({filter_path: [document.getElementsByName('filter_path')[0].value],
- needed_tags: [document.getElementsByName('needed_tags')[0].value]},
- PATH_PLAYER);
- player_command('reload');
-}
-
-{% endblock %}
-
-
-{% block css %}
-td.screen_half { width: 50%; }
-th.screen_half_titles { text-align: center; }
-td.entry_control { width: 5em; }
{% endblock %}
{% block body %}
-<table>
-<td class="screen_half">
-
-<table>
-<tr><th colspan=2 class="screen_half_titles">playlist config</th></tr>
-<tr><th>filter filename</th><td><input name="filter_path" value="{{filter_path}}" /></td></tr>
-<tr><th>needed tags</th><td><input name="needed_tags" value="{{needed_tags}}" /></td></tr>
-<tr><td colspan=2><button onclick="redo_playlist()">reload</button></td></tr>
-</table>
-
-</td>
-<td class="screen_half">
-
+<a href="#playing">#playing</a>
+<button onclick="player_command('rebuild')">rebuild</button>
+<hr />
<table id="playlist_rows">
-<tr><th colspan=3 class="screen_half_titles">playlist (<a href="#playing">#playing</a>)</th></tr>
-</table>
-
-</td>
-</tr>
</table>
{% endblock %}
-
"""Map POST requests to handlers for various paths."""
if self.pagename == PAGE_NAMES['file']:
self._receive_file_data()
- elif self.pagename == PAGE_NAMES['files']:
- self._receive_files_command()
elif self.pagename == PAGE_NAMES['player']:
self._receive_player_command()
elif self.pagename == PAGE_NAMES['purge']:
self._receive_yt_query()
def _receive_file_data(self) -> None:
- digest = Hash.from_b64(self.path_toks[2])
- if self.postvars.has_key('play'):
- with DbConn() as conn:
- file = VideoFile.get_one(conn, digest)
- self.server.player.inject_and_play(file)
- self._redirect(Path(self.postvars.first_for('redir_target')))
- return
if not (self.server.config.allow_file_edit # also if whitelist, …
and self.server.config.tags_display_whitelist.empty):
self.send_http(b'no way', code=403) # … cuz input form under …
return # … this display filter might have suppressed set tags
with DbConn() as conn:
- file = VideoFile.get_one(conn, digest)
+ file = VideoFile.get_one(conn, Hash.from_b64(self.path_toks[2]))
if self.postvars.has_key('unlink'):
file.unlink_locally()
file.set_flags({FILE_FLAGS[FlagName(name)]
file.ensure_absence_if_deleted()
self._redirect(Path(self.postvars.first_for('redir_target')))
- def _receive_files_command(self) -> None:
- for k in self.postvars.keys_starting_with('play_'):
- with DbConn() as conn:
- file = VideoFile.get_one(
- conn, Hash.from_b64(k.split('_', 1)[1]))
- self.server.player.inject_and_play(file)
- self._redirect(Path(self.postvars.first_for('redir_target')))
-
def _receive_player_command(self) -> None:
command = self.postvars.first_for('command')
if 'play' == command:
self.server.player.prev()
elif 'next' == command:
self.server.player.next()
- elif 'reload' == command:
+ elif 'rebuild' == command:
self.server.player.load_files_and_mpv()
elif command.startswith('jump_'):
self.server.player.jump_to(int(command.split('_')[1]))
self.server.player.move_entry(int(command.split('_')[1]))
elif command.startswith('down_'):
self.server.player.move_entry(int(command.split('_')[1]), False)
- if self.postvars.has_key('filter_path'):
- self.server.player.filter_path = FilterStr(
- self.postvars.first_for('filter_path'))
- if self.postvars.has_key('needed_tags'):
- self.server.player.needed_tags = TagSet.from_joined(
- self.postvars.first_for('needed_tags'))
+ elif command.startswith('rm_'):
+ self.server.player.remove(int(command.split('_')[1]))
+ elif command.startswith('inject_'):
+ with DbConn() as conn:
+ file = VideoFile.get_one(
+ conn, Hash.from_b64(command.split('_', 1)[1]))
+ self.server.player.inject(file)
self.send_http(b'OK')
def _purge_deleted_files(self) -> None:
tmpl_ctx: dict[str, Any]
) -> None:
tmpl_ctx['selected'] = tmpl_ctx.get('selected', '')
- tmpl_ctx['redir_target'] = self.path
tmpl_ctx['background_color'] = self.server.config.background_color
tmpl_ctx['page_names'] = PAGE_NAMES
self.send_rendered(tmpl_name, tmpl_ctx)
unused_tags = file.unused_tags(conn)
self._send_rendered_template(
_NAME_TEMPLATE_FILE_DATA,
- {'file': file,
- 'allow_edit': self.server.config.allow_file_edit,
+ {'allow_edit': self.server.config.allow_file_edit,
+ 'file': file,
'flag_names': list(FILE_FLAGS),
+ 'redir_target': self.path,
'unused_tags': unused_tags})
def _send_files_index(self) -> None:
self.playlist[i0])
self._signal_update()
- def inject_and_play(self, file: VideoFile) -> None:
- """Inject file after current title, then jump to it."""
- if self.playlist:
- self._idx += 1
- self.playlist.insert(self._idx, file)
+ def remove(self, idx: int) -> None:
+ """Remove from playlist title at idx."""
+ if self._mpv:
+ self._mpv.command('playlist-remove', idx)
+ self.playlist[idx:idx + 1] = []
+ self._signal_update()
+
+ def inject(self, file: VideoFile) -> None:
+ """Inject file after current title."""
+ self.playlist.insert(self._idx + 1, file)
if self._mpv:
self._mpv.command('loadfile', file.full_path,
- 'insert-at', self._idx)
- self._play_at_index()
+ 'insert-at', self._idx + 1)
+ self._signal_update()
class DownloadsManager: