mirror of
https://github.com/Benexl/FastAnime.git
synced 2026-02-04 11:07:48 -08:00
feat: PoC icat for viewing manga
This commit is contained in:
@@ -66,7 +66,9 @@ def search(config: "Config", anime_titles: str, episode_range: str):
|
||||
from yt_dlp.utils import sanitize_filename
|
||||
|
||||
from ...MangaProvider import MangaProvider
|
||||
from ..utils.feh import feh_manga_viewer
|
||||
|
||||
# from ..utils.feh import feh_manga_viewer
|
||||
from ..utils.icat import icat_manga_viewer
|
||||
|
||||
manga_title = anime_titles[0]
|
||||
|
||||
@@ -136,7 +138,7 @@ def search(config: "Config", anime_titles: str, episode_range: str):
|
||||
print(
|
||||
f"[purple bold]Now Reading: [/] {search_result_manga_title} [cyan bold]Chapter:[/] {chapter_info['title']}"
|
||||
)
|
||||
feh_manga_viewer(chapter_info["thumbnails"], str(chapter_info["title"]))
|
||||
icat_manga_viewer(chapter_info["thumbnails"], str(chapter_info["title"]))
|
||||
if anilist_helper:
|
||||
anilist_helper.update_anime_list(
|
||||
{"mediaId": anilist_id, "progress": chapter_number}
|
||||
|
||||
101
fastanime/cli/utils/icat.py
Normal file
101
fastanime/cli/utils/icat.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import termios
|
||||
import tty
|
||||
from sys import exit
|
||||
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.align import Align
|
||||
from rich.text import Text
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def get_key():
|
||||
"""Read a single keypress (including arrows)."""
|
||||
fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fd)
|
||||
try:
|
||||
tty.setraw(fd)
|
||||
ch1 = sys.stdin.read(1)
|
||||
if ch1 == "\x1b":
|
||||
ch2 = sys.stdin.read(2)
|
||||
return ch1 + ch2
|
||||
return ch1
|
||||
finally:
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||
|
||||
|
||||
def draw_banner_at(msg: str, row: int):
|
||||
"""Move cursor to `row`, then render a centered, cyan-bordered panel."""
|
||||
sys.stdout.write(f"\x1b[{row};1H")
|
||||
text = Text(msg, justify="center")
|
||||
panel = Panel(Align(text, align="center"), border_style="cyan", padding=(1, 2))
|
||||
console.print(panel)
|
||||
|
||||
|
||||
def icat_manga_viewer(image_links: list[str], window_title: str):
|
||||
ICAT = shutil.which("kitty")
|
||||
if not ICAT:
|
||||
console.print("[bold red]kitty (for icat) not found[/]")
|
||||
exit(1)
|
||||
|
||||
idx, total = 0, len(image_links)
|
||||
title = f"{window_title} ({total} images)"
|
||||
show_banner = True
|
||||
|
||||
try:
|
||||
while True:
|
||||
console.clear()
|
||||
term_width, term_height = shutil.get_terminal_size((80, 24))
|
||||
|
||||
# Calculate space for image based on banner visibility
|
||||
if show_banner:
|
||||
msg_lines = 3 # Title + blank + controls
|
||||
panel_height = msg_lines + 4 # Padding and borders
|
||||
image_height = term_height - panel_height - 1
|
||||
else:
|
||||
image_height = term_height
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
ICAT,
|
||||
"+kitten",
|
||||
"icat",
|
||||
"--clear",
|
||||
"--scale-up",
|
||||
"--place",
|
||||
f"{term_width}x{image_height}@0x0",
|
||||
"--z-index",
|
||||
"-1",
|
||||
image_links[idx],
|
||||
]
|
||||
)
|
||||
|
||||
if show_banner:
|
||||
controls = (
|
||||
f"[{idx + 1}/{total}] Prev: [h/←] Next: [l/→] "
|
||||
f"Toggle Banner: [b] Quit: [q/Ctrl-C]"
|
||||
)
|
||||
msg = f"{title}\n\n{controls}"
|
||||
start_row = term_height - panel_height
|
||||
draw_banner_at(msg, start_row)
|
||||
|
||||
# key handling
|
||||
key = get_key()
|
||||
if key in ("l", "\x1b[C"):
|
||||
idx = (idx + 1) % total
|
||||
elif key in ("h", "\x1b[D"):
|
||||
idx = (idx - 1) % total
|
||||
elif key == "b":
|
||||
show_banner = not show_banner
|
||||
elif key in ("q", "\x03"):
|
||||
break
|
||||
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
console.clear()
|
||||
console.print("Exited viewer.", style="bold")
|
||||
Reference in New Issue
Block a user