feat: add saved-video collections and category views
This commit is contained in:
+63
-2
@@ -109,6 +109,9 @@ actions! {
|
||||
WatchLaterBrowse, "view.watch_later.browse", "Browse this category's watch later, or the combined collection elsewhere", &[Context::Normal], ["W"];
|
||||
WatchLaterFilter, "view.watch_later.filter", "Cycle watch-later filter: all, unwatched, watched", &[Context::Normal], ["f"];
|
||||
WatchLaterRemove, "view.watch_later.remove", "Confirm removal of the current filtered watch-later subset", &[Context::Normal], ["D"];
|
||||
SavedVideoSave, "video.saved.save", "Save the selected video (also in previews)", VIEW, ["v"];
|
||||
SavedVideoBrowse, "view.saved.browse", "Browse this category's saved videos, or the combined collection elsewhere", &[Context::Normal], ["V"];
|
||||
SavedVideoRemove, "video.saved.remove", "Remove the selected saved video (also in previews)", VIEW, ["x"];
|
||||
SelectorNext, "selector.select.next", "Select the next category or channel", &[Context::SelectorNormal], ["j", "down"];
|
||||
SelectorPrevious, "selector.select.previous", "Select the previous category or channel", &[Context::SelectorNormal], ["k", "up"];
|
||||
SelectorInputNext, "selector.input.next", "Select the next match while editing the filter", &[Context::SelectorInput], ["down", "ctrl+j"];
|
||||
@@ -477,6 +480,23 @@ impl Bindings {
|
||||
),
|
||||
],
|
||||
),
|
||||
(
|
||||
"SAVED VIDEOS",
|
||||
&[
|
||||
(
|
||||
&[SavedVideoSave],
|
||||
"Save the selected video (also in previews)",
|
||||
),
|
||||
(
|
||||
&[SavedVideoBrowse],
|
||||
"Browse category saved videos; combined elsewhere",
|
||||
),
|
||||
(
|
||||
&[SavedVideoRemove],
|
||||
"Remove the selected video (also in previews)",
|
||||
),
|
||||
],
|
||||
),
|
||||
(
|
||||
"FULL DESCRIPTION",
|
||||
&[
|
||||
@@ -926,8 +946,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn aliases_replace_defaults_and_can_disable_actions() {
|
||||
let bindings = configured("[keys.view]\nrefresh = ['x', 'CTRL+y']\n[keys.app]\nquit = []\n[keys.input]\nsubmit = 'RETURN'\ncancel = 'EsC'\n").unwrap();
|
||||
let quoted = configured("[keys]\n'view.refresh' = ['x', 'CTRL+y']\n'app.quit' = []\n'input.submit' = 'RETURN'\n'input.cancel' = 'EsC'\n").unwrap();
|
||||
let bindings = configured("[keys.video.saved]\nremove = []\n[keys.view]\nrefresh = ['x', 'CTRL+y']\n[keys.app]\nquit = []\n[keys.input]\nsubmit = 'RETURN'\ncancel = 'EsC'\n").unwrap();
|
||||
let quoted = configured("[keys]\n'video.saved.remove' = []\n'view.refresh' = ['x', 'CTRL+y']\n'app.quit' = []\n'input.submit' = 'RETURN'\n'input.cancel' = 'EsC'\n").unwrap();
|
||||
assert_eq!(quoted, bindings);
|
||||
assert_eq!(
|
||||
press(
|
||||
@@ -1047,6 +1067,47 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn saved_video_overrides_disable_and_respect_contexts() {
|
||||
let defaults = Bindings::default();
|
||||
for context in ALL {
|
||||
for (key, action, enabled) in [
|
||||
('v', Action::SavedVideoSave, VIEW.contains(context)),
|
||||
('V', Action::SavedVideoBrowse, *context == Context::Normal),
|
||||
('x', Action::SavedVideoRemove, VIEW.contains(context)),
|
||||
] {
|
||||
assert_eq!(
|
||||
press(&defaults, *context, KeyCode::Char(key), KeyModifiers::NONE),
|
||||
enabled.then_some(action),
|
||||
);
|
||||
}
|
||||
}
|
||||
let bindings = configured(
|
||||
"[keys.video.saved]\nsave = 'alt+v'\nremove = []\n[keys.view.saved]\nbrowse = 'shift+x'\n",
|
||||
)
|
||||
.unwrap();
|
||||
for context in ALL {
|
||||
assert_eq!(
|
||||
press(&bindings, *context, KeyCode::Char('v'), KeyModifiers::ALT),
|
||||
VIEW.contains(context).then_some(Action::SavedVideoSave),
|
||||
);
|
||||
assert_eq!(
|
||||
press(&bindings, *context, KeyCode::Char('x'), KeyModifiers::SHIFT),
|
||||
(*context == Context::Normal).then_some(Action::SavedVideoBrowse),
|
||||
);
|
||||
for key in ['v', 'V', 'x'] {
|
||||
assert_eq!(
|
||||
press(&bindings, *context, KeyCode::Char(key), KeyModifiers::NONE),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
let collision = configured("[keys]\nview.saved.browse = 'v'")
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
assert!(collision.contains("view.saved.browse") && collision.contains("video.saved.save"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_entries_and_collisions_have_actionable_errors() {
|
||||
for (source, path) in [
|
||||
|
||||
Reference in New Issue
Block a user