use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::path::Path;
use super::super::{App, AppScreen};
use crate::tui::screens::{GameDetailPrevious, GameDetailScreen};
impl App {
pub(in crate::tui::app) async fn handle_library_browse(
&mut self,
key: &KeyEvent,
) -> Result<bool> {
use crate::tui::path_picker::PathPickerEvent;
use crate::tui::screens::library_browse::LibraryViewMode;
if let AppScreen::LibraryBrowse(ref mut lib) = self.screen {
if lib.upload_prompt.is_some() {
if let Some(up) = lib.upload_prompt.as_mut() {
if key.code == KeyCode::Esc {
lib.close_upload_prompt();
return Ok(false);
}
if key.modifiers.contains(KeyModifiers::CONTROL)
&& matches!(key.code, KeyCode::Char('s') | KeyCode::Char('S'))
{
up.scan_after = !up.scan_after;
return Ok(false);
}
match up.picker.handle_key(key) {
PathPickerEvent::Confirmed(path) => {
let scan_after = up.scan_after;
if !Path::new(&path).is_file() {
lib.set_metadata_footer(Some(format!(
"Not a file: {}",
path.display()
)));
return Ok(false);
}
let Some(pid) = lib.selected_platform_id() else {
lib.set_metadata_footer(Some(
"Select a console before uploading.".into(),
));
return Ok(false);
};
lib.close_upload_prompt();
self.spawn_library_upload_worker(pid, path, scan_after);
}
PathPickerEvent::None => {}
}
}
return Ok(false);
}
}
if self.library_upload_inflight {
return Ok(false);
}
let mut pending_rom_load: Option<(
Option<crate::core::cache::RomCacheKey>,
Option<crate::endpoints::roms::GetRoms>,
u64,
&'static str,
)> = None;
let mut cancel_rom_load = false;
let mut prefetch_collections = false;
let lib = match &mut self.screen {
AppScreen::LibraryBrowse(l) => l,
_ => return Ok(false),
};
if key.modifiers.contains(KeyModifiers::CONTROL) {
match key.code {
KeyCode::Left => {
lib.adjust_left_panel_percent(-5);
self.config.tui_layout.library_left_panel_percent = lib.left_panel_percent;
self.persist_tui_layout();
return Ok(false);
}
KeyCode::Right => {
lib.adjust_left_panel_percent(5);
self.config.tui_layout.library_left_panel_percent = lib.left_panel_percent;
self.persist_tui_layout();
return Ok(false);
}
_ => {}
}
}
match key.code {
KeyCode::Up | KeyCode::Char('k') => {
if lib.view_mode == LibraryViewMode::List {
lib.list_previous();
if lib.list_len() > 0 {
lib.clear_roms();
let key = lib.cache_key();
let expected = lib.expected_rom_count();
if expected > 0 {
let req = Self::selected_rom_request_for_library(lib);
lib.set_rom_loading(true);
pending_rom_load = Some((key, req, expected, "list_move_up"));
} else {
lib.set_rom_loading(false);
cancel_rom_load = true;
}
if lib.subsection
== crate::tui::screens::library_browse::LibrarySubsection::ByCollection
{
tracing::debug!("collections-selection move=up expected={expected}");
prefetch_collections = true;
}
}
} else {
lib.rom_previous();
}
}
KeyCode::Down | KeyCode::Char('j') => {
if lib.view_mode == LibraryViewMode::List {
lib.list_next();
if lib.list_len() > 0 {
lib.clear_roms();
let key = lib.cache_key();
let expected = lib.expected_rom_count();
if expected > 0 {
let req = Self::selected_rom_request_for_library(lib);
lib.set_rom_loading(true);
pending_rom_load = Some((key, req, expected, "list_move_down"));
} else {
lib.set_rom_loading(false);
cancel_rom_load = true;
}
if lib.subsection
== crate::tui::screens::library_browse::LibrarySubsection::ByCollection
{
tracing::debug!("collections-selection move=down expected={expected}");
prefetch_collections = true;
}
}
} else {
lib.rom_next();
}
}
KeyCode::Left | KeyCode::Char('h') if lib.view_mode == LibraryViewMode::Roms => {
lib.back_to_list();
}
KeyCode::Right | KeyCode::Char('l') => lib.switch_view(),
KeyCode::Tab => lib.switch_view(),
KeyCode::Enter => {
if lib.view_mode == LibraryViewMode::List {
lib.switch_view();
} else if let Some((primary, others)) = lib.get_selected_group() {
let placeholder = self.transient_screen_placeholder();
let lib_screen = std::mem::replace(&mut self.screen, placeholder);
if let AppScreen::LibraryBrowse(l) = lib_screen {
self.screen = AppScreen::GameDetail(Box::new(GameDetailScreen::new(
primary,
others,
GameDetailPrevious::Library(l),
self.downloads.shared(),
self.config.tui_layout.game_detail_cover_panel_width,
)));
self.maybe_start_game_detail_cover_load();
self.refresh_current_game_saves();
}
}
}
KeyCode::Char('t') => {
lib.switch_subsection();
if lib.view_mode == LibraryViewMode::List && lib.list_len() > 0 {
let key = lib.cache_key();
let expected = lib.expected_rom_count();
if expected > 0 {
let req = Self::selected_rom_request_for_library(lib);
lib.set_rom_loading(true);
pending_rom_load = Some((key, req, expected, "switch_subsection"));
} else {
lib.set_rom_loading(false);
cancel_rom_load = true;
}
}
if lib.subsection
== crate::tui::screens::library_browse::LibrarySubsection::ByCollection
{
tracing::debug!("collections-subsection entered");
prefetch_collections = true;
}
}
KeyCode::Esc => {
if lib.view_mode == LibraryViewMode::Roms {
lib.back_to_list();
} else {
return Ok(true);
}
}
KeyCode::Char('q') => return Ok(true),
_ => {}
}
if cancel_rom_load {
self.cancel_primary_rom_load();
} else if let Some((key, req, expected, context)) = pending_rom_load {
self.queue_primary_rom_load(key, req, expected, context);
}
if prefetch_collections {
self.queue_collection_prefetches_from_screen(1, "library_selection");
}
Ok(false)
}
}