mirror of
https://github.com/Benexl/FastAnime.git
synced 2026-01-05 17:27:27 -08:00
feat: implement restore mode for dynamic search with last query and cached results
This commit is contained in:
@@ -13,11 +13,38 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
SEARCH_CACHE_DIR = APP_CACHE_DIR / "previews" / "dynamic-search"
|
||||
SEARCH_RESULTS_FILE = SEARCH_CACHE_DIR / "current_search_results.json"
|
||||
LAST_QUERY_FILE = SEARCH_CACHE_DIR / "last_query.txt"
|
||||
RESTORE_MODE_FILE = SEARCH_CACHE_DIR / ".restore_mode"
|
||||
FZF_SCRIPTS_DIR = SCRIPTS_DIR / "fzf"
|
||||
SEARCH_TEMPLATE_SCRIPT = (FZF_SCRIPTS_DIR / "search.py").read_text(encoding="utf-8")
|
||||
FILTER_PARSER_SCRIPT = FZF_SCRIPTS_DIR / "_filter_parser.py"
|
||||
|
||||
|
||||
def _load_cached_titles() -> list[str]:
|
||||
"""Load titles from cached search results for display in fzf."""
|
||||
if not SEARCH_RESULTS_FILE.exists():
|
||||
return []
|
||||
|
||||
try:
|
||||
with open(SEARCH_RESULTS_FILE, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
media_list = data.get("data", {}).get("Page", {}).get("media", [])
|
||||
titles = []
|
||||
for media in media_list:
|
||||
title_obj = media.get("title", {})
|
||||
title = (
|
||||
title_obj.get("english")
|
||||
or title_obj.get("romaji")
|
||||
or title_obj.get("native")
|
||||
or "Unknown"
|
||||
)
|
||||
titles.append(title)
|
||||
return titles
|
||||
except (IOError, json.JSONDecodeError):
|
||||
return []
|
||||
|
||||
|
||||
@session.menu
|
||||
def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
"""Dynamic search menu that provides real-time search results."""
|
||||
@@ -27,6 +54,12 @@ def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
# Ensure cache directory exists
|
||||
SEARCH_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Check if we're in restore mode (coming back from media_actions)
|
||||
restore_mode = RESTORE_MODE_FILE.exists()
|
||||
if restore_mode:
|
||||
# Clear the restore flag
|
||||
RESTORE_MODE_FILE.unlink(missing_ok=True)
|
||||
|
||||
# Read the GraphQL search query
|
||||
from .....libs.media_api.anilist import gql
|
||||
|
||||
@@ -46,6 +79,7 @@ def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
"GRAPHQL_ENDPOINT": "https://graphql.anilist.co",
|
||||
"GRAPHQL_QUERY": search_query_json,
|
||||
"SEARCH_RESULTS_FILE": SEARCH_RESULTS_FILE.as_posix(),
|
||||
"LAST_QUERY_FILE": LAST_QUERY_FILE.as_posix(),
|
||||
"AUTH_HEADER": auth_header,
|
||||
}
|
||||
|
||||
@@ -71,6 +105,19 @@ def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
# Header hint for filter syntax
|
||||
filter_hint = "💡 Filters: @genre:action @status:airing @year:2024 @sort:score (type @help for more)"
|
||||
|
||||
# Only load previous query if we're in restore mode (coming back from media_actions)
|
||||
initial_query = None
|
||||
cached_results = None
|
||||
if restore_mode:
|
||||
# Load previous query
|
||||
if LAST_QUERY_FILE.exists():
|
||||
try:
|
||||
initial_query = LAST_QUERY_FILE.read_text(encoding="utf-8").strip()
|
||||
except IOError:
|
||||
pass
|
||||
# Load cached results to display immediately without network request
|
||||
cached_results = _load_cached_titles()
|
||||
|
||||
try:
|
||||
# Prepare preview functionality
|
||||
preview_command = None
|
||||
@@ -85,12 +132,16 @@ def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
search_command=search_command_final,
|
||||
preview=preview_command,
|
||||
header=filter_hint,
|
||||
initial_query=initial_query,
|
||||
initial_results=cached_results,
|
||||
)
|
||||
else:
|
||||
choice = ctx.selector.search(
|
||||
prompt="Search Anime",
|
||||
search_command=search_command_final,
|
||||
header=filter_hint,
|
||||
initial_query=initial_query,
|
||||
initial_results=cached_results,
|
||||
)
|
||||
except NotImplementedError:
|
||||
feedback.error("Dynamic search is not supported by your current selector")
|
||||
@@ -129,6 +180,9 @@ def dynamic_search(ctx: Context, state: State) -> State | InternalDirective:
|
||||
logger.error(f"Could not find selected media for choice: {choice}")
|
||||
return InternalDirective.MAIN
|
||||
|
||||
# Set restore mode flag so we can restore state when user goes back
|
||||
RESTORE_MODE_FILE.touch()
|
||||
|
||||
# Navigate to media actions with the selected item
|
||||
return State(
|
||||
menu_name=MenuName.MEDIA_ACTIONS,
|
||||
|
||||
Reference in New Issue
Block a user