feat: edit watching and watched status
This commit is contained in:
+101
-1
@@ -27,7 +27,7 @@ use crate::{
|
||||
keys::{Action, Context},
|
||||
miruro_browser::{self, Episode, Media, Request, Response, Worker},
|
||||
ui,
|
||||
video_state::{CollectionKind, State},
|
||||
video_state::{CollectionKind, State, WatchStatus},
|
||||
youtube::{PlayerLaunch, Video},
|
||||
};
|
||||
|
||||
@@ -615,6 +615,23 @@ impl Browser {
|
||||
Err(error) => self.fail(error),
|
||||
}
|
||||
}
|
||||
fn set_watch_status(&mut self, status: WatchStatus) {
|
||||
let Some(video) = self.screen().selected_video() else {
|
||||
return;
|
||||
};
|
||||
let result = self.state.set_watch_status(&video, status);
|
||||
self.rebuild_collections();
|
||||
match result {
|
||||
Ok(()) => {
|
||||
self.status = match status {
|
||||
WatchStatus::Watching => "Marked episode as watching.",
|
||||
WatchStatus::Watched => "Marked episode as watched.",
|
||||
}
|
||||
.into();
|
||||
}
|
||||
Err(error) => self.fail(error),
|
||||
}
|
||||
}
|
||||
fn remove(&mut self, bulk: bool) {
|
||||
let Content::Collection { kind, videos, .. } = &self.screen().content else {
|
||||
return;
|
||||
@@ -811,6 +828,8 @@ impl Browser {
|
||||
Some(Action::WatchingBrowse) => self.collection(CollectionKind::Watching),
|
||||
Some(Action::WatchLaterSave) => self.save(CollectionKind::WatchLater),
|
||||
Some(Action::SavedVideoSave) => self.save(CollectionKind::Saved),
|
||||
Some(Action::WatchStatusWatching) => self.set_watch_status(WatchStatus::Watching),
|
||||
Some(Action::WatchStatusWatched) => self.set_watch_status(WatchStatus::Watched),
|
||||
Some(Action::CollectionRemoveSelected) => self.remove(false),
|
||||
Some(Action::CollectionRemoveBulk) => self.remove(true),
|
||||
Some(Action::WatchLaterFilter) => {
|
||||
@@ -875,6 +894,8 @@ impl Browser {
|
||||
bindings.extend([
|
||||
(Action::WatchLaterSave, "Save episode to watch later"),
|
||||
(Action::SavedVideoSave, "Save episode"),
|
||||
(Action::WatchStatusWatching, "Mark episode as watching"),
|
||||
(Action::WatchStatusWatched, "Mark episode as watched"),
|
||||
]);
|
||||
}
|
||||
if let Content::Collection { kind, .. } = self.screen().content {
|
||||
@@ -934,6 +955,8 @@ impl Browser {
|
||||
&[
|
||||
(Action::InfoHide, "close"),
|
||||
(Action::Help, "help"),
|
||||
(Action::WatchStatusWatching, "mark watching"),
|
||||
(Action::WatchStatusWatched, "mark watched"),
|
||||
(Action::DescriptionNext, "down"),
|
||||
(Action::DescriptionPrevious, "up"),
|
||||
(Action::DescriptionPageNext, "page down"),
|
||||
@@ -946,6 +969,8 @@ impl Browser {
|
||||
(Action::Help, "help"),
|
||||
(Action::VideoPlay, "play"),
|
||||
(Action::InfoOverview, "info"),
|
||||
(Action::WatchStatusWatching, "mark watching"),
|
||||
(Action::WatchStatusWatched, "mark watched"),
|
||||
(Action::CollectionRemoveSelected, "remove"),
|
||||
(Action::CollectionRemoveBulk, "remove all"),
|
||||
(Action::WatchLaterFilter, "filter"),
|
||||
@@ -968,6 +993,8 @@ impl Browser {
|
||||
},
|
||||
),
|
||||
(Action::InfoOverview, "info"),
|
||||
(Action::WatchStatusWatching, "mark watching"),
|
||||
(Action::WatchStatusWatched, "mark watched"),
|
||||
(Action::ViewPrevious, "back"),
|
||||
(Action::WatchLaterBrowse, "later"),
|
||||
(Action::SavedVideoBrowse, "saved"),
|
||||
@@ -1636,6 +1663,79 @@ mod tests {
|
||||
assert!(sources(&directory).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn manual_watch_status_refreshes_filters_and_preserves_other_providers() {
|
||||
let directory = Directory::new();
|
||||
let mut browser = directory.browser(Some("anime"));
|
||||
catalog_results(&mut browser);
|
||||
browser.key(KeyEvent::new(KeyCode::Char('m'), KeyModifiers::NONE));
|
||||
assert!(browser.state.videos(CollectionKind::Watching).is_empty());
|
||||
assert!(!browser.bindings().iter().any(|(action, _)| {
|
||||
matches!(
|
||||
action,
|
||||
Action::WatchStatusWatching | Action::WatchStatusWatched
|
||||
)
|
||||
}));
|
||||
enter_series(&mut browser);
|
||||
let episode = browser.screen().selected_video().unwrap();
|
||||
let mut youtube = episode.clone();
|
||||
youtube.id = "jNQXAC9IVRw".into();
|
||||
youtube.channel_id = Some("UC4QobU6STFB0P71PMvOGN5A".into());
|
||||
youtube.uploader_id = Some("@jawed".into());
|
||||
browser
|
||||
.state
|
||||
.save(CollectionKind::Watching, &youtube)
|
||||
.unwrap();
|
||||
browser.save(CollectionKind::WatchLater);
|
||||
browser.description_focus = true;
|
||||
browser.key(KeyEvent::new(KeyCode::Char('m'), KeyModifiers::NONE));
|
||||
assert!(
|
||||
browser
|
||||
.state
|
||||
.contains(CollectionKind::Watching, &episode.id)
|
||||
);
|
||||
assert!(!browser.state.is_watched(&episode.id));
|
||||
browser.description_focus = false;
|
||||
browser.collection(CollectionKind::Watching);
|
||||
browser.open();
|
||||
assert!(browser.pending.is_some());
|
||||
browser.key(KeyEvent::new(KeyCode::Char('M'), KeyModifiers::NONE));
|
||||
assert!(browser.state.is_watched(&episode.id));
|
||||
assert_eq!(browser.screen().len(), 0);
|
||||
assert!(browser.pending.is_none());
|
||||
browser.collection(CollectionKind::WatchLater);
|
||||
browser.key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::NONE));
|
||||
assert_eq!(browser.screen().len(), 0);
|
||||
browser.key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::NONE));
|
||||
assert_eq!(browser.screen().len(), 1);
|
||||
browser.key(KeyEvent::new(KeyCode::Char('m'), KeyModifiers::NONE));
|
||||
assert_eq!(browser.screen().len(), 0);
|
||||
assert!(!browser.state.is_watched(&episode.id));
|
||||
assert!(
|
||||
browser
|
||||
.state
|
||||
.contains(CollectionKind::Watching, &episode.id)
|
||||
);
|
||||
assert!(
|
||||
browser
|
||||
.state
|
||||
.contains(CollectionKind::Watching, &youtube.id)
|
||||
);
|
||||
assert!(!browser.state.is_watched(&youtube.id));
|
||||
let state = State::open(&browser.config_path).unwrap();
|
||||
assert!(state.contains(CollectionKind::Watching, &episode.id));
|
||||
assert!(state.contains(CollectionKind::WatchLater, &episode.id));
|
||||
let overrides: toml_edit::DocumentMut =
|
||||
"[keys.video.status]\nwatched = 'alt+m'\n".parse().unwrap();
|
||||
browser.config.keys = crate::keys::Bindings::from_toml(overrides.get("keys")).unwrap();
|
||||
browser.collection(CollectionKind::Watching);
|
||||
browser.key(KeyEvent::new(KeyCode::Char('M'), KeyModifiers::NONE));
|
||||
assert!(!browser.state.is_watched(&episode.id));
|
||||
browser.key(KeyEvent::new(KeyCode::Char('m'), KeyModifiers::ALT));
|
||||
assert!(browser.state.is_watched(&episode.id));
|
||||
assert!(state.contains(CollectionKind::Watching, &youtube.id));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offline_collections_and_filtered_bulk_removal_never_touch_youtube() {
|
||||
let directory = Directory::new();
|
||||
|
||||
Reference in New Issue
Block a user