fix: default enqueue to Ctrl+Return only

This commit is contained in:
2026-10-22 16:37:43 +02:00
parent 585907f876
commit acdd6dc3e9
7 changed files with 15 additions and 19 deletions
+4 -4
View File
@@ -57,7 +57,7 @@ terebi --new-instance --url 'https://www.youtube.com/watch?v=VIDEO_ID' \
--progress-file '/private/session/progress.jsonl'
```
Plain Enter opens one independent player instance without replacing existing playback. Cmd/Ctrl+Enter appends to a running player's queue instead. Tubular creates a private reporting session per video and consumes Terebi's progress records independently of the launcher. `--player` overrides the Terebi CLI executable; it is not a generic mpv/IINA adapter. Tubular reports launcher failures, while later streaming/playback errors appear in Terebi. Quitting Tubular leaves launched players running.
Plain Enter opens one independent player instance without replacing existing playback. Ctrl+Enter appends to a running player's queue instead. Tubular creates a private reporting session per video and consumes Terebi's progress records independently of the launcher. `--player` overrides the Terebi CLI executable; it is not a generic mpv/IINA adapter. Tubular reports launcher failures, while later streaming/playback errors appear in Terebi. Quitting Tubular leaves launched players running.
### Multiple video selection
@@ -71,7 +71,7 @@ Checks belong to each cached view/screen and follow stable video identities thro
Two or more checked videos launch `terebi --new-instance --queue-file '/private/session/queue.json'`. The private version-1 manifest contains ordered canonical episode/video page URLs and one independent `progress_file` per item. Terebi reuses its queue navigation and resolves each item when selected, not in advance; no expiring playback sources are stored. Each item's watching/watched state and resume identity remain independent, including after Tubular restarts. Single-video launches retain the command above. See the [queue contract](docs/terebi-url-playback-handoff.md#ordered-stream-queue-handoff).
**Cmd+Return or Ctrl+Return** (`video.enqueue`) sends the same checked rows, or the hovered row when none are checked, to a running Terebi queue without replacing its current playback. Both bindings are available on every platform; the terminal must transmit the modified Return, or you can rebind the action. Enqueue always uses `terebi --enqueue --queue-file '/private/session/queue.json'`, even for one video, preserving independent per-item progress. If Terebi is not running, it starts with that queue. Plain Return still opens a new instance. These shortcuts do nothing on Miruro catalog titles or saved shows and do not submit text inputs.
**Ctrl+Return** (`video.enqueue`) sends the same checked rows, or the hovered row when none are checked, to a running Terebi queue without replacing its current playback. The terminal must transmit the modified Return, or you can rebind the action. Enqueue always uses `terebi --enqueue --queue-file '/private/session/queue.json'`, even for one video, preserving independent per-item progress. If Terebi is not running, it starts with that queue. Plain Return still opens a new instance. These shortcuts do nothing on Miruro catalog titles or saved shows and do not submit text inputs.
### Miruro browser
@@ -86,7 +86,7 @@ Catalog autocomplete returns at most eight anime titles, without pagination. Tit
| `j` / `k`, ↓ / ↑; `g` / `G`, Home / End | Select a title or episode |
| Space / Esc | Check/uncheck the hovered episode / discard episode checks |
| Enter | Open a series, or play checked episodes in displayed order (hovered episode when none are checked) |
| Cmd+Return / Ctrl+Return | Append checked episodes, or the hovered episode, to a running Terebi queue (`video.enqueue`) |
| Ctrl+Return | Append checked episodes, or the hovered episode, to a running Terebi queue (`video.enqueue`) |
| `y` | Copy the hovered episode's page URL (also in previews and offline collections; `video.copy_url`) |
| `-` / `+` | Back / forward through cached screens, preserving query and selection |
| `w` / `v` | Save the selected episode to watch later / saved episodes |
@@ -123,7 +123,7 @@ These are the default bindings. Overrides in `[keys]` replace an action's bindin
| `j` / `k`, ↓ / ↑ | Select the next / previous video |
| Space / Esc | Check/uncheck the hovered video / discard checks |
| Enter | Play checked videos in displayed order, or the hovered video when none are checked |
| Cmd+Return / Ctrl+Return | Append checked videos, or the hovered video, to a running Terebi queue (`video.enqueue`) |
| Ctrl+Return | Append checked videos, or the hovered video, to a running Terebi queue (`video.enqueue`) |
| `p` | Reopen the provider chooser |
| `o` | Open the selected YouTube video in the default browser (also works in previews; configurable as `video.open`) |
| `y` | Copy the hovered video's page URL (also in previews and offline collections; `video.copy_url`) |
+1 -1
View File
@@ -119,7 +119,7 @@ Each selected entry reports only to its own registered destination. Switching dr
terebi --enqueue --queue-file '/private/session/queue.json'
```
`video.enqueue` defaults to both Super/Cmd+Return and Ctrl+Return. It shares plain Enter's checked-display-order selection and hovered-row fallback in video/episode lists, previews and offline collections. Miruro catalog/show rows and text inputs do not enqueue. Plain Enter remains a new-instance launch.
`video.enqueue` defaults to Ctrl+Return. It shares plain Enter's checked-display-order selection and hovered-row fallback in video/episode lists, previews and offline collections. Miruro catalog/show rows and text inputs do not enqueue. Plain Enter remains a new-instance launch.
The CLI delivers a manifest reference through an explicit-app native URL-open event, so later submissions reach an already running player rather than relying on startup arguments. The receiver appends in supplied order without restarting current playback, changing paused/playing intent, cancelling current resolution or resolving appended items early. An empty or newly launched player starts the first queued item. OS-level delivery to a running packaged app still needs user confirmation; headless receiver checks are not LaunchServices proof.
+1 -1
View File
@@ -120,7 +120,7 @@ actions! {
ViewTabPrevious, "view.tab.previous", "Select the previous view tab", VIEW, ["shift+tab"];
ViewRefresh, "view.refresh", "Refresh the current view and configuration", VIEW, ["r"];
VideoPlay, "video.play", "Play checked videos in displayed order, or the selected video", VIEW, ["enter"];
VideoEnqueue, "video.enqueue", "Append checked videos in displayed order, or the selected video, to Terebi's queue", VIEW, ["super+enter", "ctrl+enter"];
VideoEnqueue, "video.enqueue", "Append checked videos in displayed order, or the selected video, to Terebi's queue", VIEW, ["ctrl+enter"];
VideoOpen, "video.open", "Open the selected YouTube video in the default browser", VIEW, ["o"];
VideoCopyUrl, "video.copy_url", "Copy the selected video's URL to the terminal clipboard", VIEW, ["y"];
VideoNext, "video.select.next", "Select the next video", VIEW, ["j", "down", "ctrl+j"];
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -5
View File
@@ -239,11 +239,7 @@ fn playback_checks_render_independently_and_live_hints_use_configured_keys() {
#[test]
fn playback_checks_survive_spawn_failure_clear_after_spawn_and_fall_back_to_hover() {
for modifiers in [
KeyModifiers::NONE,
KeyModifiers::SUPER,
KeyModifiers::CONTROL,
] {
for modifiers in [KeyModifiers::NONE, KeyModifiers::CONTROL] {
let mut app = app(&["tubular"]);
app.views[0].videos = youtube::search_results(
r#"{"entries":[{"id":"jNQXAC9IVRw","title":"First"},{"id":"rQ_J9WH6CGk","title":"Second"}]}"#,
+5 -1
View File
@@ -66,7 +66,7 @@ fn enqueue_is_configurable_and_only_active_in_video_views() {
let overrides = configured("[keys.video]\nenqueue = 'f22'\n").unwrap();
for &context in ALL {
let expected = VIEW.contains(&context).then_some(Action::VideoEnqueue);
for modifiers in [KeyModifiers::SUPER, KeyModifiers::CONTROL] {
for modifiers in [KeyModifiers::CONTROL] {
assert_eq!(
press(&defaults, context, KeyCode::Enter, modifiers),
expected
@@ -76,6 +76,10 @@ fn enqueue_is_configurable_and_only_active_in_video_views() {
Some(Action::VideoEnqueue),
);
}
assert_eq!(
press(&defaults, context, KeyCode::Enter, KeyModifiers::SUPER),
None
);
assert_eq!(
press(&overrides, context, KeyCode::F(22), KeyModifiers::NONE),
expected,
+1 -5
View File
@@ -736,11 +736,7 @@ fn collection_checks_prune_hidden_and_removed_episodes_without_resurrection() {
#[cfg(unix)]
#[test]
fn episode_launch_retains_checks_on_failure_and_clears_only_after_spawn() {
for modifiers in [
KeyModifiers::NONE,
KeyModifiers::SUPER,
KeyModifiers::CONTROL,
] {
for modifiers in [KeyModifiers::NONE, KeyModifiers::CONTROL] {
let directory = Directory::new();
let mut browser = directory.browser(Some("anime"));
catalog_results(&mut browser);